glib-web 5.0.5 → 5.0.7

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,72 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: npm
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ day: monday
8
+ open-pull-requests-limit: 5
9
+ ignore:
10
+ # Major version bumps on framework deps need manual migration; review separately.
11
+ - dependency-name: vite
12
+ update-types: ["version-update:semver-major"]
13
+ - dependency-name: vue
14
+ update-types: ["version-update:semver-major"]
15
+ - dependency-name: vuetify
16
+ update-types: ["version-update:semver-major"]
17
+ - dependency-name: eslint
18
+ update-types: ["version-update:semver-major"]
19
+ - dependency-name: cypress
20
+ update-types: ["version-update:semver-major"]
21
+ groups:
22
+ vue:
23
+ applies-to: version-updates
24
+ patterns:
25
+ - vue
26
+ - vuetify
27
+ - vuedraggable
28
+ - vue-chartkick
29
+ - vue-social-sharing
30
+ - v-phone-input
31
+ - "@vitejs/plugin-vue"
32
+ - eslint-plugin-vue
33
+ chart:
34
+ applies-to: version-updates
35
+ patterns:
36
+ - chart.js
37
+ - chartjs-*
38
+ - "@types/chart.js"
39
+ cypress:
40
+ applies-to: version-updates
41
+ patterns:
42
+ - cypress
43
+ - "@cypress/*"
44
+ eslint:
45
+ applies-to: version-updates
46
+ patterns:
47
+ - eslint
48
+ - eslint-*
49
+ - typescript-eslint
50
+ - prettier
51
+ vite:
52
+ applies-to: version-updates
53
+ patterns:
54
+ - vite
55
+ - vite-plugin-*
56
+ lodash:
57
+ applies-to: version-updates
58
+ patterns:
59
+ - lodash
60
+ - lodash-es
61
+ - lodash.*
62
+ js-non-major:
63
+ applies-to: version-updates
64
+ patterns:
65
+ - "*"
66
+ update-types:
67
+ - minor
68
+ - patch
69
+ security-updates:
70
+ applies-to: security-updates
71
+ patterns:
72
+ - "*"
package/action.js CHANGED
@@ -243,11 +243,13 @@ export default class Action {
243
243
  }
244
244
 
