@almadar/std 14.8.0 → 14.10.0

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.
Files changed (59) hide show
  1. package/behaviors/registry/app/organisms/std-api-gateway.orb +1303 -4002
  2. package/behaviors/registry/app/organisms/std-booking-system.orb +2131 -3645
  3. package/behaviors/registry/app/organisms/std-cicd-pipeline.orb +1449 -3612
  4. package/behaviors/registry/app/organisms/std-cms.orb +1833 -4943
  5. package/behaviors/registry/app/organisms/std-coding-academy.orb +686 -1238
  6. package/behaviors/registry/app/organisms/std-crm.orb +1872 -5949
  7. package/behaviors/registry/app/organisms/std-devops-dashboard.orb +2046 -5532
  8. package/behaviors/registry/app/organisms/std-finance-tracker.orb +1141 -3716
  9. package/behaviors/registry/app/organisms/std-healthcare.orb +3281 -7478
  10. package/behaviors/registry/app/organisms/std-helpdesk.orb +1046 -4062
  11. package/behaviors/registry/app/organisms/std-hr-portal.orb +2560 -6447
  12. package/behaviors/registry/app/organisms/std-iot-dashboard.orb +1657 -3716
  13. package/behaviors/registry/app/organisms/std-lms.orb +1933 -3916
  14. package/behaviors/registry/app/organisms/std-project-manager.orb +1417 -5232
  15. package/behaviors/registry/app/organisms/std-realtime-chat.orb +1308 -3873
  16. package/behaviors/registry/app/organisms/std-social-feed.orb +1135 -1700
  17. package/behaviors/registry/app/organisms/std-trading-dashboard.orb +1333 -3187
  18. package/behaviors/registry/core/atoms/std-graphs.orb +40 -41
  19. package/behaviors/registry/core/atoms/std-stats.orb +131 -110
  20. package/behaviors/registry/core/molecules/std-app-layout.orb +90 -21
  21. package/behaviors/registry/service/atoms/std-service-custom-bearer.orb +351 -345
  22. package/behaviors/registry/service/atoms/std-service-email.orb +334 -328
  23. package/behaviors/registry/service/atoms/std-service-github.orb +308 -365
  24. package/behaviors/registry/service/atoms/std-service-llm.orb +329 -437
  25. package/behaviors/registry/service/atoms/std-service-oauth.orb +261 -564
  26. package/behaviors/registry/service/atoms/std-service-redis.orb +299 -405
  27. package/behaviors/registry/service/atoms/std-service-storage.orb +293 -505
  28. package/behaviors/registry/service/atoms/std-service-twilio.orb +315 -393
  29. package/behaviors/registry/service/atoms/std-service-youtube.orb +266 -547
  30. package/dist/behaviors/registry/app/organisms/std-api-gateway.orb +1303 -4002
  31. package/dist/behaviors/registry/app/organisms/std-booking-system.orb +2131 -3645
  32. package/dist/behaviors/registry/app/organisms/std-cicd-pipeline.orb +1449 -3612
  33. package/dist/behaviors/registry/app/organisms/std-cms.orb +1833 -4943
  34. package/dist/behaviors/registry/app/organisms/std-coding-academy.orb +686 -1238
  35. package/dist/behaviors/registry/app/organisms/std-crm.orb +1872 -5949
  36. package/dist/behaviors/registry/app/organisms/std-devops-dashboard.orb +2046 -5532
  37. package/dist/behaviors/registry/app/organisms/std-finance-tracker.orb +1141 -3716
  38. package/dist/behaviors/registry/app/organisms/std-healthcare.orb +3281 -7478
  39. package/dist/behaviors/registry/app/organisms/std-helpdesk.orb +1046 -4062
  40. package/dist/behaviors/registry/app/organisms/std-hr-portal.orb +2560 -6447
  41. package/dist/behaviors/registry/app/organisms/std-iot-dashboard.orb +1657 -3716
  42. package/dist/behaviors/registry/app/organisms/std-lms.orb +1933 -3916
  43. package/dist/behaviors/registry/app/organisms/std-project-manager.orb +1417 -5232
  44. package/dist/behaviors/registry/app/organisms/std-realtime-chat.orb +1308 -3873
  45. package/dist/behaviors/registry/app/organisms/std-social-feed.orb +1135 -1700
  46. package/dist/behaviors/registry/app/organisms/std-trading-dashboard.orb +1333 -3187
  47. package/dist/behaviors/registry/core/atoms/std-graphs.orb +40 -41
  48. package/dist/behaviors/registry/core/atoms/std-stats.orb +131 -110
  49. package/dist/behaviors/registry/core/molecules/std-app-layout.orb +90 -21
  50. package/dist/behaviors/registry/service/atoms/std-service-custom-bearer.orb +351 -345
  51. package/dist/behaviors/registry/service/atoms/std-service-email.orb +334 -328
  52. package/dist/behaviors/registry/service/atoms/std-service-github.orb +308 -365
  53. package/dist/behaviors/registry/service/atoms/std-service-llm.orb +329 -437
  54. package/dist/behaviors/registry/service/atoms/std-service-oauth.orb +261 -564
  55. package/dist/behaviors/registry/service/atoms/std-service-redis.orb +299 -405
  56. package/dist/behaviors/registry/service/atoms/std-service-storage.orb +293 -505
  57. package/dist/behaviors/registry/service/atoms/std-service-twilio.orb +315 -393
  58. package/dist/behaviors/registry/service/atoms/std-service-youtube.orb +266 -547
  59. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "std-social-feed",
3
- "version": "1.0.0",
4
- "description": "Social feed: posts with comments. Pick for Twitter/Instagram-style timelines with replies.",
3
+ "version": "2.0.0",
4
+ "description": "Social feed: posts with images, likes, and threaded comments. Pick for Twitter/Instagram-style timelines.",
5
5
  "orbitals": [
6
6
  {
7
7
  "name": "PostOrbital",
@@ -9,11 +9,36 @@
9
9
  {
10
10
  "from": "std/behaviors/std-app-layout",
11
11
  "as": "AppShell"
12
+ },
13
+ {
14
+ "from": "std/behaviors/std-modal",
15
+ "as": "Modal"
16
+ },
17
+ {
18
+ "from": "std/behaviors/std-confirmation",
19
+ "as": "Confirmation"
20
+ },
21
+ {
22
+ "from": "std/behaviors/std-search",
23
+ "as": "Search"
24
+ },
25
+ {
26
+ "from": "std/behaviors/std-stats",
27
+ "as": "Stats"
28
+ },
29
+ {
30
+ "from": "std/behaviors/std-browse",
31
+ "as": "Browse"
32
+ },
33
+ {
34
+ "from": "std/behaviors/std-service-storage",
35
+ "as": "Storage"
12
36
  }
13
37
  ],
14
38
  "entity": {
15
39
  "name": "Post",
16
- "persistence": "runtime",
40
+ "collection": "posts",
41
+ "persistence": "persistent",
17
42
  "fields": [
18
43
  {
19
44
  "name": "id",
@@ -21,9 +46,9 @@
21
46
  "required": true
22
47
  },
23
48
  {
24
- "name": "title",
49
+ "name": "author",
25
50
  "type": "string",
26
- "default": ""
51
+ "required": true
27
52
  },
28
53
  {
29
54
  "name": "content",
@@ -31,12 +56,12 @@
31
56
  "default": ""
32
57
  },
33
58
  {
34
- "name": "author",
59
+ "name": "image",
35
60
  "type": "string",
36
61
  "default": ""
37
62
  },
38
63
  {
39
- "name": "createdAt",
64
+ "name": "timestamp",
40
65
  "type": "datetime",
41
66
  "default": ""
42
67
  },
@@ -44,6 +69,16 @@
44
69
  "name": "likes",
45
70
  "type": "number",
46
71
  "default": 0.0
72
+ },
73
+ {
74
+ "name": "tag",
75
+ "type": "string",
76
+ "default": ""
77
+ },
78
+ {
79
+ "name": "pendingId",
80
+ "type": "string",
81
+ "default": ""
47
82
  }
48
83
  ]
49
84
  },
@@ -52,152 +87,39 @@
52
87
  "ref": "AppShell.traits.AppLayout",
53
88
  "name": "PostAppLayout",
54
89
  "config": {
55
- "searchEvent": "POST_SEARCH",
56
- "notificationClickEvent": "POST_NOTIFICATIONS_OPEN",
57
90
  "navItems": [
58
91
  {
92
+ "label": "Feed",
59
93
  "href": "/feed",
60
- "icon": "layout-list",
61
- "label": "Feed"
94
+ "icon": "rss"
62
95
  },
63
96
  {
64
- "icon": "message-circle",
65
- "label": "Messages",
66
- "href": "/messages"
97
+ "label": "Comments",
98
+ "href": "/comments",
99
+ "icon": "message-circle"
67
100
  }
68
101
  ],
69
- "contentTrait": "@trait.PostBrowse",
102
+ "contentTrait": "@trait.FeedCatalog",
103
+ "appName": "SocialFeed",
104
+ "searchEvent": "POST_SEARCH",
70
105
  "notifications": [],
71
- "appName": "SocialFeed"
106
+ "notificationClickEvent": "POST_NOTIFICATIONS_OPEN"
72
107
  },
73
108
  "events": {
74
- "NOTIFY_CLICK": "POST_NOTIFICATIONS_OPEN",
75
- "SEARCH": "POST_SEARCH"
109
+ "SEARCH": "POST_SEARCH",
110
+ "NOTIFY_CLICK": "POST_NOTIFICATIONS_OPEN"
76
111
  }
77
112
  },
