@7365admin1/layer-common 4.124.0 → 4.124.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @iservice365/layer-common
2
2
 
3
+ ## 4.124.2
4
+
5
+ ### Patch Changes
6
+
7
+ - aefd40e: Robot detail: Cancel now says the robot drives back to its charger (core sends it home after a cancel), and the confirm offers "Stop here" to leave it where it stops.
8
+
9
+ ## 4.124.1
10
+
11
+ ### Patch Changes
12
+
13
+ - 3f10a5a: Robot setup: saved point names and the zone editor fill in again (an early watcher hit not-yet-created state - point name boxes were empty).
14
+
3
15
  ## 4.124.0
4
16
 
5
17
  ### Minor Changes
@@ -3264,11 +3276,11 @@ Monthly report: a month that had patrols opens the list of that month's patrol r
3264
3276
  `utils/console-tier.ts` + `composables/useConsoleTier.ts` mirror the server's
3265
3277
  own rule from two endpoints the console already calls, unprojected:
3266
3278
 
3267
- GET /api/members/user/:user/app/admin the Seven365 staff membership
3268
- GET /api/roles/id/:role that membership's role document
3279
+ GET /api/members/user/:user/app/admin the Seven365 staff membership
3280
+ GET /api/roles/id/:role that membership's role document
3269
3281
 
3270
- owner = member.type === "admin" && role.type === "admin" && role.default === true
3271
- staff = member.type === "admin" && role.type === "admin"
3282
+ owner = member.type === "admin" && role.type === "admin" && role.default === true
3283
+ staff = member.type === "admin" && role.type === "admin"
3272
3284
 
3273
3285
  `role.default` is the marker because it is the only property of a platform
3274
3286
  staff role no API caller can set - `role.controller.ts` validates create and
@@ -245,6 +245,8 @@
245
245
  <div class="hero-dialog__body">{{ confirming.text.body }}</div>
246
246
  <div class="hero-dialog__actions">
247
247
  <v-btn variant="outlined" @click="confirmOpen = false">Don't send</v-btn>
248
+ <!-- Cancel sends the robot home (core 2026-10-15); this keeps it where it stops. -->
249
+ <v-btn v-if="confirming.kind === 'cancel'" variant="outlined" @click="confirmSend(true)">Stop here</v-btn>
248
250
  <v-btn color="primary" variant="flat" :disabled="!!confirming.zones && !confirming.zoneNames?.length" @click="confirmSend">{{ confirming.text.action }}</v-btn>
249
251
  </div>
250
252
  </div>
@@ -796,10 +798,10 @@ function pickRoute(id: unknown) {
796
798
  c.what = /^patrol/i.test(name) ? name : `patrolling ${name}`;
797
799
  c.text = commandConfirm("area", { type: "security", name: record.value?.name, route: { name, stops }, map });
798
800
  }
