merge ui
This commit is contained in:
@@ -1,31 +1,62 @@
|
||||
<script setup lang="ts">
|
||||
import HelloWorld from './components/HelloWorld.vue'
|
||||
import { ref } from 'vue';
|
||||
import type { IEntity } from './types/entity.type';
|
||||
import type { IService } from './types/service.type';
|
||||
import type { Scheme } from './types/scheme.type';
|
||||
import Table from './table/Table.vue';
|
||||
import { getDefaultValues } from './utils/structs/defaults.util';
|
||||
|
||||
class Entity implements IEntity {
|
||||
constructor(public Id: number, public Name: string, public Region: string) { }
|
||||
}
|
||||
|
||||
class Service implements IService<Entity> {
|
||||
private readonly entities = ref<Entity[]>([])
|
||||
private maxId = 0
|
||||
|
||||
async create(data: Entity): Promise<void | never> {
|
||||
this.maxId++
|
||||
this.entities.value.push({ ...data, Id: this.maxId })
|
||||
}
|
||||
async delete(id: number): Promise<void | never> {
|
||||
this.entities.value = this.entities.value.filter(el => el.Id != id)
|
||||
}
|
||||
async read(id: number): Promise<Entity | undefined> {
|
||||
return this.entities.value.find(el => el.Id == id)
|
||||
}
|
||||
async readAll(): Promise<Entity[]> {
|
||||
return this.entities.value
|
||||
}
|
||||
async update(data: Entity): Promise<void | never> {
|
||||
this.entities.value = this.entities.value.map(el => el.Id == data.Id ? data : el)
|
||||
}
|
||||
}
|
||||
|
||||
const service = new Service
|
||||
|
||||
const scheme: Scheme<Entity> = {
|
||||
Id: {
|
||||
hidden: true,
|
||||
russian: 'Id'
|
||||
},
|
||||
Name: {
|
||||
type: {
|
||||
primitive: 'string'
|
||||
},
|
||||
russian: 'Имя'
|
||||
},
|
||||
Region: {
|
||||
type: {
|
||||
nested: {
|
||||
field: [],
|
||||
values: ['kemerovo', 'kuzbass', 'berlin']
|
||||
}
|
||||
},
|
||||
russian: "Место жительства"
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="container">
|
||||
<div>
|
||||
<a wml-openURL="https://wails.io">
|
||||
<img src="/wails.png" class="logo" alt="Wails logo"/>
|
||||
</a>
|
||||
<a wml-openURL="https://vuejs.org/">
|
||||
<img src="/vue.svg" class="logo vue" alt="Vue logo"/>
|
||||
</a>
|
||||
</div>
|
||||
<HelloWorld msg="Wails + Vue" />
|
||||
</div>
|
||||
<Table :scheme :service :get-defaults="() => getDefaultValues(scheme)"></Table>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.logo {
|
||||
height: 6em;
|
||||
padding: 1.5em;
|
||||
will-change: filter;
|
||||
}
|
||||
.logo:hover {
|
||||
filter: drop-shadow(0 0 2em #e80000aa);
|
||||
}
|
||||
.logo.vue:hover {
|
||||
filter: drop-shadow(0 0 2em #42b883aa);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from "vue";
|
||||
import { Events } from "@wailsio/runtime";
|
||||
import * as PostService from "../../bindings/app/internal/services/postservice";
|
||||
|
||||
const name = ref("");
|
||||
const result = ref("Please enter your name below 👇");
|
||||
const time = ref("Listening for Time event...");
|
||||
|
||||
const doGreet = () => {
|
||||
let localName = name.value;
|
||||
if (!localName) {
|
||||
localName = "anonymous";
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
console.log(await PostService.GetById(5));
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>Kuzbass</h1>
|
||||
|
||||
<div class="result"></div>
|
||||
<div class="card">
|
||||
<div class="input-box">
|
||||
<input
|
||||
class="input"
|
||||
v-model="name"
|
||||
type="text"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<button class="btn" @click="doGreet">Greet</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<div><p>Click on the Wails logo to learn more</p></div>
|
||||
<div><p></p></div>
|
||||
</div>
|
||||
</template>
|
||||
4
frontend/src/components/buttons/FloatingButton.vue
Normal file
4
frontend/src/components/buttons/FloatingButton.vue
Normal file
@@ -0,0 +1,4 @@
|
||||
<template>
|
||||
<button class="fixed bottom-6 right-6 aspect-square h-10 text-3xl flex items-center justify-center rounded-full focus-visible:outline-none text-black"
|
||||
style="background:var(--p-primary-color)"><span class="pi pi-plus"></span></button>
|
||||
</template>
|
||||
@@ -1,4 +1,12 @@
|
||||
import { createApp } from 'vue'
|
||||
import './style.css'
|
||||
import App from './App.vue'
|
||||
import { Config } from 'primevue'
|
||||
import Aura from '@primevue/themes/aura'
|
||||
import 'primeicons/primeicons.css'
|
||||
|
||||
createApp(App).mount('#app')
|
||||
createApp(App).use(Config, {
|
||||
theme: {
|
||||
preset: Aura
|
||||
}
|
||||
}).mount('#app')
|
||||
|
||||
43
frontend/src/post/PostScheme.vue
Normal file
43
frontend/src/post/PostScheme.vue
Normal file
@@ -0,0 +1,43 @@
|
||||
<script setup lang="ts">
|
||||
import Table from '../table/Table.vue'
|
||||
import { onMounted, reactive } from 'vue'
|
||||
import { getDefaultValues } from '../utils/structs/defaults.util'
|
||||
import S from './post.service.ts'
|
||||
import type { Scheme } from '../types/scheme.type'
|
||||
import { Post } from '../../bindings/app/internal/services/models.ts'
|
||||
|
||||
const service = new S
|
||||
|
||||
onMounted(async () => {
|
||||
|
||||
})
|
||||
|
||||
|
||||
const scheme: Scheme<Post> = reactive({
|
||||
Id:{
|
||||
type: {
|
||||
primitive: "number",
|
||||
},
|
||||
},
|
||||
Text:{
|
||||
type: {
|
||||
primitive: "string",
|
||||
},
|
||||
},
|
||||
CreatedAt:{
|
||||
type: {
|
||||
primitive: "number",
|
||||
},
|
||||
},
|
||||
|
||||
})
|
||||
|
||||
const getDefaults = () => getDefaultValues(scheme)
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<main class="w-screen h-screen">
|
||||
<Table :scheme :service :getDefaults></Table>
|
||||
</main>
|
||||
</template>
|
||||
27
frontend/src/post/post.service.ts
Normal file
27
frontend/src/post/post.service.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { GetAll, Create, Delete, GetById, Update, Count } from "../../bindings/app/internal/services/postservice.ts"
|
||||
import type { Post } from "../../bindings/app/internal/services/models.ts"
|
||||
import type { IService } from "../types/service.type.ts"
|
||||
|
||||
export default class PostService implements IService<Post> {
|
||||
async read(id: number) {
|
||||
return await GetById(id)
|
||||
}
|
||||
|
||||
async readAll() {
|
||||
return await GetAll()
|
||||
}
|
||||
|
||||
async create(item: Post) {
|
||||
await Create(item)
|
||||
}
|
||||
|
||||
async delete(id: number) {
|
||||
return await Delete(id)
|
||||
}
|
||||
async update(item: Post) {
|
||||
await Update(item)
|
||||
}
|
||||
async count() {
|
||||
return await Count()
|
||||
}
|
||||
}
|
||||
3
frontend/src/style.css
Normal file
3
frontend/src/style.css
Normal file
@@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
94
frontend/src/table/DialogWindow.vue
Normal file
94
frontend/src/table/DialogWindow.vue
Normal file
@@ -0,0 +1,94 @@
|
||||
<script setup lang="ts" generic="T extends IEntity">
|
||||
import { Button, DatePicker, Dialog, InputNumber, InputText, MultiSelect, Select, Textarea, ToggleSwitch } from 'primevue';
|
||||
import type { IEntity } from '../types/entity.type';
|
||||
import type { Scheme } from '../types/scheme.type';
|
||||
import type { IService } from '../types/service.type';
|
||||
import { manyStructsView } from '../utils/structs/structs-view.util';
|
||||
import { type UnwrapRef } from 'vue';
|
||||
|
||||
const showCreate = defineModel<boolean>('show')
|
||||
const createItem = defineModel<T>('item')
|
||||
|
||||
const items = defineModel<UnwrapRef<T[]>>('items')
|
||||
|
||||
const props = defineProps<{
|
||||
scheme: Scheme<T>,
|
||||
getDefaults: () => Partial<T>,
|
||||
service: IService<T>,
|
||||
updateMode?: boolean
|
||||
}>()
|
||||
|
||||
type Key = keyof T
|
||||
const keys = Object.keys(props.scheme) as Key[]
|
||||
|
||||
const emits = defineEmits<{
|
||||
(e: 'onSave', data: any): void
|
||||
(e: 'onSaveUpdate', data: any): void
|
||||
(e: 'onSaveCreate', data: any): void
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Dialog v-model:visible="showCreate">
|
||||
<div class="flex flex-col justify-center gap-5">
|
||||
<div v-for="key in keys" v-show="!props.scheme[key].hidden && !props.scheme[key].readonly"
|
||||
class="flex items-center gap-5">
|
||||
<h1 class="w-[200px]">{{ props.scheme[key].russian }}</h1>
|
||||
<div>
|
||||
<div v-if="props.scheme[key]?.customWindow?.[props.updateMode ? 'update' : 'create']">
|
||||
<slot :name="<string>key + (props.updateMode ? 'Update' : 'Create')"></slot>
|
||||
</div>
|
||||
<div v-else-if="props.scheme[key]?.customWindow?.common">
|
||||
<slot :name="<string>key"></slot>
|
||||
</div>
|
||||
<InputNumber class="w-[300px]" v-model:model-value="<number>createItem![key]"
|
||||
v-else-if="props.scheme[key]?.type?.primitive === 'number'" />
|
||||
<InputText class="w-[300px]" v-model:model-value="<string>createItem![key]"
|
||||
v-else-if="props.scheme[key].type?.primitive === 'string'" />
|
||||
<DatePicker class="w-[300px]" v-model:model-value="<Date>createItem![key]"
|
||||
v-else-if="props.scheme[key].type?.primitive === 'date'" />
|
||||
<Textarea class="w-[300px]" v-model="<string>createItem![key]"
|
||||
v-else-if="props.scheme[key].type?.primitive === 'multiple'" />
|
||||
<ToggleSwitch class="w-[300px]" v-model:model-value="<boolean>createItem![key]"
|
||||
v-else-if="props.scheme[key].type?.primitive === 'boolean'" />
|
||||
<Select v-else-if="props.scheme[key].type?.nested?.values && !props.scheme[key].type?.many"
|
||||
v-model:model-value="createItem![key]" :options="props.scheme[key].type.nested.values"
|
||||
:placeholder="`Выберите ${props.scheme[key].russian}`" class="w-[300px]">
|
||||
<template #option="{ option }">
|
||||
{{ manyStructsView(option, props.scheme[key].type.nested.field) }}
|
||||
</template>
|
||||
<template #value="{ value }">
|
||||
{{ manyStructsView(value, props.scheme[key].type.nested.field) }}
|
||||
</template>
|
||||
</Select>
|
||||
<MultiSelect v-else-if="props.scheme[key].type?.many" v-model:model-value="createItem![key]"
|
||||
:options="props.scheme[key].type?.nested?.values"
|
||||
class="w-[300px] h-11"
|
||||
:placeholder="`Выберите ${props.scheme[key].russian}`">
|
||||
<template #option="{ option }">
|
||||
{{ manyStructsView(option, props.scheme[key]?.type?.nested?.field) }}
|
||||
</template>
|
||||
<template #value="{ value }">
|
||||
{{ manyStructsView(value, props.scheme[key]?.type?.nested?.field) }}
|
||||
</template>
|
||||
</MultiSelect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<Button severity="success" @click="async () => {
|
||||
if (props.updateMode) {
|
||||
props.service.update(createItem as T)
|
||||
emits('onSaveUpdate', createItem as T)
|
||||
emits('onSave', createItem as T)
|
||||
} else {
|
||||
props.service.create(createItem as T)
|
||||
emits('onSaveCreate', createItem as T)
|
||||
emits('onSave', createItem as T)
|
||||
}
|
||||
items = await service.readAll() as UnwrapRef<T[]>
|
||||
showCreate = false
|
||||
}">Сохранить</Button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
155
frontend/src/table/Table.vue
Normal file
155
frontend/src/table/Table.vue
Normal file
@@ -0,0 +1,155 @@
|
||||
<script setup lang="ts" generic="T extends IEntity">
|
||||
import { onMounted, ref, watch, type UnwrapRef } from "vue";
|
||||
import type { TableProps } from "../types/table-props.type";
|
||||
import { DataTable, Column, Button } from "primevue";
|
||||
import { manyStructsView } from "../utils/structs/structs-view.util";
|
||||
import type { TableEmits } from "../types/table-emits.type";
|
||||
import FloatingButton from "../components/buttons/FloatingButton.vue";
|
||||
import type { IEntity } from "../types/entity.type";
|
||||
import DialogWindow from "./DialogWindow.vue";
|
||||
|
||||
const props = defineProps<TableProps<T>>();
|
||||
|
||||
const items = ref<T[]>([]);
|
||||
|
||||
onMounted(async () => {
|
||||
items.value = await props.service.readAll();
|
||||
});
|
||||
|
||||
type Key = keyof T;
|
||||
const keys = Object.keys(props.scheme) as Key[];
|
||||
const emits = defineEmits<TableEmits>();
|
||||
|
||||
const showCreate = ref(false);
|
||||
const createItem = ref<null | T>(null);
|
||||
|
||||
const showUpdate = ref(false);
|
||||
const updateItem = ref<null | T>(null);
|
||||
|
||||
watch(showUpdate, (value) => {
|
||||
if (!value) {
|
||||
updateItem.value = null;
|
||||
}
|
||||
});
|
||||
|
||||
watch(updateItem, (value) => {
|
||||
if (value) {
|
||||
showUpdate.value = true;
|
||||
} else {
|
||||
showUpdate.value = false;
|
||||
}
|
||||
});
|
||||
|
||||
watch(showCreate, (value) => {
|
||||
if (value) {
|
||||
createItem.value = props.getDefaults();
|
||||
} else {
|
||||
createItem.value = null;
|
||||
}
|
||||
});
|
||||
|
||||
watch(createItem, (value) => {
|
||||
if (value) {
|
||||
showCreate.value = true;
|
||||
} else {
|
||||
showCreate.value = false;
|
||||
}
|
||||
});
|
||||
|
||||
const handleFloatingButtonClick = () => {
|
||||
emits('onCreateOpen')
|
||||
emits('onOpen')
|
||||
showCreate.value = true;
|
||||
};
|
||||
const slots = defineSlots();
|
||||
|
||||
const createSlotName = (key: any) => key + "Create";
|
||||
const updateSlotName = (key: any) => key + "Update";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogWindow
|
||||
:scheme="props.scheme"
|
||||
:service="props.service"
|
||||
:get-defaults="props.getDefaults"
|
||||
v-model:item="<T>createItem"
|
||||
v-model:show="showCreate"
|
||||
v-model:items="items"
|
||||
@on-save="data => emits('onSave', data)"
|
||||
@on-save-create="data => emits('onSaveCreate', data)"
|
||||
>
|
||||
<template v-for="key in keys" #[key]>
|
||||
<slot :name="<string>key"></slot>
|
||||
</template>
|
||||
<template v-for="key in keys" #[createSlotName(key)]>
|
||||
<slot :name="createSlotName(key)"></slot>
|
||||
</template>
|
||||
</DialogWindow>
|
||||
<DialogWindow
|
||||
:scheme="props.scheme"
|
||||
update-mode
|
||||
:service="props.service"
|
||||
:get-defaults="props.getDefaults"
|
||||
v-model:item="<T>updateItem"
|
||||
v-model:show="showUpdate"
|
||||
v-model:items="items"
|
||||
@on-save="data => emits('onSave', data)"
|
||||
@on-save-update="data => emits('onSaveUpdate', data)"
|
||||
>
|
||||
<template v-for="key in keys" #[key]>
|
||||
<slot :name="<string>key"></slot>
|
||||
</template>
|
||||
<template v-for="key in keys" #[updateSlotName(key)]>
|
||||
<slot :name="updateSlotName(key)"></slot>
|
||||
</template>
|
||||
</DialogWindow>
|
||||
<div>
|
||||
<DataTable :value="<[]>items">
|
||||
<template #header v-if="props.name">
|
||||
<p>{{ props.name }}</p>
|
||||
</template>
|
||||
<template v-for="key in keys">
|
||||
<Column
|
||||
:header="props.scheme[key]?.russian"
|
||||
v-if="!props.scheme[key].hidden"
|
||||
>
|
||||
<template #body="{ data }">
|
||||
<p>
|
||||
{{
|
||||
manyStructsView(
|
||||
data[key],
|
||||
props.scheme[key]?.type?.nested?.field,
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
</template>
|
||||
</Column>
|
||||
</template>
|
||||
<Column header="Действия">
|
||||
<template #body="{ data }">
|
||||
<div class="flex gap-2">
|
||||
<Button
|
||||
severity="secondary"
|
||||
icon="pi pi-pencil"
|
||||
@click="() => {
|
||||
emits('onUpdateOpen')
|
||||
emits('onOpen')
|
||||
updateItem = data
|
||||
}"
|
||||
></Button>
|
||||
<Button
|
||||
severity="danger"
|
||||
icon="pi pi-trash"
|
||||
@click="async () => {
|
||||
emits('onDelete', data)
|
||||
await props.service.delete(data.Id)
|
||||
items = await props.service.readAll() as UnwrapRef<T[]>
|
||||
}"
|
||||
></Button>
|
||||
</div>
|
||||
</template>
|
||||
</Column>
|
||||
</DataTable>
|
||||
<FloatingButton @click="handleFloatingButtonClick" />
|
||||
</div>
|
||||
</template>
|
||||
3
frontend/src/types/entity.type.ts
Normal file
3
frontend/src/types/entity.type.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export interface IEntity {
|
||||
Id: number
|
||||
}
|
||||
1
frontend/src/types/primitive-field-type.type.ts
Normal file
1
frontend/src/types/primitive-field-type.type.ts
Normal file
@@ -0,0 +1 @@
|
||||
export type PrimitiveFieldType = "date" | "number" | "string" | "boolean" | "multiple"
|
||||
21
frontend/src/types/scheme-field.type.ts
Normal file
21
frontend/src/types/scheme-field.type.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import type { IEntity } from "./entity.type"
|
||||
import type { PrimitiveFieldType } from "./primitive-field-type.type"
|
||||
|
||||
export interface ISchemeField<T extends IEntity> {
|
||||
type?: {
|
||||
primitive?: PrimitiveFieldType
|
||||
nested?: {
|
||||
field: string[]
|
||||
values: T[]
|
||||
}
|
||||
many?: boolean
|
||||
}
|
||||
russian?: string
|
||||
hidden?: boolean
|
||||
readonly?: boolean
|
||||
customWindow?: {
|
||||
common?: boolean
|
||||
create?: boolean
|
||||
update?: boolean
|
||||
}
|
||||
}
|
||||
4
frontend/src/types/scheme.type.ts
Normal file
4
frontend/src/types/scheme.type.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import type { IEntity } from "./entity.type";
|
||||
import type { ISchemeField } from "./scheme-field.type";
|
||||
|
||||
export type Scheme<T extends IEntity, S extends IEntity=any> = Record<keyof T, ISchemeField<S>>
|
||||
7
frontend/src/types/service.type.ts
Normal file
7
frontend/src/types/service.type.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export interface IService<T> {
|
||||
read(id: number): Promise<T | undefined>
|
||||
readAll(): Promise<T[]>
|
||||
create(data: T): Promise<void | never>
|
||||
update(data: T): Promise<void | never>
|
||||
delete(id: number): Promise<void | never>
|
||||
}
|
||||
12
frontend/src/types/table-emits.type.ts
Normal file
12
frontend/src/types/table-emits.type.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export type TableEmits = {
|
||||
(e: 'onCreateOpen'): void
|
||||
(e: 'onCreateClose', data: any): void
|
||||
(e: 'onUpdateOpen'): void
|
||||
(e: 'onUpdateClose', data: any): void
|
||||
(e: 'onOpen'): void
|
||||
(e: 'onClose', data: any): void
|
||||
(e: 'onDelete', data: any): void
|
||||
(e: 'onSaveUpdate', data: any): void
|
||||
(e: 'onSaveCreate', data: any): void
|
||||
(e: 'onSave', data: any): void
|
||||
}
|
||||
11
frontend/src/types/table-props.type.ts
Normal file
11
frontend/src/types/table-props.type.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import type { IEntity } from "./entity.type";
|
||||
import type { Scheme } from "./scheme.type";
|
||||
import type { IService } from "./service.type";
|
||||
|
||||
export interface TableProps<T extends IEntity> {
|
||||
service: IService<T>
|
||||
scheme: Scheme<T>
|
||||
name?: string
|
||||
getDefaults: () => Partial<T>
|
||||
validate?: (data: T) => never | void
|
||||
}
|
||||
10
frontend/src/utils/date/converters.util.ts
Normal file
10
frontend/src/utils/date/converters.util.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
const getFullTimestamp = (n: number): number => {
|
||||
const length = String(n).length
|
||||
let str = ''
|
||||
while (str.length + length < 13) {
|
||||
str += '0'
|
||||
}
|
||||
return parseInt(`${n}${str}`)
|
||||
}
|
||||
export const toDate = (n: number) => new Date(getFullTimestamp(n))
|
||||
export const toTimestamp = (d: Date) => d.getTime()
|
||||
6
frontend/src/utils/date/getters.ts
Normal file
6
frontend/src/utils/date/getters.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export const getTomorrow = (): Date => {
|
||||
const today = new Date();
|
||||
const tomorrow = new Date(today);
|
||||
tomorrow.setDate(today.getDate() + 1);
|
||||
return tomorrow;
|
||||
}
|
||||
27
frontend/src/utils/structs/defaults.util.ts
Normal file
27
frontend/src/utils/structs/defaults.util.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import type { IEntity } from "../../types/entity.type";
|
||||
import type { Scheme } from "../../types/scheme.type";
|
||||
import { getTomorrow } from "../date/getters";
|
||||
|
||||
export const getDefaultValues = <T extends IEntity>(scheme: Scheme<T>) => {
|
||||
const keys = Object.keys(scheme) as (keyof typeof scheme)[]
|
||||
let obj: any = {}
|
||||
|
||||
for (let key of keys) {
|
||||
const primitive = scheme[key]?.type?.primitive
|
||||
if (primitive == 'string' || primitive == 'multiple') {
|
||||
obj[key] = ''
|
||||
} else if (primitive == 'date') {
|
||||
obj[key] = getTomorrow()
|
||||
} else if (primitive == 'boolean') {
|
||||
obj[key] = false
|
||||
} else if (primitive == 'number') {
|
||||
obj[key] = 1
|
||||
} else if (scheme[key].type?.many) {
|
||||
obj[key] = []
|
||||
} else if (scheme[key]?.type?.nested?.values) {
|
||||
obj[key] = scheme[key].type.nested.values[0]
|
||||
}
|
||||
}
|
||||
|
||||
return obj as T
|
||||
}
|
||||
18
frontend/src/utils/structs/structs-view.util.ts
Normal file
18
frontend/src/utils/structs/structs-view.util.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export const structView = (item: any, path: any) => {
|
||||
if (!item) return;
|
||||
if (!path?.length) return item;
|
||||
let result = item
|
||||
let i = 0
|
||||
let current
|
||||
while (current != path[path.length - 1] && result) {
|
||||
current = path[i]
|
||||
result = result[current]
|
||||
i++
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export const manyStructsView = (items: any, path: any) => {
|
||||
if (!Array.isArray(items)) return structView(items, path);
|
||||
return items.map(item => structView(item, path)).join(", ")
|
||||
}
|
||||
1
frontend/src/utils/sugar/if-null.util.ts
Normal file
1
frontend/src/utils/sugar/if-null.util.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const ifNull = (data: any, elseData: any) => data? data : elseData
|
||||
Reference in New Issue
Block a user