@conduction/nextcloud-vue 0.1.0-beta.4 → 0.1.0-beta.6
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 +67614 -0
- package/dist/nextcloud-vue.cjs.js +9559 -8983
- package/dist/nextcloud-vue.cjs.js.map +1 -1
- package/dist/nextcloud-vue.cjs.map +1 -0
- package/dist/nextcloud-vue.css +1231 -1231
- package/dist/nextcloud-vue.esm.js +9559 -8983
- package/dist/nextcloud-vue.esm.js.map +1 -1
- package/package.json +14 -5
- package/src/components/CnActionsBar/CnActionsBar.vue +235 -235
- package/src/components/CnAdvancedFormDialog/CnAdvancedFormDialog.vue +579 -579
- package/src/components/CnAdvancedFormDialog/CnDataTab.vue +217 -217
- package/src/components/CnAdvancedFormDialog/CnMetadataTab.vue +121 -121
- package/src/components/CnAdvancedFormDialog/CnPropertiesTab.vue +418 -418
- package/src/components/CnAdvancedFormDialog/CnPropertyValueCell.vue +247 -247
- package/src/components/CnCardGrid/CnCardGrid.vue +152 -152
- package/src/components/CnCellRenderer/CnCellRenderer.vue +132 -132
- package/src/components/CnChartWidget/CnChartWidget.vue +320 -320
- package/src/components/CnConfigurationCard/CnConfigurationCard.vue +77 -77
- package/src/components/CnCopyDialog/CnCopyDialog.vue +250 -250
- package/src/components/CnDashboardGrid/CnDashboardGrid.vue +225 -225
- package/src/components/CnDashboardPage/CnDashboardPage.vue +390 -390
- package/src/components/CnDataTable/CnDataTable.vue +349 -349
- package/src/components/CnDeleteDialog/CnDeleteDialog.vue +170 -170
- package/src/components/CnDetailCard/CnDetailCard.vue +214 -214
- package/src/components/CnDetailPage/CnDetailPage.vue +285 -281
- package/src/components/CnFacetSidebar/CnFacetSidebar.vue +231 -231
- package/src/components/CnFilterBar/CnFilterBar.vue +152 -152
- package/src/components/CnFormDialog/CnFormDialog.vue +302 -11
- package/src/components/CnIcon/CnIcon.vue +89 -89
- package/src/components/CnIndexPage/CnIndexPage.vue +884 -874
- package/src/components/CnIndexSidebar/CnIndexSidebar.vue +503 -503
- package/src/components/CnItemCard/CnItemCard.vue +132 -132
- package/src/components/CnKpiGrid/CnKpiGrid.vue +89 -89
- package/src/components/CnMassActionBar/CnMassActionBar.vue +160 -160
- package/src/components/CnMassCopyDialog/CnMassCopyDialog.vue +320 -320
- package/src/components/CnMassDeleteDialog/CnMassDeleteDialog.vue +238 -238
- package/src/components/CnMassExportDialog/CnMassExportDialog.vue +190 -190
- package/src/components/CnMassImportDialog/CnMassImportDialog.vue +491 -491
- package/src/components/CnNoteCard/CnNoteCard.vue +149 -149
- package/src/components/CnNotesCard/CnNotesCard.vue +413 -413
- package/src/components/CnObjectCard/CnObjectCard.vue +292 -292
- package/src/components/CnObjectCard/eslint-setup.md +235 -0
- package/src/components/CnObjectCard/package.json-or.json +132 -0
- package/src/components/CnObjectSidebar/CnObjectSidebar.vue +876 -876
- package/src/components/CnPageHeader/CnPageHeader.vue +57 -57
- package/src/components/CnPagination/CnPagination.vue +252 -252
- package/src/components/CnRegisterMapping/CnRegisterMapping.vue +792 -792
- package/src/components/CnRowActions/CnRowActions.vue +95 -73
- package/src/components/CnSchemaFormDialog/CnSchemaConfigurationTab.vue +226 -226
- package/src/components/CnSchemaFormDialog/CnSchemaFormDialog.vue +787 -787
- package/src/components/CnSchemaFormDialog/CnSchemaPropertiesTab.vue +305 -305
- package/src/components/CnSchemaFormDialog/CnSchemaPropertyActions.vue +1398 -1398
- package/src/components/CnSchemaFormDialog/CnSchemaSecurityTab.vue +236 -236
- package/src/components/CnSettingsCard/CnSettingsCard.vue +92 -92
- package/src/components/CnSettingsSection/CnSettingsSection.vue +266 -266
- package/src/components/CnStatsBlock/CnStatsBlock.vue +420 -420
- package/src/components/CnStatusBadge/CnStatusBadge.vue +77 -77
- package/src/components/CnTabbedFormDialog/CnTabbedFormDialog.vue +540 -540
- package/src/components/CnTasksCard/CnTasksCard.vue +373 -373
- package/src/components/CnTileWidget/CnTileWidget.vue +159 -159
- package/src/components/CnTimelineStages/CnTimelineStages.vue +292 -292
- package/src/components/CnUserActionMenu/CnUserActionMenu.vue +435 -435
- package/src/components/CnVersionInfoCard/CnVersionInfoCard.vue +312 -312
- package/src/components/CnWidgetRenderer/CnWidgetRenderer.vue +180 -180
- package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +211 -211
- package/src/index.js +1 -1
- package/src/types/notification.d.ts +13 -13
- package/src/types/organisation.d.ts +15 -15
- package/src/types/schema.d.ts +13 -13
- package/src/types/task.d.ts +6 -6
- package/src/utils/headers.js +5 -3
|
@@ -1,418 +1,418 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="cn-advanced-form-dialog__table-container">
|
|
3
|
-
<table class="cn-advanced-form-dialog__table">
|
|
4
|
-
<thead>
|
|
5
|
-
<tr class="cn-advanced-form-dialog__table-row">
|
|
6
|
-
<th class="cn-advanced-form-dialog__table-col-constrained">
|
|
7
|
-
Property
|
|
8
|
-
</th>
|
|
9
|
-
<th class="cn-advanced-form-dialog__table-col-expanded">
|
|
10
|
-
Value
|
|
11
|
-
</th>
|
|
12
|
-
</tr>
|
|
13
|
-
</thead>
|
|
14
|
-
<tbody>
|
|
15
|
-
<tr
|
|
16
|
-
v-for="([key, value]) in objectProperties"
|
|
17
|
-
:key="key"
|
|
18
|
-
class="cn-advanced-form-dialog__table-row"
|
|
19
|
-
:class="{
|
|
20
|
-
'cn-advanced-form-dialog__table-row--selected': selectedProperty === key,
|
|
21
|
-
'cn-advanced-form-dialog__table-row--edited': formData[key] !== undefined,
|
|
22
|
-
'cn-advanced-form-dialog__table-row--non-editable': !isPropertyEditable(key, resolvedValue(key, value)),
|
|
23
|
-
[getPropertyValidationClass(key, value)]: validationDisplay === 'indicator',
|
|
24
|
-
}"
|
|
25
|
-
@click="handleRowClick(key, $event)">
|
|
26
|
-
<td class="cn-advanced-form-dialog__table-col-constrained cn-advanced-form-dialog__prop-cell">
|
|
27
|
-
<div class="cn-advanced-form-dialog__prop-cell-content">
|
|
28
|
-
<AlertCircle
|
|
29
|
-
v-if="validationDisplay === 'indicator' && getPropertyValidationState(key, resolvedValue(key, value)) === 'invalid'"
|
|
30
|
-
class="cn-advanced-form-dialog__validation-icon cn-advanced-form-dialog__validation-icon--error"
|
|
31
|
-
:size="16"
|
|
32
|
-
:title="getPropertyErrorMessage(key, resolvedValue(key, value))" />
|
|
33
|
-
<Alert
|
|
34
|
-
v-else-if="validationDisplay === 'indicator' && getPropertyValidationState(key, resolvedValue(key, value)) === 'warning'"
|
|
35
|
-
class="cn-advanced-form-dialog__validation-icon cn-advanced-form-dialog__validation-icon--warning"
|
|
36
|
-
:size="16"
|
|
37
|
-
:title="getPropertyWarningMessage(key, resolvedValue(key, value))" />
|
|
38
|
-
<Plus
|
|
39
|
-
v-else-if="validationDisplay === 'indicator' && getPropertyValidationState(key, resolvedValue(key, value)) === 'new'"
|
|
40
|
-
class="cn-advanced-form-dialog__validation-icon cn-advanced-form-dialog__validation-icon--new"
|
|
41
|
-
:size="16"
|
|
42
|
-
:title="getPropertyNewMessage(key)" />
|
|
43
|
-
<LockOutline
|
|
44
|
-
v-else-if="!isPropertyEditable(key, resolvedValue(key, value))"
|
|
45
|
-
class="cn-advanced-form-dialog__validation-icon cn-advanced-form-dialog__validation-icon--lock"
|
|
46
|
-
:size="16"
|
|
47
|
-
:title="getEditabilityWarning(key, resolvedValue(key, value)) || ''" />
|
|
48
|
-
<span :title="getPropertyTooltip(key)">{{ getPropertyDisplayName(key) }}</span>
|
|
49
|
-
</div>
|
|
50
|
-
</td>
|
|
51
|
-
<td class="cn-advanced-form-dialog__table-col-expanded cn-advanced-form-dialog__value-cell">
|
|
52
|
-
<CnPropertyValueCell
|
|
53
|
-
:ref="'cell-' + key"
|
|
54
|
-
:property-key="key"
|
|
55
|
-
:schema="schema"
|
|
56
|
-
:value="resolvedValue(key, value)"
|
|
57
|
-
:is-editable="isPropertyEditable(key, resolvedValue(key, value))"
|
|
58
|
-
:is-editing="selectedProperty === key"
|
|
59
|
-
:display-name="getPropertyDisplayName(key)"
|
|
60
|
-
:editability-warning="getPropertyEditabilityWarning(key, resolvedValue(key, value))"
|
|
61
|
-
@update:value="onPropertyValueUpdate(key, $event)" />
|
|
62
|
-
</td>
|
|
63
|
-
</tr>
|
|
64
|
-
</tbody>
|
|
65
|
-
</table>
|
|
66
|
-
</div>
|
|
67
|
-
</template>
|
|
68
|
-
|
|
69
|
-
<script>
|
|
70
|
-
import AlertCircle from 'vue-material-design-icons/AlertCircle.vue'
|
|
71
|
-
import Alert from 'vue-material-design-icons/Alert.vue'
|
|
72
|
-
import LockOutline from 'vue-material-design-icons/LockOutline.vue'
|
|
73
|
-
import Plus from 'vue-material-design-icons/Plus.vue'
|
|
74
|
-
import CnPropertyValueCell from './CnPropertyValueCell.vue'
|
|
75
|
-
|
|
76
|
-
export default {
|
|
77
|
-
name: 'CnPropertiesTab',
|
|
78
|
-
|
|
79
|
-
components: {
|
|
80
|
-
AlertCircle,
|
|
81
|
-
Alert,
|
|
82
|
-
LockOutline,
|
|
83
|
-
Plus,
|
|
84
|
-
CnPropertyValueCell,
|
|
85
|
-
},
|
|
86
|
-
|
|
87
|
-
props: {
|
|
88
|
-
schema: { type: Object, default: null },
|
|
89
|
-
item: { type: Object, default: null },
|
|
90
|
-
formData: { type: Object, default: () => ({}) },
|
|
91
|
-
selectedProperty: { type: String, default: null },
|
|
92
|
-
editableTypes: { type: Array, default: () => ['string', 'number', 'integer', 'boolean'] },
|
|
93
|
-
validationDisplay: { type: String, default: 'indicator' },
|
|
94
|
-
excludeFields: { type: Array, default: () => [] },
|
|
95
|
-
includeFields: { type: Array, default: null },
|
|
96
|
-
},
|
|
97
|
-
|
|
98
|
-
computed: {
|
|
99
|
-
objectProperties() {
|
|
100
|
-
const schemaProps = this.schema?.properties || {}
|
|
101
|
-
const obj = this.item || {}
|
|
102
|
-
const exclude = this.excludeFields || []
|
|
103
|
-
const include = this.includeFields
|
|
104
|
-
const filterKey = (k) => {
|
|
105
|
-
if (k === '@self' || k === 'id') return false
|
|
106
|
-
if (exclude.includes(k)) return false
|
|
107
|
-
if (include && !include.includes(k)) return false
|
|
108
|
-
return true
|
|
109
|
-
}
|
|
110
|
-
const existing = Object.entries(obj).filter(([k]) => filterKey(k))
|
|
111
|
-
const missing = []
|
|
112
|
-
for (const [key, prop] of Object.entries(schemaProps)) {
|
|
113
|
-
if (!filterKey(key)) continue
|
|
114
|
-
if (!Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
115
|
-
let def
|
|
116
|
-
switch (prop.type) {
|
|
117
|
-
case 'string': def = prop.const ?? ''; break
|
|
118
|
-
case 'number':
|
|
119
|
-
case 'integer': def = 0; break
|
|
120
|
-
case 'boolean': def = false; break
|
|
121
|
-
case 'array': def = []; break
|
|
122
|
-
case 'object': def = {}; break
|
|
123
|
-
default: def = ''
|
|
124
|
-
}
|
|
125
|
-
missing.push([key, def])
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
return [...existing, ...missing]
|
|
129
|
-
},
|
|
130
|
-
},
|
|
131
|
-
|
|
132
|
-
methods: {
|
|
133
|
-
/** The effective value for a key: formData override or the object's own value */
|
|
134
|
-
resolvedValue(key, objectValue) {
|
|
135
|
-
return this.formData[key] !== undefined ? this.formData[key] : objectValue
|
|
136
|
-
},
|
|
137
|
-
|
|
138
|
-
onPropertyValueUpdate(key, value) {
|
|
139
|
-
this.$emit('update:property-value', { key, value })
|
|
140
|
-
},
|
|
141
|
-
|
|
142
|
-
isPropertyEditable(key, value) {
|
|
143
|
-
const prop = this.schema?.properties?.[key]
|
|
144
|
-
if (!prop) return true
|
|
145
|
-
if (prop.const !== undefined) return false
|
|
146
|
-
if (prop.immutable && value != null && value !== '') return false
|
|
147
|
-
const type = prop.type || 'string'
|
|
148
|
-
return this.editableTypes.includes(type)
|
|
149
|
-
},
|
|
150
|
-
|
|
151
|
-
getPropertyDisplayName(key) {
|
|
152
|
-
return (this.schema?.properties?.[key]?.title) || key
|
|
153
|
-
},
|
|
154
|
-
|
|
155
|
-
getPropertyTooltip(key) {
|
|
156
|
-
const prop = this.schema?.properties?.[key]
|
|
157
|
-
if (prop?.description) {
|
|
158
|
-
if (prop.title && prop.title !== key) {
|
|
159
|
-
return `${prop.title}: ${prop.description}`
|
|
160
|
-
}
|
|
161
|
-
return prop.description
|
|
162
|
-
}
|
|
163
|
-
return `Property: ${key}`
|
|
164
|
-
},
|
|
165
|
-
|
|
166
|
-
getPropertyValidationClass(key, value) {
|
|
167
|
-
const state = this.getPropertyValidationState(key, value)
|
|
168
|
-
switch (state) {
|
|
169
|
-
case 'invalid': return 'cn-advanced-form-dialog__table-row--invalid'
|
|
170
|
-
case 'warning': return 'cn-advanced-form-dialog__table-row--warning'
|
|
171
|
-
case 'new': return 'cn-advanced-form-dialog__table-row--new'
|
|
172
|
-
case 'valid': return 'cn-advanced-form-dialog__table-row--valid'
|
|
173
|
-
default: return ''
|
|
174
|
-
}
|
|
175
|
-
},
|
|
176
|
-
|
|
177
|
-
getPropertyValidationState(key, value) {
|
|
178
|
-
const prop = this.schema?.properties?.[key]
|
|
179
|
-
const existsInObject = this.item ? Object.prototype.hasOwnProperty.call(this.item, key) : false
|
|
180
|
-
if (!prop) return 'warning'
|
|
181
|
-
if (!existsInObject) return 'new'
|
|
182
|
-
if (this.isValidPropertyValue(key, value, prop)) return 'valid'
|
|
183
|
-
return 'invalid'
|
|
184
|
-
},
|
|
185
|
-
|
|
186
|
-
isValidPropertyValue(key, value, schemaProperty) {
|
|
187
|
-
if (value === null || value === undefined || value === '') {
|
|
188
|
-
const required = (this.schema?.required || []).includes(key) || schemaProperty?.required
|
|
189
|
-
return !required
|
|
190
|
-
}
|
|
191
|
-
const type = schemaProperty?.type || 'string'
|
|
192
|
-
switch (type) {
|
|
193
|
-
case 'string':
|
|
194
|
-
if (typeof value !== 'string') return false
|
|
195
|
-
if (schemaProperty?.format === 'date-time' && !this.isValidDate(value)) return false
|
|
196
|
-
if (schemaProperty?.const && value !== schemaProperty.const) return false
|
|
197
|
-
return true
|
|
198
|
-
case 'number':
|
|
199
|
-
return typeof value === 'number' && !Number.isNaN(value)
|
|
200
|
-
case 'boolean':
|
|
201
|
-
return typeof value === 'boolean'
|
|
202
|
-
case 'array':
|
|
203
|
-
return Array.isArray(value)
|
|
204
|
-
case 'object':
|
|
205
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
206
|
-
default:
|
|
207
|
-
return true
|
|
208
|
-
}
|
|
209
|
-
},
|
|
210
|
-
|
|
211
|
-
getPropertyErrorMessage(key, value) {
|
|
212
|
-
const prop = this.schema?.properties?.[key]
|
|
213
|
-
if (!prop) {
|
|
214
|
-
return `Property '${key}' is not defined in the current schema. This property exists in the object but is not part of the schema definition.`
|
|
215
|
-
}
|
|
216
|
-
const isRequired = (this.schema?.required || []).includes(key) || prop.required
|
|
217
|
-
if ((value === null || value === undefined || value === '') && isRequired) {
|
|
218
|
-
return `Required property '${key}' is missing or empty.`
|
|
219
|
-
}
|
|
220
|
-
const expectedType = prop.type
|
|
221
|
-
const actualType = Array.isArray(value) ? 'array' : typeof value
|
|
222
|
-
if (expectedType && expectedType !== actualType) {
|
|
223
|
-
return `Property '${key}' should be ${expectedType} but is ${actualType}.`
|
|
224
|
-
}
|
|
225
|
-
if (prop.format === 'date-time' && !this.isValidDate(value)) {
|
|
226
|
-
return `Property '${key}' should be a valid date-time value.`
|
|
227
|
-
}
|
|
228
|
-
if (prop.const && value !== prop.const) {
|
|
229
|
-
return `Property '${key}' should be '${prop.const}' but is '${value}'.`
|
|
230
|
-
}
|
|
231
|
-
return `Property '${key}' has an invalid value.`
|
|
232
|
-
},
|
|
233
|
-
|
|
234
|
-
getPropertyWarningMessage(key, value) {
|
|
235
|
-
const displayValue = String(value).length > 100 ? String(value).slice(0, 100) + '…' : String(value)
|
|
236
|
-
return `Property '${key}' exists in the object but is not defined in the current schema. This might happen when property names are changed in the schema. Current value: '${displayValue}'.`
|
|
237
|
-
},
|
|
238
|
-
|
|
239
|
-
getPropertyNewMessage(key) {
|
|
240
|
-
return `Property '${key}' is defined in the schema but doesn't have a value yet. Click to add a value.`
|
|
241
|
-
},
|
|
242
|
-
|
|
243
|
-
getPropertyEditabilityWarning(key, value) {
|
|
244
|
-
if (!this.isPropertyEditable(key, value)) {
|
|
245
|
-
return 'This property cannot be edited in the Properties tab. Use the Data tab to modify it.'
|
|
246
|
-
}
|
|
247
|
-
return null
|
|
248
|
-
},
|
|
249
|
-
|
|
250
|
-
getEditabilityWarning(key, value) {
|
|
251
|
-
const prop = this.schema?.properties?.[key]
|
|
252
|
-
if (prop?.const !== undefined) {
|
|
253
|
-
return `This property is constant and must always be '${prop.const}'. Const properties cannot be modified to maintain data integrity.`
|
|
254
|
-
}
|
|
255
|
-
if (prop?.immutable && (value !== null && value !== undefined && value !== '')) {
|
|
256
|
-
const displayValue = String(value).length > 100 ? String(value).slice(0, 100) + '…' : String(value)
|
|
257
|
-
return `This property is immutable and cannot be changed once it has a value. Current value: '${displayValue}'. Immutable properties preserve data consistency.`
|
|
258
|
-
}
|
|
259
|
-
if (!this.isPropertyEditable(key, value)) {
|
|
260
|
-
return this.getPropertyEditabilityWarning(key, value)
|
|
261
|
-
}
|
|
262
|
-
return null
|
|
263
|
-
},
|
|
264
|
-
|
|
265
|
-
handleRowClick(key, event) {
|
|
266
|
-
if (event.target.tagName === 'INPUT' || event.target.tagName === 'BUTTON' || event.target.closest('.cn-advanced-form-dialog__value-input-container')) return
|
|
267
|
-
const value = this.resolvedValue(key, this.objectProperties.find(([k]) => k === key)?.[1])
|
|
268
|
-
if (!this.isPropertyEditable(key, value)) return
|
|
269
|
-
const prop = this.schema?.properties?.[key]
|
|
270
|
-
if (prop && !this.editableTypes.includes(prop.type || 'string')) return
|
|
271
|
-
this.$emit('update:selected-property', key)
|
|
272
|
-
this.$nextTick(() => {
|
|
273
|
-
const ref = this.$refs['cell-' + key]
|
|
274
|
-
const cell = ref && (Array.isArray(ref) ? ref[0] : ref)
|
|
275
|
-
if (cell && cell.focus) cell.focus()
|
|
276
|
-
})
|
|
277
|
-
},
|
|
278
|
-
|
|
279
|
-
isValidDate(v) {
|
|
280
|
-
if (!v) return false
|
|
281
|
-
const d = new Date(v)
|
|
282
|
-
return d instanceof Date && !Number.isNaN(d.getTime())
|
|
283
|
-
},
|
|
284
|
-
},
|
|
285
|
-
}
|
|
286
|
-
</script>
|
|
287
|
-
|
|
288
|
-
<style scoped>
|
|
289
|
-
.cn-advanced-form-dialog__table-container {
|
|
290
|
-
background: var(--color-main-background);
|
|
291
|
-
border-radius: var(--border-radius);
|
|
292
|
-
overflow: hidden;
|
|
293
|
-
box-shadow: 0 2px 4px var(--color-box-shadow);
|
|
294
|
-
border: 1px solid var(--color-border);
|
|
295
|
-
margin-bottom: calc(5 * var(--default-grid-baseline));
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
.cn-advanced-form-dialog__table {
|
|
299
|
-
width: 100%;
|
|
300
|
-
border-collapse: collapse;
|
|
301
|
-
background-color: var(--color-main-background);
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
.cn-advanced-form-dialog__table th,
|
|
305
|
-
.cn-advanced-form-dialog__table td {
|
|
306
|
-
padding: calc(3 * var(--default-grid-baseline));
|
|
307
|
-
text-align: left;
|
|
308
|
-
border-bottom: 1px solid var(--color-border);
|
|
309
|
-
vertical-align: middle;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
.cn-advanced-form-dialog__table th {
|
|
313
|
-
background: var(--color-background-dark);
|
|
314
|
-
font-weight: 500;
|
|
315
|
-
color: var(--color-text-maxcontrast);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
.cn-advanced-form-dialog__table-row {
|
|
319
|
-
cursor: pointer;
|
|
320
|
-
transition: background-color 0.2s ease;
|
|
321
|
-
background-color: var(--color-main-background);
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
.cn-advanced-form-dialog__table-row:hover {
|
|
325
|
-
background-color: var(--color-background-hover);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
/* Active/selected row: light blue; ensure it wins over validation state classes */
|
|
329
|
-
.cn-advanced-form-dialog__table-row.cn-advanced-form-dialog__table-row--selected,
|
|
330
|
-
.cn-advanced-form-dialog__table-row--selected:hover {
|
|
331
|
-
background-color: var(--color-primary-light);
|
|
332
|
-
box-shadow: inset 3px 0 0 0 var(--color-primary);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
.cn-advanced-form-dialog__table-row--edited {
|
|
336
|
-
background-color: var(--color-success-light);
|
|
337
|
-
box-shadow: inset 3px 0 0 0 var(--color-success);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
.cn-advanced-form-dialog__table-row--non-editable {
|
|
341
|
-
background-color: var(--color-background-dark);
|
|
342
|
-
cursor: not-allowed;
|
|
343
|
-
opacity: 0.7;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
.cn-advanced-form-dialog__table-row--non-editable * {
|
|
347
|
-
cursor: not-allowed !important;
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
.cn-advanced-form-dialog__table-row--valid {
|
|
351
|
-
box-shadow: inset 3px 0 0 0 var(--color-success);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
.cn-advanced-form-dialog__table-row--invalid {
|
|
355
|
-
background-color: var(--color-error-light);
|
|
356
|
-
box-shadow: inset 3px 0 0 0 var(--color-error);
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
.cn-advanced-form-dialog__table-row--warning {
|
|
360
|
-
background-color: var(--color-warning-light);
|
|
361
|
-
box-shadow: inset 3px 0 0 0 var(--color-warning);
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
.cn-advanced-form-dialog__table-row--new {
|
|
365
|
-
box-shadow: inset 3px 0 0 0 var(--color-primary-element);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
.cn-advanced-form-dialog__table-col-constrained {
|
|
369
|
-
width: 150px;
|
|
370
|
-
max-width: 150px;
|
|
371
|
-
overflow: hidden;
|
|
372
|
-
text-overflow: ellipsis;
|
|
373
|
-
white-space: nowrap;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
.cn-advanced-form-dialog__table-col-expanded {
|
|
377
|
-
width: auto;
|
|
378
|
-
min-width: 200px;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
.cn-advanced-form-dialog__prop-cell {
|
|
382
|
-
width: 30%;
|
|
383
|
-
font-weight: 600;
|
|
384
|
-
box-shadow: inset 3px 0 0 0 var(--color-primary);
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
.cn-advanced-form-dialog__value-cell {
|
|
388
|
-
width: 70%;
|
|
389
|
-
word-break: break-word;
|
|
390
|
-
border-radius: 4px;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
.cn-advanced-form-dialog__prop-cell-content {
|
|
394
|
-
display: flex;
|
|
395
|
-
align-items: center;
|
|
396
|
-
gap: 8px;
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
.cn-advanced-form-dialog__validation-icon {
|
|
400
|
-
flex-shrink: 0;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
.cn-advanced-form-dialog__validation-icon--error {
|
|
404
|
-
color: var(--color-error);
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
.cn-advanced-form-dialog__validation-icon--warning {
|
|
408
|
-
color: var(--color-warning);
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
.cn-advanced-form-dialog__validation-icon--lock {
|
|
412
|
-
color: var(--color-text-lighter);
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
.cn-advanced-form-dialog__validation-icon--new {
|
|
416
|
-
color: var(--color-primary-element);
|
|
417
|
-
}
|
|
418
|
-
</style>
|
|
1
|
+
<template>
|
|
2
|
+
<div class="cn-advanced-form-dialog__table-container">
|
|
3
|
+
<table class="cn-advanced-form-dialog__table">
|
|
4
|
+
<thead>
|
|
5
|
+
<tr class="cn-advanced-form-dialog__table-row">
|
|
6
|
+
<th class="cn-advanced-form-dialog__table-col-constrained">
|
|
7
|
+
Property
|
|
8
|
+
</th>
|
|
9
|
+
<th class="cn-advanced-form-dialog__table-col-expanded">
|
|
10
|
+
Value
|
|
11
|
+
</th>
|
|
12
|
+
</tr>
|
|
13
|
+
</thead>
|
|
14
|
+
<tbody>
|
|
15
|
+
<tr
|
|
16
|
+
v-for="([key, value]) in objectProperties"
|
|
17
|
+
:key="key"
|
|
18
|
+
class="cn-advanced-form-dialog__table-row"
|
|
19
|
+
:class="{
|
|
20
|
+
'cn-advanced-form-dialog__table-row--selected': selectedProperty === key,
|
|
21
|
+
'cn-advanced-form-dialog__table-row--edited': formData[key] !== undefined,
|
|
22
|
+
'cn-advanced-form-dialog__table-row--non-editable': !isPropertyEditable(key, resolvedValue(key, value)),
|
|
23
|
+
[getPropertyValidationClass(key, value)]: validationDisplay === 'indicator',
|
|
24
|
+
}"
|
|
25
|
+
@click="handleRowClick(key, $event)">
|
|
26
|
+
<td class="cn-advanced-form-dialog__table-col-constrained cn-advanced-form-dialog__prop-cell">
|
|
27
|
+
<div class="cn-advanced-form-dialog__prop-cell-content">
|
|
28
|
+
<AlertCircle
|
|
29
|
+
v-if="validationDisplay === 'indicator' && getPropertyValidationState(key, resolvedValue(key, value)) === 'invalid'"
|
|
30
|
+
class="cn-advanced-form-dialog__validation-icon cn-advanced-form-dialog__validation-icon--error"
|
|
31
|
+
:size="16"
|
|
32
|
+
:title="getPropertyErrorMessage(key, resolvedValue(key, value))" />
|
|
33
|
+
<Alert
|
|
34
|
+
v-else-if="validationDisplay === 'indicator' && getPropertyValidationState(key, resolvedValue(key, value)) === 'warning'"
|
|
35
|
+
class="cn-advanced-form-dialog__validation-icon cn-advanced-form-dialog__validation-icon--warning"
|
|
36
|
+
:size="16"
|
|
37
|
+
:title="getPropertyWarningMessage(key, resolvedValue(key, value))" />
|
|
38
|
+
<Plus
|
|
39
|
+
v-else-if="validationDisplay === 'indicator' && getPropertyValidationState(key, resolvedValue(key, value)) === 'new'"
|
|
40
|
+
class="cn-advanced-form-dialog__validation-icon cn-advanced-form-dialog__validation-icon--new"
|
|
41
|
+
:size="16"
|
|
42
|
+
:title="getPropertyNewMessage(key)" />
|
|
43
|
+
<LockOutline
|
|
44
|
+
v-else-if="!isPropertyEditable(key, resolvedValue(key, value))"
|
|
45
|
+
class="cn-advanced-form-dialog__validation-icon cn-advanced-form-dialog__validation-icon--lock"
|
|
46
|
+
:size="16"
|
|
47
|
+
:title="getEditabilityWarning(key, resolvedValue(key, value)) || ''" />
|
|
48
|
+
<span :title="getPropertyTooltip(key)">{{ getPropertyDisplayName(key) }}</span>
|
|
49
|
+
</div>
|
|
50
|
+
</td>
|
|
51
|
+
<td class="cn-advanced-form-dialog__table-col-expanded cn-advanced-form-dialog__value-cell">
|
|
52
|
+
<CnPropertyValueCell
|
|
53
|
+
:ref="'cell-' + key"
|
|
54
|
+
:property-key="key"
|
|
55
|
+
:schema="schema"
|
|
56
|
+
:value="resolvedValue(key, value)"
|
|
57
|
+
:is-editable="isPropertyEditable(key, resolvedValue(key, value))"
|
|
58
|
+
:is-editing="selectedProperty === key"
|
|
59
|
+
:display-name="getPropertyDisplayName(key)"
|
|
60
|
+
:editability-warning="getPropertyEditabilityWarning(key, resolvedValue(key, value))"
|
|
61
|
+
@update:value="onPropertyValueUpdate(key, $event)" />
|
|
62
|
+
</td>
|
|
63
|
+
</tr>
|
|
64
|
+
</tbody>
|
|
65
|
+
</table>
|
|
66
|
+
</div>
|
|
67
|
+
</template>
|
|
68
|
+
|
|
69
|
+
<script>
|
|
70
|
+
import AlertCircle from 'vue-material-design-icons/AlertCircle.vue'
|
|
71
|
+
import Alert from 'vue-material-design-icons/Alert.vue'
|
|
72
|
+
import LockOutline from 'vue-material-design-icons/LockOutline.vue'
|
|
73
|
+
import Plus from 'vue-material-design-icons/Plus.vue'
|
|
74
|
+
import CnPropertyValueCell from './CnPropertyValueCell.vue'
|
|
75
|
+
|
|
76
|
+
export default {
|
|
77
|
+
name: 'CnPropertiesTab',
|
|
78
|
+
|
|
79
|
+
components: {
|
|
80
|
+
AlertCircle,
|
|
81
|
+
Alert,
|
|
82
|
+
LockOutline,
|
|
83
|
+
Plus,
|
|
84
|
+
CnPropertyValueCell,
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
props: {
|
|
88
|
+
schema: { type: Object, default: null },
|
|
89
|
+
item: { type: Object, default: null },
|
|
90
|
+
formData: { type: Object, default: () => ({}) },
|
|
91
|
+
selectedProperty: { type: String, default: null },
|
|
92
|
+
editableTypes: { type: Array, default: () => ['string', 'number', 'integer', 'boolean'] },
|
|
93
|
+
validationDisplay: { type: String, default: 'indicator' },
|
|
94
|
+
excludeFields: { type: Array, default: () => [] },
|
|
95
|
+
includeFields: { type: Array, default: null },
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
computed: {
|
|
99
|
+
objectProperties() {
|
|
100
|
+
const schemaProps = this.schema?.properties || {}
|
|
101
|
+
const obj = this.item || {}
|
|
102
|
+
const exclude = this.excludeFields || []
|
|
103
|
+
const include = this.includeFields
|
|
104
|
+
const filterKey = (k) => {
|
|
105
|
+
if (k === '@self' || k === 'id') return false
|
|
106
|
+
if (exclude.includes(k)) return false
|
|
107
|
+
if (include && !include.includes(k)) return false
|
|
108
|
+
return true
|
|
109
|
+
}
|
|
110
|
+
const existing = Object.entries(obj).filter(([k]) => filterKey(k))
|
|
111
|
+
const missing = []
|
|
112
|
+
for (const [key, prop] of Object.entries(schemaProps)) {
|
|
113
|
+
if (!filterKey(key)) continue
|
|
114
|
+
if (!Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
115
|
+
let def
|
|
116
|
+
switch (prop.type) {
|
|
117
|
+
case 'string': def = prop.const ?? ''; break
|
|
118
|
+
case 'number':
|
|
119
|
+
case 'integer': def = 0; break
|
|
120
|
+
case 'boolean': def = false; break
|
|
121
|
+
case 'array': def = []; break
|
|
122
|
+
case 'object': def = {}; break
|
|
123
|
+
default: def = ''
|
|
124
|
+
}
|
|
125
|
+
missing.push([key, def])
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return [...existing, ...missing]
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
methods: {
|
|
133
|
+
/** The effective value for a key: formData override or the object's own value */
|
|
134
|
+
resolvedValue(key, objectValue) {
|
|
135
|
+
return this.formData[key] !== undefined ? this.formData[key] : objectValue
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
onPropertyValueUpdate(key, value) {
|
|
139
|
+
this.$emit('update:property-value', { key, value })
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
isPropertyEditable(key, value) {
|
|
143
|
+
const prop = this.schema?.properties?.[key]
|
|
144
|
+
if (!prop) return true
|
|
145
|
+
if (prop.const !== undefined) return false
|
|
146
|
+
if (prop.immutable && value != null && value !== '') return false
|
|
147
|
+
const type = prop.type || 'string'
|
|
148
|
+
return this.editableTypes.includes(type)
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
getPropertyDisplayName(key) {
|
|
152
|
+
return (this.schema?.properties?.[key]?.title) || key
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
getPropertyTooltip(key) {
|
|
156
|
+
const prop = this.schema?.properties?.[key]
|
|
157
|
+
if (prop?.description) {
|
|
158
|
+
if (prop.title && prop.title !== key) {
|
|
159
|
+
return `${prop.title}: ${prop.description}`
|
|
160
|
+
}
|
|
161
|
+
return prop.description
|
|
162
|
+
}
|
|
163
|
+
return `Property: ${key}`
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
getPropertyValidationClass(key, value) {
|
|
167
|
+
const state = this.getPropertyValidationState(key, value)
|
|
168
|
+
switch (state) {
|
|
169
|
+
case 'invalid': return 'cn-advanced-form-dialog__table-row--invalid'
|
|
170
|
+
case 'warning': return 'cn-advanced-form-dialog__table-row--warning'
|
|
171
|
+
case 'new': return 'cn-advanced-form-dialog__table-row--new'
|
|
172
|
+
case 'valid': return 'cn-advanced-form-dialog__table-row--valid'
|
|
173
|
+
default: return ''
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
getPropertyValidationState(key, value) {
|
|
178
|
+
const prop = this.schema?.properties?.[key]
|
|
179
|
+
const existsInObject = this.item ? Object.prototype.hasOwnProperty.call(this.item, key) : false
|
|
180
|
+
if (!prop) return 'warning'
|
|
181
|
+
if (!existsInObject) return 'new'
|
|
182
|
+
if (this.isValidPropertyValue(key, value, prop)) return 'valid'
|
|
183
|
+
return 'invalid'
|
|
184
|
+
},
|
|
185
|
+
|
|
186
|
+
isValidPropertyValue(key, value, schemaProperty) {
|
|
187
|
+
if (value === null || value === undefined || value === '') {
|
|
188
|
+
const required = (this.schema?.required || []).includes(key) || schemaProperty?.required
|
|
189
|
+
return !required
|
|
190
|
+
}
|
|
191
|
+
const type = schemaProperty?.type || 'string'
|
|
192
|
+
switch (type) {
|
|
193
|
+
case 'string':
|
|
194
|
+
if (typeof value !== 'string') return false
|
|
195
|
+
if (schemaProperty?.format === 'date-time' && !this.isValidDate(value)) return false
|
|
196
|
+
if (schemaProperty?.const && value !== schemaProperty.const) return false
|
|
197
|
+
return true
|
|
198
|
+
case 'number':
|
|
199
|
+
return typeof value === 'number' && !Number.isNaN(value)
|
|
200
|
+
case 'boolean':
|
|
201
|
+
return typeof value === 'boolean'
|
|
202
|
+
case 'array':
|
|
203
|
+
return Array.isArray(value)
|
|
204
|
+
case 'object':
|
|
205
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
206
|
+
default:
|
|
207
|
+
return true
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
|
|
211
|
+
getPropertyErrorMessage(key, value) {
|
|
212
|
+
const prop = this.schema?.properties?.[key]
|
|
213
|
+
if (!prop) {
|
|
214
|
+
return `Property '${key}' is not defined in the current schema. This property exists in the object but is not part of the schema definition.`
|
|
215
|
+
}
|
|
216
|
+
const isRequired = (this.schema?.required || []).includes(key) || prop.required
|
|
217
|
+
if ((value === null || value === undefined || value === '') && isRequired) {
|
|
218
|
+
return `Required property '${key}' is missing or empty.`
|
|
219
|
+
}
|
|
220
|
+
const expectedType = prop.type
|
|
221
|
+
const actualType = Array.isArray(value) ? 'array' : typeof value
|
|
222
|
+
if (expectedType && expectedType !== actualType) {
|
|
223
|
+
return `Property '${key}' should be ${expectedType} but is ${actualType}.`
|
|
224
|
+
}
|
|
225
|
+
if (prop.format === 'date-time' && !this.isValidDate(value)) {
|
|
226
|
+
return `Property '${key}' should be a valid date-time value.`
|
|
227
|
+
}
|
|
228
|
+
if (prop.const && value !== prop.const) {
|
|
229
|
+
return `Property '${key}' should be '${prop.const}' but is '${value}'.`
|
|
230
|
+
}
|
|
231
|
+
return `Property '${key}' has an invalid value.`
|
|
232
|
+
},
|
|
233
|
+
|
|
234
|
+
getPropertyWarningMessage(key, value) {
|
|
235
|
+
const displayValue = String(value).length > 100 ? String(value).slice(0, 100) + '…' : String(value)
|
|
236
|
+
return `Property '${key}' exists in the object but is not defined in the current schema. This might happen when property names are changed in the schema. Current value: '${displayValue}'.`
|
|
237
|
+
},
|
|
238
|
+
|
|
239
|
+
getPropertyNewMessage(key) {
|
|
240
|
+
return `Property '${key}' is defined in the schema but doesn't have a value yet. Click to add a value.`
|
|
241
|
+
},
|
|
242
|
+
|
|
243
|
+
getPropertyEditabilityWarning(key, value) {
|
|
244
|
+
if (!this.isPropertyEditable(key, value)) {
|
|
245
|
+
return 'This property cannot be edited in the Properties tab. Use the Data tab to modify it.'
|
|
246
|
+
}
|
|
247
|
+
return null
|
|
248
|
+
},
|
|
249
|
+
|
|
250
|
+
getEditabilityWarning(key, value) {
|
|
251
|
+
const prop = this.schema?.properties?.[key]
|
|
252
|
+
if (prop?.const !== undefined) {
|
|
253
|
+
return `This property is constant and must always be '${prop.const}'. Const properties cannot be modified to maintain data integrity.`
|
|
254
|
+
}
|
|
255
|
+
if (prop?.immutable && (value !== null && value !== undefined && value !== '')) {
|
|
256
|
+
const displayValue = String(value).length > 100 ? String(value).slice(0, 100) + '…' : String(value)
|
|
257
|
+
return `This property is immutable and cannot be changed once it has a value. Current value: '${displayValue}'. Immutable properties preserve data consistency.`
|
|
258
|
+
}
|
|
259
|
+
if (!this.isPropertyEditable(key, value)) {
|
|
260
|
+
return this.getPropertyEditabilityWarning(key, value)
|
|
261
|
+
}
|
|
262
|
+
return null
|
|
263
|
+
},
|
|
264
|
+
|
|
265
|
+
handleRowClick(key, event) {
|
|
266
|
+
if (event.target.tagName === 'INPUT' || event.target.tagName === 'BUTTON' || event.target.closest('.cn-advanced-form-dialog__value-input-container')) return
|
|
267
|
+
const value = this.resolvedValue(key, this.objectProperties.find(([k]) => k === key)?.[1])
|
|
268
|
+
if (!this.isPropertyEditable(key, value)) return
|
|
269
|
+
const prop = this.schema?.properties?.[key]
|
|
270
|
+
if (prop && !this.editableTypes.includes(prop.type || 'string')) return
|
|
271
|
+
this.$emit('update:selected-property', key)
|
|
272
|
+
this.$nextTick(() => {
|
|
273
|
+
const ref = this.$refs['cell-' + key]
|
|
274
|
+
const cell = ref && (Array.isArray(ref) ? ref[0] : ref)
|
|
275
|
+
if (cell && cell.focus) cell.focus()
|
|
276
|
+
})
|
|
277
|
+
},
|
|
278
|
+
|
|
279
|
+
isValidDate(v) {
|
|
280
|
+
if (!v) return false
|
|
281
|
+
const d = new Date(v)
|
|
282
|
+
return d instanceof Date && !Number.isNaN(d.getTime())
|
|
283
|
+
},
|
|
284
|
+
},
|
|
285
|
+
}
|
|
286
|
+
</script>
|
|
287
|
+
|
|
288
|
+
<style scoped>
|
|
289
|
+
.cn-advanced-form-dialog__table-container {
|
|
290
|
+
background: var(--color-main-background);
|
|
291
|
+
border-radius: var(--border-radius);
|
|
292
|
+
overflow: hidden;
|
|
293
|
+
box-shadow: 0 2px 4px var(--color-box-shadow);
|
|
294
|
+
border: 1px solid var(--color-border);
|
|
295
|
+
margin-bottom: calc(5 * var(--default-grid-baseline));
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.cn-advanced-form-dialog__table {
|
|
299
|
+
width: 100%;
|
|
300
|
+
border-collapse: collapse;
|
|
301
|
+
background-color: var(--color-main-background);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.cn-advanced-form-dialog__table th,
|
|
305
|
+
.cn-advanced-form-dialog__table td {
|
|
306
|
+
padding: calc(3 * var(--default-grid-baseline));
|
|
307
|
+
text-align: left;
|
|
308
|
+
border-bottom: 1px solid var(--color-border);
|
|
309
|
+
vertical-align: middle;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.cn-advanced-form-dialog__table th {
|
|
313
|
+
background: var(--color-background-dark);
|
|
314
|
+
font-weight: 500;
|
|
315
|
+
color: var(--color-text-maxcontrast);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
.cn-advanced-form-dialog__table-row {
|
|
319
|
+
cursor: pointer;
|
|
320
|
+
transition: background-color 0.2s ease;
|
|
321
|
+
background-color: var(--color-main-background);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
.cn-advanced-form-dialog__table-row:hover {
|
|
325
|
+
background-color: var(--color-background-hover);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/* Active/selected row: light blue; ensure it wins over validation state classes */
|
|
329
|
+
.cn-advanced-form-dialog__table-row.cn-advanced-form-dialog__table-row--selected,
|
|
330
|
+
.cn-advanced-form-dialog__table-row--selected:hover {
|
|
331
|
+
background-color: var(--color-primary-light);
|
|
332
|
+
box-shadow: inset 3px 0 0 0 var(--color-primary);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.cn-advanced-form-dialog__table-row--edited {
|
|
336
|
+
background-color: var(--color-success-light);
|
|
337
|
+
box-shadow: inset 3px 0 0 0 var(--color-success);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
.cn-advanced-form-dialog__table-row--non-editable {
|
|
341
|
+
background-color: var(--color-background-dark);
|
|
342
|
+
cursor: not-allowed;
|
|
343
|
+
opacity: 0.7;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.cn-advanced-form-dialog__table-row--non-editable * {
|
|
347
|
+
cursor: not-allowed !important;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.cn-advanced-form-dialog__table-row--valid {
|
|
351
|
+
box-shadow: inset 3px 0 0 0 var(--color-success);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
.cn-advanced-form-dialog__table-row--invalid {
|
|
355
|
+
background-color: var(--color-error-light);
|
|
356
|
+
box-shadow: inset 3px 0 0 0 var(--color-error);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
.cn-advanced-form-dialog__table-row--warning {
|
|
360
|
+
background-color: var(--color-warning-light);
|
|
361
|
+
box-shadow: inset 3px 0 0 0 var(--color-warning);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
.cn-advanced-form-dialog__table-row--new {
|
|
365
|
+
box-shadow: inset 3px 0 0 0 var(--color-primary-element);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
.cn-advanced-form-dialog__table-col-constrained {
|
|
369
|
+
width: 150px;
|
|
370
|
+
max-width: 150px;
|
|
371
|
+
overflow: hidden;
|
|
372
|
+
text-overflow: ellipsis;
|
|
373
|
+
white-space: nowrap;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.cn-advanced-form-dialog__table-col-expanded {
|
|
377
|
+
width: auto;
|
|
378
|
+
min-width: 200px;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
.cn-advanced-form-dialog__prop-cell {
|
|
382
|
+
width: 30%;
|
|
383
|
+
font-weight: 600;
|
|
384
|
+
box-shadow: inset 3px 0 0 0 var(--color-primary);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.cn-advanced-form-dialog__value-cell {
|
|
388
|
+
width: 70%;
|
|
389
|
+
word-break: break-word;
|
|
390
|
+
border-radius: 4px;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
.cn-advanced-form-dialog__prop-cell-content {
|
|
394
|
+
display: flex;
|
|
395
|
+
align-items: center;
|
|
396
|
+
gap: 8px;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
.cn-advanced-form-dialog__validation-icon {
|
|
400
|
+
flex-shrink: 0;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.cn-advanced-form-dialog__validation-icon--error {
|
|
404
|
+
color: var(--color-error);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
.cn-advanced-form-dialog__validation-icon--warning {
|
|
408
|
+
color: var(--color-warning);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
.cn-advanced-form-dialog__validation-icon--lock {
|
|
412
|
+
color: var(--color-text-lighter);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
.cn-advanced-form-dialog__validation-icon--new {
|
|
416
|
+
color: var(--color-primary-element);
|
|
417
|
+
}
|
|
418
|
+
</style>
|