page picker
This commit is contained in:
@@ -82,6 +82,15 @@ public class PagesController : ZeroApiTreeEntityStoreController<Page, IPagesStor
|
||||
return result;
|
||||
}
|
||||
|
||||
[HttpGet("")]
|
||||
[ZeroAuthorize(PagePermissions.Read)]
|
||||
public virtual Task<ActionResult<Paged>> Get([FromQuery] ListQuery<Page> query)
|
||||
{
|
||||
query.SearchFor(x => x.Name);
|
||||
query.OrderQuery = q => q.OrderByDescending(x => x.Sort).ThenByDescending(x => x.CreatedDate);
|
||||
return GetModelsByIndex<zero_Api_Pages_Listing>(query);
|
||||
}
|
||||
|
||||
[HttpPost("")]
|
||||
[ZeroAuthorize(PagePermissions.Create)]
|
||||
public virtual Task<ActionResult<Result>> Create(Page saveModel) => CreateModel(saveModel);
|
||||
|
||||
@@ -131,7 +131,7 @@
|
||||
const schema = typeof this.config === 'string' ? await this.zero.getSchema(this.config) : this.config;
|
||||
this.editorConfig = compileEditor(this.zero, schema);
|
||||
|
||||
this.onConfigure(this);
|
||||
this.onConfigure(this.editorConfig, this);
|
||||
|
||||
this.loaded = true;
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="ui-module-item" v-if="!loading" :data-module="alias" :class="{'can-edit': canEdit, 'no-preview': !preview }">
|
||||
<div class="ui-module-item-content" v-if="module" @click="emit('edit')">
|
||||
<span v-if="!preview || !preview.hideLabel" class="ui-module-item-header" v-localize="module.name"><ui-icon :symbol="module.icon" /> <span v-localize="module.name"></span></span>
|
||||
<span v-if="!preview || !preview.hideLabel" class="ui-module-item-header"><ui-icon :symbol="module.icon" /> <span v-localize="module.name"></span></span>
|
||||
<module-preview-inner v-if="tryRender && typeof preview.template === 'string'" :template="preview.template" :value="value" :options="preview" />
|
||||
<div v-if="tryRender && typeof preview.template !== 'string'" class="ui-module-preview-inner">
|
||||
<component :is="preview.template" :model="value" :options="preview" />
|
||||
|
||||
@@ -10,12 +10,16 @@ export default {
|
||||
|
||||
getById: (id: string, changeVector?: string, config?: ApiRequestConfig) => get('pages/' + id, { ...config, params: { changeVector } }),
|
||||
|
||||
getByQuery: (query: ApiRequestQuery, config?: ApiRequestConfig) => get('pages', { ...config, params: { ...query } }),
|
||||
|
||||
getChildren: (id: string, query: ApiRequestQuery, config?: ApiRequestConfig) => get(`pages/${id}/children`, { ...config, params: { ...query } }),
|
||||
|
||||
getAllowedFlavors: (id: string, config?: ApiRequestConfig) => get(`pages/${id}/flavors`, { ...config }),
|
||||
|
||||
getDependencies: (id: string, config?: ApiRequestConfig) => get(`backoffice/pages/${id}/dependencies`, { ...config }),
|
||||
|
||||
getPreviews: (ids: string[], config?: ApiRequestConfig) => get(`backoffice/pages/previews`, { ...config, params: { ids } }),
|
||||
|
||||
|
||||
create: (model: any, config?: ApiRequestConfig) => post('pages', model, config),
|
||||
|
||||
|
||||
@@ -26,12 +26,8 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import api from './api';
|
||||
|
||||
//import PageInfoTab from './page-info.vue';
|
||||
//import Overlay from 'zero/helpers/overlay.js'
|
||||
//import MoveOverlay from './overlays/move.vue'
|
||||
//import CopyOverlay from './overlays/copy.vue'
|
||||
//import Strings from 'zero/helpers/strings.js';
|
||||
import actions from './actions';
|
||||
import PageInfoTab from './partials/page-info.vue';
|
||||
|
||||
export default defineComponent({
|
||||
|
||||
@@ -144,22 +140,42 @@
|
||||
},
|
||||
|
||||
|
||||
async move(item)
|
||||
{
|
||||
await actions.move(item);
|
||||
},
|
||||
|
||||
|
||||
async copy(item)
|
||||
{
|
||||
await actions.copy(item);
|
||||
},
|
||||
|
||||
|
||||
async remove(item)
|
||||
{
|
||||
await actions.remove(item);
|
||||
},
|
||||
|
||||
|
||||
onEditorConfigure(editor)
|
||||
{
|
||||
//if (this.isFolder)
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
if (this.isFolder)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//editor.tabs.push({
|
||||
// alias: 'zero.info',
|
||||
// name: '@page.info_tab',
|
||||
// class: 'is-info is-blank',
|
||||
// count: value => null,
|
||||
// disabled: value => false,
|
||||
// component: PageInfoTab,
|
||||
// fields: []
|
||||
//});
|
||||
editor.tabs.push({
|
||||
alias: 'zero.info',
|
||||
name: '@page.info_tab',
|
||||
class: 'is-info is-blank',
|
||||
sort: 99999,
|
||||
fieldsets: [],
|
||||
hidden: _ => false,
|
||||
count: _ => null,
|
||||
disabled: _ => false,
|
||||
component: PageInfoTab
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
<template>
|
||||
<div class="page-editor-info">
|
||||
<div class="ui-box" v-if="!isCreate && urls.length">
|
||||
<ui-property label="@page.infotab.links" :is-text="true" :vertical="false">
|
||||
<a v-for="url in urls" class="ui-link" :href="url" target="_blank"><ui-icon symbol="fth-external-link"></ui-icon> {{url}}</a>
|
||||
</ui-property>
|
||||
<!--<ui-property label="@page.infotab.revisions" :is-text="true" :vertical="false">-->
|
||||
<!--<ui-revisions :get="getRevisions" />-->
|
||||
<!--</ui-property>-->
|
||||
</div>
|
||||
<div class="ui-box">
|
||||
<!--<ui-property label="@page.schedule.label" :is-text="true" :vertical="false">
|
||||
<ui-daterangepicker :value="{ from: value.publishDate, to: value.unpublishDate }" @input="onRangeChange" :class="{ 'is-primary': value.publishDate || value.unpublishDate }" :disabled="disabled" />
|
||||
</ui-property>-->
|
||||
<ui-property label="@page.type" :is-text="true" v-if="pageType" :vertical="false">
|
||||
<ui-icon :symbol="pageType.icon" style="margin-right:6px;"></ui-icon>{{pageType.name}}
|
||||
</ui-property>
|
||||
<ui-property v-if="!isCreate" label="@ui.id" :is-text="true" :vertical="false">
|
||||
{{value.id}}
|
||||
</ui-property>
|
||||
<ui-property v-if="!isCreate" label="@ui.createdDate" :is-text="true" :vertical="false">
|
||||
<ui-date v-model="value.createdDate" />
|
||||
</ui-property>
|
||||
<ui-property v-if="!isCreate" label="@ui.modifiedDate" :is-text="true" :vertical="false">
|
||||
<ui-date v-model="value.lastModifiedDate" />
|
||||
</ui-property>
|
||||
<ui-property v-if="!isCreate" label="@ui.entityfields.alias" :is-text="true" :vertical="false">
|
||||
{{value.alias}}
|
||||
</ui-property>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import api from '../api';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: [ Object, Array ]
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
pageType: null,
|
||||
urls: []
|
||||
}),
|
||||
|
||||
computed: {
|
||||
isCreate()
|
||||
{
|
||||
return !this.value.id;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
mounted()
|
||||
{
|
||||
//api.getPageType(this.value.pageTypeAlias).then(pageType =>
|
||||
//{
|
||||
// this.pageType = pageType;
|
||||
//});
|
||||
//if (this.value.id)
|
||||
//{
|
||||
// api.getUrls(this.value.id).then(urls =>
|
||||
// {
|
||||
// this.urls = urls;
|
||||
// });
|
||||
//}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
|
||||
getRevisions(page)
|
||||
{
|
||||
//return api.getRevisions(this.value.id, page);
|
||||
},
|
||||
|
||||
onRangeChange(value)
|
||||
{
|
||||
this.value.publishDate = value.from;
|
||||
this.value.unpublishDate = value.to;
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.page-editor-info
|
||||
{
|
||||
padding: 0 !important;
|
||||
}
|
||||
.page-editor-info .ui-view-box-aside
|
||||
{
|
||||
padding: 0;
|
||||
}
|
||||
.page-editor-info .ui-box
|
||||
{
|
||||
margin: 0;
|
||||
}
|
||||
.page-editor-info .ui-box + .ui-box
|
||||
{
|
||||
margin-top: var(--padding-s);
|
||||
}
|
||||
.page-editor-info .ui-property + .ui-property
|
||||
{
|
||||
/*border-top: none;
|
||||
margin-top: 0;
|
||||
padding-top: var(--padding-s);*/
|
||||
}
|
||||
.page-editor-info .ui-box:last-child
|
||||
{
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -91,6 +91,7 @@
|
||||
if (item.id === 'recyclebin')
|
||||
{
|
||||
item.hasActions = false;
|
||||
item.disabled = true;
|
||||
//item.url = {
|
||||
// name: 'recyclebin'
|
||||
//};
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<ui-pagepicker :value="value" @input="$emit('input', $event)" :model="config.model" :limit="limit" :disabled="config.disabled" :root-id="rootId" :disabled-ids="disabledIds" />
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
value: [String, Array],
|
||||
config: Object,
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
rootId: [String, Function],
|
||||
disabledIds: {
|
||||
type: [Array, Function],
|
||||
default: []
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,132 @@
|
||||
<template>
|
||||
<ui-trinity class="ui-pagepicker-overlay">
|
||||
<template v-slot:header>
|
||||
<ui-header-bar :title="config.title" :back-button="false" :close-button="true" />
|
||||
</template>
|
||||
<template v-slot:footer>
|
||||
<ui-button type="light onbg" :label="config.closeLabel" :parent="config.rootId" @click="config.close"></ui-button>
|
||||
</template>
|
||||
|
||||
<div v-if="opened" class="ui-box ui-pagepicker-overlay-items">
|
||||
<ui-tree ref="tree" :get="getItems" :parent="config.rootId" @select="onSelect" />
|
||||
</div>
|
||||
</ui-trinity>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import api from '../api';
|
||||
|
||||
export default {
|
||||
|
||||
props: {
|
||||
model: String,
|
||||
config: Object
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
opened: false
|
||||
}),
|
||||
|
||||
computed: {
|
||||
disabledIds()
|
||||
{
|
||||
return this.config.disabledIds || [];
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
mounted()
|
||||
{
|
||||
setTimeout(() => this.opened = true, 300);
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
|
||||
onSelect(item)
|
||||
{
|
||||
this.config.confirm(item);
|
||||
},
|
||||
|
||||
// get tree items
|
||||
async getItems(parent)
|
||||
{
|
||||
const result = await api.tree.getChildren((parent || 'root'), this.model);
|
||||
|
||||
result.data.forEach(item =>
|
||||
{
|
||||
if (item.id === this.model)
|
||||
{
|
||||
item.isSelected = true;
|
||||
}
|
||||
if (this.disabledIds.indexOf(item.id) > -1 && item.id !== this.model)
|
||||
{
|
||||
item.disabled = true;
|
||||
}
|
||||
if (item.id === 'recyclebin')
|
||||
{
|
||||
item.disabled = true;
|
||||
}
|
||||
item.hasActions = false;
|
||||
});
|
||||
|
||||
if (!parent)
|
||||
{
|
||||
result.data.splice(0, 0, {
|
||||
id: null,
|
||||
parentId: null,
|
||||
image: null,
|
||||
name: '@page.root',
|
||||
children: 0,
|
||||
root: true,
|
||||
sort: 0,
|
||||
icon: 'fth-arrow-down-circle',
|
||||
root: true
|
||||
});
|
||||
}
|
||||
|
||||
return result.data;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.ui-pagepicker-overlay content
|
||||
{
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.ui-box.ui-pagepicker-overlay-items
|
||||
{
|
||||
margin: 0;
|
||||
padding: 20px 0;
|
||||
|
||||
.ui-tree-item.is-selected, .ui-tree-item:hover:not(.is-disabled)
|
||||
{
|
||||
background: var(--color-bg-xxlight);
|
||||
}
|
||||
|
||||
& +.ui-box
|
||||
{
|
||||
margin-top: var(--padding);
|
||||
}
|
||||
|
||||
.ui-tree-item.is-selected
|
||||
{
|
||||
&:after
|
||||
{
|
||||
font-family: "Feather";
|
||||
content: "\e83e";
|
||||
font-size: 16px;
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.ui-tree-item-text
|
||||
{
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,212 @@
|
||||
<template>
|
||||
<div class="ui-pagepicker" :class="{'is-disabled': disabled }">
|
||||
<input ref="input" type="hidden" :value="value" />
|
||||
<div class="ui-pagepicker-previews" v-if="previews.length > 0">
|
||||
<div v-for="preview in previews" class="ui-pagepicker-preview">
|
||||
<ui-select-button :icon="preview.icon" :label="preview.name" :description="preview.text" :disabled="disabled" @click="pick(preview.id)" :tokens="{ id: preview.id }" />
|
||||
<ui-icon-button v-if="!disabled" @click="remove(preview.id)" icon="fth-x" title="@ui.close" />
|
||||
</div>
|
||||
</div>
|
||||
<ui-select-button v-if="canAdd" icon="fth-plus" :label="limit > 1 ? '@ui.add' : '@ui.select'" @click="pick()" :disabled="disabled" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script lang="ts">
|
||||
import api from '../api';
|
||||
import * as overlays from '../../../services/overlay';
|
||||
|
||||
export default {
|
||||
name: 'uiPagepicker',
|
||||
|
||||
props: {
|
||||
value: {
|
||||
type: [String, Array],
|
||||
default: null
|
||||
},
|
||||
model: Object,
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
disabledIds: {
|
||||
type: [Array, Function],
|
||||
default: []
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
rootId: {
|
||||
type: [String, Function],
|
||||
default: null
|
||||
},
|
||||
options: {
|
||||
type: Object,
|
||||
default: () => { }
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
previews: []
|
||||
}),
|
||||
|
||||
watch: {
|
||||
value()
|
||||
{
|
||||
this.updatePreviews();
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
multiple()
|
||||
{
|
||||
return this.limit > 1;
|
||||
},
|
||||
canAdd()
|
||||
{
|
||||
let count = Array.isArray(this.value) ? this.value.length : (!this.value ? 0 : 1);
|
||||
return !this.disabled && count < this.limit;
|
||||
}
|
||||
},
|
||||
|
||||
mounted()
|
||||
{
|
||||
this.updatePreviews();
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
onChange(value)
|
||||
{
|
||||
this.$emit('change', value);
|
||||
this.$emit('input', value);
|
||||
this.$emit('update:value', value);
|
||||
// TODO this does not trigger the forms dirty flag
|
||||
},
|
||||
|
||||
|
||||
async updatePreviews()
|
||||
{
|
||||
if (!this.value || (Array.isArray(this.value) && !this.value.length))
|
||||
{
|
||||
this.previews = [];
|
||||
return;
|
||||
}
|
||||
|
||||
let ids = Array.isArray(this.value) ? this.value : [this.value];
|
||||
|
||||
const result = await api.getPreviews(ids);
|
||||
this.previews = result.data;
|
||||
},
|
||||
|
||||
|
||||
remove(id)
|
||||
{
|
||||
if (Array.isArray(this.value))
|
||||
{
|
||||
let index = this.value.indexOf(id);
|
||||
this.value.splice(index, 1);
|
||||
this.onChange(this.value);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.onChange(this.limit > 1 ? [] : null);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
async pick(id)
|
||||
{
|
||||
if (this.disabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let disabledIds = [];
|
||||
|
||||
if (!!this.value && !Array.isArray(this.value))
|
||||
{
|
||||
disabledIds = [this.value];
|
||||
}
|
||||
else if (Array.isArray(this.value))
|
||||
{
|
||||
disabledIds = this.value;
|
||||
}
|
||||
|
||||
disabledIds.push(this.model.id);
|
||||
|
||||
if (typeof this.disabledIds === 'function')
|
||||
{
|
||||
let moreDisabledIds = this.disabledIds(this.model) || [];
|
||||
disabledIds.push(...moreDisabledIds);
|
||||
}
|
||||
else if (this.disabledIds.length > 0)
|
||||
{
|
||||
disabledIds.push(...this.disabledIds);
|
||||
}
|
||||
|
||||
const result = await overlays.open({
|
||||
title: '@page.picker.headline',
|
||||
closeLabel: '@ui.close',
|
||||
component: () => import('./overlay.vue'),
|
||||
display: 'editor',
|
||||
model: this.multiple ? id : this.value,
|
||||
rootId: typeof this.rootId === 'function' ? this.rootId(this.model) : this.rootId,
|
||||
disabledIds: disabledIds
|
||||
});
|
||||
|
||||
if (result.eventType == 'confirm')
|
||||
{
|
||||
if (this.multiple)
|
||||
{
|
||||
if (!this.value || !Array.isArray(this.value))
|
||||
{
|
||||
this.onChange([result.value.id]);
|
||||
}
|
||||
else if (this.value.indexOf(result.value.id) < 0)
|
||||
{
|
||||
if (id)
|
||||
{
|
||||
this.remove(id);
|
||||
}
|
||||
this.value.push(result.value.id);
|
||||
this.onChange(this.value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.onChange(result.value ? result.value.id : null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.ui-pagepicker-preview
|
||||
{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.ui-icon-button
|
||||
{
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
//background: none;
|
||||
|
||||
i
|
||||
{
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ui-pagepicker-previews + .ui-select-button,
|
||||
.ui-pagepicker-preview + .ui-pagepicker-preview
|
||||
{
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
@@ -6,9 +6,6 @@ export default {
|
||||
|
||||
install(app: ZeroPluginOptions)
|
||||
{
|
||||
//app.vue.component('ui-countrypicker', defineAsyncComponent(() => import('./ui-countrypicker.vue')));
|
||||
|
||||
//app.schema('spaces:default', () => import('./schemas/list-default'));
|
||||
app.schema('pages:zero.folder', () => import('./schemas/folder-editor'));
|
||||
|
||||
app.linkArea('zero.pages', '@zero.config.linkareas.pages', () => import('./partials/linkpicker.vue'));
|
||||
@@ -33,6 +30,26 @@ export default {
|
||||
]
|
||||
});
|
||||
|
||||
app.link
|
||||
app.vue.component('ui-pagepicker', defineAsyncComponent(() => import('./picker/ui-pagepicker.vue')));
|
||||
app.fieldType('pagePicker', defineAsyncComponent(() => import('./picker/field-pagepicker.vue')));
|
||||
}
|
||||
} as ZeroPlugin;
|
||||
} as ZeroPlugin;
|
||||
|
||||
|
||||
declare module 'zero/schemas'
|
||||
{
|
||||
export interface ZeroEditorField
|
||||
{
|
||||
/**
|
||||
* Renders a page picker
|
||||
* @param {PagePickerFieldOptions} [options] - Custom options
|
||||
*/
|
||||
pagePicker(options?: PagePickerFieldOptions): ZeroEditorField;
|
||||
}
|
||||
|
||||
export interface PagePickerFieldOptions extends PickerFieldOptions
|
||||
{
|
||||
rootId?: string | ((model: any) => string);
|
||||
disabledIds?: string[] | ((model: any) => string[]);
|
||||
}
|
||||
}
|
||||
@@ -8,12 +8,16 @@ public class PagesController : ZeroBackofficeController
|
||||
{
|
||||
readonly IPagesStore Store;
|
||||
readonly IPageTreeService PageTreeService;
|
||||
readonly IPageTypeService PageTypeService;
|
||||
readonly IRoutes Routes;
|
||||
|
||||
|
||||
public PagesController(IPagesStore store, IPageTreeService pageTreeService)
|
||||
public PagesController(IPagesStore store, IPageTreeService pageTreeService, IPageTypeService pageTypeService, IRoutes routes)
|
||||
{
|
||||
Store = store;
|
||||
PageTreeService = pageTreeService;
|
||||
PageTypeService = pageTypeService;
|
||||
Routes = routes;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,4 +41,45 @@ public class PagesController : ZeroBackofficeController
|
||||
pages = descendantCount + 1
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("previews")]
|
||||
public async Task<ActionResult<List<LinkPreview>>> GetPreviews([FromQuery] List<string> ids)
|
||||
{
|
||||
IEnumerable<FlavorConfig> pageTypes = PageTypeService.GetAll();
|
||||
Dictionary<string, Page> pages = await Store.Load(ids.ToArray());
|
||||
Dictionary<Page, Route> routes = await Routes.GetRoutes(pages.Where(x => x.Value != null).Select(x => x.Value).ToArray());
|
||||
|
||||
List<LinkPreview> previews = new();
|
||||
|
||||
foreach ((string id, Page page) in pages)
|
||||
{
|
||||
if (page != null)
|
||||
{
|
||||
routes.TryGetValue(page, out Route route);
|
||||
FlavorConfig pageType = PageTypeService.GetByAlias(page.Flavor);
|
||||
|
||||
previews.Add(new()
|
||||
{
|
||||
Name = page.Name,
|
||||
Text = route?.Url.Or("@page.picker.urlnotfound"),
|
||||
Id = page.Id,
|
||||
Icon = pageType?.Icon.Or("fth-folder")
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
previews.Add(new()
|
||||
{
|
||||
HasError = true,
|
||||
Icon = "fth-alert-circle color-red",
|
||||
Id = "tmp_" + IdGenerator.Create(),
|
||||
Name = "@errors.preview.notfound",
|
||||
Text = "@errors.preview.notfound_text"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return previews;
|
||||
}
|
||||
}
|
||||
@@ -524,7 +524,8 @@
|
||||
},
|
||||
|
||||
"picker": {
|
||||
"headline": "Select a page"
|
||||
"headline": "Select a page",
|
||||
"urlnotfound": "URL not found"
|
||||
},
|
||||
|
||||
"infotab": {
|
||||
|
||||
Reference in New Issue
Block a user