78
113
  {
79
- "name": "PostBrowse",
114
+ "name": "FeedCatalog",
80
115
  "category": "interaction",
81
- "linkedEntity": "Post",
82
116
  "emits": [
83
117
  {
84
- "event": "COMMENT",
118
+ "event": "CREATE",
85
119
  "scope": "external",
86
120
  "payloadSchema": [
87
121
  {
88
- "name": "id",
89
- "type": "string"
90
- }
91
- ]
92
- },
93
- {
94
- "event": "CREATE"
95
- },
96
- {
97
- "event": "VIEW",
98
- "payloadSchema": [
99
- {
100
- "name": "id",
101
- "type": "string",
102
- "required": true
103
- },
104
- {
105
- "name": "row.id",
106
- "type": "string",
107
- "required": true
108
- },
109
- {
110
- "name": "row.title",
111
- "type": "string"
112
- },
113
- {
114
- "name": "row.content",
115
- "type": "string"
116
- },
117
- {
118
- "name": "row.author",
119
- "type": "string"
120
- },
121
- {
122
- "name": "row.createdAt",
123
- "type": "datetime"
124
- },
125
- {
126
- "name": "row.likes",
127
- "type": "number"
128
- }
129
- ]
130
- },
131
- {
132
- "event": "PostLoaded",
133
- "description": "Fired when Post finishes loading",
134
- "scope": "internal",
135
- "payloadSchema": [
136
- {
137
- "name": "data",
138
- "type": "[Post]"
139
- }
140
- ]
141
- },
142
- {
143
- "event": "PostLoadFailed",
144
- "description": "Fired when Post fails to load",
145
- "scope": "internal",
146
- "payloadSchema": [
147
- {
148
- "name": "error",
149
- "type": "string"
150
- },
151
- {
152
- "name": "code",
153
- "type": "string"
154
- }
155
- ]
156
- },
157
- {
158
- "event": "PostSaved",
159
- "scope": "internal",
160
- "payloadSchema": [
161
- {
162
- "name": "id",
163
- "type": "string"
164
- }
165
- ]
166
- },
167
- {
168
- "event": "PostSaveFailed",
169
- "scope": "internal",
170
- "payloadSchema": [
171
- {
172
- "name": "error",
173
- "type": "string"
174
- },
175
- {
176
- "name": "code",
177
- "type": "string"
178
- }
179
- ]
180
- },
181
- {
182
- "event": "CommentSaved",
183
- "scope": "internal",
184
- "payloadSchema": [
185
- {
186
- "name": "id",
187
- "type": "string"
188
- }
189
- ]
190
- },
191
- {
192
- "event": "CommentSaveFailed",
193
- "scope": "internal",
194
- "payloadSchema": [
195
- {
196
- "name": "error",
197
- "type": "string"
198
- },
199
- {
200
- "name": "code",
122
+ "name": "source",
201
123
  "type": "string"
202
124
  }
203
125
  ]
@@ -224,7 +146,7 @@
224
146
  "stateMachine": {
225
147
  "states": [
226
148
  {
227
- "name": "browsing",
149
+ "name": "composing",
228
150
  "isInitial": true
229
151
  }
230
152
  ],
@@ -253,704 +175,439 @@
253
175
  }
254
176
  ]
255
177
  },
256
- {
257
- "key": "PostLoaded",
258
- "name": "Post loaded",
259
- "payloadSchema": [
260
- {
261
- "name": "data",
262
- "type": "[Post]"
263
- }
264
- ]
265
- },
266
- {
267
- "key": "PostLoadFailed",
268
- "name": "Post load failed",
269
- "payloadSchema": [
270
- {
271
- "name": "error",
272
- "type": "string"
273
- },
274
- {
275
- "name": "code",
276
- "type": "string"
277
- }
278
- ]
279
- },
280
- {
281
- "key": "COMMENT",
282
- "name": "Comment"
283
- },
284
178
  {
285
179
  "key": "CREATE",
286
180
  "name": "Create"
287
- },
288
- {
289
- "key": "VIEW",
290
- "name": "View",
291
- "payloadSchema": [
292
- {
293
- "name": "id",
294
- "type": "string",
295
- "required": true
296
- },
297
- {
298
- "name": "row",
299
- "type": "Post"
300
- }
301
- ]
302
- },
303
- {
304
- "key": "PostSaved",
305
- "name": "Post saved",
306
- "payloadSchema": [
307
- {
308
- "name": "id",
309
- "type": "string"
310
- }
311
- ]
312
- },
313
- {
314
- "key": "PostSaveFailed",
315
- "name": "Post save failed",
316
- "payloadSchema": [
317
- {
318
- "name": "error",
319
- "type": "string"
320
- },
321
- {
322
- "name": "code",
323
- "type": "string"
324
- }
325
- ]
326
- },
327
- {
328
- "key": "CommentSaved",
329
- "name": "Comment saved",
330
- "payloadSchema": [
331
- {
332
- "name": "id",
333
- "type": "string"
334
- }
335
- ]
336
- },
337
- {
338
- "key": "CommentSaveFailed",
339
- "name": "Comment save failed",
340
- "payloadSchema": [
341
- {
342
- "name": "error",
343
- "type": "string"
344
- },
345
- {
346
- "name": "code",
347
- "type": "string"
348
- }
349
- ]
350
181
  }
351
182
  ],
352
183
  "transitions": [
353
184
  {
354
- "from": "browsing",
355
- "to": "browsing",
185
+ "from": "composing",
186
+ "to": "composing",
356
187
  "event": "INIT",
357
188
  "effects": [
358
- [
359
- "fetch",
360
- "Post",
361
- {
362
- "emit": {
363
- "failure": "PostLoadFailed",
364
- "success": "PostLoaded"
365
- }
366
- }
367
- ],
368
189
  [
369
190
  "render-ui",
370
191
  "main",
371
192
  {
372
- "gap": "md",
373
- "direction": "vertical",
374
- "align": "center",
375
- "className": "py-12",
376
- "type": "stack",
377
193
  "children": [
378
194
  {
379
- "type": "spinner"
195
+ "type": "stack",
196
+ "align": "center",
197
+ "direction": "horizontal",
198
+ "justify": "between",
199
+ "gap": "md",
200
+ "children": [
201
+ {
202
+ "children": [
203
+ {
204
+ "name": "rss",
205
+ "type": "icon"
206
+ },
207
+ {
208
+ "content": "Feed",
209
+ "variant": "h2",
210
+ "type": "typography"
211
+ }
212
+ ],
213
+ "direction": "horizontal",
214
+ "type": "stack",
215
+ "gap": "sm",
216
+ "align": "center"
217
+ },
218
+ {
219
+ "gap": "sm",
220
+ "children": [
221
+ {
222
+ "action": "CREATE",
223
+ "type": "button",
224
+ "variant": "primary",
225
+ "label": "New Post",
226
+ "icon": "plus"
227
+ }
228
+ ],
229
+ "type": "stack",
230
+ "direction": "horizontal"
231
+ }
232
+ ]
233
+ },
234
+ {
235
+ "type": "divider"
380
236
  },
381
237
  {
382
- "type": "typography",
383
- "variant": "caption",
384
- "color": "muted",
385
- "content": "Loading…"
386
- }
387
- ]
238
+ "gap": "md",
239
+ "type": "stack",
240
+ "children": [
241
+ "@trait.PostSearch"
242
+ ],
243
+ "direction": "horizontal",
244
+ "align": "center"
245
+ },
246
+ "@trait.PostStats",
247
+ {
248
+ "type": "divider"
249
+ },
250
+ "@trait.PostBrowseList"
251
+ ],
252
+ "type": "stack",
253
+ "direction": "vertical",
254
+ "gap": "lg"
388
255
  }
389
256
  ]
390
257
  ]
391
258
  },
