create-aiaui-module 0.1.1-TEST → 0.2.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 (52) hide show
  1. package/README.md +13 -12
  2. package/bin/create-aiaui-module.js +24 -32
  3. package/package.json +4 -3
  4. package/runtime/_runtime/host.py +7 -15
  5. package/runtime/_runtime/registry.py +4 -1
  6. package/templates/JobDashboard/CUSTOMIZATION.md +123 -0
  7. package/templates/{JobInformation → JobDashboard}/README.md +22 -9
  8. package/templates/JobDashboard/backend/api.py +144 -0
  9. package/templates/JobDashboard/backend/config.json +46 -0
  10. package/templates/JobDashboard/client/dist/modules.js +3513 -0
  11. package/templates/JobDashboard/client/src/contract.ts +146 -0
  12. package/templates/JobDashboard/client/src/customization.ts +30 -0
  13. package/templates/JobDashboard/client/src/defaults/DefaultPanel.vue +129 -0
  14. package/templates/JobDashboard/client/src/defaults/Icons.vue +49 -0
  15. package/templates/JobDashboard/client/src/defaults/InputCarriers.vue +18 -0
  16. package/templates/JobDashboard/client/src/defaults/JobBottom.vue +32 -0
  17. package/templates/JobDashboard/client/src/defaults/JobCard.vue +48 -0
  18. package/templates/JobDashboard/client/src/defaults/JobHeader.vue +41 -0
  19. package/templates/JobDashboard/client/src/defaults/JobMiddle.vue +41 -0
  20. package/templates/JobDashboard/client/src/defaults/JobName.vue +9 -0
  21. package/templates/JobDashboard/client/src/defaults/LotId.vue +14 -0
  22. package/templates/JobDashboard/client/src/defaults/OutputCarriers.vue +21 -0
  23. package/templates/JobDashboard/client/src/defaults/Recipe.vue +12 -0
  24. package/templates/JobDashboard/client/src/defaults/Status.vue +29 -0
  25. package/templates/JobDashboard/client/src/defaults/Timeline.vue +65 -0
  26. package/templates/JobDashboard/client/src/defaults/board-data.ts +36 -0
  27. package/templates/JobDashboard/client/src/defaults/config-defaults.ts +36 -0
  28. package/templates/JobDashboard/client/src/defaults/format.ts +51 -0
  29. package/templates/JobDashboard/client/src/defaults/slots.ts +26 -0
  30. package/templates/JobDashboard/client/src/defaults/styles.css +619 -0
  31. package/templates/{JobInformation/resources → JobDashboard/client}/src/index.ts +10 -18
  32. package/templates/JobInformation/CUSTOMIZATION.md +0 -173
  33. package/templates/JobInformation/api.py +0 -53
  34. package/templates/JobInformation/resources/dist/modules.js +0 -2919
  35. package/templates/JobInformation/resources/src/bus.ts +0 -38
  36. package/templates/JobInformation/resources/src/contract.ts +0 -74
  37. package/templates/JobInformation/resources/src/customization.ts +0 -25
  38. package/templates/JobInformation/resources/src/defaults/DefaultPanel.vue +0 -22
  39. package/templates/JobInformation/resources/src/defaults/Header.vue +0 -12
  40. package/templates/JobInformation/resources/src/defaults/InputCarriers.vue +0 -15
  41. package/templates/JobInformation/resources/src/defaults/OutputCarriers.vue +0 -14
  42. package/templates/JobInformation/resources/src/defaults/Recipe.vue +0 -18
  43. package/templates/JobInformation/resources/src/defaults/Timeline.vue +0 -22
  44. package/templates/JobInformation/resources/src/defaults/slots.ts +0 -16
  45. package/templates/JobInformation/resources/src/defaults/styles.css +0 -90
  46. /package/templates/{JobInformation/resources → JobDashboard/client}/build.mjs +0 -0
  47. /package/templates/{JobInformation/resources → JobDashboard/client}/dist/manifest.json +0 -0
  48. /package/templates/{JobInformation/resources → JobDashboard/client}/package-lock.json +0 -0
  49. /package/templates/{JobInformation/resources → JobDashboard/client}/package.json +0 -0
  50. /package/templates/{JobInformation/resources → JobDashboard/client}/src/vite-env.d.ts +0 -0
  51. /package/templates/{JobInformation/resources → JobDashboard/client}/vite.config.mjs +0 -0
  52. /package/templates/{JobInformation → JobDashboard}/contractVersion +0 -0
