@7365admin1/layer-common 4.64.2 → 4.64.4

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.64.4
4
+
5
+ ### Patch Changes
6
+
7
+ - d47f886: Invite member: when the Role list cannot be loaded (for example no access to the organisation's roles), it says so instead of "No roles have been created for this site yet".
8
+
9
+ ## 4.64.3
10
+
11
+ ### Patch Changes
12
+
13
+ - ed34f76: Invite member: "Create more" keeps the same app and site, so the Role list after an invitation is the same as before it (it used to switch to the organisation-type roles). When no role exists for the site, the list says so and links to Roles & Permissions.
14
+
3
15
  ## 4.64.2
4
16
 
5
17
  ### Patch Changes
@@ -1709,11 +1721,11 @@
1709
1721
  `utils/console-tier.ts` + `composables/useConsoleTier.ts` mirror the server's
1710
1722
  own rule from two endpoints the console already calls, unprojected:
1711
1723
 
1712
- GET /api/members/user/:user/app/admin the Seven365 staff membership
1713
- GET /api/roles/id/:role that membership's role document
1724
+ GET /api/members/user/:user/app/admin the Seven365 staff membership
1725
+ GET /api/roles/id/:role that membership's role document
1714
1726
 
1715
- owner = member.type === "admin" && role.type === "admin" && role.default === true
1716
- staff = member.type === "admin" && role.type === "admin"
1727
+ owner = member.type === "admin" && role.type === "admin" && role.default === true
1728
+ staff = member.type === "admin" && role.type === "admin"
1717
1729
 
1718
1730
  `role.default` is the marker because it is the only property of a platform
1719
1731
  staff role no API caller can set - `role.controller.ts` validates create and
@@ -53,7 +53,18 @@
53
53
  :rules="[requiredRule]"
54
54
  class="filter-field"
55
55
  density="comfortable"
56
- ></v-autocomplete>
56
+ >
57
+ <template #no-data>
58
+ <v-list-item data-test="invite-no-roles">
59
+ <v-list-item-title class="text-wrap">
60
+ {{ noRolesText }}
61
+ </v-list-item-title>
62
+ <NuxtLink v-if="rolesPageLink && !rolesError" :to="rolesPageLink">
63
+ Open Roles &amp; Permissions
64
+ </NuxtLink>
65
+ </v-list-item>
66
+ </template>
67
+ </v-autocomplete>
57
68
  </v-col>
58
69
  </v-row>
59
70
  </v-col>
@@ -248,6 +259,17 @@ const loading = reactive({
248
259
  verifyingEmail: false,
249
260
  });
250
261
 
262
+ /*
263
+ * The app this form invites into when it opens. "Create more" resets to THIS,
264
+ * never to a literal: it used to reset to "organization", so after the first
265
+ * invitation the Role list switched to the organisation-type roles ("Site
266
+ * Admin", "Org Admin") and this site's own roles vanished (owner report
267
+ * 2026-09-28, Wing Tai / The LakeGarden Residences).
268
+ */
269
+ function initialApp() {
270
+ return props.adminState ? (props.app || "") : "property_management_agency"
271
+ }
272
+
251
273
  const invite = ref<Record<string, any>>({
252
274
  email: "",
253
275
  app: "",
@@ -274,9 +296,7 @@ watch(
274
296
  * ORGANISATION-admin invitation, which is a separate flow, and changing it
275
297
  * here would move where those members land.
276
298
  */
277
- invite.value.app = props.adminState
278
- ? (props.app || "")
279
- : "property_management_agency"
299
+ invite.value.app = initialApp()
280
300
  },
281
301
  { immediate: true }
282
302
  )
@@ -454,7 +474,7 @@ const { getInvitableRoles } = useRole();
454
474
  * templates are gone from any invitation that names an organisation - the
455
475
  * server refuses them there (`core roleInvitable`).
456
476
  */
457
- const { data: RolesData, refresh: refreshRoles } = await useLazyAsyncData(
477
+ const { data: RolesData, refresh: refreshRoles, error: rolesError } = await useLazyAsyncData(
458
478
  "get-roles-by-type-" + props.org + "-" + props.app + "-" + fixedSite.value,
459
479
  () =>
460
480
  getInvitableRoles({
@@ -481,6 +501,27 @@ watchEffect(() => {
481
501
 
482
502
  const roleOptions = computed(() => inviteRoleOptions(roles.value));
483
503
 
504
+ const noRolesText = computed(() =>
505
+ rolesError?.value
506
+ ? "The roles could not be loaded. You may not have access to this organisation's roles; refresh, or sign in again."
507
+ : fixedSite.value
508
+ ? "No roles have been created for this site yet. Create one in Roles & Permissions first."
509
+ : "No roles have been created yet. Create one in Roles & Permissions first."
510
+ );
511
+
512
+ /* This screen's own Roles & Permissions page, when the app has one. */
513
+ const route = useRoute();
514
+ const router = useRouter();
515
+ const rolesPageLink = computed(() => {
516
+ const path = route.path.replace(/\/invitations(\/.*)?$/, "/roles-permissions");
517
+ if (path === route.path) return "";
518
+ try {
519
+ return router.resolve(path).matched.length ? path : "";
520
+ } catch {
521
+ return "";
522
+ }
523
+ });
524
+
484
525
  async function handleUpdateApp(value: string) {
485
526
  invite.value.role = "";
486
527
  if (!fixedSite.value) {
@@ -499,8 +540,11 @@ const message = ref("");
499
540
 
500
541
  function resetInvite() {
501
542
  invite.value.email = "";
502
- invite.value.app = "organization";
543
+ invite.value.app = initialApp();
503
544
  invite.value.role = "";
545
+ // Same site as before: a fixed site stays fixed, a picked one is cleared.
546
+ invite.value.site = fixedSite.value;
547
+ if (!invite.value.site) invite.value.siteName = "";
504
548
  message.value = "";
505
549
  }
506
550
 
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.64.2",
5
+ "version": "4.64.4",
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.",