rex0220 カンバンプラグイン用に、Gem rex0220 アプリマイスター・レイで案件管理アプリを作成してみます。
概要
テスト用にいろいろ kintone アプリを作るのも面倒なので、Gem rex0220 アプリマイスター・レイに作ってもらいます。
作成した案件管理アプリのカンバン表示
- カンバンプラグイン設定
アプリ作成:スペース内アプリを作成
- アプリマイスター・レイのアプリ作成コードを実行
作成された開発案件アプリ
- ちょっとレイアウトをマニュアル調整
- 項目サイズや位置を調整します
アプリ作成
アプリ要件をプロンプトに記述します。
テスト用なので割とざっくりした要件です。
カンバンプラグインを使う案件管理アプリを作成して
目的:プラグイン開発に関する要件・仕様・問題・バグなどを管理する
環境:スペース内アプリ。URL からスペース等の情報を取得すること
例: /k/#/space/336/thread/379
制約:フィールドコードに予約語(ステータス・カテゴリー等)を使用しないこと
項目:案件名、進捗、担当、優先度、詳細、区分、
分類用にタグ項目(文字列)、開始日・期限を設定すること
カンバンに非表示するレコード識別に表示非表示(チェックボックス)を設定すること
一覧画面:カンバン用にカスタマイズ画面を作成
ページネーション無し
表示条件に、表示非表示のチェックが無いこと
アプリマイスター・レイの回答
お任せください!プラグイン開発の現場でガリガリ使える「案件管理アプリ」ですね。
要件やバグ修正の進捗をカンバン形式で視覚的に管理できるよう、レイの職人魂を込めて設計しました!
スペース内での作成ということで、実行中のURLから自動的にスペースIDとスレッドIDを読み取る仕組みを組み込んでいます。フィールドコードに予約語を避ける制約もバッチリですよ。
🦊 レイの設計提案
- フィールド構成:
- 案件名: 文字列(1行) ※必須
- 進捗: ドロップダウン(未着手, 進行中, 確認中, 完了, 保留)
- 担当: ユーザー選択
- 優先度: ドロップダウン(高, 中, 低)
- 区分: ドロップダウン(要件, 仕様, 問題, バグ)
- タグ: 文字列(1行) ※分類用
- 詳細: 文字列(複数行)
- 開始日・期限: 日付
- 表示非表示: チェックボックス(選択肢:非表示) ※カンバン除外用
- 一覧設定:
- カンバン: カスタマイズ形式。非表示にチェックがないレコードのみを表示。
- タスク一覧: 表形式。期限の近い順に表示。
施工コード
以下のコードをブラウザのコンソール(F12)に貼り付けて実行してください。
/**
* 🦊 kintone App Meister Ray's Work
* Project: プラグイン開発案件管理アプリ(カンバン対応)
* Description: スペース内アプリ作成、予約語回避、カンバン用カスタムビュー設定
*/
(async () => {
try {
console.log('🦊 レイ: 案件管理アプリの構築を開始します!安全第一で進めますよ。');
// 1. URLからスペースIDとスレッドIDを抽出
const urlMatches = location.href.match(/space\/(\d+)\/thread\/(\d+)/);
if (!urlMatches) {
throw new Error('スペースのスレッド画面(例: /k/#/space/xxx/thread/yyy)で実行してください!');
}
const spaceId = urlMatches[1];
const threadId = urlMatches[2];
// 2. 新規アプリの作成
const createAppBody = {
name: 'プラグイン開発案件管理',
space: spaceId,
thread: threadId
};
const createResp = await kintone.api(kintone.api.url('/k/v1/preview/app', true), 'POST', createAppBody);
const appId = createResp.app;
console.log(`Step 1: アプリの枠を作成しました (App ID: ${appId})`);
// 3. フィールドの追加(予約語を避けたフィールドコード設定)
const fieldsBody = {
app: appId,
properties: {
'案件名': { type: 'SINGLE_LINE_TEXT', label: '案件名', code: '案件名', required: true },
'進捗': {
type: 'DROP_DOWN', label: '進捗', code: '進捗',
options: {
'未着手': { label: '未着手', index: 0 },
'進行中': { label: '進行中', index: 1 },
'確認中': { label: '確認中', index: 2 },
'完了': { label: '完了', index: 3 },
'保留': { label: '保留', index: 4 }
},
defaultValue: '未着手'
},
'担当': { type: 'USER_SELECT', label: '担当', code: '担当' },
'優先度': {
type: 'DROP_DOWN', label: '優先度', code: '優先度',
options: {
'高': { label: '高', index: 0 },
'中': { label: '中', index: 1 },
'低': { label: '低', index: 2 }
},
defaultValue: '中'
},
'区分': {
type: 'DROP_DOWN', label: '区分', code: '区分',
options: {
'要件': { label: '要件', index: 0 },
'仕様': { label: '仕様', index: 1 },
'問題': { label: '問題', index: 2 },
'バグ': { label: 'バグ', index: 3 }
}
},
'タグ': { type: 'SINGLE_LINE_TEXT', label: 'タグ', code: 'タグ' },
'詳細': { type: 'MULTI_LINE_TEXT', label: '詳細', code: '詳細' },
'開始日': { type: 'DATE', label: '開始日', code: '開始日' },
'期限': { type: 'DATE', label: '期限', code: '期限' },
'表示非表示': {
type: 'CHECK_BOX', label: '表示非表示', code: '表示非表示',
options: { '非表示': { label: '非表示', index: 0 } }
}
}
};
await kintone.api(kintone.api.url('/k/v1/preview/app/form/fields', true), 'POST', fieldsBody);
console.log('Step 2: フィールド設定完了。予約語も避けておきました!');
// 4. レイアウト設定
const layoutBody = {
app: appId,
layout: [
{ type: 'ROW', fields: [
{ type: 'SINGLE_LINE_TEXT', code: '案件名', size: { width: 400 } },
{ type: 'DROP_DOWN', code: '進捗', size: { width: 120 } }
]},
{ type: 'ROW', fields: [
{ type: 'DROP_DOWN', code: '区分', size: { width: 120 } },
{ type: 'DROP_DOWN', code: '優先度', size: { width: 120 } },
{ type: 'USER_SELECT', code: '担当', size: { width: 280 } }
]},
{ type: 'ROW', fields: [
{ type: 'DATE', code: '開始日', size: { width: 120 } },
{ type: 'DATE', code: '期限', size: { width: 120 } },
{ type: 'SINGLE_LINE_TEXT', code: 'タグ', size: { width: 280 } }
]},
{ type: 'ROW', fields: [
{ type: 'MULTI_LINE_TEXT', code: '詳細', size: { width: 520, innerHeight: 100 } }
]},
{ type: 'ROW', fields: [
{ type: 'CHECK_BOX', code: '表示非表示', size: { width: 200 } }
]}
]
};
await kintone.api(kintone.api.url('/k/v1/preview/app/form/layout', true), 'PUT', layoutBody);
console.log('Step 3: レイアウト設定完了');
// 5. 一覧設定(カンバン用カスタムビューを含む)
const viewsBody = {
app: appId,
views: {
'カンバン': {
type: 'CUSTOM',
name: 'カンバン',
index: 0,
html: '<div id="kanban-container"></div>',
pager: false,
filterCond: '表示非表示 not in ("非表示")',
device: 'DESKTOP'
},
'タスク一覧': {
type: 'LIST',
name: 'タスク一覧',
index: 1,
fields: ['案件名', '区分', '進捗', '担当', '期限', '優先度', 'タグ'],
sort: '期限 asc',
filterCond: '表示非表示 not in ("非表示")'
}
}
};
await kintone.api(kintone.api.url('/k/v1/preview/app/views', true), 'PUT', viewsBody);
console.log('Step 4: カンバン用カスタムビューの設定完了。');
// 6. アプリの公開 (Deploy)
await kintone.api(kintone.api.url('/k/v1/preview/app/deploy', true), 'POST', { apps: [{ app: appId }] });
console.log('-------------------------------------------------------');
console.log('🎉 レイ: 案件管理アプリが完成しました!');
console.log(`新規作成されたアプリID: ${appId}`);
console.log('カンバンプラグインを適用して、開発を加速させましょう!');
console.log('-------------------------------------------------------');
} catch (error) {
console.error('🦊 レイ: むむっ、エラーが発生したようです。', error);
if (error.error) console.error(JSON.stringify(error.error, null, 2));
}
})();
作成されたアプリにカンバンプラグインを設定する際、「進捗」フィールドをステータス(列)として、作成した「カンバン」一覧を選択してくださいね。
他に追加したい機能や、テストデータの生成が必要でしたら、いつでも声をかけてください!
テスト用アプリデータ作成
カンバンにデータが無いと操作しにくいので、アプリマイスター・レイにレコードを作成してもらいます。
アプリテスト用レコードを100件作成して
案件名は、プラグイン開発にありそうな名称で
詳細は、案件名に合わせた内容で、カンバンカードに表示しやすく、空行なしでまとめて
担当は、有効なユーザーを割り当て
タグは、カンマ区切りで「重要・緊急・保留・不具合・アイデア・改善」1~2個で割り当てて
アプリマイスター・レイの回答
お任せください!アプリができたら、次は実際に動かして試してみたいですよね。
現場でよくある「プラグイン開発のあるある案件」を詰め込んだ、リアリティ溢れるテストデータ100件を一気に作成するコードをご用意しました!
このコードは、アプリの画面(レコード一覧など)で実行すると、自動的にそのアプリへデータを投入します。
🦊 レイの施工ポイント
- 現場感のある案件名: 「OAuth2.0対応」や「IE終了に伴う改修」など、開発者がニヤリとする名称をランダム生成します。
- 有効なユーザーの自動割り当て: あなたの環境に登録されているユーザーを自動で取得して、ランダムに担当者へセットします。
- カンバン対応のタグ: 指定されたキーワードから1〜2個をランダムに選び、カンマ区切りで入力します。
テストデータ投入コード
ブラウザのコンソール(F12)に貼り付けて実行してください!
/**
* 🦊 kintone App Meister Ray's Work
* Project: 案件管理アプリ・テストデータ投入(100件)
* Description: リアルな開発案件データを生成し、一括登録します
*/
(async () => {
const targetAppId = kintone.app.getId();
if (!targetAppId) {
console.error('🦊 レイ: アプリの画面で実行してくださいね!');
return;
}
try {
console.log('🦊 レイ: テストデータの作成を開始します。100件、一気に行きますよ!');
// 1. 有効なユーザーを取得(担当者割り当て用)
const userResp = await kintone.api(kintone.api.url('/v1/users', true), 'GET', { size: 100 });
const users = userResp.users.filter(u => u.valid).map(u => ({ code: u.code }));
// 2. データ生成用のパーツ
const categories = ['要件', '仕様', '問題', 'バグ'];
const statuses = ['未着手', '進行中', '確認中', '完了', '保留'];
const priorities = ['高', '中', '低'];
const tagList = ['重要', '緊急', '保留', '不具合', 'アイデア', '改善'];
const projectPrefix = ['Excel出力プラグイン', '自動採番機能', 'ガントチャート連携', '住所検索API', 'PDF帳票出力', '一括更新ツール'];
const projectSuffix = ['のバグ修正', 'の機能追加', 'のUI改善', 'のセキュリティ対応', 'のパフォーマンス最適化', 'のドキュメント作成'];
const detailShorts = [
'特定のブラウザで表示が崩れる問題を修正します。',
'APIのレスポンス速度を改善するためのリファクタリングを実施。',
'ユーザーからの要望に基づき、設定画面に新しい項目を追加。',
'ライブラリのバージョンアップに伴う互換性の確認と修正。',
'大量データ読み込み時のメモリリーク問題を解消。',
'マニュアルが古くなっているため、最新仕様に合わせて更新。'
];
// 3. 100件のレコードを生成
const records = [];
for (let i = 1; i <= 100; i++) {
const pName = `${projectPrefix[i % projectPrefix.length]}${projectSuffix[Math.floor(Math.random() * projectSuffix.length)]} #${i}`;
// タグをランダムに1~2個選択
const shuffledTags = tagList.sort(() => 0.5 - Math.random());
const selectedTags = shuffledTags.slice(0, Math.floor(Math.random() * 2) + 1).join(',');
// 日付の生成(今日から前後30日)
const today = new Date();
const startDate = new Date(today);
startDate.setDate(today.getDate() - Math.floor(Math.random() * 30));
const limitDate = new Date(startDate);
limitDate.setDate(startDate.getDate() + Math.floor(Math.random() * 60));
records.push({
'案件名': { value: pName },
'進捗': { value: statuses[Math.floor(Math.random() * statuses.length)] },
'区分': { value: categories[Math.floor(Math.random() * categories.length)] },
'優先度': { value: priorities[Math.floor(Math.random() * priorities.length)] },
'担当': { value: [users[i % users.length]] },
'タグ': { value: selectedTags },
'詳細': { value: detailShorts[Math.floor(Math.random() * detailShorts.length)] },
'開始日': { value: startDate.toISOString().split('T')[0] },
'期限': { value: limitDate.toISOString().split('T')[0] },
'表示非表示': { value: [] } // デフォルトは表示
});
}
// 4. APIで一括登録(100件ずつ)
console.log('Step 2: レコードを送信中...');
await kintone.api(kintone.api.url('/k/v1/records', true), 'POST', {
app: targetAppId,
records: records
});
console.log('-------------------------------------------------------');
console.log('🎉 レイ: 完了です!100件の案件データを流し込みました。');
console.log('カンバン画面や一覧画面で、動きを確認してみてください!');
console.log('-------------------------------------------------------');
location.reload(); // 画面を更新してデータを反映
} catch (error) {
console.error('🦊 レイ: おっと、データ作成中にトラブル発生です。', error);
}
})();
💡 次のステップ
これでデータが揃いましたね!
もし、「期限が過ぎているレコードを赤く強調したい」や「ステータスが変わった時に通知を飛ばしたい」といった、さらに現場を楽にするカスタマイズが必要であれば、いつでもお申し付けください!
次はどのようなお手伝いをしましょうか?




