Merge branch 'develop' into nice_dev
This commit is contained in:
commit
bfa2e9fe08
5 changed files with 297 additions and 160 deletions
|
|
@ -1,7 +1,21 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, reactive, watchEffect, watch } from "vue";
|
||||
import type { dataRowRound } from "@/modules/09_leave/interface/response/round.ts";
|
||||
import type {
|
||||
dataRowRound,
|
||||
MyObjectRoundRef,
|
||||
} from "@/modules/09_leave/interface/response/round";
|
||||
import DialogHeader from "@/components/DialogHeader.vue";
|
||||
import { useCounterMixin } from "@/stores/mixin";
|
||||
import { useQuasar } from "quasar";
|
||||
|
||||
const $q = useQuasar();
|
||||
const mixin = useCounterMixin();
|
||||
const { dialogConfirm } = mixin;
|
||||
|
||||
const amRef = ref<Object | null>(null);
|
||||
const amOutRef = ref<Object | null>(null);
|
||||
const pmRef = ref<Object | null>(null);
|
||||
const pmOutRef = ref<Object | null>(null);
|
||||
|
||||
const formData = reactive<dataRowRound>({
|
||||
am: "",
|
||||
|
|
@ -10,8 +24,45 @@ const formData = reactive<dataRowRound>({
|
|||
pmOut: "",
|
||||
note: "",
|
||||
status: false,
|
||||
isDefault: false,
|
||||
});
|
||||
|
||||
const objectRound: MyObjectRoundRef = {
|
||||
am: amRef,
|
||||
amOut: amOutRef,
|
||||
pm: pmRef,
|
||||
pmOut: pmOutRef,
|
||||
};
|
||||
|
||||
function validateForm() {
|
||||
const hasError = [];
|
||||
for (const key in objectRound) {
|
||||
if (Object.prototype.hasOwnProperty.call(objectRound, key)) {
|
||||
const property = objectRound[key];
|
||||
if (property.value && typeof property.value.validate === "function") {
|
||||
const isValid = property.value.validate();
|
||||
hasError.push(isValid);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasError.every((result) => result === true)) {
|
||||
onSubmit();
|
||||
} else {
|
||||
console.log("ไม่ผ่าน ");
|
||||
console.log(hasError);
|
||||
}
|
||||
}
|
||||
function onSubmit() {
|
||||
dialogConfirm(
|
||||
$q,
|
||||
async () => {
|
||||
console.log(formData);
|
||||
props.closeDialog?.();
|
||||
},
|
||||
"ยืนยันการบันทึกข้อมูล",
|
||||
"ต้องการยืนยันการบันทึกข้อมูลนี้หรือไม่ ?"
|
||||
);
|
||||
}
|
||||
const props = defineProps({
|
||||
modal: Boolean,
|
||||
editCheck: String,
|
||||
|
|
@ -19,11 +70,6 @@ const props = defineProps({
|
|||
detailData: Object,
|
||||
});
|
||||
|
||||
function clickSave() {
|
||||
if (props.closeDialog) {
|
||||
props.closeDialog();
|
||||
}
|
||||
}
|
||||
function close() {
|
||||
if (props.closeDialog) {
|
||||
props.closeDialog();
|
||||
|
|
@ -32,8 +78,8 @@ function close() {
|
|||
watch(
|
||||
() => props.modal,
|
||||
(newDetailData, oldDetailData) => {
|
||||
console.log(props.editCheck)
|
||||
if (props.editCheck === 'add') {
|
||||
console.log(props.editCheck);
|
||||
if (props.editCheck === "add") {
|
||||
formData.am = "";
|
||||
formData.amOut = "";
|
||||
formData.pm = "";
|
||||
|
|
@ -41,7 +87,7 @@ watch(
|
|||
formData.note = "";
|
||||
formData.status = false;
|
||||
} else {
|
||||
if(props.detailData){
|
||||
if (props.detailData) {
|
||||
formData.am = props.detailData.am;
|
||||
formData.amOut = props.detailData.amOut;
|
||||
formData.pm = props.detailData.pm;
|
||||
|
|
@ -57,129 +103,221 @@ watch(
|
|||
<template>
|
||||
<q-dialog v-model="props.modal" persistent>
|
||||
<q-card style="min-width: 350px" class="bg-grey-11">
|
||||
<DialogHeader
|
||||
:tittle="
|
||||
props.editCheck === 'add'
|
||||
? 'เพิ่มรอบการปฏิบัติงาน'
|
||||
: props.detailData
|
||||
? `แก้ไขรอบ ${props.detailData.round}`
|
||||
: ''
|
||||
"
|
||||
:close="close"
|
||||
/>
|
||||
<q-separator color="grey-4" />
|
||||
<q-card-section style="max-height: 50vh" class="scroll q-pa-none">
|
||||
<div
|
||||
class="col q-ma-md q-pa-sm bg-white border_custom text-weight-medium"
|
||||
>
|
||||
<p style="color: #06884d; font-size: 16px">ครึ่งเช้า</p>
|
||||
<div class="row justify-between q-my-sm items-center">
|
||||
<p class="q-ma-none">เวลาเข้างาน</p>
|
||||
<q-input
|
||||
class="inputgreen"
|
||||
:readonly="props.editCheck === 'edit'"
|
||||
:outlined="props.editCheck === 'add'"
|
||||
dense
|
||||
lazy-rules
|
||||
borderless
|
||||
v-model="formData.am"
|
||||
hide-bottom-space
|
||||
type="time"
|
||||
/>
|
||||
</div>
|
||||
<q-separator inset />
|
||||
<div class="row items-center q-my-sm justify-between">
|
||||
<p class="q-ma-none">เวลาออกงาน</p>
|
||||
<q-input
|
||||
class="inputgreen"
|
||||
:readonly="props.editCheck === 'edit'"
|
||||
:outlined="props.editCheck === 'add'"
|
||||
dense
|
||||
v-model="formData.amOut"
|
||||
lazy-rules
|
||||
borderless
|
||||
hide-bottom-space
|
||||
type="time"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col q-ma-md q-pa-sm bg-white border_custom text-weight-medium"
|
||||
>
|
||||
<p style="color: #06884d; font-size: 16px">ครึ่งบ่าย</p>
|
||||
<div class="row justify-between q-my-sm items-center">
|
||||
<p class="q-ma-none">เวลาเข้างาน</p>
|
||||
<q-input
|
||||
class="inputgreen"
|
||||
:readonly="props.editCheck === 'edit'"
|
||||
:outlined="props.editCheck === 'add'"
|
||||
dense
|
||||
lazy-rules
|
||||
borderless
|
||||
v-model="formData.pm"
|
||||
hide-bottom-space
|
||||
type="time"
|
||||
/>
|
||||
</div>
|
||||
<q-separator inset />
|
||||
<div class="row items-center q-my-sm justify-between">
|
||||
<p class="q-ma-none">เวลาออกงาน</p>
|
||||
<q-input
|
||||
class="inputgreen"
|
||||
:readonly="props.editCheck === 'edit'"
|
||||
:outlined="props.editCheck === 'add'"
|
||||
dense
|
||||
v-model="formData.pmOut"
|
||||
lazy-rules
|
||||
borderless
|
||||
hide-bottom-space
|
||||
type="time"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<q-input
|
||||
class="col-12 bg-white q-ma-md"
|
||||
outlined
|
||||
stack-label
|
||||
v-model="formData.note"
|
||||
label="คำอธิบาย"
|
||||
hide-bottom-space
|
||||
type="textarea"
|
||||
></q-input>
|
||||
<div
|
||||
class="col q-ma-md q-pa-sm bg-white border_custom text-weight-medium"
|
||||
>
|
||||
<div class="row items-center q-my-sm justify-between">
|
||||
<p class="q-ma-none">สถานะการใช้งาน</p>
|
||||
<label class="toggle-control">
|
||||
<input type="checkbox" v-model="formData.status" />
|
||||
<span class="control"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-separator color="grey-4" />
|
||||
<div class="q-pa-xs">
|
||||
<div class="row justify-end">
|
||||
<q-btn
|
||||
id="onSubmit"
|
||||
type="submit"
|
||||
flat
|
||||
round
|
||||
@click="clickSave"
|
||||
color="secondary"
|
||||
icon="mdi-content-save-outline"
|
||||
><q-tooltip>{{
|
||||
props.editCheck === 'add' ? "บันทึกข้อมูล" : "บันทึกแก้ไขข้อมูล"
|
||||
}}</q-tooltip></q-btn
|
||||
<form @submit.prevent="validateForm">
|
||||
<DialogHeader
|
||||
:tittle="
|
||||
props.editCheck === 'add'
|
||||
? 'เพิ่มรอบการปฏิบัติงาน'
|
||||
: props.detailData
|
||||
? `แก้ไขรอบ ${props.detailData.round}`
|
||||
: ''
|
||||
"
|
||||
:close="close"
|
||||
/>
|
||||
<q-separator color="grey-4" />
|
||||
<q-card-section style="max-height: 50vh" class="scroll q-pa-none">
|
||||
<div
|
||||
class="col q-ma-md q-pa-sm bg-white border_custom text-weight-medium"
|
||||
>
|
||||
<p style="color: #06884d; font-size: 16px">ครึ่งเช้า</p>
|
||||
<div class="row justify-between q-my-sm items-start">
|
||||
<p class="q-ma-none mt">เวลาเข้างาน</p>
|
||||
<q-input
|
||||
ref="amRef"
|
||||
class="inputgreen"
|
||||
:readonly="props.editCheck === 'edit'"
|
||||
:outlined="props.editCheck === 'add'"
|
||||
dense
|
||||
lazy-rules
|
||||
borderless
|
||||
v-model="formData.am"
|
||||
:rules="[
|
||||
(val) => !!val || 'กรุณากรอกเวลาเข้างาน',
|
||||
(val) => {
|
||||
if (val && formData.amOut) {
|
||||
if (val > formData.amOut) {
|
||||
return 'เวลาเข้างานต้องน้อยกว่าเวลาออกงาน';
|
||||
}
|
||||
if (val >= formData.pm && val <= formData.pmOut) {
|
||||
return 'เวลาเข้างานต้องไม่อยู่ในช่วงบ่าย';
|
||||
}
|
||||
if(val === formData.amOut){
|
||||
return 'เวลาเข้างานช่วงเช้าต้องไม่ซ้ำกับออกงานเช้า'
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
},
|
||||
]"
|
||||
hide-bottom-space
|
||||
type="time"
|
||||
style="width: 140px"
|
||||
/>
|
||||
</div>
|
||||
<q-separator inset />
|
||||
<div class="row items-start q-my-sm justify-between">
|
||||
<p class="q-ma-none mt">เวลาออกงาน</p>
|
||||
<q-input
|
||||
ref="amOutRef"
|
||||
class="inputgreen"
|
||||
:readonly="props.editCheck === 'edit'"
|
||||
:outlined="props.editCheck === 'add'"
|
||||
dense
|
||||
v-model="formData.amOut"
|
||||
lazy-rules
|
||||
borderless
|
||||
:rules="[
|
||||
(val) => !!val || 'กรุณากรอกเวลาออกงาน',
|
||||
(val) => {
|
||||
if (val && formData.am) {
|
||||
if (val < formData.am) {
|
||||
return 'เวลาออกงานต้องมากกว่าเวลาเข้างาน';
|
||||
}
|
||||
if (val >= formData.pm && val <= formData.pmOut) {
|
||||
return 'เวลาออกงานต้องไม่อยู่ในช่วงบ่าย';
|
||||
}
|
||||
if(val === formData.am){
|
||||
return 'เวลาออกงานช่วงเช้าต้องไม่ซ้ำกับเข้างานเช้า'
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
]"
|
||||
hide-bottom-space
|
||||
type="time"
|
||||
style="width: 140px"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col q-ma-md q-pa-sm bg-white border_custom text-weight-medium"
|
||||
>
|
||||
<p style="color: #06884d; font-size: 16px">ครึ่งบ่าย</p>
|
||||
<div class="row justify-between q-my-sm items-start">
|
||||
<p class="q-ma-none mt">เวลาเข้างาน</p>
|
||||
<q-input
|
||||
ref="pmRef"
|
||||
:rules="[
|
||||
(val) => !!val || 'กรุณากรอกเวลาเข้างาน',
|
||||
(val) => {
|
||||
if (val && formData.pmOut) {
|
||||
if (val > formData.pmOut) {
|
||||
return 'เวลาเข้างานต้องน้อยกว่าเวลาออกงาน';
|
||||
}
|
||||
if (val >= formData.am && val <= formData.amOut) {
|
||||
return 'เวลาเข้างานต้องไม่อยู่ในช่วงเช้า';
|
||||
}
|
||||
if(val === formData.pmOut){
|
||||
return 'เวลาเข้างานช่วงบ่ายต้องไม่ซ้ำกับออกงานช่วงบ่าย'
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
]"
|
||||
class="inputgreen"
|
||||
:readonly="props.editCheck === 'edit'"
|
||||
:outlined="props.editCheck === 'add'"
|
||||
dense
|
||||
lazy-rules
|
||||
borderless
|
||||
v-model="formData.pm"
|
||||
hide-bottom-space
|
||||
type="time"
|
||||
style="width: 140px"
|
||||
/>
|
||||
</div>
|
||||
<q-separator inset />
|
||||
<div class="row items-start q-my-sm justify-between">
|
||||
<p class="q-ma-none mt">เวลาออกงาน</p>
|
||||
<q-input
|
||||
ref="pmOutRef"
|
||||
:rules="[
|
||||
(val) => !!val || 'กรุณากรอกเวลาออกงาน',
|
||||
(val) => {
|
||||
if (val && formData.pm) {
|
||||
if (val < formData.pm) {
|
||||
return 'เวลาออกงานต้องมากกว่าเวลาเข้างาน';
|
||||
}
|
||||
if (val >= formData.am && val <= formData.amOut) {
|
||||
return 'เวลาออกงานต้องไม่อยู่ในช่วงเช้า';
|
||||
}
|
||||
if(val === formData.pm){
|
||||
return 'เวลาเข้างานช่วงบ่ายต้องไม่ซ้ำกับออกงานช่วงบ่าย'
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
]"
|
||||
class="inputgreen"
|
||||
:readonly="props.editCheck === 'edit'"
|
||||
:outlined="props.editCheck === 'add'"
|
||||
dense
|
||||
v-model="formData.pmOut"
|
||||
lazy-rules
|
||||
borderless
|
||||
hide-bottom-space
|
||||
type="time"
|
||||
style="width: 140px"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<q-input
|
||||
class="col-12 bg-white q-ma-md"
|
||||
outlined
|
||||
stack-label
|
||||
v-model="formData.note"
|
||||
label="คำอธิบาย"
|
||||
hide-bottom-space
|
||||
type="textarea"
|
||||
></q-input>
|
||||
<div
|
||||
class="col q-ma-md q-pa-sm bg-white border_custom text-weight-medium"
|
||||
>
|
||||
<div class="row items-center q-my-sm justify-between">
|
||||
<p class="q-ma-none">เวลา Default</p>
|
||||
<label class="toggle-control">
|
||||
<input type="checkbox" v-model="formData.isDefault" />
|
||||
<span class="control"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col q-ma-md q-pa-sm bg-white border_custom text-weight-medium"
|
||||
>
|
||||
<div class="row items-center q-my-sm justify-between">
|
||||
<p class="q-ma-none">สถานะการใช้งาน</p>
|
||||
<label class="toggle-control">
|
||||
<input type="checkbox" v-model="formData.status" />
|
||||
<span class="control"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-separator color="grey-4" />
|
||||
<div class="q-pa-xs">
|
||||
<div class="row justify-end">
|
||||
<q-btn
|
||||
id="onSubmit"
|
||||
type="submit"
|
||||
flat
|
||||
round
|
||||
color="secondary"
|
||||
icon="mdi-content-save-outline"
|
||||
><q-tooltip>{{
|
||||
props.editCheck === "add" ? "บันทึกข้อมูล" : "บันทึกแก้ไขข้อมูล"
|
||||
}}</q-tooltip></q-btn
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.mt {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.border_custom {
|
||||
border-radius: 6px !important;
|
||||
border: 1px solid #e1e1e1;
|
||||
|
|
|
|||
|
|
@ -6,14 +6,23 @@ interface RoundRows {
|
|||
phone: string;
|
||||
}
|
||||
interface dataRowRound {
|
||||
am:string
|
||||
amOut:string
|
||||
pm:string
|
||||
pmOut:string
|
||||
note:string
|
||||
status:boolean
|
||||
am: string
|
||||
amOut: string
|
||||
pm: string
|
||||
pmOut: string
|
||||
note: string
|
||||
status: boolean
|
||||
isDefault: boolean
|
||||
}
|
||||
interface MyObjectRoundRef {
|
||||
am: object | null,
|
||||
amOut: object | null,
|
||||
pm: object | null,
|
||||
pmOut: object | null,
|
||||
[key: string]: any;
|
||||
}
|
||||
export type {
|
||||
RoundRows,
|
||||
dataRowRound
|
||||
dataRowRound,
|
||||
MyObjectRoundRef
|
||||
};
|
||||
|
|
@ -38,15 +38,6 @@ export const useRoundDataStore = defineStore(
|
|||
headerStyle: "font-size: 14px",
|
||||
style: "font-size: 14px",
|
||||
},
|
||||
{
|
||||
name: "amOut",
|
||||
align: "left",
|
||||
label: "ออก",
|
||||
sortable: true,
|
||||
field: "amOut",
|
||||
headerStyle: "font-size: 14px",
|
||||
style: "font-size: 14px",
|
||||
},
|
||||
{
|
||||
name: "pm",
|
||||
align: "left",
|
||||
|
|
@ -56,15 +47,6 @@ export const useRoundDataStore = defineStore(
|
|||
headerStyle: "font-size: 14px",
|
||||
style: "font-size: 14px",
|
||||
},
|
||||
{
|
||||
name: "pmOut",
|
||||
align: "left",
|
||||
label: "ออก",
|
||||
sortable: true,
|
||||
field: "pmOut",
|
||||
headerStyle: "font-size: 14px",
|
||||
style: "font-size: 14px",
|
||||
},
|
||||
{
|
||||
name: "note",
|
||||
align: "left",
|
||||
|
|
@ -91,12 +73,11 @@ export const useRoundDataStore = defineStore(
|
|||
let datalist: dataRowRound[] = data.map((e: dataRowRound) => {
|
||||
return {
|
||||
round:`${e.am}-${e.pmOut}`,
|
||||
am: e.am,
|
||||
amOut: e.amOut,
|
||||
pm: e.pm,
|
||||
pmOut: e.pmOut,
|
||||
am: `${e.am}-${e.amOut}`,
|
||||
pm: `${e.pm}-${e.pmOut}`,
|
||||
note: e.note === '' ? '-':e.note,
|
||||
status: e.status,
|
||||
isDefault: e.isDefault,
|
||||
};
|
||||
});
|
||||
rows.value = datalist;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ onMounted(() => {
|
|||
pmOut: "15:30",
|
||||
note: "",
|
||||
status: true,
|
||||
isDefault:true
|
||||
},
|
||||
{
|
||||
am: "08:30",
|
||||
|
|
@ -65,6 +66,7 @@ onMounted(() => {
|
|||
pmOut: "15:30",
|
||||
note: "",
|
||||
status: false,
|
||||
isDefault:true
|
||||
},
|
||||
{
|
||||
am: "09:30",
|
||||
|
|
@ -73,6 +75,7 @@ onMounted(() => {
|
|||
pmOut: "15:30",
|
||||
note: "",
|
||||
status: true,
|
||||
isDefault:true
|
||||
},
|
||||
{
|
||||
am: "10:30",
|
||||
|
|
@ -81,6 +84,7 @@ onMounted(() => {
|
|||
pmOut: "15:30",
|
||||
note: "",
|
||||
status: true,
|
||||
isDefault:false
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
|
@ -164,6 +168,7 @@ onMounted(() => {
|
|||
>
|
||||
<template v-slot:header="props">
|
||||
<q-tr :props="props">
|
||||
<q-th auto-width></q-th>
|
||||
<q-th
|
||||
v-for="col in props.cols"
|
||||
:key="col.name"
|
||||
|
|
@ -176,6 +181,16 @@ onMounted(() => {
|
|||
</template>
|
||||
<template v-slot:body="props">
|
||||
<q-tr :props="props" class="cursor-pointer">
|
||||
<q-td auto-width>
|
||||
<q-icon
|
||||
v-if="props.row.isDefault === true"
|
||||
name="mdi-bookmark"
|
||||
size="xs"
|
||||
color="primary"
|
||||
>
|
||||
<q-tooltip>เวลา Default</q-tooltip>
|
||||
</q-icon>
|
||||
</q-td>
|
||||
<q-td v-for="col in props.cols" :key="col.name" :props="props" @click.prevent="openModal(props.row,'edit')">
|
||||
<div v-if="col.name === 'status'" class="text-center">
|
||||
<q-icon
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@ const getCommandDetail = async () => {
|
|||
code.value != "c-pm-19" &&
|
||||
code.value != "c-pm-20" &&
|
||||
code.value != "c-pm-21" &&
|
||||
code.value != "c-pm-22" &&
|
||||
code.value != "c-pm-23"
|
||||
) {
|
||||
fetchReportAttachment("pdf", orderId.value);
|
||||
|
|
@ -275,7 +274,6 @@ const saveUpload = () => {
|
|||
code.value != "c-pm-19" &&
|
||||
code.value != "c-pm-20" &&
|
||||
code.value != "c-pm-21" &&
|
||||
code.value != "c-pm-22" &&
|
||||
code.value != "c-pm-23"
|
||||
) {
|
||||
await postfileTailer();
|
||||
|
|
@ -311,7 +309,6 @@ const saveDetail = () => {
|
|||
code.value != "c-pm-19" &&
|
||||
code.value != "c-pm-20" &&
|
||||
code.value != "c-pm-21" &&
|
||||
code.value != "c-pm-22" &&
|
||||
code.value != "c-pm-23"
|
||||
) {
|
||||
// ดึงรายงานในส่วนของแนบท้ายมาใหม่
|
||||
|
|
@ -410,7 +407,6 @@ const validateFormUpload = () => {
|
|||
code.value != "c-pm-19" &&
|
||||
code.value != "c-pm-20" &&
|
||||
code.value != "c-pm-21" &&
|
||||
code.value != "c-pm-22" &&
|
||||
code.value != "c-pm-23" &&
|
||||
fileOrder.value !== null &&
|
||||
fileTailer.value !== null
|
||||
|
|
@ -512,7 +508,6 @@ const viewFileUpload = async (url: string) => {
|
|||
code != 'c-pm-19' &&
|
||||
code != 'c-pm-20' &&
|
||||
code != 'c-pm-21' &&
|
||||
code != 'c-pm-22' &&
|
||||
code != 'c-pm-23'
|
||||
"
|
||||
@click="setTab('second')"
|
||||
|
|
@ -693,7 +688,6 @@ const viewFileUpload = async (url: string) => {
|
|||
code != 'c-pm-19' &&
|
||||
code != 'c-pm-20' &&
|
||||
code != 'c-pm-21' &&
|
||||
code != 'c-pm-22' &&
|
||||
code != 'c-pm-23'
|
||||
"
|
||||
>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue