288 lines
8.4 KiB
Vue
288 lines
8.4 KiB
Vue
<template>
|
|
<pn-page-card>
|
|
<template #title>
|
|
{{$t('mask__title')}}
|
|
</template>
|
|
|
|
<template #footer>
|
|
<q-btn
|
|
rounded color="primary"
|
|
class="w100 q-mt-md q-mb-xs fix-disabled-btn"
|
|
@click="updateCompanies()"
|
|
>
|
|
{{ $t('mask__btn_ok') }}
|
|
</q-btn>
|
|
</template>
|
|
|
|
<pn-scroll-list>
|
|
<template #card-body-header>
|
|
<div class="q-ma-sm q-pa-sm bg-grey-11 flex no-wrap items-center" style="border-radius: var(--top-radius);">
|
|
<q-icon name="mdi-information q-pr-xs" size="sm" color="primary"/>
|
|
<span class="text-caption">
|
|
{{ $t('mask__info_block')}}
|
|
</span>
|
|
</div>
|
|
</template>
|
|
<q-table
|
|
flat
|
|
:rows="displayCompanies"
|
|
:columns="tableColumns"
|
|
hide-pagination
|
|
:pagination="{ rowsPerPage: 0 }"
|
|
dense
|
|
row-key="id"
|
|
style="max-width: 100% !important"
|
|
>
|
|
<template #header>
|
|
<q-tr>
|
|
<q-th style="width: 10%">
|
|
<q-icon name="mdi-domino-mask" size="sm"/>
|
|
</q-th>
|
|
<q-th style="width: 45%">
|
|
<span class="text-bold">
|
|
{{ $t('mask__table_header_company') }}
|
|
</span>
|
|
</q-th>
|
|
<q-th style="width: 45%">
|
|
<span class="text-bold">
|
|
{{ $t('mask__table_header_visible') }}
|
|
<q-btn
|
|
flat
|
|
@click="showDialogHelp=true"
|
|
color="primary"
|
|
dense round
|
|
size="sm"
|
|
icon="mdi-help-circle-outline"
|
|
/>
|
|
</span>
|
|
</q-th>
|
|
</q-tr>
|
|
</template>
|
|
|
|
<template #body="props">
|
|
<q-tr :props="props">
|
|
<q-td key="checkbox" :props="props">
|
|
<q-toggle
|
|
v-model="props.row.masked"
|
|
size="sm"
|
|
:color="props.row.masked ? 'red' : 'brand'"
|
|
/>
|
|
</q-td>
|
|
<q-td key="name" :props="props">
|
|
{{ props.row.name }}
|
|
</q-td>
|
|
<q-td key="visible" :props="props">
|
|
<q-select
|
|
v-if="props.row.masked"
|
|
v-model="props.row.company_list"
|
|
multiple
|
|
:options="companiesSelect(props.row.id)"
|
|
option-value="id"
|
|
emit-value
|
|
dense
|
|
borderless
|
|
dropdown-icon="mdi-plus"
|
|
class="fix-select"
|
|
:label-slot="!props.row.hasFocus && !props.row.isMenuOpen && (props.row.company_list.length === 0)"
|
|
@popup-show="props.row.isMenuOpen = true"
|
|
@popup-hide="props.row.isMenuOpen = false"
|
|
@focus="props.row.hasFocus = true"
|
|
@blur="props.row.hasFocus = false"
|
|
>
|
|
<template #label>
|
|
<span
|
|
v-if="(!props.row.hasFocus || !props.row.isMenuOpen) && (props.row.company_list.length === 0)"
|
|
class="q-field__label"
|
|
>
|
|
{{ $t('mask__table_visible_none') }}
|
|
</span>
|
|
</template>
|
|
<template #selected>
|
|
<div
|
|
v-for="id in props.row.company_list"
|
|
:key=id
|
|
class="q-pa-xs"
|
|
>
|
|
<pn-auto-avatar
|
|
:img="getCompanyById(id)?.logo"
|
|
:name="getCompanyById(id)?.name"
|
|
size="md"
|
|
type="rounded"
|
|
/>
|
|
</div>
|
|
</template>
|
|
<template #option="scope">
|
|
<q-item v-bind="scope.itemProps">
|
|
<q-item-section avatar>
|
|
<pn-auto-avatar
|
|
:img="scope.opt.logo"
|
|
:name="scope.opt.name"
|
|
size="md"
|
|
type="rounded"
|
|
/>
|
|
</q-item-section>
|
|
<q-item-section>
|
|
<q-item-label>{{ scope.opt.name }}</q-item-label>
|
|
</q-item-section>
|
|
</q-item>
|
|
</template>
|
|
</q-select>
|
|
<span
|
|
v-else
|
|
>
|
|
{{ $t('mask__table_visible_all') }}
|
|
</span>
|
|
</q-td>
|
|
|
|
</q-tr>
|
|
</template>
|
|
</q-table>
|
|
<div class="q-py-none flex column w100" style="min-height: 18px"/>
|
|
</pn-scroll-list>
|
|
|
|
<q-dialog v-model="showDialogHelp">
|
|
<q-card class="q-ma-sm w100">
|
|
<q-card-section class="row items-center q-pb-none">
|
|
<span class="text-h6">
|
|
<q-icon name="mdi-domino-mask"/>
|
|
{{ $t('mask__help_title')}}
|
|
</span>
|
|
<q-space />
|
|
<q-btn icon="close" flat round dense v-close-popup />
|
|
</q-card-section>
|
|
<q-card-section class="q-pt-sm">
|
|
<p>{{ $t('mask__help_message1')}}</p>
|
|
<p>{{ $t('mask__help_message2')}}</p>
|
|
</q-card-section>
|
|
</q-card>
|
|
</q-dialog>
|
|
</pn-page-card>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, computed, watch } from 'vue'
|
|
import { useCompaniesStore } from 'stores/companies'
|
|
import { useRouter } from 'vue-router'
|
|
|
|
const showDialogHelp = ref<boolean>(false)
|
|
const companiesStore = useCompaniesStore()
|
|
const router = useRouter()
|
|
|
|
const companies = computed(() => companiesStore.companies)
|
|
const companiesMask = computed(() => companiesStore.companiesMask)
|
|
|
|
const tableColumns = [
|
|
{ name: 'checkbox', field: 'checkbox', label: 'checkbox', sortable: false, style: "width: 10%" },
|
|
{ name: 'name', field: 'name', align: 'left' as const, label: 'name', sortable: false, style: "width: 45% !important; text-wrap: auto" },
|
|
{ name: 'visible', field: 'visible', align: 'center' as const, label: 'visible', sortable: false, style: "width: 45% !important" }
|
|
]
|
|
|
|
interface DisplayCompany {
|
|
id: number
|
|
name: string
|
|
logo?: string
|
|
masked: boolean
|
|
company_list: number[],
|
|
isMenuOpen: boolean
|
|
hasFocus: boolean
|
|
}
|
|
|
|
const displayCompanies = ref<DisplayCompany[]>([])
|
|
|
|
watch(
|
|
() => [companies.value, companiesMask.value],
|
|
() => {
|
|
updateDisplayCompanies()
|
|
},
|
|
{ immediate: true, deep: true }
|
|
)
|
|
|
|
function updateDisplayCompanies() {
|
|
if (companies.value.length === 0 || companiesMask.value.length === 0) return
|
|
|
|
displayCompanies.value = companies.value
|
|
.filter(el => !el.is_own)
|
|
.map(el => ({
|
|
id: el.id,
|
|
name: el.name,
|
|
logo: el.logo ?? '',
|
|
masked: companiesStore.checkCompanyMasked(el.id),
|
|
company_list: getList(el.id),
|
|
isMenuOpen: false,
|
|
hasFocus: false
|
|
}))
|
|
}
|
|
|
|
function getList (companyId: number) {
|
|
const company = companiesMask.value.find(el => Number(el.company_id) === companyId)
|
|
return company?.company_list ?? []
|
|
}
|
|
|
|
const mask = computed(() => displayCompanies.value
|
|
.filter(el => el.masked)
|
|
.map(el => ({
|
|
company_id: el.id,
|
|
company_list: el.company_list.sort(compareNumbers)
|
|
}))
|
|
.sort((a, b) => compareNumbers(a.company_id, b.company_id))
|
|
)
|
|
|
|
function getCompanyById (id: number) {
|
|
return companies.value.find(c => c.id === id)
|
|
}
|
|
|
|
function companiesSelect (id :number) {
|
|
return displayCompanies.value
|
|
.map(el => ({
|
|
id: el.id,
|
|
name: el.name,
|
|
logo: el.logo
|
|
}))
|
|
.filter(el => el.id !== id)
|
|
}
|
|
|
|
async function updateCompanies () {
|
|
await companiesStore.updateMask(mask.value)
|
|
router.back()
|
|
}
|
|
|
|
function compareNumbers (a: number, b: number): number {
|
|
if (Number.isNaN(a)) return Number.isNaN(b) ? 0 : 1
|
|
if (Number.isNaN(b)) return -1
|
|
|
|
if (a === b) return 0
|
|
return a < b ? -1 : 1
|
|
}
|
|
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
|
|
.fix-select :deep(.q-field__control) {
|
|
align-items: center;
|
|
}
|
|
|
|
.fix-select :deep(.q-field__native) {
|
|
justify-content: flex-end;
|
|
}
|
|
|
|
.fix-select :deep(.q-field__label.no-pointer-events) {
|
|
left: 50% !important;
|
|
transform: translateX(-50%) !important;
|
|
}
|
|
|
|
:deep(.fix-select .q-icon) {
|
|
color: $green-14 !important;
|
|
}
|
|
|
|
|
|
|
|
:deep(.masked .q-icon) {
|
|
color: red;
|
|
}
|
|
|
|
:deep(.unmasked .q-icon) {
|
|
color: 'brand';
|
|
}
|
|
</style>
|