392
259
  {
393
- "from": "browsing",
394
- "to": "browsing",
395
- "event": "POST_SEARCH",
260
+ "from": "composing",
261
+ "to": "composing",
262
+ "event": "POST_SEARCH"
263
+ },
264
+ {
265
+ "from": "composing",
266
+ "to": "composing",
267
+ "event": "POST_NOTIFICATIONS_OPEN",
396
268
  "effects": [
397
- [
398
- "fetch",
399
- "Post",
400
- {
401
- "emit": {
402
- "success": "PostLoaded",
403
- "failure": "PostLoadFailed"
404
- }
405
- }
406
- ],
407
269
  [
408
270
  "render-ui",
409
271
  "main",
410
272
  {
411
- "direction": "vertical",
412
- "className": "py-12",
413
273
  "align": "center",
274
+ "direction": "vertical",
275
+ "gap": "md",
276
+ "className": "py-8",
414
277
  "children": [
415
278
  {
416
- "type": "spinner"
417
- },
418
- {
419
- "color": "muted",
420
- "variant": "caption",
421
- "type": "typography",
422
- "content": "Searching…"
423
- }
424
- ],
425
- "gap": "md",
426
- "type": "stack"
427
- }
428
- ]
429
- ]
430
- },
431
- {
432
- "from": "browsing",
433
- "to": "browsing",
434
- "event": "POST_NOTIFICATIONS_OPEN",
435
- "effects": [
436
- [
437
- "render-ui",
438
- "main",
439
- {
440
- "children": [
441
- {
442
- "type": "icon",
443
- "name": "bell"
279
+ "type": "icon",
280
+ "name": "bell"
444
281
  },
445
282
  {
283
+ "variant": "h3",
446
284
  "content": "No notifications",
447
- "type": "typography",
448
- "variant": "h3"
285
+ "type": "typography"
449
286
  },
450
287
  {
451
- "variant": "caption",
452
288
  "color": "muted",
453
289
  "type": "typography",
290
+ "variant": "caption",
454
291
  "content": "You're all caught up."
455
292
  },
456
293
  {
457
- "type": "button",
458
- "variant": "ghost",
294
+ "action": "INIT",
459
295
  "label": "Back to feed",
460
- "action": "INIT"
296
+ "type": "button",
297
+ "variant": "ghost"
461
298
  }
462
299
  ],
463
- "gap": "md",
464
- "direction": "vertical",
465
- "align": "center",
466
- "type": "stack",
467
- "className": "py-8"
300
+ "type": "stack"
468
301
  }
469
302
  ]
470
303
  ]
304
+ }
305
+ ]
306
+ },
307
+ "scope": "instance"
308
+ },
309
+ {
310
+ "ref": "Search.traits.SearchResultSearch",
311
+ "name": "PostSearch",
312
+ "config": {
313
+ "event": "POST_SEARCH",
314
+ "placeholder": "Search posts…"
315
+ }
316
+ },
317
+ {
318
+ "ref": "Stats.traits.StatsItemStats",
319
+ "name": "PostStats",
320
+ "config": {
321
+ "title": "Feed",
322
+ "metrics": [
323
+ {
324
+ "aggregation": "count",
325
+ "label": "Total Posts",
326
+ "icon": "rss",
327
+ "format": "number",
328
+ "variant": "primary"
471
329
  },
472
330
  {
473
- "from": "browsing",
474
- "to": "browsing",
475
- "event": "PostLoaded",
476
- "effects": [
331
+ "format": "number",
332
+ "aggregation": "count",
333
+ "filter": [
334
+ "fn",
335
+ "row",
477
336
  [
478
- "render-ui",
479
- "main",
480
- {
481
- "type": "stack",
482
- "gap": "lg",
483
- "direction": "vertical",
484
- "children": [
485
- {
486
- "align": "center",
487
- "direction": "horizontal",
488
- "gap": "md",
489
- "justify": "between",
490
- "type": "stack",
491
- "children": [
492
- {
493
- "type": "stack",
494
- "direction": "horizontal",
495
- "children": [
496
- {
497
- "type": "icon",
498
- "name": "rss"
499
- },
500
- {
501
- "type": "typography",
502
- "content": "Feed",
503
- "variant": "h2"
504
- }
505
- ],
506
- "gap": "sm",
507
- "align": "center"
508
- },
509
- {
510
- "gap": "sm",
511
- "type": "stack",
512
- "children": [
513
- {
514
- "icon": "plus",
515
- "type": "button",
516
- "action": "CREATE",
517
- "label": "New Post",
518
- "variant": "primary"
519
- }
520
- ],
521
- "direction": "horizontal"
522
- }
523
- ]
524
- },
525
- {
526
- "type": "divider"
527
- },
528
- {
529
- "gap": "sm",
530
- "fields": [
531
- {
532
- "name": "title",
533
- "variant": "h3",
534
- "icon": "rss"
535
- },
536
- {
537
- "format": "number",
538
- "variant": "badge",
539
- "name": "likes"
540
- },
541
- {
542
- "variant": "body",
543
- "name": "author"
544
- },
545
- {
546
- "name": "content",
547
- "variant": "body"
548
- },
549
- {
550
- "label": "Posted",
551
- "variant": "caption",
552
- "format": "date",
553
- "name": "createdAt"
554
- }
555
- ],
556
- "variant": "card",
557
- "entity": "@payload.data",
558
- "type": "data-list",
559
- "itemActions": [
560
- {
561
- "label": "View",
562
- "variant": "ghost",
563
- "event": "VIEW"
564
- }
565
- ]
566
- }
567
- ]
568
- }
337
+ "=",
338
+ "@row.timestamp",
339
+ "today"
569
340
  ]
570
- ]
341
+ ],
342
+ "label": "Today",
343
+ "icon": "calendar",
344
+ "variant": "info"
571
345
  },
572
346
  {
573
- "from": "browsing",
574
- "to": "browsing",
575
- "event": "PostLoadFailed",
576
- "effects": [
577
- [
578
- "render-ui",
579
- "main",
580
- {
581
- "children": [
582
- {
583
- "type": "icon",
584
- "name": "alert-triangle",
585
- "color": "destructive"
586
- },
587
- {
588
- "content": "Failed to load post",
589
- "type": "typography",
590
- "variant": "h3"
591
- },
592
- {
593
- "color": "muted",
594
- "variant": "body",
595
- "content": "@payload.error",
596
- "type": "typography"
597
- },
598
- {
599
- "icon": "rotate-ccw",
600
- "type": "button",
601
- "variant": "primary",
602
- "label": "Retry",
603
- "action": "INIT"
604
- }
605
- ],
606
- "align": "center",
607
- "direction": "vertical",
608
- "className": "py-12",
609
- "gap": "md",
610
- "type": "stack"
611
- }
612
- ]
613
- ]
347
+ "aggregation": "mode",
348
+ "label": "Top Author",
349
+ "icon": "user",
350
+ "field": "author",
351
+ "format": "text",
352
+ "variant": "default"
353
+ },
354
+ {
355
+ "field": "tag",
356
+ "aggregation": "mode",
357
+ "icon": "hash",
358
+ "variant": "warning",
359
+ "label": "Top Tag",
360
+ "format": "text"
614
361
  }
615
362
  ]
616
363
  },
617
- "scope": "collection"
618
- },
619
- {
620
- "name": "PostCreate",
621
- "category": "interaction",
622
- "linkedEntity": "Post",
623
- "emits": [
624
- {
625
- "event": "PostLoadFailed",
626
- "description": "Fired when Post fails to load",
627
- "scope": "internal",
628
- "payloadSchema": [
629
- {
630
- "name": "error",
631
- "type": "string"
632
- },
633
- {
634
- "name": "code",
635
- "type": "string"
636
- }
637
- ]
638
- },
639
- {
640
- "event": "PostLoaded",
641
- "description": "Fired when Post finishes loading",
642
- "scope": "internal",
643
- "payloadSchema": [
644
- {
645
- "name": "data",
646
- "type": "[Post]"
647
- }
648
- ]
649
- },
650
- {
651
- "event": "PostSaveFailed",
652
- "scope": "internal",
653
- "payloadSchema": [
654
- {
655
- "name": "error",
656
- "type": "string"
657
- },
658
- {
659
- "name": "code",
660
- "type": "string"
661
- }
662
- ]
663
- },
664
- {
665
- "event": "PostSaved",
666
- "scope": "internal",
667
- "payloadSchema": [
668
- {
669
- "name": "id",
670
- "type": "string"
671
- }
672
- ]
673
- }
674
- ],
675
364
  "listens": [
676
365
  {
677
- "event": "CREATE",
678
- "triggers": "CREATE",
366
+ "event": "BrowseItemLoaded",
367
+ "triggers": "ITEMS_LOADED",
679
368
  "source": {
680
369
  "kind": "trait",
681
- "trait": "PostBrowse"
370
+ "trait": "PostBrowseList"
682
371
  }
683
372
  }
684
- ],
685
- "stateMachine": {
686
- "states": [
687
- {
688
- "name": "closed",
689
- "isInitial": true
690
- },
691
- {
692
- "name": "open"
693
- }
694
- ],
695
- "events": [
696
- {
697
- "key": "INIT",
698
- "name": "Initialize"
699
- },
700
- {
701
- "key": "CREATE",
702
- "name": "Create"
703
- },
704
- {
705
- "key": "CLOSE",
706
- "name": "Close"
707
- },
708
- {
709
- "key": "SAVE",
710
- "name": "Save",
711
- "payloadSchema": [
712
- {
713
- "name": "data",
714
- "type": "object",
715
- "required": true
716
- }
717
- ]
718
- },
373
+ ]
374
+ },
375
+ {
376
+ "ref": "Browse.traits.BrowseItemBrowse",
377
+ "name": "PostBrowseList",
378
+ "linkedEntity": "Post",
379
+ "config": {
380
+ "fields": [
719
381
  {
720
- "key": "PostLoadFailed",
721
- "name": "Post load failed",
722
- "payloadSchema": [
723
- {
724
- "name": "error",
725
- "type": "string"
726
- },
727
- {
728
- "name": "code",
729
- "type": "string"
730
- }
731
- ]
382
+ "variant": "h4",
383
+ "icon": "user",
384
+ "name": "author"
732
385
  },
733
386
  {
734
- "key": "PostLoaded",
735
- "name": "Post loaded",
736
- "payloadSchema": [
737
- {
738
- "name": "data",
739
- "type": "[Post]"
740
- }
741
- ]
387
+ "variant": "body",
388
+ "name": "content"
742
389
  },
743
390
  {
744
- "key": "PostSaveFailed",
745
- "name": "Post save failed",
746
- "payloadSchema": [
747
- {
748
- "name": "error",
749
- "type": "string"
750
- },
751
- {
752
- "name": "code",
753
- "type": "string"
754
- }
755
- ]
391
+ "format": "date",
392
+ "name": "timestamp",
393
+ "variant": "caption"
756
394
  },
757
395
  {
758
- "key": "PostSaved",
759
- "name": "Post saved",
760
- "payloadSchema": [
761
- {
762
- "name": "id",
763
- "type": "string"
764
- }
765
- ]
396
+ "variant": "badge",
397
+ "format": "number",
398
+ "name": "likes"
766
399
  }
767
400
  ],
768
- "transitions": [
401
+ "imageField": "image",
402
+ "cols": 1.0,
403
+ "gap": "md",
404
+ "itemActions": [
769
405
  {
770
- "from": "closed",
771
- "to": "closed",
772
- "event": "INIT",
773
- "effects": [
774
- [
775
- "fetch",
776
- "Post",
777
- {
778
- "emit": {
779
- "success": "PostLoaded",
780
- "failure": "PostLoadFailed"
781
- }
782
- }
783
- ]
784
- ]
785
- },
786
- {
787
- "from": "closed",
788
- "to": "open",
789
- "event": "CREATE",
790
- "effects": [
791
- [
792
- "fetch",
793
- "Post",
794
- {
795
- "emit": {
796
- "success": "PostLoaded",
797
- "failure": "PostLoadFailed"
798
- }
799
- }
800
- ],
801
- [
802
- "render-ui",
803
- "modal",
804
- {
805
- "gap": "md",
806
- "type": "stack",
807
- "children": [
808
- {
809
- "children": [
810
- {
811
- "name": "plus-circle",
812
- "type": "icon"
813
- },
814
- {
815
- "variant": "h3",
816
- "content": "Create Post",
817
- "type": "typography"
818
- }
819
- ],
820
- "gap": "sm",
821
- "type": "stack",
822
- "direction": "horizontal"
823
- },
824
- {
825
- "type": "divider"
826
- },
827
- {
828
- "type": "form-section",
829
- "cancelEvent": "CLOSE",
830
- "submitEvent": "SAVE",
831
- "fields": [
832
- "title",
833
- "content",
834
- "author",
835
- "likes"
836
- ],
837
- "mode": "create"
838
- }
839
- ],
840
- "direction": "vertical"
841
- }
842
- ]
843
- ]
406
+ "label": "View",
407
+ "event": "VIEW",
408
+ "variant": "ghost"
844
409
  },
845
410
  {
846
- "from": "open",
847
- "to": "closed",
848
- "event": "CLOSE",
849
- "effects": [
850
- [
851
- "render-ui",
852
- "modal",
853
- null
854
- ],
855
- [
856
- "render-ui",
857
- "main",
858
- {
859
- "type": "box"
860
- }
861
- ],
862
- [
863
- "notify",
864
- "Cancelled",
865
- "info"
866
- ]
867
- ]
411
+ "event": "EDIT",
412
+ "label": "Edit",
413
+ "variant": "ghost"
868
414
  },
869
415
  {
870
- "from": "open",
871
- "to": "closed",
872
- "event": "SAVE",
873
- "effects": [
874
- [
875
- "persist",
876
- "create",
877
- "Post",
878
- "@payload.data",
879
- {
880
- "emit": {
881
- "success": "PostSaved",
882
- "failure": "PostSaveFailed"
883
- }
884
- }
885
- ],
886
- [
887
- "render-ui",
888
- "modal",
889
- null
890
- ],
891
- [
892
- "render-ui",
893
- "main",
894
- {
895
- "type": "box"
896
- }
897
- ]
898
- ]
416
+ "event": "DELETE",
417
+ "variant": "danger",
418
+ "label": "Delete"
899
419
  }
900
- ]
420
+ ],
421
+ "variant": "card"
901
422
  },
902
- "scope": "collection"
423
+ "listens": [
424
+ {
425
+ "event": "SEARCH",
426
+ "triggers": "REFETCH_QUERY",
427
+ "source": {
428
+ "kind": "trait",
429
+ "trait": "PostSearch"
430
+ }
431
+ },
432
+ {
433
+ "event": "POST_CREATED",
434
+ "triggers": "INIT",
435
+ "source": {
436
+ "kind": "trait",
437
+ "trait": "PostPersistor"
438
+ }
439
+ },
440
+ {
441
+ "event": "POST_UPDATED",
442
+ "triggers": "INIT",
443
+ "source": {
444
+ "kind": "trait",
445
+ "trait": "PostPersistor"
446
+ }
447
+ },
448
+ {
449
+ "event": "POST_DELETED",
450
+ "triggers": "INIT",
451
+ "source": {
452
+ "kind": "trait",
453
+ "trait": "PostPersistor"
454
+ }
455
+ }
456
+ ]
903
457
  },
904
458
  {
905
- "name": "PostView",
906
- "category": "interaction",
459
+ "ref": "Modal.traits.ModalRecordModal",
460
+ "name": "PostCreate",
907
461
  "linkedEntity": "Post",
908
- "emits": [
462
+ "config": {
463
+ "mode": "create",
464
+ "title": "New Post",
465
+ "fields": [
466
+ "author",
467
+ "content",
468
+ "image",
469
+ "tag"
470
+ ],
471
+ "icon": "plus-circle"
472
+ },
473
+ "events": {
474
+ "OPEN": "CREATE"
475
+ },
476
+ "listens": [
909
477
  {
910
- "event": "PostLoaded",
911
- "description": "Fired when Post finishes loading",
912
- "scope": "internal",
913
- "payloadSchema": [
914
- {
915
- "name": "data",
916
- "type": "[Post]"
917
- }
918
- ]
919
- },
478
+ "event": "CREATE",
479
+ "triggers": "CREATE",
480
+ "source": {
481
+ "kind": "trait",
482
+ "trait": "FeedCatalog"
483
+ }
484
+ }
485
+ ]
486
+ },
487
+ {
488
+ "ref": "Modal.traits.ModalRecordModal",
489
+ "name": "PostEdit",
490
+ "linkedEntity": "Post",
491
+ "config": {
492
+ "fields": [
493
+ "author",
494
+ "content",
495
+ "image",
496
+ "tag"
497
+ ],
498
+ "icon": "edit",
499
+ "title": "Edit Post",
500
+ "mode": "edit"
501
+ },
502
+ "events": {
503
+ "OPEN": "EDIT"
504
+ },
505
+ "listens": [
920
506
  {
921
- "event": "PostLoadFailed",
922
- "description": "Fired when Post fails to load",
923
- "scope": "internal",
924
- "payloadSchema": [
925
- {
926
- "name": "error",
927
- "type": "string"
928
- },
929
- {
930
- "name": "code",
931
- "type": "string"
932
- }
933
- ]
507
+ "event": "EDIT",
508
+ "triggers": "EDIT",
509
+ "source": {
510
+ "kind": "trait",
511
+ "trait": "PostBrowseList"
512
+ }
934
513
  }
935
- ],
514
+ ]
515
+ },
516
+ {
517
+ "ref": "Modal.traits.ModalRecordModal",
518
+ "name": "PostView",
519
+ "linkedEntity": "Post",
520
+ "config": {
521
+ "mode": "edit",
522
+ "icon": "eye",
523
+ "fields": [
524
+ "author",
525
+ "content",
526
+ "image",
527
+ "tag",
528
+ "likes"
529
+ ],
530
+ "title": "View Post"
531
+ },
532
+ "events": {
533
+ "OPEN": "VIEW"
534
+ },
936
535
  "listens": [
937
536
  {
938
537
  "event": "VIEW",
939
538
  "triggers": "VIEW",
940
539
  "source": {
941
540
  "kind": "trait",
942
- "trait": "PostBrowse"
541
+ "trait": "PostBrowseList"
542
+ }
543
+ }
544
+ ]
545
+ },
546
+ {
547
+ "ref": "Confirmation.traits.ConfirmActionConfirmation",
548
+ "name": "PostDeleteConfirm",
549
+ "linkedEntity": "Post",
550
+ "config": {
551
+ "title": "Delete Post",
552
+ "icon": "alert-triangle",
553
+ "confirmLabel": "Delete",
554
+ "alertMessage": "This action cannot be undone."
555
+ },
556
+ "events": {
557
+ "REQUEST": "DELETE",
558
+ "CONFIRM": "CONFIRM_DELETE"
559
+ },
560
+ "listens": [
561
+ {
562
+ "event": "DELETE",
563
+ "triggers": "DELETE",
564
+ "source": {
565
+ "kind": "trait",
566
+ "trait": "PostBrowseList"
943
567
  }
944
568
  }
569
+ ]
570
+ },
571
+ {
572
+ "ref": "Storage.traits.ServiceStorageStorage",
573
+ "name": "PostImageUpload",
574
+ "config": {
575
+ "uiTrait": "@trait.PostImageUploadForm",
576
+ "acl": "public",
577
+ "maxSize": 10485760.0,
578
+ "bucket": "social-feed-images",
579
+ "allowedMimeTypes": [
580
+ "image/png",
581
+ "image/jpeg",
582
+ "image/gif",
583
+ "image/webp"
584
+ ]
585
+ }
586
+ },
587
+ {
588
+ "name": "PostImageUploadForm",
589
+ "category": "interaction",
590
+ "emits": [
591
+ {
592
+ "event": "UPLOAD",
593
+ "scope": "external",
594
+ "payloadSchema": [
595
+ {
596
+ "name": "source",
597
+ "type": "string"
598
+ },
599
+ {
600
+ "name": "file",
601
+ "type": "string"
602
+ }
603
+ ]
604
+ }
945
605
  ],
946
606
  "stateMachine": {
947
607
  "states": [
948
608
  {
949
- "name": "closed",
609
+ "name": "ready",
950
610
  "isInitial": true
951
- },
952
- {
953
- "name": "open"
954
611
  }
955
612
  ],
956
613
  "events": [
@@ -959,412 +616,81 @@
959
616
  "name": "Initialize"
960
617
  },
961
618
  {
962
- "key": "VIEW",
963
- "name": "View",
964
- "payloadSchema": [
965
- {
966
- "name": "id",
967
- "type": "string",
968
- "required": true
969
- }
970
- ]
971
- },
972
- {
973
- "key": "CLOSE",
974
- "name": "Close"
975
- },
976
- {
977
- "key": "SAVE",
978
- "name": "Save",
979
- "payloadSchema": [
980
- {
981
- "name": "data",
982
- "type": "object",
983
- "required": true
984
- }
985
- ]
986
- },
987
- {
988
- "key": "PostLoaded",
989
- "name": "Post loaded",
990
- "payloadSchema": [
991
- {
992
- "name": "data",
993
- "type": "[Post]"
994
- }
995
- ]
996
- },
997
- {
998
- "key": "PostLoadFailed",
999
- "name": "Post load failed",
1000
- "payloadSchema": [
1001
- {
1002
- "name": "error",
1003
- "type": "string"
1004
- },
1005
- {
1006
- "name": "code",
1007
- "type": "string"
1008
- }
1009
- ]
619
+ "key": "UPLOAD",
620
+ "name": "Upload"
1010
621
  }
1011
622
  ],
1012
623
  "transitions": [
1013
624
  {
1014
- "from": "closed",
1015
- "to": "closed",
625
+ "from": "ready",
626
+ "to": "ready",
1016
627
  "event": "INIT",
1017
628
  "effects": [
1018
- [
1019
- "set",
1020
- "@entity.author",
1021
- ""
1022
- ],
1023
- [
1024
- "set",
1025
- "@entity.content",
1026
- ""
1027
- ],
1028
- [
1029
- "set",
1030
- "@entity.createdAt",
1031
- ""
1032
- ],
1033
- [
1034
- "set",
1035
- "@entity.likes",
1036
- 0.0
1037
- ],
1038
- [
1039
- "set",
1040
- "@entity.title",
1041
- ""
1042
- ],
1043
- [
1044
- "fetch",
1045
- "Post",
1046
- {
1047
- "emit": {
1048
- "success": "PostLoaded",
1049
- "failure": "PostLoadFailed"
1050
- }
1051
- }
1052
- ]
1053
- ]
1054
- },
1055
- {
1056
- "from": "closed",
1057
- "to": "open",
1058
- "event": "VIEW",
1059
- "effects": [
1060
- [
1061
- "fetch",
1062
- "Post",
1063
- {
1064
- "id": "@payload.id",
1065
- "emit": {
1066
- "failure": "PostLoadFailed",
1067
- "success": "PostLoaded"
1068
- }
1069
- }
1070
- ],
1071
629
  [
1072
630
  "render-ui",
1073
- "modal",
631
+ "main",
1074
632
  {
1075
- "direction": "vertical",
1076
633
  "children": [
1077
634
  {
1078
- "children": [
1079
- {
1080
- "name": "eye",
1081
- "type": "icon"
1082
- },
1083
- {
1084
- "variant": "h3",
1085
- "type": "typography",
1086
- "content": "@entity.title"
1087
- }
1088
- ],
1089
- "align": "center",
1090
- "direction": "horizontal",
1091
- "type": "stack",
1092
- "gap": "sm"
1093
- },
1094
- {
1095
- "type": "divider"
1096
- },
1097
- {
1098
- "gap": "md",
1099
- "children": [
1100
- {
1101
- "variant": "caption",
1102
- "content": "Title",
1103
- "type": "typography"
1104
- },
1105
- {
1106
- "content": "@entity.title",
1107
- "type": "typography",
1108
- "variant": "body"
1109
- }
1110
- ],
1111
- "type": "stack",
1112
- "direction": "horizontal"
1113
- },
1114
- {
1115
- "type": "stack",
1116
- "direction": "horizontal",
1117
- "gap": "md",
1118
- "children": [
1119
- {
1120
- "content": "Content",
1121
- "type": "typography",
1122
- "variant": "caption"
1123
- },
1124
- {
1125
- "variant": "body",
1126
- "content": "@entity.content",
1127
- "type": "typography"
1128
- }
1129
- ]
1130
- },
1131
- {
1132
- "children": [
1133
- {
1134
- "type": "typography",
1135
- "variant": "caption",
1136
- "content": "Author"
1137
- },
1138
- {
1139
- "content": "@entity.author",
1140
- "variant": "body",
1141
- "type": "typography"
1142
- }
1143
- ],
1144
- "type": "stack",
1145
- "direction": "horizontal",
1146
- "gap": "md"
1147
- },
1148
- {
1149
- "direction": "horizontal",
1150
- "children": [
1151
- {
1152
- "content": "Created At",
1153
- "type": "typography",
1154
- "variant": "caption"
1155
- },
1156
- {
1157
- "type": "typography",
1158
- "content": "@entity.createdAt",
1159
- "variant": "body"
1160
- }
1161
- ],
1162
- "gap": "md",
1163
- "type": "stack"
1164
- },
1165
- {
1166
- "children": [
1167
- {
1168
- "type": "typography",
1169
- "variant": "caption",
1170
- "content": "Likes"
1171
- },
1172
- {
1173
- "variant": "body",
1174
- "content": "@entity.likes",
1175
- "type": "typography"
1176
- }
1177
- ],
1178
- "direction": "horizontal",
1179
- "type": "stack",
1180
- "gap": "md"
635
+ "type": "typography",
636
+ "variant": "caption",
637
+ "content": "Attach an image"
1181
638
  },
1182
639
  {
1183
- "type": "divider"
640
+ "inputType": "text",
641
+ "type": "input",
642
+ "placeholder": "Choose image…"
1184
643
  },
1185
644
  {
1186
- "type": "stack",
1187
- "children": [
1188
- {
1189
- "type": "button",
1190
- "action": "CLOSE",
1191
- "variant": "ghost",
1192
- "label": "Close"
1193
- }
1194
- ],
1195
- "direction": "horizontal",
1196
- "justify": "end",
1197
- "gap": "sm"
645
+ "icon": "upload",
646
+ "type": "button",
647
+ "action": "UPLOAD",
648
+ "label": "Upload",
649
+ "variant": "ghost"
1198
650
  }
1199
651
  ],
1200
652
  "type": "stack",
653
+ "direction": "vertical",
1201
654
  "gap": "md"
1202
655
  }
1203
656
  ]
1204
657
  ]
1205
- },
1206
- {
1207
- "from": "open",
1208
- "to": "closed",
1209
- "event": "CLOSE",
1210
- "effects": [
1211
- [
1212
- "render-ui",
1213
- "modal",
1214
- null
1215
- ],
1216
- [
1217
- "render-ui",
1218
- "main",
1219
- {
1220
- "type": "box"
1221
- }
1222
- ],
1223
- [
1224
- "notify",
1225
- "Cancelled",
1226
- "info"
1227
- ]
1228
- ]
1229
- },
1230
- {
1231
- "from": "open",
1232
- "to": "closed",
1233
- "event": "SAVE",
1234
- "effects": [
1235
- [
1236
- "render-ui",
1237
- "modal",
1238
- null
1239
- ],
1240
- [
1241
- "render-ui",
1242
- "main",
1243
- {
1244
- "type": "box"
1245
- }
1246
- ]
1247
- ]
1248
658
  }
1249
659
  ]
1250
660
  },
