Skip to content

Commit 1eb3517

Browse files
authored
Merge pull request #379 from objectstack-ai/copilot/add-dashboard-kanban-calendar-chatbot
2 parents 1b27d70 + 11b82f6 commit 1eb3517

42 files changed

Lines changed: 5050 additions & 19 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitkeep-build-fixed

Whitespace-only changes.

apps/console/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@
3333
"@object-ui/plugin-calendar": "workspace:*",
3434
"@object-ui/plugin-charts": "workspace:*",
3535
"@object-ui/plugin-dashboard": "workspace:*",
36+
"@object-ui/plugin-detail": "workspace:*",
3637
"@object-ui/plugin-form": "workspace:*",
3738
"@object-ui/plugin-gantt": "workspace:*",
3839
"@object-ui/plugin-grid": "workspace:*",
3940
"@object-ui/plugin-kanban": "workspace:*",
41+
"@object-ui/plugin-list": "workspace:*",
4042
"@object-ui/react": "workspace:*",
4143
"@object-ui/types": "workspace:*",
4244
"@objectstack/client": "^0.9.0",

apps/console/src/main.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import { startMockServer } from './mocks/browser';
1212

1313
// Register plugins
1414
import '@object-ui/plugin-charts';
15+
import '@object-ui/plugin-list';
16+
import '@object-ui/plugin-detail';
1517

