makersclaw 0.7.0 → 0.8.1
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/README.md +17 -4
- package/package.json +1 -1
- package/r/activity-log.json +52 -0
- package/r/agent-changes.json +51 -0
- package/r/agent-chat.json +53 -0
- package/r/agent-column.json +85 -0
- package/r/agent-dock.json +57 -0
- package/r/agent-kit.json +49 -0
- package/r/agent-marks.json +49 -0
- package/r/agent-pane.json +93 -0
- package/r/ai-action.json +56 -0
- package/r/annotate.json +4 -4
- package/r/approval-request.json +2 -2
- package/r/approval.json +54 -0
- package/r/ask-bar.json +50 -0
- package/r/audio-player.json +2 -2
- package/r/auth-form.json +2 -2
- package/r/automation-editor.json +66 -0
- package/r/automation-list.json +57 -0
- package/r/automation-model.json +118 -0
- package/r/automations-screen.json +71 -0
- package/r/board.json +2 -2
- package/r/calendar-view.json +3 -3
- package/r/cart.json +2 -2
- package/r/chart.json +5 -5
- package/r/chat-pane.json +84 -0
- package/r/chat.json +3 -3
- package/r/code-editor.json +2 -2
- package/r/comment-box.json +3 -3
- package/r/connect-card.json +51 -0
- package/r/contact-section.json +2 -2
- package/r/core.json +18 -6
- package/r/cost.json +51 -0
- package/r/csv-import.json +3 -3
- package/r/data-picker.json +60 -0
- package/r/data-table.json +2 -2
- package/r/diagram.json +2 -2
- package/r/doc-editor.json +2 -2
- package/r/doc-page.json +3 -3
- package/r/email-render.json +2 -2
- package/r/faq.json +2 -2
- package/r/file-upload.json +2 -2
- package/r/first-run.json +63 -0
- package/r/fix-note.json +57 -0
- package/r/flow-canvas.json +3 -3
- package/r/flow-editor.json +79 -0
- package/r/footer.json +3 -3
- package/r/gantt.json +3 -3
- package/r/job-panel.json +2 -2
- package/r/json-editor.json +3 -3
- package/r/library-shelf.json +56 -0
- package/r/map.json +2 -2
- package/r/margin-notes.json +67 -0
- package/r/menubar.json +2 -2
- package/r/mind-map.json +4 -4
- package/r/navigation-menu.json +2 -2
- package/r/needs-you.json +55 -0
- package/r/order-detail.json +2 -2
- package/r/org-chart.json +4 -4
- package/r/pace-bar.json +69 -0
- package/r/page-builder.json +3 -3
- package/r/payment-methods.json +2 -2
- package/r/pdf-document.json +2 -2
- package/r/pdf-viewer.json +3 -3
- package/r/product-detail.json +2 -2
- package/r/product-grid.json +3 -3
- package/r/record-form.json +2 -2
- package/r/record-grid.json +52 -0
- package/r/record-notes.json +4 -4
- package/r/registry.json +4089 -1510
- package/r/run-history.json +52 -0
- package/r/run-view.json +80 -0
- package/r/schedule-card.json +54 -0
- package/r/schedule-engine.json +79 -0
- package/r/schedule-gantt.json +83 -0
- package/r/schedule-ruler.json +64 -0
- package/r/search-dialog.json +2 -2
- package/r/settings-list.json +2 -2
- package/r/setup-checklist.json +2 -2
- package/r/share-dialog.json +2 -2
- package/r/sidebar.json +3 -3
- package/r/signature-pad.json +2 -2
- package/r/sketch-canvas.json +3 -3
- package/r/source-receipt.json +52 -0
- package/r/spreadsheet.json +3 -3
- package/r/stat-cards.json +3 -3
- package/r/step-picker.json +53 -0
- package/r/step-settings.json +72 -0
- package/r/suggestion.json +58 -0
- package/r/sum-bar.json +64 -0
- package/r/task-list.json +3 -3
- package/r/task-model.json +2 -2
- package/r/testimonials.json +2 -2
- package/r/tier-map.json +67 -0
- package/r/time-grid.json +73 -0
- package/r/time-strip.json +64 -0
- package/r/top-bar.json +66 -0
- package/r/transaction-list.json +2 -2
- package/r/trigger-picker.json +61 -0
- package/r/whiteboard.json +4 -4
- package/r/workflow-view.json +55 -0
- package/registry/blocks/activity-log/README.md +112 -0
- package/registry/blocks/activity-log/activity-log.jsx +351 -0
- package/registry/blocks/activity-log/block.json +33 -0
- package/registry/blocks/activity-log/demo.jsx +48 -0
- package/registry/blocks/activity-log/index.js +4 -0
- package/registry/blocks/agent-changes/README.md +94 -0
- package/registry/blocks/agent-changes/agent-changes.jsx +118 -0
- package/registry/blocks/agent-changes/block.json +28 -0
- package/registry/blocks/agent-changes/demo.jsx +39 -0
- package/registry/blocks/agent-changes/index.js +3 -0
- package/registry/blocks/agent-chat/README.md +145 -0
- package/registry/blocks/agent-chat/agent-chat.jsx +415 -0
- package/registry/blocks/agent-chat/block.json +30 -0
- package/registry/blocks/agent-chat/demo.jsx +165 -0
- package/registry/blocks/agent-chat/index.js +3 -0
- package/registry/blocks/agent-column/README.md +197 -0
- package/registry/blocks/agent-column/agent-column.jsx +492 -0
- package/registry/blocks/agent-column/block.json +67 -0
- package/registry/blocks/agent-column/column-picker.jsx +163 -0
- package/registry/blocks/agent-column/demo.jsx +50 -0
- package/registry/blocks/agent-column/index.js +7 -0
- package/registry/blocks/agent-column/model.js +164 -0
- package/registry/blocks/agent-column/receipt.jsx +483 -0
- package/registry/blocks/agent-column/spreadsheet-type.jsx +24 -0
- package/registry/blocks/agent-dock/README.md +210 -0
- package/registry/blocks/agent-dock/agent-dock.jsx +356 -0
- package/registry/blocks/agent-dock/block.json +47 -0
- package/registry/blocks/agent-dock/demo.jsx +153 -0
- package/registry/blocks/agent-dock/dock-model.js +118 -0
- package/registry/blocks/agent-dock/index.js +5 -0
- package/registry/blocks/agent-kit/README.md +73 -0
- package/registry/blocks/agent-kit/agent-kit.jsx +86 -0
- package/registry/blocks/agent-kit/block.json +10 -0
- package/registry/blocks/agent-kit/demo.jsx +35 -0
- package/registry/blocks/agent-kit/index.js +3 -0
- package/registry/blocks/agent-marks/README.md +80 -0
- package/registry/blocks/agent-marks/agent-marks.jsx +133 -0
- package/registry/blocks/agent-marks/block.json +27 -0
- package/registry/blocks/agent-marks/demo.jsx +49 -0
- package/registry/blocks/agent-marks/index.js +3 -0
- package/registry/blocks/agent-pane/README.md +225 -0
- package/registry/blocks/agent-pane/agent-pane.jsx +244 -0
- package/registry/blocks/agent-pane/block.json +41 -0
- package/registry/blocks/agent-pane/composer.jsx +6 -0
- package/registry/blocks/agent-pane/demo.jsx +233 -0
- package/registry/blocks/agent-pane/dock-context.js +10 -0
- package/registry/blocks/agent-pane/index.js +4 -0
- package/registry/blocks/agent-pane/prose.jsx +84 -0
- package/registry/blocks/agent-pane/questions.jsx +134 -0
- package/registry/blocks/agent-pane/transcript.jsx +268 -0
- package/registry/blocks/agent-pane/work.jsx +368 -0
- package/registry/blocks/ai-action/README.md +94 -0
- package/registry/blocks/ai-action/ai-action.jsx +188 -0
- package/registry/blocks/ai-action/block.json +34 -0
- package/registry/blocks/ai-action/demo.jsx +93 -0
- package/registry/blocks/ai-action/index.js +3 -0
- package/registry/blocks/annotate/README.md +14 -11
- package/registry/blocks/approval/README.md +145 -0
- package/registry/blocks/approval/approval.jsx +163 -0
- package/registry/blocks/approval/block.json +31 -0
- package/registry/blocks/approval/demo.jsx +121 -0
- package/registry/blocks/approval/index.js +3 -0
- package/registry/blocks/ask-bar/README.md +105 -0
- package/registry/blocks/ask-bar/ask-bar.jsx +166 -0
- package/registry/blocks/ask-bar/block.json +26 -0
- package/registry/blocks/ask-bar/demo.jsx +78 -0
- package/registry/blocks/ask-bar/index.js +3 -0
- package/registry/blocks/automation-editor/README.md +291 -0
- package/registry/blocks/automation-editor/automation-editor.jsx +656 -0
- package/registry/blocks/automation-editor/block.json +39 -0
- package/registry/blocks/automation-editor/demo.jsx +284 -0
- package/registry/blocks/automation-editor/index.js +4 -0
- package/registry/blocks/automation-editor/run-inputs.jsx +82 -0
- package/registry/blocks/automation-list/README.md +129 -0
- package/registry/blocks/automation-list/automation-list.jsx +476 -0
- package/registry/blocks/automation-list/block.json +35 -0
- package/registry/blocks/automation-list/demo.jsx +67 -0
- package/registry/blocks/automation-list/index.js +3 -0
- package/registry/blocks/automation-model/README.md +109 -0
- package/registry/blocks/automation-model/block.json +135 -0
- package/registry/blocks/automation-model/catalog.js +256 -0
- package/registry/blocks/automation-model/check.js +161 -0
- package/registry/blocks/automation-model/demo.jsx +42 -0
- package/registry/blocks/automation-model/edit.js +262 -0
- package/registry/blocks/automation-model/fixes.js +287 -0
- package/registry/blocks/automation-model/glyph.jsx +13 -0
- package/registry/blocks/automation-model/graph.js +410 -0
- package/registry/blocks/automation-model/index.js +33 -0
- package/registry/blocks/automation-model/overlay.js +175 -0
- package/registry/blocks/automation-model/parts.jsx +94 -0
- package/registry/blocks/automation-model/schedule.js +53 -0
- package/registry/blocks/automation-model/templates.js +128 -0
- package/registry/blocks/automation-model/values.js +29 -0
- package/registry/blocks/automation-model/words.js +439 -0
- package/registry/blocks/automations-screen/README.md +207 -0
- package/registry/blocks/automations-screen/automations-screen.jsx +452 -0
- package/registry/blocks/automations-screen/block.json +47 -0
- package/registry/blocks/automations-screen/demo.jsx +364 -0
- package/registry/blocks/automations-screen/index.js +4 -0
- package/registry/blocks/automations-screen/screen-model.js +129 -0
- package/registry/blocks/chart/cartesian.jsx +1 -1
- package/registry/blocks/chart/core.jsx +33 -23
- package/registry/blocks/chart/pie.jsx +1 -1
- package/registry/blocks/chat/README.md +4 -1
- package/registry/blocks/chat/demo.jsx +2 -2
- package/registry/blocks/chat-pane/README.md +143 -0
- package/registry/blocks/chat-pane/block.json +48 -0
- package/registry/blocks/chat-pane/chat-attach.js +166 -0
- package/registry/blocks/chat-pane/chat-composer.jsx +195 -0
- package/registry/blocks/chat-pane/chat-context.js +17 -0
- package/registry/blocks/chat-pane/chat-model.js +43 -0
- package/registry/blocks/chat-pane/chat-pane.jsx +398 -0
- package/registry/blocks/chat-pane/chats-list.jsx +52 -0
- package/registry/blocks/chat-pane/demo.jsx +103 -0
- package/registry/blocks/chat-pane/index.js +9 -0
- package/registry/blocks/connect-card/README.md +99 -0
- package/registry/blocks/connect-card/block.json +10 -0
- package/registry/blocks/connect-card/connect-card.jsx +103 -0
- package/registry/blocks/connect-card/demo.jsx +49 -0
- package/registry/blocks/connect-card/index.js +3 -0
- package/registry/blocks/cost/README.md +115 -0
- package/registry/blocks/cost/block.json +10 -0
- package/registry/blocks/cost/cost.jsx +176 -0
- package/registry/blocks/cost/demo.jsx +66 -0
- package/registry/blocks/cost/index.js +3 -0
- package/registry/blocks/data-picker/README.md +81 -0
- package/registry/blocks/data-picker/block.json +38 -0
- package/registry/blocks/data-picker/data-picker.jsx +210 -0
- package/registry/blocks/data-picker/demo.jsx +34 -0
- package/registry/blocks/data-picker/fields.js +89 -0
- package/registry/blocks/data-picker/index.js +4 -0
- package/registry/blocks/data-table/demo.jsx +1 -1
- package/registry/blocks/first-run/README.md +118 -0
- package/registry/blocks/first-run/block.json +11 -0
- package/registry/blocks/first-run/demo.jsx +88 -0
- package/registry/blocks/first-run/first-run-model.js +51 -0
- package/registry/blocks/first-run/first-run.jsx +156 -0
- package/registry/blocks/first-run/index.js +5 -0
- package/registry/blocks/first-run/probe-rules.js +26 -0
- package/registry/blocks/fix-note/README.md +79 -0
- package/registry/blocks/fix-note/block.json +35 -0
- package/registry/blocks/fix-note/demo.jsx +30 -0
- package/registry/blocks/fix-note/fix-note.jsx +235 -0
- package/registry/blocks/fix-note/index.js +3 -0
- package/registry/blocks/flow-canvas/README.md +15 -8
- package/registry/blocks/flow-editor/README.md +108 -0
- package/registry/blocks/flow-editor/block.json +44 -0
- package/registry/blocks/flow-editor/demo.jsx +115 -0
- package/registry/blocks/flow-editor/flow-canvas.jsx +568 -0
- package/registry/blocks/flow-editor/flow-editor.jsx +154 -0
- package/registry/blocks/flow-editor/index.js +6 -0
- package/registry/blocks/flow-editor/minimap.jsx +78 -0
- package/registry/blocks/flow-editor/outline.jsx +134 -0
- package/registry/blocks/footer/README.md +3 -2
- package/registry/blocks/library-shelf/README.md +117 -0
- package/registry/blocks/library-shelf/block.json +28 -0
- package/registry/blocks/library-shelf/demo.jsx +68 -0
- package/registry/blocks/library-shelf/index.js +3 -0
- package/registry/blocks/library-shelf/library-shelf.jsx +211 -0
- package/registry/blocks/library-shelf/probe-rules.js +15 -0
- package/registry/blocks/margin-notes/README.md +222 -0
- package/registry/blocks/margin-notes/block.json +10 -0
- package/registry/blocks/margin-notes/demo.jsx +144 -0
- package/registry/blocks/margin-notes/index.js +20 -0
- package/registry/blocks/margin-notes/margin-model.js +224 -0
- package/registry/blocks/margin-notes/margin-notes.jsx +465 -0
- package/registry/blocks/mind-map/README.md +4 -2
- package/registry/blocks/needs-you/README.md +177 -0
- package/registry/blocks/needs-you/block.json +34 -0
- package/registry/blocks/needs-you/demo.jsx +143 -0
- package/registry/blocks/needs-you/index.js +3 -0
- package/registry/blocks/needs-you/needs-you.jsx +441 -0
- package/registry/blocks/org-chart/README.md +4 -2
- package/registry/blocks/pace-bar/README.md +230 -0
- package/registry/blocks/pace-bar/block.json +10 -0
- package/registry/blocks/pace-bar/demo.jsx +255 -0
- package/registry/blocks/pace-bar/index.js +22 -0
- package/registry/blocks/pace-bar/pace-bar.jsx +461 -0
- package/registry/blocks/pace-bar/pace-model.js +288 -0
- package/registry/blocks/page-builder/README.md +1 -1
- package/registry/blocks/page-builder/demo.jsx +3 -3
- package/registry/blocks/pdf-viewer/README.md +4 -1
- package/registry/blocks/record-grid/README.md +100 -0
- package/registry/blocks/record-grid/block.json +28 -0
- package/registry/blocks/record-grid/demo.jsx +43 -0
- package/registry/blocks/record-grid/index.js +3 -0
- package/registry/blocks/record-grid/record-grid.jsx +251 -0
- package/registry/blocks/run-history/README.md +138 -0
- package/registry/blocks/run-history/block.json +10 -0
- package/registry/blocks/run-history/demo.jsx +74 -0
- package/registry/blocks/run-history/index.js +3 -0
- package/registry/blocks/run-history/run-history.jsx +218 -0
- package/registry/blocks/run-view/README.md +174 -0
- package/registry/blocks/run-view/block.json +50 -0
- package/registry/blocks/run-view/demo.jsx +286 -0
- package/registry/blocks/run-view/index.js +5 -0
- package/registry/blocks/run-view/run-controls.jsx +266 -0
- package/registry/blocks/run-view/run-view.jsx +236 -0
- package/registry/blocks/run-view/runs-list.jsx +99 -0
- package/registry/blocks/schedule-card/README.md +121 -0
- package/registry/blocks/schedule-card/block.json +10 -0
- package/registry/blocks/schedule-card/demo.jsx +82 -0
- package/registry/blocks/schedule-card/index.js +3 -0
- package/registry/blocks/schedule-card/schedule-card.jsx +136 -0
- package/registry/blocks/schedule-engine/README.md +137 -0
- package/registry/blocks/schedule-engine/block.json +10 -0
- package/registry/blocks/schedule-engine/demo.jsx +82 -0
- package/registry/blocks/schedule-engine/engine.js +769 -0
- package/registry/blocks/schedule-engine/index.js +9 -0
- package/registry/blocks/schedule-engine/ops.js +71 -0
- package/registry/blocks/schedule-engine/place.js +294 -0
- package/registry/blocks/schedule-engine/tree.js +79 -0
- package/registry/blocks/schedule-engine/waits.js +80 -0
- package/registry/blocks/schedule-gantt/README.md +159 -0
- package/registry/blocks/schedule-gantt/block.json +10 -0
- package/registry/blocks/schedule-gantt/demo.jsx +223 -0
- package/registry/blocks/schedule-gantt/gantt-model.js +219 -0
- package/registry/blocks/schedule-gantt/geometry.js +176 -0
- package/registry/blocks/schedule-gantt/index.js +26 -0
- package/registry/blocks/schedule-gantt/schedule-gantt.jsx +882 -0
- package/registry/blocks/schedule-gantt/sheet.jsx +372 -0
- package/registry/blocks/schedule-gantt/track.jsx +190 -0
- package/registry/blocks/schedule-ruler/README.md +148 -0
- package/registry/blocks/schedule-ruler/block.json +10 -0
- package/registry/blocks/schedule-ruler/demo.jsx +181 -0
- package/registry/blocks/schedule-ruler/index.js +21 -0
- package/registry/blocks/schedule-ruler/ruler-model.js +239 -0
- package/registry/blocks/schedule-ruler/schedule-ruler.jsx +548 -0
- package/registry/blocks/sidebar/README.md +23 -13
- package/registry/blocks/sketch-canvas/README.md +15 -9
- package/registry/blocks/source-receipt/README.md +97 -0
- package/registry/blocks/source-receipt/block.json +30 -0
- package/registry/blocks/source-receipt/demo.jsx +71 -0
- package/registry/blocks/source-receipt/index.js +3 -0
- package/registry/blocks/source-receipt/source-receipt.jsx +107 -0
- package/registry/blocks/spreadsheet/spreadsheet.jsx +15 -1
- package/registry/blocks/step-picker/README.md +78 -0
- package/registry/blocks/step-picker/block.json +31 -0
- package/registry/blocks/step-picker/demo.jsx +23 -0
- package/registry/blocks/step-picker/index.js +3 -0
- package/registry/blocks/step-picker/step-picker.jsx +144 -0
- package/registry/blocks/step-settings/README.md +100 -0
- package/registry/blocks/step-settings/block.json +44 -0
- package/registry/blocks/step-settings/demo.jsx +93 -0
- package/registry/blocks/step-settings/fields.jsx +58 -0
- package/registry/blocks/step-settings/flow-settings.jsx +115 -0
- package/registry/blocks/step-settings/index.js +5 -0
- package/registry/blocks/step-settings/step-settings.jsx +290 -0
- package/registry/blocks/suggestion/README.md +171 -0
- package/registry/blocks/suggestion/block.json +40 -0
- package/registry/blocks/suggestion/demo.jsx +91 -0
- package/registry/blocks/suggestion/index.js +3 -0
- package/registry/blocks/suggestion/suggestion.jsx +436 -0
- package/registry/blocks/sum-bar/README.md +122 -0
- package/registry/blocks/sum-bar/block.json +10 -0
- package/registry/blocks/sum-bar/demo.jsx +110 -0
- package/registry/blocks/sum-bar/index.js +5 -0
- package/registry/blocks/sum-bar/sum-bar.jsx +209 -0
- package/registry/blocks/sum-bar/sum-model.js +126 -0
- package/registry/blocks/tier-map/README.md +217 -0
- package/registry/blocks/tier-map/block.json +10 -0
- package/registry/blocks/tier-map/demo.jsx +222 -0
- package/registry/blocks/tier-map/index.js +24 -0
- package/registry/blocks/tier-map/tier-map.jsx +574 -0
- package/registry/blocks/tier-map/tier-model.js +318 -0
- package/registry/blocks/time-grid/README.md +305 -0
- package/registry/blocks/time-grid/block.json +10 -0
- package/registry/blocks/time-grid/demo.jsx +279 -0
- package/registry/blocks/time-grid/grid-model.js +322 -0
- package/registry/blocks/time-grid/index.js +25 -0
- package/registry/blocks/time-grid/time-grid.jsx +1325 -0
- package/registry/blocks/time-strip/README.md +141 -0
- package/registry/blocks/time-strip/block.json +10 -0
- package/registry/blocks/time-strip/demo.jsx +129 -0
- package/registry/blocks/time-strip/index.js +19 -0
- package/registry/blocks/time-strip/strip-model.js +178 -0
- package/registry/blocks/time-strip/time-strip.jsx +260 -0
- package/registry/blocks/top-bar/README.md +149 -0
- package/registry/blocks/top-bar/block.json +35 -0
- package/registry/blocks/top-bar/demo.jsx +78 -0
- package/registry/blocks/top-bar/index.js +5 -0
- package/registry/blocks/top-bar/probe-rules.js +74 -0
- package/registry/blocks/top-bar/top-bar-model.js +152 -0
- package/registry/blocks/top-bar/top-bar.jsx +244 -0
- package/registry/blocks/trigger-picker/README.md +98 -0
- package/registry/blocks/trigger-picker/block.json +38 -0
- package/registry/blocks/trigger-picker/demo.jsx +59 -0
- package/registry/blocks/trigger-picker/index.js +3 -0
- package/registry/blocks/trigger-picker/trigger-picker.jsx +374 -0
- package/registry/blocks/whiteboard/README.md +20 -14
- package/registry/blocks/workflow-view/README.md +123 -0
- package/registry/blocks/workflow-view/block.json +10 -0
- package/registry/blocks/workflow-view/demo.jsx +90 -0
- package/registry/blocks/workflow-view/index.js +3 -0
- package/registry/blocks/workflow-view/workflow-view.jsx +203 -0
- package/src/cli.mjs +2 -2
- package/src/install.mjs +100 -22
- package/src/registry.mjs +37 -3
- package/templates/next/browser/lib/data.js +6 -1
- package/templates/next/files/README.md +909 -26
- package/templates/next/files/app/shell.jsx +54 -37
- package/templates/next/files/check/automation-format.ts +2103 -0
- package/templates/next/files/check/automation-package.ts +142 -0
- package/templates/next/files/check/run.mjs +1043 -12
- package/templates/next/files/components/ui/field.jsx +17 -4
- package/templates/next/files/components/ui/icon.jsx +13 -0
- package/templates/next/files/components/ui/index.js +3 -1
- package/templates/next/files/components/ui/layout.jsx +382 -0
- package/templates/next/files/components/ui/notice.jsx +70 -0
- package/templates/next/files/components/ui/page.jsx +124 -0
- package/templates/next/files/components/ui/stat.jsx +22 -7
- package/templates/next/files/components/ui/toast.jsx +6 -3
- package/templates/next/files/lib/automations.js +660 -0
- package/templates/next/files/lib/claw.js +244 -5
- package/templates/next/files/lib/door.js +92 -0
- package/templates/next/files/lib/hooks.js +1694 -6
- package/templates/next/files/lib/platform.js +611 -14
- package/templates/next/template.json +22 -3
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// One scheduled job on a card. Props in, callbacks out; the block never
|
|
4
|
+
// reads the schedule or the runs itself, and formats nothing (each line
|
|
5
|
+
// comes in as words). Tokens only. The state is a mark and a word, never
|
|
6
|
+
// a colour alone. Its own width decides its layout (@container): under
|
|
7
|
+
// about 320 px the next run and Run now stack, the button full width.
|
|
8
|
+
// With an `href` the WHOLE card opens the job: the chevron is a stretched
|
|
9
|
+
// link over the card, and the switch, the Run button and any link or
|
|
10
|
+
// button in `children` sit above it and keep their own press.
|
|
11
|
+
//
|
|
12
|
+
// Moved from the CRM (makersclaw-store packages/crm 0.7.0) into the
|
|
13
|
+
// template's kit (0.8.1, D15), with the on/off switch.
|
|
14
|
+
|
|
15
|
+
import { Button, Icon, IconButton, Switch, cx } from "../../ui";
|
|
16
|
+
|
|
17
|
+
const STATE = {
|
|
18
|
+
ok: { icon: "circle-check", text: "text-success" },
|
|
19
|
+
failed: { icon: "circle-x", text: "text-destructive" },
|
|
20
|
+
running: { icon: "loader", text: "text-info" },
|
|
21
|
+
off: { icon: "pause", text: "text-warning" },
|
|
22
|
+
none: { icon: "circle-dashed", text: "text-muted-foreground" },
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* title "Morning read"
|
|
27
|
+
* icon a kit Icon name (default "clock")
|
|
28
|
+
* state { tone: ok|failed|running|off|none, words: "Ran 07:02" }
|
|
29
|
+
* summary what the last run did, one or two lines
|
|
30
|
+
* cost "640 credits" (this run)
|
|
31
|
+
* allowance { used: 4180, of: 10000, words: "4,180 of 10,000 this week" }
|
|
32
|
+
* next "Next: Wed 30 Sep, 07:00"
|
|
33
|
+
* run { label: "Read now", price: "about 700 cr", onRun, loading, disabled, why }
|
|
34
|
+
* enabled the job is on (the switch's state)
|
|
35
|
+
* onToggle(next) the switch: drawn only when given
|
|
36
|
+
* toggleLabel the switch's words (default "On" / "Off")
|
|
37
|
+
* toggleBusy the switch's press is out: it waits
|
|
38
|
+
* href the job's page: a chevron at the card's head opens it
|
|
39
|
+
* children anything more, under the summary (a reason, a desk link)
|
|
40
|
+
*/
|
|
41
|
+
export function ScheduleCard({
|
|
42
|
+
title,
|
|
43
|
+
icon = "clock",
|
|
44
|
+
state,
|
|
45
|
+
summary,
|
|
46
|
+
cost,
|
|
47
|
+
allowance,
|
|
48
|
+
next,
|
|
49
|
+
run,
|
|
50
|
+
enabled,
|
|
51
|
+
onToggle,
|
|
52
|
+
toggleLabel,
|
|
53
|
+
toggleBusy = false,
|
|
54
|
+
href,
|
|
55
|
+
className,
|
|
56
|
+
children,
|
|
57
|
+
}) {
|
|
58
|
+
const s = STATE[state?.tone] ?? STATE.none;
|
|
59
|
+
const pct = allowance && allowance.of > 0 ? Math.max(0, Math.min(1, allowance.used / allowance.of)) : null;
|
|
60
|
+
const full = pct != null && pct >= 1;
|
|
61
|
+
const on = Boolean(enabled);
|
|
62
|
+
return (
|
|
63
|
+
<section
|
|
64
|
+
aria-label={title}
|
|
65
|
+
className={cx(
|
|
66
|
+
"@container grid min-w-0 gap-2 rounded-[var(--radius)] border border-border bg-card p-3 text-[13px] text-card-foreground",
|
|
67
|
+
href && "relative transition-colors hover:bg-accent/30 [&_:is(a,button):not([data-card-link])]:relative [&_:is(a,button):not([data-card-link])]:z-10",
|
|
68
|
+
className,
|
|
69
|
+
)}
|
|
70
|
+
>
|
|
71
|
+
<div className="flex min-w-0 items-start gap-2">
|
|
72
|
+
<Icon name={icon} size={16} className="mt-0.5 shrink-0 text-muted-foreground" />
|
|
73
|
+
<div className="grid min-w-0 flex-1 gap-0.5">
|
|
74
|
+
<b className="min-w-0 truncate font-semibold">{title}</b>
|
|
75
|
+
{state?.words ? (
|
|
76
|
+
<span className={cx("inline-flex min-w-0 items-center gap-1.5 text-xs", s.text)}>
|
|
77
|
+
<Icon name={s.icon} size={12} className={cx("shrink-0", state?.tone === "running" && "animate-spin motion-reduce:animate-none")} />
|
|
78
|
+
<span className="min-w-0 truncate">{state.words}</span>
|
|
79
|
+
</span>
|
|
80
|
+
) : null}
|
|
81
|
+
</div>
|
|
82
|
+
{onToggle ? (
|
|
83
|
+
<Switch
|
|
84
|
+
checked={on}
|
|
85
|
+
disabled={toggleBusy}
|
|
86
|
+
onChange={(e) => onToggle(Boolean(e?.target?.checked))}
|
|
87
|
+
label={toggleLabel ?? (on ? "On" : "Off")}
|
|
88
|
+
className="relative z-10 -my-2 shrink-0 text-xs"
|
|
89
|
+
/>
|
|
90
|
+
) : null}
|
|
91
|
+
{href ? (
|
|
92
|
+
<IconButton
|
|
93
|
+
icon="chevron-right"
|
|
94
|
+
size="sm"
|
|
95
|
+
href={href}
|
|
96
|
+
label={`Open ${title}`}
|
|
97
|
+
data-card-link=""
|
|
98
|
+
className="-my-1.5 -mr-1.5 after:absolute after:inset-0 after:rounded-[var(--radius)] after:content-['']"
|
|
99
|
+
/>
|
|
100
|
+
) : null}
|
|
101
|
+
</div>
|
|
102
|
+
{summary ? <p className="text-xs leading-snug">{summary}</p> : null}
|
|
103
|
+
{children}
|
|
104
|
+
{cost || allowance ? (
|
|
105
|
+
<div className="grid gap-1">
|
|
106
|
+
<span className={cx("text-xs", full ? "text-destructive" : "text-muted-foreground")}>{[cost, allowance?.words].filter(Boolean).join(" · ")}</span>
|
|
107
|
+
{pct != null ? (
|
|
108
|
+
<span aria-hidden="true" className="block h-1 overflow-hidden rounded-sm bg-border">
|
|
109
|
+
<span className={cx("block h-full", full ? "bg-destructive" : "bg-muted-foreground")} style={{ width: `${pct * 100}%` }} />
|
|
110
|
+
</span>
|
|
111
|
+
) : null}
|
|
112
|
+
</div>
|
|
113
|
+
) : null}
|
|
114
|
+
{next || run ? (
|
|
115
|
+
<div className="flex flex-col items-stretch gap-1.5 text-xs @xs:flex-row @xs:flex-wrap @xs:items-center">
|
|
116
|
+
{next ? <span className="min-w-0 text-muted-foreground">{next}</span> : null}
|
|
117
|
+
<span className="hidden flex-1 @xs:block" />
|
|
118
|
+
{run ? (
|
|
119
|
+
<Button
|
|
120
|
+
size="sm"
|
|
121
|
+
icon="play"
|
|
122
|
+
loading={run.loading}
|
|
123
|
+
disabled={run.disabled}
|
|
124
|
+
onClick={run.onRun}
|
|
125
|
+
title={run.why}
|
|
126
|
+
className="max-w-full"
|
|
127
|
+
>
|
|
128
|
+
<span className="truncate">{run.label ?? "Run now"}</span>
|
|
129
|
+
{run.price ? <span className="font-normal text-muted-foreground">{run.price}</span> : null}
|
|
130
|
+
</Button>
|
|
131
|
+
) : null}
|
|
132
|
+
</div>
|
|
133
|
+
) : null}
|
|
134
|
+
</section>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Schedule engine
|
|
2
|
+
|
|
3
|
+
The rules a dated plan follows, as plain functions over plain rows. No
|
|
4
|
+
React, no I/O: the browser runs them on every pointer move of a drag, a
|
|
5
|
+
script runs them for an agent, and the tests run them under node. The same
|
|
6
|
+
dates everywhere.
|
|
7
|
+
|
|
8
|
+
Born in a Gantt planner's app, which carried 770 lines of it (and an SQL
|
|
9
|
+
copy that the tests pin to it). It is the engine under the `schedule-gantt`
|
|
10
|
+
block, and it works alone.
|
|
11
|
+
|
|
12
|
+
```js
|
|
13
|
+
import { schedule, shiftDependents, replanFromToday } from "../components/blocks/schedule-engine"; // a Makersclaw app ("./blocks/schedule-engine" from components/)
|
|
14
|
+
// shadcn project: import { schedule } from "@/components/makersclaw/blocks/schedule-engine"
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## The model
|
|
18
|
+
|
|
19
|
+
- A task runs `d` working days (Monday to Friday; `calendar: "everyday"`
|
|
20
|
+
counts all seven). A milestone takes none and sits at the end of its day.
|
|
21
|
+
- A task's planned start is a floor: the forward pass only ever moves work
|
|
22
|
+
later. **Finished work** (status `done`, or progress 100) stays where it
|
|
23
|
+
happened.
|
|
24
|
+
- A task with sub-tasks is a **summary**: its dates are its leaves' span. A
|
|
25
|
+
link **to** a summary binds every leaf under it; a link **from** one reads
|
|
26
|
+
its span (last finish, or first start for start links).
|
|
27
|
+
- Cancelled tasks and tasks with no dates are off the plan, and so are
|
|
28
|
+
their links.
|
|
29
|
+
- **Slack** is the latest finish minus the earliest finish, in working days.
|
|
30
|
+
Slack 0 is critical. The **long pole** is the unfinished critical task
|
|
31
|
+
with the most work left; the later wins a tie.
|
|
32
|
+
|
|
33
|
+
## Rows in
|
|
34
|
+
|
|
35
|
+
- task: `{ id, parent_id, title, start_date, due_date, is_milestone,
|
|
36
|
+
progress, status, position }` (dates `'YYYY-MM-DD'`).
|
|
37
|
+
- link: `{ id, task_id, depends_on_id, kind, lag_days }`: `task_id` waits on
|
|
38
|
+
`depends_on_id`. `kind`: `finish_to_start` (default), `start_to_start`,
|
|
39
|
+
`finish_to_finish`, `start_to_finish`, or `FS` / `SS` / `FF` / `SF`.
|
|
40
|
+
|
|
41
|
+
## The plan
|
|
42
|
+
|
|
43
|
+
- `schedule(tasks, links, { calendar })` → `{ rows, links, start, finish,
|
|
44
|
+
critical, stuck, violations }`.
|
|
45
|
+
- `rows`: `Map(id → { id, parentId, summary, milestone, pinned, dated,
|
|
46
|
+
stuck, start, due, planStart, planDue, lateStart, lateDue, duration,
|
|
47
|
+
slack, critical, progress, shifted, drivers, leafIds })`. `start` / `due`
|
|
48
|
+
are the stored dates (a summary: its leaves' span); `plan*` where the
|
|
49
|
+
forward pass puts it; `shifted` is true when the stored dates break a
|
|
50
|
+
link.
|
|
51
|
+
- `links`: `Map(id → { id, taskId, dependsOnId, kind, lag, valid, reason,
|
|
52
|
+
slack, critical, violated, violation })`.
|
|
53
|
+
- `critical`: critical leaf ids in plan order. `stuck`: ids in or behind
|
|
54
|
+
a loop. `violations`: link ids whose stored dates break them.
|
|
55
|
+
- `shiftDependents(tasks, links, moves, { nextLinks, nextTasks })` → `{
|
|
56
|
+
changes: [{ id, start_date, due_date, from, summary? }], clamped, before,
|
|
57
|
+
after, finishBefore, finishAfter }`. `moves`: `[{ id, start, due }]`; a
|
|
58
|
+
summary's `start` moves its unfinished leaves as a block. Only tasks the
|
|
59
|
+
move affects are in `changes`.
|
|
60
|
+
- `replanFromToday(tasks, links, today)`: not started and its start has
|
|
61
|
+
passed → today; started and overdue → its remaining share from today;
|
|
62
|
+
a passed milestone → today. Then the dependents shift. Adds `moves`.
|
|
63
|
+
- `alignConflicts(tasks, links)`: every task that starts before its links
|
|
64
|
+
allow moves to its earliest date. Adds `moves`.
|
|
65
|
+
- `linkProblem(tasks, links, taskId, dependsOnId)` → why the link can't be
|
|
66
|
+
made, in words, or `null`.
|
|
67
|
+
- `longPole(plan)` → the id.
|
|
68
|
+
- Lower level: `buildNetwork`, `forwardPass`, `backwardPass`,
|
|
69
|
+
`criticalPath`, `makeCalendar`, `spanOf`, `datesOf`, `dayOf`, `isoOf`,
|
|
70
|
+
`addWorkdays`, `workdaysBetween`, `durationOf`, `linkKind`, `LINK_KINDS`.
|
|
71
|
+
- The tree: `taskTree(tasks)` → `{ order: [{ id, parentId, depth, outline,
|
|
72
|
+
childCount, index }], byId }`, `descendantsOf`, `positionBetween`,
|
|
73
|
+
`siblingOrder`.
|
|
74
|
+
|
|
75
|
+
## Planning a write
|
|
76
|
+
|
|
77
|
+
None of these writes. Each returns the values a save needs.
|
|
78
|
+
|
|
79
|
+
- `placeNew(tasks, { add: { parent_id, after_id, start, due, days,
|
|
80
|
+
milestone }, today, project })` → `{ parent_id, sort_order, start_date,
|
|
81
|
+
due_date, is_milestone, resum }`.
|
|
82
|
+
- `outlineChange(tasks, links, { id, kind: "in" | "out" | "up" | "down" |
|
|
83
|
+
"under", parent_id })` → `{ ok, parent_id, old_parent_id, sort_order,
|
|
84
|
+
order_only, changes, summaries, finishBefore, finishAfter, words }` or
|
|
85
|
+
`{ ok: false, error }`.
|
|
86
|
+
- `lengthChange(tasks, links, { id, days, project })`.
|
|
87
|
+
- `summaryChanges(tasks, links, ids)` → the summaries to re-span.
|
|
88
|
+
- `overlapsOf(tasks, plan, { ownerOf })` → who is on two things at once,
|
|
89
|
+
`[{ owner, from, to, count, ids }]`.
|
|
90
|
+
- `snapshotOf(tasks, links)` → `{ finish_date, data }`, the rows a baseline
|
|
91
|
+
keeps.
|
|
92
|
+
|
|
93
|
+
## The short form of a link
|
|
94
|
+
|
|
95
|
+
`2.5FS`, `6.3SS+5d`, `3.4SF-2d`, several joined with a semicolon: an outline
|
|
96
|
+
number, the kind (finish to start when left out), a signed lag in working
|
|
97
|
+
days. `shortForm(outline, kind, lag)`, `waitsWords(links, taskId,
|
|
98
|
+
outlineOf)`, `parseWaits(text, idOf)` → `{ links, problems }`, `lagWords`,
|
|
99
|
+
`KIND_WORDS` (the four kinds named in full, each with a clause).
|
|
100
|
+
|
|
101
|
+
## One entry for an agent
|
|
102
|
+
|
|
103
|
+
`operate({ operation, tasks, links, ... })` answers `schedule`, `move`,
|
|
104
|
+
`replan`, `mend`, `place`, `outline`, `length`, `link`, `snapshot` and
|
|
105
|
+
`load` as plain JSON (a Map is an object keyed by id, a Set a list). A
|
|
106
|
+
package's `references/plan.mjs` is ten lines around it:
|
|
107
|
+
|
|
108
|
+
```js
|
|
109
|
+
import { operate } from "../app/components/blocks/schedule-engine/ops.js";
|
|
110
|
+
let input = "";
|
|
111
|
+
for await (const chunk of process.stdin) input += chunk;
|
|
112
|
+
process.stdout.write(JSON.stringify(operate(JSON.parse(input))) + "\n");
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Example
|
|
116
|
+
|
|
117
|
+
```js
|
|
118
|
+
const plan = schedule(tasks, links);
|
|
119
|
+
plan.finish; // "2026-11-03"
|
|
120
|
+
plan.rows.get("t7").slack; // 0 = on the critical path
|
|
121
|
+
const moved = shiftDependents(tasks, links, [{ id: "t7", start: "2026-10-12", due: "2026-10-16" }]);
|
|
122
|
+
moved.finishAfter; // what the move cost the finish
|
|
123
|
+
moved.changes; // every date to save, in one write
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## States and edges
|
|
127
|
+
|
|
128
|
+
An empty plan has no finish (`null`) and no critical path. A loop leaves the
|
|
129
|
+
tasks in it where they were (`stuck`) and everything else is planned. A
|
|
130
|
+
weekend date counts from the Monday after (a start) or back to the Friday
|
|
131
|
+
(a finish). A link to a task with no dates is `valid: false, reason:
|
|
132
|
+
"undated"`. A parent that is not in the list makes a root.
|
|
133
|
+
|
|
134
|
+
## Tests
|
|
135
|
+
|
|
136
|
+
`test/schedule-engine.test.mjs` (the rules, every expected date worked out
|
|
137
|
+
by hand on a real calendar) and `test/schedule-engine-writes.test.mjs`.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "schedule-engine",
|
|
3
|
+
"title": "Schedule engine",
|
|
4
|
+
"description": "The rules a dated plan follows, as pure functions over plain rows: working days (Monday to Friday), the four link kinds (finish to start, start to start, finish to finish, start to finish) with lag and lead, the forward and backward pass, slack, the critical path and the long pole, shifting every dependent when a task moves, re-planning unfinished work from today, mending links the dates ignore, summaries that span their sub-tasks, finished work pinned in place, and the outline tree with its 1, 1.1, 1.2 numbers. Also the plans for a write: where a new task goes and with what dates, what an indent, outdent, move or reorder changes, a task's length, who is on two things at once, the rows a baseline keeps, and the short form of a link (2.4FS+2d) both ways. One entry, operate(), answers all of it as JSON so an agent's script and a screen get the same dates.",
|
|
5
|
+
"useWhen": "A plan with tasks that wait on each other and dates that must follow: a project schedule, a launch plan, a roadmap whose slips ripple, an agent that re-plans or answers 'when do we finish and what decides it'. The engine under the schedule-gantt block, usable alone with no chart. Not for undated to-dos (task-list) or stages (board).",
|
|
6
|
+
"tags": ["schedule", "gantt", "critical path", "slack", "dependencies", "working days", "lag", "baseline", "re-plan", "outline", "project plan", "milestones", "ms project", "pure", "agent"],
|
|
7
|
+
"exports": ["dayOf", "isoOf", "weekdayOf", "makeCalendar", "LINK_KINDS", "linkKind", "spanOf", "datesOf", "workdaysBetween", "addWorkdays", "durationOf", "buildNetwork", "forwardPass", "backwardPass", "criticalPath", "schedule", "shiftDependents", "replanFromToday", "alignConflicts", "linkProblem", "longPole", "taskTree", "descendantsOf", "positionBetween", "siblingOrder", "KIND_WORDS", "lagWords", "shortForm", "waitsWords", "parseWaits", "nextWorkday", "summaryChanges", "placeNew", "familyLinkProblem", "outlineChange", "lengthChange", "overlapsOf", "snapshotOf", "operate", "plain", "OPERATIONS"],
|
|
8
|
+
"files": ["index.js", "engine.js", "tree.js", "waits.js", "place.js", "ops.js"],
|
|
9
|
+
"requires": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// schedule-engine in the gallery — the gallery's and the smoke test's
|
|
4
|
+
// surface. Not installed into apps. The block is pure functions, so the
|
|
5
|
+
// demo is a small plan, a "slip" control and what the rules say it costs:
|
|
6
|
+
// Plan five tasks with their dates, slack and the critical path
|
|
7
|
+
// Slip push the design back and read the new finish, the tasks that
|
|
8
|
+
// move with it and the ones with slack that do not
|
|
9
|
+
// Links the short form, written and read back
|
|
10
|
+
import { useMemo, useState } from "react";
|
|
11
|
+
import { Button, Card, Notice } from "../components/ui";
|
|
12
|
+
import { addWorkdays, lagWords, parseWaits, schedule, shiftDependents, waitsWords, taskTree } from "../components/blocks/schedule-engine";
|
|
13
|
+
|
|
14
|
+
const TASKS = [
|
|
15
|
+
{ id: "d", parent_id: null, title: "Design", start_date: "2026-10-05", due_date: "2026-10-09", is_milestone: false, progress: 100, status: "done", position: 1 },
|
|
16
|
+
{ id: "b", parent_id: null, title: "Build", start_date: "2026-10-12", due_date: "2026-10-23", is_milestone: false, progress: 20, status: "in_progress", position: 2 },
|
|
17
|
+
{ id: "w", parent_id: null, title: "Write the docs", start_date: "2026-10-12", due_date: "2026-10-14", is_milestone: false, progress: 0, status: "todo", position: 3 },
|
|
18
|
+
{ id: "t", parent_id: null, title: "Test", start_date: "2026-10-26", due_date: "2026-10-30", is_milestone: false, progress: 0, status: "todo", position: 4 },
|
|
19
|
+
{ id: "l", parent_id: null, title: "Launch", start_date: "2026-11-02", due_date: "2026-11-02", is_milestone: true, progress: 0, status: "todo", position: 5 },
|
|
20
|
+
];
|
|
21
|
+
const LINKS = [
|
|
22
|
+
{ id: "1", task_id: "b", depends_on_id: "d", kind: "finish_to_start", lag_days: 0 },
|
|
23
|
+
{ id: "2", task_id: "w", depends_on_id: "d", kind: "finish_to_start", lag_days: 0 },
|
|
24
|
+
{ id: "3", task_id: "t", depends_on_id: "b", kind: "finish_to_start", lag_days: 0 },
|
|
25
|
+
{ id: "4", task_id: "t", depends_on_id: "w", kind: "finish_to_finish", lag_days: 5 },
|
|
26
|
+
{ id: "5", task_id: "l", depends_on_id: "t", kind: "finish_to_start", lag_days: 0 },
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
export default function ScheduleEngineDemo() {
|
|
30
|
+
const [slip, setSlip] = useState(0);
|
|
31
|
+
const tree = useMemo(() => taskTree(TASKS), []);
|
|
32
|
+
const outlineOf = (id) => tree.byId.get(id)?.outline;
|
|
33
|
+
const moves = slip ? [{ id: "b", start: "2026-10-12", due: addWorkdays("2026-10-23", slip) }] : [];
|
|
34
|
+
const result = useMemo(() => shiftDependents(TASKS, LINKS, moves), [slip]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
35
|
+
const plan = result.before;
|
|
36
|
+
const text = waitsWords(LINKS, "t", outlineOf);
|
|
37
|
+
const back = parseWaits(text, (o) => tree.order.find((e) => e.outline === o)?.id ?? null);
|
|
38
|
+
return (
|
|
39
|
+
<div className="grid gap-4 p-4">
|
|
40
|
+
<Card>
|
|
41
|
+
<div className="grid gap-3 p-4">
|
|
42
|
+
<p className="text-sm">
|
|
43
|
+
Finish <b>{plan.finish}</b>. Critical: {plan.critical.map((id) => TASKS.find((t) => t.id === id).title).join(", ")}.
|
|
44
|
+
</p>
|
|
45
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
46
|
+
<Button size="sm" onClick={() => setSlip((n) => n + 1)}>Slip Build a day</Button>
|
|
47
|
+
<Button size="sm" variant="ghost" onClick={() => setSlip(0)}>Put it back</Button>
|
|
48
|
+
<span className="text-xs text-muted-foreground">{slip ? `Build slipped ${slip} working ${slip === 1 ? "day" : "days"}` : "Nothing has slipped"}</span>
|
|
49
|
+
</div>
|
|
50
|
+
{slip ? (
|
|
51
|
+
<Notice>
|
|
52
|
+
The finish goes from {result.finishBefore} to {result.finishAfter}. Moves: {result.changes.map((c) => `${TASKS.find((t) => t.id === c.id).title} to ${c.start_date}`).join("; ") || "none"}.
|
|
53
|
+
</Notice>
|
|
54
|
+
) : null}
|
|
55
|
+
</div>
|
|
56
|
+
</Card>
|
|
57
|
+
<Card>
|
|
58
|
+
<div className="grid gap-1 p-4 text-sm">
|
|
59
|
+
{tree.order.map((e) => {
|
|
60
|
+
const t = TASKS.find((x) => x.id === e.id);
|
|
61
|
+
const r = plan.rows.get(e.id);
|
|
62
|
+
return (
|
|
63
|
+
<div key={e.id} className="flex flex-wrap items-baseline gap-3 tabular-nums">
|
|
64
|
+
<span className="w-8 text-muted-foreground">{e.outline}</span>
|
|
65
|
+
<span className="w-40">{t.title}</span>
|
|
66
|
+
<span className="w-44 text-muted-foreground">{r.planStart} to {r.planDue}</span>
|
|
67
|
+
<span className={r.critical ? "font-semibold text-destructive" : "text-muted-foreground"}>{r.critical ? "0 wd slack" : `${r.slack} wd slack`}</span>
|
|
68
|
+
</div>
|
|
69
|
+
);
|
|
70
|
+
})}
|
|
71
|
+
</div>
|
|
72
|
+
</Card>
|
|
73
|
+
<Card>
|
|
74
|
+
<div className="grid gap-1 p-4 text-sm">
|
|
75
|
+
<p>
|
|
76
|
+
Test waits on: <code>{text}</code> (lag {lagWords(5) || "none"} on the second). Read back: {back.links.map((l) => `${l.outline} ${l.kind} ${l.lag_days}`).join("; ")}.
|
|
77
|
+
</p>
|
|
78
|
+
</div>
|
|
79
|
+
</Card>
|
|
80
|
+
</div>
|
|
81
|
+
);
|
|
82
|
+
}
|