@7365admin1/layer-common 4.64.2 → 4.64.3

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,11 @@
1
1
  # @iservice365/layer-common
2
2
 
3
+ ## 4.64.3
4
+
5
+ ### Patch Changes
6
+
7
+ - 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.
8
+
3
9
  ## 4.64.2
4
10
 
5
11
  ### Patch Changes
@@ -1709,11 +1715,11 @@
1709
1715
  `utils/console-tier.ts` + `composables/useConsoleTier.ts` mirror the server's
1710
1716
  own rule from two endpoints the console already calls, unprojected:
1711
1717
 
1712
- GET /api/members/user/:user/app/admin the Seven365 staff membership
1713
- GET /api/roles/id/:role that membership's role document
1718
+ GET /api/members/user/:user/app/admin the Seven365 staff membership
1719
+ GET /api/roles/id/:role that membership's role document
1714
1720
 
1715
- owner = member.type === "admin" && role.type === "admin" && role.default === true
1716
- staff = member.type === "admin" && role.type === "admin"
1721
+ owner = member.type === "admin" && role.type === "admin" && role.default === true
1722
+ staff = member.type === "admin" && role.type === "admin"
1717
1723
 
1718
1724
  `role.default` is the marker because it is the only property of a platform
1719
1725
  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" :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
  )
@@ -481,6 +501,25 @@ watchEffect(() => {
481
501
 
482
502
  const roleOptions = computed(() => inviteRoleOptions(roles.value));
483
503
 
504
+ const noRolesText = computed(() =>
505
+ fixedSite.value
506
+ ? "No roles have been created for this site yet. Create one in Roles & Permissions first."
507
+ : "No roles have been created yet. Create one in Roles & Permissions first."
508
+ );
509
+
510
+ /* This screen's own Roles & Permissions page, when the app has one. */
511
+ const route = useRoute();
512
+ const router = useRouter();
513
+ const rolesPageLink = computed(() => {
514
+ const path = route.path.replace(/\/invitations(\/.*)?$/, "/roles-permissions");
515
+ if (path === route.path) return "";
516
+ try {
517
+ return router.resolve(path).matched.length ? path : "";
518
+ } catch {
519
+ return "";
520
+ }
521
+ });
522
+
484
523
  async function handleUpdateApp(value: string) {
485
524
  invite.value.role = "";
486
525
  if (!fixedSite.value) {
@@ -499,8 +538,11 @@ const message = ref("");
499
538
 
500
539
  function resetInvite() {
501
540
  invite.value.email = "";
502
- invite.value.app = "organization";
541
+ invite.value.app = initialApp();
503
542
  invite.value.role = "";
543
+ // Same site as before: a fixed site stays fixed, a picked one is cleared.
544
+ invite.value.site = fixedSite.value;
545
+ if (!invite.value.site) invite.value.siteName = "";
504
546
  message.value = "";
505
547
  }
506
548
 
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.3",
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.",