1251
- "scope": "collection"
1252
- }
1253
- ],
1254
- "pages": [
1255
- {
1256
- "name": "FeedPage",
1257
- "path": "/feed",
1258
- "traits": [
1259
- {
1260
- "ref": "PostAppLayout"
1261
- },
1262
- {
1263
- "ref": "PostBrowse"
1264
- },
1265
- {
1266
- "ref": "PostCreate"
1267
- },
1268
- {
1269
- "ref": "PostView"
1270
- }
1271
- ]
1272
- }
1273
- ]
1274
- },
1275
- {
1276
- "name": "CommentOrbital",
1277
- "entity": {
1278
- "name": "Comment",
1279
- "persistence": "runtime",
1280
- "fields": [
1281
- {
1282
- "name": "id",
1283
- "type": "string",
1284
- "required": true
1285
- },
1286
- {
1287
- "name": "body",
1288
- "type": "string"
1289
- },
1290
- {
1291
- "name": "author",
1292
- "type": "string",
1293
- "default": ""
1294
- },
1295
- {
1296
- "name": "postId",
1297
- "type": "string"
1298
- },
1299
- {
1300
- "name": "createdAt",
1301
- "type": "datetime",
1302
- "default": ""
1303
- }
1304
- ]
1305
- },
1306
- "traits": [
661
+ "scope": "instance"
662
+ },
1307
663
  {
1308
- "name": "CommentBrowse",
1309
- "category": "interaction",
1310
- "linkedEntity": "Comment",
664
+ "name": "PostPersistor",
665
+ "category": "lifecycle",
666
+ "linkedEntity": "Post",
1311
667
  "emits": [
1312
668
  {
1313
- "event": "COMPOSE"
1314
- },
1315
- {
1316
- "event": "VIEW",
669
+ "event": "POST_CREATED",
670
+ "scope": "external",
1317
671
  "payloadSchema": [
1318
672
  {
1319
673
  "name": "id",
1320
- "type": "string",
1321
- "required": true
1322
- },
1323
- {
1324
- "name": "row.id",
1325
- "type": "string",
1326
- "required": true
1327
- },
1328
- {
1329
- "name": "row.body",
1330
- "type": "string"
1331
- },
1332
- {
1333
- "name": "row.author",
1334
- "type": "string"
1335
- },
1336
- {
1337
- "name": "row.postId",
1338
674
  "type": "string"
1339
- },
1340
- {
1341
- "name": "row.createdAt",
1342
- "type": "datetime"
1343
675
  }
1344
676
  ]
1345
677
  },
1346
678
  {
1347
- "event": "CommentLoaded",
1348
- "description": "Fired when Comment finishes loading",
1349
- "scope": "internal",
679
+ "event": "POST_UPDATED",
680
+ "scope": "external",
1350
681
  "payloadSchema": [
1351
682
  {
1352
- "name": "data",
1353
- "type": "[Comment]"
683
+ "name": "id",
684
+ "type": "string"
1354
685
  }
1355
686
  ]
1356
687
  },
1357
688
  {
1358
- "event": "CommentLoadFailed",
1359
- "description": "Fired when Comment fails to load",
1360
- "scope": "internal",
689
+ "event": "POST_DELETED",
690
+ "scope": "external",
1361
691
  "payloadSchema": [
1362
692
  {
1363
- "name": "error",
1364
- "type": "string"
1365
- },
1366
- {
1367
- "name": "code",
693
+ "name": "id",
1368
694
  "type": "string"
1369
695
  }
1370
696
  ]
@@ -1372,27 +698,42 @@
1372
698
  ],
1373
699
  "listens": [
1374
700
  {
1375
- "event": "SEND",
1376
- "triggers": "INIT",
701
+ "event": "SAVE",
702
+ "triggers": "DO_CREATE",
1377
703
  "source": {
1378
704
  "kind": "trait",
1379
- "trait": "CommentCompose"
705
+ "trait": "PostCreate"
1380
706
  }
1381
707
  },
1382
708
  {
1383
- "event": "COMMENT",
1384
- "triggers": "INIT",
709
+ "event": "SAVE",
710
+ "triggers": "DO_UPDATE",
711
+ "source": {
712
+ "kind": "trait",
713
+ "trait": "PostEdit"
714
+ }
715
+ },
716
+ {
717
+ "event": "DO_UPDATE",
718
+ "triggers": "DO_UPDATE",
719
+ "source": {
720
+ "kind": "trait",
721
+ "trait": "PostLikeTracker"
722
+ }
723
+ },
724
+ {
725
+ "event": "CONFIRM_DELETE",
726
+ "triggers": "DO_DELETE",
1385
727
  "source": {
1386
- "kind": "orbital",
1387
- "orbital": "PostOrbital",
1388
- "trait": "PostBrowse"
728
+ "kind": "trait",
729
+ "trait": "PostDeleteConfirm"
1389
730
  }
1390
731
  }
1391
732
  ],
1392
733
  "stateMachine": {
1393
734
  "states": [
1394
735
  {
1395
- "name": "browsing",
736
+ "name": "idle",
1396
737
  "isInitial": true
1397
738
  }
1398
739
  ],
@@ -1402,288 +743,372 @@
1402
743
  "name": "Initialize"
1403
744
  },
1404
745
  {
1405
- "key": "CommentLoaded",
1406
- "name": "Comment loaded",
746
+ "key": "DO_CREATE",
747
+ "name": "Do Create",
1407
748
  "payloadSchema": [
1408
749
  {
1409
750
  "name": "data",
1410
- "type": "[Comment]"
751
+ "type": "object",
752
+ "required": true
1411
753
  }
1412
754
  ]
1413
755
  },
1414
756
  {
1415
- "key": "CommentLoadFailed",
1416
- "name": "Comment load failed",
757
+ "key": "DO_UPDATE",
758
+ "name": "Do Update",
1417
759
  "payloadSchema": [
1418
760
  {
1419
- "name": "error",
1420
- "type": "string"
1421
- },
761
+ "name": "data",
762
+ "type": "object",
763
+ "required": true
764
+ }
765
+ ]
766
+ },
767
+ {
768
+ "key": "DO_DELETE",
769
+ "name": "Do Delete",
770
+ "payloadSchema": [
1422
771
  {
1423
- "name": "code",
772
+ "name": "id",
1424
773
  "type": "string"
1425
774
  }
1426
775
  ]
1427
776
  },
1428
777
  {
1429
- "key": "COMPOSE",
1430
- "name": "Compose"
778
+ "key": "POST_CREATED",
779
+ "name": "Post Created"
780
+ },
781
+ {
782
+ "key": "POST_UPDATED",
783
+ "name": "Post Updated"
1431
784
  },
1432
785
  {
1433
- "key": "VIEW",
1434
- "name": "View"
786
+ "key": "POST_DELETED",
787
+ "name": "Post Deleted"
1435
788
  }
1436
789
  ],
1437
790
  "transitions": [
1438
791
  {
1439
- "from": "browsing",
1440
- "to": "browsing",
1441
- "event": "INIT",
792
+ "from": "idle",
793
+ "to": "idle",
794
+ "event": "INIT"
795
+ },
796
+ {
797
+ "from": "idle",
798
+ "to": "idle",
799
+ "event": "DO_CREATE",
1442
800
  "effects": [
1443
801
  [
1444
- "fetch",
1445
- "Comment",
802
+ "persist",
803
+ "create",
804
+ "Post",
805
+ "@payload.data",
806
+ {
807
+ "emit": {
808
+ "success": "POST_CREATED"
809
+ }
810
+ }
811
+ ]
812
+ ]
813
+ },
814
+ {
815
+ "from": "idle",
816
+ "to": "idle",
817
+ "event": "DO_UPDATE",
818
+ "effects": [
819
+ [
820
+ "persist",
821
+ "update",
822
+ "Post",
823
+ "@payload.data",
824
+ {
825
+ "emit": {
826
+ "success": "POST_UPDATED"
827
+ }
828
+ }
829
+ ]
830
+ ]
831
+ },
832
+ {
833
+ "from": "idle",
834
+ "to": "idle",
835
+ "event": "DO_DELETE",
836
+ "effects": [
837
+ [
838
+ "persist",
839
+ "delete",
840
+ "Post",
841
+ "@payload.id",
1446
842
  {
1447
843
  "emit": {
1448
- "success": "CommentLoaded",
1449
- "failure": "CommentLoadFailed"
844
+ "success": "POST_DELETED"
1450
845
  }
1451
846
  }
847
+ ]
848
+ ]
849
+ }
850
+ ]
851
+ },
852
+ "scope": "instance"
853
+ },
854
+ {
855
+ "name": "PostLikeTracker",
856
+ "category": "interaction",
857
+ "linkedEntity": "Post",
858
+ "emits": [
859
+ {
860
+ "event": "DO_UPDATE",
861
+ "scope": "external",
862
+ "payloadSchema": [
863
+ {
864
+ "name": "data",
865
+ "type": "object",
866
+ "required": true
867
+ }
868
+ ]
869
+ }
870
+ ],
871
+ "stateMachine": {
872
+ "states": [
873
+ {
874
+ "name": "ready",
875
+ "isInitial": true
876
+ }
877
+ ],
878
+ "events": [
879
+ {
880
+ "key": "INIT",
881
+ "name": "Initialize"
882
+ },
883
+ {
884
+ "key": "LIKE",
885
+ "name": "Like",
886
+ "payloadSchema": [
887
+ {
888
+ "name": "id",
889
+ "type": "string"
890
+ },
891
+ {
892
+ "name": "data",
893
+ "type": "object",
894
+ "required": true
895
+ }
896
+ ]
897
+ },
898
+ {
899
+ "key": "DO_UPDATE",
900
+ "name": "Do Update"
901
+ }
902
+ ],
903
+ "transitions": [
904
+ {
905
+ "from": "ready",
906
+ "to": "ready",
907
+ "event": "INIT",
908
+ "effects": [
909
+ [
910
+ "set",
911
+ "@entity.likes",
912
+ 0.0
913
+ ],
914
+ [
915
+ "fetch",
916
+ "Post"
1452
917
  ],
1453
918
  [
1454
919
  "render-ui",
1455
920
  "main",
1456
921
  {
1457
- "align": "center",
1458
922
  "children": [
1459
923
  {
1460
- "type": "spinner"
924
+ "icon": "heart",
925
+ "type": "button",
926
+ "action": "LIKE",
927
+ "variant": "ghost",
928
+ "label": "Like"
1461
929
  },
1462
930
  {
1463
- "color": "muted",
1464
931
  "variant": "caption",
1465
- "content": "Loading…",
932
+ "content": "@entity.likes",
1466
933
  "type": "typography"
1467
934
  }
1468
935
  ],
1469
- "gap": "md",
1470
- "type": "stack",
1471
- "className": "py-12",
1472
- "direction": "vertical"
936
+ "direction": "horizontal",
937
+ "align": "center",
938
+ "gap": "sm",
939
+ "type": "stack"
1473
940
  }
1474
941
  ]
1475
942
  ]
1476
943
  },
1477
944
  {
1478
- "from": "browsing",
1479
- "to": "browsing",
1480
- "event": "CommentLoaded",
945
+ "from": "ready",
946
+ "to": "ready",
947
+ "event": "LIKE",
1481
948
  "effects": [
1482
949
  [
1483
- "render-ui",
1484
- "main",
950
+ "set",
951
+ "@entity.likes",
952
+ "@payload.data.likes"
953
+ ],
954
+ [
955
+ "emit",
956
+ "DO_UPDATE",
1485
957
  {
1486
- "type": "dashboard-layout",
1487
- "appName": "SocialFeed",
1488
- "children": [
1489
- {
1490
- "className": "max-w-5xl mx-auto w-full",
1491
- "direction": "vertical",
1492
- "children": [
1493
- {
1494
- "justify": "between",
1495
- "children": [
1496
- {
1497
- "children": [
1498
- {
1499
- "type": "icon",
1500
- "name": "message-circle"
1501
- },
1502
- {
1503
- "type": "typography",
1504
- "variant": "h2",
1505
- "content": "Messages"
1506
- }
1507
- ],
1508
- "type": "stack",
1509
- "direction": "horizontal",
1510
- "gap": "sm",
1511
- "align": "center"
1512
- },
1513
- {
1514
- "gap": "sm",
1515
- "type": "stack",
1516
- "direction": "horizontal",
1517
- "children": [
1518
- {
1519
- "variant": "primary",
1520
- "label": "Compose",
1521
- "icon": "edit",
1522
- "type": "button",
1523
- "action": "COMPOSE"
1524
- }
1525
- ]
1526
- }
1527
- ],
1528
- "align": "center",
1529
- "direction": "horizontal",
1530
- "gap": "md",
1531
- "type": "stack"
1532
- },
1533
- {
1534
- "type": "divider"
1535
- },
1536
- {
1537
- "gap": "sm",
1538
- "entity": "@payload.data",
1539
- "type": "data-list",
1540
- "itemActions": [
1541
- {
1542
- "variant": "ghost",
1543
- "label": "View",
1544
- "event": "VIEW"
1545
- }
1546
- ],
1547
- "fields": [
1548
- {
1549
- "name": "author",
1550
- "variant": "h4",
1551
- "icon": "message-circle"
1552
- },
1553
- {
1554
- "name": "body",
1555
- "variant": "body"
1556
- },
1557
- {
1558
- "format": "date",
1559
- "variant": "caption",
1560
- "name": "createdAt"
1561
- }
1562
- ],
1563
- "variant": "card"
1564
- }
1565
- ],
1566
- "gap": "lg",
1567
- "type": "stack"
1568
- }
1569
- ],
1570
- "navItems": [
1571
- {
1572
- "href": "/feed",
1573
- "icon": "layout-list",
1574
- "label": "Feed"
1575
- },
1576
- {
1577
- "label": "Messages",
1578
- "href": "/messages",
1579
- "icon": "message-circle"
1580
- }
1581
- ]
958
+ "data": "@payload.data"
1582
959
  }
1583
960
  ]
1584
961
  ]
962
+ }
963
+ ]
964
+ },
965
+ "scope": "instance"
966
+ }
967
+ ],
968
+ "pages": [
969
+ {
970
+ "name": "FeedPage",
971
+ "path": "/feed",
972
+ "traits": [
973
+ {
974
+ "ref": "PostAppLayout"
975
+ },
976
+ {
977
+ "ref": "FeedCatalog"
978
+ },
979
+ {
980
+ "ref": "PostSearch"
981
+ },
982
+ {
983
+ "ref": "PostStats"
984
+ },
985
+ {
986
+ "ref": "PostBrowseList"
987
+ },
988
+ {
989
+ "ref": "PostCreate"
990
+ },
991
+ {
992
+ "ref": "PostEdit"
993
+ },
994
+ {
995
+ "ref": "PostView"
996
+ },
997
+ {
998
+ "ref": "PostDeleteConfirm"
999
+ },
1000
+ {
1001
+ "ref": "PostImageUpload"
1002
+ },
1003
+ {
1004
+ "ref": "PostImageUploadForm"
1005
+ },
1006
+ {
1007
+ "ref": "PostPersistor"
1008
+ },
1009
+ {
1010
+ "ref": "PostLikeTracker"
1011
+ }
1012
+ ]
1013
+ }
1014
+ ]
1015
+ },
1016
+ {
1017
+ "name": "CommentOrbital",
1018
+ "uses": [
1019
+ {
1020
+ "from": "std/behaviors/std-app-layout",
1021
+ "as": "AppShell"
1022
+ },
1023
+ {
1024
+ "from": "std/behaviors/std-modal",
1025
+ "as": "Modal"
1026
+ },
1027
+ {
1028
+ "from": "std/behaviors/std-confirmation",
1029
+ "as": "Confirmation"
1030
+ },
1031
+ {
1032
+ "from": "std/behaviors/std-browse",
1033
+ "as": "Browse"
1034
+ }
1035
+ ],
1036
+ "entity": {
1037
+ "name": "Comment",
1038
+ "collection": "comments",
1039
+ "persistence": "persistent",
1040
+ "fields": [
1041
+ {
1042
+ "name": "id",
1043
+ "type": "string",
1044
+ "required": true
1045
+ },
1046
+ {
1047
+ "name": "postId",
1048
+ "type": "string",
1049
+ "required": true
1050
+ },
1051
+ {
1052
+ "name": "author",
1053
+ "type": "string",
1054
+ "default": ""
1055
+ },
1056
+ {
1057
+ "name": "body",
1058
+ "type": "string",
1059
+ "default": ""
1060
+ },
1061
+ {
1062
+ "name": "createdAt",
1063
+ "type": "datetime",
1064
+ "default": ""
1065
+ },
1066
+ {
1067
+ "name": "pendingId",
1068
+ "type": "string",
1069
+ "default": ""
1070
+ }
1071
+ ]
1072
+ },
1073
+ "traits": [
1074
+ {
1075
+ "ref": "AppShell.traits.AppLayout",
1076
+ "name": "CommentAppLayout",
1077
+ "linkedEntity": "Comment",
1078
+ "config": {
1079
+ "contentTrait": "@trait.CommentDisplay",
1080
+ "appName": "SocialFeed",
1081
+ "notifications": [],
1082
+ "notificationClickEvent": "COMMENT_NOTIFICATIONS_OPEN",
1083
+ "navItems": [
1084
+ {
1085
+ "icon": "rss",
1086
+ "label": "Feed",
1087
+ "href": "/feed"
1585
1088
  },
1586
1089
  {
1587
- "from": "browsing",
1588
- "to": "browsing",
1589
- "event": "CommentLoadFailed",
1590
- "effects": [
1591
- [
1592
- "render-ui",
1593
- "main",
1594
- {
1595
- "gap": "md",
1596
- "type": "stack",
1597
- "className": "py-12",
1598
- "children": [
1599
- {
1600
- "color": "destructive",
1601
- "name": "alert-triangle",
1602
- "type": "icon"
1603
- },
1604
- {
1605
- "variant": "h3",
1606
- "content": "Failed to load comment",
1607
- "type": "typography"
1608
- },
1609
- {
1610
- "content": "@payload.error",
1611
- "variant": "body",
1612
- "type": "typography",
1613
- "color": "muted"
1614
- },
1615
- {
1616
- "variant": "primary",
1617
- "icon": "rotate-ccw",
1618
- "label": "Retry",
1619
- "type": "button",
1620
- "action": "INIT"
1621
- }
1622
- ],
1623
- "direction": "vertical",
1624
- "align": "center"
1625
- }
1626
- ]
1627
- ]
1090
+ "icon": "message-circle",
1091
+ "href": "/comments",
1092
+ "label": "Comments"
1628
1093
  }
1629
- ]
1094
+ ],
1095
+ "searchEvent": "COMMENT_SEARCH"
1630
1096
  },
1631
- "scope": "collection"
1097
+ "events": {
1098
+ "SEARCH": "COMMENT_SEARCH",
1099
+ "NOTIFY_CLICK": "COMMENT_NOTIFICATIONS_OPEN"
1100
+ }
1632
1101
  },
1633
1102
  {
1634
- "name": "CommentCompose",
1103
+ "name": "CommentDisplay",
1635
1104
  "category": "interaction",
1636
- "linkedEntity": "Comment",
1637
1105
  "emits": [
1638
1106
  {
1639
- "event": "SEND"
1640
- },
1641
- {
1642
- "event": "CommentLoadFailed",
1643
- "description": "Fired when Comment fails to load",
1644
- "scope": "internal",
1645
- "payloadSchema": [
1646
- {
1647
- "name": "error",
1648
- "type": "string"
1649
- },
1650
- {
1651
- "name": "code",
1652
- "type": "string"
1653
- }
1654
- ]
1655
- },
1656
- {
1657
- "event": "CommentLoaded",
1658
- "description": "Fired when Comment finishes loading",
1659
- "scope": "internal",
1660
- "payloadSchema": [
1661
- {
1662
- "name": "data",
1663
- "type": "[Comment]"
1664
- }
1665
- ]
1666
- },
1667
- {
1668
- "event": "CommentSaveFailed",
1669
- "scope": "internal",
1670
- "payloadSchema": [
1671
- {
1672
- "name": "error",
1673
- "type": "string"
1674
- },
1675
- {
1676
- "name": "code",
1677
- "type": "string"
1678
- }
1679
- ]
1680
- },
1681
- {
1682
- "event": "CommentSaved",
1683
- "scope": "internal",
1107
+ "event": "CREATE",
1108
+ "scope": "external",
1684
1109
  "payloadSchema": [
1685
1110
  {
1686
- "name": "id",
1111
+ "name": "source",
1687
1112
  "type": "string"
1688
1113
  }
1689
1114
  ]
@@ -1691,22 +1116,27 @@
1691
1116
  ],
1692
1117
  "listens": [
1693
1118
  {
1694
- "event": "COMPOSE",
1695
- "triggers": "COMPOSE",
1119
+ "event": "COMMENT_SEARCH",
1120
+ "triggers": "COMMENT_SEARCH",
1121
+ "source": {
1122
+ "kind": "trait",
1123
+ "trait": "CommentAppLayout"
1124
+ }
1125
+ },
1126
+ {
1127
+ "event": "COMMENT_NOTIFICATIONS_OPEN",
1128
+ "triggers": "COMMENT_NOTIFICATIONS_OPEN",
1696
1129
  "source": {
1697
1130
  "kind": "trait",
1698
- "trait": "CommentBrowse"
1131
+ "trait": "CommentAppLayout"
1699
1132
  }
1700
1133
  }
1701
1134
  ],
1702
1135
  "stateMachine": {
1703
1136
  "states": [
1704
1137
  {
1705
- "name": "closed",
1138
+ "name": "composing",
1706
1139
  "isInitial": true
1707
- },
1708
- {
1709
- "name": "open"
1710
1140
  }
1711
1141
  ],
1712
1142
  "events": [
@@ -1715,224 +1145,354 @@
1715
1145
  "name": "Initialize"
1716
1146
  },
1717
1147
  {
1718
- "key": "COMPOSE",
1719
- "name": "Compose"
1720
- },
1721
- {
1722
- "key": "CLOSE",
1723
- "name": "Close"
1724
- },
1725
- {
1726
- "key": "SEND",
1727
- "name": "Send",
1728
- "payloadSchema": [
1729
- {
1730
- "name": "data",
1731
- "type": "string"
1732
- }
1733
- ]
1734
- },
1735
- {
1736
- "key": "CommentLoadFailed",
1737
- "name": "Comment load failed",
1148
+ "key": "COMMENT_SEARCH",
1149
+ "name": "Comment Search",
1738
1150
  "payloadSchema": [
1739
1151
  {
1740
- "name": "error",
1741
- "type": "string"
1742
- },
1743
- {
1744
- "name": "code",
1152
+ "name": "value",
1745
1153
  "type": "string"
1746
1154
  }
1747
1155
  ]
1748
1156
  },
1749
1157
  {
1750
- "key": "CommentLoaded",
1751
- "name": "Comment loaded",
1752
- "payloadSchema": [
1753
- {
1754
- "name": "data",
1755
- "type": "[Comment]"
1756
- }
1757
- ]
1758
- },
1759
- {
1760
- "key": "CommentSaveFailed",
1761
- "name": "Comment save failed",
1158
+ "key": "COMMENT_NOTIFICATIONS_OPEN",
1159
+ "name": "Comment Notifications Open",
1762
1160
  "payloadSchema": [
1763
1161
  {
1764
- "name": "error",
1765
- "type": "string"
1766
- },
1767
- {
1768
- "name": "code",
1162
+ "name": "id",
1769
1163
  "type": "string"
1770
1164
  }
1771
1165
  ]
1772
1166
  },
1773
1167
  {
1774
- "key": "CommentSaved",
1775
- "name": "Comment saved",
1776
- "payloadSchema": [
1777
- {
1778
- "name": "id",
1779
- "type": "string"
1780
- }
1781
- ]
1168
+ "key": "CREATE",
1169
+ "name": "Create"
1782
1170
  }
1783
1171
  ],
1784
1172
  "transitions": [
1785
1173
  {
1786
- "from": "closed",
1787
- "to": "closed",
1174
+ "from": "composing",
1175
+ "to": "composing",
1788
1176
  "event": "INIT",
1789
- "effects": [
1790
- [
1791
- "fetch",
1792
- "Comment",
1793
- {
1794
- "emit": {
1795
- "failure": "CommentLoadFailed",
1796
- "success": "CommentLoaded"
1797
- }
1798
- }
1799
- ]
1800
- ]
1801
- },
1802
- {
1803
- "from": "closed",
1804
- "to": "open",
1805
- "event": "COMPOSE",
1806
1177
  "effects": [
1807
1178
  [
1808
1179
  "render-ui",
1809
- "modal",
1180
+ "main",
1810
1181
  {
1811
1182
  "direction": "vertical",
1183
+ "className": "max-w-5xl mx-auto w-full",
1812
1184
  "type": "stack",
1813
- "gap": "md",
1185
+ "gap": "lg",
1814
1186
  "children": [
1815
1187
  {
1816
- "direction": "horizontal",
1817
- "type": "stack",
1188
+ "justify": "between",
1189
+ "align": "center",
1190
+ "gap": "md",
1818
1191
  "children": [
1819
1192
  {
1820
- "type": "icon",
1821
- "name": "edit"
1193
+ "type": "stack",
1194
+ "direction": "horizontal",
1195
+ "align": "center",
1196
+ "children": [
1197
+ {
1198
+ "type": "icon",
1199
+ "name": "message-circle"
1200
+ },
1201
+ {
1202
+ "variant": "h2",
1203
+ "type": "typography",
1204
+ "content": "Comments"
1205
+ }
1206
+ ],
1207
+ "gap": "sm"
1822
1208
  },
1823
1209
  {
1824
- "type": "typography",
1825
- "content": "New Comment",
1826
- "variant": "h3"
1210
+ "type": "stack",
1211
+ "children": [
1212
+ {
1213
+ "action": "CREATE",
1214
+ "type": "button",
1215
+ "icon": "edit",
1216
+ "label": "New Comment",
1217
+ "variant": "primary"
1218
+ }
1219
+ ],
1220
+ "direction": "horizontal",
1221
+ "gap": "sm"
1827
1222
  }
1828
1223
  ],
1829
- "gap": "sm"
1224
+ "type": "stack",
1225
+ "direction": "horizontal"
1830
1226
  },
1831
1227
  {
1832
1228
  "type": "divider"
1833
1229
  },
1834
- {
1835
- "mode": "create",
1836
- "fields": [
1837
- "body",
1838
- "author",
1839
- "postId"
1840
- ],
1841
- "type": "form-section",
1842
- "submitEvent": "SEND",
1843
- "cancelEvent": "CLOSE"
1844
- }
1230
+ "@trait.CommentBrowseList"
1845
1231
  ]
1846
1232
  }
1847
1233
  ]
1848
1234
  ]
1849
1235
  },
1850
1236
  {
1851
- "from": "open",
1852
- "to": "closed",
1853
- "event": "CLOSE",
1854
- "effects": [
1855
- [
1856
- "render-ui",
1857
- "modal",
1858
- null
1859
- ],
1860
- [
1861
- "render-ui",
1862
- "main",
1863
- {
1864
- "type": "box"
1865
- }
1866
- ],
1867
- [
1868
- "notify",
1869
- "Cancelled",
1870
- "info"
1871
- ]
1872
- ]
1237
+ "from": "composing",
1238
+ "to": "composing",
1239
+ "event": "COMMENT_SEARCH"
1873
1240
  },
1874
1241
  {
1875
- "from": "open",
1876
- "to": "closed",
1877
- "event": "SEND",
1242
+ "from": "composing",
1243
+ "to": "composing",
1244
+ "event": "COMMENT_NOTIFICATIONS_OPEN",
1878
1245
  "effects": [
1879
- [
1880
- "persist",
1881
- "create",
1882
- "Comment",
1883
- "@payload.data",
1884
- {
1885
- "emit": {
1886
- "success": "CommentSaved",
1887
- "failure": "CommentSaveFailed"
1888
- }
1889
- }
1890
- ],
1891
- [
1892
- "render-ui",
1893
- "modal",
1894
- null
1895
- ],
1896
1246
  [
1897
1247
  "render-ui",
1898
1248
  "main",
1899
1249
  {
1900
- "type": "box"
1250
+ "className": "py-8",
1251
+ "children": [
1252
+ {
1253
+ "name": "bell",
1254
+ "type": "icon"
1255
+ },
1256
+ {
1257
+ "type": "typography",
1258
+ "content": "No notifications",
1259
+ "variant": "h3"
1260
+ },
1261
+ {
1262
+ "color": "muted",
1263
+ "type": "typography",
1264
+ "variant": "caption",
1265
+ "content": "You're all caught up."
1266
+ },
1267
+ {
1268
+ "variant": "ghost",
1269
+ "label": "Back to comments",
1270
+ "type": "button",
1271
+ "action": "INIT"
1272
+ }
1273
+ ],
1274
+ "gap": "md",
1275
+ "direction": "vertical",
1276
+ "type": "stack",
1277
+ "align": "center"
1901
1278
  }
1902
1279
  ]
1903
1280
  ]
1904
1281
  }
1905
- ]
1282
+ ]
1283
+ },
1284
+ "scope": "instance"
1285
+ },
1286
+ {
1287
+ "ref": "Browse.traits.BrowseItemBrowse",
1288
+ "name": "CommentBrowseList",
1289
+ "linkedEntity": "Comment",
1290
+ "config": {
1291
+ "itemActions": [
1292
+ {
1293
+ "event": "VIEW",
1294
+ "label": "View",
1295
+ "variant": "ghost"
1296
+ },
1297
+ {
1298
+ "event": "EDIT",
1299
+ "label": "Edit",
1300
+ "variant": "ghost"
1301
+ },
1302
+ {
1303
+ "event": "DELETE",
1304
+ "label": "Delete",
1305
+ "variant": "danger"
1306
+ }
1307
+ ],
1308
+ "cols": 1.0,
1309
+ "gap": "sm",
1310
+ "fields": [
1311
+ {
1312
+ "variant": "h4",
1313
+ "name": "author",
1314
+ "icon": "user"
1315
+ },
1316
+ {
1317
+ "name": "body",
1318
+ "variant": "body"
1319
+ },
1320
+ {
1321
+ "variant": "caption",
1322
+ "format": "date",
1323
+ "name": "createdAt"
1324
+ }
1325
+ ],
1326
+ "variant": "card"
1327
+ },
1328
+ "listens": [
1329
+ {
1330
+ "event": "COMMENT_CREATED",
1331
+ "triggers": "INIT",
1332
+ "source": {
1333
+ "kind": "trait",
1334
+ "trait": "CommentPersistor"
1335
+ }
1336
+ },
1337
+ {
1338
+ "event": "COMMENT_UPDATED",
1339
+ "triggers": "INIT",
1340
+ "source": {
1341
+ "kind": "trait",
1342
+ "trait": "CommentPersistor"
1343
+ }
1344
+ },
1345
+ {
1346
+ "event": "COMMENT_DELETED",
1347
+ "triggers": "INIT",
1348
+ "source": {
1349
+ "kind": "trait",
1350
+ "trait": "CommentPersistor"
1351
+ }
1352
+ }
1353
+ ]
1354
+ },
1355
+ {
1356
+ "ref": "Modal.traits.ModalRecordModal",
1357
+ "name": "CommentCreate",
1358
+ "linkedEntity": "Comment",
1359
+ "config": {
1360
+ "icon": "plus-circle",
1361
+ "fields": [
1362
+ "postId",
1363
+ "author",
1364
+ "body"
1365
+ ],
1366
+ "mode": "create",
1367
+ "title": "New Comment"
1368
+ },
1369
+ "events": {
1370
+ "OPEN": "CREATE"
1371
+ },
1372
+ "listens": [
1373
+ {
1374
+ "event": "CREATE",
1375
+ "triggers": "CREATE",
1376
+ "source": {
1377
+ "kind": "trait",
1378
+ "trait": "CommentDisplay"
1379
+ }
1380
+ }
1381
+ ]
1382
+ },
1383
+ {
1384
+ "ref": "Modal.traits.ModalRecordModal",
1385
+ "name": "CommentEdit",
1386
+ "linkedEntity": "Comment",
1387
+ "config": {
1388
+ "mode": "edit",
1389
+ "fields": [
1390
+ "postId",
1391
+ "author",
1392
+ "body"
1393
+ ],
1394
+ "icon": "edit",
1395
+ "title": "Edit Comment"
1396
+ },
1397
+ "events": {
1398
+ "OPEN": "EDIT"
1906
1399
  },
1907
- "scope": "collection"
1400
+ "listens": [
1401
+ {
1402
+ "event": "EDIT",
1403
+ "triggers": "EDIT",
1404
+ "source": {
1405
+ "kind": "trait",
1406
+ "trait": "CommentBrowseList"
1407
+ }
1408
+ }
1409
+ ]
1908
1410
  },
