mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
add custom pages builder
This commit is contained in:
parent
8ab947af11
commit
195f292599
9 changed files with 203 additions and 29 deletions
|
|
@ -1,5 +1,4 @@
|
|||
<script setup>
|
||||
import { reactive, onBeforeMount } from "vue";
|
||||
// Containers
|
||||
import Grid from "@components/Widget/Grid.vue";
|
||||
import GridLayout from "@components/Widget/GridLayout.vue";
|
||||
|
|
@ -10,7 +9,7 @@ import Subtitle from "@components/Widget/Subtitle.vue";
|
|||
import ContentStat from "@components/Content/Stat.vue";
|
||||
import ContentDetailList from "@components/Content/DetailList.vue";
|
||||
// Icon
|
||||
import IconStatus from "@components/Widget/Status.vue";
|
||||
import Icons from "@components/Widget/Icons.vue";
|
||||
// Form
|
||||
import Checkbox from "@components/Forms/Field/Checkbox.vue";
|
||||
import Select from "@components/Forms/Field/Select.vue";
|
||||
|
|
@ -23,8 +22,8 @@ import Stat from "@components/Widget/Stat.vue";
|
|||
import Instance from "@components/Widget/Instance.vue";
|
||||
|
||||
/**
|
||||
@name Builder.vue
|
||||
@description This component is a wrapper to create a complete page using containers and widgets.
|
||||
@name Builder/Collection.vue
|
||||
@description This component is a builder containing all collection of widgets / containers / components to create a complete page.
|
||||
We have to define each container and each widget inside it.
|
||||
This is an abstract component that will be used to create any kind of page content (base dashboard elements like menu and news excluded)
|
||||
@example
|
||||
|
|
@ -93,9 +92,8 @@ const props = defineProps({
|
|||
v-if="widget.type === 'ContentStat'"
|
||||
v-bind="widget.data"
|
||||
/>
|
||||
<IconStat v-if="widget.type === 'IconStat'" v-bind="widget.data" />
|
||||
<Icons v-if="widget.type === 'Icons'" v-bind="widget.data" />
|
||||
<Instance v-if="widget.type === 'Instance'" v-bind="widget.data" />
|
||||
<IconStatus v-if="widget.type === 'IconStatus'" v-bind="widget.data" />
|
||||
<ContentDetailList
|
||||
v-if="widget.type === 'ContentDetailList'"
|
||||
v-bind="widget.data"
|
||||
61
vuejs/client/src/components/Builder/Home.vue
Normal file
61
vuejs/client/src/components/Builder/Home.vue
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<script setup>
|
||||
// Containers
|
||||
import Grid from "@components/Widget/Grid.vue";
|
||||
import GridLayout from "@components/Widget/GridLayout.vue";
|
||||
import Stat from "@components/Widget/Stat.vue";
|
||||
|
||||
/**
|
||||
@name Builder/Home.vue
|
||||
@description This component is lightweight builder containing only the necessary components to create the home page.
|
||||
@example
|
||||
[
|
||||
{
|
||||
type: "card",
|
||||
link : "https://panel.bunkerweb.io/?utm_campaign=self&utm_source=ui"
|
||||
containerColumns: { pc: 4, tablet: 6, mobile: 12 },
|
||||
widgets: [
|
||||
{
|
||||
type: "Stat",
|
||||
data: {
|
||||
title: "home_version",
|
||||
subtitle: "home_all_features_available" if is_pro_version else "home_upgrade_pro",
|
||||
subtitleColor: "success" is is_pro_version else "warning",
|
||||
stat: "home_pro" if is_pro_version else "home_free",
|
||||
iconName: "crown" if is_pro_version else "core",
|
||||
iconColor: "amber",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
@param {array} builder - Array of containers and widgets
|
||||
*/
|
||||
|
||||
const props = defineProps({
|
||||
builder: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- top level grid (layout) -->
|
||||
<GridLayout
|
||||
v-for="(container, index) in props.builder"
|
||||
:key="index"
|
||||
:gridLayoutClass="container.containerClass"
|
||||
:type="container.type"
|
||||
:title="container.title"
|
||||
:link="container.link"
|
||||
:columns="container.containerColumns"
|
||||
>
|
||||
<!-- widget grid -->
|
||||
<Grid>
|
||||
<!-- widget element -->
|
||||
<template v-for="(widget, index) in container.widgets" :key="index">
|
||||
<Stat v-if="widget.type === 'Stat'" v-bind="widget.data" />
|
||||
</template>
|
||||
</Grid>
|
||||
</GridLayout>
|
||||
</template>
|
||||
63
vuejs/client/src/components/Builder/Instances.vue
Normal file
63
vuejs/client/src/components/Builder/Instances.vue
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
<script setup>
|
||||
// Containers
|
||||
import Grid from "@components/Widget/Grid.vue";
|
||||
import GridLayout from "@components/Widget/GridLayout.vue";
|
||||
import Instance from "@components/Widget/Instance.vue";
|
||||
|
||||
/**
|
||||
@name Builder/Instances.vue
|
||||
@description This component is lightweight builder containing only the necessary components to create the instances page.
|
||||
@example
|
||||
[
|
||||
{
|
||||
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",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
@param {array} builder - Array of containers and widgets
|
||||
*/
|
||||
|
||||
const props = defineProps({
|
||||
builder: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- top level grid (layout) -->
|
||||
<GridLayout
|
||||
v-for="(container, index) in props.builder"
|
||||
:key="index"
|
||||
:gridLayoutClass="container.containerClass"
|
||||
:type="container.type"
|
||||
:title="container.title"
|
||||
:link="container.link"
|
||||
:columns="container.containerColumns"
|
||||
>
|
||||
<!-- widget grid -->
|
||||
<Grid>
|
||||
<!-- widget element -->
|
||||
<template v-for="(widget, index) in container.widgets" :key="index">
|
||||
<Instance v-if="widget.type === 'Instance'" v-bind="widget.data" />
|
||||
</template>
|
||||
</Grid>
|
||||
</GridLayout>
|
||||
</template>
|
||||
|
|
@ -1,15 +1,12 @@
|
|||
<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 Fields from "@components/Form/Fields.vue";
|
||||
import Title from "@components/Widget/Title.vue";
|
||||
import Subtitle from "@components/Widget/Subtitle.vue";
|
||||
|
||||
/**
|
||||
@name Forms/Type/Advanced.vue
|
||||
@name Form/Advanced.vue
|
||||
@description This component is used to create a complete advanced form with plugin selection.
|
||||
@example
|
||||
const data = [
|
||||
|
|
@ -85,13 +82,7 @@ const props = defineProps({
|
|||
v-for="(setting, name, 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" />
|
||||
<Fields :setting="setting" />
|
||||
</template>
|
||||
</Container>
|
||||
</Container>
|
||||
54
vuejs/client/src/components/Form/Fields.vue
Normal file
54
vuejs/client/src/components/Form/Fields.vue
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
<script setup>
|
||||
import { reactive, defineProps, onMounted, ref } from "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";
|
||||
|
||||
/**
|
||||
@name Form/Fields.vue
|
||||
@description This component wraps all available fields for a form.
|
||||
@example
|
||||
{
|
||||
columns : {"pc": 6, "tablet": 12, "mobile": 12},
|
||||
id:"test-check",
|
||||
value: "yes",
|
||||
label: "Checkbox",
|
||||
name: "checkbox",
|
||||
required: true,
|
||||
hideLabel: false,
|
||||
inpType: "checkbox",
|
||||
headerClass: "text-red-500"
|
||||
popovers : [
|
||||
{
|
||||
text: "This is a popover text",
|
||||
iconName: "info",
|
||||
iconColor: "info",
|
||||
},
|
||||
]
|
||||
}
|
||||
@param {object} setting - Setting needed to render a field.
|
||||
*/
|
||||
|
||||
const props = defineProps({
|
||||
// id && value && method
|
||||
setting: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: {},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Checkbox
|
||||
v-if="props.setting.inpType === 'checkbox'"
|
||||
v-bind="props.setting"
|
||||
/>
|
||||
<Select v-if="props.setting.inpType === 'select'" v-bind="props.setting" />
|
||||
<Datepicker
|
||||
v-if="props.setting.inpType === 'datepicker'"
|
||||
v-bind="props.setting"
|
||||
/>
|
||||
<Input v-if="props.setting.inpType === 'input'" v-bind="props.setting" />
|
||||
</template>
|
||||
|
|
@ -3,7 +3,7 @@ import Container from "@components/Widget/Container.vue";
|
|||
import Title from "@components/Widget/Title.vue";
|
||||
import Subtitle from "@components/Widget/Subtitle.vue";
|
||||
import ContentStat from "@components/Content/Stat.vue";
|
||||
import Icon from "@components/Widget/Icons.vue";
|
||||
import Icons from "@components/Widget/Icons.vue";
|
||||
|
||||
/**
|
||||
@name Widget/Stat.vue
|
||||
|
|
@ -83,7 +83,7 @@ const props = defineProps({
|
|||
:subtitleColor="props.subtitleColor"
|
||||
/>
|
||||
</div>
|
||||
<Icon
|
||||
<Icons
|
||||
v-if="props.iconName"
|
||||
:iconName="props.iconName"
|
||||
:iconColor="props.iconColor"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<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 Builder from "@components/Builder/Collection.vue";
|
||||
import Advanced from "@components/Form/Advanced.vue";
|
||||
import { useGlobal } from "@utils/global.js";
|
||||
import { useForm } from "@utils/form.js";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
<script setup>
|
||||
import { reactive, onBeforeMount } from "vue";
|
||||
import { reactive, onBeforeMount, onMounted } from "vue";
|
||||
import DashboardLayout from "@components/Dashboard/Layout.vue";
|
||||
import Builder from "@components/Builder.vue";
|
||||
import BuilderHome from "@components/Builder/Home.vue";
|
||||
import { useGlobal } from "@utils/global.js";
|
||||
import { useForm } from "@utils/form.js";
|
||||
|
||||
/**
|
||||
@name Page/Home.vue
|
||||
|
|
@ -24,6 +26,11 @@ onBeforeMount(() => {
|
|||
home.builder = data;
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
useGlobal();
|
||||
useForm();
|
||||
});
|
||||
|
||||
// const data = [
|
||||
// {
|
||||
// type: "card",
|
||||
|
|
@ -120,6 +127,6 @@ onBeforeMount(() => {
|
|||
|
||||
<template>
|
||||
<DashboardLayout>
|
||||
<Builder v-if="home.builder" :builder="home.builder" />
|
||||
<BuilderHome v-if="home.builder" :builder="home.builder" />
|
||||
</DashboardLayout>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script setup>
|
||||
import { reactive, onBeforeMount, onMounted } from "vue";
|
||||
import DashboardLayout from "@components/Dashboard/Layout.vue";
|
||||
import Builder from "@components/Builder.vue";
|
||||
import BuilderInstances from "@components/Builder/Instances.vue";
|
||||
import { useGlobal } from "@utils/global.js";
|
||||
import { useForm } from "@utils/form.js";
|
||||
|
||||
|
|
@ -11,7 +11,7 @@ import { useForm } from "@utils/form.js";
|
|||
This page displays current instances and allows to manage them.
|
||||
*/
|
||||
|
||||
const home = reactive({
|
||||
const instances = reactive({
|
||||
builder: "",
|
||||
});
|
||||
|
||||
|
|
@ -23,7 +23,7 @@ onBeforeMount(() => {
|
|||
dataEl && !dataEl.getAttribute(dataAtt).includes(dataAtt)
|
||||
? JSON.parse(dataEl.getAttribute(dataAtt))
|
||||
: {};
|
||||
home.builder = data;
|
||||
instances.builder = data;
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
|
|
@ -57,7 +57,7 @@ onMounted(() => {
|
|||
|
||||
<template>
|
||||
<DashboardLayout>
|
||||
<Builder v-if="home.builder" :builder="home.builder" />
|
||||
<BuilderInstances v-if="instances.builder" :builder="instances.builder" />
|
||||
<div id="test-el"></div>
|
||||
</DashboardLayout>
|
||||
</template>
|
||||
|
|
|
|||
Loading…
Reference in a new issue