1618
// Start MSW before rendering the app
1719
async function bootstrap() {

examples/kitchen-sink/objectstack.config.ts

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,18 @@ export default defineStack({
3131
type: 'page',
3232
pageName: 'help_page',
3333
label: 'Help & Resources'
34+
},
35+
{
36+
id: 'nav_listview',
37+
type: 'page',
38+
pageName: 'list_view_demo',
39+
label: 'ListView Demo'
40+
},
41+
{
42+
id: 'nav_detailview',
43+
type: 'page',
44+
pageName: 'detail_view_demo',
45+
label: 'DetailView Demo'
3446
}
3547
]
3648
})
@@ -169,6 +181,95 @@ export default defineStack({
169181
]
170182
}
171183
]
184+
},
185+
{
186+
name: 'list_view_demo',
187+
label: 'ListView Demo',
188+
type: 'app',
189+
regions: [
190+
{
191+
name: 'main',
192+
components: [
193+
{
194+
type: 'list-view',
195+
properties: {
196+
objectName: 'contacts',
197+
viewType: 'grid',
198+
fields: ['name', 'email', 'phone', 'company'],
199+
sort: [{ field: 'name', order: 'asc' }],
200+
options: {
201+
grid: {
202+
columns: ['name', 'email', 'phone', 'company'],
203+
pageSize: 25,
204+
},
205+
kanban: {
206+
groupField: 'status',
207+
titleField: 'name',
208+
},
209+
}
210+
}
211+
}
212+
]
213+
}
214+
]
215+
},
216+
{
217+
name: 'detail_view_demo',
218+
label: 'DetailView Demo',
219+
type: 'app',
220+
regions: [
221+
{
222+
name: 'main',
223+
components: [
224+
{
225+
type: 'detail-view',
226+
properties: {
227+
title: 'Contact Details',
228+
objectName: 'contacts',
229+
resourceId: '1',
230+
sections: [
231+
{
232+
title: 'Basic Information',
233+
icon: '👤',
234+
fields: [
235+
{ name: 'name', label: 'Full Name' },
236+
{ name: 'email', label: 'Email' },
237+
{ name: 'phone', label: 'Phone' },
238+
{ name: 'company', label: 'Company' },
239+
],
240+
columns: 2,
241+
},
242+
{
243+
title: 'Additional Details',
244+
collapsible: true,
245+
defaultCollapsed: false,
246+
fields: [
247+
{ name: 'title', label: 'Job Title' },
248+
{ name: 'department', label: 'Department' },
249+
],
250+
columns: 2,
251+
}
252+
],
253+
tabs: [
254+
{
255+
key: 'details',
256+
label: 'Details',
257+
icon: '📋',
258+
},
259+
{
260+
key: 'activity',
261+
label: 'Activity',
262+
badge: '5',
263+
}
264+
],
265+
showBack: true,
266+
showEdit: true,
267+
showDelete: true,
268+
}
269+
}
270+
]
271+
}
272+
]
172273
}
173274
],
174275
manifest: {

packages/components/src/stories-json/chatbot.stories.tsx

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,140 @@ export const CustomerSupport: Story = {
109109
className: 'w-full max-w-2xl'
110110
} as any,
111111
};
112+
113+
export const WithMarkdown: Story = {
114+
render: renderStory,
115+
args: {
116+
type: 'chatbot',
117+
messages: [
118+
{
119+
id: '1',
120+
role: 'user',
121+
content: 'Can you show me how to use markdown?',
122+
},
123+
{
124+
id: '2',
125+
role: 'assistant',
126+
content: `Sure! Here are some markdown examples:
127+
128+
**Bold text** and *italic text*
129+
130+
# Heading 1
131+
## Heading 2
132+
133+
- List item 1
134+
- List item 2
135+
- List item 3
136+
137+
\`inline code\` and code blocks:
138+
139+
\`\`\`javascript
140+
const greeting = "Hello, World!";
141+
console.log(greeting);
142+
\`\`\`
143+
144+
> This is a blockquote
145+
`,
146+
}
147+
],
148+
placeholder: 'Type your message...',
149+
enableMarkdown: true,
150+
showTimestamp: false,
151+
autoResponse: true,
152+
autoResponseText: 'Markdown is great for formatting!',
153+
className: 'w-full max-w-2xl'
154+
} as any,
155+
};
156+
157+
export const WithCodeHighlighting: Story = {
158+
render: renderStory,
159+
args: {
160+
type: 'chatbot',
161+
messages: [
162+
{
163+
id: '1',
164+
role: 'user',
165+
content: 'Can you help me with a React component?',
166+
},
167+
{
168+
id: '2',
169+
role: 'assistant',
170+
content: `Of course! Here's a simple React component example:
171+
172+
\`\`\`tsx
173+
import React from 'react';
174+
175+
interface ButtonProps {
176+
label: string;
177+
onClick: () => void;
178+
}
179+
180+
export const Button: React.FC<ButtonProps> = ({ label, onClick }) => {
181+
return (
182+
<button
183+
onClick={onClick}
184+
className="px-4 py-2 bg-blue-500 text-white rounded"
185+
>
186+
{label}
187+
</button>
188+
);
189+
};
190+
\`\`\`
191+
192+
This component accepts a \`label\` and \`onClick\` handler as props.`,
193+
}
194+
],
195+
placeholder: 'Ask me anything...',
196+
enableMarkdown: true,
197+
showTimestamp: false,
198+
autoResponse: true,
199+
autoResponseText: 'I can help with code examples!',
200+
className: 'w-full max-w-2xl'
201+
} as any,
202+
};
203+
204+
export const WithFileUpload: Story = {
205+
render: renderStory,
206+
args: {
207+
type: 'chatbot',
208+
messages: [
209+
{
210+
id: '1',
211+
role: 'assistant',
212+
content: 'You can upload files by clicking the attachment button below.',
213+
}
214+
],
215+
placeholder: 'Type your message or upload a file...',
216+
enableFileUpload: true,
217+
acceptedFileTypes: 'image/*,.pdf,.doc,.docx',
218+
maxFileSize: 5242880, // 5MB
219+
showTimestamp: false,
220+
autoResponse: true,
221+
autoResponseText: 'File received! Processing...',
222+
className: 'w-full max-w-2xl'
223+
} as any,
224+
};
225+
226+
export const StreamingResponse: Story = {
227+
render: renderStory,
228+
args: {
229+
type: 'chatbot',
230+
messages: [
231+
{
232+
id: '1',
233+
role: 'user',
234+
content: 'Tell me a story',
235+
},
236+
{
237+
id: '2',
238+
role: 'assistant',
239+
content: 'Once upon a time in a digital world...',
240+
streaming: true,
241+
}
242+
],
243+
placeholder: 'Type your message...',
244+
enableMarkdown: true,
245+
showTimestamp: false,
246+
className: 'w-full max-w-2xl'
247+
} as any,
248+
};

