output blueprint info
This commit is contained in:
@@ -0,0 +1,325 @@
|
||||
<template>
|
||||
<div class="blueprint" v-if="value && (isParent || isChild)">
|
||||
<div class="blueprint-box">
|
||||
<template v-if="isChild">
|
||||
<div class="blueprint-inner">
|
||||
<ui-icon symbol="fth-cloud" :size="22" />
|
||||
<p v-localize:html="'@blueprint.hint.childText'"></p>
|
||||
</div>
|
||||
<aside>
|
||||
<ui-button class="blueprint-button-settings" type="blank small" icon="fth-settings"
|
||||
:title="{ key: value.blueprint.desync.length > 0 ? '@blueprint.hint.xUnlocked' : '@blueprint.hint.settingsButton', tokens: { count: value.blueprint.desync.length }}"
|
||||
@click="openSettings" />
|
||||
<router-link replace :to="switchLink" class="ui-button type-light type-small" v-localize="'@blueprint.hint.goToBlueprint'"></router-link>
|
||||
</aside>
|
||||
</template>
|
||||
<template v-if="isParent">
|
||||
<div class="blueprint-inner">
|
||||
<ui-icon symbol="fth-cloud" :size="22" />
|
||||
<p v-localize:html="value.id ? '@blueprint.hint.parentText' : '@blueprint.hint.parentCreateText'"></p>
|
||||
</div>
|
||||
<aside v-if="value.id">
|
||||
<router-link replace :to="switchLink" class="ui-button type-light type-small" v-localize="'@blueprint.hint.goToChild'"></router-link>
|
||||
</aside>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import * as overlays from '../../../services/overlay';
|
||||
|
||||
export default {
|
||||
name: 'uiEditorBlueprintProperty',
|
||||
|
||||
props: {
|
||||
value: {
|
||||
type: Object
|
||||
},
|
||||
meta: {
|
||||
type: Object,
|
||||
default: () => { }
|
||||
},
|
||||
config: {
|
||||
type: Object,
|
||||
default: () => { }
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
inject: ['editor'],
|
||||
|
||||
watch: {
|
||||
'$route': function ()
|
||||
{
|
||||
this.bind();
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
isParent()
|
||||
{
|
||||
return this.config.isBlueprintParent(this.$route, this.value);
|
||||
},
|
||||
isChild()
|
||||
{
|
||||
return this.config.isBlueprintChild(this.$route, this.value);
|
||||
},
|
||||
switchLink()
|
||||
{
|
||||
return {
|
||||
name: this.$route.name,
|
||||
params: this.$route.params,
|
||||
query: {
|
||||
...(this.$route.query || {}),
|
||||
'zero.scope': !this.isChild ? undefined : 'system'
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
mounted()
|
||||
{
|
||||
this.bind();
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
async openSettings()
|
||||
{
|
||||
const editor = typeof this.editor === 'string' ? this.zero.getSchema(this.editor) : this.editor;
|
||||
|
||||
const result = await overlays.open({
|
||||
component: () => import('./settings.vue'),
|
||||
display: 'editor',
|
||||
model: {
|
||||
value: this.value,
|
||||
blueprintConfig: this.config
|
||||
}
|
||||
});
|
||||
|
||||
console.info(result);
|
||||
return;
|
||||
this.value.blueprint = res.blueprint;
|
||||
this.$emit('input', res.blueprint);
|
||||
if (typeof res.update === 'function')
|
||||
{
|
||||
res.update(this.value);
|
||||
}
|
||||
//EventHub.$emit('page.update');
|
||||
},
|
||||
|
||||
bind()
|
||||
{
|
||||
const form = this.getForm();
|
||||
const onLoaded = () =>
|
||||
{
|
||||
this.$nextTick(() =>
|
||||
{
|
||||
this.setupSync(form);
|
||||
});
|
||||
};
|
||||
|
||||
if (form.loadingState === 'default')
|
||||
{
|
||||
onLoaded();
|
||||
}
|
||||
else
|
||||
{
|
||||
form.$on('loaded', onLoaded);
|
||||
}
|
||||
},
|
||||
|
||||
setupSync(form)
|
||||
{
|
||||
const meta = form.$parent.meta;
|
||||
|
||||
if (meta)
|
||||
{
|
||||
meta.canDelete = this.isBlueprint;
|
||||
meta.canEdit = this.isBlueprint;
|
||||
}
|
||||
|
||||
if (this.hasBlueprint)
|
||||
{
|
||||
const properties = this.getProperties(form);
|
||||
|
||||
properties.forEach(property =>
|
||||
{
|
||||
if (property.config.path !== 'blueprint')
|
||||
{
|
||||
//property.setBlock(BlueprintBlockComponent);
|
||||
//property.setDisabled(true);
|
||||
}
|
||||
//property.$el.classList.add('is-property-locked');
|
||||
//property.setLocked(true);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
getForm()
|
||||
{
|
||||
let component = this.$parent;
|
||||
|
||||
do
|
||||
{
|
||||
if (component.$options.name === 'uiForm')
|
||||
{
|
||||
return component;
|
||||
}
|
||||
}
|
||||
while (component = component.$parent);
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
|
||||
// find all form properties
|
||||
getProperties(form)
|
||||
{
|
||||
let find = 'uiEditorComponent';
|
||||
let components = [];
|
||||
|
||||
// find components which can output errors
|
||||
let traverseChildren = (parent) =>
|
||||
{
|
||||
parent.$children.forEach(component =>
|
||||
{
|
||||
if (component.$options.name === find)
|
||||
{
|
||||
components.push(component);
|
||||
}
|
||||
else
|
||||
{
|
||||
traverseChildren(component);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
traverseChildren(form);
|
||||
|
||||
return components;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.ui-property.is-property-locked
|
||||
{
|
||||
pointer-events: none;
|
||||
opacity: .8;
|
||||
}
|
||||
|
||||
/*.language .ui-property.has-block:after,
|
||||
.mails .ui-property.has-block:after
|
||||
{
|
||||
position: absolute;
|
||||
left: -13px;
|
||||
top: -7px;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 16px;
|
||||
background: var(--color-box);
|
||||
content: "\e887";
|
||||
font-family: 'Feather';
|
||||
font-size: 15px;
|
||||
font-weight: 400;
|
||||
color: var(--color-text-dim);
|
||||
}*/
|
||||
|
||||
|
||||
.blueprint
|
||||
{
|
||||
position: relative;
|
||||
margin: 0 -32px 0;
|
||||
padding: 0 32px 0;
|
||||
margin-bottom: 30px;
|
||||
//background: var(--color-box-nested);
|
||||
border-top-left-radius: var(--radius);
|
||||
border-top-right-radius: var(--radius);
|
||||
|
||||
aside
|
||||
{
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&.is-shared
|
||||
{
|
||||
//border-bottom: 1px dotted var(--color-accent-error);
|
||||
}
|
||||
}
|
||||
|
||||
.blueprint-box
|
||||
{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: var(--padding-s);
|
||||
padding-left: var(--padding-m);
|
||||
border-radius: var(--radius);
|
||||
border: 1px dashed var(--color-line-dashed);
|
||||
//background: repeating-linear-gradient(-45deg, transparent, transparent 2px, var(--color-bg-shade-2) 2px, var(--color-bg-shade-2) 4px);
|
||||
}
|
||||
|
||||
.blueprint-button-settings
|
||||
{
|
||||
margin-right: -5px;
|
||||
}
|
||||
|
||||
.blueprint-inner
|
||||
{
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(0, 1fr);
|
||||
grid-gap: var(--padding-m);
|
||||
align-items: center;
|
||||
font-size: var(--font-size);
|
||||
line-height: 1.4;
|
||||
position: relative;
|
||||
padding-right: var(--padding-s);
|
||||
|
||||
p
|
||||
{
|
||||
margin: 0;
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
.ui-icon
|
||||
{
|
||||
color: var(--color-text);
|
||||
margin-top: -2px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
<!--<button type="button" class="ui-property-lock" v-if="locked" > <i class="fth-lock" > </i > </button >
|
||||
/*.ui-property.is-locked
|
||||
{
|
||||
|
||||
}*/
|
||||
.ui-property-lock
|
||||
{
|
||||
display: inline-flex;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 10px;
|
||||
background: var(--color-button-light);
|
||||
color: var(--color-text);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 10px;
|
||||
position: relative;
|
||||
top: -1px;
|
||||
margin-right: 8px;
|
||||
}-->
|
||||
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
<template>
|
||||
<ui-trinity class="blueprint-settings">
|
||||
<template v-slot:header>
|
||||
<ui-header-bar title="Synchronisation" :back-button="false" :close-button="true" />
|
||||
</template>
|
||||
<template v-slot:footer>
|
||||
<ui-button type="light onbg" label="@ui.close" @click="config.close" />
|
||||
<ui-button type="primary" label="@ui.confirm" @click="onSave" :state="state" />
|
||||
</template>
|
||||
|
||||
<p class="blueprint-settings-text">By default all properties of your entity are synced with its blueprint.<br />You can disable synchronisation per property so it won't be overridden on changes.</p>
|
||||
|
||||
<div class="ui-box" v-if="loaded">
|
||||
<ui-property class="blueprint-settings-tableheader" :key="-1" label="Property" :vertical="false">
|
||||
<b>Synchronized</b>
|
||||
</ui-property>
|
||||
<template v-for="(field, index) in items">
|
||||
<ui-property v-if="!field.disabled" :key="index" :label="field.label" :description="field.description" :vertical="false" :class="{'not-synced': !field.synced}">
|
||||
<ui-toggle v-model:on="field.synced" />
|
||||
</ui-property>
|
||||
</template>
|
||||
</div>
|
||||
</ui-trinity>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import { arrayRemove } from '../../../utils/arrays';
|
||||
//import Localization from 'zero/helpers/localization.js';
|
||||
//import BlueprintApi from 'zero/api/blueprint.js';
|
||||
|
||||
export default {
|
||||
name: 'uiEditorBlueprintSettings',
|
||||
|
||||
props: {
|
||||
model: Object,
|
||||
config: Object
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
state: 'default',
|
||||
loaded: false,
|
||||
editor: null,
|
||||
items: []
|
||||
}),
|
||||
|
||||
|
||||
mounted()
|
||||
{
|
||||
this.model.blueprintConfig.fields.forEach(field =>
|
||||
{
|
||||
let item = JSON.parse(JSON.stringify(field));
|
||||
item.synced = field.synced(this.model.value);
|
||||
this.items.push(item);
|
||||
});
|
||||
this.loaded = true;
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
|
||||
onSave()
|
||||
{
|
||||
this.state = 'loading';
|
||||
|
||||
let desync = JSON.parse(JSON.stringify(this.model.value.blueprint.desync));
|
||||
let resync = [];
|
||||
|
||||
this.items.forEach(field =>
|
||||
{
|
||||
let desynced = this.model.value.blueprint.desync.indexOf(field.path) > -1;
|
||||
|
||||
if (field.synced && desynced)
|
||||
{
|
||||
arrayRemove(desync, field.path);
|
||||
resync.push(field.path);
|
||||
}
|
||||
else if (!field.synced && !desynced)
|
||||
{
|
||||
desync.push(field.path);
|
||||
}
|
||||
});
|
||||
|
||||
this.model.value.blueprint.desync = desync;
|
||||
|
||||
// we need to revert changed values which were switch backed to synchronised state
|
||||
// to do this we load the blueprint entity and its copy properties
|
||||
|
||||
if (resync.length > 0)
|
||||
{
|
||||
BlueprintApi.getById(this.model.value.blueprint.id).then(blueprint =>
|
||||
{
|
||||
this.config.confirm({
|
||||
blueprint: this.model.value.blueprint,
|
||||
update: entity =>
|
||||
{
|
||||
resync.forEach(path =>
|
||||
{
|
||||
entity[path] = blueprint[path]; // TODO does not work for nested paths
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
//this.state = 'success';
|
||||
this.config.confirm({
|
||||
blueprint: this.model.value.blueprint
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
|
||||
//rebuildModel()
|
||||
//{
|
||||
// this.selector = Strings.selectorToArray(this.config.path);
|
||||
// let currentValue = this.value;
|
||||
// let found = false;
|
||||
|
||||
// if (!this.selector || !this.selector.length || !currentValue)
|
||||
// {
|
||||
// found = true;
|
||||
// this.model = null;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// for (var key of this.selector)
|
||||
// {
|
||||
// if (key in currentValue)
|
||||
// {
|
||||
// found = true;
|
||||
// currentValue = currentValue[key];
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// this.model = found ? currentValue : null;
|
||||
// }
|
||||
//},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.blueprint-settings-text
|
||||
{
|
||||
margin: 0 0 var(--padding);
|
||||
line-height: 1.5;
|
||||
}
|
||||
.blueprint-settings-headline
|
||||
{
|
||||
margin: 0 0 var(--padding) !important;
|
||||
}
|
||||
|
||||
.blueprint-settings .ui-property
|
||||
{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.blueprint-settings .blueprint-settings-tableheader
|
||||
{
|
||||
border-bottom: 1px dashed var(--color-line-dashed);
|
||||
padding-bottom: 20px;
|
||||
margin-bottom: 26px;
|
||||
|
||||
b
|
||||
{
|
||||
display: inline-block;
|
||||
margin-top: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.blueprint-settings .ui-property + .ui-property
|
||||
{
|
||||
margin-top: var(--padding-s);
|
||||
padding-top: 0;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.blueprint-settings .ui-property-content
|
||||
{
|
||||
display: inline;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.blueprint-settings .ui-property-label
|
||||
{
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
.blueprint-settings .ui-property.not-synced .ui-property-label
|
||||
{
|
||||
font-weight: 400;
|
||||
color: var(--color-text-dim);
|
||||
}
|
||||
|
||||
.blueprint-settings-lock
|
||||
{
|
||||
color: var(--color-text-dim);
|
||||
}
|
||||
|
||||
/*.blueprint-settings .ui-property.not-synced .ui-property-label:before
|
||||
{
|
||||
content: "\e929";
|
||||
font-family: 'Feather';
|
||||
margin-right: 0.8em;
|
||||
color: var(--color-text-dim);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.blueprint-settings .ui-property:not(.not-synced) .ui-property-label:before
|
||||
{
|
||||
content: "\e8f8";
|
||||
font-family: 'Feather';
|
||||
margin-right: 0.8em;
|
||||
color: var(--color-primary);
|
||||
font-weight: 400;
|
||||
}*/
|
||||
</style>
|
||||
@@ -1,189 +0,0 @@
|
||||
-<template>
|
||||
<ui-property v-if="loaded && !isHidden"
|
||||
:field="config.path"
|
||||
:label="label"
|
||||
:hide-label="config.options.hideLabel"
|
||||
:description="description"
|
||||
:required="isRequired"
|
||||
:disabled="isDisabled"
|
||||
:vertical="config.options.vertical"
|
||||
:class="{'is-disabled': isDisabled }"
|
||||
:locked="isLocked"
|
||||
:can-unlock="canUnlock || false"
|
||||
@unlock="unlock"
|
||||
@lock="lock">
|
||||
<component :is="config.component" v-bind="config.componentOptions" :value="model" :entity="value" :meta="meta" @input="onChange" :disabled="isDisabled" />
|
||||
<p v-if="config.options.helpText" class="ui-property-help" v-localize="config.options.helpText"></p>
|
||||
</ui-property>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import { selectorToArray } from '../../utils/arrays';
|
||||
import { setObjectValue } from '../../utils/objects';
|
||||
import { localize } from '../../services/localization';
|
||||
//import Overlay from 'zero/helpers/overlay.js';
|
||||
|
||||
export default {
|
||||
name: 'uiEditorComponent',
|
||||
|
||||
inject: [ 'meta' ],
|
||||
|
||||
props: {
|
||||
config: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
editor: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
value: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
value: {
|
||||
deep: true,
|
||||
handler: function ()
|
||||
{
|
||||
this.rebuildModel();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
model: null,
|
||||
loaded: false,
|
||||
manualDisabled: false,
|
||||
selector: null
|
||||
}),
|
||||
|
||||
mounted()
|
||||
{
|
||||
this.rebuildModel();
|
||||
this.loaded = true;
|
||||
},
|
||||
|
||||
computed: {
|
||||
isHidden()
|
||||
{
|
||||
return this.loaded && typeof this.config.options.condition === 'function' && !this.config.options.condition(this.value, this);
|
||||
},
|
||||
isRequired()
|
||||
{
|
||||
return typeof this.config.isRequired === 'function' ? this.config.isRequired(this.value) : this.config.isRequired;
|
||||
},
|
||||
isDisabled()
|
||||
{
|
||||
return this.manualDisabled || this.disabled || (typeof this.config.options.disabled === 'boolean' && this.config.options.disabled) || (typeof this.config.options.disabled === 'function' && this.config.options.disabled(this.value, this.model));
|
||||
},
|
||||
label()
|
||||
{
|
||||
return this.config.options.label || this.editor.templateLabel(this.config.path);
|
||||
},
|
||||
description()
|
||||
{
|
||||
return localize(this.config.options.description || this.editor.templateDescription(this.config.path), { hideEmpty: true });
|
||||
},
|
||||
isLocked()
|
||||
{
|
||||
return this.editor.blueprint && !this.editor.blueprint.unlocked(this.value, this.config);
|
||||
},
|
||||
canUnlock()
|
||||
{
|
||||
return this.editor.blueprint && this.editor.blueprint.canUnlock(this.value, this.config);
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
rebuildModel()
|
||||
{
|
||||
this.selector = selectorToArray(this.config.path);
|
||||
let currentValue = this.value;
|
||||
let found = false;
|
||||
|
||||
if (!this.selector || !this.selector.length || !currentValue)
|
||||
{
|
||||
found = true;
|
||||
this.model = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var key of this.selector)
|
||||
{
|
||||
if (currentValue && key in currentValue)
|
||||
{
|
||||
found = true;
|
||||
currentValue = currentValue[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.model = found ? currentValue : null;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
onChange(value)
|
||||
{
|
||||
let oldValue = JSON.parse(JSON.stringify(this.model));
|
||||
|
||||
if (typeof value === 'function')
|
||||
{
|
||||
value(this.value);
|
||||
}
|
||||
else
|
||||
{
|
||||
setObjectValue(this.value, this.selector, value);
|
||||
}
|
||||
this.$emit('input', this.value);
|
||||
|
||||
if (typeof this.config.options.onChange === 'function')
|
||||
{
|
||||
this.config.options.onChange(value, {
|
||||
oldValue,
|
||||
model: this.value,
|
||||
component: this
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
setDisabled(disabled)
|
||||
{
|
||||
this.manualDisabled = disabled;
|
||||
},
|
||||
|
||||
|
||||
async unlock()
|
||||
{
|
||||
//Overlay.confirm({
|
||||
// title: 'Unlock property',
|
||||
// text: 'Unlock this property to override the value passed by the blueprint',
|
||||
// confirmLabel: 'Confirm',
|
||||
// closeLabel: 'Cancel'
|
||||
//}).then(
|
||||
// async () => await this.editor.blueprint.unlock(this.value, this.config),
|
||||
// () => {}
|
||||
//);
|
||||
},
|
||||
|
||||
async lock()
|
||||
{
|
||||
let originalValue = await this.editor.blueprint.lock(this.value, this.config);
|
||||
this.onChange(originalValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -7,6 +7,11 @@
|
||||
:required="!field.optional(value)"
|
||||
:disabled="isDisabled"
|
||||
:vertical="!field.horizontal"
|
||||
:class="{'is-disabled': isDisabled }"
|
||||
:locked="isLocked"
|
||||
:can-unlock="canUnlock || false"
|
||||
@unlock="unlock"
|
||||
@lock="lock"
|
||||
>
|
||||
<component :is="field.component" v-bind="field.options"
|
||||
:value="model"
|
||||
@@ -14,17 +19,6 @@
|
||||
@input="onChange" />
|
||||
<p v-if="field.helpText" class="ui-property-help" v-localize="field.helpText"></p>
|
||||
</ui-property>
|
||||
|
||||
<!--<ui-property v-if="loaded && !isHidden"
|
||||
:vertical="field.configuration.vertical"
|
||||
:class="{'is-disabled': isDisabled }"
|
||||
:locked="isLocked"
|
||||
:can-unlock="canUnlock || false"
|
||||
@unlock="unlock"
|
||||
@lock="lock">
|
||||
<component :is="config.component" v-bind="config.componentOptions" :value="model" :entity="value" :meta="meta" @input="onChange" :disabled="isDisabled" />
|
||||
<p v-if="field.configuration.helpText" class="ui-property-help" v-localize="field.configuration.helpText"></p>
|
||||
</ui-property>-->
|
||||
</template>
|
||||
|
||||
|
||||
@@ -90,15 +84,15 @@
|
||||
isDisabled()
|
||||
{
|
||||
return this.manualDisabled || this.disabled || this.field.readonly(this.model);
|
||||
},
|
||||
isLocked()
|
||||
{
|
||||
return false; //this.editor.blueprint && !this.editor.blueprint.unlocked(this.value, this.field);
|
||||
},
|
||||
canUnlock()
|
||||
{
|
||||
return false; // this.editor.blueprint && this.editor.blueprint.canUnlock(this.value, this.field);
|
||||
}
|
||||
//isLocked()
|
||||
//{
|
||||
// return this.editor.blueprint && !this.editor.blueprint.unlocked(this.value, this.field);
|
||||
//},
|
||||
//canUnlock()
|
||||
//{
|
||||
// return this.editor.blueprint && this.editor.blueprint.canUnlock(this.value, this.field);
|
||||
//}
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
:disabled="tab.disabled(value)">
|
||||
<h3 v-if="display == 'boxes' && tab.name" class="ui-headline editor-tab-headline" v-localize="tab.name"></h3>
|
||||
<slot name="blueprint">
|
||||
<!--<blueprint-property v-if="value && editorConfig.blueprint" :value="value" :meta="meta" :config="editorConfig.blueprint" />-->
|
||||
<blueprint-property v-if="value && editorConfig.blueprint.isEnabled" :value="value" :meta="meta" :config="editorConfig.blueprint" />
|
||||
</slot>
|
||||
<div v-if="!tab.component" class="ui-property ui-property-parent" v-for="(fieldset, fieldsetIndex) in tab.fieldsets" :key="fieldsetIndex">
|
||||
|
||||
@@ -47,13 +47,10 @@
|
||||
|
||||
import './ui-editor.scss';
|
||||
import EditorComponent from './ui-editor-component.vue';
|
||||
//import { createBlueprintConfig } from './editor-blueprint';
|
||||
//import BlueprintProperty from './blueprint/property.vue';
|
||||
import BlueprintProperty from './blueprint/property.vue';
|
||||
import { defineComponent } from 'vue';
|
||||
import { compileEditor } from '../../editor/compile';
|
||||
|
||||
let createBlueprintConfig = () => null;
|
||||
|
||||
export default defineComponent({
|
||||
name: 'uiEditor',
|
||||
|
||||
@@ -91,7 +88,7 @@
|
||||
},
|
||||
},
|
||||
|
||||
components: { EditorComponent },
|
||||
components: { EditorComponent, BlueprintProperty },
|
||||
|
||||
data: () => ({
|
||||
display: 'tabs',
|
||||
@@ -122,9 +119,7 @@
|
||||
this.system = this.$route.query['zero.scope'] == 'system';
|
||||
const schema = typeof this.config === 'string' ? await this.zero.getSchema(this.config) : this.config;
|
||||
const editor = compileEditor(this.zero, schema);
|
||||
|
||||
this.editorConfig = editor;
|
||||
//this.editorConfig.blueprint = createBlueprintConfig(this.zero, this.editorConfig, this.value);
|
||||
|
||||
this.onConfigure(this);
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
}
|
||||
if (shared)
|
||||
{
|
||||
routeObj.query['zero.scope'] = 'shared';
|
||||
routeObj.query['zero.scope'] = 'system';
|
||||
}
|
||||
this.$router.push(routeObj);
|
||||
}
|
||||
|
||||
@@ -2,12 +2,16 @@ import { Component } from "vue";
|
||||
import { ZeroEditorField } from "zero/schemas";
|
||||
import { Zero } from "../core";
|
||||
import { ZeroEditor } from "./editor";
|
||||
import { createBlueprintConfig } from "./editor-blueprint";
|
||||
import { ZeroEditorCanvasBase, ZeroEditorTab } from "./editor-canvas";
|
||||
import { ZeroEditorFieldConfiguration } from "./editor-field";
|
||||
import { localize } from '../services/localization';
|
||||
|
||||
|
||||
export interface ZeroCompiledEditor
|
||||
{
|
||||
alias: string;
|
||||
blueprint: any;
|
||||
tabs: ZeroCompiledEditorTab[];
|
||||
}
|
||||
|
||||
@@ -108,8 +112,8 @@ export function compileField(zero: Zero, editor: ZeroEditor, field: ZeroEditorFi
|
||||
return false;
|
||||
},
|
||||
|
||||
label: editor.onLabelCreate(field),
|
||||
description: editor.onDescriptionCreate(field),
|
||||
label: editor.onLabelCreate(field),
|
||||
description: localize(editor.onDescriptionCreate(field), { hideEmpty: true }),
|
||||
hideLabel: field.configuration.hideLabel,
|
||||
helpText: field.configuration.helpText,
|
||||
classes: field.configuration.classes,
|
||||
@@ -125,6 +129,8 @@ export function compileField(zero: Zero, editor: ZeroEditor, field: ZeroEditorFi
|
||||
export function compileEditor(zero: Zero, editor: ZeroEditor): ZeroCompiledEditor
|
||||
{
|
||||
let model = {
|
||||
alias: editor.alias,
|
||||
blueprint: null,
|
||||
tabs: []
|
||||
} as ZeroCompiledEditor;
|
||||
|
||||
@@ -220,5 +226,7 @@ export function compileEditor(zero: Zero, editor: ZeroEditor): ZeroCompiledEdito
|
||||
}
|
||||
});
|
||||
|
||||
model.blueprint = createBlueprintConfig(model.alias, model);
|
||||
|
||||
return model;
|
||||
}
|
||||
+26
-17
@@ -2,6 +2,7 @@
|
||||
import { localize } from '../services/localization';
|
||||
import { arrayRemove } from '../utils/arrays';
|
||||
import { useUiStore } from '../ui/store';
|
||||
import { ZeroCompiledEditor } from './compile';
|
||||
|
||||
function unlocked(config, model, field)
|
||||
{
|
||||
@@ -77,16 +78,17 @@ function unlock(config, model, field)
|
||||
* @param {string} alias - Alias for the tab
|
||||
* @returns {EditorBlueprint}
|
||||
*/
|
||||
export function createBlueprintConfig(zero, editor, model)
|
||||
export function createBlueprintConfig(alias: string, editor: ZeroCompiledEditor)
|
||||
{
|
||||
const store = useUiStore();
|
||||
let blueprintAlias = editor.blueprintAlias;
|
||||
let blueprintAlias = editor.alias;
|
||||
let canBeBlueprinted = store.blueprints.indexOf(blueprintAlias) > -1;
|
||||
|
||||
if (!blueprintAlias || !canBeBlueprinted)
|
||||
{
|
||||
return {
|
||||
alias: blueprintAlias,
|
||||
isEnabled: false,
|
||||
unlocked: () => true,
|
||||
canUnlock: () => false,
|
||||
isBlueprintParent: () => false,
|
||||
@@ -128,28 +130,35 @@ export function createBlueprintConfig(zero, editor, model)
|
||||
});
|
||||
|
||||
// add blueprint setting for custom fields
|
||||
editor.fields.forEach(field =>
|
||||
editor.tabs.forEach(tab =>
|
||||
{
|
||||
let alias = field.path;
|
||||
|
||||
if (processed.indexOf(alias) < 0)
|
||||
tab.fieldsets.forEach(set =>
|
||||
{
|
||||
processed.push(alias);
|
||||
|
||||
if (config.unlocked.indexOf(alias) > -1 || config.unlocked.find(x => alias.indexOf(x + '.') === 0))
|
||||
set.fields.forEach(field =>
|
||||
{
|
||||
fields.push({
|
||||
path: alias,
|
||||
label: field.options.label || editor.templateLabel(alias),
|
||||
description: localize(field.options.description || editor.templateDescription(alias), { hideEmpty: true }),
|
||||
synced: model => !model.blueprint || model.blueprint.desync.indexOf(alias) < 0
|
||||
});
|
||||
}
|
||||
}
|
||||
let alias = field.path;
|
||||
|
||||
if (processed.indexOf(alias) < 0)
|
||||
{
|
||||
processed.push(alias);
|
||||
|
||||
if (config.unlocked.indexOf(alias) > -1 || config.unlocked.find(x => alias.indexOf(x + '.') === 0))
|
||||
{
|
||||
fields.push({
|
||||
path: alias,
|
||||
label: field.label,
|
||||
description: field.description,
|
||||
synced: model => !model.blueprint || model.blueprint.desync.indexOf(alias) < 0
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
alias: blueprintAlias,
|
||||
isEnabled: true,
|
||||
unlocked: (model, field) => unlocked(config, model, field),
|
||||
canUnlock: (model, field) => canUnlock(config, model, field),
|
||||
unlock: async (model, field) => await unlock(config, model, field),
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Component, ComponentPropsOptions } from "vue";
|
||||
import { EditorSchema, ZeroEditorField } from "zero/schemas";
|
||||
import { ZeroEditorField } from "zero/schemas";
|
||||
import { ZeroEditorCanvas } from "./editor-canvas";
|
||||
|
||||
export class ZeroEditor extends ZeroEditorCanvas
|
||||
{
|
||||
alias: string;
|
||||
|
||||
resourcePrefix?: string;
|
||||
|
||||
system: boolean = false;
|
||||
@@ -19,8 +20,9 @@ export class ZeroEditor extends ZeroEditorCanvas
|
||||
};
|
||||
|
||||
|
||||
constructor()
|
||||
constructor(alias: string)
|
||||
{
|
||||
super();
|
||||
this.alias = alias;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
import { ZeroEditor } from "../../../editor/editor";
|
||||
import { formatDate } from '../../../utils/dates';
|
||||
|
||||
const editor = new ZeroEditor();
|
||||
const editor = new ZeroEditor('countries');
|
||||
|
||||
editor.resourcePrefix = '@country.fields.';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
import { ZeroEditor } from '../../../editor/editor';
|
||||
|
||||
const editor = new ZeroEditor();
|
||||
const editor = new ZeroEditor('integrations');
|
||||
|
||||
editor.resourcePrefix = '@translation.fields.';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
import { ZeroEditor } from '../../../editor/editor';
|
||||
|
||||
const editor = new ZeroEditor();
|
||||
const editor = new ZeroEditor('languages');
|
||||
|
||||
editor.resourcePrefix = '@language.fields.';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
import { ZeroEditor } from "../../../editor/editor";
|
||||
|
||||
const editor = new ZeroEditor();
|
||||
const editor = new ZeroEditor('mailtemplates');
|
||||
|
||||
editor.resourcePrefix = '@mailTemplate.fields.';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
import { ZeroEditor } from '../../../editor/editor';
|
||||
|
||||
const editor = new ZeroEditor();
|
||||
const editor = new ZeroEditor('translations');
|
||||
|
||||
editor.resourcePrefix = '@translation.fields.';
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ export interface LocalizeOptions
|
||||
}
|
||||
|
||||
|
||||
export const localize = (key: string, options?: LocalizeOptions): string =>
|
||||
export const localize = (key: string | null, options?: LocalizeOptions): string =>
|
||||
{
|
||||
let params = extendObject({
|
||||
force: false,
|
||||
|
||||
Reference in New Issue
Block a user