@conduction/nextcloud-vue 0.1.0-beta.12 → 0.1.0-beta.14
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/dist/nextcloud-vue.cjs.js +19981 -648
- package/dist/nextcloud-vue.cjs.js.map +1 -1
- package/dist/nextcloud-vue.css +2314 -342
- package/dist/nextcloud-vue.esm.js +19982 -648
- package/dist/nextcloud-vue.esm.js.map +1 -1
- package/l10n/en.json +255 -2
- package/l10n/nl.json +247 -2
- package/package.json +2 -1
- package/src/components/CnAdvancedFormDialog/CnDataTab.vue +1 -4
- package/src/components/CnContextMenu/CnContextMenu.vue +1 -1
- package/src/components/CnDataTable/CnDataTable.vue +7 -2
- package/src/components/CnInfoWidget/CnInfoWidget.vue +0 -1
- package/src/components/CnObjectDataWidget/CnObjectDataWidget.vue +2 -2
- package/src/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue +2 -2
- package/src/components/CnRowActions/CnRowActions.vue +1 -1
- package/src/components/CnSchemaFormDialog/CnSchemaConfigurationTab.vue +36 -34
- package/src/components/CnSchemaFormDialog/CnSchemaFormDialog.vue +47 -36
- package/src/components/CnSchemaFormDialog/CnSchemaPropertiesTab.vue +29 -22
- package/src/components/CnSchemaFormDialog/CnSchemaPropertyActions.vue +170 -163
- package/src/components/CnSchemaFormDialog/CnSchemaSecurityTab.vue +473 -116
- package/src/components/CnStatsBlock/CnStatsBlock.vue +18 -18
- package/src/components/CnTabbedFormDialog/CnTabbedFormDialog.vue +12 -0
- package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +7 -7
- package/src/composables/useContextMenu.js +1 -1
- package/src/css/CnSchemaFormDialog.css +258 -2
- package/src/css/dashboard.css +1 -0
- package/src/css/detail-page.css +5 -5
- package/src/css/index.css +1 -0
- package/src/css/patches.css +20 -0
- package/src/store/plugins/search.js +7 -7
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="cn-schema-form__form-editor">
|
|
3
3
|
<NcTextArea :disabled="loading"
|
|
4
|
-
label="Description"
|
|
4
|
+
:label="t('nextcloud-vue', 'Description')"
|
|
5
5
|
:value.sync="schema.description" />
|
|
6
6
|
<NcTextArea :disabled="loading"
|
|
7
|
-
label="Summary"
|
|
7
|
+
:label="t('nextcloud-vue', 'Summary')"
|
|
8
8
|
:value.sync="schema.summary" />
|
|
9
9
|
<NcTextField :disabled="loading"
|
|
10
|
-
label="Slug"
|
|
10
|
+
:label="t('nextcloud-vue', 'Slug')"
|
|
11
11
|
:value.sync="schema.slug" />
|
|
12
12
|
|
|
13
13
|
<!-- Schema Composition Section -->
|
|
14
14
|
<div>
|
|
15
|
-
<h3>Schema
|
|
15
|
+
<h3>{{ t('nextcloud-vue', 'Schema composition (JSON Schema)') }}</h3>
|
|
16
16
|
|
|
17
17
|
<!-- allOf - Multiple Inheritance (Recommended) -->
|
|
18
18
|
<NcSelect
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
:close-on-select="false"
|
|
25
25
|
label="title"
|
|
26
26
|
track-by="id"
|
|
27
|
-
input-label="allOf - Inherits from ALL schemas (Recommended)"
|
|
28
|
-
placeholder="Select schemas to inherit from (supports multiple parents)">
|
|
27
|
+
:input-label="t('nextcloud-vue', 'allOf - Inherits from ALL schemas (Recommended)')"
|
|
28
|
+
:placeholder="t('nextcloud-vue', 'Select schemas to inherit from (supports multiple parents)')">
|
|
29
29
|
<template #option="{ title, description }">
|
|
30
30
|
<div class="cn-schema-form__schema-option">
|
|
31
31
|
<span class="cn-schema-form__option-title">{{ title }}</span>
|
|
@@ -34,11 +34,11 @@
|
|
|
34
34
|
</template>
|
|
35
35
|
</NcSelect>
|
|
36
36
|
<NcNoteCard v-if="schema.allOf && schema.allOf.length > 0" type="info">
|
|
37
|
-
<p><strong>allOf - Multiple
|
|
38
|
-
<p>Instance must validate against
|
|
39
|
-
<p><strong>Important
|
|
37
|
+
<p><strong>{{ t('nextcloud-vue', 'allOf - Multiple inheritance') }}</strong></p>
|
|
38
|
+
<p>{{ t('nextcloud-vue', 'Instance must validate against all selected schemas. Properties from all parent schemas are merged. This is the recommended pattern for schema extension and multiple inheritance.') }}</p>
|
|
39
|
+
<p><strong>{{ t('nextcloud-vue', 'Important:') }}</strong> {{ t('nextcloud-vue', 'Child schemas can only add constraints, never relax them (Liskov substitution principle). Metadata (title, description, order) can be overridden.') }}</p>
|
|
40
40
|
<div v-if="allOfSchemaNames.length > 0">
|
|
41
|
-
<strong>Parent
|
|
41
|
+
<strong>{{ t('nextcloud-vue', 'Parent schemas:') }}</strong>
|
|
42
42
|
<ul>
|
|
43
43
|
<li v-for="name in allOfSchemaNames" :key="name">
|
|
44
44
|
{{ name }}
|
|
@@ -57,8 +57,8 @@
|
|
|
57
57
|
:close-on-select="false"
|
|
58
58
|
label="title"
|
|
59
59
|
track-by="id"
|
|
60
|
-
input-label="oneOf - Exactly
|
|
61
|
-
placeholder="Select schemas (instance must match exactly one)">
|
|
60
|
+
:input-label="t('nextcloud-vue', 'oneOf - Exactly one schema must match')"
|
|
61
|
+
:placeholder="t('nextcloud-vue', 'Select schemas (instance must match exactly one)')">
|
|
62
62
|
<template #option="{ title, description }">
|
|
63
63
|
<div class="cn-schema-form__schema-option">
|
|
64
64
|
<span class="cn-schema-form__option-title">{{ title }}</span>
|
|
@@ -67,8 +67,8 @@
|
|
|
67
67
|
</template>
|
|
68
68
|
</NcSelect>
|
|
69
69
|
<NcNoteCard v-if="schema.oneOf && schema.oneOf.length > 0" type="info">
|
|
70
|
-
<p><strong>oneOf - Mutually
|
|
71
|
-
<p>Instance must validate against
|
|
70
|
+
<p><strong>{{ t('nextcloud-vue', 'oneOf - Mutually exclusive') }}</strong></p>
|
|
71
|
+
<p>{{ t('nextcloud-vue', 'Instance must validate against exactly one of the selected schemas. Properties are not merged. Use for discriminated unions or type variants.') }}</p>
|
|
72
72
|
</NcNoteCard>
|
|
73
73
|
|
|
74
74
|
<!-- anyOf - Flexible Composition -->
|
|
@@ -81,8 +81,8 @@
|
|
|
81
81
|
:close-on-select="false"
|
|
82
82
|
label="title"
|
|
83
83
|
track-by="id"
|
|
84
|
-
input-label="anyOf - At least
|
|
85
|
-
placeholder="Select schemas (instance must match at least one)">
|
|
84
|
+
:input-label="t('nextcloud-vue', 'anyOf - At least one schema must match')"
|
|
85
|
+
:placeholder="t('nextcloud-vue', 'Select schemas (instance must match at least one)')">
|
|
86
86
|
<template #option="{ title, description }">
|
|
87
87
|
<div class="cn-schema-form__schema-option">
|
|
88
88
|
<span class="cn-schema-form__option-title">{{ title }}</span>
|
|
@@ -91,73 +91,74 @@
|
|
|
91
91
|
</template>
|
|
92
92
|
</NcSelect>
|
|
93
93
|
<NcNoteCard v-if="schema.anyOf && schema.anyOf.length > 0" type="info">
|
|
94
|
-
<p><strong>anyOf - Flexible
|
|
95
|
-
<p>Instance must validate against
|
|
94
|
+
<p><strong>{{ t('nextcloud-vue', 'anyOf - Flexible composition') }}</strong></p>
|
|
95
|
+
<p>{{ t('nextcloud-vue', 'Instance must validate against at least one of the selected schemas. Properties are not merged. More permissive than oneOf.') }}</p>
|
|
96
96
|
</NcNoteCard>
|
|
97
97
|
</div>
|
|
98
98
|
<NcSelect
|
|
99
99
|
v-model="schema.configuration.objectNameField"
|
|
100
100
|
:disabled="loading"
|
|
101
101
|
:options="propertyOptions"
|
|
102
|
-
input-label="Object
|
|
103
|
-
placeholder="Select a property to use as object name" />
|
|
102
|
+
:input-label="t('nextcloud-vue', 'Object name field')"
|
|
103
|
+
:placeholder="t('nextcloud-vue', 'Select a property to use as object name')" />
|
|
104
104
|
<NcSelect
|
|
105
105
|
v-model="schema.configuration.objectDescriptionField"
|
|
106
106
|
:disabled="loading"
|
|
107
107
|
:options="propertyOptions"
|
|
108
|
-
input-label="Object
|
|
109
|
-
placeholder="Select a property to use as object description" />
|
|
108
|
+
:input-label="t('nextcloud-vue', 'Object description field')"
|
|
109
|
+
:placeholder="t('nextcloud-vue', 'Select a property to use as object description')" />
|
|
110
110
|
<NcSelect
|
|
111
111
|
v-model="schema.configuration.objectImageField"
|
|
112
112
|
:disabled="loading"
|
|
113
113
|
:options="propertyOptions"
|
|
114
|
-
input-label="Object
|
|
115
|
-
placeholder="Select a property to use as object image representing the object. e.g. logo (should contain base64 encoded image)" />
|
|
114
|
+
:input-label="t('nextcloud-vue', 'Object image field')"
|
|
115
|
+
:placeholder="t('nextcloud-vue', 'Select a property to use as object image representing the object. e.g. logo (should contain base64 encoded image)')" />
|
|
116
116
|
<NcSelect
|
|
117
117
|
v-model="schema.configuration.objectSummaryField"
|
|
118
118
|
:disabled="loading"
|
|
119
119
|
:options="propertyOptions"
|
|
120
|
-
input-label="Object
|
|
121
|
-
placeholder="Select a property to use as object summary. e.g. summary, abstract, or excerpt" />
|
|
120
|
+
:input-label="t('nextcloud-vue', 'Object summary field')"
|
|
121
|
+
:placeholder="t('nextcloud-vue', 'Select a property to use as object summary. e.g. summary, abstract, or excerpt')" />
|
|
122
122
|
<NcCheckboxRadioSwitch
|
|
123
123
|
:disabled="loading"
|
|
124
124
|
:checked.sync="schema.configuration.allowFiles">
|
|
125
|
-
Allow
|
|
125
|
+
{{ t('nextcloud-vue', 'Allow files') }}
|
|
126
126
|
</NcCheckboxRadioSwitch>
|
|
127
127
|
<NcCheckboxRadioSwitch
|
|
128
128
|
:disabled="loading"
|
|
129
129
|
:checked.sync="schema.configuration.autoPublish">
|
|
130
|
-
Auto-
|
|
130
|
+
{{ t('nextcloud-vue', 'Auto-publish objects') }}
|
|
131
131
|
</NcCheckboxRadioSwitch>
|
|
132
132
|
<NcTextField
|
|
133
133
|
v-model="allowedTagsInput"
|
|
134
134
|
:disabled="loading"
|
|
135
|
-
label="Allowed
|
|
136
|
-
placeholder="image, document, audio, video"
|
|
135
|
+
:label="t('nextcloud-vue', 'Allowed tags (comma-separated)')"
|
|
136
|
+
:placeholder="t('nextcloud-vue', 'image, document, audio, video')"
|
|
137
137
|
@update:value="updateAllowedTags" />
|
|
138
138
|
<NcCheckboxRadioSwitch
|
|
139
139
|
:disabled="loading"
|
|
140
140
|
:checked.sync="schema.hardValidation">
|
|
141
|
-
Hard
|
|
141
|
+
{{ t('nextcloud-vue', 'Hard validation') }}
|
|
142
142
|
</NcCheckboxRadioSwitch>
|
|
143
143
|
<NcTextField :disabled="loading"
|
|
144
|
-
label="Max
|
|
144
|
+
:label="t('nextcloud-vue', 'Max depth')"
|
|
145
145
|
type="number"
|
|
146
146
|
:value.sync="schema.maxDepth" />
|
|
147
147
|
<NcCheckboxRadioSwitch
|
|
148
148
|
:disabled="loading"
|
|
149
149
|
:checked.sync="schema.immutable">
|
|
150
|
-
Immutable
|
|
150
|
+
{{ t('nextcloud-vue', 'Immutable') }}
|
|
151
151
|
</NcCheckboxRadioSwitch>
|
|
152
152
|
<NcCheckboxRadioSwitch
|
|
153
153
|
:disabled="loading"
|
|
154
154
|
:checked.sync="schema.searchable">
|
|
155
|
-
Searchable in SOLR
|
|
155
|
+
{{ t('nextcloud-vue', 'Searchable in SOLR') }}
|
|
156
156
|
</NcCheckboxRadioSwitch>
|
|
157
157
|
</div>
|
|
158
158
|
</template>
|
|
159
159
|
|
|
160
160
|
<script>
|
|
161
|
+
import { translate as t } from '@nextcloud/l10n'
|
|
161
162
|
import {
|
|
162
163
|
NcTextField,
|
|
163
164
|
NcTextArea,
|
|
@@ -213,6 +214,7 @@ export default {
|
|
|
213
214
|
},
|
|
214
215
|
},
|
|
215
216
|
methods: {
|
|
217
|
+
t,
|
|
216
218
|
updateAllowedTags(value) {
|
|
217
219
|
if (!value || value.trim() === '') {
|
|
218
220
|
this.$set(this.schema.configuration, 'allowedTags', [])
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
:dialog-title="dialogTitle"
|
|
7
7
|
entity-name="Schema"
|
|
8
8
|
:size="size"
|
|
9
|
-
:disable-save="
|
|
9
|
+
:disable-save="!!saveDisabledReason"
|
|
10
|
+
:disable-save-tooltip="saveDisabledReason"
|
|
10
11
|
:success-text="resolvedSuccessText"
|
|
11
12
|
:cancel-label="cancelLabel"
|
|
12
13
|
:close-label="closeLabel"
|
|
@@ -19,14 +20,14 @@
|
|
|
19
20
|
<div v-if="schemaItem.id"
|
|
20
21
|
class="cn-schema-form__detail-item cn-schema-form__id-card">
|
|
21
22
|
<div class="cn-schema-form__id-card-header">
|
|
22
|
-
<span class="cn-schema-form__detail-label">ID / UUID
|
|
23
|
+
<span class="cn-schema-form__detail-label">{{ t('nextcloud-vue', 'ID / UUID:') }}</span>
|
|
23
24
|
<NcButton class="cn-schema-form__copy-button"
|
|
24
25
|
@click="copyToClipboard(schemaItem.uuid || schemaItem.id)">
|
|
25
26
|
<template #icon>
|
|
26
27
|
<Check v-if="isCopied" :size="20" />
|
|
27
28
|
<ContentCopy v-else :size="20" />
|
|
28
29
|
</template>
|
|
29
|
-
{{ isCopied ? 'Copied' : 'Copy' }}
|
|
30
|
+
{{ isCopied ? t('nextcloud-vue', 'Copied') : t('nextcloud-vue', 'Copy') }}
|
|
30
31
|
</NcButton>
|
|
31
32
|
</div>
|
|
32
33
|
<span class="cn-schema-form__detail-value">{{ schemaItem.id }}</span>
|
|
@@ -35,7 +36,7 @@
|
|
|
35
36
|
</div>
|
|
36
37
|
<div class="cn-schema-form__detail-item cn-schema-form__title-with-badge">
|
|
37
38
|
<NcTextField :disabled="dialogLoading"
|
|
38
|
-
label="Title *"
|
|
39
|
+
:label="t('nextcloud-vue', 'Title *')"
|
|
39
40
|
:value.sync="schemaItem.title" />
|
|
40
41
|
<span v-if="schemaItem.allOf && schemaItem.allOf.length > 0"
|
|
41
42
|
class="cn-schema-form__statusPill cn-schema-form__statusPill--success">
|
|
@@ -51,20 +52,20 @@
|
|
|
51
52
|
</span>
|
|
52
53
|
</div>
|
|
53
54
|
<div v-if="schemaItem.created" class="cn-schema-form__detail-item">
|
|
54
|
-
<span class="cn-schema-form__detail-label">Created
|
|
55
|
+
<span class="cn-schema-form__detail-label">{{ t('nextcloud-vue', 'Created:') }}</span>
|
|
55
56
|
<span class="cn-schema-form__detail-value">{{ new Date(schemaItem.created).toLocaleString() }}</span>
|
|
56
57
|
</div>
|
|
57
58
|
<div v-if="schemaItem.updated" class="cn-schema-form__detail-item">
|
|
58
|
-
<span class="cn-schema-form__detail-label">Updated
|
|
59
|
+
<span class="cn-schema-form__detail-label">{{ t('nextcloud-vue', 'Updated:') }}</span>
|
|
59
60
|
<span class="cn-schema-form__detail-value">{{ new Date(schemaItem.updated).toLocaleString() }}</span>
|
|
60
61
|
</div>
|
|
61
62
|
<div class="cn-schema-form__detail-item">
|
|
62
|
-
<span class="cn-schema-form__detail-label">Version
|
|
63
|
-
<span class="cn-schema-form__detail-value">{{ schemaItem.version || 'Not set' }}</span>
|
|
63
|
+
<span class="cn-schema-form__detail-label">{{ t('nextcloud-vue', 'Version:') }}</span>
|
|
64
|
+
<span class="cn-schema-form__detail-value">{{ schemaItem.version || t('nextcloud-vue', 'Not set') }}</span>
|
|
64
65
|
</div>
|
|
65
66
|
<div class="cn-schema-form__detail-item">
|
|
66
|
-
<span class="cn-schema-form__detail-label">Owner
|
|
67
|
-
<span class="cn-schema-form__detail-value">{{ schemaItem.owner || 'Not set' }}</span>
|
|
67
|
+
<span class="cn-schema-form__detail-label">{{ t('nextcloud-vue', 'Owner:') }}</span>
|
|
68
|
+
<span class="cn-schema-form__detail-value">{{ schemaItem.owner || t('nextcloud-vue', 'Not set') }}</span>
|
|
68
69
|
</div>
|
|
69
70
|
</div>
|
|
70
71
|
</template>
|
|
@@ -327,9 +328,9 @@ export default {
|
|
|
327
328
|
*/
|
|
328
329
|
dialogTabs() {
|
|
329
330
|
return [
|
|
330
|
-
{ id: 'properties', title: 'Properties' },
|
|
331
|
-
{ id: 'configuration', title: 'Configuration' },
|
|
332
|
-
{ id: 'security', title: 'Security' },
|
|
331
|
+
{ id: 'properties', title: t('nextcloud-vue', 'Properties') },
|
|
332
|
+
{ id: 'configuration', title: t('nextcloud-vue', 'Configuration') },
|
|
333
|
+
{ id: 'security', title: t('nextcloud-vue', 'Security') },
|
|
333
334
|
]
|
|
334
335
|
},
|
|
335
336
|
sortedUserGroups() {
|
|
@@ -357,15 +358,15 @@ export default {
|
|
|
357
358
|
},
|
|
358
359
|
typeOptionsForSelect() {
|
|
359
360
|
return [
|
|
360
|
-
{ id: 'string', label: 'String' },
|
|
361
|
-
{ id: 'number', label: 'Number' },
|
|
362
|
-
{ id: 'integer', label: 'Integer' },
|
|
363
|
-
{ id: 'boolean', label: 'Boolean' },
|
|
364
|
-
{ id: 'array', label: 'Array' },
|
|
365
|
-
{ id: 'object', label: 'Object' },
|
|
366
|
-
{ id: 'dictionary', label: 'Dictionary' },
|
|
367
|
-
{ id: 'file', label: 'File' },
|
|
368
|
-
{ id: 'oneOf', label: 'One
|
|
361
|
+
{ id: 'string', label: t('nextcloud-vue', 'String') },
|
|
362
|
+
{ id: 'number', label: t('nextcloud-vue', 'Number') },
|
|
363
|
+
{ id: 'integer', label: t('nextcloud-vue', 'Integer') },
|
|
364
|
+
{ id: 'boolean', label: t('nextcloud-vue', 'Boolean') },
|
|
365
|
+
{ id: 'array', label: t('nextcloud-vue', 'Array') },
|
|
366
|
+
{ id: 'object', label: t('nextcloud-vue', 'Object') },
|
|
367
|
+
{ id: 'dictionary', label: t('nextcloud-vue', 'Dictionary') },
|
|
368
|
+
{ id: 'file', label: t('nextcloud-vue', 'File') },
|
|
369
|
+
{ id: 'oneOf', label: t('nextcloud-vue', 'One of') },
|
|
369
370
|
]
|
|
370
371
|
},
|
|
371
372
|
propertyOptions() {
|
|
@@ -385,8 +386,25 @@ export default {
|
|
|
385
386
|
*/
|
|
386
387
|
resolvedSuccessText() {
|
|
387
388
|
if (this.successText) return this.successText
|
|
388
|
-
return '
|
|
389
|
+
return t('nextcloud-vue', '{title} saved successfully.', { title: t('nextcloud-vue', 'Schema') })
|
|
389
390
|
},
|
|
391
|
+
/**
|
|
392
|
+
* Returns a human-readable reason the save button is disabled, or '' when saving is allowed.
|
|
393
|
+
* Used for both :disable-save and the WCAG tooltip/aria-label on the button.
|
|
394
|
+
*
|
|
395
|
+
* @return {string}
|
|
396
|
+
*/
|
|
397
|
+
saveDisabledReason() {
|
|
398
|
+
if (!this.schemaItem.title) {
|
|
399
|
+
return t('nextcloud-vue', 'A schema title is required before saving')
|
|
400
|
+
}
|
|
401
|
+
const hasUnnamedProperty = Object.keys(this.schemaItem.properties || {}).some(key => key === '')
|
|
402
|
+
if (hasUnnamedProperty) {
|
|
403
|
+
return t('nextcloud-vue', 'All properties must have a name before saving')
|
|
404
|
+
}
|
|
405
|
+
return ''
|
|
406
|
+
},
|
|
407
|
+
|
|
390
408
|
allOfSchemaNames() {
|
|
391
409
|
if (!this.schemaItem.allOf || !Array.isArray(this.schemaItem.allOf) || this.schemaItem.allOf.length === 0) {
|
|
392
410
|
return []
|
|
@@ -485,6 +503,7 @@ export default {
|
|
|
485
503
|
},
|
|
486
504
|
},
|
|
487
505
|
methods: {
|
|
506
|
+
t,
|
|
488
507
|
findSchemaBySlug(schemaSlug) {
|
|
489
508
|
if (!schemaSlug) return undefined
|
|
490
509
|
return this.availableSchemas.find(schema =>
|
|
@@ -623,29 +642,21 @@ export default {
|
|
|
623
642
|
},
|
|
624
643
|
|
|
625
644
|
addProperty() {
|
|
626
|
-
|
|
627
|
-
let counter = 1
|
|
628
|
-
|
|
629
|
-
while (this.schemaItem.properties[newPropertyName]) {
|
|
630
|
-
counter++
|
|
631
|
-
newPropertyName = `new_${counter}`
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
this.$set(this.schemaItem.properties, newPropertyName, {
|
|
645
|
+
this.$set(this.schemaItem.properties, '', {
|
|
635
646
|
type: 'string',
|
|
636
647
|
format: '',
|
|
637
|
-
title:
|
|
648
|
+
title: '',
|
|
638
649
|
description: '',
|
|
639
650
|
facetable: false,
|
|
640
651
|
})
|
|
641
652
|
|
|
642
653
|
this.checkPropertiesModified()
|
|
643
|
-
this.selectedProperty =
|
|
654
|
+
this.selectedProperty = ''
|
|
644
655
|
},
|
|
645
656
|
|
|
646
657
|
updatePropertyKey(oldKey, newKey) {
|
|
647
|
-
if (
|
|
648
|
-
if (this.schemaItem.properties[newKey] && newKey !== oldKey) return
|
|
658
|
+
if (newKey === oldKey) return
|
|
659
|
+
if (this.schemaItem.properties[newKey] !== undefined && newKey !== oldKey) return
|
|
649
660
|
|
|
650
661
|
const propertyData = { ...this.schemaItem.properties[oldKey] }
|
|
651
662
|
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
row-key="_id"
|
|
8
8
|
:selectable="false"
|
|
9
9
|
:row-class="getRowClass"
|
|
10
|
-
:
|
|
10
|
+
:cell-class="getCellClass"
|
|
11
|
+
:empty-text="t('nextcloud-vue', 'No properties found. Click "Add property" to create one.')"
|
|
11
12
|
@row-click="onRowClick">
|
|
12
13
|
<template #actions-header>
|
|
13
14
|
<NcButton
|
|
@@ -17,7 +18,7 @@
|
|
|
17
18
|
<template #icon>
|
|
18
19
|
<Plus :size="20" />
|
|
19
20
|
</template>
|
|
20
|
-
Add property
|
|
21
|
+
{{ t('nextcloud-vue', 'Add property') }}
|
|
21
22
|
</NcButton>
|
|
22
23
|
</template>
|
|
23
24
|
|
|
@@ -26,11 +27,11 @@
|
|
|
26
27
|
<AlertOutline v-if="isPropertyModified(row._key)"
|
|
27
28
|
:size="16"
|
|
28
29
|
class="cn-schema-form__warning-icon"
|
|
29
|
-
:title="'Property has been modified. Changes will only take effect after the schema is saved.'" />
|
|
30
|
+
:title="t('nextcloud-vue', 'Property has been modified. Changes will only take effect after the schema is saved.')" />
|
|
30
31
|
<NcTextField
|
|
31
32
|
ref="propertyNameInput"
|
|
32
33
|
:value="row._key"
|
|
33
|
-
label="(technical) Property
|
|
34
|
+
:label="t('nextcloud-vue', '(technical) Property name')"
|
|
34
35
|
@update:value="onPropertyKeyUpdate(row._key, $event)"
|
|
35
36
|
@click.stop />
|
|
36
37
|
</div>
|
|
@@ -38,30 +39,30 @@
|
|
|
38
39
|
<AlertOutline v-if="isPropertyModified(row._key)"
|
|
39
40
|
:size="16"
|
|
40
41
|
class="cn-schema-form__warning-icon"
|
|
41
|
-
:title="'Property has been modified. Changes will only take effect after the schema is saved.'" />
|
|
42
|
+
:title="t('nextcloud-vue', 'Property has been modified. Changes will only take effect after the schema is saved.')" />
|
|
42
43
|
<div class="cn-schema-form__name-with-chips">
|
|
43
44
|
<span class="cn-schema-form__property-name">{{ row._key }}</span>
|
|
44
45
|
<div class="cn-schema-form__inline-chips">
|
|
45
46
|
<span v-if="isPropertyRequired(schema, row._key)"
|
|
46
|
-
class="cn-schema-form__property-chip cn-schema-form__chip-primary">Required</span>
|
|
47
|
+
class="cn-schema-form__property-chip cn-schema-form__chip-primary">{{ t('nextcloud-vue', 'Required') }}</span>
|
|
47
48
|
<span v-if="row.immutable"
|
|
48
|
-
class="cn-schema-form__property-chip cn-schema-form__chip-secondary">Immutable</span>
|
|
49
|
+
class="cn-schema-form__property-chip cn-schema-form__chip-secondary">{{ t('nextcloud-vue', 'Immutable') }}</span>
|
|
49
50
|
<span v-if="row.deprecated"
|
|
50
|
-
class="cn-schema-form__property-chip cn-schema-form__chip-warning">Deprecated</span>
|
|
51
|
+
class="cn-schema-form__property-chip cn-schema-form__chip-warning">{{ t('nextcloud-vue', 'Deprecated') }}</span>
|
|
51
52
|
<span v-if="row.visible === false"
|
|
52
|
-
class="cn-schema-form__property-chip cn-schema-form__chip-secondary">Hidden in view</span>
|
|
53
|
+
class="cn-schema-form__property-chip cn-schema-form__chip-secondary">{{ t('nextcloud-vue', 'Hidden in view') }}</span>
|
|
53
54
|
<span v-if="row.hideOnCollection"
|
|
54
|
-
class="cn-schema-form__property-chip cn-schema-form__chip-secondary">Hidden in
|
|
55
|
+
class="cn-schema-form__property-chip cn-schema-form__chip-secondary">{{ t('nextcloud-vue', 'Hidden in collection') }}</span>
|
|
55
56
|
<span v-if="row.hideOnForm"
|
|
56
|
-
class="cn-schema-form__property-chip cn-schema-form__chip-secondary">Hidden in
|
|
57
|
+
class="cn-schema-form__property-chip cn-schema-form__chip-secondary">{{ t('nextcloud-vue', 'Hidden in form') }}</span>
|
|
57
58
|
<span v-if="row.const !== undefined"
|
|
58
|
-
class="cn-schema-form__property-chip cn-schema-form__chip-success">Constant</span>
|
|
59
|
+
class="cn-schema-form__property-chip cn-schema-form__chip-success">{{ t('nextcloud-vue', 'Constant') }}</span>
|
|
59
60
|
<span v-if="row.enum && row.enum.length > 0"
|
|
60
|
-
class="cn-schema-form__property-chip cn-schema-form__chip-success">Enumeration ({{ row.enum.length }}
|
|
61
|
+
class="cn-schema-form__property-chip cn-schema-form__chip-success">{{ t('nextcloud-vue', 'Enumeration ({count})', { count: row.enum.length }) }}</span>
|
|
61
62
|
<span v-if="row.facetable === true || (typeof row.facetable === 'object' && row.facetable !== null)"
|
|
62
|
-
class="cn-schema-form__property-chip cn-schema-form__chip-info">Facetable</span>
|
|
63
|
+
class="cn-schema-form__property-chip cn-schema-form__chip-info">{{ t('nextcloud-vue', 'Facetable') }}</span>
|
|
63
64
|
<span v-if="hasCustomTableSettings(row._key)"
|
|
64
|
-
class="cn-schema-form__property-chip cn-schema-form__chip-table">Table</span>
|
|
65
|
+
class="cn-schema-form__property-chip cn-schema-form__chip-table">{{ t('nextcloud-vue', 'Table') }}</span>
|
|
65
66
|
</div>
|
|
66
67
|
</div>
|
|
67
68
|
</div>
|
|
@@ -72,7 +73,7 @@
|
|
|
72
73
|
v-if="selectedProperty === row._key"
|
|
73
74
|
v-model="schema.properties[row._key].type"
|
|
74
75
|
:options="typeOptionsForSelect"
|
|
75
|
-
input-label="Property
|
|
76
|
+
:input-label="t('nextcloud-vue', 'Property type')"
|
|
76
77
|
@click.stop />
|
|
77
78
|
<span v-else>{{ row.type }}</span>
|
|
78
79
|
</template>
|
|
@@ -95,13 +96,14 @@
|
|
|
95
96
|
</CnDataTable>
|
|
96
97
|
</div>
|
|
97
98
|
<CnNoteCard v-if="propertiesModified && !loading" type="warning" class="cn-schema-form__properties-warning">
|
|
98
|
-
<p>Properties have been modified. Changes will only take effect after the schema is saved
|
|
99
|
+
<p>{{ t('nextcloud-vue', 'Properties have been modified. Changes will only take effect after the schema is saved.') }}</p>
|
|
99
100
|
</CnNoteCard>
|
|
100
101
|
</Fragment>
|
|
101
102
|
</template>
|
|
102
103
|
|
|
103
104
|
<!-- eslint-disable jsdoc/valid-types -->
|
|
104
105
|
<script>
|
|
106
|
+
import { translate as t } from '@nextcloud/l10n'
|
|
105
107
|
import { NcButton, NcTextField, NcSelect } from '@nextcloud/vue'
|
|
106
108
|
import { CnDataTable } from '../CnDataTable/index.js'
|
|
107
109
|
import { CnNoteCard } from '../CnNoteCard/index.js'
|
|
@@ -166,8 +168,8 @@ export default {
|
|
|
166
168
|
nextPropertyId: 1,
|
|
167
169
|
isRenaming: false,
|
|
168
170
|
tableColumns: [
|
|
169
|
-
{ key: '_key', label: 'Name', sortable: false },
|
|
170
|
-
{ key: 'type', label: 'Type', sortable: false },
|
|
171
|
+
{ key: '_key', label: t('nextcloud-vue', 'Name'), sortable: false },
|
|
172
|
+
{ key: 'type', label: t('nextcloud-vue', 'Type'), sortable: false },
|
|
171
173
|
],
|
|
172
174
|
}
|
|
173
175
|
},
|
|
@@ -202,7 +204,7 @@ export default {
|
|
|
202
204
|
},
|
|
203
205
|
watch: {
|
|
204
206
|
selectedProperty(newKey) {
|
|
205
|
-
if (newKey) {
|
|
207
|
+
if (newKey !== null) {
|
|
206
208
|
// Skip focus+select when the change comes from a rename —
|
|
207
209
|
// onPropertyKeyUpdate handles its own cursor positioning.
|
|
208
210
|
if (this.isRenaming) {
|
|
@@ -227,6 +229,7 @@ export default {
|
|
|
227
229
|
},
|
|
228
230
|
},
|
|
229
231
|
methods: {
|
|
232
|
+
t,
|
|
230
233
|
getStablePropertyId(propertyName) {
|
|
231
234
|
if (!this.propertyStableIds[propertyName]) {
|
|
232
235
|
this.propertyStableIds[propertyName] = this.nextPropertyId++
|
|
@@ -265,14 +268,18 @@ export default {
|
|
|
265
268
|
return classes.join(' ')
|
|
266
269
|
},
|
|
267
270
|
|
|
271
|
+
getCellClass(row) {
|
|
272
|
+
return this.selectedProperty === row._key ? 'cn-schema-form__editing-cell' : ''
|
|
273
|
+
},
|
|
274
|
+
|
|
268
275
|
onRowClick(row) {
|
|
269
276
|
if (this.selectedProperty === row._key) return
|
|
270
277
|
this.$emit('update:selected-property', row._key)
|
|
271
278
|
},
|
|
272
279
|
|
|
273
280
|
onPropertyKeyUpdate(oldKey, newKey) {
|
|
274
|
-
if (
|
|
275
|
-
if (this.schema.properties[newKey] && newKey !== oldKey) return
|
|
281
|
+
if (newKey === oldKey) return
|
|
282
|
+
if (this.schema.properties[newKey] !== undefined && newKey !== oldKey) return
|
|
276
283
|
|
|
277
284
|
this.isRenaming = true
|
|
278
285
|
|