packages/components/src/stories-json/dashboard.stories.tsx

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,114 @@ export const WithChartsAndMetrics: Story = {
205205
]
206206
} as any,
207207
};
208+
209+
export const WithGridLayout: Story = {
210+
render: renderStory,
211+
args: {
212+
type: 'dashboard',
213+
name: 'sales_dashboard',
214+
title: 'Sales Analytics Dashboard',
215+
enableGridLayout: true,
216+
persistLayout: true,
217+
widgets: [
218+
{
219+
id: 'total-revenue',
220+
type: 'metric-card',
221+
title: 'Total Revenue',
222+
value: '$142,892',
223+
change: '+12.5%',
224+
trend: 'up',
225+
layout: { x: 0, y: 0, w: 3, h: 2 },
226+
},
227+
{
228+
id: 'new-customers',
229+
type: 'metric-card',
230+
title: 'New Customers',
231+
value: '847',
232+
change: '+8.2%',
233+
trend: 'up',
234+
layout: { x: 3, y: 0, w: 3, h: 2 },
235+
},
236+
{
237+
id: 'conversion-rate',
238+
type: 'metric-card',
239+
title: 'Conversion Rate',
240+
value: '3.24%',
241+
change: '-0.5%',
242+
trend: 'down',
243+
layout: { x: 6, y: 0, w: 3, h: 2 },
244+
},
245+
{
246+
id: 'revenue-chart',
247+
type: 'bar',
248+
title: 'Monthly Revenue',
249+
data: [
250+
{ month: 'Jan', revenue: 12000 },
251+
{ month: 'Feb', revenue: 15000 },
252+
{ month: 'Mar', revenue: 18000 },
253+
{ month: 'Apr', revenue: 14000 },
254+
{ month: 'May', revenue: 20000 },
255+
{ month: 'Jun', revenue: 22000 },
256+
],
257+
xAxisKey: 'month',
258+
series: [{ dataKey: 'revenue' }],
259+
layout: { x: 0, y: 2, w: 6, h: 4 },
260+
},
261+
{
262+
id: 'top-products',
263+
type: 'table',
264+
title: 'Top Products',
265+
columns: ['Product', 'Sales', 'Revenue'],
266+
data: [
267+
{ Product: 'Product A', Sales: 245, Revenue: '$12,450' },
268+
{ Product: 'Product B', Sales: 189, Revenue: '$9,450' },
269+
{ Product: 'Product C', Sales: 156, Revenue: '$7,800' },
270+
],
271+
layout: { x: 6, y: 2, w: 3, h: 4 },
272+
},
273+
],
274+
} as any,
275+
};
276+
277+
export const EditableLayout: Story = {
278+
render: renderStory,
279+
args: {
280+
type: 'dashboard',
281+
name: 'custom_dashboard',
282+
title: 'Customizable Dashboard',
283+
enableGridLayout: true,
284+
enableEditMode: true,
285+
persistLayout: true,
286+
widgets: [
287+
{
288+
id: 'widget-1',
289+
type: 'metric-card',
290+
title: 'Metric 1',
291+
value: '1,234',
292+
layout: { x: 0, y: 0, w: 3, h: 2 },
293+
},
294+
{
295+
id: 'widget-2',
296+
type: 'metric-card',
297+
title: 'Metric 2',
298+
value: '5,678',
299+
layout: { x: 3, y: 0, w: 3, h: 2 },
300+
},
301+
{
302+
id: 'widget-3',
303+
type: 'line',
304+
title: 'Trend Chart',
305+
data: [
306+
{ date: 'Mon', value: 100 },
307+
{ date: 'Tue', value: 150 },
308+
{ date: 'Wed', value: 130 },
309+
{ date: 'Thu', value: 180 },
310+
{ date: 'Fri', value: 200 },
311+
],
312+
xAxisKey: 'date',
313+
series: [{ dataKey: 'value' }],
314+
layout: { x: 0, y: 2, w: 6, h: 3 },
315+
},
316+
],
317+
} as any,
318+
};

0 commit comments

Comments
 (0)