mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
start table component
This commit is contained in:
parent
1b078263b7
commit
e61e40b245
5 changed files with 241 additions and 102 deletions
|
|
@ -1275,34 +1275,61 @@ body {
|
|||
@apply fill-gray-700 stroke-gray-600;
|
||||
}
|
||||
|
||||
/* LIST */
|
||||
.list-container {
|
||||
/* TABLE */
|
||||
|
||||
.table-container {
|
||||
@apply col-span-12 overflow-x-auto overflow-y-hidden;
|
||||
}
|
||||
|
||||
.table-container-wrap {
|
||||
@apply col-span-12 overflow-x-auto grid grid-cols-12;
|
||||
}
|
||||
|
||||
.table {
|
||||
@apply w-full grid grid-cols-12 block;
|
||||
}
|
||||
|
||||
.list-content-container {
|
||||
@apply dark:text-gray-400 block w-full rounded col-span-12 overflow-x-hidden overflow-y-auto max-h-[300px];
|
||||
.sm.table {
|
||||
@apply min-w-[600px];
|
||||
}
|
||||
|
||||
.list-content-item {
|
||||
@apply text-sm col-span-12 block border-b hover:bg-gray-100 dark:hover:bg-slate-700 items-center grid grid-cols-12 border-gray-300 py-2.5 px-1;
|
||||
.md.table {
|
||||
@apply min-w-[800px];
|
||||
}
|
||||
|
||||
.list-content {
|
||||
@apply border-b hover:bg-gray-100 dark:hover:bg-slate-700 border-gray-300 py-2.5 dark:text-gray-400;
|
||||
.base.table {
|
||||
@apply min-w-[1000px];
|
||||
}
|
||||
|
||||
.list-content-item-wrap {
|
||||
@apply break-words items-center col-span-12 grid grid-cols-12 text-sm dark:text-gray-400;
|
||||
.lg.table {
|
||||
@apply min-w-[1200px];
|
||||
}
|
||||
|
||||
.list-header-container {
|
||||
.xl.table {
|
||||
@apply min-w-[1400px];
|
||||
}
|
||||
|
||||
.table-header {
|
||||
@apply block w-full col-span-12 grid grid-cols-12 pl-2;
|
||||
}
|
||||
|
||||
.list-header-item {
|
||||
.table-header-item {
|
||||
@apply block dark:text-gray-300 pb-1 text-sm font-bold m-0 border-b border-gray-400;
|
||||
}
|
||||
|
||||
.table-content {
|
||||
@apply dark:text-gray-400 block w-full rounded col-span-12 overflow-x-hidden overflow-y-auto max-h-[300px];
|
||||
}
|
||||
|
||||
.table-content-item {
|
||||
@apply text-sm col-span-12 block border-b hover:bg-gray-100 dark:hover:bg-slate-700 items-center grid grid-cols-12 border-gray-300 py-2.5 px-1;
|
||||
}
|
||||
|
||||
.table-content-item-wrap {
|
||||
@apply py-2.5 px-1;
|
||||
}
|
||||
|
||||
|
||||
/** MISC **/
|
||||
|
||||
.line-separator {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
149
vuejs/client/src/components/Widget/Table.vue
Normal file
149
vuejs/client/src/components/Widget/Table.vue
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
<script setup>
|
||||
import Container from "@components/Widget/Container.vue";
|
||||
import Text from "@components/Widget/Text.vue";
|
||||
import Icons from "@components/Widget/Icons.vue";
|
||||
import Fields from "@components/Form/Fields.vue";
|
||||
import Button from "@components/Widget/Button.vue";
|
||||
import { reactive, computed, resolveComponent } from "vue";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
/**
|
||||
@name Widget/Table.vue
|
||||
@description This component is used to create a table.
|
||||
You need to provide a title, a header, a list of positions, and a list of items.
|
||||
Items need to be an array of array with a cell being a regular widget. Not all widget are supported. Check this component import list to see which widget are supported.
|
||||
For example, Text, Icons, Icons, Buttons and Fields are supported.
|
||||
@example
|
||||
{
|
||||
"title": "Table title",
|
||||
"header": ["Header 1", "Header 2", "Header 3"],
|
||||
"minWidth": "base",
|
||||
"positions": [4,4,4],
|
||||
"items": [
|
||||
[
|
||||
{
|
||||
"type": "Text",
|
||||
"data": {
|
||||
"text": "whitelist-download"
|
||||
|
||||
}
|
||||
},
|
||||
...
|
||||
],
|
||||
...
|
||||
],
|
||||
}
|
||||
|
||||
@param {string} title - Determine the title of the table.
|
||||
@param {array} header - Determine the header of the table.
|
||||
@param {array} positions - Determine the position of each item in the table in a list of number based on 12 columns grid.
|
||||
@param {array} items - items to render in the table. This need to be an array (row) of array (cols) with a cell being a regular widget.
|
||||
@param {string} [minWidth="base"] - Determine the minimum size of the table. Can be "base", "sm", "md", "lg", "xl".
|
||||
@param {string} [containerClass=""] - Container additional class.
|
||||
@param {string} [containerWrapClass=""] - Container wrap additional class.
|
||||
@param {string} [tableClass=""] - Table additional class.
|
||||
*/
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
minWidth: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "base",
|
||||
},
|
||||
positions: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
header: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
items: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
containerClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
containerWrapClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
tableClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
});
|
||||
|
||||
const table = reactive({
|
||||
length: computed(() => {
|
||||
return props.header.length;
|
||||
}),
|
||||
rowLength: computed(() => {
|
||||
return props.items.length;
|
||||
}),
|
||||
title: computed(() => {
|
||||
return props.title ? props.title : "dashboard_table";
|
||||
}),
|
||||
id: uuidv4(),
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Container :containerClass="`${props.containerClass} table-container`">
|
||||
<Container
|
||||
:containerClass="`${props.containerWrapClass} table-container-wrap`"
|
||||
>
|
||||
<table
|
||||
:aria-colcount="table.length"
|
||||
:aria-rowcount="table.rowLength"
|
||||
:class="['table', props.minWidth, props.tableClass]"
|
||||
:aria-describedby="table.id"
|
||||
>
|
||||
<span class="sr-only" :id="table.id">
|
||||
{{ $t(table.title, table.title) }}
|
||||
</span>
|
||||
<thead class="table-header">
|
||||
<tr
|
||||
v-for="(head, id) in props.header"
|
||||
:class="['table-header-item', `col-span-${props.positions[id]}`]"
|
||||
>
|
||||
<th role="columnheader">
|
||||
{{ head }}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="table-content">
|
||||
<tr
|
||||
v-for="rowId in table.rowLength"
|
||||
role="row"
|
||||
:aria-rowindex="rowId"
|
||||
class="table-content-item"
|
||||
>
|
||||
<template v-for="(col, id) in props.items[rowId - 1]">
|
||||
<td
|
||||
:class="[
|
||||
'table-content-item-wrap',
|
||||
`col-span-${props.positions[id]}`,
|
||||
]"
|
||||
>
|
||||
<Text v-if="col.type === 'Text'" v-bind="col.data" />
|
||||
<Icons v-if="col.type === 'Icons'" v-bind="col.data" />
|
||||
<Fields v-if="col.type === 'Fields'" v-bind="col.data" />
|
||||
<Button v-if="col.type === 'Button'" v-bind="col.data" />
|
||||
</td>
|
||||
</template>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</Container>
|
||||
</Container>
|
||||
</template>
|
||||
|
|
@ -96,6 +96,7 @@
|
|||
"dashboard_easy_required": "{setting} in step {step} is required",
|
||||
"dashboard_templates_title_default": "Configuration templates",
|
||||
"dashboard_templates_subtitle_default": "Manage your settings with available templates and using the mode that suits you best.",
|
||||
"dashboard_table": "Table element",
|
||||
"inp_input_valid": "input valid",
|
||||
"inp_input_error_required": "input is required",
|
||||
"inp_input_error": "input is invalid",
|
||||
|
|
|
|||
|
|
@ -1,38 +1,12 @@
|
|||
<script setup>
|
||||
import { reactive, onBeforeMount, triggerRef } from "vue";
|
||||
import Checkbox from "@components/Forms/Field/Checkbox.vue";
|
||||
import Select from "@components/Forms/Field/Select.vue";
|
||||
import Input from "@components/Forms/Field/Input.vue";
|
||||
import Datepicker from "@components/Forms/Field/Datepicker.vue";
|
||||
import Combobox from "@components/Forms/Field/Combobox.vue";
|
||||
import Editor from "@components/Forms/Field/Editor.vue";
|
||||
import Button from "@components/Widget/Button.vue";
|
||||
import DashboardLayout from "@components/Dashboard/Layout.vue";
|
||||
import GridLayout from "@components/Widget/GridLayout.vue";
|
||||
import Grid from "@components/Widget/Grid.vue";
|
||||
|
||||
const checkboxData = {
|
||||
id: "test-checkbox",
|
||||
value: "yes",
|
||||
name: "test-checkbox",
|
||||
disabled: false,
|
||||
required: true,
|
||||
label: "Test checkbox",
|
||||
tabId: "1",
|
||||
};
|
||||
|
||||
const selectData = {
|
||||
id: "test-select",
|
||||
value: "yes",
|
||||
values: ["yes", "no"],
|
||||
name: "test-select",
|
||||
disabled: false,
|
||||
required: false,
|
||||
requiredValues: ["no"],
|
||||
label: "Test select",
|
||||
tabId: "1",
|
||||
columns: { pc: 12, tablet: 12, mobile: 12 },
|
||||
};
|
||||
import Table from "@components/Widget/Table.vue";
|
||||
|
||||
const inputData = {
|
||||
id: "test-input",
|
||||
|
|
@ -46,66 +20,6 @@ const inputData = {
|
|||
columns: { pc: 12, tablet: 12, mobile: 12 },
|
||||
};
|
||||
|
||||
const datepickerData = {
|
||||
id: "test-datepicker",
|
||||
name: "test-datepicker",
|
||||
disabled: false,
|
||||
required: true,
|
||||
label: "Test datepicker",
|
||||
tabId: "1",
|
||||
};
|
||||
|
||||
const buttonData = {
|
||||
id: "test-button",
|
||||
text: "Test button",
|
||||
type: "button",
|
||||
disabled: false,
|
||||
eventAttr: {
|
||||
store: "modal",
|
||||
default: "close",
|
||||
value: "open",
|
||||
target: "modal_id",
|
||||
valueExpanded: "open",
|
||||
},
|
||||
columns: { pc: 12, tablet: 12, mobile: 12 },
|
||||
tabId: "1",
|
||||
};
|
||||
|
||||
const buttonSVGData = {
|
||||
id: "test-button",
|
||||
text: "Test button",
|
||||
type: "button",
|
||||
disabled: false,
|
||||
eventAttr: {
|
||||
store: "modal",
|
||||
default: "close",
|
||||
value: "open",
|
||||
target: "modal_id",
|
||||
valueExpanded: "open",
|
||||
},
|
||||
columns: { pc: 12, tablet: 12, mobile: 12 },
|
||||
tabId: "1",
|
||||
iconName: "plus",
|
||||
};
|
||||
|
||||
const buttonOnlySVGData = {
|
||||
id: "test-button",
|
||||
text: "Test button",
|
||||
hideText: true,
|
||||
type: "button",
|
||||
disabled: false,
|
||||
eventAttr: {
|
||||
store: "modal",
|
||||
default: "close",
|
||||
value: "open",
|
||||
target: "modal_id",
|
||||
valueExpanded: "open",
|
||||
},
|
||||
columns: { pc: 12, tablet: 12, mobile: 12 },
|
||||
tabId: "1",
|
||||
iconName: "plus",
|
||||
};
|
||||
|
||||
const comboboxData = {
|
||||
id: "test-combobox",
|
||||
value: "yes",
|
||||
|
|
@ -129,6 +43,55 @@ const editorData = {
|
|||
tabId: "1",
|
||||
columns: { pc: 12, tablet: 12, mobile: 12 },
|
||||
};
|
||||
|
||||
const tableData = {
|
||||
title: "Table title",
|
||||
minWidth: "sm",
|
||||
header: ["Header 1", "Header 2", "Header 3"],
|
||||
positions: [4, 4, 4],
|
||||
items: [
|
||||
[
|
||||
{
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "whitelist-download",
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "whitelist-download",
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "whitelist-download",
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "whitelist-download",
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "whitelist-download",
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "Text",
|
||||
data: {
|
||||
text: "whitelist-download",
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -142,8 +105,7 @@ const editorData = {
|
|||
<GridLayout :columns="{ pc: 4, tablet: 6, mobile: 12 }">
|
||||
<!-- widget grid -->
|
||||
<Grid>
|
||||
<Combobox v-bind="comboboxData" />
|
||||
<Editor v-bind="editorData" />
|
||||
<Table v-bind="tableData" />
|
||||
</Grid>
|
||||
</GridLayout>
|
||||
</DashboardLayout>
|
||||
|
|
|
|||
Loading…
Reference in a new issue