Skip to content

Commit 6e94642

Browse files
authored
Replacing admin blocks (#5296)
* Admin: Refactoring and improve index blocks #2642 * Admin: Include link to Colors page in the AdminBlocks response payload #2642 * Minor: Format code #2642 * Display: Add BaseDivider component #2642 * Internal: Add page categories for admin blocks #2642 * Admin: Allow edit blocks #2642
1 parent 453cfc9 commit 6e94642

File tree

12 files changed

+543
-116
lines changed

12 files changed

+543
-116
lines changed

assets/css/scss/atoms/_divider.scss

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
.divider {
2+
@apply bg-white;
3+
4+
&[aria-orientation="vertical"] {
5+
@apply before:absolute before:block before:left-1/2 before:top-0 before:h-full before:content-[""] before:border-l before:border-solid before:border-gray-25
6+
flex min-h-full mx-2 py-2 relative justify-center;
7+
8+
div {
9+
@apply first:py-2;
10+
}
11+
}
12+
13+
&[aria-orientation="horizontal"] {
14+
@apply before:absolute before:block before:left-0 before:w-full before:top-1/2 before:content-[""] before:border-t before:border-solid before:border-gray-25
15+
flex w-full relative items-center my-2 px-2;
16+
17+
div {
18+
@apply first:px-2;
19+
}
20+
}
21+
22+
div {
23+
@apply first:z-[1] first:bg-white first:text-gray-50 first:font-semibold first:text-caption;
24+
}
25+
}

assets/css/scss/index.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
@import "atoms/buttons";
2020
@import "atoms/calendar";
2121
@import "atoms/checkbox";
22+
@import "atoms/divider";
2223
@import "atoms/dropdown";
2324
@import "atoms/fieldset";
2425
@import "atoms/inline_message";
Lines changed: 77 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<template>
2-
<div class="admin-index__block-container">
2+
<div
3+
class="admin-index__block-container"
4+
:class="id"
5+
>
36
<div class="admin-index__block">
47
<div class="flex gap-2 justify-between">
58
<h4>
@@ -9,9 +12,17 @@
912
</div>
1013

1114
<div class="space-y-4">
12-
<p v-if="props.description" class="text-body-4" v-text="props.description" />
13-
14-
<form v-if="props.searchUrl" :action="props.searchUrl" method="get">
15+
<p
16+
v-if="props.description"
17+
class="text-body-4"
18+
v-text="props.description"
19+
/>
20+
21+
<form
22+
v-if="props.searchUrl"
23+
:action="props.searchUrl"
24+
method="get"
25+
>
1526
<BaseInputGroup
1627
:button-label="t('Search')"
1728
:input-placeholder="t('Keyword')"
@@ -22,7 +33,10 @@
2233
</div>
2334

2435
<div class="p-menu p-component p-ripple-disabled">
25-
<ul class="p-menu-list p-reset" role="menu">
36+
<ul
37+
class="p-menu-list p-reset"
38+
role="menu"
39+
>
2640
<li
2741
v-for="(item, index) in visibleItems"
2842
:key="index"
@@ -32,43 +46,88 @@
3246
role="menuitem"
3347
>
3448
<div class="p-menuitem-content">
35-
<a :href="item.url" class="p-menuitem-link">
36-
<span class="p-menuitem-text" v-text="item.label" />
49+
<router-link
50+
v-if="item.route"
51+
v-slot="{ href, navigate }"
52+
:to="item.route"
53+
custom
54+
>
55+
<a
56+
:href="href"
57+
class="p-menuitem-link"
58+
v-bind="props.action"
59+
@click="navigate"
60+
>
61+
<span
62+
class="p-menuitem-text"
63+
v-text="item.label"
64+
/>
65+
</a>
66+
</router-link>
67+
<a
68+
v-else-if="item.url"
69+
:href="item.url"
70+
class="p-menuitem-link"
71+
v-bind="props.action"
72+
>
73+
<span
74+
class="p-menuitem-text"
75+
v-text="item.label"
76+
/>
3777
</a>
3878
</div>
3979
</li>
40-
<slot></slot>
4180
</ul>
4281
</div>
82+
83+
<AdminBlockExtraContent
84+
:id="id"
85+
v-model="modelExtraContent"
86+
:editable="editable"
87+
/>
4388
</div>
4489
</div>
4590
</template>
4691

4792
<script setup>
48-
import { computed } from "vue";
49-
import { useI18n } from "vue-i18n";
50-
import BaseInputGroup from "../basecomponents/BaseInputGroup.vue";
51-
import BaseIcon from "../basecomponents/BaseIcon.vue";
93+
import { computed } from "vue"
94+
import { useI18n } from "vue-i18n"
95+
import BaseInputGroup from "../basecomponents/BaseInputGroup.vue"
96+
import BaseIcon from "../basecomponents/BaseIcon.vue"
97+
import AdminBlockExtraContent from "./AdminBlockExtraContent.vue"
98+
99+
const { t } = useI18n()
52100
53-
const { t } = useI18n();
101+
const modelExtraContent = defineModel("extraContent", {
102+
type: Object,
103+
})
54104
55105
const props = defineProps({
106+
id: {
107+
type: String,
108+
required: true,
109+
},
110+
editable: {
111+
type: Boolean,
112+
required: false,
113+
default: false,
114+
},
56115
icon: { type: String, required: false, default: () => "admin-settings" },
57116
title: { type: String, require: true, default: () => "" },
58117
description: { type: String, required: false, default: () => null },
59118
searchUrl: { type: String, required: false, default: () => null },
60119
items: { type: Array, required: true, default: () => [] },
61-
});
120+
})
62121
63122
const visibleItems = computed(() =>
64123
props.items
65124
.map((item) => {
66125
if (!Object.keys(item).includes("visible")) {
67-
item.visible = true;
126+
item.visible = true
68127
}
69128
70-
return item;
129+
return item
71130
})
72-
.filter((item) => item.visible)
73-
);
131+
.filter((item) => item.visible),
132+
)
74133
</script>
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<script setup>
2+
import { ref } from "vue"
3+
import { useI18n } from "vue-i18n"
4+
import Inplace from "primevue/inplace"
5+
import BaseTinyEditor from "../basecomponents/BaseTinyEditor.vue"
6+
import { useSecurityStore } from "../../store/securityStore"
7+
import pageService from "../../services/pageService"
8+
import BaseDivider from "../basecomponents/BaseDivider.vue"
9+
10+
const props = defineProps({
11+
id: {
12+
type: String,
13+
required: true,
14+
},
15+
editable: {
16+
type: Boolean,
17+
required: true,
18+
},
19+
})
20+
21+
const modelExtraContent = defineModel({
22+
type: Object,
23+
})
24+
25+
const securityStore = useSecurityStore()
26+
27+
const { t, locale } = useI18n()
28+
29+
const newExtraContent = ref(modelExtraContent.value.content)
30+
31+
async function saveExtraContent() {
32+
if (modelExtraContent.value["@id"]) {
33+
if (!newExtraContent.value) {
34+
await pageService.delete(modelExtraContent.value["@id"])
35+
36+
modelExtraContent.value = {
37+
category: modelExtraContent.value.category,
38+
}
39+
40+
return
41+
}
42+
43+
const page = await pageService.update(modelExtraContent.value["@id"], {
44+
content: newExtraContent.value,
45+
})
46+
47+
modelExtraContent.value.content = page.content
48+
49+
return
50+
}
51+
52+
if (newExtraContent.value) {
53+
const page = await pageService.post({
54+
title: props.id,
55+
content: newExtraContent.value,
56+
enabled: true,
57+
locale: locale.value,
58+
url: "/api/access_urls/" + window.access_url_id,
59+
creator: securityStore.user["@id"],
60+
category: modelExtraContent.value.category,
61+
})
62+
63+
modelExtraContent.value = {
64+
"@id": page["@id"],
65+
content: page.content,
66+
category: page.category["@id"],
67+
}
68+
}
69+
}
70+
</script>
71+
72+
<template>
73+
<Inplace
74+
v-if="editable"
75+
:closable="true"
76+
@close="saveExtraContent"
77+
>
78+
<template #display>
79+
<BaseDivider
80+
align="right"
81+
:title="t('Editable content')"
82+
/>
83+
<div
84+
v-if="modelExtraContent.content"
85+
class="text-body-2"
86+
v-html="modelExtraContent.content"
87+
/>
88+
</template>
89+
<template #content>
90+
<BaseTinyEditor
91+
v-model="newExtraContent"
92+
:editor-id="'new-description-editor' + id"
93+
:full-page="false"
94+
/>
95+
</template>
96+
</Inplace>
97+
<div
98+
v-else-if="modelExtraContent.content"
99+
class="text-body-2"
100+
v-html="modelExtraContent.content"
101+
/>
102+
</template>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<script setup>
2+
import Divider from "primevue/divider"
3+
4+
defineProps({
5+
align: {
6+
type: String,
7+
required: false,
8+
default: null,
9+
},
10+
layout: {
11+
type: String,
12+
required: false,
13+
default: "horizontal",
14+
},
15+
title: {
16+
type: [String, undefined],
17+
required: false,
18+
default: null,
19+
},
20+
})
21+
</script>
22+
23+
<template>
24+
<Divider
25+
:align="align"
26+
:layout="layout"
27+
class="divider"
28+
unstyled
29+
>
30+
{{ title }}
31+
</Divider>
32+
</template>

0 commit comments

Comments
 (0)