@7365admin1/layer-common 3.2.1-staging.68 → 3.2.1-staging.69
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.
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
"@7365admin1/layer-common": patch
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Mark the selected camera on the wall, and stop telling the reader to raise a
|
|
6
|
+
ticket without saying what for.
|
|
7
|
+
|
|
8
|
+
Two things the owner found on the live wall after the last copy pass. Both are
|
|
9
|
+
copy and presentation only — **no behaviour, no capability gating, no permission
|
|
10
|
+
check and no request is changed.**
|
|
11
|
+
|
|
12
|
+
**1. The camera's name was still printed twice.**
|
|
13
|
+
|
|
14
|
+
The tile said `BBQ AREA` and the panel underneath said it again. The last pass
|
|
15
|
+
merged the panel's heading into its status line, which changed the layout and
|
|
16
|
+
left the repetition exactly where it was.
|
|
17
|
+
|
|
18
|
+
The name was there to answer "which of these nine tiles is this panel about?".
|
|
19
|
+
That is a real question and a name is the wrong answer to it — it makes the
|
|
20
|
+
reader scan the wall for a matching caption. So:
|
|
21
|
+
|
|
22
|
+
- **the selected tile is now visibly selected**: a 3 px accent ring with a scrim
|
|
23
|
+
hairline inside it, so the ring holds against a bright picture as well as a
|
|
24
|
+
dark one, plus the accent underline on the name chip that the toolbar already
|
|
25
|
+
uses to mark a selected tool. Both read at 1x1, 2x2 and 3x3;
|
|
26
|
+
- **the camera's name is removed from the panel entirely**. The panel opens on
|
|
27
|
+
the recorder's state — "● Recorder responding";
|
|
28
|
+
- `aria-current` marks the same tile for anyone not looking at the ring.
|
|
29
|
+
|
|
30
|
+
The highlight had never worked in the most common case, which is why the name
|
|
31
|
+
was load-bearing: it was bound to the raw clicked id, and before anyone clicks —
|
|
32
|
+
or after paging — nothing on the wall was marked while the panel was already
|
|
33
|
+
describing the first tile. It is now bound to the tile the panel actually
|
|
34
|
+
resolves to, so the two can never disagree.
|
|
35
|
+
|
|
36
|
+
**The panel can never be about a tile that is off screen**, so it never needs to
|
|
37
|
+
name one: the focused camera is resolved out of the current PAGE, so paging away
|
|
38
|
+
from a selection re-resolves to the first tile of the page in front of you and
|
|
39
|
+
the ring follows. Paging back restores the original selection. Extracted as
|
|
40
|
+
`focusedCamera()` in `camera-wall.ts` with four tests, including the 5-cameras
|
|
41
|
+
-across-2-pages case.
|
|
42
|
+
|
|
43
|
+
**2. "Ask your Seven365 administrator" was a dead end.**
|
|
44
|
+
|
|
45
|
+
It was the whole of the advice under every switched-off control, and it tells
|
|
46
|
+
the administrator nothing and a property manager only to go and wait. The screen
|
|
47
|
+
never said what the request should ask for.
|
|
48
|
+
|
|
49
|
+
The advice now names the two changes that are actually missing, because they are
|
|
50
|
+
two different jobs for two different people: **the site's network has to let our
|
|
51
|
+
server reach the camera recorder**, and **that recorder then has to be added to
|
|
52
|
+
the server's configuration**. Both are stated in plain words, with who arranges
|
|
53
|
+
them, and with the fact that neither is switchable from this page.
|
|
54
|
+
|
|
55
|
+
No environment variable name appears in any of it — those belong in
|
|
56
|
+
`iservice365-core/docs/camera-integration-config.md`, not on a property
|
|
57
|
+
manager's screen — and there is a test that keeps it that way. The other reason
|
|
58
|
+
codes (`device-http-disabled`, `device-http-unreachable`, `device-http-locked-out`,
|
|
59
|
+
`control-not-enabled`, `no-recorder-configured`, and the unknown-code fallback)
|
|
60
|
+
get the same treatment; the Site Settings ones already said what to do and are
|
|
61
|
+
unchanged.
|
|
62
|
+
|
|
63
|
+
The truthful-status rules are untouched: the wall still refuses to say "Live"
|
|
64
|
+
until the video service reports a decoded frame, and the recorder's state is
|
|
65
|
+
still a separate fact from the tile's badge.
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
:online="online"
|
|
127
127
|
:health="healthById[camera._id]"
|
|
128
128
|
:now="now"
|
|
129
|
-
:focused="camera._id ===
|
|
129
|
+
:focused="camera._id === focused?._id"
|
|
130
130
|
@focus="focusedId = $event._id"
|
|
131
131
|
/>
|
|
132
132
|
</div>
|
|
@@ -171,32 +171,39 @@
|
|
|
171
171
|
-->
|
|
172
172
|
<div v-if="focused" class="vms__caps">
|
|
173
173
|
<!--
|
|
174
|
-
THE
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
174
|
+
THE CAMERA'S NAME IS GONE FROM THIS PANEL ENTIRELY. THE SELECTED TILE
|
|
175
|
+
SAYS WHICH CAMERA THIS IS.
|
|
176
|
+
|
|
177
|
+
It was here twice before: once as a heading, then — after a first
|
|
178
|
+
attempt at this — as the subject of the status line. The owner's point
|
|
179
|
+
was never the line break. It was the REPETITION: the tile directly above
|
|
180
|
+
is already captioned "BBQ AREA", and printing it again underneath adds
|
|
181
|
+
no fact.
|
|
182
|
+
|
|
183
|
+
The reason it was kept is real — the panel describes ONE of up to nine
|
|
184
|
+
tiles and the reader has to know which — but a name is the wrong way to
|
|
185
|
+
answer it. Naming a tile makes the reader search the wall for a matching
|
|
186
|
+
caption; an accent ring makes the wall answer at a glance. So the ring
|
|
187
|
+
is the identification (`vms-tile--focused`) and the panel is free to be
|
|
188
|
+
about the camera rather than about naming it.
|
|
189
|
+
|
|
190
|
+
**And the panel can never describe a tile that is off screen**, so it
|
|
191
|
+
never needs to fall back to naming one. `focused` is resolved out of
|
|
192
|
+
`tiles` — the CURRENT page — so paging away re-resolves it to the first
|
|
193
|
+
tile of the page you are now looking at. There is no state in which this
|
|
194
|
+
panel is about something you cannot see. That is asserted in
|
|
195
|
+
`camera-wall.test.ts` so it cannot quietly stop being true.
|
|
188
196
|
-->
|
|
189
197
|
<div class="vms__health">
|
|
190
|
-
<span class="vms__health-state">
|
|
191
|
-
<span class="vms__health-dot" :class="`vms__health-dot--${focusedHealth.tone}`" />
|
|
192
|
-
{{ focused.name || focused._id }}
|
|
193
|
-
</span>
|
|
194
198
|
<!--
|
|
195
199
|
THE RECORDER's own state — a different fact from the tile badge above,
|
|
196
200
|
which is about the picture. They can disagree, and when they do the
|
|
197
201
|
reader needs both, not a merged verdict.
|
|
198
202
|
-->
|
|
199
|
-
<span class="vms__health-
|
|
203
|
+
<span class="vms__health-state">
|
|
204
|
+
<span class="vms__health-dot" :class="`vms__health-dot--${focusedHealth.tone}`" />
|
|
205
|
+
{{ focusedHealth.label }}
|
|
206
|
+
</span>
|
|
200
207
|
<!--
|
|
201
208
|
"Last picture" ONLY WHEN THERE HAS BEEN ONE.
|
|
202
209
|
|
|
@@ -283,6 +290,7 @@ import {
|
|
|
283
290
|
capabilityView,
|
|
284
291
|
clampPage,
|
|
285
292
|
DEFAULT_WALL_LAYOUT,
|
|
293
|
+
focusedCamera,
|
|
286
294
|
healthView,
|
|
287
295
|
isDenseLayout,
|
|
288
296
|
sharedCapabilityNote,
|
|
@@ -441,10 +449,28 @@ function togglePick(id: string) {
|
|
|
441
449
|
|
|
442
450
|
/* --------------------------------------------------------- what is focused */
|
|
443
451
|
|
|
452
|
+
/**
|
|
453
|
+
* WHICH TILE THE PANEL IS ABOUT — and it is always a tile you can see.
|
|
454
|
+
*
|
|
455
|
+
* `focusedId` is what somebody clicked; `focused` is what the panel actually
|
|
456
|
+
* describes, and the two are deliberately not the same thing. It is resolved out
|
|
457
|
+
* of `tiles`, which is the CURRENT PAGE, so:
|
|
458
|
+
*
|
|
459
|
+
* - before anyone clicks, the panel describes the first tile on the wall;
|
|
460
|
+
* - paging away from your selection re-resolves to the first tile of the page
|
|
461
|
+
* you are now on, rather than describing a camera that is no longer drawn;
|
|
462
|
+
* - paging back returns to your selection, because `focusedId` is not cleared.
|
|
463
|
+
*
|
|
464
|
+
* **The tile highlight is bound to `focused`, not to `focusedId`** — that one
|
|
465
|
+
* character was the whole defect behind "the panel repeats the tile's name".
|
|
466
|
+
* Bound to `focusedId`, the fallback cases above lit NO tile at all: the panel
|
|
467
|
+
* described the first camera on the page and nothing on the wall said so, which
|
|
468
|
+
* is exactly why the name had to be printed in the panel to make sense of it.
|
|
469
|
+
* Bound to `focused`, the wall always shows which tile is being described, and
|
|
470
|
+
* the name in the panel becomes the repetition the owner said it was.
|
|
471
|
+
*/
|
|
444
472
|
const focusedId = ref("");
|
|
445
|
-
const focused = computed(
|
|
446
|
-
() => tiles.value.find((c) => c._id === focusedId.value) || tiles.value[0] || null
|
|
447
|
-
);
|
|
473
|
+
const focused = computed(() => focusedCamera(tiles.value, focusedId.value));
|
|
448
474
|
|
|
449
475
|
function capability(key: string) {
|
|
450
476
|
return capabilityView(focused.value, key);
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
:class="{ 'vms-tile--dense': dense, 'vms-tile--focused': focused, 'vms-tile--empty': !camera }"
|
|
6
6
|
:tabindex="camera ? 0 : -1"
|
|
7
7
|
:aria-label="camera ? `${camera.name || camera._id}, ${view.label}` : 'Empty position'"
|
|
8
|
+
:aria-current="focused ? 'true' : undefined"
|
|
8
9
|
@click="camera && $emit('focus', camera)"
|
|
9
10
|
@dblclick="camera && toggleFullscreen()"
|
|
10
11
|
@keydown.enter="camera && toggleFullscreen()"
|
|
@@ -486,8 +487,40 @@ async function toggleFullscreen() {
|
|
|
486
487
|
min-height: 0;
|
|
487
488
|
}
|
|
488
489
|
|
|
490
|
+
/*
|
|
491
|
+
THE SELECTED TILE, AND WHY IT IS NOW LOUDER.
|
|
492
|
+
|
|
493
|
+
The panel under the wall describes ONE tile. It used to say which by printing
|
|
494
|
+
the camera's name — directly under a tile already captioned with that name —
|
|
495
|
+
because the ring here was too quiet to be doing that job: 2 px of #5b9be0
|
|
496
|
+
disappears against a bright picture, and at nine tiles it was a hairline the
|
|
497
|
+
eye skipped. So the panel was answering "which one?" in words, and the words
|
|
498
|
+
read as the name repeated twice.
|
|
499
|
+
|
|
500
|
+
Two marks now, and between them they hold at 1x1, 2x2 and 3x3:
|
|
501
|
+
|
|
502
|
+
- a **3 px accent ring**, with a 1 px scrim hairline INSIDE it. The hairline is
|
|
503
|
+
what makes the ring survive a white picture — accent-on-white is a weak edge,
|
|
504
|
+
accent-on-near-black is not, so the ring carries its own dark backing rather
|
|
505
|
+
than depending on what the camera happens to be pointing at.
|
|
506
|
+
- the **name chip underlined in the accent**, which is the same mark the
|
|
507
|
+
toolbar already uses for a selected tool (`.vms__tool--on`). At 3x3 the ring
|
|
508
|
+
is 3 px on a ~118 px tile; the underline sits right beside the caption a
|
|
509
|
+
supervisor is already reading, so identification does not depend on
|
|
510
|
+
perceiving 3 px from across a room.
|
|
511
|
+
|
|
512
|
+
INVENTED VALUES, recorded: the ring is 3 px where it was 2 px. Everything else
|
|
513
|
+
is existing — `--vms-accent`, `--vms-scrim-solid`, and the toolbar's 2 px
|
|
514
|
+
underline idiom. No new colour.
|
|
515
|
+
*/
|
|
489
516
|
.vms-tile--focused {
|
|
490
|
-
box-shadow:
|
|
517
|
+
box-shadow:
|
|
518
|
+
inset 0 0 0 3px var(--vms-accent, #5b9be0),
|
|
519
|
+
inset 0 0 0 4px var(--vms-scrim-solid, rgba(7, 9, 12, 0.82));
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
.vms-tile--focused .vms-tile__name {
|
|
523
|
+
box-shadow: inset 0 -2px 0 var(--vms-accent, #5b9be0);
|
|
491
524
|
}
|
|
492
525
|
|
|
493
526
|
.vms-tile:focus-visible {
|
package/package.json
CHANGED
|
@@ -4,9 +4,11 @@ import { test } from "node:test";
|
|
|
4
4
|
import {
|
|
5
5
|
agoLabel,
|
|
6
6
|
capabilityView,
|
|
7
|
+
CAPABILITY_NEXT_STEPS,
|
|
7
8
|
clampPage,
|
|
8
9
|
clampPan,
|
|
9
10
|
clampZoom,
|
|
11
|
+
focusedCamera,
|
|
10
12
|
healthView,
|
|
11
13
|
isDenseLayout,
|
|
12
14
|
playerOrigin,
|
|
@@ -70,6 +72,46 @@ test("a selection sets the order, and a stale id is dropped rather than drawn",
|
|
|
70
72
|
assert.equal(tiles[0]._id, "b");
|
|
71
73
|
});
|
|
72
74
|
|
|
75
|
+
/* ------------------------------------------- which tile the panel is about */
|
|
76
|
+
|
|
77
|
+
/*
|
|
78
|
+
THE PANEL STOPPED PRINTING THE CAMERA'S NAME, AND THESE ARE THE TWO FACTS
|
|
79
|
+
THAT LET IT.
|
|
80
|
+
|
|
81
|
+
The name was there so the reader could tell which of up to nine tiles the
|
|
82
|
+
panel described. It is now the selected tile's accent ring that answers that —
|
|
83
|
+
which is only safe while the panel can never be about a tile that is not
|
|
84
|
+
drawn. Five cameras across two pages is exactly the case the owner asked
|
|
85
|
+
about, so it is exactly the case pinned here.
|
|
86
|
+
*/
|
|
87
|
+
const FIVE = ["a", "b", "c", "d", "e"].map((id) => ip({ _id: id, name: id.toUpperCase() }));
|
|
88
|
+
|
|
89
|
+
test("nothing selected yet: the panel is about the first tile ON THIS PAGE", () => {
|
|
90
|
+
assert.equal(focusedCamera(wallTiles(FIVE, [], "2x2", 0), "")?._id, "a");
|
|
91
|
+
// Page 2 of the same wall holds one camera, and the panel is about that one —
|
|
92
|
+
// not still about "a", which is no longer on screen.
|
|
93
|
+
assert.equal(focusedCamera(wallTiles(FIVE, [], "2x2", 1), "")?._id, "e");
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test("paging away from your selection never leaves the panel describing an off-page camera", () => {
|
|
97
|
+
// Selected "a" on page 1, then paged to page 2. "a" is not drawn there.
|
|
98
|
+
const pageTwo = wallTiles(FIVE, [], "2x2", 1);
|
|
99
|
+
const shown = focusedCamera(pageTwo, "a");
|
|
100
|
+
assert.equal(shown?._id, "e");
|
|
101
|
+
assert.ok(
|
|
102
|
+
pageTwo.some((c) => c._id === shown?._id),
|
|
103
|
+
"the panel must always describe a tile on the current page"
|
|
104
|
+
);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test("paging back restores the selection, because the raw id is kept", () => {
|
|
108
|
+
assert.equal(focusedCamera(wallTiles(FIVE, [], "2x2", 0), "c")?._id, "c");
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test("an empty wall has nothing to describe", () => {
|
|
112
|
+
assert.equal(focusedCamera([], "a"), null);
|
|
113
|
+
});
|
|
114
|
+
|
|
73
115
|
/* ---------------------------------------------------------------- rule 2/3 */
|
|
74
116
|
|
|
75
117
|
test("no descriptor at all counts as NOT available", () => {
|
|
@@ -132,7 +174,38 @@ test("a switched-off control says what would switch it on and who to ask", () =>
|
|
|
132
174
|
// The server's sentence is still verbatim — rule 3 is not traded away for rule 5.
|
|
133
175
|
assert.match(v.detail, /^No direct connection/);
|
|
134
176
|
assert.match(v.nextStep, /Seven365 administrator/);
|
|
135
|
-
assert.match(v.nextStep, /not
|
|
177
|
+
assert.match(v.nextStep, /not switchable from this page/i);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
/*
|
|
181
|
+
THE ADVICE HAS TO NAME THE TWO CHANGES, AND IT HAS TO STAY OUT OF THE
|
|
182
|
+
DEPLOYMENT MANUAL.
|
|
183
|
+
|
|
184
|
+
"Ask your Seven365 administrator" was the whole of the old advice and it was a
|
|
185
|
+
dead end — worse than useless for the owner, who IS the administrator. What
|
|
186
|
+
makes the new line actionable is that it names the two real changes: the
|
|
187
|
+
network has to let the server reach the recorder, and the recorder then has to
|
|
188
|
+
be configured on the server. Both halves are pinned here, because dropping
|
|
189
|
+
either one silently returns the sentence to a shrug.
|
|
190
|
+
|
|
191
|
+
And the other direction is pinned too: no environment variable name may appear
|
|
192
|
+
in copy a property manager reads. The names are correct, they are in
|
|
193
|
+
`iservice365-core/docs/camera-integration-config.md`, and they are unreadable
|
|
194
|
+
to the person this screen is written for.
|
|
195
|
+
*/
|
|
196
|
+
test("the setup advice names the network change AND the server change", () => {
|
|
197
|
+
const advice = CAPABILITY_NEXT_STEPS["device-http-not-configured"];
|
|
198
|
+
assert.match(advice, /network/i);
|
|
199
|
+
assert.match(advice, /recorder/i);
|
|
200
|
+
assert.match(advice, /server's configuration/i);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
test("no environment variable name is ever shown to a reader", () => {
|
|
204
|
+
// Anything SCREAMING_SNAKE would be a deployment detail leaking into product
|
|
205
|
+
// copy. `CAMERA_DEVICE_HTTP` and friends belong in the deployment document.
|
|
206
|
+
for (const [reason, advice] of Object.entries(CAPABILITY_NEXT_STEPS)) {
|
|
207
|
+
assert.doesNotMatch(advice, /[A-Z][A-Z0-9]*_[A-Z0-9_]+/, `${reason} names a variable`);
|
|
208
|
+
}
|
|
136
209
|
});
|
|
137
210
|
|
|
138
211
|
/* ---------------------------------------------------------------- rule 7 */
|
package/utils/camera-wall.ts
CHANGED
|
@@ -196,6 +196,30 @@ export function wallTiles(
|
|
|
196
196
|
return chosen.slice(start, start + tiles);
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
+
/**
|
|
200
|
+
* WHICH TILE THE DETAIL PANEL IS ABOUT, and the guarantee that makes the panel
|
|
201
|
+
* able to stop naming it.
|
|
202
|
+
*
|
|
203
|
+
* The panel used to print the camera's name so the reader could tell which of
|
|
204
|
+
* up to nine tiles it was describing. The name is gone — the selected tile wears
|
|
205
|
+
* an accent ring instead — and that only works because **this can never return a
|
|
206
|
+
* camera that is not on the page being looked at.** It resolves out of the
|
|
207
|
+
* CURRENT page's tiles, so a selection left behind on page 1 does not leave the
|
|
208
|
+
* panel describing an invisible camera from page 2; it falls back to the first
|
|
209
|
+
* tile of the page you are actually on, which the ring then marks.
|
|
210
|
+
*
|
|
211
|
+
* The caller keeps the raw id, so paging back restores the original selection.
|
|
212
|
+
*
|
|
213
|
+
* Extracted from the component purely so this guarantee is a tested rule rather
|
|
214
|
+
* than a line of template nobody would think to check.
|
|
215
|
+
*/
|
|
216
|
+
export function focusedCamera(
|
|
217
|
+
tiles: TWallCamera[],
|
|
218
|
+
focusedId: string | undefined
|
|
219
|
+
): TWallCamera | null {
|
|
220
|
+
return tiles.find((c) => c._id === focusedId) || tiles[0] || null;
|
|
221
|
+
}
|
|
222
|
+
|
|
199
223
|
/**
|
|
200
224
|
* How many grid rows this page actually needs — the other half of packing.
|
|
201
225
|
*
|
|
@@ -253,22 +277,49 @@ const NOT_PROBED = "This camera has not been asked what it can do yet.";
|
|
|
253
277
|
* **Every one of these says the same true and unwelcome thing in a different
|
|
254
278
|
* way: none of it is switched on from this page.** Saying so plainly is the
|
|
255
279
|
* point. An empty settings screen that quietly does nothing would be worse.
|
|
280
|
+
*
|
|
281
|
+
* ## "Ask your Seven365 administrator" was a dead end, and it has been replaced
|
|
282
|
+
*
|
|
283
|
+
* That was the whole of the advice, and the owner — who IS the administrator —
|
|
284
|
+
* read it on the live wall and pointed out that it tells him nothing. It tells a
|
|
285
|
+
* property manager nothing either: they raise a ticket and wait, because the
|
|
286
|
+
* screen never said what the ticket should ASK FOR.
|
|
287
|
+
*
|
|
288
|
+
* The real answer is two changes, and they are two different jobs for two
|
|
289
|
+
* different people:
|
|
290
|
+
*
|
|
291
|
+
* 1. **a network change** — the site's network has to let our server reach the
|
|
292
|
+
* camera recorder. Today it does not: the recorder answers video only.
|
|
293
|
+
* 2. **a configuration change on our server** — that recorder then has to be
|
|
294
|
+
* added to the server's configuration.
|
|
295
|
+
*
|
|
296
|
+
* So each line below names the change that is missing and who does it, in that
|
|
297
|
+
* order. **No environment variable is named**, deliberately: the names belong in
|
|
298
|
+
* the deployment documentation (`iservice365-core/docs/camera-integration-config.md`),
|
|
299
|
+
* not on a property manager's screen, and printing them would make the sentence
|
|
300
|
+
* unreadable to the person it is written for without helping the person who
|
|
301
|
+
* needs them, who has the document.
|
|
302
|
+
*
|
|
303
|
+
* Nor does any line point at the camera setup guide. That guide covers ADDING a
|
|
304
|
+
* camera in Site Settings; it does not cover recorder connectivity, so sending
|
|
305
|
+
* the reader there would be sending them somewhere that does not answer the
|
|
306
|
+
* question. Naming the two changes IS the actionable content.
|
|
256
307
|
*/
|
|
257
308
|
export const CAPABILITY_NEXT_STEPS: Record<string, string> = {
|
|
258
309
|
"device-http-not-configured":
|
|
259
|
-
"Not
|
|
310
|
+
"Not switchable from this page. It needs the site's network opened so our server can reach the camera recorder, and that recorder then added to the server's configuration — your Seven365 administrator arranges both with whoever installed the cameras.",
|
|
260
311
|
"device-http-disabled":
|
|
261
|
-
"
|
|
312
|
+
"Not switchable from this page. The connection to the recorder exists but is turned off in the server's configuration — your Seven365 administrator turns it on.",
|
|
262
313
|
"device-http-unreachable":
|
|
263
|
-
"
|
|
314
|
+
"Our server cannot reach this camera's recorder. Usually the site's network is blocking it or the recorder is down — your Seven365 administrator and whoever installed the cameras check it between them.",
|
|
264
315
|
"device-http-locked-out":
|
|
265
|
-
"Sign-ins to the recorder are being held back so its account is not locked out.
|
|
316
|
+
"Sign-ins to the recorder are being held back so its account is not locked out. It clears on its own; if it keeps happening the password held for the recorder is wrong and your Seven365 administrator corrects it in the server's configuration.",
|
|
266
317
|
"control-not-enabled":
|
|
267
|
-
"
|
|
318
|
+
"Not switchable from this page. This one moves real hardware, so a Seven365 backend lead has to approve it before it is turned on in the server's configuration.",
|
|
268
319
|
"device-no-ptz":
|
|
269
320
|
"This camera cannot move, so there is nothing to switch on. A different camera would be needed.",
|
|
270
321
|
"no-recorder-configured":
|
|
271
|
-
"
|
|
322
|
+
"Not switchable from this page. This camera's video service has no recorder linked to it in the server's configuration — your Seven365 administrator adds it.",
|
|
272
323
|
"no-channel-in-address":
|
|
273
324
|
"This camera's address does not say which stream it is. Correct it in Site Settings, under CCTV.",
|
|
274
325
|
"not-a-relay-player-url":
|
|
@@ -292,7 +343,7 @@ export const CAPABILITY_NEXT_STEPS: Record<string, string> = {
|
|
|
292
343
|
* setting on this page, and there is still somebody to ask.
|
|
293
344
|
*/
|
|
294
345
|
const NEXT_STEP_FALLBACK =
|
|
295
|
-
"
|
|
346
|
+
"Not switchable from this page — it needs a change to the server's configuration, which your Seven365 administrator makes.";
|
|
296
347
|
|
|
297
348
|
/**
|
|
298
349
|
* The capabilities the wall draws a control for, and their plain names.
|