@@ -1,173 +0,0 @@
1
- # JobInformation customization
2
-
3
- This module ships with a built-in panel and exposes three customization
4
- levels. All of them keep the host-facing `mount(container, context)` /
5
- `unmount()` contract stable, so the Instance does not need to know which
6
- level you chose.
7
-
8
- ## Customization entry
9
-
10
- Edit `resources/src/customization.ts`. It exports a single `customization`
11
- object:
12
-
13
- ```ts
14
- import type { Customization } from "./contract";
15
-
16
- export const customization: Customization = { mode: "slots", slots: {} };
17
- ```
18
-
19
- ## Level 1 — default
20
-
21
- Leave `customization.ts` untouched. The module renders the built-in panel
22
- from `resources/src/defaults/`.
23
-
24
- ## Level 2 — partial (replace boxes)
25
-
26
- Set `mode: "slots"` and provide a `slots` map. Keys are the built-in slot
27
- names; values are Vue components that receive `context` as a prop.
28
-
29
- ```ts
30
- import MyHeader from "./custom/MyHeader.vue";
31
- import type { Customization } from "./contract";
32
-
33
- export const customization: Customization = {
34
- mode: "slots",
35
- slots: { header: MyHeader },
36
- };
37
- ```
38
-
39
- ### Built-in slots
40
-
41
- - `header` — job/lot identity and current state
42
- - `inputCarriers` — input carriers
43
- - `outputCarriers` — output carriers
44
- - `timeline` — progress steps
45
- - `recipe` — recipe/tool summary and actions
46
-
47
- ### Slot component contract
48
-
49
- ```vue
50
- <script setup lang="ts">
51
- import type { ModuleContext } from "../contract";
52
-
53
- defineProps<{ context: ModuleContext }>();
54
- </script>
55
-
56
- <template>
57
- <section class="aiaji-slot">…</section>
58
- </template>
59
- ```
60
-
61
- `context.api.call(method, path, options)` reaches this module's backend
62
- router. `context.signal` is aborted when the host unmounts the module, so
63
- long-running requests should observe it.
64
-
65
-
66
- ## Communicating between slots
67
-
68
- Every slot component in one mount — built-in or custom — receives the same
69
- `context` object. On top of `api` and `signal`, `context` carries a **bus**
70
- created fresh on each `mount` and dead on `unmount` (so switching Instance
71
- gets you a clean bus automatically). It never crosses module or Instance
72
- boundaries.
73
-
74
- ### 1. Events (recommended for most cases)
75
-
76
- Decoupled one-to-many communication:
77
-
78
- ```ts
79
- // MyInput.vue — sender
80
- const props = defineProps<{ context: ModuleContext }>();
81
-
82
- function onSelect(id: string) {
83
- props.context.bus.emit("lot:selected", { id });
84
- }
85
-
86
- onBeforeUnmount(() => props.context.bus.off("lot:selected", onSelect));
87
- ```
88
-
89
- ```ts
90
- // MyOutput.vue — receiver
91
- const props = defineProps<{ context: ModuleContext }>();
92
-
93
- onMounted(() =>
94
- props.context.bus.on("lot:selected", (payload) => {
95
- // `payload` is whatever the emitter passed; type it locally if you like
96
- console.log("lot picked:", payload?.id);
97
- }),
98
- );
99
- onBeforeUnmount(() => props.context.bus.off("lot:selected", someHandler));
100
- ```
101
-
102
- - `emit` with no listeners is a no-op (safe).
103
- - Always `off` what you `on` in `onBeforeUnmount`, or old listeners fire on remount.
104
- - Type the payload where you need it; the bus signature is loose by design.
105
-
106
- ### 2. Imperative handles (when you must call into a sibling)
107
-
108
- For `expose/peer` — e.g. OutputCarriers telling InputCarriers to focus a lot:
109
-
110
- ```ts
111
- // MyInput.vue — publisher
112
- const handle = {
113
- focusLot(id: string) {
114
- /* imperative action inside InputCarriers */
115
- },
116
- };
117
- onMounted(() => props.context.bus.expose("inputCarriers", handle));
118
- onUnmounted(() => props.context.bus.release("inputCarriers"));
119
- ```
120
-
121
- ```ts
122
- // MyOutput.vue — caller
123
- props.context.bus
124
- .peer<{ focusLot(id: string): void }>("inputCarriers")
125
- ?.focusLot("CR-01"); // always `?.` — peer returns undefined if the slot
126
- // was replaced away or hasn't mounted yet
127
- ```
128
-
129
- ### 3. Module-scope shared state (no bus needed)
130
-
131
- For pure data sync between two custom slots, a `reactive()` in a
132
- module-scope file also works with zero coupling:
133
-
134
- ```ts
135
- // resources/src/custom/shared.ts
136
- import { reactive } from "vue";
137
- export const shared = reactive({ selectedLot: null as string | null });
138
- ```
139
-
140
- ```ts
141
- // both MyInput.vue and MyOutput.vue
142
- import { shared } from "./shared";
143
- shared.selectedLot = "CR-01"; // set in one, read in the other
144
- ```
145
-
146
- Rule of thumb: defaults → events; only reach for `expose/peer` when the
147
- caller genuinely needs the peer's imperative API and accepts a
148
- not-yet-mounted/null risk.
149
-
150
-
151
- ## Level 3 — full override
152
-
153
- Set `mode: "full"` and implement both entry points. The shell skips the
154
- built-in panel entirely.
155
-
156
- ```ts
157
- export const customization: Customization = {
158
- mode: "full",
159
- mount(container, context) {
160
- // render anything you want into `container`
161
- },
162
- unmount() {
163
- // tear down your renderer
164
- },
165
- };
166
- ```
167
-
168
- ## Styling
169
-
170
- The built-in styles are bundled into `modules.js`, so no separate CSS asset
171
- is required. Slot components can reuse the built-in `aiaji-*` classes and the
172
- `--aia-*` CSS variables (`--aia-text`, `--aia-border`, `--aia-accent`), or
173
- bring their own inline styles.
@@ -1,53 +0,0 @@
1
- """Editable Job Information example, mounted under /modules/JobInformation."""
2
-
3
- import inspect
4
-
5
- from fastapi import APIRouter
6
-
7
-
8
- def create_api(context) -> APIRouter:
9
- """Entry point invoked by the generated PyAIAUI host.
10
-
11
- The Instance injects its live objects via ``PyAIAUI.AIAUI.start(services={...})``
12
- and they arrive here through ``context.services``.
13
- """
14
- router = APIRouter()
15
-
16
- @router.get("/server")
17
- async def server():
18
- secs_server = context.services.get("secs_server")
19
- if secs_server is None:
20
- return {"available": False, "name": None, "connected": None}
21
- driver = getattr(secs_server, "driver", None)
22
- check = getattr(driver, "is_connected", None)
23
- connected = check() if callable(check) else None
24
- if inspect.isawaitable(connected):
25
- connected = await connected
26
- return {
27
- "available": True,
28
- "name": getattr(secs_server, "name", None),
29
- "connected": connected,
30
- }
31
-
32
- @router.get("/jobs")
33
- async def jobs(name: str = "", page: int = 1, pageSize: int = 20):
34
- repository = context.services.get("job_repository")
35
- if repository is not None:
36
- result = repository.list_jobs(name=name, page=page, page_size=pageSize)
37
- return await result if inspect.isawaitable(result) else result
38
-
39
- # Sample data is used only until the Instance injects a repository.
40
- items = [
41
- {"id": "demo-1", "name": "DEMO-JOB-001", "state": "Running"},
42
- {"id": "demo-2", "name": "DEMO-JOB-002", "state": "Queued"},
43
- ]
44
- matched = [item for item in items if name.casefold() in item["name"].casefold()]
45
- start = (page - 1) * pageSize
46
- return {
47
- "items": matched[start : start + pageSize],
48
- "total": len(matched),
49
- "page": page,
50
- "pageSize": pageSize,
51
- }
52
-
53
- return router