@conduction/nextcloud-vue 0.1.0-beta.16 → 0.1.0-beta.18

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.
@@ -26,6 +26,7 @@ var Vue = require('vue');
26
26
  var ContentSaveOutline = require('vue-material-design-icons/ContentSaveOutline.vue');
27
27
  var AlertCircle = require('vue-material-design-icons/AlertCircle.vue');
28
28
  var Alert = require('vue-material-design-icons/Alert.vue');
29
+ var PencilOutline = require('vue-material-design-icons/PencilOutline.vue');
29
30
  var LockOutline = require('vue-material-design-icons/LockOutline.vue');
30
31
  var Tooltip = require('@nextcloud/vue/dist/Directives/Tooltip.js');
31
32
  var pinia = require('pinia');
@@ -8474,7 +8475,7 @@ var script$R = {
8474
8475
  computed: {
8475
8476
  itemName() {
8476
8477
  if (this.nameFormatter) return this.nameFormatter(this.item)
8477
- return this.item[this.nameField] || this.item.name || this.item.title || this.item.id
8478
+ return this.item[this.nameField] || this.item.name || this.item.naam || this.item.title || this.item.id
8478
8479
  },
8479
8480
  resolvedWarningText() {
8480
8481
  return this.warningText.replace('{name}', this.itemName)
@@ -8635,7 +8636,7 @@ __vue_render__$R._withStripped = true;
8635
8636
  /* style */
8636
8637
  const __vue_inject_styles__$R = undefined;
8637
8638
  /* scoped */
8638
- const __vue_scope_id__$R = "data-v-4fc24979";
8639
+ const __vue_scope_id__$R = "data-v-a85683fa";
8639
8640
  /* module identifier */
8640
8641
  const __vue_module_identifier__$R = undefined;
8641
8642
  /* functional template */
@@ -46032,6 +46033,15 @@ var script$M = {
46032
46033
  datetimeValue() {
46033
46034
  const v = this.value;
46034
46035
  if (!v) return null
46036
+ // Date-only strings (YYYY-MM-DD) are parsed as UTC midnight by the spec,
46037
+ // which shifts to the previous day in positive-UTC-offset timezones when
46038
+ // fed to a picker that renders in local time. Parse them as local midnight.
46039
+ if (this.schemaProp?.format === 'date'
46040
+ && typeof v === 'string'
46041
+ && /^\d{4}-\d{2}-\d{2}$/.test(v)) {
46042
+ const [year, month, day] = v.split('-').map(Number);
46043
+ return new Date(year, month - 1, day)
46044
+ }
46035
46045
  const d = new Date(v);
46036
46046
  return Number.isNaN(d.getTime()) ? null : d
46037
46047
  },
@@ -46075,6 +46085,11 @@ var script$M = {
46075
46085
  const v = this.value;
46076
46086
  if (!v) return ''
46077
46087
  const fmt = this.schemaProp?.format;
46088
+ // Same local-midnight parse as datetimeValue to avoid UTC-shift in display.
46089
+ if (fmt === 'date' && typeof v === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(v)) {
46090
+ const [year, month, day] = v.split('-').map(Number);
46091
+ return new Date(year, month - 1, day).toLocaleDateString()
46092
+ }
46078
46093
  const d = new Date(v);
46079
46094
  if (Number.isNaN(d.getTime())) return String(v)
46080
46095
  if (fmt === 'date') return d.toLocaleDateString()
@@ -46144,7 +46159,12 @@ var script$M = {
46144
46159
  }
46145
46160
  const fmt = this.schemaProp?.format;
46146
46161
  if (fmt === 'date') {
46147
- this.$emit('update:value', date.toISOString().slice(0, 10));
46162
+ // Use local-time accessors — toISOString() converts to UTC first,
46163
+ // which shifts midnight local time to the previous day in UTC+n zones.
46164
+ const year = date.getFullYear();
46165
+ const month = String(date.getMonth() + 1).padStart(2, '0');
46166
+ const day = String(date.getDate()).padStart(2, '0');
46167
+ this.$emit('update:value', `${year}-${month}-${day}`);
46148
46168
  return
46149
46169
  }
46150
46170
  if (fmt === 'time') {
@@ -46827,7 +46847,7 @@ __vue_render__$M._withStripped = true;
46827
46847
  /* style */
46828
46848
  const __vue_inject_styles__$M = undefined;
46829
46849
  /* scoped */
46830
- const __vue_scope_id__$M = "data-v-55998c61";
46850
+ const __vue_scope_id__$M = "data-v-60085d3b";
46831
46851
  /* module identifier */
46832
46852
  const __vue_module_identifier__$M = undefined;
46833
46853
  /* functional template */
@@ -46971,14 +46991,24 @@ __vue_render__$M._withStripped = true;
46971
46991
  //
46972
46992
  //
46973
46993
  //
46994
+ //
46995
+ //
46996
+ //
46997
+ //
46998
+ //
46999
+ //
47000
+ //
47001
+ //
46974
47002
 
46975
47003
 
46976
47004
  var script$L = {
46977
47005
  name: 'CnPropertiesTab',
46978
47006
 
46979
47007
  components: {
47008
+ NcNoteCard: vue.NcNoteCard,
46980
47009
  AlertCircle,
46981
47010
  Alert,
47011
+ PencilOutline,
46982
47012
  LockOutline,
46983
47013
  Plus,
46984
47014
  CnPropertyValueCell: __vue_component__$M,
@@ -47015,9 +47045,14 @@ var script$L = {
47015
47045
  * Any other CSS color string is applied directly.
47016
47046
  */
47017
47047
  propCellColor: { type: String, default: null },
47048
+ isNew: { type: Boolean, default: false },
47018
47049
  },
47019
47050
 
47020
47051
  computed: {
47052
+ hasUnsavedChanges() {
47053
+ if (this.isNew) return false
47054
+ return Object.keys(this.formData).some(key => this.isValueChanged(key))
47055
+ },
47021
47056
  propCellStyle() {
47022
47057
  if (this.propCellColor === null) return undefined
47023
47058
  if (this.propCellColor === 'none') return { boxShadow: 'none' }
@@ -47104,7 +47139,7 @@ var script$L = {
47104
47139
  return { boxShadow: 'inset 3px 0 0 0 var(--color-error)' }
47105
47140
  }
47106
47141
  if (this.isValueChanged(key)) {
47107
- return { boxShadow: 'inset 3px 0 0 0 var(--color-warning)' }
47142
+ return { boxShadow: 'inset 3px 0 0 0 var(--color-primary-element)' }
47108
47143
  }
47109
47144
  if (state === 'valid') {
47110
47145
  return { boxShadow: 'inset 3px 0 0 0 var(--color-success)' }
@@ -47113,7 +47148,7 @@ var script$L = {
47113
47148
  return { boxShadow: 'inset 3px 0 0 0 var(--color-warning)' }
47114
47149
  }
47115
47150
  if (state === 'new') {
47116
- return { boxShadow: 'inset 3px 0 0 0 var(--color-primary-element)' }
47151
+ return { boxShadow: 'inset 3px 0 0 0 var(--color-new)' }
47117
47152
  }
47118
47153
  return this.propCellStyle
47119
47154
  },
@@ -47394,346 +47429,382 @@ var __vue_render__$L = function () {
47394
47429
  var _c = _vm._self._c || _h;
47395
47430
  return _c(
47396
47431
  "div",
47397
- { staticClass: "cn-advanced-form-dialog__table-container" },
47398
47432
  [
47399
- _c("table", { staticClass: "cn-advanced-form-dialog__table" }, [
47400
- _c("thead", [
47401
- _c("tr", { staticClass: "cn-advanced-form-dialog__table-row" }, [
47402
- _c(
47403
- "th",
47404
- { staticClass: "cn-advanced-form-dialog__table-col-constrained" },
47405
- [
47406
- _vm._v(
47407
- "\n\t\t\t\t\t" +
47408
- _vm._s(_vm.t("nextcloud-vue", "Property")) +
47409
- "\n\t\t\t\t"
47410
- ),
47411
- ]
47412
- ),
47413
- _vm._v(" "),
47414
- _c(
47415
- "th",
47416
- { staticClass: "cn-advanced-form-dialog__table-col-expanded" },
47417
- [
47418
- _vm._v(
47419
- "\n\t\t\t\t\t" +
47420
- _vm._s(_vm.t("nextcloud-vue", "Value")) +
47421
- "\n\t\t\t\t"
47422
- ),
47423
- ]
47424
- ),
47425
- _vm._v(" "),
47426
- _vm.hasRowActionsSlot
47427
- ? _c(
47428
- "th",
47429
- { staticClass: "cn-advanced-form-dialog__table-col-actions" },
47430
- [_vm._t("row-actions-header")],
47431
- 2
47432
- )
47433
- : _vm._e(),
47433
+ _vm.hasUnsavedChanges
47434
+ ? _c(
47435
+ "NcNoteCard",
47436
+ {
47437
+ staticClass: "cn-advanced-form-dialog__unsaved-note",
47438
+ attrs: { type: "warning" },
47439
+ },
47440
+ [
47441
+ _vm._v(
47442
+ "\n\t\t" +
47443
+ _vm._s(
47444
+ _vm.t(
47445
+ "nextcloud-vue",
47446
+ "You have unsaved changes. Save to apply them."
47447
+ )
47448
+ ) +
47449
+ "\n\t"
47450
+ ),
47451
+ ]
47452
+ )
47453
+ : _vm._e(),
47454
+ _vm._v(" "),
47455
+ _c("div", { staticClass: "cn-advanced-form-dialog__table-container" }, [
47456
+ _c("table", { staticClass: "cn-advanced-form-dialog__table" }, [
47457
+ _c("thead", [
47458
+ _c("tr", { staticClass: "cn-advanced-form-dialog__table-row" }, [
47459
+ _c(
47460
+ "th",
47461
+ {
47462
+ staticClass: "cn-advanced-form-dialog__table-col-constrained",
47463
+ },
47464
+ [
47465
+ _vm._v(
47466
+ "\n\t\t\t\t\t\t" +
47467
+ _vm._s(_vm.t("nextcloud-vue", "Property")) +
47468
+ "\n\t\t\t\t\t"
47469
+ ),
47470
+ ]
47471
+ ),
47472
+ _vm._v(" "),
47473
+ _c(
47474
+ "th",
47475
+ { staticClass: "cn-advanced-form-dialog__table-col-expanded" },
47476
+ [
47477
+ _vm._v(
47478
+ "\n\t\t\t\t\t\t" +
47479
+ _vm._s(_vm.t("nextcloud-vue", "Value")) +
47480
+ "\n\t\t\t\t\t"
47481
+ ),
47482
+ ]
47483
+ ),
47484
+ _vm._v(" "),
47485
+ _vm.hasRowActionsSlot
47486
+ ? _c(
47487
+ "th",
47488
+ {
47489
+ staticClass: "cn-advanced-form-dialog__table-col-actions",
47490
+ },
47491
+ [_vm._t("row-actions-header")],
47492
+ 2
47493
+ )
47494
+ : _vm._e(),
47495
+ ]),
47434
47496
  ]),
47435
- ]),
47436
- _vm._v(" "),
47437
- _c(
47438
- "tbody",
47439
- _vm._l(_vm.objectProperties, function (ref) {
47440
- var _obj;
47497
+ _vm._v(" "),
47498
+ _c(
47499
+ "tbody",
47500
+ _vm._l(_vm.objectProperties, function (ref) {
47501
+ var _obj;
47441
47502
 
47442
- var key = ref[0];
47443
- var value = ref[1];
47444
- return _c(
47445
- "tr",
47446
- {
47447
- key: key,
47448
- staticClass: "cn-advanced-form-dialog__table-row",
47449
- class:
47450
- ((_obj = {
47451
- "cn-advanced-form-dialog__table-row--selected":
47452
- _vm.selectedProperty === key,
47453
- "cn-advanced-form-dialog__table-row--edited":
47454
- _vm.isValueChanged(key),
47455
- "cn-advanced-form-dialog__table-row--non-editable":
47456
- !_vm.isPropertyEditable(
47457
- key,
47458
- _vm.resolvedValue(key, value)
47459
- ),
47460
- }),
47461
- (_obj[_vm.getPropertyValidationClass(key, value)] =
47462
- _vm.validationDisplay === "indicator"),
47463
- _obj),
47464
- on: {
47465
- click: function ($event) {
47466
- return _vm.handleRowClick(key, $event)
47467
- },
47468
- },
47469
- },
47470
- [
47471
- _c(
47472
- "td",
47473
- {
47474
- staticClass:
47475
- "cn-advanced-form-dialog__table-col-constrained cn-advanced-form-dialog__prop-cell",
47476
- style: _vm.getPropCellStyle(key, value),
47477
- },
47478
- [
47479
- _c(
47480
- "div",
47481
- {
47482
- staticClass:
47483
- "cn-advanced-form-dialog__prop-cell-content",
47484
- },
47485
- [
47486
- _vm.validationDisplay === "indicator" &&
47487
- _vm.getPropertyValidationState(
47503
+ var key = ref[0];
47504
+ var value = ref[1];
47505
+ return _c(
47506
+ "tr",
47507
+ {
47508
+ key: key,
47509
+ staticClass: "cn-advanced-form-dialog__table-row",
47510
+ class:
47511
+ ((_obj = {
47512
+ "cn-advanced-form-dialog__table-row--selected":
47513
+ _vm.selectedProperty === key,
47514
+ "cn-advanced-form-dialog__table-row--edited":
47515
+ _vm.isValueChanged(key),
47516
+ "cn-advanced-form-dialog__table-row--non-editable":
47517
+ !_vm.isPropertyEditable(
47488
47518
  key,
47489
47519
  _vm.resolvedValue(key, value)
47490
- ) === "invalid"
47491
- ? _c("AlertCircle", {
47492
- staticClass:
47493
- "cn-advanced-form-dialog__validation-icon cn-advanced-form-dialog__validation-icon--error",
47494
- attrs: {
47495
- size: 16,
47496
- title: _vm.getPropertyErrorMessage(
47497
- key,
47498
- _vm.resolvedValue(key, value)
47499
- ),
47500
- },
47501
- })
47502
- : _vm.validationDisplay === "indicator" &&
47503
- _vm.isValueChanged(key) &&
47504
- _vm.getPropertyValidationState(
47505
- key,
47506
- _vm.resolvedValue(key, value)
47507
- ) !== "invalid"
47508
- ? _c("Alert", {
47509
- staticClass:
47510
- "cn-advanced-form-dialog__validation-icon cn-advanced-form-dialog__validation-icon--edited",
47511
- attrs: {
47512
- size: 16,
47513
- title: _vm.t(
47514
- "nextcloud-vue",
47515
- "This field has been changed"
47516
- ),
47517
- },
47518
- })
47519
- : _vm.validationDisplay === "indicator" &&
47520
- _vm.getPropertyValidationState(
47521
- key,
47522
- _vm.resolvedValue(key, value)
47523
- ) === "warning"
47524
- ? _c("Alert", {
47525
- staticClass:
47526
- "cn-advanced-form-dialog__validation-icon cn-advanced-form-dialog__validation-icon--warning",
47527
- attrs: {
47528
- size: 16,
47529
- title: _vm.getPropertyWarningMessage(
47530
- key,
47531
- _vm.resolvedValue(key, value)
47532
- ),
47533
- },
47534
- })
47535
- : _vm.validationDisplay === "indicator" &&
47536
- _vm.getPropertyValidationState(
47537
- key,
47538
- _vm.resolvedValue(key, value)
47539
- ) === "new"
47540
- ? _c("Plus", {
47541
- staticClass:
47542
- "cn-advanced-form-dialog__validation-icon cn-advanced-form-dialog__validation-icon--new",
47543
- attrs: {
47544
- size: 16,
47545
- title: _vm.getPropertyNewMessage(key),
47546
- },
47547
- })
47548
- : !_vm.isPropertyEditable(
47549
- key,
47550
- _vm.resolvedValue(key, value)
47551
- )
47552
- ? _c("LockOutline", {
47553
- staticClass:
47554
- "cn-advanced-form-dialog__validation-icon cn-advanced-form-dialog__validation-icon--lock",
47555
- attrs: {
47556
- size: 16,
47557
- title:
47558
- _vm.getEditabilityWarning(
47559
- key,
47560
- _vm.resolvedValue(key, value)
47561
- ) || "",
47562
- },
47563
- })
47564
- : _vm._e(),
47565
- _vm._v(" "),
47566
- _c(
47567
- "span",
47568
- { attrs: { title: _vm.getPropertyTooltip(key) } },
47569
- [_vm._v(_vm._s(_vm.getPropertyDisplayName(key)))]
47570
47520
  ),
47571
- _vm._v(" "),
47572
- _vm.isRequired(key)
47573
- ? _c(
47574
- "span",
47575
- {
47521
+ }),
47522
+ (_obj[_vm.getPropertyValidationClass(key, value)] =
47523
+ _vm.validationDisplay === "indicator"),
47524
+ _obj),
47525
+ on: {
47526
+ click: function ($event) {
47527
+ return _vm.handleRowClick(key, $event)
47528
+ },
47529
+ },
47530
+ },
47531
+ [
47532
+ _c(
47533
+ "td",
47534
+ {
47535
+ staticClass:
47536
+ "cn-advanced-form-dialog__table-col-constrained cn-advanced-form-dialog__prop-cell",
47537
+ style: _vm.getPropCellStyle(key, value),
47538
+ },
47539
+ [
47540
+ _c(
47541
+ "div",
47542
+ {
47543
+ staticClass:
47544
+ "cn-advanced-form-dialog__prop-cell-content",
47545
+ },
47546
+ [
47547
+ _vm.validationDisplay === "indicator" &&
47548
+ _vm.getPropertyValidationState(
47549
+ key,
47550
+ _vm.resolvedValue(key, value)
47551
+ ) === "invalid"
47552
+ ? _c("AlertCircle", {
47576
47553
  staticClass:
47577
- "cn-advanced-form-dialog__required-indicator",
47554
+ "cn-advanced-form-dialog__validation-icon cn-advanced-form-dialog__validation-icon--error",
47578
47555
  attrs: {
47579
- title: _vm.t("nextcloud-vue", "Required"),
47580
- "aria-label": "required",
47556
+ size: 16,
47557
+ title: _vm.getPropertyErrorMessage(
47558
+ key,
47559
+ _vm.resolvedValue(key, value)
47560
+ ),
47581
47561
  },
47582
- },
47583
- [_vm._v("*")]
47584
- )
47585
- : _vm._e(),
47586
- _vm._v(" "),
47587
- _vm.isImmutableHint(key)
47588
- ? _c(
47589
- "span",
47590
- {
47562
+ })
47563
+ : _vm.validationDisplay === "indicator" &&
47564
+ _vm.isValueChanged(key) &&
47565
+ _vm.getPropertyValidationState(
47566
+ key,
47567
+ _vm.resolvedValue(key, value)
47568
+ ) !== "invalid"
47569
+ ? _c("PencilOutline", {
47570
+ directives: [
47571
+ {
47572
+ name: "tooltip",
47573
+ rawName: "v-tooltip",
47574
+ value: _vm.t(
47575
+ "nextcloud-vue",
47576
+ "This field has been changed — save to apply"
47577
+ ),
47578
+ expression:
47579
+ "t('nextcloud-vue', 'This field has been changed — save to apply')",
47580
+ },
47581
+ ],
47591
47582
  staticClass:
47592
- "cn-advanced-form-dialog__immutable-badge",
47583
+ "cn-advanced-form-dialog__validation-icon cn-advanced-form-dialog__validation-icon--edited",
47584
+ attrs: { size: 16 },
47585
+ })
47586
+ : _vm.validationDisplay === "indicator" &&
47587
+ _vm.getPropertyValidationState(
47588
+ key,
47589
+ _vm.resolvedValue(key, value)
47590
+ ) === "warning"
47591
+ ? _c("Alert", {
47592
+ staticClass:
47593
+ "cn-advanced-form-dialog__validation-icon cn-advanced-form-dialog__validation-icon--warning",
47593
47594
  attrs: {
47594
- title: _vm.t(
47595
- "nextcloud-vue",
47596
- "This value can be set on creation but cannot be changed afterwards."
47595
+ size: 16,
47596
+ title: _vm.getPropertyWarningMessage(
47597
+ key,
47598
+ _vm.resolvedValue(key, value)
47597
47599
  ),
47598
47600
  },
47599
- },
47600
- [
47601
- _vm._v(
47602
- "\n\t\t\t\t\t\t\t" +
47603
- _vm._s(_vm.t("nextcloud-vue", "Set once")) +
47604
- "\n\t\t\t\t\t\t"
47605
- ),
47606
- ]
47607
- )
47608
- : _vm._e(),
47609
- ],
47610
- 1
47611
- ),
47612
- ]
47613
- ),
47614
- _vm._v(" "),
47615
- _c(
47616
- "td",
47617
- {
47618
- staticClass:
47619
- "cn-advanced-form-dialog__table-col-expanded cn-advanced-form-dialog__value-cell",
47620
- },
47621
- [
47622
- _vm._t(
47623
- "value-cell",
47624
- function () {
47625
- return [
47626
- _c("CnPropertyValueCell", {
47627
- ref: "cell-" + key,
47628
- refInFor: true,
47629
- attrs: {
47630
- "property-key": key,
47631
- schema: _vm.schema,
47632
- value: _vm.resolvedValue(key, value),
47633
- "is-editable": _vm.isPropertyEditable(
47601
+ })
47602
+ : _vm.validationDisplay === "indicator" &&
47603
+ _vm.getPropertyValidationState(
47634
47604
  key,
47635
47605
  _vm.resolvedValue(key, value)
47636
- ),
47637
- "is-editing": _vm.selectedProperty === key,
47638
- "display-name": _vm.getPropertyDisplayName(key),
47639
- "editability-warning":
47640
- _vm.getPropertyEditabilityWarning(
47606
+ ) === "new"
47607
+ ? _c("Plus", {
47608
+ staticClass:
47609
+ "cn-advanced-form-dialog__validation-icon cn-advanced-form-dialog__validation-icon--new",
47610
+ attrs: {
47611
+ size: 16,
47612
+ title: _vm.getPropertyNewMessage(key),
47613
+ },
47614
+ })
47615
+ : !_vm.isPropertyEditable(
47616
+ key,
47617
+ _vm.resolvedValue(key, value)
47618
+ )
47619
+ ? _c("LockOutline", {
47620
+ staticClass:
47621
+ "cn-advanced-form-dialog__validation-icon cn-advanced-form-dialog__validation-icon--lock",
47622
+ attrs: {
47623
+ size: 16,
47624
+ title:
47625
+ _vm.getEditabilityWarning(
47626
+ key,
47627
+ _vm.resolvedValue(key, value)
47628
+ ) || "",
47629
+ },
47630
+ })
47631
+ : _vm._e(),
47632
+ _vm._v(" "),
47633
+ _c(
47634
+ "span",
47635
+ { attrs: { title: _vm.getPropertyTooltip(key) } },
47636
+ [_vm._v(_vm._s(_vm.getPropertyDisplayName(key)))]
47637
+ ),
47638
+ _vm._v(" "),
47639
+ _vm.isRequired(key)
47640
+ ? _c(
47641
+ "span",
47642
+ {
47643
+ staticClass:
47644
+ "cn-advanced-form-dialog__required-indicator",
47645
+ attrs: {
47646
+ title: _vm.t("nextcloud-vue", "Required"),
47647
+ "aria-label": "required",
47648
+ },
47649
+ },
47650
+ [_vm._v("*")]
47651
+ )
47652
+ : _vm._e(),
47653
+ _vm._v(" "),
47654
+ _vm.isImmutableHint(key)
47655
+ ? _c(
47656
+ "span",
47657
+ {
47658
+ staticClass:
47659
+ "cn-advanced-form-dialog__immutable-badge",
47660
+ attrs: {
47661
+ title: _vm.t(
47662
+ "nextcloud-vue",
47663
+ "This value can be set on creation but cannot be changed afterwards."
47664
+ ),
47665
+ },
47666
+ },
47667
+ [
47668
+ _vm._v(
47669
+ "\n\t\t\t\t\t\t\t\t" +
47670
+ _vm._s(
47671
+ _vm.t("nextcloud-vue", "Set once")
47672
+ ) +
47673
+ "\n\t\t\t\t\t\t\t"
47674
+ ),
47675
+ ]
47676
+ )
47677
+ : _vm._e(),
47678
+ ],
47679
+ 1
47680
+ ),
47681
+ ]
47682
+ ),
47683
+ _vm._v(" "),
47684
+ _c(
47685
+ "td",
47686
+ {
47687
+ staticClass:
47688
+ "cn-advanced-form-dialog__table-col-expanded cn-advanced-form-dialog__value-cell",
47689
+ },
47690
+ [
47691
+ _vm._t(
47692
+ "value-cell",
47693
+ function () {
47694
+ return [
47695
+ _c("CnPropertyValueCell", {
47696
+ ref: "cell-" + key,
47697
+ refInFor: true,
47698
+ attrs: {
47699
+ "property-key": key,
47700
+ schema: _vm.schema,
47701
+ value: _vm.resolvedValue(key, value),
47702
+ "is-editable": _vm.isPropertyEditable(
47641
47703
  key,
47642
47704
  _vm.resolvedValue(key, value)
47643
47705
  ),
47644
- widget:
47645
- (_vm.propertyOverrides[key] &&
47646
- _vm.propertyOverrides[key].widget) ||
47647
- null,
47648
- "select-options":
47649
- (_vm.propertyOverrides[key] &&
47650
- _vm.propertyOverrides[key].selectOptions) ||
47651
- null,
47652
- "select-multiple": _vm.propertyOverrides[key]
47653
- ? _vm.propertyOverrides[key].selectMultiple !==
47654
- false
47655
- : true,
47656
- "textarea-rows":
47657
- (_vm.propertyOverrides[key] &&
47658
- _vm.propertyOverrides[key].textareaRows) ||
47659
- 4,
47660
- },
47661
- on: {
47662
- "update:value": function ($event) {
47663
- return _vm.onPropertyValueUpdate(key, $event)
47706
+ "is-editing": _vm.selectedProperty === key,
47707
+ "display-name": _vm.getPropertyDisplayName(key),
47708
+ "editability-warning":
47709
+ _vm.getPropertyEditabilityWarning(
47710
+ key,
47711
+ _vm.resolvedValue(key, value)
47712
+ ),
47713
+ widget:
47714
+ (_vm.propertyOverrides[key] &&
47715
+ _vm.propertyOverrides[key].widget) ||
47716
+ null,
47717
+ "select-options":
47718
+ (_vm.propertyOverrides[key] &&
47719
+ _vm.propertyOverrides[key].selectOptions) ||
47720
+ null,
47721
+ "select-multiple": _vm.propertyOverrides[key]
47722
+ ? _vm.propertyOverrides[key]
47723
+ .selectMultiple !== false
47724
+ : true,
47725
+ "textarea-rows":
47726
+ (_vm.propertyOverrides[key] &&
47727
+ _vm.propertyOverrides[key].textareaRows) ||
47728
+ 4,
47664
47729
  },
47665
- },
47666
- }),
47667
- ]
47668
- },
47669
- {
47670
- propertyKey: key,
47671
- value: value,
47672
- resolvedValue: _vm.resolvedValue(key, value),
47673
- isEditing: _vm.selectedProperty === key,
47674
- isEditable: _vm.isPropertyEditable(
47675
- key,
47676
- _vm.resolvedValue(key, value)
47677
- ),
47678
- displayName: _vm.getPropertyDisplayName(key),
47679
- schemaProp:
47680
- _vm.schema &&
47681
- _vm.schema.properties &&
47682
- _vm.schema.properties[key],
47683
- editabilityWarning: _vm.getPropertyEditabilityWarning(
47684
- key,
47685
- _vm.resolvedValue(key, value)
47686
- ),
47687
- onUpdate: function (v) {
47688
- return _vm.onPropertyValueUpdate(key, v)
47689
- },
47690
- }
47691
- ),
47692
- ],
47693
- 2
47694
- ),
47695
- _vm._v(" "),
47696
- _vm.hasRowActionsSlot
47697
- ? _c(
47698
- "td",
47699
- {
47700
- staticClass:
47701
- "cn-advanced-form-dialog__table-col-actions",
47702
- on: {
47703
- click: function ($event) {
47704
- $event.stopPropagation();
47705
- },
47730
+ on: {
47731
+ "update:value": function ($event) {
47732
+ return _vm.onPropertyValueUpdate(key, $event)
47733
+ },
47734
+ },
47735
+ }),
47736
+ ]
47706
47737
  },
47707
- },
47708
- [
47709
- _vm._t("row-actions", null, {
47738
+ {
47710
47739
  propertyKey: key,
47711
47740
  value: value,
47712
47741
  resolvedValue: _vm.resolvedValue(key, value),
47742
+ isEditing: _vm.selectedProperty === key,
47713
47743
  isEditable: _vm.isPropertyEditable(
47714
47744
  key,
47715
47745
  _vm.resolvedValue(key, value)
47716
47746
  ),
47717
- isSchemaProperty: !!(
47747
+ displayName: _vm.getPropertyDisplayName(key),
47748
+ schemaProp:
47718
47749
  _vm.schema &&
47719
47750
  _vm.schema.properties &&
47720
- Object.prototype.hasOwnProperty.call(
47721
- _vm.schema.properties,
47722
- key
47723
- )
47751
+ _vm.schema.properties[key],
47752
+ editabilityWarning: _vm.getPropertyEditabilityWarning(
47753
+ key,
47754
+ _vm.resolvedValue(key, value)
47724
47755
  ),
47725
- }),
47726
- ],
47727
- 2
47728
- )
47729
- : _vm._e(),
47730
- ]
47731
- )
47732
- }),
47733
- 0
47734
- ),
47756
+ onUpdate: function (v) {
47757
+ return _vm.onPropertyValueUpdate(key, v)
47758
+ },
47759
+ }
47760
+ ),
47761
+ ],
47762
+ 2
47763
+ ),
47764
+ _vm._v(" "),
47765
+ _vm.hasRowActionsSlot
47766
+ ? _c(
47767
+ "td",
47768
+ {
47769
+ staticClass:
47770
+ "cn-advanced-form-dialog__table-col-actions",
47771
+ on: {
47772
+ click: function ($event) {
47773
+ $event.stopPropagation();
47774
+ },
47775
+ },
47776
+ },
47777
+ [
47778
+ _vm._t("row-actions", null, {
47779
+ propertyKey: key,
47780
+ value: value,
47781
+ resolvedValue: _vm.resolvedValue(key, value),
47782
+ isEditable: _vm.isPropertyEditable(
47783
+ key,
47784
+ _vm.resolvedValue(key, value)
47785
+ ),
47786
+ isSchemaProperty: !!(
47787
+ _vm.schema &&
47788
+ _vm.schema.properties &&
47789
+ Object.prototype.hasOwnProperty.call(
47790
+ _vm.schema.properties,
47791
+ key
47792
+ )
47793
+ ),
47794
+ }),
47795
+ ],
47796
+ 2
47797
+ )
47798
+ : _vm._e(),
47799
+ ]
47800
+ )
47801
+ }),
47802
+ 0
47803
+ ),
47804
+ ]),
47735
47805
  ]),
47736
- ]
47806
+ ],
47807
+ 1
47737
47808
  )
47738
47809
  };
47739
47810
  var __vue_staticRenderFns__$L = [];
@@ -47742,7 +47813,7 @@ __vue_render__$L._withStripped = true;
47742
47813
  /* style */
47743
47814
  const __vue_inject_styles__$L = undefined;
47744
47815
  /* scoped */
47745
- const __vue_scope_id__$L = "data-v-0e9d750d";
47816
+ const __vue_scope_id__$L = "data-v-7a17ec5c";
47746
47817
  /* module identifier */
47747
47818
  const __vue_module_identifier__$L = undefined;
47748
47819
  /* functional template */
@@ -50978,7 +51049,7 @@ function relationsPlugin(options = {}) {
50978
51049
  * upload (multipart), publish, unpublish, and delete.
50979
51050
  *
50980
51051
  * State: files, filesLoading, filesError, tags, tagsLoading, tagsError
50981
- * Actions: fetchFiles, uploadFiles, publishFile, unpublishFile, deleteFile, clearFiles, fetchTags
51052
+ * Actions: fetchFiles, uploadFiles, publishFile, unpublishFile, deleteFile, batchFiles, clearFiles, fetchTags
50982
51053
  * Getters: getFiles, isFilesLoading, getFilesError, getTags, isTagsLoading, getTagsError
50983
51054
  *
50984
51055
  * @param {object} [options={}] Plugin options
@@ -51214,6 +51285,58 @@ function filesPlugin(options = {}) {
51214
51285
  this.filesLoading = false;
51215
51286
  }
51216
51287
  },
51288
+
51289
+ /**
51290
+ * Apply a batch action across multiple files in ONE request.
51291
+ *
51292
+ * Replaces the N-sequential-call pattern (loop calling
51293
+ * publishFile/unpublishFile/deleteFile per id) with a single POST
51294
+ * to /files/batch. The backend returns 200 when every operation
51295
+ * succeeds, or 207 (multi-status) when some fail; the per-file
51296
+ * outcomes live in `data.results` and the aggregate counts in
51297
+ * `data.summary` (`{ succeeded, failed, total }`).
51298
+ *
51299
+ * @param {string} type The registered object type slug
51300
+ * @param {string} objectId The parent object ID
51301
+ * @param {('publish'|'depublish'|'delete'|'label')} action The batch action to apply
51302
+ * @param {(string|number)[]} fileIds File IDs to act on (max 100, validated server-side)
51303
+ * @param {object} [params={}] Action-specific parameters (e.g. labels for the 'label' action)
51304
+ * @return {Promise<object|null>} Response body `{ results, summary }`, or null on transport error
51305
+ */
51306
+ async batchFiles(type, objectId, action, fileIds, params = {}) {
51307
+ this.filesLoading = true;
51308
+ this.filesError = null;
51309
+
51310
+ try {
51311
+ const url = this._buildUrl(type, objectId) + '/files/batch';
51312
+
51313
+ const response = await fetch(url, {
51314
+ method: 'POST',
51315
+ headers: buildHeaders(),
51316
+ body: JSON.stringify({
51317
+ action,
51318
+ fileIds,
51319
+ ...params,
51320
+ }),
51321
+ });
51322
+
51323
+ // 200 = all succeeded, 207 = partial success — both are
51324
+ // valid responses; the caller inspects data.summary.
51325
+ if (!response.ok && response.status !== 207) {
51326
+ this.filesError = await parseResponseError(response, 'files');
51327
+ return null
51328
+ }
51329
+
51330
+ const data = await response.json();
51331
+ await this.fetchFiles(type, objectId);
51332
+ return data
51333
+ } catch (error) {
51334
+ this.filesError = networkError(error);
51335
+ return null
51336
+ } finally {
51337
+ this.filesLoading = false;
51338
+ }
51339
+ },
51217
51340
  },
51218
51341
  }
51219
51342
  }
@@ -64848,6 +64971,18 @@ __vue_render__$B._withStripped = true;
64848
64971
  //
64849
64972
  //
64850
64973
  //
64974
+ //
64975
+ //
64976
+ //
64977
+ //
64978
+ //
64979
+ //
64980
+ //
64981
+ //
64982
+ //
64983
+ //
64984
+ //
64985
+ //
64851
64986
 
64852
64987
 
64853
64988
  /**
@@ -64907,6 +65042,20 @@ var script$A = {
64907
65042
  type: String,
64908
65043
  default: null,
64909
65044
  },
65045
+ /**
65046
+ * Position of the title-icon slot in the header.
65047
+ * 'left' places it before the title; 'right' places it after the actions.
65048
+ */
65049
+ titleIconPosition: {
65050
+ type: String,
65051
+ default: 'right',
65052
+ validator: (v) => ['left', 'right'].includes(v),
65053
+ },
65054
+ /** CSS color value applied to the title-icon slot container */
65055
+ titleIconColor: {
65056
+ type: String,
65057
+ default: null,
65058
+ },
64910
65059
  /** Footer action buttons: [{ text, link }] */
64911
65060
  buttons: {
64912
65061
  type: Array,
@@ -64972,6 +65121,20 @@ var __vue_render__$A = function () {
64972
65121
  [
64973
65122
  _vm.showTitle
64974
65123
  ? _c("div", { staticClass: "cn-widget-wrapper__header" }, [
65124
+ _vm.$slots["title-icon"] && _vm.titleIconPosition === "left"
65125
+ ? _c(
65126
+ "div",
65127
+ {
65128
+ staticClass: "cn-widget-wrapper__title-icon",
65129
+ style: _vm.titleIconColor
65130
+ ? { color: _vm.titleIconColor }
65131
+ : {},
65132
+ },
65133
+ [_vm._t("title-icon")],
65134
+ 2
65135
+ )
65136
+ : _vm._e(),
65137
+ _vm._v(" "),
64975
65138
  _c("div", { staticClass: "cn-widget-wrapper__header-left" }, [
64976
65139
  _vm.iconUrl
64977
65140
  ? _c("img", {
@@ -64996,6 +65159,20 @@ var __vue_render__$A = function () {
64996
65159
  [_vm._t("actions")],
64997
65160
  2
64998
65161
  ),
65162
+ _vm._v(" "),
65163
+ _vm.$slots["title-icon"] && _vm.titleIconPosition === "right"
65164
+ ? _c(
65165
+ "div",
65166
+ {
65167
+ staticClass: "cn-widget-wrapper__title-icon",
65168
+ style: _vm.titleIconColor
65169
+ ? { color: _vm.titleIconColor }
65170
+ : {},
65171
+ },
65172
+ [_vm._t("title-icon")],
65173
+ 2
65174
+ )
65175
+ : _vm._e(),
64999
65176
  ])
65000
65177
  : _vm._e(),
65001
65178
  _vm._v(" "),
@@ -65037,7 +65214,7 @@ __vue_render__$A._withStripped = true;
65037
65214
  /* style */
65038
65215
  const __vue_inject_styles__$A = undefined;
65039
65216
  /* scoped */
65040
- const __vue_scope_id__$A = "data-v-2653d35b";
65217
+ const __vue_scope_id__$A = "data-v-38c9c90e";
65041
65218
  /* module identifier */
65042
65219
  const __vue_module_identifier__$A = undefined;
65043
65220
  /* functional template */
@@ -65636,6 +65813,12 @@ __vue_render__$y._withStripped = true;
65636
65813
  //
65637
65814
  //
65638
65815
  //
65816
+ //
65817
+ //
65818
+ //
65819
+ //
65820
+ //
65821
+ //
65639
65822
 
65640
65823
 
65641
65824
  /**
@@ -65826,6 +66009,16 @@ var script$x = {
65826
66009
  return def?.buttons || []
65827
66010
  },
65828
66011
 
66012
+ getWidgetTitleIconPosition(item) {
66013
+ const def = this.getWidgetDef(item.widgetId);
66014
+ return def?.titleIconPosition || 'right'
66015
+ },
66016
+
66017
+ getWidgetTitleIconColor(item) {
66018
+ const def = this.getWidgetDef(item.widgetId);
66019
+ return def?.titleIconColor || null
66020
+ },
66021
+
65829
66022
  isTile(item) {
65830
66023
  const def = this.getWidgetDef(item.widgetId);
65831
66024
  return def?.type === 'tile'
@@ -65990,9 +66183,37 @@ var __vue_render__$x = function () {
65990
66183
  flush: item.flush === true,
65991
66184
  buttons: _vm.getWidgetButtons(item),
65992
66185
  "style-config": item.styleConfig || {},
66186
+ "title-icon-position":
66187
+ _vm.getWidgetTitleIconPosition(item),
66188
+ "title-icon-color":
66189
+ _vm.getWidgetTitleIconColor(item),
65993
66190
  },
65994
66191
  scopedSlots: _vm._u(
65995
66192
  [
66193
+ _vm.$slots[
66194
+ "widget-" + item.widgetId + "-title-icon"
66195
+ ]
66196
+ ? {
66197
+ key: "title-icon",
66198
+ fn: function () {
66199
+ return [
66200
+ _vm._t(
66201
+ "widget-" +
66202
+ item.widgetId +
66203
+ "-title-icon",
66204
+ null,
66205
+ {
66206
+ item: item,
66207
+ widget: _vm.getWidgetDef(
66208
+ item.widgetId
66209
+ ),
66210
+ }
66211
+ ),
66212
+ ]
66213
+ },
66214
+ proxy: true,
66215
+ }
66216
+ : null,
65996
66217
  _vm.$slots[
65997
66218
  "widget-" + item.widgetId + "-actions"
65998
66219
  ]
@@ -66023,6 +66244,7 @@ var __vue_render__$x = function () {
66023
66244
  ),
66024
66245
  },
66025
66246
  [
66247
+ _vm._v(" "),
66026
66248
  _vm._v(" "),
66027
66249
  _vm._t("widget-" + item.widgetId, null, {
66028
66250
  item: item,
@@ -66094,7 +66316,7 @@ __vue_render__$x._withStripped = true;
66094
66316
  /* style */
66095
66317
  const __vue_inject_styles__$x = undefined;
66096
66318
  /* scoped */
66097
- const __vue_scope_id__$x = "data-v-5b5cafec";
66319
+ const __vue_scope_id__$x = "data-v-3abb3b3a";
66098
66320
  /* module identifier */
66099
66321
  const __vue_module_identifier__$x = undefined;
66100
66322
  /* functional template */
@@ -104901,6 +105123,7 @@ var translations$1 = {
104901
105123
  "The 'admin' group always has full access (cannot be changed)": "The 'admin' group always has full access (cannot be changed)",
104902
105124
  "The following items will be permanently deleted. Remove any items you want to keep.": "The following items will be permanently deleted. Remove any items you want to keep.",
104903
105125
  "The object owner always has full access": "The object owner always has full access",
105126
+ "This field has been changed — save to apply": "This field has been changed — save to apply",
104904
105127
  Time: "Time",
104905
105128
  Title: "Title",
104906
105129
  "Title *": "Title *",
@@ -104933,6 +105156,7 @@ var translations$1 = {
104933
105156
  "Widget not available": "Widget not available",
104934
105157
  "Write a note...": "Write a note...",
104935
105158
  "Write back": "Write back",
105159
+ "You have unsaved changes. Save to apply them.": "You have unsaved changes. Save to apply them.",
104936
105160
  "{name} (Copy)": "{name} (Copy)",
104937
105161
  "{name} - Copy": "{name} - Copy",
104938
105162
  "{title} saved successfully.": "{title} saved successfully.",
@@ -105314,6 +105538,7 @@ var translations = {
105314
105538
  "The 'admin' group always has full access (cannot be changed)": "De 'admin'-groep heeft altijd volledige toegang (kan niet worden gewijzigd)",
105315
105539
  "The following items will be permanently deleted. Remove any items you want to keep.": "De volgende items worden permanent verwijderd. Haal items die u wilt bewaren uit de selectie.",
105316
105540
  "The object owner always has full access": "De eigenaar van het object heeft altijd volledige toegang",
105541
+ "This field has been changed — save to apply": "Dit veld is gewijzigd — sla op om toe te passen",
105317
105542
  Time: "Tijd",
105318
105543
  Title: "Titel",
105319
105544
  "Title *": "Titel *",
@@ -105346,6 +105571,7 @@ var translations = {
105346
105571
  "Widget not available": "Widget niet beschikbaar",
105347
105572
  "Write a note...": "Schrijf een notitie...",
105348
105573
  "Write back": "Terugschrijven",
105574
+ "You have unsaved changes. Save to apply them.": "U heeft niet-opgeslagen wijzigingen. Sla op om ze toe te passen.",
105349
105575
  "{name} (Copy)": "{name} (Kopie)",
105350
105576
  "{name} - Copy": "{name} - Kopie",
105351
105577
  "{title} saved successfully.": "{title} succesvol opgeslagen.",