@7365admin1/layer-common 3.2.8-staging.216 → 3.2.8-staging.219

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.
@@ -180,10 +180,6 @@
180
180
  <script setup lang="ts">
181
181
  import QrcodeVue from "qrcode.vue";
182
182
 
183
- definePageMeta({
184
- middleware: ["01-auth", "02-org"],
185
- memberOnly: true,
186
- });
187
183
 
188
184
  const props = defineProps({
189
185
  canViewAllQrTagging: {
@@ -138,10 +138,6 @@
138
138
  // into the consuming apps but not reliably into the layer's own components.
139
139
  import { readListPage } from "../utils/list-page";
140
140
 
141
- definePageMeta({
142
- middleware: ["01-auth", "02-org"],
143
- memberOnly: true,
144
- });
145
141
  const props = defineProps({
146
142
  headers: {
147
143
  type: Array as PropType<Array<Record<string, any>>>,
@@ -162,10 +162,6 @@
162
162
  // into the consuming apps but not reliably into the layer's own components.
163
163
  import { levelCount } from "../../utils/data";
164
164
 
165
- definePageMeta({
166
- middleware: ["01-auth", "02-org"],
167
- memberOnly: true,
168
- });
169
165
 
170
166
  const props = defineProps({
171
167
  headers: {
@@ -89,9 +89,6 @@ import { APP_CONSTANTS } from '../constants/app';
89
89
  // is a ReferenceError that blanks the screen in every consuming app.
90
90
  import { readListPage } from '../utils/list-page';
91
91
 
92
- definePageMeta({
93
- memberOnly: true,
94
- })
95
92
 
96
93
  const props = defineProps({
97
94
  siteId: {
@@ -610,10 +610,6 @@
610
610
  // into the consuming apps but not reliably into the layer's own components.
611
611
  import { readListPage } from "../utils/list-page";
612
612
 
613
- definePageMeta({
614
- middleware: ["01-auth", "02-org"],
615
- memberOnly: true,
616
- });
617
613
  const props = defineProps({
618
614
  headers: {
619
615
  type: Array as PropType<Array<Record<string, any>>>,
@@ -213,10 +213,6 @@
213
213
  </style>
214
214
 
215
215
  <script lang="ts" setup>
216
- definePageMeta({
217
- middleware: ["01-auth", "02-org"],
218
- memberOnly: true,
219
- });
220
216
 
221
217
  // imports
222
218
 
@@ -249,10 +249,6 @@
249
249
  </template>
250
250
 
251
251
  <script lang="ts" setup>
252
- definePageMeta({
253
- middleware: ["01-auth", "02-org"],
254
- memberOnly: true,
255
- });
256
252
 
257
253
  // props
258
254
  const props = defineProps({
@@ -155,10 +155,6 @@
155
155
  </template>
156
156
 
157
157
  <script lang="ts" setup>
158
- definePageMeta({
159
- middleware: ["01-auth", "02-org"],
160
- memberOnly: true,
161
- });
162
158
 
163
159
  // props
164
160
  const props = defineProps({
@@ -97,10 +97,6 @@
97
97
  </style>
98
98
 
99
99
  <script lang="ts" setup>
100
- definePageMeta({
101
- middleware: ["01-auth", "02-org"],
102
- memberOnly: true,
103
- });
104
100
 
105
101
  // imports
106
102
 
@@ -84,8 +84,16 @@
84
84
  {{ formatDateInvited(item.dateInvited) }}
85
85
  </template>
86
86
  <template #item.action-table="{ item }">
87
+ <!--
88
+ `props.assignRole` belongs in this test. The menu's only item that
89
+ is not status-dependent is Assign Role, but the menu itself opened
90
+ only for suspend / activate / delete -- so a role granted
91
+ `members:assign-member-role` and nothing else got no menu at all,
92
+ and the permission was unreachable.
93
+ -->
87
94
  <v-menu
88
95
  v-if="
96
+ props.assignRole ||
89
97
  (currentStatus === 'active' &&
90
98
  (canSuspendMembers || canDeleteMembers)) ||
91
99
  (currentStatus === 'suspended' &&
@@ -317,7 +317,12 @@ async function submit() {
317
317
  });
318
318
  emit("success");
319
319
  } catch (error: any) {
320
- message.value = error.response._data.message;
320
+ // Same unguarded chain as the preview dialog had: on a network or timeout
321
+ // failure `error.response` is undefined and the catch threw inside itself,
322
+ // leaving the user with no message at all.
323
+ message.value =
324
+ error?.response?._data?.message ??
325
+ "Could not create this role. Please check your connection and try again.";
321
326
  } finally {
322
327
  disable.value = false;
323
328
  }
@@ -99,15 +99,12 @@
99
99
  </div>
100
100
  </v-col>
101
101
 
102
- <v-col v-if="edit" cols="12" class="my-2">
103
- <v-row no-gutters>
104
- <v-col cols="12" class="text-center">
105
- <span class="role-perm__error">{{ message }}</span>
106
- </v-col>
107
- </v-row>
108
- </v-col>
109
-
110
- <v-col cols="12" class="my-2">
102
+ <!--
103
+ One message, once. This block used to appear twice -- inside
104
+ `v-if="edit"` and again unconditionally -- so a refused save printed
105
+ the server's sentence back to back.
106
+ -->
107
+ <v-col v-if="message" cols="12" class="my-2">
111
108
  <v-row no-gutters>
112
109
  <v-col cols="12" class="text-center">
113
110
  <span class="role-perm__error">{{ message }}</span>
@@ -122,7 +119,7 @@
122
119
  <AppButton v-if="!edit" variant="ghost" @click="emit('cancel')">Close</AppButton>
123
120
  <AppButton v-else variant="ghost" @click="edit = false">Cancel</AppButton>
124
121
 
125
- <AppButton v-if="!edit" :disabled="disable" @click="edit = true">Edit</AppButton>
122
+ <AppButton v-if="!edit && canUpdateRole" :disabled="disable" @click="edit = true">Edit</AppButton>
126
123
  <AppButton v-else :disabled="Boolean(errorMessages) || disable" @click="submit()">
127
124
  Submit
128
125
  </AppButton>
@@ -159,6 +156,15 @@ const props = defineProps({
159
156
  type: Array as PropType<string[]>,
160
157
  default: () => [],
161
158
  },
159
+ // "Update role". This dialog had no permission prop at all, so it showed Edit
160
+ // to everyone -- including on the seeded platform-owner role -- and the
161
+ // `canUpdateRole` the apps have been passing to `RolePermissionMain` in good
162
+ // faith did nothing. `RolePermissionMain` is the only thing that renders this
163
+ // dialog and always passes it, so the default is closed.
164
+ canUpdateRole: {
165
+ type: Boolean,
166
+ default: false,
167
+ },
162
168
  });
163
169
 
164
170
  const validForm = ref(false);
@@ -282,7 +288,12 @@ async function submit() {
282
288
  await updatePermissionById(props.id, definedModel.value);
283
289
  emit("success");
284
290
  } catch (error: any) {
285
- message.value = error.response._data.message;
291
+ // `error.response` is undefined on a network or timeout failure, so the old
292
+ // unguarded chain threw inside its own catch: nothing was shown, the button
293
+ // came back enabled, and the save looked like it had simply been ignored.
294
+ message.value =
295
+ error?.response?._data?.message ??
296
+ "Could not save this role. Please check your connection and try again.";
286
297
  } finally {
287
298
  disable.value = false;
288
299
  }
@@ -42,12 +42,13 @@
42
42
 
43
43
  <v-data-table
44
44
  :headers="props.headers"
45
- :items="items"
45
+ :items="visibleItems"
46
46
  item-value="_id"
47
47
  items-per-page="20"
48
48
  fixed-header
49
49
  hide-default-footer
50
50
  hide-default-header
51
+ :no-data-text="emptyText"
51
52
  @click:row="tableRowClickHandler"
52
53
  style="max-height: calc(100vh - (180px))"
53
54
  >
@@ -102,6 +103,7 @@
102
103
  v-model:edit="edit"
103
104
  :name="name"
104
105
  :id="roleId"
106
+ :can-update-role="props.canUpdateRole"
105
107
  :web-only-resources="props.webOnlyResources"
106
108
  />
107
109
  </v-dialog>
@@ -245,13 +247,18 @@ const props = defineProps({
245
247
  type: Boolean,
246
248
  default: false,
247
249
  },
250
+ // "See all roles". Defaults to `true` because nine of the ten pages that
251
+ // render this component do not pass it, and until now nothing read it at all
252
+ // -- so `true` is exactly what those pages have always had. The one page that
253
+ // does pass it now gets a gate that works.
248
254
  canViewRole: {
249
255
  type: Boolean,
250
- default: false,
256
+ default: true,
251
257
  },
258
+ // "See role details" -- opening a role. Same reasoning as `canViewRole`.
252
259
  canViewByRole: {
253
260
  type: Boolean,
254
- default: false,
261
+ default: true,
255
262
  },
256
263
  canDeleteRole: {
257
264
  type: Boolean,
@@ -281,6 +288,7 @@ const {
281
288
  data: getRoleReq,
282
289
  refresh: getRoles,
283
290
  status: getRoleReqStatus,
291
+ error: getRoleReqError,
284
292
  } = useLazyAsyncData(
285
293
  "roles-permissions-get-all",
286
294
  () =>
@@ -305,7 +313,33 @@ watchEffect(() => {
305
313
  }
306
314
  });
307
315
 
316
+ // "See all roles". Without it the list is not drawn at all, and `emptyText`
317
+ // below says so rather than leaving a blank table to be read as a failure.
318
+ const visibleItems = computed(() => (props.canViewRole ? items.value : []));
319
+
320
+ /**
321
+ * SAY WHY THE TABLE IS EMPTY. "No data available" was shown for three
322
+ * different situations -- you may not see roles, the request failed, and this
323
+ * organisation genuinely has none -- so a refusal was indistinguishable from an
324
+ * empty list and neither was distinguishable from a broken screen.
325
+ */
326
+ const emptyText = computed(() => {
327
+ if (!props.canViewRole) return "You do not have permission to view roles.";
328
+ const status = (getRoleReqError.value as any)?.response?.status
329
+ ?? (getRoleReqError.value as any)?.statusCode;
330
+ if (status === 401 || status === 403) {
331
+ return "You do not have permission to view the roles for this organisation.";
332
+ }
333
+ if (getRoleReqError.value) {
334
+ return "Could not load roles. Please refresh to try again.";
335
+ }
336
+ return "No roles have been created yet.";
337
+ });
338
+
308
339
  function tableRowClickHandler(_: any, data: any) {
340
+ // "See role details". Ungated until now, which is why granting or withholding
341
+ // it changed nothing.
342
+ if (!props.canViewByRole) return;
309
343
  previewDialog.value = true;
310
344
  roleId.value = data.item._id;
311
345
  }
@@ -167,10 +167,6 @@
167
167
  import useUtils from '../composables/useUtils';
168
168
  import useVehicle from '../composables/useVehicle';
169
169
 
170
- definePageMeta({
171
- middleware: ["01-auth", "02-org"],
172
- memberOnly: true,
173
- })
174
170
 
175
171
 
176
172
  const props = defineProps({
@@ -1226,9 +1226,6 @@
1226
1226
  import moment from "moment-timezone";
1227
1227
  import QRCode from "qrcode";
1228
1228
 
1229
- definePageMeta({
1230
- middleware: ["01-auth", "02-org"],
1231
- });
1232
1229
 
1233
1230
  const { downloadPDF } = usePDFDownload();
1234
1231
 
@@ -115,9 +115,6 @@ import useUtils from '../composables/useUtils';
115
115
  import useSite from '../composables/useSite';
116
116
 
117
117
 
118
- definePageMeta({
119
- middleware: ["01-auth", "02-org"],
120
- });
121
118
 
122
119
 
123
120
  const props = defineProps({
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@7365admin1/layer-common",
3
3
  "license": "MIT",
4
4
  "type": "module",
5
- "version": "3.2.8-staging.216",
5
+ "version": "3.2.8-staging.219",
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.",