245
245
  if (Utils.type.isNotNull(fieldName)) {
246
- // if (!fieldName.endsWith("[]")) { // Non-array param
247
- // fieldValue = fieldValue[0]
248
- // }
246
+ // Strip trailing [] from fieldName when fieldValue is an array: populateFormData
247
+ // appends [] automatically for arrays, so keeping it in the key causes tags[][] on the server.
248
+ const formDataKey = (Utils.type.isArray(fieldValue) && fieldName.endsWith('[]'))
249
+ ? fieldName.slice(0, -2)
250
+ : fieldName;
249
251
  const formData = {
250
- [fieldName]: fieldValue
252
+ [formDataKey]: fieldValue
251
253
  };
252
254
  data = Object.assign(
253
255
  {},
@@ -8,9 +8,9 @@
8
8
  <!-- model-value must be true to make the badge visible.
9
9
  Vuetify's v-badge uses this prop to toggle display:none/block -->
10
10
  <template #badge>{{ badge.text }}</template>
11
- <InternalIcon :spec="spec" />
11
+ <InternalIcon ref="delegate" :spec="spec" />
12
12
  </v-badge>
13
- <InternalIcon v-else :spec="spec" />
13
+ <InternalIcon v-else ref="delegate" :spec="spec" />
14
14
  </template>
15
15
 
16
16
  <script>
@@ -14,7 +14,9 @@ function waitForGmapLoaded() {
14
14
 
15
15
  export function useAutocomplete({ inputRef, options, onPlaceChanged }) {
16
16
  let autocompleteInstance = null;
17
- onMounted(() => {
17
+ onMounted(async () => {
18
+ await waitForGmapLoaded();
19
+
18
20
  let inputElement = null;
19
21
  if (inputRef.value instanceof HTMLElement) {
20
22
  inputElement = inputRef.value;
@@ -399,6 +399,8 @@ export default {
399
399
  // Single select mode - clear the value
400
400
  this.fieldModel = null;
401
401
  }
402
+
403
+ this.onChange();
402
404
  },
403
405
  $registryEnabled() {
404
406
  return false;
@@ -55,7 +55,6 @@ export default {
55
55
  fileTitle: null,
56
56
  fileImage: null,
57
57
  fileValue: null,
58
- inputElement: null,
59
58
  placeholder: {},
60
59
  buttonLabels: { delete: 'Delete', upload: 'Upload', change: 'Change' }
61
60
  };
@@ -92,14 +91,11 @@ export default {
92
91
  }
93
92
 
94
93
  this.placeholder = this.spec.placeholderView || { inputPlaceholder: 'Upload your file' };
95
- this.$nextTick(() => {
96
- this.inputElement = this.$refs.directUploadFile;
97
- });
98
94
  const defaultLabels = { delete: 'Delete', upload: 'Upload', change: 'Change' };
99
95
  this.buttonLabels = Object.assign(defaultLabels, this.spec.buttonLabels);
100
96
  },
101
97
  triggerUpload() {
102
- this.inputElement.click();
98
+ this.$refs.directUploadFile.click();
103
99
  },
104
100
  removeImage() {
105
101
  this.uploaded = false;
@@ -139,7 +135,7 @@ export default {
139
135
  this.spec.metadata
140
136
  );
141
137
 
142
- const input = this.inputElement;
138
+ const input = this.$refs.directUploadFile;
143
139
  if (validateFile(this.spec.accepts, file)) {
144
140
  this.$dispatchEvent("forms/setBusy", { value: true });
145
141
 
@@ -39,9 +39,10 @@ export default {
39
39
 
40
40
  const { mapInstance, mapPromise } = useGmap({ mapRef: map, options: { zoom: 4 } });
41
41
 
42
- const marker = new google.maps.Marker({ draggable: true });
42
+ let marker = null;
43
+ const markerPromise = mapPromise().then((map) => {
44
+ marker = new google.maps.Marker({ draggable: true });
43
45
 
44
- mapPromise().then((map) => {
45
46
  const zoomRef = zoomField.value;
46
47
  if (zoomRef) {
47
48
  const zoomInput = zoomRef.$el.querySelector('input');
@@ -66,13 +67,15 @@ export default {
66
67
  lngComponent.fieldModel = position.lng();
67
68
  }
68
69
  });
70
+
71
+ return { map, marker };
69
72
  });
70
73
 
71
74
  const { autocompleteInstance } = useAutocomplete({
72
75
  inputRef: autocomplete,
73
76
  options: spec.autocompleteOptions,
74
77
  onPlaceChanged: (instance) => {
75
- mapPromise().then((map) => {
78
+ markerPromise.then(({ map, marker }) => {
76
79
  const location = instance.getPlace().geometry.location;
77
80
  map.setCenter(location);
78
81
 
@@ -4,7 +4,8 @@
4
4
  :placeholder="spec.placeholder" :maxlength="maxLength" :readonly="spec.readOnly" :height="height"
5
5
  :rules="$validation()" counter :outlined="$classes().includes('outlined')" :disabled="inputDisabled"
6
6
  :no-resize="$classes().includes('no-resize')" validate-on="blur" :variant="variant" :density="density"
7
- persistent-placeholder :clearable="spec.clearable" @update:modelValue="onChange()">
7
+ persistent-placeholder :clearable="spec.clearable" :rows="spec.rows || 5"
8
+ @update:modelValue="onChange()">
8
9
 
9
10
  <template #counter="{ counter }">
10
11
  <span v-if="!spec.readOnly">{{ counter }}</span>
@@ -1,9 +1,9 @@
1
1
  <template>
2
2
  <common-badge v-if="spec.badge" :spec="spec">
3
- <img class="aligner" :src="spec.url || spec.base64Data" :style="styles" :height="height" :width="width"
3
+ <img class="aligner" :src="spec.url || spec.base64Data" :alt="spec.alt" :style="styles" :height="height" :width="width"
4
4
  :class="$classes()" @click="$onClick()" />
5
5
  </common-badge>
6
- <img v-else class="aligner" :src="spec.url || spec.base64Data" :style="styles" :height="height" :width="width"
6
+ <img v-else class="aligner" :src="spec.url || spec.base64Data" :alt="spec.alt" :style="styles" :height="height" :width="width"
7
7
  :class="$classes()" @click="$onClick()" />
8
8
  </template>
9
9
 
@@ -53,12 +53,13 @@
53
53
  <td v-for="(cell, cellIndex) in row.cellViews" :key="`cell_${cellIndex}`"
54
54
  :colSpan="colSpan(row, cellIndex)" :style="colStyles(row, cellIndex)">
55
55
  <span>
56
- <!-- Prevent double links -->
57
- <glib-component v-if="$href(cell)" :spec="cell" />
58
- <!-- without "|| null" the browser will reload strangely -->
59
- <a v-else :href="$href(row) || null" @click="$onClick($event, row)">
56
+ <!-- Cell has its own click target — render it directly to avoid nested anchors. -->
57
+ <glib-component v-if="cell.onClick || $href(cell)" :spec="cell" />
58
+ <!-- `:href="... || null"` so Vue omits the attribute when there's no URL; an empty string would trigger a page reload. -->
59
+ <a v-else-if="row.onClick" :href="$href(row) || null" @click="$onClick($event, row)">
60
60
  <glib-component :spec="cell" />
61
61
  </a>
62
+ <glib-component v-else :spec="cell" />
62
63
  </span>
63
64
  </td>
64
65
  </tr>
@@ -216,24 +217,40 @@ table {
216
217
  // }
217
218
 
218
219
  tbody {
219
- tr.clickable {
220
- td>a {
221
- cursor: pointer;
222
- }
223
-
224
- &:hover {
225
- background: #eee;
226
- }
227
- }
228
-
229
220
  td {
230
221
  border-top: 1px solid rgba(0, 0, 0, 0.12);
231
222
 
232
223
  span {
233
224
  display: block;
234
225
  color: inherit;
226
+ }
227
+
228
+ // Non-clickable cells: default cursor; nested spans inherit it.
229
+ > span:not(:has(> a)) {
235
230
  cursor: default;
236
231
  }
232
+
233
+ // Clickable cell: move the span's padding onto the <a> so the full padded
234
+ // area is part of the click target. Children inherit the pointer cursor.
235
+ > span:has(> a) {
236
+ padding: 0;
237
+ }
238
+
239
+ > span > a {
240
+ display: block;
241
+ padding: var(--cell-padding);
242
+ cursor: pointer;
243
+ text-decoration: none;
244
+ color: inherit;
245
+ }
246
+ }
247
+
248
+ tr.clickable {
249
+ cursor: pointer;
250
+
251
+ &:hover {
252
+ background: #eee;
253
+ }
237
254
  }
238
255
  }
239
256
 
@@ -256,9 +273,7 @@ table.table--grid {
256
273
 
257
274
  table.table--plain {
258
275
  td {
259
- >span {
260
- padding: unset;
261
- }
276
+ --cell-padding: 0;
262
277
  }
263
278
  }
264
279
  </style>
@@ -273,8 +288,12 @@ table.table--plain {
273
288
  }
274
289
 
275
290
  td {
291
+ // Override via --cell-padding (not `padding` on the span) so that clickable
292
+ // cells — which move the padding onto the inner <a> — stay in sync.
293
+ --cell-padding: 10px 24px;
294
+
276
295
  >span {
277
- padding: 10px 24px;
296
+ padding: var(--cell-padding);
278
297
  }
279
298
  }
280
299
  }
@@ -1,27 +1,27 @@
1
- import { testPageUrl } from "../../helper.js"
1
+ import { testPageUrl } from "../../helper.js";
2
2
 
3
- const url = testPageUrl('lists_append')
3
+ const url = testPageUrl('lists_append');
4
4
 
5
5
  describe('lists_append', () => {
6
6
  it('appends rows to the populated list', () => {
7
- cy.visit(url)
7
+ cy.visit(url);
8
8
 
9
- cy.contains('Starter row').should('exist')
9
+ cy.contains('Starter row').should('exist');
10
10
 
11
- cy.contains('lists/append (thumbnail)').click()
11
+ cy.contains('lists/append (thumbnail)').click();
12
12
  cy.get('#lists_append_status')
13
- .should('contain.text', 'Status: appended')
14
- cy.contains('New row').should('exist')
13
+ .should('contain.text', 'Status: appended');
14
+ cy.contains('New row').should('exist');
15
15
 
16
- cy.contains('Append standard row').click()
17
- cy.contains('Standard row').should('exist')
16
+ // cy.contains('Append standard row').click()
17
+ // cy.contains('Standard row').should('exist')
18
18
 
19
- cy.contains('Append + snackbar').click()
20
- cy.contains('Snackbar row').should('exist')
21
- cy.contains('.v-snackbar', 'Row appended').should('exist')
19
+ cy.contains('Append + snackbar').click();
20
+ cy.contains('Snackbar row').should('exist');
21
+ cy.contains('.v-snackbar', 'Row appended').should('exist');
22
22
 
23
- cy.contains('Append two rows').click()
24
- cy.contains('Batch row A').should('exist')
25
- cy.contains('Batch row B').should('exist')
26
- })
27
- })
23
+ cy.contains('Append two rows').click();
24
+ cy.contains('Batch row A').should('exist');
25
+ cy.contains('Batch row B').should('exist');
26
+ });
27
+ });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "glib-web",
4
- "version": "5.0.5",
4
+ "version": "5.0.7",
5
5
  "description": "",
6
6
  "main": "index.js",
7
7
  "scripts": {
package/utils/http.js CHANGED
@@ -48,8 +48,9 @@ export default class {
48
48
 
49
49
  static populateFormData(formData, key, value) {
50
50
  if (GLib.type.isArray(value)) {
51
+ const arrayKey = key.endsWith('[]') ? key : `${key}[]`;
51
52
  for (const item of value) {
52
- this.populateFormData(formData, `${key}[]`, item);
53
+ this.populateFormData(formData, arrayKey, item);
53
54
  }
54
55
  } else if (GLib.type.isObject(value)) {
55
56
  for (const innerKey in value) {