799
- function confirmSend() {
801
+ function confirmSend(stayHere = false) {
800
802
  const c = confirming.value;
801
803
  confirmOpen.value = false;
802
- if (c) run(c.kind, c.body, c.what);
804
+ if (c) run(c.kind, stayHere === true ? { ...c.body, stayHere: true } : c.body, c.what);
803
805
  }
804
806
 
805
807
  /** The robot's plan image size for its floor, for turning plan clicks into pixels. */
@@ -65,13 +65,6 @@ const props = defineProps<{ setup: Record<string, any>; busy?: boolean }>();
65
65
  const emit = defineEmits<{ apply: [change: Record<string, any>, ctx?: { map?: string }] }>();
66
66
 
67
67
  const mapId = ref<string | null>(null);
68
- watch(() => props.setup, (s) => {
69
- if (!mapId.value || !(s.maps ?? []).some((m: any) => m.mapId === mapId.value)) mapId.value = s.currentMapId ?? s.maps?.[0]?.mapId ?? null;
70
- for (const k of Object.keys(names)) delete names[k];
71
- for (const m of s.maps ?? []) for (const p of m.points ?? []) names[p.targetPointId] = p.name;
72
- newName.value = "";
73
- stopPick();
74
- }, { immediate: true });
75
68
  const map = computed(() => (props.setup.maps ?? []).find((m: any) => m.mapId === mapId.value) ?? null);
76
69
  const placed = computed(() => (map.value?.points ?? []).filter((p: any) => p.at).map((p: any) => ({ targetPointId: p.targetPointId, name: p.name, x: p.at.x, y: p.at.y })));
77
70
  const names = reactive<Record<string, string>>({});
@@ -100,6 +93,15 @@ function add(at: "robot" | TShare) {
100
93
  if (!map.value) return;
101
94
  emit("apply", { action: "point-add", mapId: map.value.mapId, name: newName.value.trim(), at, ...yaw() }, { map: map.value.name });
102
95
  }
96
+ // Last: an immediate watcher runs during setup, so everything it touches must already exist.
97
+ watch(() => props.setup, (s) => {
98
+ if (!mapId.value || !(s.maps ?? []).some((m: any) => m.mapId === mapId.value)) mapId.value = s.currentMapId ?? s.maps?.[0]?.mapId ?? null;
99
+ for (const k of Object.keys(names)) delete names[k];
100
+ for (const m of s.maps ?? []) for (const p of m.points ?? []) names[p.targetPointId] = p.name;
101
+ newName.value = "";
102
+ stopPick();
103
+ }, { immediate: true });
104
+
103
105
  function donePick() {
104
106
  if (!picked.value || !map.value) return;
105
107
  const at = { x: Math.round(picked.value.x * 100) / 100, y: Math.round(picked.value.y * 100) / 100 };
@@ -109,7 +109,6 @@ function reset() {
109
109
  wallsDirty.value = slowDirty.value = false;
110
110
  cancelDraw();
111
111
  }
112
- watch(() => props.setup, reset, { immediate: true });
113
112
 
114
113
  /* ---- drawing ---- */
115
114
  const drawing = ref<{ kind: TKind; name: string; target: TDraftShape | null } | null>(null);
@@ -145,6 +144,9 @@ const drawn = computed(() => [
145
144
  ...safe.value.map((z) => ({ kind: "safe" as const, name: z.name, points: z.points })),
146
145
  ]);
147
146
 
147
+ // Last: an immediate watcher runs during setup, so everything reset() touches must already exist.
148
+ watch(() => props.setup, reset, { immediate: true });
149
+
148
150
  function save(kind: "wall" | "slow") {
149
151
  if (!map.value) return;
150
152
  emit("apply", zonesChange(map.value.mapId, kind, kind === "wall" ? loadedWalls.value : loadedSlow.value, kind === "wall" ? walls.value : slow.value), { map: map.value.name });
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@7365admin1/layer-common",
3
3
  "license": "MIT",
4
4
  "type": "module",
5
- "version": "4.124.0",
5
+ "version": "4.124.2",
6
6
  "author": "7365admin1",
7
7
  "main": "./nuxt.config.ts",
8
8
  "//files": "What a consumer extending this layer actually loads. Without this npm ships the whole working tree - the changesets, the CI workflows, the render harness in tools/ and any scratch directory that happened to exist at publish time. Nuxt resolves a layer by directory, so every runtime directory below has to stay listed; adding a new top-level runtime directory means adding it here too.",
@@ -1767,7 +1767,7 @@ export function commandConfirm(
1767
1767
  return: `${who} stops what it is doing and drives back to its charger.`,
1768
1768
  pause: `${who} stops where it is and waits. Press Resume to carry on.`,
1769
1769
  resume: `${who} carries on with the job it paused.`,
1770
- cancel: `${who} stops the current job and stays where it is. It will not carry on by itself.`,
1770
+ cancel: `${who} stops the current job and drives back to its charger. Choose "Stop here" to leave it where it stops instead.`,
1771
1771
  navigate: at ? `${who} drives to ${at}.` : `${who} drives to the point you pick.`,
1772
1772
  relocalize: at
1773
1773
  ? `${who} is told it is standing at ${at}. Only do this if it really is there - a wrong position gets it lost.`