@oxygen-cms/ui 1.9.0 → 2.0.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.
Files changed (28) hide show
  1. package/.github/workflows/node.js.yml +3 -3
  2. package/package.json +1 -1
  3. package/src/CrudApi.js +39 -0
  4. package/src/PagesApi.js +2 -0
  5. package/src/PartialsApi.js +7 -0
  6. package/src/components/ContentResourceEdit.vue +964 -0
  7. package/src/components/{PageEdit.vue → PageEditWysiwyg.vue} +1 -1
  8. package/src/components/ResourceList.vue +10 -3
  9. package/src/components/VersionsDrawer.vue +386 -0
  10. package/src/components/content/PartialNodeView.vue +1 -1
  11. package/src/components/pages/CreatePageDropdown.vue +5 -5
  12. package/src/components/pages/PageActions.vue +67 -0
  13. package/src/components/pages/PageChooseParent.vue +170 -0
  14. package/src/components/pages/PageEdit.vue +149 -0
  15. package/src/components/pages/PageList.vue +1 -1
  16. package/src/components/{PageNestedRow.vue → pages/PageNestedRow.vue} +3 -3
  17. package/src/components/{PageStatusIcon.vue → pages/PageStatusIcon.vue} +1 -1
  18. package/src/components/{PageTable.vue → pages/PageTable.vue} +5 -5
  19. package/src/components/partials/CreatePartialDropdown.vue +1 -1
  20. package/src/components/{PartialActions.vue → partials/PartialActions.vue} +1 -1
  21. package/src/components/partials/PartialEdit.vue +49 -0
  22. package/src/components/{PartialList.vue → partials/PartialList.vue} +3 -3
  23. package/src/components/{PartialStatusIcon.vue → partials/PartialStatusIcon.vue} +1 -1
  24. package/src/components/{PartialTable.vue → partials/PartialTable.vue} +1 -1
  25. package/src/icons.js +11 -2
  26. package/src/modules/PagesPartials.js +11 -16
  27. package/src/components/PageActions.vue +0 -151
  28. /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>
@@ -7,7 +7,7 @@
7
7
  </template>
8
8
 
9
9
  <script>
10
- import PageTable from "../PageTable.vue";
10
+ import PageTable from "./PageTable.vue";
11
11
  import PagesApi from "../../PagesApi.js";
12
12
 
13
13
  export default {
@@ -17,8 +17,8 @@
17
17
 
18
18
  <script>
19
19
  import PageStatusIcon from "./PageStatusIcon.vue";
20
- import Updated from "./Updated.vue";
21
- import PagesApi from "../PagesApi.js";
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 "../styles/pages-table.scss";
41
+ @import "../../styles/pages-table.scss";
42
42
 
43
43
  //.has-darker-top-border {
44
44
  ////border-top-color: $grey-dark;
@@ -3,7 +3,7 @@
3
3
  </template>
4
4
 
5
5
  <script>
6
- import PagesApi from "../PagesApi.js";
6
+ import PagesApi from "../../PagesApi.js";
7
7
 
8
8
  export default {
9
9
  name: "PageStatusIcon",
@@ -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" v-if="props.row.stage === PagesApi.STAGE_PUBLISHED">{{ 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>
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 "./Updated.vue";
70
- import PagesApi from "../PagesApi.js";
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 "./util.css";
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 "../styles/pages-table";
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('/partials/' + response.item.id + '/edit');
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
  }
@@ -5,7 +5,7 @@
5
5
  </template>
6
6
 
7
7
  <script>
8
- import PartialsApi from "../PartialsApi.js";
8
+ import PartialsApi from "../../PartialsApi.js";
9
9
 
10
10
  export default {
11
11
  name: "PartialActions",
@@ -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 "../PartialsApi.js";
23
- import ContentEditor from "./content/ContentEditor.vue";
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 "./util.css";
69
+ @import "../util.css";
70
70
 
71
71
  .card {
72
72
  cursor: pointer;
@@ -3,7 +3,7 @@
3
3
  </template>
4
4
 
5
5
  <script>
6
- import PartialsApi from "../PartialsApi.js";
6
+ import PartialsApi from "../../PartialsApi.js";
7
7
 
8
8
  export default {
9
9
  name: "PartialStatusIcon",
@@ -33,7 +33,7 @@
33
33
  </template>
34
34
 
35
35
  <script>
36
- import Updated from "./Updated.vue";
36
+ import Updated from "../Updated.vue";
37
37
  import PartialStatusIcon from "./PartialStatusIcon.vue";
38
38
 
39
39
  export default {
package/src/icons.js CHANGED
@@ -102,7 +102,15 @@ import {
102
102
  faCog,
103
103
  faArchive,
104
104
  faGlobeAsia,
105
- faPenSquare, faKey
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,14 @@
1
1
  import LegacyPage from "../components/LegacyPage.vue";
2
2
  import { WEB_CONTENT } from "../main.js";
3
- import PageEdit from "../components/PageEdit.vue";
3
+ import PageEdit from "../components/pages/PageEdit.vue";
4
+ import PartialEdit from "../components/partials/PartialEdit.vue";
4
5
  import ResourceList from "../components/ResourceList.vue";
5
- import PageTable from "../components/PageTable.vue";
6
+ import PageTable from "../components/pages/PageTable.vue";
6
7
  import PagesApi from "../PagesApi.js";
7
8
  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";
9
+ import PartialTable from "../components/partials/PartialTable.vue";
10
+ import PageActions from "../components/pages/PageActions.vue";
11
+ import PartialActions from "../components/partials/PartialActions.vue";
11
12
  import CreatePageDropdown from "../components/pages/CreatePageDropdown.vue";
12
13
  import CreatePartialDropdown from "../components/partials/CreatePartialDropdown.vue";
13
14
 
@@ -42,7 +43,7 @@ export default function(ui) {
42
43
 
43
44
  ui.addAuthenticatedRoutes([
44
45
  {
45
- path: '(pages|partials)/:subpath/edit',
46
+ path: 'pages/:subpath/edit',
46
47
  component: LegacyPage,
47
48
  props: (route) => {
48
49
  return {
@@ -68,9 +69,9 @@ export default function(ui) {
68
69
  },
69
70
  {
70
71
  path: 'partials/:id',
71
- redirect: to => {
72
- return { path: 'partials/' + to.params.id + '/edit' }
73
- }
72
+ name: 'partials.edit',
73
+ component: PartialEdit,
74
+ meta: { title: 'Edit Partial' }
74
75
  },
75
76
  {
76
77
  path: 'partials/create',
@@ -84,17 +85,11 @@ export default function(ui) {
84
85
  props: { ...pagesProps, inTrash: true }
85
86
  },
86
87
  {
87
- path: 'pages2/:id',
88
+ path: 'pages/:id',
88
89
  name: 'pages.edit',
89
90
  component: PageEdit,
90
91
  meta: { title: 'Edit Page' }
91
92
  },
92
- {
93
- path: 'pages/:id',
94
- redirect: to => {
95
- return { path: 'pages/' + to.params.id + '/edit' }
96
- }
97
- },
98
93
  {
99
94
  path: 'pages',
100
95
  name: 'pages.list',