create-mcp-use-app 0.4.8 → 0.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +303 -168
- package/dist/templates/apps-sdk/index.ts +16 -18
- package/dist/templates/apps-sdk/package.json +1 -1
- package/dist/templates/apps-sdk/resources/display-weather.tsx +55 -41
- package/dist/templates/apps-sdk/styles.css +3 -4
- package/dist/templates/apps-sdk/tsconfig.json +0 -1
- package/dist/templates/mcp-ui/index.ts +111 -103
- package/dist/templates/mcp-ui/package.json +1 -1
- package/dist/templates/mcp-ui/resources/kanban-board.tsx +228 -150
- package/dist/templates/mcp-ui/tsconfig.json +0 -1
- package/dist/templates/starter/index.ts +65 -66
- package/dist/templates/starter/package.json +1 -1
- package/dist/templates/starter/resources/display-weather.tsx +56 -42
- package/dist/templates/starter/resources/kanban-board.tsx +228 -150
- package/dist/templates/starter/styles.css +3 -4
- package/dist/templates/starter/tsconfig.json +0 -1
- package/package.json +1 -1
|
@@ -1,47 +1,83 @@
|
|
|
1
|
-
import React, { useEffect, useState } from
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
2
|
|
|
3
3
|
interface Task {
|
|
4
|
-
id: string
|
|
5
|
-
title: string
|
|
6
|
-
description: string
|
|
7
|
-
status:
|
|
8
|
-
priority:
|
|
9
|
-
assignee?: string
|
|
4
|
+
id: string;
|
|
5
|
+
title: string;
|
|
6
|
+
description: string;
|
|
7
|
+
status: "todo" | "in-progress" | "done";
|
|
8
|
+
priority: "low" | "medium" | "high";
|
|
9
|
+
assignee?: string;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
interface KanbanBoardProps {
|
|
13
|
-
initialTasks?: Task[]
|
|
13
|
+
initialTasks?: Task[];
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
const KanbanBoard: React.FC<KanbanBoardProps> = ({ initialTasks = [] }) => {
|
|
17
|
-
const [tasks, setTasks] = useState<Task[]>(initialTasks)
|
|
18
|
-
const [newTask, setNewTask] = useState({
|
|
17
|
+
const [tasks, setTasks] = useState<Task[]>(initialTasks);
|
|
18
|
+
const [newTask, setNewTask] = useState({
|
|
19
|
+
title: "",
|
|
20
|
+
description: "",
|
|
21
|
+
priority: "medium" as Task["priority"],
|
|
22
|
+
});
|
|
19
23
|
|
|
20
24
|
// Load tasks from URL parameters or use defaults
|
|
21
25
|
useEffect(() => {
|
|
22
|
-
const urlParams = new URLSearchParams(window.location.search)
|
|
23
|
-
const tasksParam = urlParams.get(
|
|
26
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
27
|
+
const tasksParam = urlParams.get("tasks");
|
|
24
28
|
|
|
25
29
|
if (tasksParam) {
|
|
26
30
|
try {
|
|
27
|
-
const parsedTasks = JSON.parse(decodeURIComponent(tasksParam))
|
|
28
|
-
setTasks(parsedTasks)
|
|
31
|
+
const parsedTasks = JSON.parse(decodeURIComponent(tasksParam));
|
|
32
|
+
setTasks(parsedTasks);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.error("Error parsing tasks from URL:", error);
|
|
29
35
|
}
|
|
30
|
-
|
|
31
|
-
console.error('Error parsing tasks from URL:', error)
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
36
|
+
} else {
|
|
35
37
|
// Default tasks for demo
|
|
36
38
|
setTasks([
|
|
37
|
-
{
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
{
|
|
40
|
+
id: "1",
|
|
41
|
+
title: "Design UI mockups",
|
|
42
|
+
description: "Create wireframes for the new dashboard",
|
|
43
|
+
status: "todo",
|
|
44
|
+
priority: "high",
|
|
45
|
+
assignee: "Alice",
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: "2",
|
|
49
|
+
title: "Implement authentication",
|
|
50
|
+
description: "Add login and registration functionality",
|
|
51
|
+
status: "in-progress",
|
|
52
|
+
priority: "high",
|
|
53
|
+
assignee: "Bob",
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: "3",
|
|
57
|
+
title: "Write documentation",
|
|
58
|
+
description: "Document the API endpoints",
|
|
59
|
+
status: "done",
|
|
60
|
+
priority: "medium",
|
|
61
|
+
assignee: "Charlie",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: "4",
|
|
65
|
+
title: "Setup CI/CD",
|
|
66
|
+
description: "Configure automated testing and deployment",
|
|
67
|
+
status: "todo",
|
|
68
|
+
priority: "medium",
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
id: "5",
|
|
72
|
+
title: "Code review",
|
|
73
|
+
description: "Review pull requests from the team",
|
|
74
|
+
status: "in-progress",
|
|
75
|
+
priority: "low",
|
|
76
|
+
assignee: "David",
|
|
77
|
+
},
|
|
78
|
+
]);
|
|
43
79
|
}
|
|
44
|
-
}, [])
|
|
80
|
+
}, []);
|
|
45
81
|
|
|
46
82
|
const addTask = () => {
|
|
47
83
|
if (newTask.title.trim()) {
|
|
@@ -49,93 +85,109 @@ const KanbanBoard: React.FC<KanbanBoardProps> = ({ initialTasks = [] }) => {
|
|
|
49
85
|
id: Date.now().toString(),
|
|
50
86
|
title: newTask.title,
|
|
51
87
|
description: newTask.description,
|
|
52
|
-
status:
|
|
88
|
+
status: "todo",
|
|
53
89
|
priority: newTask.priority,
|
|
54
|
-
}
|
|
55
|
-
setTasks([...tasks, task])
|
|
56
|
-
setNewTask({ title:
|
|
90
|
+
};
|
|
91
|
+
setTasks([...tasks, task]);
|
|
92
|
+
setNewTask({ title: "", description: "", priority: "medium" });
|
|
57
93
|
}
|
|
58
|
-
}
|
|
94
|
+
};
|
|
59
95
|
|
|
60
|
-
const moveTask = (taskId: string, newStatus: Task[
|
|
61
|
-
setTasks(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
96
|
+
const moveTask = (taskId: string, newStatus: Task["status"]) => {
|
|
97
|
+
setTasks(
|
|
98
|
+
tasks.map((task) =>
|
|
99
|
+
task.id === taskId ? { ...task, status: newStatus } : task
|
|
100
|
+
)
|
|
101
|
+
);
|
|
102
|
+
};
|
|
65
103
|
|
|
66
104
|
const deleteTask = (taskId: string) => {
|
|
67
|
-
setTasks(tasks.filter(task => task.id !== taskId))
|
|
68
|
-
}
|
|
105
|
+
setTasks(tasks.filter((task) => task.id !== taskId));
|
|
106
|
+
};
|
|
69
107
|
|
|
70
|
-
const getTasksByStatus = (status: Task[
|
|
71
|
-
return tasks.filter(task => task.status === status)
|
|
72
|
-
}
|
|
108
|
+
const getTasksByStatus = (status: Task["status"]) => {
|
|
109
|
+
return tasks.filter((task) => task.status === status);
|
|
110
|
+
};
|
|
73
111
|
|
|
74
|
-
const getPriorityColor = (priority: Task[
|
|
112
|
+
const getPriorityColor = (priority: Task["priority"]) => {
|
|
75
113
|
switch (priority) {
|
|
76
|
-
case
|
|
77
|
-
|
|
78
|
-
case
|
|
79
|
-
|
|
114
|
+
case "high":
|
|
115
|
+
return "#ff4757";
|
|
116
|
+
case "medium":
|
|
117
|
+
return "#ffa502";
|
|
118
|
+
case "low":
|
|
119
|
+
return "#2ed573";
|
|
120
|
+
default:
|
|
121
|
+
return "#57606f";
|
|
80
122
|
}
|
|
81
|
-
}
|
|
123
|
+
};
|
|
82
124
|
|
|
83
125
|
const columns = [
|
|
84
|
-
{ id:
|
|
85
|
-
{ id:
|
|
86
|
-
{ id:
|
|
87
|
-
] as const
|
|
126
|
+
{ id: "todo", title: "To Do", color: "#57606f" },
|
|
127
|
+
{ id: "in-progress", title: "In Progress", color: "#ffa502" },
|
|
128
|
+
{ id: "done", title: "Done", color: "#2ed573" },
|
|
129
|
+
] as const;
|
|
88
130
|
|
|
89
131
|
return (
|
|
90
|
-
<div style={{ padding:
|
|
91
|
-
<div style={{ marginBottom:
|
|
92
|
-
<h1 style={{ margin:
|
|
132
|
+
<div style={{ padding: "20px" }}>
|
|
133
|
+
<div style={{ marginBottom: "30px" }}>
|
|
134
|
+
<h1 style={{ margin: "0 0 20px 0", color: "#2c3e50" }}>Kanban Board</h1>
|
|
93
135
|
|
|
94
136
|
{/* Add new task form */}
|
|
95
|
-
<div
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
137
|
+
<div
|
|
138
|
+
style={{
|
|
139
|
+
background: "white",
|
|
140
|
+
padding: "20px",
|
|
141
|
+
borderRadius: "8px",
|
|
142
|
+
boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
|
|
143
|
+
marginBottom: "20px",
|
|
144
|
+
}}
|
|
102
145
|
>
|
|
103
|
-
<h3 style={{ margin:
|
|
104
|
-
<div style={{ display:
|
|
146
|
+
<h3 style={{ margin: "0 0 15px 0" }}>Add New Task</h3>
|
|
147
|
+
<div style={{ display: "flex", gap: "10px", flexWrap: "wrap" }}>
|
|
105
148
|
<input
|
|
106
149
|
type="text"
|
|
107
150
|
placeholder="Task title"
|
|
108
151
|
value={newTask.title}
|
|
109
|
-
onChange={e =>
|
|
152
|
+
onChange={(e) =>
|
|
153
|
+
setNewTask({ ...newTask, title: e.target.value })
|
|
154
|
+
}
|
|
110
155
|
style={{
|
|
111
|
-
padding:
|
|
112
|
-
border:
|
|
113
|
-
borderRadius:
|
|
114
|
-
flex:
|
|
115
|
-
minWidth:
|
|
156
|
+
padding: "8px 12px",
|
|
157
|
+
border: "1px solid #ddd",
|
|
158
|
+
borderRadius: "4px",
|
|
159
|
+
flex: "1",
|
|
160
|
+
minWidth: "200px",
|
|
116
161
|
}}
|
|
117
162
|
/>
|
|
118
163
|
<input
|
|
119
164
|
type="text"
|
|
120
165
|
placeholder="Description"
|
|
121
166
|
value={newTask.description}
|
|
122
|
-
onChange={e =>
|
|
167
|
+
onChange={(e) =>
|
|
168
|
+
setNewTask({ ...newTask, description: e.target.value })
|
|
169
|
+
}
|
|
123
170
|
style={{
|
|
124
|
-
padding:
|
|
125
|
-
border:
|
|
126
|
-
borderRadius:
|
|
127
|
-
flex:
|
|
128
|
-
minWidth:
|
|
171
|
+
padding: "8px 12px",
|
|
172
|
+
border: "1px solid #ddd",
|
|
173
|
+
borderRadius: "4px",
|
|
174
|
+
flex: "1",
|
|
175
|
+
minWidth: "200px",
|
|
129
176
|
}}
|
|
130
177
|
/>
|
|
131
178
|
<select
|
|
132
179
|
title="Priority"
|
|
133
180
|
value={newTask.priority}
|
|
134
|
-
onChange={e =>
|
|
181
|
+
onChange={(e) =>
|
|
182
|
+
setNewTask({
|
|
183
|
+
...newTask,
|
|
184
|
+
priority: e.target.value as Task["priority"],
|
|
185
|
+
})
|
|
186
|
+
}
|
|
135
187
|
style={{
|
|
136
|
-
padding:
|
|
137
|
-
border:
|
|
138
|
-
borderRadius:
|
|
188
|
+
padding: "8px 12px",
|
|
189
|
+
border: "1px solid #ddd",
|
|
190
|
+
borderRadius: "4px",
|
|
139
191
|
}}
|
|
140
192
|
>
|
|
141
193
|
<option value="low">Low Priority</option>
|
|
@@ -145,12 +197,12 @@ const KanbanBoard: React.FC<KanbanBoardProps> = ({ initialTasks = [] }) => {
|
|
|
145
197
|
<button
|
|
146
198
|
onClick={addTask}
|
|
147
199
|
style={{
|
|
148
|
-
padding:
|
|
149
|
-
background:
|
|
150
|
-
color:
|
|
151
|
-
border:
|
|
152
|
-
borderRadius:
|
|
153
|
-
cursor:
|
|
200
|
+
padding: "8px 16px",
|
|
201
|
+
background: "#3498db",
|
|
202
|
+
color: "white",
|
|
203
|
+
border: "none",
|
|
204
|
+
borderRadius: "4px",
|
|
205
|
+
cursor: "pointer",
|
|
154
206
|
}}
|
|
155
207
|
>
|
|
156
208
|
Add Task
|
|
@@ -160,82 +212,94 @@ const KanbanBoard: React.FC<KanbanBoardProps> = ({ initialTasks = [] }) => {
|
|
|
160
212
|
</div>
|
|
161
213
|
|
|
162
214
|
{/* Kanban columns */}
|
|
163
|
-
<div style={{ display:
|
|
164
|
-
{columns.map(column => (
|
|
215
|
+
<div style={{ display: "flex", gap: "20px", overflowX: "auto" }}>
|
|
216
|
+
{columns.map((column) => (
|
|
165
217
|
<div
|
|
166
218
|
key={column.id}
|
|
167
219
|
style={{
|
|
168
|
-
flex:
|
|
169
|
-
minWidth:
|
|
170
|
-
background:
|
|
171
|
-
borderRadius:
|
|
172
|
-
boxShadow:
|
|
173
|
-
overflow:
|
|
220
|
+
flex: "1",
|
|
221
|
+
minWidth: "300px",
|
|
222
|
+
background: "white",
|
|
223
|
+
borderRadius: "8px",
|
|
224
|
+
boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
|
|
225
|
+
overflow: "hidden",
|
|
174
226
|
}}
|
|
175
227
|
>
|
|
176
228
|
<div
|
|
177
229
|
style={{
|
|
178
230
|
background: column.color,
|
|
179
|
-
color:
|
|
180
|
-
padding:
|
|
181
|
-
fontWeight:
|
|
182
|
-
display:
|
|
183
|
-
justifyContent:
|
|
184
|
-
alignItems:
|
|
231
|
+
color: "white",
|
|
232
|
+
padding: "15px 20px",
|
|
233
|
+
fontWeight: "bold",
|
|
234
|
+
display: "flex",
|
|
235
|
+
justifyContent: "space-between",
|
|
236
|
+
alignItems: "center",
|
|
185
237
|
}}
|
|
186
238
|
>
|
|
187
239
|
<span>{column.title}</span>
|
|
188
|
-
<span
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
240
|
+
<span
|
|
241
|
+
style={{
|
|
242
|
+
background: "rgba(255,255,255,0.2)",
|
|
243
|
+
padding: "4px 8px",
|
|
244
|
+
borderRadius: "12px",
|
|
245
|
+
fontSize: "12px",
|
|
246
|
+
}}
|
|
194
247
|
>
|
|
195
248
|
{getTasksByStatus(column.id).length}
|
|
196
249
|
</span>
|
|
197
250
|
</div>
|
|
198
251
|
|
|
199
|
-
<div style={{ padding:
|
|
200
|
-
{getTasksByStatus(column.id).map(task => (
|
|
252
|
+
<div style={{ padding: "20px", minHeight: "400px" }}>
|
|
253
|
+
{getTasksByStatus(column.id).map((task) => (
|
|
201
254
|
<div
|
|
202
255
|
key={task.id}
|
|
203
256
|
style={{
|
|
204
|
-
background:
|
|
205
|
-
border:
|
|
206
|
-
borderRadius:
|
|
207
|
-
padding:
|
|
208
|
-
marginBottom:
|
|
209
|
-
cursor:
|
|
257
|
+
background: "#f8f9fa",
|
|
258
|
+
border: "1px solid #e9ecef",
|
|
259
|
+
borderRadius: "6px",
|
|
260
|
+
padding: "15px",
|
|
261
|
+
marginBottom: "10px",
|
|
262
|
+
cursor: "grab",
|
|
210
263
|
}}
|
|
211
264
|
draggable
|
|
212
265
|
onDragStart={(e) => {
|
|
213
|
-
e.dataTransfer.setData(
|
|
266
|
+
e.dataTransfer.setData("text/plain", task.id);
|
|
214
267
|
}}
|
|
215
|
-
onDragOver={e => e.preventDefault()}
|
|
268
|
+
onDragOver={(e) => e.preventDefault()}
|
|
216
269
|
onDrop={(e) => {
|
|
217
|
-
e.preventDefault()
|
|
218
|
-
const taskId = e.dataTransfer.getData(
|
|
270
|
+
e.preventDefault();
|
|
271
|
+
const taskId = e.dataTransfer.getData("text/plain");
|
|
219
272
|
if (taskId === task.id) {
|
|
220
273
|
// Move to next column
|
|
221
|
-
const currentIndex = columns.findIndex(
|
|
222
|
-
|
|
274
|
+
const currentIndex = columns.findIndex(
|
|
275
|
+
(col) => col.id === column.id
|
|
276
|
+
);
|
|
277
|
+
const nextColumn = columns[currentIndex + 1];
|
|
223
278
|
if (nextColumn) {
|
|
224
|
-
moveTask(taskId, nextColumn.id)
|
|
279
|
+
moveTask(taskId, nextColumn.id);
|
|
225
280
|
}
|
|
226
281
|
}
|
|
227
282
|
}}
|
|
228
283
|
>
|
|
229
|
-
<div
|
|
230
|
-
|
|
284
|
+
<div
|
|
285
|
+
style={{
|
|
286
|
+
display: "flex",
|
|
287
|
+
justifyContent: "space-between",
|
|
288
|
+
alignItems: "flex-start",
|
|
289
|
+
marginBottom: "8px",
|
|
290
|
+
}}
|
|
291
|
+
>
|
|
292
|
+
<h4 style={{ margin: "0", color: "#2c3e50" }}>
|
|
293
|
+
{task.title}
|
|
294
|
+
</h4>
|
|
231
295
|
<button
|
|
232
296
|
onClick={() => deleteTask(task.id)}
|
|
233
297
|
style={{
|
|
234
|
-
background:
|
|
235
|
-
border:
|
|
236
|
-
color:
|
|
237
|
-
cursor:
|
|
238
|
-
fontSize:
|
|
298
|
+
background: "none",
|
|
299
|
+
border: "none",
|
|
300
|
+
color: "#e74c3c",
|
|
301
|
+
cursor: "pointer",
|
|
302
|
+
fontSize: "16px",
|
|
239
303
|
}}
|
|
240
304
|
>
|
|
241
305
|
×
|
|
@@ -243,33 +307,46 @@ const KanbanBoard: React.FC<KanbanBoardProps> = ({ initialTasks = [] }) => {
|
|
|
243
307
|
</div>
|
|
244
308
|
|
|
245
309
|
{task.description && (
|
|
246
|
-
<p
|
|
310
|
+
<p
|
|
311
|
+
style={{
|
|
312
|
+
margin: "0 0 10px 0",
|
|
313
|
+
color: "#6c757d",
|
|
314
|
+
fontSize: "14px",
|
|
315
|
+
}}
|
|
316
|
+
>
|
|
247
317
|
{task.description}
|
|
248
318
|
</p>
|
|
249
319
|
)}
|
|
250
320
|
|
|
251
|
-
<div
|
|
321
|
+
<div
|
|
322
|
+
style={{
|
|
323
|
+
display: "flex",
|
|
324
|
+
justifyContent: "space-between",
|
|
325
|
+
alignItems: "center",
|
|
326
|
+
}}
|
|
327
|
+
>
|
|
252
328
|
<div
|
|
253
329
|
style={{
|
|
254
330
|
background: getPriorityColor(task.priority),
|
|
255
|
-
color:
|
|
256
|
-
padding:
|
|
257
|
-
borderRadius:
|
|
258
|
-
fontSize:
|
|
259
|
-
fontWeight:
|
|
331
|
+
color: "white",
|
|
332
|
+
padding: "2px 8px",
|
|
333
|
+
borderRadius: "12px",
|
|
334
|
+
fontSize: "12px",
|
|
335
|
+
fontWeight: "bold",
|
|
260
336
|
}}
|
|
261
337
|
>
|
|
262
338
|
{task.priority.toUpperCase()}
|
|
263
339
|
</div>
|
|
264
340
|
|
|
265
341
|
{task.assignee && (
|
|
266
|
-
<span
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
342
|
+
<span
|
|
343
|
+
style={{
|
|
344
|
+
background: "#e9ecef",
|
|
345
|
+
padding: "2px 8px",
|
|
346
|
+
borderRadius: "12px",
|
|
347
|
+
fontSize: "12px",
|
|
348
|
+
color: "#495057",
|
|
349
|
+
}}
|
|
273
350
|
>
|
|
274
351
|
{task.assignee}
|
|
275
352
|
</span>
|
|
@@ -279,12 +356,13 @@ const KanbanBoard: React.FC<KanbanBoardProps> = ({ initialTasks = [] }) => {
|
|
|
279
356
|
))}
|
|
280
357
|
|
|
281
358
|
{getTasksByStatus(column.id).length === 0 && (
|
|
282
|
-
<div
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
359
|
+
<div
|
|
360
|
+
style={{
|
|
361
|
+
textAlign: "center",
|
|
362
|
+
color: "#6c757d",
|
|
363
|
+
padding: "40px 20px",
|
|
364
|
+
fontStyle: "italic",
|
|
365
|
+
}}
|
|
288
366
|
>
|
|
289
367
|
No tasks in this column
|
|
290
368
|
</div>
|
|
@@ -294,7 +372,7 @@ const KanbanBoard: React.FC<KanbanBoardProps> = ({ initialTasks = [] }) => {
|
|
|
294
372
|
))}
|
|
295
373
|
</div>
|
|
296
374
|
</div>
|
|
297
|
-
)
|
|
298
|
-
}
|
|
375
|
+
);
|
|
376
|
+
};
|
|
299
377
|
|
|
300
|
-
export default KanbanBoard
|
|
378
|
+
export default KanbanBoard;
|