はじめに
皆さん、仕事ををやる上でタスク管理ツールを使われると思います。
RedmineとかBacklogとか使ってますか?
そんな感じのものを
下記を使えばノーコードで作れるんじゃないのかなと思って作ってみた次第です。
CRUDのWebApi開発は不要!Json登録でWebApiを作れるシステムを作った話
また不完全ですが、作れました!!
作ったもの
みなさんが凄いもの作ってくれることを期待して、あえて90年代のデザインにしました😁


公開WebApi
これと同じような感じで使えます。
エンジニア・プログラマにしか使えないSNSを作ってみた話
エンドポイント
https://versatileapi.herokuapp.com/api/task_management
ユーザー
登録
POST /user
更新
PUT /user/:user_id
取得
GET /user/:user_id
全件取得
GET /user/all
ODataクエリが使用できます。(全て対応はしていません)
スキーマ
{
"additionalProperties": false,
"type": "object",
"properties": {
"name": {
"description": "名前",
"type": "string",
"minLength": 1,
"maxLength": 50
}
},
"required": [
"name"
]
}
カテゴリ
登録
POST /category
更新
PUT /category/:category_id
取得
GET /category/:category_id
全件取得
GET /category/all
ODataクエリが使用できます。(全て対応はしていません)
スキーマ
{
"additionalProperties":false,
"type": "object",
"properties": {
"category_name": {
"description": "カテゴリ名",
"type": "string",
"minLength": 1,
"maxLength": 50
}
},
"required": [
"category_name"
]
}
タスク
登録
POST /task
更新
PUT /task/:task_id
取得
GET /task/:task_id
全件取得
GET /task/all
ODataクエリが使用できます。(全て対応はしていません)
スキーマ
{
"additionalProperties": false,
"type": "object",
"properties": {
"title": {
"description": "タスク名",
"type": "string",
"minLength": 1,
"maxLength": 140
},
"description": {
"description": "タスクの内容",
"type": "string",
"minLength": 1,
"maxLength": 1000
},
"in_charge_user_id": {
"description": "担当者Id",
"type": "string",
"minLength": 36,
"maxLength": 36
},
"start_datetime": {
"description": "開始日",
"type": "string",
"format":"date"
},
"end_datetime": {
"description": "期限日",
"type": "string",
"format":"date"
},
"scheduled": {
"description": "予定",
"type": "number"
},
"achievements": {
"description": "実績",
"type": "number"
},
"status": {
"description": "状態",
"type": "string",
"enum": [
"waiting",
"working",
"pending",
"completed",
"discontinued"
]
},
"category_id": {
"description": "カテゴリId",
"type": "string",
"minLength": 36,
"maxLength": 36
}
},
"required": [
"title",
"status"
]
}
暫定で作ったフロントエンドのHTML
一応公開しておきます。vue.jsで作りました
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>タスク管理ツール</title>
</head>
<body>
<h2>タスク一覧</h2>
<div id="app">
<ul id="example-1">
<li v-for="item in taskList" :key="taskList.id">
<a :href="'./task-detail.html?taskid='+ item.id"> {{ item.title }}</a>
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
<script>
const api = "https://versatileapi.herokuapp.com/api/task_management/";
const app = new Vue({
el: "#app",
data: {
taskList: []
},
async mounted() {
//可読性は良いけど、待たないほうが早い
let taksInfo = await (await fetch(api + "task/all")).json();
taksInfo.forEach(res => {
this.taskList.push(res);
});
},
methods: {
}
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>タスク管理ツール</title>
</head>
<body>
<div id="app">
<h2>タスク詳細</h2>
<p>タイトル:{{title}}</p>
<p>チケット内容:{{description}}</p>
<p>担当者:{{in_charge_user}}</p>
<div style="display: flex;">
<p>開始日:{{start_datetime}}</p>
<p>期限日:{{end_datetime}}</p>
</div>
<div style="display: flex;">
<p>予定:{{scheduled}}</p>
<p>実績:{{achievements}}</p>
</div>
<p>状態:{{status}}</p>
<p>カテゴリ:{{categoryName}}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
<script>
const api = "https://versatileapi.herokuapp.com/api/task_management/";
const app = new Vue({
el: "#app",
data: {
title: "",
description: "",
in_charge_user: "",
start_datetime: "",
end_datetime: "",
scheduled: "",
achievements: "",
status: "",
categoryName: "",
},
async mounted() {
let taskId = this.getUrlQueries()["taskid"];
//可読性は良いけど、待たないほうが早い
let taksInfo = await (await fetch(api + "task/" + taskId)).json();
let userName = "";
if (taksInfo["in_charge_user_id"] != null)
userName = (await (await fetch(api + "user/" + taksInfo["in_charge_user_id"])).json())["name"];
let categoryName = "";
if (taksInfo["category_id"] != null)
categoryName = (await (await fetch(api + "category/" + taksInfo["category_id"])).json())["category_name"];
this.title = taksInfo["title"];
this.description = taksInfo["description"];
this.in_charge_user = userName;
this.start_datetime = taksInfo["start_datetime"];
this.end_datetime = taksInfo["end_datetime"];
this.scheduled = taksInfo["scheduled"];
this.achievements = taksInfo["achievements"];
this.status = taksInfo["status"];
this.categoryName = categoryName;
},
methods: {
getUrlQueries: function () {
var queryStr = window.location.search.slice(1);
queries = {};
if (!queryStr) {
return queries;
}
queryStr.split("&").forEach(function (queryStr) {
var queryArr = queryStr.split("=");
queries[queryArr[0]] = queryArr[1];
});
return queries;
}
}
});
</script>
</body>
</html>