mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
merge titles +start global config page + advanced
* merge all title components in one title * same with subtitle * update components using title and subtitle * enhance css entry point * start global config page and advanced form
This commit is contained in:
parent
0ee88857a3
commit
9499259c74
26 changed files with 691 additions and 236 deletions
|
|
@ -184,7 +184,7 @@ body {
|
|||
}
|
||||
|
||||
.select-btn {
|
||||
@apply relative dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-800 dark:disabled:border-gray-800/0 duration-300 ease-in-out dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 hover:border-gray-600 focus:border-gray-600 flex justify-between align-middle items-center text-left text-sm leading-5.6 w-full rounded-lg border border-solid border-gray-400 bg-white bg-clip-padding px-1.5 py-1 md:px-2.5 md:py-1.5 font-normal text-gray-700 transition-all placeholder:text-gray-500;
|
||||
@apply relative dark:disabled:text-gray-300 disabled:text-gray-700 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-800 dark:disabled:border-gray-800/0 duration-300 ease-in-out dark:border-slate-600 dark:bg-slate-700 dark:text-gray-300 hover:border-gray-600 focus:border-gray-600 flex justify-between align-middle items-center text-left text-sm leading-5.6 w-full md:max-w-[350px] rounded-lg border border-solid border-gray-400 bg-white bg-clip-padding px-1.5 py-1 md:px-2.5 md:py-1.5 font-normal text-gray-700 transition-all placeholder:text-gray-500;
|
||||
}
|
||||
|
||||
.select-btn-name {
|
||||
|
|
@ -220,7 +220,7 @@ body {
|
|||
}
|
||||
|
||||
.input-regular {
|
||||
@apply hover:border-gray-600 outline-none dark:border-slate-600 dark:bg-slate-700 dark:text-gray-200 focus:border-gray-300/0 dark:focus:border-gray-600/0 focus:ring-1 focus:valid:ring-green-500 focus:invalid:ring-red-500 text-sm leading-5.6 ease-in block w-full appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-1.5 py-1 md:px-2.5 md:py-1.5 font-normal text-gray-700 transition-all placeholder:text-gray-500 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-800 dark:disabled:border-gray-800/0 dark:disabled:text-gray-300 disabled:text-gray-700;
|
||||
@apply hover:border-gray-600 outline-none dark:border-slate-600 dark:bg-slate-700 dark:text-gray-200 focus:border-gray-300/0 dark:focus:border-gray-600/0 focus:ring-1 focus:valid:ring-green-500 focus:invalid:ring-red-500 text-sm leading-5.6 ease-in block w-full md:max-w-[350px] appearance-none rounded-lg border border-solid border-gray-300 bg-white bg-clip-padding px-1.5 py-1 md:px-2.5 md:py-1.5 font-normal text-gray-700 transition-all placeholder:text-gray-500 disabled:bg-gray-400 disabled:border-gray-400/0 dark:disabled:bg-gray-800 dark:disabled:border-gray-800/0 dark:disabled:text-gray-300 disabled:text-gray-700;
|
||||
}
|
||||
|
||||
.invalid.input-regular,
|
||||
|
|
@ -829,10 +829,9 @@ body {
|
|||
|
||||
/* CONTENT COMPONENT */
|
||||
|
||||
.content-title {
|
||||
@apply text-lg font-bold mb-2 col-span-12;
|
||||
.content-text {
|
||||
@apply leading-normal text-base mb-0 lowercase;
|
||||
}
|
||||
|
||||
/* CONTENT DETAIL LSIT COMPONENT */
|
||||
|
||||
.content-detail-list-container {
|
||||
|
|
@ -851,6 +850,38 @@ body {
|
|||
@apply min-w-[2rem] break-all transition duration-300 ease-in-out pl-3 col-span-1 mb-0 font-sans text-sm font-semibold leading-normal uppercase dark:text-gray-100;
|
||||
}
|
||||
|
||||
.content-stat {
|
||||
@apply my-1 font-bold dark:text-white/90 uppercase;
|
||||
}
|
||||
|
||||
/* TITLE */
|
||||
|
||||
.title-container {
|
||||
@apply break-words max-w-[80%] font-bold mb-2 col-span-12 dark:text-white/90 transition duration-300 ease-in-out text-2xl;
|
||||
}
|
||||
|
||||
.title-card {
|
||||
@apply break-words max-w-[80%] mb-2 font-bold dark:text-white/90 transition duration-300 ease-in-out text-xl;
|
||||
}
|
||||
|
||||
.title-stat {
|
||||
@apply mb-0 font-sans text-sm font-semibold leading-normal uppercase dark:text-gray-400;
|
||||
}
|
||||
|
||||
/* SUBTITLE */
|
||||
|
||||
.subtitle-container {
|
||||
@apply leading-normal text-xl mb-0 lowercase;
|
||||
}
|
||||
|
||||
.subtitle-card {
|
||||
@apply leading-normal text-base mb-0 lowercase;
|
||||
}
|
||||
|
||||
.subtitle-stat {
|
||||
@apply font-bold leading-normal text-sm mb-0 lowercase;
|
||||
}
|
||||
|
||||
/* STAT COMPONENT */
|
||||
|
||||
.stat-content-container.no-icon {
|
||||
|
|
@ -861,18 +892,6 @@ body {
|
|||
@apply mr-12;
|
||||
}
|
||||
|
||||
.stat-title {
|
||||
@apply mb-0 font-sans text-sm font-semibold leading-normal uppercase dark:text-gray-400;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
@apply my-1 font-bold dark:text-white/90 uppercase;
|
||||
}
|
||||
|
||||
.stat-subtitle {
|
||||
@apply font-bold leading-normal text-sm mb-0 lowercase;
|
||||
}
|
||||
|
||||
.stat-svg {
|
||||
@apply leading-none text-lg relative w-6 h-6;
|
||||
}
|
||||
|
|
@ -887,14 +906,6 @@ body {
|
|||
@apply relative transition dark:brightness-110 shadow-md bg-white dark:bg-slate-850 dark:shadow-dark-xl rounded-2xl bg-clip-border transform duration-300 ease-in-out;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
@apply break-words max-w-[80%] font-bold mb-2 col-span-12 dark:text-white/90 transition duration-300 ease-in-out text-2xl;
|
||||
}
|
||||
|
||||
.card-content-title {
|
||||
@apply break-words max-w-[80%] mb-2 font-bold dark:text-white/90 transition duration-300 ease-in-out text-xl;
|
||||
}
|
||||
|
||||
/* CARD INFO */
|
||||
|
||||
.card-info-text {
|
||||
|
|
@ -1284,147 +1295,291 @@ body {
|
|||
|
||||
/* TEXT COLOR MODIFIER */
|
||||
|
||||
.success.stat-subtitle {
|
||||
.success.subtitle-stat,
|
||||
.success.subtitle-card,
|
||||
.success.title-card,
|
||||
.success.title-container,
|
||||
.success.title-stat {
|
||||
@apply text-green-500;
|
||||
}
|
||||
|
||||
.error.stat-subtitle {
|
||||
.error.subtitle-stat,
|
||||
.error.subtitle-card,
|
||||
.error.title-card,
|
||||
.error.title-container,
|
||||
.error.title-stat {
|
||||
@apply text-red-500;
|
||||
}
|
||||
|
||||
.warning.stat-subtitle {
|
||||
.warning.subtitle-stat,
|
||||
.warning.subtitle-card,
|
||||
.warning.title-card,
|
||||
.warning.title-container,
|
||||
.warning.title-stat {
|
||||
@apply text-yellow-500;
|
||||
}
|
||||
|
||||
.info.stat-subtitle {
|
||||
.info.subtitle-stat,
|
||||
.info.subtitle-card,
|
||||
.info.title-card,
|
||||
.info.title-container,
|
||||
.info.title-stat {
|
||||
@apply text-sky-500;
|
||||
}
|
||||
|
||||
.purple.stat-subtitle {
|
||||
.purple.subtitle-stat,
|
||||
.purple.subtitle-card,
|
||||
.purple.title-card,
|
||||
.purple.title-container,
|
||||
.purple.title-stat {
|
||||
@apply text-purple-500;
|
||||
}
|
||||
|
||||
.green.stat-subtitle {
|
||||
.green.subtitle-stat,
|
||||
.green.subtitle-card,
|
||||
.green.title-card,
|
||||
.green.title-container,
|
||||
.green.title-stat {
|
||||
@apply text-green-500;
|
||||
}
|
||||
|
||||
.red.stat-subtitle {
|
||||
.red.subtitle-stat,
|
||||
.red.subtitle-card,
|
||||
.red.title-card,
|
||||
.red.title-container,
|
||||
.red.title-stat {
|
||||
@apply text-red-500;
|
||||
}
|
||||
|
||||
.orange.stat-subtitle {
|
||||
.orange.subtitle-stat,
|
||||
.orange.subtitle-card,
|
||||
.orange.title-card,
|
||||
.orange.title-container,
|
||||
.orange.title-stat {
|
||||
@apply text-orange-500;
|
||||
}
|
||||
|
||||
.blue.stat-subtitle {
|
||||
.blue.subtitle-stat,
|
||||
.blue.subtitle-card,
|
||||
.blue.title-card,
|
||||
.blue.title-container,
|
||||
.blue.title-stat {
|
||||
@apply text-blue-500;
|
||||
}
|
||||
|
||||
.yellow.stat-subtitle {
|
||||
.yellow.subtitle-stat,
|
||||
.yellow.subtitle-card,
|
||||
.yellow.title-card,
|
||||
.yellow.title-container,
|
||||
.yellow.title-stat {
|
||||
@apply text-yellow-500;
|
||||
}
|
||||
|
||||
.gray.stat-subtitle {
|
||||
.gray.subtitle-stat,
|
||||
.gray.subtitle-card,
|
||||
.gray.title-card,
|
||||
.gray.title-container,
|
||||
.gray.title-stat {
|
||||
@apply text-gray-500;
|
||||
}
|
||||
|
||||
.dark.stat-subtitle {
|
||||
.dark.subtitle-stat,
|
||||
.dark.subtitle-card,
|
||||
.dark.title-card,
|
||||
.dark.title-container,
|
||||
.dark.title-stat {
|
||||
@apply text-slate-500;
|
||||
}
|
||||
|
||||
.amber.stat-subtitle {
|
||||
.amber.subtitle-stat,
|
||||
.amber.subtitle-card,
|
||||
.amber.title-card,
|
||||
.amber.title-container,
|
||||
.amber.title-stat {
|
||||
@apply text-amber-500;
|
||||
}
|
||||
|
||||
.emerald.stat-subtitle {
|
||||
.emerald.subtitle-stat,
|
||||
.emerald.subtitle-card,
|
||||
.emerald.title-card,
|
||||
.emerald.title-container,
|
||||
.emerald.title-stat {
|
||||
@apply text-emerald-500;
|
||||
}
|
||||
|
||||
.teal.stat-subtitle {
|
||||
.teal.subtitle-stat,
|
||||
.teal.subtitle-card,
|
||||
.teal.title-card,
|
||||
.teal.title-container,
|
||||
.teal.title-stat {
|
||||
@apply text-teal-500;
|
||||
}
|
||||
|
||||
.indigo.stat-subtitle {
|
||||
.indigo.subtitle-stat,
|
||||
.indigo.subtitle-card,
|
||||
.indigo.title-card,
|
||||
.indigo.title-container,
|
||||
.indigo.title-stat {
|
||||
@apply text-indigo-500;
|
||||
}
|
||||
|
||||
.cyan.stat-subtitle {
|
||||
.cyan.subtitle-stat,
|
||||
.cyan.subtitle-card,
|
||||
.cyan.title-card,
|
||||
.cyan.title-container,
|
||||
.cyan.title-stat {
|
||||
@apply text-cyan-500;
|
||||
}
|
||||
|
||||
.sky.stat-subtitle {
|
||||
.sky.subtitle-stat,
|
||||
.sky.subtitle-card,
|
||||
.sky.title-card,
|
||||
.sky.title-container,
|
||||
.sky.title-stat {
|
||||
@apply text-sky-500;
|
||||
}
|
||||
|
||||
.pink.stat-subtitle {
|
||||
.pink.subtitle-stat,
|
||||
.pink.subtitle-card,
|
||||
.pink.title-card,
|
||||
.pink.title-container,
|
||||
.pink.title-stat {
|
||||
@apply text-pink-500;
|
||||
}
|
||||
|
||||
.lime.stat-subtitle {
|
||||
.lime.subtitle-stat,
|
||||
.lime.subtitle-card,
|
||||
.lime.title-card,
|
||||
.lime.title-container,
|
||||
.lime.title-stat {
|
||||
@apply text-lime-500;
|
||||
}
|
||||
|
||||
.purple-darker.stat-subtitle {
|
||||
.purple-darker.subtitle-stat,
|
||||
.purple.subtitle-card,
|
||||
.purple.title-card,
|
||||
.purple.title-container,
|
||||
.purple.title-stat {
|
||||
@apply text-purple-600;
|
||||
}
|
||||
|
||||
.green-darker.stat-subtitle {
|
||||
.green-darker.subtitle-stat,
|
||||
.green-dark.subtitle-card,
|
||||
.green-dark.title-card,
|
||||
.green-dark.title-container,
|
||||
.green-dark.title-stat {
|
||||
@apply text-green-700;
|
||||
}
|
||||
|
||||
.red-darker.stat-subtitle {
|
||||
.red-darker.subtitle-stat,
|
||||
.red-darker.subtitle-card,
|
||||
.red-darker.title-card,
|
||||
.red-darker.title-container,
|
||||
.red-darker.title-stat {
|
||||
@apply text-red-700;
|
||||
}
|
||||
|
||||
.orange-darker.stat-subtitle {
|
||||
.orange-darker.subtitle-stat,
|
||||
.orange-darker.subtitle-card,
|
||||
.orange-darker.title-card,
|
||||
.orange-darker.title-container,
|
||||
.orange-darker.title-stat {
|
||||
@apply text-orange-600;
|
||||
}
|
||||
|
||||
.blue-darker.stat-subtitle {
|
||||
.blue-darker.subtitle-stat,
|
||||
.blue-darker.subtitle-card,
|
||||
.blue-darker.title-card,
|
||||
.blue-darker.title-container,
|
||||
.blue-darker.title-stat {
|
||||
@apply text-blue-600;
|
||||
}
|
||||
|
||||
.yellow-darker.stat-subtitle {
|
||||
.yellow-darker.subtitle-stat,
|
||||
.yellow-darker.subtitle-card,
|
||||
.yellow-darker.title-card,
|
||||
.yellow-darker.title-container,
|
||||
.yellow-darker.title-stat {
|
||||
@apply text-yellow-600;
|
||||
}
|
||||
|
||||
.gray-darker.stat-subtitle {
|
||||
.gray-darker.subtitle-stat,
|
||||
.gray-darker.subtitle-card,
|
||||
.gray-darker.title-card,
|
||||
.gray-darker.title-container,
|
||||
.gray-darker.title-stat {
|
||||
@apply text-gray-600;
|
||||
}
|
||||
|
||||
.dark-darker.stat-subtitle {
|
||||
.dark-darker.subtitle-stat,
|
||||
.dark-darker.subtitle-card,
|
||||
.dark-darker.title-card,
|
||||
.dark-darker.title-container,
|
||||
.dark-darker.title-stat {
|
||||
@apply text-slate-600;
|
||||
}
|
||||
|
||||
.amber-darker.stat-subtitle {
|
||||
.amber-darker.subtitle-stat,
|
||||
.amber-darker.subtitle-card,
|
||||
.amber-darker.title-card,
|
||||
.amber-darker.title-container,
|
||||
.amber-darker.title-stat {
|
||||
@apply text-amber-600;
|
||||
}
|
||||
|
||||
.emerald-darker.stat-subtitle {
|
||||
.emerald-darker.subtitle-stat,
|
||||
.emerald-darker.subtitle-card,
|
||||
.emerald-darker.title-card,
|
||||
.emerald-darker.title-container,
|
||||
.emerald-darker.title-stat {
|
||||
@apply text-emerald-600;
|
||||
}
|
||||
|
||||
.teal-darker.stat-subtitle {
|
||||
.teal-darker.subtitle-stat,
|
||||
.teal-darker.subtitle-card,
|
||||
.teal-darker.title-card,
|
||||
.teal-darker.title-container,
|
||||
.teal-darker.title-stat {
|
||||
@apply text-teal-600;
|
||||
}
|
||||
|
||||
.indigo-darker.stat-subtitle {
|
||||
.indigo-darker.subtitle-stat,
|
||||
.indigo-darker.subtitle-card,
|
||||
.indigo-darker.title-card,
|
||||
.indigo-darker.title-container,
|
||||
.indigo-darker.title-stat {
|
||||
@apply text-indigo-600;
|
||||
}
|
||||
|
||||
.cyan-darker.stat-subtitle {
|
||||
.cyan-darker.subtitle-stat,
|
||||
.cyan-darker.subtitle-card,
|
||||
.cyan-darker.title-card,
|
||||
.cyan-darker.title-container,
|
||||
.cyan-darker.title-stat {
|
||||
@apply text-cyan-600;
|
||||
}
|
||||
|
||||
.sky-darker.stat-subtitle {
|
||||
.sky-darker.subtitle-stat,
|
||||
.sky-darker.subtitle-card,
|
||||
.sky-darker.title-card,
|
||||
.sky-darker.title-container,
|
||||
.sky-darker.title-stat {
|
||||
@apply text-sky-700;
|
||||
}
|
||||
|
||||
.pink-darker.stat-subtitle {
|
||||
.pink-darker.subtitle-stat,
|
||||
.pink-darker.subtitle-card,
|
||||
.pink-darker.title-card,
|
||||
.pink-darker.title-container,
|
||||
.pink-darker.title-stat {
|
||||
@apply text-pink-600;
|
||||
}
|
||||
|
||||
.lime-darker.stat-subtitle {
|
||||
.lime-darker.subtitle-stat,
|
||||
.lime-darker.subtitle-card,
|
||||
.lime-darker.title-card,
|
||||
.lime-darker.title-container,
|
||||
.lime-darker.title-stat {
|
||||
@apply text-lime-600;
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -3,12 +3,9 @@ import { reactive, onBeforeMount } from "vue";
|
|||
// Containers
|
||||
import Grid from "@components/Widget/Grid.vue";
|
||||
import GridLayout from "@components/Widget/GridLayout.vue";
|
||||
// Title
|
||||
import TitleCard from "@components/Title/Card.vue";
|
||||
import TitleCardContent from "@components/Title/CardContent.vue";
|
||||
import TitleStat from "@components/Title/Stat.vue";
|
||||
// Subtitle
|
||||
import SubtitleStat from "@components/Subtitle/Stat.vue";
|
||||
// Headings
|
||||
import Title from "@components/Widget/Title.vue";
|
||||
import Subtitle from "@components/Widget/Subtitle.vue";
|
||||
// Content
|
||||
import ContentStat from "@components/Content/Stat.vue";
|
||||
import ContentDetailList from "@components/Content/DetailList.vue";
|
||||
|
|
@ -85,22 +82,14 @@ const props = defineProps({
|
|||
<Grid>
|
||||
<!-- widget element -->
|
||||
<template v-for="(widget, index) in container.widgets" :key="index">
|
||||
<TitleCard v-if="widget.type === 'TitleCard'" v-bind="widget.data" />
|
||||
<TitleCardContent
|
||||
v-if="widget.type === 'TitleCardContent'"
|
||||
v-bind="widget.data"
|
||||
/>
|
||||
<Title v-if="widget.type === 'Title'" v-bind="widget.data" />
|
||||
<Subtitle v-if="widget.type === 'Subtitle'" v-bind="widget.data" />
|
||||
<Checkbox v-if="widget.type === 'Checkbox'" v-bind="widget.data" />
|
||||
<Select v-if="widget.type === 'Select'" v-bind="widget.data" />
|
||||
<Input v-if="widget.type === 'Input'" v-bind="widget.data" />
|
||||
<Datepicker v-if="widget.type === 'Datepicker'" v-bind="widget.data" />
|
||||
<Button v-if="widget.type === 'Button'" v-bind="widget.data" />
|
||||
<Stat v-if="widget.type === 'Stat'" v-bind="widget.data" />
|
||||
<TitleStat v-if="widget.type === 'TitleStat'" v-bind="widget.data" />
|
||||
<SubtitleStat
|
||||
v-if="widget.type === 'SubtitleStat'"
|
||||
v-bind="widget.data"
|
||||
/>
|
||||
<ContentStat
|
||||
v-if="widget.type === 'ContentStat'"
|
||||
v-bind="widget.data"
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ const props = defineProps({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<h5 :class="['stat-value', props.statClass]">
|
||||
<h5 :class="['content-stat', props.statClass]">
|
||||
{{ $t(props.stat, props.stat) }}
|
||||
</h5>
|
||||
</template>
|
||||
|
|
|
|||
31
vuejs/client/src/components/Content/Text.vue
Normal file
31
vuejs/client/src/components/Content/Text.vue
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<script setup>
|
||||
/**
|
||||
@name Content/Text.vue
|
||||
@description This component is used for regular paragraph.
|
||||
@example
|
||||
{
|
||||
text: "This is a paragraph",
|
||||
textClass: "text-3xl"
|
||||
}
|
||||
@param {string} text - The text value. Can be a translation key or by default raw text.
|
||||
@param {string} [textClass=""] - Additional class if needef
|
||||
*/
|
||||
|
||||
const props = defineProps({
|
||||
text: {
|
||||
type: [String, Number],
|
||||
required: true,
|
||||
},
|
||||
textClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h5 :class="['content-text', props.textClass]">
|
||||
{{ $t(props.text, props.text) }}
|
||||
</h5>
|
||||
</template>
|
||||
|
|
@ -19,12 +19,14 @@ import ErrorField from "@components/Forms/Error/Field.vue";
|
|||
name: "checkbox",
|
||||
required: true,
|
||||
hideLabel: false,
|
||||
inpType: "checkbox",
|
||||
headerClass: "text-red-500"
|
||||
}
|
||||
@param {string} id
|
||||
@param {string} label - The label of the field. Can be a translation key or by default raw text.
|
||||
@param {string} name - The name of the field. Case no label, this is the fallback. Can be a translation key or by default raw text.
|
||||
@param {string} value
|
||||
@param {string} [inpType="checkbox"] - The type of the field, useful when we have multiple fields in the same container to display the right field
|
||||
@param {boolean} [disabled=false]
|
||||
@param {boolean} [required=false]
|
||||
@param {object} [columns={"pc": "12", "tablet": "12", "mobile": "12}] - Field has a grid system. This allow to get multiple field in the same row if needed.
|
||||
|
|
@ -50,6 +52,11 @@ const props = defineProps({
|
|||
type: String,
|
||||
required: true,
|
||||
},
|
||||
inpType: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "checkbox",
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
|
|
@ -119,7 +126,7 @@ onMounted(() => {
|
|||
|
||||
<template>
|
||||
<Container
|
||||
:containerClass="`w-full m-1 p-1 ${props.containerClass}`"
|
||||
:containerClass="`w-full p-2 md:p-3 ${props.containerClass}`"
|
||||
:columns="props.columns"
|
||||
>
|
||||
<Header
|
||||
|
|
|
|||
|
|
@ -27,10 +27,12 @@ import "@assets/css/flatpickr.dark.css";
|
|||
noPickBeforeStamp: 1735682600000,
|
||||
noPickAfterStamp: 1735689600000,
|
||||
inpClass: "text-center",
|
||||
inpType : ""
|
||||
}
|
||||
@param {string} id
|
||||
@param {string} label - The label of the field. Can be a translation key or by default raw text.
|
||||
@param {string} name - The name of the field. Case no label, this is the fallback. Can be a translation key or by default raw text.
|
||||
@param {string} [inpType="datepicker"] - The type of the field, useful when we have multiple fields in the same container to display the right field
|
||||
@param {string|number|date} [defaultDate=null] - Default date when instanciate
|
||||
@param {string|number} [noPickBeforeStamp=""] - Impossible to pick a date before this date
|
||||
@param {string|number} [noPickAfterStamp=""] - Impossible to pick a date after this date
|
||||
|
|
@ -57,6 +59,11 @@ const props = defineProps({
|
|||
type: String,
|
||||
required: false,
|
||||
},
|
||||
inpType: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "datepicker",
|
||||
},
|
||||
hideLabel: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
|
|
@ -614,7 +621,8 @@ function setIndex(calendarEl, tabindex) {
|
|||
|
||||
<template>
|
||||
<Container
|
||||
:containerClass="`w-full m-1 p-1 ${props.containerClass}`"
|
||||
v-if="props.inpType === 'datepicker'"
|
||||
:containerClass="`w-full p-2 md:p-3 ${props.containerClass}`"
|
||||
:columns="props.columns"
|
||||
>
|
||||
<Header
|
||||
|
|
|
|||
|
|
@ -22,12 +22,14 @@ import ErrorField from "@components/Forms/Error/Field.vue";
|
|||
required: true,
|
||||
label: 'Test input',
|
||||
pattern : "(test)",
|
||||
inpType: "input",
|
||||
}
|
||||
@param {string} id
|
||||
@param {string} type - text, email, password, number, tel, url
|
||||
@param {string} label - The label of the field. Can be a translation key or by default raw text.
|
||||
@param {string} name - The name of the field. Case no label, this is the fallback. Can be a translation key or by default raw text. @param {string} label
|
||||
@param {string} value
|
||||
@param {string} [inpType="input"] - The type of the field, useful when we have multiple fields in the same container to display the right field
|
||||
@param {object} [columns={"pc": "12", "tablet": "12", "mobile": "12}] - Field has a grid system. This allow to get multiple field in the same row if needed.
|
||||
@param {boolean} [disabled=false]
|
||||
@param {boolean} [required=false]
|
||||
|
|
@ -61,6 +63,11 @@ const props = defineProps({
|
|||
type: String,
|
||||
required: true,
|
||||
},
|
||||
inpType: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "input",
|
||||
},
|
||||
required: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
|
|
@ -167,7 +174,7 @@ onMounted(() => {
|
|||
|
||||
<template>
|
||||
<Container
|
||||
:containerClass="`w-full m-1 p-1 ${props.containerClass}`"
|
||||
:containerClass="`w-full p-2 md:p-3 ${props.containerClass}`"
|
||||
:columns="props.columns"
|
||||
>
|
||||
<Header
|
||||
|
|
|
|||
|
|
@ -21,12 +21,14 @@ import ErrorField from "@components/Forms/Error/Field.vue";
|
|||
required: true,
|
||||
requiredValues : ['no'], // need required to be checked
|
||||
label: 'Test select',
|
||||
inpType: "select",
|
||||
}
|
||||
@param {string} id
|
||||
@param {string} label - The label of the field. Can be a translation key or by default raw text.
|
||||
@param {string} name - The name of the field. Case no label, this is the fallback. Can be a translation key or by default raw text.
|
||||
@param {string} value
|
||||
@param {array} values
|
||||
@param {string} [inpType="select"] - The type of the field, useful when we have multiple fields in the same container to display the right field
|
||||
@param {boolean} [disabled=false]
|
||||
@param {boolean} [required=false]
|
||||
@param {array} [requiredValues=[]] - values that need to be selected to be valid, works only if required is true
|
||||
|
|
@ -57,6 +59,11 @@ const props = defineProps({
|
|||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
inpType: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "select",
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
|
|
@ -197,7 +204,7 @@ const emits = defineEmits(["inp"]);
|
|||
|
||||
<template>
|
||||
<Container
|
||||
:containerClass="`w-full m-1 p-1 ${props.containerClass}`"
|
||||
:containerClass="`w-full p-2 md:p-3 ${props.containerClass}`"
|
||||
:columns="props.columns"
|
||||
>
|
||||
<Header
|
||||
|
|
|
|||
92
vuejs/client/src/components/Forms/Type/Advanced.vue
Normal file
92
vuejs/client/src/components/Forms/Type/Advanced.vue
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
<script setup>
|
||||
import { reactive, defineProps, onMounted, ref } from "vue";
|
||||
import Container from "@components/Widget/Container.vue";
|
||||
import Checkbox from "@components/Forms/Field/Checkbox.vue";
|
||||
import Input from "@components/Forms/Field/Input.vue";
|
||||
import Select from "@components/Forms/Field/Select.vue";
|
||||
import Datepicker from "@components/Forms/Field/Datepicker.vue";
|
||||
import Title from "@components/Widget/Title.vue";
|
||||
import Subtitle from "@components/Widget/Subtitle.vue";
|
||||
|
||||
/**
|
||||
@name Forms/Type/Advanced.vue
|
||||
@description This component is used to create a complete advanced form with plugin selection.
|
||||
@example
|
||||
const data = [
|
||||
{
|
||||
name: "plugin name",
|
||||
type: "pro",
|
||||
is_activate: true,
|
||||
description: "plugin description",
|
||||
page: "/page",
|
||||
settings: [
|
||||
{
|
||||
columns: { pc: 6, tablet: 12, mobile: 12 },
|
||||
id: "test-check",
|
||||
value: "yes",
|
||||
label: "Checkbox",
|
||||
name: "checkbox",
|
||||
required: true,
|
||||
hideLabel: false,
|
||||
headerClass: "text-red-500",
|
||||
inpType: "checkbox",
|
||||
},
|
||||
{
|
||||
id: "test-input",
|
||||
value: "yes",
|
||||
type: "text",
|
||||
name: "test-input",
|
||||
disabled: false,
|
||||
required: true,
|
||||
label: "Test input",
|
||||
pattern: "(test)",
|
||||
inpType: "input",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@param {array} settings - List of settings that must fit Field components format.
|
||||
@param {boolean} [isActive=true] - Check if the form is active, it will display the form if true
|
||||
*/
|
||||
|
||||
const props = defineProps({
|
||||
// id && value && method
|
||||
plugins: {
|
||||
type: Array,
|
||||
required: true,
|
||||
default: [],
|
||||
},
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Container
|
||||
v-if="props.isActive"
|
||||
:tag="'form'"
|
||||
method="POST"
|
||||
:containerClass="`col-span-12 w-full m-1 p-1`"
|
||||
:columns="props.columns"
|
||||
>
|
||||
<Container class="col-span-12 w-full" v-for="plugin in plugins">
|
||||
<Title type="card" :title="plugin.name" />
|
||||
<Subtitle type="card" :subtitle="plugin.description" />
|
||||
|
||||
<Container class="grid grid-cols-12 w-full">
|
||||
<template v-for="(setting, index) in plugin.settings" :key="index">
|
||||
<Checkbox v-if="setting.inpType === 'checkbox'" v-bind="setting" />
|
||||
<Select v-if="setting.inpType === 'select'" v-bind="setting" />
|
||||
<Datepicker
|
||||
v-if="setting.inpType === 'datepicker'"
|
||||
v-bind="setting"
|
||||
/>
|
||||
<Input v-if="setting.inpType === 'input'" v-bind="setting" />
|
||||
</template>
|
||||
</Container>
|
||||
</Container>
|
||||
</Container>
|
||||
</template>
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
<script setup>
|
||||
/**
|
||||
@name Stat/Subtitle.vue
|
||||
@description This component is a subtitle used with stats.
|
||||
This can be used alone in case we don't need a complete stat widget.
|
||||
In case you have a title, subtitle, stat and icon to display, you can directly use Stat widget.
|
||||
@example
|
||||
{
|
||||
subtitle: "Last 30 days",
|
||||
subtitleColor: "info",
|
||||
subtitleClass: "text-sm"
|
||||
}
|
||||
@param {string} subtitle - The subtitle of the stat. Can be a translation key or by default raw text.
|
||||
@param {string} [subtitleColor="info"] - The color of the subtitle between error, success, warning, info
|
||||
@param {string} [subtitleClass=""] - Additional class, useful when component is used directly on a grid system
|
||||
*/
|
||||
|
||||
const props = defineProps({
|
||||
subtitle: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
subtitleColor: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "info",
|
||||
},
|
||||
subtitleClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<p
|
||||
v-if="props.subtitle"
|
||||
:class="['stat-subtitle', props.subtitleColor, props.subtitleClass]"
|
||||
>
|
||||
{{ $t(props.subtitle, props.subtitle) }}
|
||||
</p>
|
||||
</template>
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
<script setup>
|
||||
/**
|
||||
@name Title/Card.vue
|
||||
@description This component is a used as card title.
|
||||
This can be used outside of the card container.
|
||||
@example
|
||||
{
|
||||
title: "Total Users",
|
||||
titleClass: "text-lg"
|
||||
}
|
||||
@param {string} title - Can be a translation key or by default raw text.
|
||||
@param {string} [titleClass=""] - Additional class, useful when component is used directly on a grid system
|
||||
*/
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
titleClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1 v-if="props.title" :class="[props.titleClass, 'card-title']">
|
||||
{{ $t(props.title, props.title) }}
|
||||
</h1>
|
||||
</template>
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
<script setup>
|
||||
/**
|
||||
@name Title/CardContent.vue
|
||||
@description This component is similar to TitleCard but with a lower size.
|
||||
This can be used outside of the card container.
|
||||
@example
|
||||
{
|
||||
title: "Total Users",
|
||||
titleClass: "text-lg"
|
||||
}
|
||||
@param {string} title - Can be a translation key or by default raw text.
|
||||
@param {string} [titleClass=""] - Additional class, useful when component is used directly on a grid system
|
||||
*/
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
titleClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h2 v-if="props.title" :class="[props.titleClass, 'card-content-title']">
|
||||
{{ $t(props.title, props.title) }}
|
||||
</h2>
|
||||
</template>
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
<script setup>
|
||||
/**
|
||||
@name Title/Stat.vue
|
||||
@description This component is a title used with stats.
|
||||
This can be used alone in case we don't need a complete stat widget.
|
||||
In case you have a title, subtitle, stat and icon to display, you can directly use Stat widget.
|
||||
@example
|
||||
{
|
||||
title: "Total Users",
|
||||
titleClass: "text-lg"
|
||||
}
|
||||
@param {string} title - The title of the stat. Can be a translation key or by default raw text.
|
||||
@param {string} [titleClass=""] - Additional class, useful when component is used directly on a grid system
|
||||
*/
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
titleClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<p :class="['stat-title', props.titleClass]">
|
||||
{{ $t(props.title, props.title) }}
|
||||
</p>
|
||||
</template>
|
||||
|
|
@ -14,6 +14,7 @@ import { computed } from "vue";
|
|||
}
|
||||
@param {string} [containerClass=""] - Additional class
|
||||
@param {object|boolean} [columns=false] - Work with grid system { pc: 12, tablet: 12, mobile: 12}
|
||||
@param {string} [tag="div"] - The tag for the container
|
||||
*/
|
||||
|
||||
const props = defineProps({
|
||||
|
|
@ -27,6 +28,11 @@ const props = defineProps({
|
|||
required: false,
|
||||
default: false,
|
||||
},
|
||||
tag: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "div",
|
||||
},
|
||||
});
|
||||
|
||||
const gridClass = computed(() => {
|
||||
|
|
@ -37,10 +43,11 @@ const gridClass = computed(() => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
<component
|
||||
:is="props.tag"
|
||||
data-container
|
||||
:class="[props.containerClass ? props.containerClass : '', gridClass]"
|
||||
>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</component>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script setup>
|
||||
import { defineProps } from "vue";
|
||||
import Container from "@components/Widget/Container.vue";
|
||||
import TitleCardContent from "@components/Title/CardContent.vue";
|
||||
import Title from "@components/Widget/Title.vue";
|
||||
import IconStatus from "@components/Icon/Status.vue";
|
||||
import ContentDetailList from "@components/Content/DetailList.vue";
|
||||
import ButtonGroup from "@components/Widget/ButtonGroup.vue";
|
||||
|
|
@ -9,7 +9,7 @@ import { v4 as uuidv4 } from "uuid";
|
|||
/**
|
||||
@name Widget/Instance.vue
|
||||
@description This component is an instance widget.
|
||||
This component is using the Container, TitleCardContent, IconStatus, ContentDetailList and ButtonGroup components.
|
||||
This component is using the Container, TitleCard, IconStatus, ContentDetailList and ButtonGroup components.
|
||||
@example
|
||||
{
|
||||
id: "instance-1",
|
||||
|
|
@ -72,7 +72,7 @@ const props = defineProps({
|
|||
<template>
|
||||
<Container :columns="{ pc: 12, tablet: 12, mobile: 12 }">
|
||||
<IconStatus :id="props.title" :status="props.status" />
|
||||
<TitleCardContent :title="props.title" />
|
||||
<Title type="card" :title="props.title" />
|
||||
<ContentDetailList :details="props.details" />
|
||||
<ButtonGroup
|
||||
:id="props.id"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<script setup>
|
||||
import Container from "@components/Widget/Container.vue";
|
||||
import TitleStat from "@components/Title/Stat.vue";
|
||||
import Title from "@components/Widget/Title.vue";
|
||||
import Subtitle from "@components/Widget/Subtitle.vue";
|
||||
import ContentStat from "@components/Content/Stat.vue";
|
||||
import SubtitleStat from "@components/Subtitle/Stat.vue";
|
||||
import IconStat from "@components/Icon/Stat.vue";
|
||||
|
||||
/**
|
||||
|
|
@ -74,9 +74,10 @@ const props = defineProps({
|
|||
props.iconName ? 'is-icon' : 'no-icon',
|
||||
]"
|
||||
>
|
||||
<TitleStat :title="props.title" />
|
||||
<Title type="stat" :title="props.title" />
|
||||
<ContentStat :stat="props.stat" />
|
||||
<SubtitleStat
|
||||
<Subtitle
|
||||
type="stat"
|
||||
v-if="props.subtitle"
|
||||
:subtitle="props.subtitle"
|
||||
:subtitleColor="props.subtitleColor"
|
||||
|
|
|
|||
71
vuejs/client/src/components/Widget/Subtitle.vue
Normal file
71
vuejs/client/src/components/Widget/Subtitle.vue
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
<script setup>
|
||||
import { computed } from "vue";
|
||||
/**
|
||||
@name Widget/Subtitle.vue
|
||||
@description This component is a general subtitle wrapper.
|
||||
@example
|
||||
{
|
||||
subtitle: "Total Users",
|
||||
type: "card",
|
||||
subtitleClass: "text-lg",
|
||||
subtitleColor : "info",
|
||||
tag: "h2"
|
||||
}
|
||||
@param {string} subtitle - Can be a translation key or by default raw text.
|
||||
@param {string} type - The type of subtitle between "card", "container" or "stat"
|
||||
@param {string} [tag=""] - The tag of the subtitle. Can be h1, h2, h3, h4, h5, h6 or p. If empty, will be determine by the type of subtitle.
|
||||
@param {string} [subtitleColor=""] - The color of the subtitle between error, success, warning, info or tailwind color
|
||||
@param {string} [subtitleClass=""] - Additional class, useful when component is used directly on a grid system
|
||||
*/
|
||||
|
||||
const props = defineProps({
|
||||
subtitle: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "card",
|
||||
},
|
||||
tag: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
subtitleColor: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
subtitleClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
});
|
||||
|
||||
const tag = computed(() => {
|
||||
if (props.tag) return props.tag;
|
||||
if (props.type === "container") return "p";
|
||||
if (props.type === "card") return "p";
|
||||
if (props.type === "stat") return "p";
|
||||
});
|
||||
|
||||
const baseClass = computed(() => {
|
||||
if (props.type === "container") return "subtitle-container";
|
||||
if (props.type === "card") return "subtitle-card";
|
||||
if (props.type === "stat") return "subtitle-stat";
|
||||
return "subtitle-card";
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component
|
||||
:is="tag"
|
||||
v-if="props.subtitle"
|
||||
:class="[props.subtitleClass, props.subtitleColor, baseClass]"
|
||||
>
|
||||
{{ $t(props.subtitle, props.subtitle) }}
|
||||
</component>
|
||||
</template>
|
||||
71
vuejs/client/src/components/Widget/Title.vue
Normal file
71
vuejs/client/src/components/Widget/Title.vue
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
<script setup>
|
||||
import { computed } from "vue";
|
||||
/**
|
||||
@name Widget/Title.vue
|
||||
@description This component is a general title wrapper.
|
||||
@example
|
||||
{
|
||||
title: "Total Users",
|
||||
type: "card",
|
||||
titleClass: "text-lg",
|
||||
titleColor : "info",
|
||||
tag: "h2"
|
||||
}
|
||||
@param {string} title - Can be a translation key or by default raw text.
|
||||
@param {string} type - The type of title between "card", "container" or "stat"
|
||||
@param {string} [tag=""] - The tag of the title. Can be h1, h2, h3, h4, h5, h6 or p. If empty, will be determine by the type of title.
|
||||
@param {string} [titleColor=""] - The color of the title between error, success, warning, info or tailwind color
|
||||
@param {string} [titleClass=""] - Additional class, useful when component is used directly on a grid system
|
||||
*/
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "card",
|
||||
},
|
||||
tag: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
titleColor: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
titleClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
});
|
||||
|
||||
const tag = computed(() => {
|
||||
if (props.tag) return props.tag;
|
||||
if (props.type === "container") return "h1";
|
||||
if (props.type === "card") return "h2";
|
||||
if (props.type === "stat") return "p";
|
||||
});
|
||||
|
||||
const baseClass = computed(() => {
|
||||
if (props.type === "container") return "title-container";
|
||||
if (props.type === "card") return "title-card";
|
||||
if (props.type === "stat") return "title-stat";
|
||||
return "title-card";
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component
|
||||
:is="tag"
|
||||
v-if="props.title"
|
||||
:class="[props.titleClass, props.titleColor, baseClass]"
|
||||
>
|
||||
{{ $t(props.title, props.title) }}
|
||||
</component>
|
||||
</template>
|
||||
|
|
@ -80,6 +80,9 @@
|
|||
"dashboard_status_error": "status inactive or error.",
|
||||
"dashboard_status_warning": "status warning or alert.",
|
||||
"dashboard_status_info": "status loading or waiting or unknown.",
|
||||
"inp_input_valid": "input valid",
|
||||
"inp_input_error_required": "input is required",
|
||||
"inp_input_error": "input is invalid",
|
||||
"action_send": "send {name}",
|
||||
"action_start": "start {name}",
|
||||
"action_disable": "disable {name}",
|
||||
|
|
|
|||
11
vuejs/client/src/pages/global-config/globalConfig.js
Normal file
11
vuejs/client/src/pages/global-config/globalConfig.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { createApp } from "vue";
|
||||
import { createPinia } from "pinia";
|
||||
import { getI18n } from "@utils/lang.js";
|
||||
import GlobalConfig from "./GlobalConfig.vue";
|
||||
|
||||
const pinia = createPinia();
|
||||
|
||||
createApp(GlobalConfig)
|
||||
.use(pinia)
|
||||
.use(getI18n(["dashboard", "action", "inp", "global_config"]))
|
||||
.mount("#app");
|
||||
109
vuejs/client/src/pages/global-config/globalConfig.vue
Normal file
109
vuejs/client/src/pages/global-config/globalConfig.vue
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
<script setup>
|
||||
import { reactive, onBeforeMount, onMounted } from "vue";
|
||||
import DashboardLayout from "@components/Dashboard/Layout.vue";
|
||||
import Builder from "@components/Builder.vue";
|
||||
import Advanced from "@components/Forms/Type/Advanced.vue";
|
||||
import { useGlobal } from "@utils/global.js";
|
||||
import { useForm } from "@utils/form.js";
|
||||
|
||||
/**
|
||||
@name Page/GlobalConfig.vue
|
||||
@description This component is the gllobal config page.
|
||||
This page displays an overview of multiple stats related to BunkerWeb.
|
||||
*/
|
||||
|
||||
const globalConfig = reactive({
|
||||
builder: "",
|
||||
});
|
||||
|
||||
onBeforeMount(() => {
|
||||
// Get builder data
|
||||
const dataAtt = "data-server-builder";
|
||||
const dataEl = document.querySelector(`[${dataAtt}]`);
|
||||
const data =
|
||||
dataEl && !dataEl.getAttribute(dataAtt).includes(dataAtt)
|
||||
? JSON.parse(dataEl.getAttribute(dataAtt))
|
||||
: {};
|
||||
globalConfig.builder = data;
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
useGlobal();
|
||||
useForm();
|
||||
});
|
||||
|
||||
// const data = [
|
||||
// {
|
||||
// type: "Instance",
|
||||
// data: {
|
||||
// details: [
|
||||
// { key: <instances_hostname="hostname">, value: "www.example.com" },
|
||||
// { key: <instances_method="method">, value: <dashboard_ui> or <dashboard_scheduler>...},
|
||||
// { key: <instances_port="port">, value: "1084" },
|
||||
// { key: <instances_status="status">, value: <instances_active="active"> or <instances_inactive="inactive"> },
|
||||
// ],
|
||||
// status: "success",
|
||||
// title: "www.example.com",
|
||||
// buttons: [
|
||||
// {
|
||||
// text: <action_*>,
|
||||
// color: "edit",
|
||||
// size: "normal",
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
// ];
|
||||
|
||||
const data = [
|
||||
{
|
||||
name: "plugin name",
|
||||
type: "pro",
|
||||
is_activate: true,
|
||||
description: "plugin description",
|
||||
page: "/page",
|
||||
settings: [
|
||||
{
|
||||
columns: { pc: 4, tablet: 6, mobile: 12 },
|
||||
id: "test-check",
|
||||
value: "yes",
|
||||
label: "Checkbox",
|
||||
name: "checkbox",
|
||||
required: true,
|
||||
hideLabel: false,
|
||||
inpType: "checkbox",
|
||||
},
|
||||
{
|
||||
columns: { pc: 4, tablet: 6, mobile: 12 },
|
||||
id: "test-input",
|
||||
value: "yes",
|
||||
type: "text",
|
||||
name: "test-input",
|
||||
disabled: false,
|
||||
required: true,
|
||||
label: "Test input",
|
||||
pattern: "(test)",
|
||||
inpType: "input",
|
||||
},
|
||||
{
|
||||
columns: { pc: 4, tablet: 6, mobile: 12 },
|
||||
id: "test-select",
|
||||
value: "yes",
|
||||
values: ["yes", "no"],
|
||||
name: "test-select",
|
||||
disabled: false,
|
||||
required: true,
|
||||
requiredValues: ["no"], // need required to be checked
|
||||
label: "Test select",
|
||||
inpType: "select",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DashboardLayout>
|
||||
<Advanced :plugins="data" />
|
||||
</DashboardLayout>
|
||||
</template>
|
||||
22
vuejs/client/src/pages/global-config/index.html
Normal file
22
vuejs/client/src/pages/global-config/index.html
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/x-icon" href="/images/favicon.ico" />
|
||||
<link rel="stylesheet" href="/css/style.css" />
|
||||
<link rel="stylesheet" href="/css/flag-icons.min.css" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>BunkerWeb | DASHBOARD</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="hidden" data-server-global='{"username" : "admin"}'></div>
|
||||
<div class="hidden"
|
||||
data-server-flash='[{"type" : "success", "title" : "title", "message" : "Success feedback"}, {"type" : "error", "title" : "title", "message" : "Error feedback"}, {"type" : "warning", "title" : "title", "message" : "Warning feedback"}, {"type" : "info", "title" : "title", "message" : "Info feedback"}]'>
|
||||
</div>
|
||||
<div class="hidden"
|
||||
data-server-builder='[{"type":"card","containerColumns":{"pc":6,"tablet":6,"mobile":12},"widgets":[{"type":"Instance","data":{"details":[{"key":"instances_hostname","value":"bunkerweb"},{"key":"instances_type","value":"manual"},{"key":"instances_status","value":"instances_active"}],"status":"success","title":"bunkerweb","buttons":[{"attrs":{"data-form-INSTANCE_ID":"bunkerweb","data-form-operation":"reload","data-submit-form":"true"},"text":"action_reload","color":"warning","size":"normal"},{"attrs":{"data-form-INSTANCE_ID":"bunkerweb","data-form-operation":"stop","data-submit-form":"true"},"text":"action_stop","color":"error","size":"normal"}]}}]}]'>
|
||||
</div>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="globalConfig.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -7,5 +7,5 @@ const pinia = createPinia();
|
|||
|
||||
createApp(Home)
|
||||
.use(pinia)
|
||||
.use(getI18n(["dashboard", "action", "home"]))
|
||||
.use(getI18n(["dashboard", "action", "inp", "home"]))
|
||||
.mount("#app");
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ import { useGlobal } from "@utils/global.js";
|
|||
import { useForm } from "@utils/form.js";
|
||||
|
||||
/**
|
||||
@name Page/Home.vue
|
||||
@description This component is the home page.
|
||||
This page displays an overview of multiple stats related to BunkerWeb.
|
||||
@name Page/Instances.vue
|
||||
@description This component is the instances page.
|
||||
This page displays current instances and allows to manage them.
|
||||
*/
|
||||
|
||||
const home = reactive({
|
||||
|
|
|
|||
|
|
@ -31,6 +31,10 @@ export default defineConfig({
|
|||
test: resolve(__dirname, "./src/pages/test/index.html"),
|
||||
home: resolve(__dirname, "./src/pages/home/index.html"),
|
||||
instances: resolve(__dirname, "./src/pages/instances/index.html"),
|
||||
"global-config": resolve(
|
||||
__dirname,
|
||||
"./src/pages/global-config/index.html"
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in a new issue