155 lines
4.6 KiB
Vue
155 lines
4.6 KiB
Vue
<script setup>
|
|
import axios from 'axios';
|
|
import { useQuasar } from 'quasar';
|
|
import { computed, ref } from 'vue';
|
|
import { useI18n } from 'vue-i18n';
|
|
import { useRoute } from 'vue-router';
|
|
|
|
import CrudModel from 'components/CrudModel.vue';
|
|
|
|
const $props = defineProps({
|
|
id: {
|
|
type: Number,
|
|
required: false,
|
|
default: null,
|
|
},
|
|
});
|
|
|
|
const route = useRoute();
|
|
const { t } = useI18n();
|
|
const quasar = useQuasar();
|
|
const entityId = computed(() => $props.id || route.params.id);
|
|
const URL_KEY = 'NotificationSubscriptions';
|
|
const active = ref(new Map());
|
|
const available = ref(new Map());
|
|
|
|
async function toggleNotification(notification) {
|
|
try {
|
|
if (!notification.active) {
|
|
await axios.delete(`${URL_KEY}/${notification.id}`);
|
|
swapEntry(active.value, available.value, notification.notificationFk);
|
|
} else {
|
|
const { data } = await axios.post(URL_KEY, {
|
|
notificationFk: notification.notificationFk,
|
|
userFk: entityId.value,
|
|
});
|
|
notification.id = data.id;
|
|
|
|
swapEntry(available.value, active.value, notification.notificationFk);
|
|
}
|
|
|
|
quasar.notify({
|
|
type: 'positive',
|
|
message: t(
|
|
`worker.notificationsManager.${notification.active ? '' : 'un'}subscribed`
|
|
),
|
|
});
|
|
} catch (e) {
|
|
notification.active = !notification.active;
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
const swapEntry = (from, to, key) => {
|
|
const element = from.get(key);
|
|
to.set(key, element);
|
|
from.delete(key);
|
|
};
|
|
|
|
function setNotifications(data) {
|
|
active.value = new Map(data.active);
|
|
available.value = new Map(data.available);
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<CrudModel
|
|
auto-load
|
|
:data-key="URL_KEY"
|
|
:url="`${URL_KEY}/${entityId}/getList`"
|
|
:default-reset="false"
|
|
:default-remove="false"
|
|
:default-save="false"
|
|
@on-fetch="(data) => data && setNotifications(data)"
|
|
search-url="notifications"
|
|
>
|
|
<template #body>
|
|
<div
|
|
v-for="(notifications, index) in [
|
|
[...active.values()],
|
|
[...available.values()],
|
|
]"
|
|
:key="notifications"
|
|
>
|
|
<QList class="notificationList">
|
|
<TransitionGroup>
|
|
<QCard
|
|
v-for="notification in notifications"
|
|
:key="notification.notificationFk"
|
|
class="q-pa-md"
|
|
>
|
|
<QItem>
|
|
<QItemSection avatar>
|
|
<QBtn
|
|
round
|
|
icon="mail"
|
|
:color="notification.active ? 'green' : 'grey'"
|
|
/>
|
|
</QItemSection>
|
|
<QItemSection>
|
|
<QItemLabel>{{ notification.name }}</QItemLabel>
|
|
<QItemLabel caption>
|
|
{{ notification.description }}
|
|
</QItemLabel>
|
|
</QItemSection>
|
|
<QToggle
|
|
checked-icon="check"
|
|
unchecked-icon="close"
|
|
v-model="notification.active"
|
|
color="green"
|
|
@update:model-value="toggleNotification(notification)"
|
|
/>
|
|
</QItem>
|
|
</QCard>
|
|
</TransitionGroup>
|
|
</QList>
|
|
<QSeparator
|
|
color="primary"
|
|
class="q-my-lg"
|
|
v-if="!index && available.size && active.size"
|
|
/>
|
|
</div>
|
|
</template>
|
|
</CrudModel>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
.notificationList {
|
|
display: grid;
|
|
grid-template-columns: repeat(4, 1fr);
|
|
grid-gap: 10px;
|
|
|
|
.v-enter-active,
|
|
.v-leave-active {
|
|
transition: opacity 0.5s ease;
|
|
}
|
|
|
|
.v-enter-from,
|
|
.v-leave-to {
|
|
opacity: 0;
|
|
}
|
|
}
|
|
|
|
@media (max-width: $breakpoint-md) {
|
|
.notificationList {
|
|
grid-template-columns: repeat(2, 1fr);
|
|
}
|
|
}
|
|
|
|
@media (max-width: $breakpoint-xs) {
|
|
.notificationList {
|
|
grid-template-columns: repeat(1, 1fr);
|
|
}
|
|
}
|
|
</style>
|