1909
1411
  {
1412
+ "ref": "Modal.traits.ModalRecordModal",
1910
1413
  "name": "CommentView",
1911
- "category": "interaction",
1414
+ "linkedEntity": "Comment",
1415
+ "config": {
1416
+ "title": "View Comment",
1417
+ "mode": "edit",
1418
+ "fields": [
1419
+ "postId",
1420
+ "author",
1421
+ "body",
1422
+ "createdAt"
1423
+ ],
1424
+ "icon": "eye"
1425
+ },
1426
+ "events": {
1427
+ "OPEN": "VIEW"
1428
+ },
1429
+ "listens": [
1430
+ {
1431
+ "event": "VIEW",
1432
+ "triggers": "VIEW",
1433
+ "source": {
1434
+ "kind": "trait",
1435
+ "trait": "CommentBrowseList"
1436
+ }
1437
+ }
1438
+ ]
1439
+ },
1440
+ {
1441
+ "ref": "Confirmation.traits.ConfirmActionConfirmation",
1442
+ "name": "CommentDeleteConfirm",
1443
+ "linkedEntity": "Comment",
1444
+ "config": {
1445
+ "alertMessage": "This action cannot be undone.",
1446
+ "confirmLabel": "Delete",
1447
+ "title": "Delete Comment",
1448
+ "icon": "alert-triangle"
1449
+ },
1450
+ "events": {
1451
+ "CONFIRM": "CONFIRM_DELETE",
1452
+ "REQUEST": "DELETE"
1453
+ },
1454
+ "listens": [
1455
+ {
1456
+ "event": "DELETE",
1457
+ "triggers": "DELETE",
1458
+ "source": {
1459
+ "kind": "trait",
1460
+ "trait": "CommentBrowseList"
1461
+ }
1462
+ }
1463
+ ]
1464
+ },
1465
+ {
1466
+ "name": "CommentPersistor",
1467
+ "category": "lifecycle",
1912
1468
  "linkedEntity": "Comment",
1913
1469
  "emits": [
1914
1470
  {
1915
- "event": "CommentLoaded",
1916
- "description": "Fired when Comment finishes loading",
1917
- "scope": "internal",
1471
+ "event": "COMMENT_CREATED",
1472
+ "scope": "external",
1918
1473
  "payloadSchema": [
1919
1474
  {
1920
- "name": "data",
1921
- "type": "[Comment]"
1475
+ "name": "id",
1476
+ "type": "string"
1922
1477
  }
1923
1478
  ]
1924
1479
  },
1925
1480
  {
1926
- "event": "CommentLoadFailed",
1927
- "description": "Fired when Comment fails to load",
1928
- "scope": "internal",
1481
+ "event": "COMMENT_UPDATED",
1482
+ "scope": "external",
1929
1483
  "payloadSchema": [
1930
1484
  {
1931
- "name": "error",
1485
+ "name": "id",
1932
1486
  "type": "string"
1933
- },
1487
+ }
1488
+ ]
1489
+ },
1490
+ {
1491
+ "event": "COMMENT_DELETED",
1492
+ "scope": "external",
1493
+ "payloadSchema": [
1934
1494
  {
1935
- "name": "code",
1495
+ "name": "id",
1936
1496
  "type": "string"
1937
1497
  }
1938
1498
  ]
@@ -1940,22 +1500,35 @@
1940
1500
  ],
1941
1501
  "listens": [
1942
1502
  {
1943
- "event": "VIEW",
1944
- "triggers": "VIEW",
1503
+ "event": "SAVE",
1504
+ "triggers": "DO_CREATE",
1505
+ "source": {
1506
+ "kind": "trait",
1507
+ "trait": "CommentCreate"
1508
+ }
1509
+ },
1510
+ {
1511
+ "event": "SAVE",
1512
+ "triggers": "DO_UPDATE",
1513
+ "source": {
1514
+ "kind": "trait",
1515
+ "trait": "CommentEdit"
1516
+ }
1517
+ },
1518
+ {
1519
+ "event": "CONFIRM_DELETE",
1520
+ "triggers": "DO_DELETE",
1945
1521
  "source": {
1946
1522
  "kind": "trait",
1947
- "trait": "CommentBrowse"
1523
+ "trait": "CommentDeleteConfirm"
1948
1524
  }
1949
1525
  }
1950
1526
  ],
1951
1527
  "stateMachine": {
1952
1528
  "states": [
1953
1529
  {
1954
- "name": "closed",
1530
+ "name": "idle",
1955
1531
  "isInitial": true
1956
- },
1957
- {
1958
- "name": "open"
1959
1532
  }
1960
1533
  ],
1961
1534
  "events": [
@@ -1964,281 +1537,143 @@
1964
1537
  "name": "Initialize"
1965
1538
  },
1966
1539
  {
1967
- "key": "VIEW",
1968
- "name": "View",
1540
+ "key": "DO_CREATE",
1541
+ "name": "Do Create",
1969
1542
  "payloadSchema": [
1970
1543
  {
1971
- "name": "id",
1972
- "type": "string"
1544
+ "name": "data",
1545
+ "type": "object",
1546
+ "required": true
1973
1547
  }
1974
1548
  ]
1975
1549
  },
1976
1550
  {
1977
- "key": "CLOSE",
1978
- "name": "Close"
1979
- },
1980
- {
1981
- "key": "SAVE",
1982
- "name": "Save"
1983
- },
1984
- {
1985
- "key": "CommentLoaded",
1986
- "name": "Comment loaded",
1551
+ "key": "DO_UPDATE",
1552
+ "name": "Do Update",
1987
1553
  "payloadSchema": [
1988
1554
  {
1989
1555
  "name": "data",
1990
- "type": "[Comment]"
1556
+ "type": "object",
1557
+ "required": true
1991
1558
  }
1992
1559
  ]
1993
1560
  },
1994
1561
  {
1995
- "key": "CommentLoadFailed",
1996
- "name": "Comment load failed",
1562
+ "key": "DO_DELETE",
1563
+ "name": "Do Delete",
1997
1564
  "payloadSchema": [
1998
1565
  {
1999
- "name": "error",
2000
- "type": "string"
2001
- },
2002
- {
2003
- "name": "code",
1566
+ "name": "id",
2004
1567
  "type": "string"
2005
1568
  }
2006
1569
  ]
1570
+ },
1571
+ {
1572
+ "key": "COMMENT_CREATED",
1573
+ "name": "Comment Created"
1574
+ },
1575
+ {
1576
+ "key": "COMMENT_UPDATED",
1577
+ "name": "Comment Updated"
1578
+ },
1579
+ {
1580
+ "key": "COMMENT_DELETED",
1581
+ "name": "Comment Deleted"
2007
1582
  }
2008
1583
  ],
2009
1584
  "transitions": [
2010
1585
  {
2011
- "from": "closed",
2012
- "to": "closed",
2013
- "event": "INIT",
1586
+ "from": "idle",
1587
+ "to": "idle",
1588
+ "event": "INIT"
1589
+ },
1590
+ {
1591
+ "from": "idle",
1592
+ "to": "idle",
1593
+ "event": "DO_CREATE",
2014
1594
  "effects": [
2015
1595
  [
2016
- "set",
2017
- "@entity.author",
2018
- ""
2019
- ],
2020
- [
2021
- "set",
2022
- "@entity.body",
2023
- ""
2024
- ],
2025
- [
2026
- "set",
2027
- "@entity.createdAt",
2028
- ""
2029
- ],
2030
- [
2031
- "set",
2032
- "@entity.postId",
2033
- ""
2034
- ],
2035
- [
2036
- "fetch",
1596
+ "persist",
1597
+ "create",
2037
1598
  "Comment",
1599
+ "@payload.data",
2038
1600
  {
2039
1601
  "emit": {
2040
- "success": "CommentLoaded",
2041
- "failure": "CommentLoadFailed"
1602
+ "success": "COMMENT_CREATED"
2042
1603
  }
2043
1604
  }
2044
1605
  ]
2045
1606
  ]
2046
1607
  },
2047
1608
  {
2048
- "from": "closed",
2049
- "to": "open",
2050
- "event": "VIEW",
1609
+ "from": "idle",
1610
+ "to": "idle",
1611
+ "event": "DO_UPDATE",
2051
1612
  "effects": [
2052
1613
  [
2053
- "fetch",
1614
+ "persist",
1615
+ "update",
2054
1616
  "Comment",
1617
+ "@payload.data",
2055
1618
  {
2056
- "id": "@payload.id",
2057
1619
  "emit": {
2058
- "success": "CommentLoaded",
2059
- "failure": "CommentLoadFailed"
1620
+ "success": "COMMENT_UPDATED"
2060
1621
  }
2061
1622
  }
2062
- ],
2063
- [
2064
- "render-ui",
2065
- "modal",
2066
- {
2067
- "type": "stack",
2068
- "gap": "md",
2069
- "children": [
2070
- {
2071
- "direction": "horizontal",
2072
- "gap": "sm",
2073
- "type": "stack",
2074
- "align": "center",
2075
- "children": [
2076
- {
2077
- "name": "eye",
2078
- "type": "icon"
2079
- },
2080
- {
2081
- "type": "typography",
2082
- "variant": "h3",
2083
- "content": "@entity.body"
2084
- }
2085
- ]
2086
- },
2087
- {
2088
- "type": "divider"
2089
- },
2090
- {
2091
- "type": "stack",
2092
- "direction": "horizontal",
2093
- "gap": "md",
2094
- "children": [
2095
- {
2096
- "variant": "caption",
2097
- "content": "Body",
2098
- "type": "typography"
2099
- },
2100
- {
2101
- "type": "typography",
2102
- "content": "@entity.body",
2103
- "variant": "body"
2104
- }
2105
- ]
2106
- },
2107
- {
2108
- "type": "stack",
2109
- "gap": "md",
2110
- "direction": "horizontal",
2111
- "children": [
2112
- {
2113
- "content": "Author",
2114
- "type": "typography",
2115
- "variant": "caption"
2116
- },
2117
- {
2118
- "variant": "body",
2119
- "content": "@entity.author",
2120
- "type": "typography"
2121
- }
2122
- ]
2123
- },
2124
- {
2125
- "gap": "md",
2126
- "children": [
2127
- {
2128
- "variant": "caption",
2129
- "type": "typography",
2130
- "content": "Post ID"
2131
- },
2132
- {
2133
- "content": "@entity.postId",
2134
- "type": "typography",
2135
- "variant": "body"
2136
- }
2137
- ],
2138
- "direction": "horizontal",
2139
- "type": "stack"
2140
- },
2141
- {
2142
- "children": [
2143
- {
2144
- "content": "Created At",
2145
- "type": "typography",
2146
- "variant": "caption"
2147
- },
2148
- {
2149
- "variant": "body",
2150
- "content": "@entity.createdAt",
2151
- "type": "typography"
2152
- }
2153
- ],
2154
- "direction": "horizontal",
2155
- "type": "stack",
2156
- "gap": "md"
2157
- },
2158
- {
2159
- "type": "divider"
2160
- },
2161
- {
2162
- "direction": "horizontal",
2163
- "type": "stack",
2164
- "justify": "end",
2165
- "gap": "sm",
2166
- "children": [
2167
- {
2168
- "variant": "ghost",
2169
- "type": "button",
2170
- "label": "Close",
2171
- "action": "CLOSE"
2172
- }
2173
- ]
2174
- }
2175
- ],
2176
- "direction": "vertical"
2177
- }
2178
- ]
2179
- ]
2180
- },
2181
- {
2182
- "from": "open",
2183
- "to": "closed",
2184
- "event": "CLOSE",
2185
- "effects": [
2186
- [
2187
- "render-ui",
2188
- "modal",
2189
- null
2190
- ],
2191
- [
2192
- "render-ui",
2193
- "main",
2194
- {
2195
- "type": "box"
2196
- }
2197
- ],
2198
- [
2199
- "notify",
2200
- "Cancelled",
2201
- "info"
2202
1623
  ]
2203
1624
  ]
2204
1625
  },
2205
1626
  {
2206
- "from": "open",
2207
- "to": "closed",
2208
- "event": "SAVE",
1627
+ "from": "idle",
1628
+ "to": "idle",
1629
+ "event": "DO_DELETE",
2209
1630
  "effects": [
2210
1631
  [
2211
- "render-ui",
2212
- "modal",
2213
- null
2214
- ],
2215
- [
2216
- "render-ui",
2217
- "main",
1632
+ "persist",
1633
+ "delete",
1634
+ "Comment",
1635
+ "@payload.id",
2218
1636
  {
2219
- "type": "box"
1637
+ "emit": {
1638
+ "success": "COMMENT_DELETED"
1639
+ }
2220
1640
  }
2221
1641
  ]
2222
1642
  ]
2223
1643
  }
2224
1644
  ]
2225
1645
  },
2226
- "scope": "collection"
1646
+ "scope": "instance"
2227
1647
  }
2228
1648
  ],
2229
1649
  "pages": [
2230
1650
  {
2231
- "name": "Messages",
2232
- "path": "/messages",
1651
+ "name": "Comments",
1652
+ "path": "/comments",
2233
1653
  "traits": [
2234
1654
  {
2235
- "ref": "CommentBrowse"
1655
+ "ref": "CommentAppLayout"
1656
+ },
1657
+ {
1658
+ "ref": "CommentDisplay"
2236
1659
  },
2237
1660
  {
2238
- "ref": "CommentCompose"
1661
+ "ref": "CommentBrowseList"
1662
+ },
1663
+ {
1664
+ "ref": "CommentCreate"
1665
+ },
1666
+ {
1667
+ "ref": "CommentEdit"
2239
1668
  },
2240
1669
  {
2241
1670
  "ref": "CommentView"
1671
+ },
1672
+ {
1673
+ "ref": "CommentDeleteConfirm"
1674
+ },
1675
+ {
1676
+ "ref": "CommentPersistor"
2242
1677
  }
2243
1678
  ]
2244
1679
  }