@oxygen-cms/ui 1.9.1 → 2.1.0
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/package.json +1 -1
- package/src/CrudApi.js +39 -0
- package/src/PagesApi.js +2 -0
- package/src/PartialsApi.js +7 -0
- package/src/components/ContentResourceEdit.vue +980 -0
- package/src/components/{PageEdit.vue → PageEditWysiwyg.vue} +1 -1
- package/src/components/ResourceList.vue +8 -3
- package/src/components/VersionsDrawer.vue +386 -0
- package/src/components/content/PartialNodeView.vue +1 -1
- package/src/components/pages/CreatePageDropdown.vue +5 -5
- package/src/components/pages/PageActions.vue +67 -0
- package/src/components/pages/PageChooseParent.vue +170 -0
- package/src/components/pages/PageEdit.vue +149 -0
- package/src/components/pages/PageList.vue +1 -1
- package/src/components/{PageNestedRow.vue → pages/PageNestedRow.vue} +3 -3
- package/src/components/{PageStatusIcon.vue → pages/PageStatusIcon.vue} +1 -1
- package/src/components/{PageTable.vue → pages/PageTable.vue} +5 -5
- package/src/components/partials/CreatePartialDropdown.vue +1 -1
- package/src/components/{PartialActions.vue → partials/PartialActions.vue} +1 -1
- package/src/components/partials/PartialEdit.vue +49 -0
- package/src/components/{PartialList.vue → partials/PartialList.vue} +3 -3
- package/src/components/{PartialStatusIcon.vue → partials/PartialStatusIcon.vue} +1 -1
- package/src/components/{PartialTable.vue → partials/PartialTable.vue} +1 -1
- package/src/icons.js +11 -2
- package/src/modules/PagesPartials.js +10 -27
- package/src/components/LegacyPage.vue +0 -263
- package/src/components/PageActions.vue +0 -151
- /package/src/components/{PageNestedPagination.vue → pages/PageNestedPagination.vue} +0 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="page-choose-parent">
|
|
3
|
+
<b-field v-if="label" :label="label">
|
|
4
|
+
<b-autocomplete
|
|
5
|
+
v-model="searchQuery"
|
|
6
|
+
:key="autocompleteKey"
|
|
7
|
+
:disabled="isLoading || loadingCurrentParent"
|
|
8
|
+
open-on-focus
|
|
9
|
+
:data="sortedPagesList"
|
|
10
|
+
:placeholder="placeholder"
|
|
11
|
+
clearable
|
|
12
|
+
@select="onSelect">
|
|
13
|
+
<template #default="props">
|
|
14
|
+
<span :style="getOptionStyle(props.option)">
|
|
15
|
+
{{ props.option.title }} - {{ props.option.slug }}
|
|
16
|
+
<span v-if="isCurrentParent(props.option)" style="opacity: 0.6;"> (current parent)</span>
|
|
17
|
+
</span>
|
|
18
|
+
</template>
|
|
19
|
+
<template #empty>No results found</template>
|
|
20
|
+
</b-autocomplete>
|
|
21
|
+
</b-field>
|
|
22
|
+
<b-autocomplete
|
|
23
|
+
v-else
|
|
24
|
+
v-model="searchQuery"
|
|
25
|
+
:key="autocompleteKey"
|
|
26
|
+
:disabled="isLoading || loadingCurrentParent"
|
|
27
|
+
open-on-focus
|
|
28
|
+
:data="sortedPagesList"
|
|
29
|
+
:placeholder="placeholder"
|
|
30
|
+
clearable
|
|
31
|
+
@select="onSelect">
|
|
32
|
+
<template #default="props">
|
|
33
|
+
<span :style="getOptionStyle(props.option)">
|
|
34
|
+
{{ props.option.title }} - {{ props.option.slug }}
|
|
35
|
+
<span v-if="isCurrentParent(props.option)" style="opacity: 0.6;"> (current parent)</span>
|
|
36
|
+
</span>
|
|
37
|
+
</template>
|
|
38
|
+
<template #empty>No results found</template>
|
|
39
|
+
</b-autocomplete>
|
|
40
|
+
</div>
|
|
41
|
+
</template>
|
|
42
|
+
|
|
43
|
+
<script>
|
|
44
|
+
import PagesApi from "../../PagesApi.js";
|
|
45
|
+
|
|
46
|
+
export default {
|
|
47
|
+
name: "PageChooseParent",
|
|
48
|
+
props: {
|
|
49
|
+
currentParentId: {
|
|
50
|
+
type: Number,
|
|
51
|
+
default: null
|
|
52
|
+
},
|
|
53
|
+
label: {
|
|
54
|
+
type: String,
|
|
55
|
+
default: ''
|
|
56
|
+
},
|
|
57
|
+
excludePageId: {
|
|
58
|
+
type: Number,
|
|
59
|
+
default: null // Don't allow selecting this page (e.g., can't move page to itself)
|
|
60
|
+
},
|
|
61
|
+
showSlug: {
|
|
62
|
+
type: Boolean,
|
|
63
|
+
default: false // If true, show slug in placeholder; otherwise show title
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
data() {
|
|
67
|
+
return {
|
|
68
|
+
pagesApi: new PagesApi(),
|
|
69
|
+
searchQuery: '',
|
|
70
|
+
isLoading: false,
|
|
71
|
+
pagesList: [],
|
|
72
|
+
autocompleteKey: 0, // Force re-render after selection
|
|
73
|
+
currentParentPage: null,
|
|
74
|
+
loadingCurrentParent: false
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
computed: {
|
|
78
|
+
sortedPagesList() {
|
|
79
|
+
// Sort with Home page (slug '/') at the top, then alphabetically by title
|
|
80
|
+
// Also filter out the excluded page
|
|
81
|
+
return [...this.pagesList]
|
|
82
|
+
.filter(page => !this.excludePageId || page.id !== this.excludePageId)
|
|
83
|
+
.sort((a, b) => {
|
|
84
|
+
if (a.slug === '/') return -1;
|
|
85
|
+
if (b.slug === '/') return 1;
|
|
86
|
+
return a.title.localeCompare(b.title);
|
|
87
|
+
});
|
|
88
|
+
},
|
|
89
|
+
placeholder() {
|
|
90
|
+
if (this.loadingCurrentParent) {
|
|
91
|
+
return '';
|
|
92
|
+
}
|
|
93
|
+
if (this.currentParentPage) {
|
|
94
|
+
if (this.showSlug) {
|
|
95
|
+
// For PageEdit - show slug, and (root) for root pages
|
|
96
|
+
return this.currentParentPage.slug === '/' ? '(root)' : this.currentParentPage.slug;
|
|
97
|
+
} else {
|
|
98
|
+
// For PageActions - show title
|
|
99
|
+
return this.currentParentPage.title;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return this.showSlug ? '(root)' : '(root)';
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
watch: {
|
|
106
|
+
'searchQuery': 'fetchData',
|
|
107
|
+
'currentParentId': {
|
|
108
|
+
immediate: true,
|
|
109
|
+
handler(newId) {
|
|
110
|
+
this.loadCurrentParent(newId);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
created() {
|
|
115
|
+
this.isLoading = true;
|
|
116
|
+
this.fetchData();
|
|
117
|
+
},
|
|
118
|
+
methods: {
|
|
119
|
+
async fetchData() {
|
|
120
|
+
let data = await this.pagesApi.list({ inTrash: false, page: 1, q: this.searchQuery });
|
|
121
|
+
this.pagesList = data.items;
|
|
122
|
+
this.isLoading = false;
|
|
123
|
+
},
|
|
124
|
+
async loadCurrentParent(parentId) {
|
|
125
|
+
if (!parentId || typeof parentId !== 'number') {
|
|
126
|
+
this.currentParentPage = null;
|
|
127
|
+
this.loadingCurrentParent = false;
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
this.loadingCurrentParent = true;
|
|
132
|
+
try {
|
|
133
|
+
const response = await this.pagesApi.get(parentId);
|
|
134
|
+
this.currentParentPage = response.data || response.item;
|
|
135
|
+
} catch (error) {
|
|
136
|
+
console.error('Failed to load current parent page:', error);
|
|
137
|
+
this.currentParentPage = null;
|
|
138
|
+
} finally {
|
|
139
|
+
this.loadingCurrentParent = false;
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
onSelect(parentPage) {
|
|
143
|
+
// Don't allow selecting current parent
|
|
144
|
+
if (this.isCurrentParent(parentPage)) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
this.$emit('select', parentPage);
|
|
149
|
+
|
|
150
|
+
// Clear search query and force re-render of autocomplete
|
|
151
|
+
this.searchQuery = '';
|
|
152
|
+
this.autocompleteKey++;
|
|
153
|
+
},
|
|
154
|
+
isCurrentParent(page) {
|
|
155
|
+
if (!this.currentParentId) return false;
|
|
156
|
+
return page.id === this.currentParentId;
|
|
157
|
+
},
|
|
158
|
+
getOptionStyle(option) {
|
|
159
|
+
let style = '';
|
|
160
|
+
if (option.slug === '/') {
|
|
161
|
+
style += 'font-weight: bold;';
|
|
162
|
+
}
|
|
163
|
+
if (this.isCurrentParent(option)) {
|
|
164
|
+
style += ' opacity: 0.5; cursor: not-allowed;';
|
|
165
|
+
}
|
|
166
|
+
return style;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
</script>
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<ContentResourceEdit
|
|
3
|
+
:resource-api="pagesApi"
|
|
4
|
+
display-name="Page"
|
|
5
|
+
route-prefix="pages"
|
|
6
|
+
list-route-name="pages.list"
|
|
7
|
+
trash-route-name="pages.trash"
|
|
8
|
+
:published-stage="STAGE_PUBLISHED"
|
|
9
|
+
:has-slug="true"
|
|
10
|
+
:has-hierarchy="true"
|
|
11
|
+
:has-version-actions="true"
|
|
12
|
+
:has-full-page-preview="true"
|
|
13
|
+
>
|
|
14
|
+
<!-- Page-specific settings fields -->
|
|
15
|
+
<template #settings-drawer-fields="{ model }">
|
|
16
|
+
<b-field>
|
|
17
|
+
<template #label>
|
|
18
|
+
URL
|
|
19
|
+
<b-tooltip multilined position="is-right" type="is-dark" label="The URL at which this page is located. Change the parent page to update the path prefix.">
|
|
20
|
+
<b-icon size="is-small" icon="question-circle"></b-icon>
|
|
21
|
+
</b-tooltip>
|
|
22
|
+
</template>
|
|
23
|
+
<p class="control">
|
|
24
|
+
<PageChooseParent
|
|
25
|
+
ref="parentChooser"
|
|
26
|
+
:current-parent-id="model.parent"
|
|
27
|
+
:exclude-page-id="model.id"
|
|
28
|
+
:show-slug="true"
|
|
29
|
+
@select="moveToParent($event, model)"
|
|
30
|
+
/>
|
|
31
|
+
</p>
|
|
32
|
+
<p class="control">
|
|
33
|
+
<b-button disabled style="border-left: 0; border-radius: 0;">/</b-button>
|
|
34
|
+
</p>
|
|
35
|
+
<b-input v-model="model.slugPart" placeholder="url-slug" expanded></b-input>
|
|
36
|
+
</b-field>
|
|
37
|
+
|
|
38
|
+
<b-field label="Description">
|
|
39
|
+
<b-input v-model="model.description" type="textarea" placeholder="Page description"></b-input>
|
|
40
|
+
</b-field>
|
|
41
|
+
|
|
42
|
+
<b-field>
|
|
43
|
+
<template #label>
|
|
44
|
+
Tags
|
|
45
|
+
<b-tooltip multilined position="is-right" type="is-dark" label="A list of keywords for this page. Used for SEO">
|
|
46
|
+
<b-icon size="is-small" icon="question-circle"></b-icon>
|
|
47
|
+
</b-tooltip>
|
|
48
|
+
</template>
|
|
49
|
+
<b-taginput v-model="model.tags"></b-taginput>
|
|
50
|
+
</b-field>
|
|
51
|
+
|
|
52
|
+
<div class="field">
|
|
53
|
+
<label class="label">
|
|
54
|
+
Metadata
|
|
55
|
+
<b-tooltip multilined label="An HTML field used to inject custom metadata into the page. Used for SEO." position="is-right" type="is-dark">
|
|
56
|
+
<b-icon size="is-small" icon="question-circle"></b-icon>
|
|
57
|
+
</b-tooltip>
|
|
58
|
+
</label>
|
|
59
|
+
<div class="control">
|
|
60
|
+
<CodeEditor v-model="model.meta" lang="html" height="10rem" />
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<div class="field">
|
|
65
|
+
<label class="label">Options</label>
|
|
66
|
+
<div class="control">
|
|
67
|
+
<CodeEditor v-model="model.options" lang="json" height="10rem" />
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
</template>
|
|
71
|
+
|
|
72
|
+
<!-- Page-specific dropdown actions -->
|
|
73
|
+
<template #dropdown-actions="{ model, isPublished }">
|
|
74
|
+
<b-dropdown-item
|
|
75
|
+
v-if="isPublished"
|
|
76
|
+
aria-role="menuitem"
|
|
77
|
+
@click="viewOnSite(model)"
|
|
78
|
+
>
|
|
79
|
+
<b-icon icon="external-link-alt"></b-icon>
|
|
80
|
+
View on Site
|
|
81
|
+
</b-dropdown-item>
|
|
82
|
+
</template>
|
|
83
|
+
|
|
84
|
+
<!-- Version-specific actions (e.g., View on Site for published versions) -->
|
|
85
|
+
<template #version-dropdown-actions="{ version, isPublished }">
|
|
86
|
+
<b-dropdown-item
|
|
87
|
+
v-if="isPublished"
|
|
88
|
+
aria-role="menuitem"
|
|
89
|
+
@click="viewVersionOnSite(version)"
|
|
90
|
+
>
|
|
91
|
+
<b-icon icon="external-link-alt"></b-icon>
|
|
92
|
+
View on Site
|
|
93
|
+
</b-dropdown-item>
|
|
94
|
+
</template>
|
|
95
|
+
</ContentResourceEdit>
|
|
96
|
+
</template>
|
|
97
|
+
|
|
98
|
+
<script>
|
|
99
|
+
import ContentResourceEdit from '../ContentResourceEdit.vue';
|
|
100
|
+
import CodeEditor from '../CodeEditor.vue';
|
|
101
|
+
import PageChooseParent from './PageChooseParent.vue';
|
|
102
|
+
import PagesApi from '../../PagesApi.js';
|
|
103
|
+
import { morphToNotification } from '../../api.js';
|
|
104
|
+
|
|
105
|
+
export default {
|
|
106
|
+
name: "PageEdit",
|
|
107
|
+
components: { ContentResourceEdit, CodeEditor, PageChooseParent },
|
|
108
|
+
data() {
|
|
109
|
+
return {
|
|
110
|
+
pagesApi: new PagesApi(),
|
|
111
|
+
STAGE_PUBLISHED: PagesApi.STAGE_PUBLISHED
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
methods: {
|
|
115
|
+
viewOnSite(model) {
|
|
116
|
+
const url = PagesApi.slugToUrl(model.slug || model.slugPart);
|
|
117
|
+
window.open(url, '_blank');
|
|
118
|
+
},
|
|
119
|
+
viewVersionOnSite(version) {
|
|
120
|
+
const url = PagesApi.slugToUrl(version.slug);
|
|
121
|
+
window.open(url, '_blank');
|
|
122
|
+
},
|
|
123
|
+
async moveToParent(parentPage, model) {
|
|
124
|
+
try {
|
|
125
|
+
const data = await this.pagesApi.update({
|
|
126
|
+
id: model.id,
|
|
127
|
+
parent: parentPage.id,
|
|
128
|
+
autoConvertToDraft: 'no',
|
|
129
|
+
version: false
|
|
130
|
+
});
|
|
131
|
+
this.$buefy.toast.open(morphToNotification(data));
|
|
132
|
+
|
|
133
|
+
// Tell PageChooseParent to reload the NEW parent for display (use parentPage.id, not model.parent)
|
|
134
|
+
this.$nextTick(() => {
|
|
135
|
+
if (this.$refs.parentChooser) {
|
|
136
|
+
this.$refs.parentChooser.loadCurrentParent(parentPage.id);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
} catch (error) {
|
|
140
|
+
console.error('Failed to move page:', error);
|
|
141
|
+
this.$buefy.toast.open({
|
|
142
|
+
message: 'Failed to move page',
|
|
143
|
+
type: 'is-danger'
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
</script>
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
|
|
18
18
|
<script>
|
|
19
19
|
import PageStatusIcon from "./PageStatusIcon.vue";
|
|
20
|
-
import Updated from "
|
|
21
|
-
import PagesApi from "
|
|
20
|
+
import Updated from "../Updated.vue";
|
|
21
|
+
import PagesApi from "../../PagesApi.js";
|
|
22
22
|
|
|
23
23
|
export default {
|
|
24
24
|
name: "PageNestedRow",
|
|
@@ -38,7 +38,7 @@ export default {
|
|
|
38
38
|
</script>
|
|
39
39
|
|
|
40
40
|
<style scoped lang="scss">
|
|
41
|
-
@import "
|
|
41
|
+
@import "../../styles/pages-table.scss";
|
|
42
42
|
|
|
43
43
|
//.has-darker-top-border {
|
|
44
44
|
////border-top-color: $grey-dark;
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
@details-close="item => setExpanded(item, false)"
|
|
28
28
|
@sort="onSort">
|
|
29
29
|
<b-table-column v-slot="props" label="Title" :sortable="!!onSort" field="title">{{ props.row.title }} <PageStatusIcon :item="props.row"></PageStatusIcon></b-table-column>
|
|
30
|
-
<b-table-column v-slot="props" label="URL" :sortable="!!onSort" field="slugPart"><a :href="PagesApi.slugToUrl(props.row.slug)" class="is-size-7" target="_blank"
|
|
30
|
+
<b-table-column v-slot="props" label="URL" :sortable="!!onSort" field="slugPart"><a v-if="props.row.stage === PagesApi.STAGE_PUBLISHED" :href="PagesApi.slugToUrl(props.row.slug)" class="is-size-7" target="_blank">{{ PagesApi.slugToUrl(props.row.slug) }} <b-icon icon="external-link-alt"></b-icon></a><em v-else class="is-size-7">(unpublished)</em></b-table-column>
|
|
31
31
|
<b-table-column v-slot="props" label="Description" width="30%" :sortable="!!onSort" field="description"><div class="is-size-7">{{ props.row.description }}</div></b-table-column>
|
|
32
32
|
<b-table-column v-slot="props" label="Last Updated" field="updatedAt" :sortable="!!onSort">
|
|
33
33
|
<div v-if="props.row.updatedAt" class="is-size-7"><Updated :model="props.row"></Updated></div>
|
|
@@ -66,8 +66,8 @@
|
|
|
66
66
|
|
|
67
67
|
<script>
|
|
68
68
|
import PageStatusIcon from "./PageStatusIcon.vue";
|
|
69
|
-
import Updated from "
|
|
70
|
-
import PagesApi from "
|
|
69
|
+
import Updated from "../Updated.vue";
|
|
70
|
+
import PagesApi from "../../PagesApi.js";
|
|
71
71
|
import Vue from "vue";
|
|
72
72
|
import PageNestedRow from "./PageNestedRow.vue";
|
|
73
73
|
import PageNestedPagination from "./PageNestedPagination.vue";
|
|
@@ -146,11 +146,11 @@ export default {
|
|
|
146
146
|
</script>
|
|
147
147
|
|
|
148
148
|
<style scoped lang="scss">
|
|
149
|
-
@import "
|
|
149
|
+
@import "../util.css";
|
|
150
150
|
|
|
151
151
|
::v-deep .table-wrapper.has-sticky-header {
|
|
152
152
|
flex: 1 1 auto;
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
@import "
|
|
155
|
+
@import "../../styles/pages-table";
|
|
156
156
|
</style>
|
|
@@ -101,7 +101,7 @@ export default {
|
|
|
101
101
|
this.$buefy.toast.open(morphToNotification(response));
|
|
102
102
|
this.close();
|
|
103
103
|
this.$emit('created', response.item);
|
|
104
|
-
this.$router.push('
|
|
104
|
+
this.$router.push({ name: 'partials.edit', params: { id: response.item.id } });
|
|
105
105
|
} catch(e) {
|
|
106
106
|
// Error handled by API layer
|
|
107
107
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<ContentResourceEdit
|
|
3
|
+
:resource-api="partialsApi"
|
|
4
|
+
display-name="Partial"
|
|
5
|
+
route-prefix="partials"
|
|
6
|
+
list-route-name="partials.list"
|
|
7
|
+
trash-route-name="partials.trash"
|
|
8
|
+
:published-stage="STAGE_PUBLISHED"
|
|
9
|
+
:has-slug="false"
|
|
10
|
+
:has-hierarchy="false"
|
|
11
|
+
>
|
|
12
|
+
<!-- Partial-specific settings fields -->
|
|
13
|
+
<template #settings-drawer-fields="{ model }">
|
|
14
|
+
<b-field label="Key">
|
|
15
|
+
<template #label>
|
|
16
|
+
Key
|
|
17
|
+
<b-tooltip multilined position="is-bottom-right" type="is-dark"
|
|
18
|
+
label="A unique machine-readable identifier for this partial (e.g., 'footer.copyright', 'header.navigation')">
|
|
19
|
+
<b-icon size="is-small" icon="question-circle"></b-icon>
|
|
20
|
+
</b-tooltip>
|
|
21
|
+
</template>
|
|
22
|
+
<b-input v-model="model.key" placeholder="e.g., footer.copyright" />
|
|
23
|
+
</b-field>
|
|
24
|
+
|
|
25
|
+
<b-field label="Author">
|
|
26
|
+
<b-input v-model="model.author" placeholder="Author name" />
|
|
27
|
+
</b-field>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<!-- No dropdown-actions slot needed - partials don't have "View on Site" -->
|
|
31
|
+
<!-- No version-dropdown-actions slot needed either -->
|
|
32
|
+
</ContentResourceEdit>
|
|
33
|
+
</template>
|
|
34
|
+
|
|
35
|
+
<script>
|
|
36
|
+
import ContentResourceEdit from '../ContentResourceEdit.vue';
|
|
37
|
+
import PartialsApi from '../../PartialsApi.js';
|
|
38
|
+
|
|
39
|
+
export default {
|
|
40
|
+
name: "PartialEdit",
|
|
41
|
+
components: { ContentResourceEdit },
|
|
42
|
+
data() {
|
|
43
|
+
return {
|
|
44
|
+
partialsApi: new PartialsApi(),
|
|
45
|
+
STAGE_PUBLISHED: PartialsApi.STAGE_PUBLISHED
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
</script>
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
</template>
|
|
20
20
|
|
|
21
21
|
<script>
|
|
22
|
-
import PartialsApi from "
|
|
23
|
-
import ContentEditor from "
|
|
22
|
+
import PartialsApi from "../../PartialsApi.js";
|
|
23
|
+
import ContentEditor from "../content/ContentEditor.vue";
|
|
24
24
|
|
|
25
25
|
export default {
|
|
26
26
|
name: "PartialList",
|
|
@@ -66,7 +66,7 @@ export default {
|
|
|
66
66
|
</script>
|
|
67
67
|
|
|
68
68
|
<style scoped>
|
|
69
|
-
@import "
|
|
69
|
+
@import "../util.css";
|
|
70
70
|
|
|
71
71
|
.card {
|
|
72
72
|
cursor: pointer;
|
package/src/icons.js
CHANGED
|
@@ -102,7 +102,15 @@ import {
|
|
|
102
102
|
faCog,
|
|
103
103
|
faArchive,
|
|
104
104
|
faGlobeAsia,
|
|
105
|
-
|
|
105
|
+
faBars,
|
|
106
|
+
faPenSquare,
|
|
107
|
+
faKey,
|
|
108
|
+
faHistory,
|
|
109
|
+
faEllipsisV,
|
|
110
|
+
faImage,
|
|
111
|
+
faCompress,
|
|
112
|
+
faExpand,
|
|
113
|
+
faStar
|
|
106
114
|
} from "@fortawesome/free-solid-svg-icons";
|
|
107
115
|
|
|
108
116
|
export const addIconsToLibrary = () => {
|
|
@@ -115,5 +123,6 @@ export const addIconsToLibrary = () => {
|
|
|
115
123
|
faFileExcel, faFileCsv, faChevronCircleDown, faChevronCircleUp, faTrash,
|
|
116
124
|
faEye, faEyeSlash, faCaretDown, faCaretUp, faUpload, faUser, faFolder, faHome, faFilePdf, faSignOutAlt, faTag, faStrikethrough, faUnderline, faRemoveFormat, faLink,
|
|
117
125
|
faFolderPlus, faTimes, faQuestionCircle, faFileUpload, faLandmark, faRulerHorizontal, faCog, faArchive, faGlobeAsia, faPenSquare, faKey,
|
|
118
|
-
faFolderOpen, faFile, faFileAudio, faFileImage, faShare, faGripVertical, faImages, faCalendarPlus, faPaperPlane, faHandshake, faHandshakeSlash, faExclamation, faMousePointer, faUnlink, faAngry
|
|
126
|
+
faFolderOpen, faFile, faFileAudio, faFileImage, faShare, faGripVertical, faImages, faCalendarPlus, faPaperPlane, faHandshake, faHandshakeSlash, faExclamation, faMousePointer, faUnlink, faAngry,
|
|
127
|
+
faHistory, faEllipsisV, faImage, faCompress, faExpand, faBars, faStar);
|
|
119
128
|
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import LegacyPage from "../components/LegacyPage.vue";
|
|
2
1
|
import { WEB_CONTENT } from "../main.js";
|
|
3
|
-
import PageEdit from "../components/PageEdit.vue";
|
|
2
|
+
import PageEdit from "../components/pages/PageEdit.vue";
|
|
3
|
+
import PartialEdit from "../components/partials/PartialEdit.vue";
|
|
4
4
|
import ResourceList from "../components/ResourceList.vue";
|
|
5
|
-
import PageTable from "../components/PageTable.vue";
|
|
5
|
+
import PageTable from "../components/pages/PageTable.vue";
|
|
6
6
|
import PagesApi from "../PagesApi.js";
|
|
7
7
|
import PartialsApi from "../PartialsApi.js";
|
|
8
|
-
import PartialTable from "../components/PartialTable.vue";
|
|
9
|
-
import PageActions from "../components/PageActions.vue";
|
|
10
|
-
import PartialActions from "../components/PartialActions.vue";
|
|
8
|
+
import PartialTable from "../components/partials/PartialTable.vue";
|
|
9
|
+
import PageActions from "../components/pages/PageActions.vue";
|
|
10
|
+
import PartialActions from "../components/partials/PartialActions.vue";
|
|
11
11
|
import CreatePageDropdown from "../components/pages/CreatePageDropdown.vue";
|
|
12
12
|
import CreatePartialDropdown from "../components/partials/CreatePartialDropdown.vue";
|
|
13
13
|
|
|
@@ -41,17 +41,6 @@ export default function(ui) {
|
|
|
41
41
|
const pagesProps = { displayName: 'Pages', routePrefix: 'pages', inTrash: false, tableComponent: PageTable, actionsComponent: PageActions, singularDisplayName: 'Page', defaultSortField: 'title', defaultSortOrder: 'asc', resourceApi: new PagesApi(), createDropdownComponent: CreatePageDropdown }
|
|
42
42
|
|
|
43
43
|
ui.addAuthenticatedRoutes([
|
|
44
|
-
{
|
|
45
|
-
path: '(pages|partials)/:subpath/edit',
|
|
46
|
-
component: LegacyPage,
|
|
47
|
-
props: (route) => {
|
|
48
|
-
return {
|
|
49
|
-
fullPath: route.fullPath,
|
|
50
|
-
legacyPrefix: '/oxygen/view',
|
|
51
|
-
adminPrefix: '/oxygen'
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
44
|
{
|
|
56
45
|
path: 'partials/trash',
|
|
57
46
|
name: 'partials.trash',
|
|
@@ -68,9 +57,9 @@ export default function(ui) {
|
|
|
68
57
|
},
|
|
69
58
|
{
|
|
70
59
|
path: 'partials/:id',
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
60
|
+
name: 'partials.edit',
|
|
61
|
+
component: PartialEdit,
|
|
62
|
+
meta: { title: 'Edit Partial' }
|
|
74
63
|
},
|
|
75
64
|
{
|
|
76
65
|
path: 'partials/create',
|
|
@@ -84,17 +73,11 @@ export default function(ui) {
|
|
|
84
73
|
props: { ...pagesProps, inTrash: true }
|
|
85
74
|
},
|
|
86
75
|
{
|
|
87
|
-
path: '
|
|
76
|
+
path: 'pages/:id',
|
|
88
77
|
name: 'pages.edit',
|
|
89
78
|
component: PageEdit,
|
|
90
79
|
meta: { title: 'Edit Page' }
|
|
91
80
|
},
|
|
92
|
-
{
|
|
93
|
-
path: 'pages/:id',
|
|
94
|
-
redirect: to => {
|
|
95
|
-
return { path: 'pages/' + to.params.id + '/edit' }
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
81
|
{
|
|
99
82
|
path: 'pages',
|
|
100
83
|
name: 'pages.list',
|