2020-01-29 20:37:25 +01:00
|
|
|
<template>
|
2022-06-20 10:38:49 +02:00
|
|
|
<div>
|
|
|
|
<MkStickyContainer>
|
2023-01-13 06:58:27 +01:00
|
|
|
<template #header><MkPageHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs"/></template>
|
2023-05-18 11:45:49 +02:00
|
|
|
<MkSpacer :contentMax="900">
|
2022-06-20 10:38:49 +02:00
|
|
|
<div class="ogwlenmc">
|
|
|
|
<div v-if="tab === 'local'" class="local">
|
|
|
|
<MkInput v-model="query" :debounce="true" type="search">
|
2022-12-19 11:01:30 +01:00
|
|
|
<template #prefix><i class="ti ti-search"></i></template>
|
2022-07-20 15:24:26 +02:00
|
|
|
<template #label>{{ i18n.ts.search }}</template>
|
2022-06-20 10:38:49 +02:00
|
|
|
</MkInput>
|
|
|
|
<MkSwitch v-model="selectMode" style="margin: 8px 0;">
|
|
|
|
<template #label>Select mode</template>
|
|
|
|
</MkSwitch>
|
2023-01-06 01:41:14 +01:00
|
|
|
<div v-if="selectMode" class="_buttons">
|
2022-06-20 10:38:49 +02:00
|
|
|
<MkButton inline @click="selectAll">Select all</MkButton>
|
|
|
|
<MkButton inline @click="setCategoryBulk">Set category</MkButton>
|
2023-04-19 01:25:24 +02:00
|
|
|
<MkButton inline @click="setTagBulk">Set tag</MkButton>
|
2022-06-20 10:38:49 +02:00
|
|
|
<MkButton inline @click="addTagBulk">Add tag</MkButton>
|
|
|
|
<MkButton inline @click="removeTagBulk">Remove tag</MkButton>
|
2023-04-19 01:25:24 +02:00
|
|
|
<MkButton inline @click="setLisenceBulk">Set Lisence</MkButton>
|
2022-06-20 10:38:49 +02:00
|
|
|
<MkButton inline danger @click="delBulk">Delete</MkButton>
|
2021-12-10 13:41:37 +01:00
|
|
|
</div>
|
2022-06-20 10:38:49 +02:00
|
|
|
<MkPagination ref="emojisPaginationComponent" :pagination="pagination">
|
2022-07-20 15:24:26 +02:00
|
|
|
<template #empty><span>{{ i18n.ts.noCustomEmojis }}</span></template>
|
2022-06-20 10:38:49 +02:00
|
|
|
<template #default="{items}">
|
|
|
|
<div class="ldhfsamy">
|
|
|
|
<button v-for="emoji in items" :key="emoji.id" class="emoji _panel _button" :class="{ selected: selectedEmojis.includes(emoji.id) }" @click="selectMode ? toggleSelect(emoji) : edit(emoji)">
|
2022-12-30 03:10:38 +01:00
|
|
|
<img :src="`/emoji/${emoji.name}.webp`" class="img" :alt="emoji.name"/>
|
2022-06-20 10:38:49 +02:00
|
|
|
<div class="body">
|
|
|
|
<div class="name _monospace">{{ emoji.name }}</div>
|
|
|
|
<div class="info">{{ emoji.category }}</div>
|
|
|
|
</div>
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
</MkPagination>
|
|
|
|
</div>
|
2020-10-17 13:12:00 +02:00
|
|
|
|
2022-06-20 10:38:49 +02:00
|
|
|
<div v-else-if="tab === 'remote'" class="remote">
|
|
|
|
<FormSplit>
|
|
|
|
<MkInput v-model="queryRemote" :debounce="true" type="search">
|
2022-12-19 11:01:30 +01:00
|
|
|
<template #prefix><i class="ti ti-search"></i></template>
|
2022-07-20 15:24:26 +02:00
|
|
|
<template #label>{{ i18n.ts.search }}</template>
|
2022-06-20 10:38:49 +02:00
|
|
|
</MkInput>
|
|
|
|
<MkInput v-model="host" :debounce="true">
|
2022-07-20 15:24:26 +02:00
|
|
|
<template #label>{{ i18n.ts.host }}</template>
|
2022-06-20 10:38:49 +02:00
|
|
|
</MkInput>
|
|
|
|
</FormSplit>
|
|
|
|
<MkPagination :pagination="remotePagination">
|
2022-07-20 15:24:26 +02:00
|
|
|
<template #empty><span>{{ i18n.ts.noCustomEmojis }}</span></template>
|
2022-06-20 10:38:49 +02:00
|
|
|
<template #default="{items}">
|
|
|
|
<div class="ldhfsamy">
|
|
|
|
<div v-for="emoji in items" :key="emoji.id" class="emoji _panel _button" @click="remoteMenu(emoji, $event)">
|
2022-12-30 03:10:38 +01:00
|
|
|
<img :src="`/emoji/${emoji.name}@${emoji.host}.webp`" class="img" :alt="emoji.name"/>
|
2022-06-20 10:38:49 +02:00
|
|
|
<div class="body">
|
|
|
|
<div class="name _monospace">{{ emoji.name }}</div>
|
|
|
|
<div class="info">{{ emoji.host }}</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2021-12-10 13:41:37 +01:00
|
|
|
</div>
|
2022-06-20 10:38:49 +02:00
|
|
|
</template>
|
|
|
|
</MkPagination>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</MkSpacer>
|
|
|
|
</MkStickyContainer>
|
|
|
|
</div>
|
2020-01-29 20:37:25 +01:00
|
|
|
</template>
|
|
|
|
|
2022-01-12 16:47:05 +01:00
|
|
|
<script lang="ts" setup>
|
2023-02-16 15:09:41 +01:00
|
|
|
import { computed, defineAsyncComponent, ref, shallowRef } from 'vue';
|
2022-09-06 11:21:49 +02:00
|
|
|
import MkButton from '@/components/MkButton.vue';
|
2023-01-07 07:09:46 +01:00
|
|
|
import MkInput from '@/components/MkInput.vue';
|
2022-09-06 11:21:49 +02:00
|
|
|
import MkPagination from '@/components/MkPagination.vue';
|
2023-01-07 06:59:54 +01:00
|
|
|
import MkSwitch from '@/components/MkSwitch.vue';
|
2021-12-30 13:47:48 +01:00
|
|
|
import FormSplit from '@/components/form/split.vue';
|
2022-01-12 16:47:05 +01:00
|
|
|
import { selectFile, selectFiles } from '@/scripts/select-file';
|
2021-11-11 18:02:25 +01:00
|
|
|
import * as os from '@/os';
|
2022-01-12 16:47:05 +01:00
|
|
|
import { i18n } from '@/i18n';
|
2022-06-20 10:38:49 +02:00
|
|
|
import { definePageMetadata } from '@/scripts/page-metadata';
|
2020-10-17 13:12:00 +02:00
|
|
|
|
2023-01-03 05:37:32 +01:00
|
|
|
const emojisPaginationComponent = shallowRef<InstanceType<typeof MkPagination>>();
|
2020-01-29 20:37:25 +01:00
|
|
|
|
2022-01-12 16:47:05 +01:00
|
|
|
const tab = ref('local');
|
|
|
|
const query = ref(null);
|
|
|
|
const queryRemote = ref(null);
|
|
|
|
const host = ref(null);
|
|
|
|
const selectMode = ref(false);
|
|
|
|
const selectedEmojis = ref<string[]>([]);
|
2021-04-22 15:29:33 +02:00
|
|
|
|
2022-01-12 16:47:05 +01:00
|
|
|
const pagination = {
|
2022-01-12 18:26:10 +01:00
|
|
|
endpoint: 'admin/emoji/list' as const,
|
2022-01-12 16:47:05 +01:00
|
|
|
limit: 30,
|
|
|
|
params: computed(() => ({
|
|
|
|
query: (query.value && query.value !== '') ? query.value : null,
|
|
|
|
})),
|
|
|
|
};
|
2020-01-29 20:37:25 +01:00
|
|
|
|
2022-01-12 16:47:05 +01:00
|
|
|
const remotePagination = {
|
2022-01-12 18:26:10 +01:00
|
|
|
endpoint: 'admin/emoji/list-remote' as const,
|
2022-01-12 16:47:05 +01:00
|
|
|
limit: 30,
|
|
|
|
params: computed(() => ({
|
|
|
|
query: (queryRemote.value && queryRemote.value !== '') ? queryRemote.value : null,
|
|
|
|
host: (host.value && host.value !== '') ? host.value : null,
|
|
|
|
})),
|
|
|
|
};
|
2020-01-29 20:37:25 +01:00
|
|
|
|
2022-01-12 16:47:05 +01:00
|
|
|
const selectAll = () => {
|
|
|
|
if (selectedEmojis.value.length > 0) {
|
|
|
|
selectedEmojis.value = [];
|
|
|
|
} else {
|
|
|
|
selectedEmojis.value = emojisPaginationComponent.value.items.map(item => item.id);
|
|
|
|
}
|
|
|
|
};
|
2020-02-13 17:09:39 +01:00
|
|
|
|
2022-01-12 16:47:05 +01:00
|
|
|
const toggleSelect = (emoji) => {
|
|
|
|
if (selectedEmojis.value.includes(emoji.id)) {
|
|
|
|
selectedEmojis.value = selectedEmojis.value.filter(x => x !== emoji.id);
|
|
|
|
} else {
|
|
|
|
selectedEmojis.value.push(emoji.id);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const add = async (ev: MouseEvent) => {
|
2023-05-18 11:45:49 +02:00
|
|
|
os.popup(defineAsyncComponent(() => import('./emoji-edit-dialog.vue')), {
|
|
|
|
}, {
|
|
|
|
done: result => {
|
|
|
|
if (result.created) {
|
|
|
|
emojisPaginationComponent.value.prepend(result.created);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}, 'closed');
|
2022-01-12 16:47:05 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
const edit = (emoji) => {
|
2022-05-01 15:51:07 +02:00
|
|
|
os.popup(defineAsyncComponent(() => import('./emoji-edit-dialog.vue')), {
|
2022-06-20 10:38:49 +02:00
|
|
|
emoji: emoji,
|
2022-01-12 16:47:05 +01:00
|
|
|
}, {
|
|
|
|
done: result => {
|
|
|
|
if (result.updated) {
|
2022-05-15 15:20:01 +02:00
|
|
|
emojisPaginationComponent.value.updateItem(result.updated.id, (oldEmoji: any) => ({
|
|
|
|
...oldEmoji,
|
2022-06-20 10:38:49 +02:00
|
|
|
...result.updated,
|
2022-05-15 15:20:01 +02:00
|
|
|
}));
|
2022-01-12 16:47:05 +01:00
|
|
|
} else if (result.deleted) {
|
2022-05-15 15:20:01 +02:00
|
|
|
emojisPaginationComponent.value.removeItem((item) => item.id === emoji.id);
|
2022-01-12 16:47:05 +01:00
|
|
|
}
|
2021-12-10 13:41:37 +01:00
|
|
|
},
|
2022-01-12 16:47:05 +01:00
|
|
|
}, 'closed');
|
|
|
|
};
|
2021-12-10 13:41:37 +01:00
|
|
|
|
2022-01-12 16:47:05 +01:00
|
|
|
const im = (emoji) => {
|
|
|
|
os.apiWithDialog('admin/emoji/copy', {
|
|
|
|
emojiId: emoji.id,
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
const remoteMenu = (emoji, ev: MouseEvent) => {
|
|
|
|
os.popupMenu([{
|
|
|
|
type: 'label',
|
|
|
|
text: ':' + emoji.name + ':',
|
|
|
|
}, {
|
2022-01-28 03:39:49 +01:00
|
|
|
text: i18n.ts.import,
|
2022-12-19 11:01:30 +01:00
|
|
|
icon: 'ti ti-plus',
|
2022-06-20 10:38:49 +02:00
|
|
|
action: () => { im(emoji); },
|
2022-01-28 03:53:12 +01:00
|
|
|
}], ev.currentTarget ?? ev.target);
|
2022-01-12 16:47:05 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
const menu = (ev: MouseEvent) => {
|
|
|
|
os.popupMenu([{
|
2022-12-19 11:01:30 +01:00
|
|
|
icon: 'ti ti-download',
|
2022-01-28 03:39:49 +01:00
|
|
|
text: i18n.ts.export,
|
2022-01-12 16:47:05 +01:00
|
|
|
action: async () => {
|
|
|
|
os.api('export-custom-emojis', {
|
|
|
|
})
|
2022-12-19 11:01:30 +01:00
|
|
|
.then(() => {
|
|
|
|
os.alert({
|
|
|
|
type: 'info',
|
|
|
|
text: i18n.ts.exportRequested,
|
|
|
|
});
|
|
|
|
}).catch((err) => {
|
|
|
|
os.alert({
|
|
|
|
type: 'error',
|
|
|
|
text: err.message,
|
|
|
|
});
|
2022-01-12 16:47:05 +01:00
|
|
|
});
|
2022-06-20 10:38:49 +02:00
|
|
|
},
|
2022-01-12 16:47:40 +01:00
|
|
|
}, {
|
2022-12-19 11:01:30 +01:00
|
|
|
icon: 'ti ti-upload',
|
2022-01-28 03:39:49 +01:00
|
|
|
text: i18n.ts.import,
|
2022-01-12 16:47:40 +01:00
|
|
|
action: async () => {
|
2022-01-28 03:53:12 +01:00
|
|
|
const file = await selectFile(ev.currentTarget ?? ev.target);
|
2022-01-12 16:47:40 +01:00
|
|
|
os.api('admin/emoji/import-zip', {
|
|
|
|
fileId: file.id,
|
|
|
|
})
|
2022-12-19 11:01:30 +01:00
|
|
|
.then(() => {
|
|
|
|
os.alert({
|
|
|
|
type: 'info',
|
|
|
|
text: i18n.ts.importRequested,
|
|
|
|
});
|
|
|
|
}).catch((err) => {
|
|
|
|
os.alert({
|
|
|
|
type: 'error',
|
|
|
|
text: err.message,
|
|
|
|
});
|
2022-01-12 16:47:40 +01:00
|
|
|
});
|
2022-06-20 10:38:49 +02:00
|
|
|
},
|
2022-01-28 03:53:12 +01:00
|
|
|
}], ev.currentTarget ?? ev.target);
|
2022-01-12 16:47:05 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
const setCategoryBulk = async () => {
|
|
|
|
const { canceled, result } = await os.inputText({
|
|
|
|
title: 'Category',
|
|
|
|
});
|
|
|
|
if (canceled) return;
|
|
|
|
await os.apiWithDialog('admin/emoji/set-category-bulk', {
|
|
|
|
ids: selectedEmojis.value,
|
|
|
|
category: result,
|
|
|
|
});
|
|
|
|
emojisPaginationComponent.value.reload();
|
|
|
|
};
|
|
|
|
|
2023-04-19 01:25:24 +02:00
|
|
|
const setLisenceBulk = async () => {
|
|
|
|
const { canceled, result } = await os.inputText({
|
|
|
|
title: 'License',
|
|
|
|
});
|
|
|
|
if (canceled) return;
|
|
|
|
await os.apiWithDialog('admin/emoji/set-license-bulk', {
|
|
|
|
ids: selectedEmojis.value,
|
|
|
|
license: result,
|
|
|
|
});
|
|
|
|
emojisPaginationComponent.value.reload();
|
|
|
|
};
|
|
|
|
|
2022-01-12 16:47:05 +01:00
|
|
|
const addTagBulk = async () => {
|
|
|
|
const { canceled, result } = await os.inputText({
|
|
|
|
title: 'Tag',
|
|
|
|
});
|
|
|
|
if (canceled) return;
|
|
|
|
await os.apiWithDialog('admin/emoji/add-aliases-bulk', {
|
|
|
|
ids: selectedEmojis.value,
|
|
|
|
aliases: result.split(' '),
|
|
|
|
});
|
|
|
|
emojisPaginationComponent.value.reload();
|
|
|
|
};
|
|
|
|
|
|
|
|
const removeTagBulk = async () => {
|
|
|
|
const { canceled, result } = await os.inputText({
|
|
|
|
title: 'Tag',
|
|
|
|
});
|
|
|
|
if (canceled) return;
|
|
|
|
await os.apiWithDialog('admin/emoji/remove-aliases-bulk', {
|
|
|
|
ids: selectedEmojis.value,
|
|
|
|
aliases: result.split(' '),
|
|
|
|
});
|
|
|
|
emojisPaginationComponent.value.reload();
|
|
|
|
};
|
|
|
|
|
|
|
|
const setTagBulk = async () => {
|
|
|
|
const { canceled, result } = await os.inputText({
|
|
|
|
title: 'Tag',
|
|
|
|
});
|
|
|
|
if (canceled) return;
|
|
|
|
await os.apiWithDialog('admin/emoji/set-aliases-bulk', {
|
|
|
|
ids: selectedEmojis.value,
|
|
|
|
aliases: result.split(' '),
|
|
|
|
});
|
|
|
|
emojisPaginationComponent.value.reload();
|
|
|
|
};
|
|
|
|
|
|
|
|
const delBulk = async () => {
|
|
|
|
const { canceled } = await os.confirm({
|
|
|
|
type: 'warning',
|
2022-01-28 03:39:49 +01:00
|
|
|
text: i18n.ts.deleteConfirm,
|
2022-01-12 16:47:05 +01:00
|
|
|
});
|
|
|
|
if (canceled) return;
|
|
|
|
await os.apiWithDialog('admin/emoji/delete-bulk', {
|
|
|
|
ids: selectedEmojis.value,
|
|
|
|
});
|
|
|
|
emojisPaginationComponent.value.reload();
|
|
|
|
};
|
|
|
|
|
2022-06-20 10:38:49 +02:00
|
|
|
const headerActions = $computed(() => [{
|
|
|
|
asFullButton: true,
|
2022-12-19 11:01:30 +01:00
|
|
|
icon: 'ti ti-plus',
|
2022-06-20 10:38:49 +02:00
|
|
|
text: i18n.ts.addEmoji,
|
|
|
|
handler: add,
|
|
|
|
}, {
|
2022-12-19 11:01:30 +01:00
|
|
|
icon: 'ti ti-dots',
|
2022-06-20 10:38:49 +02:00
|
|
|
handler: menu,
|
|
|
|
}]);
|
|
|
|
|
|
|
|
const headerTabs = $computed(() => [{
|
2022-06-22 09:29:21 +02:00
|
|
|
key: 'local',
|
2022-06-20 10:38:49 +02:00
|
|
|
title: i18n.ts.local,
|
|
|
|
}, {
|
2022-06-22 09:29:21 +02:00
|
|
|
key: 'remote',
|
2022-06-20 10:38:49 +02:00
|
|
|
title: i18n.ts.remote,
|
|
|
|
}]);
|
|
|
|
|
|
|
|
definePageMetadata(computed(() => ({
|
|
|
|
title: i18n.ts.customEmojis,
|
2022-12-31 12:36:49 +01:00
|
|
|
icon: 'ti ti-icons',
|
2022-06-20 10:38:49 +02:00
|
|
|
})));
|
2020-01-29 20:37:25 +01:00
|
|
|
</script>
|
|
|
|
|
2022-12-27 10:29:39 +01:00
|
|
|
<style lang="scss" scoped>
|
2021-04-22 15:29:33 +02:00
|
|
|
.ogwlenmc {
|
|
|
|
> .local {
|
2021-12-10 13:41:37 +01:00
|
|
|
.empty {
|
|
|
|
margin: var(--margin);
|
2021-10-31 11:22:19 +01:00
|
|
|
}
|
|
|
|
|
2021-04-22 15:29:33 +02:00
|
|
|
.ldhfsamy {
|
|
|
|
display: grid;
|
|
|
|
grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
|
|
|
|
grid-gap: 12px;
|
2021-12-10 13:41:37 +01:00
|
|
|
margin: var(--margin) 0;
|
2021-04-22 15:29:33 +02:00
|
|
|
|
|
|
|
> .emoji {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
2022-01-12 16:47:05 +01:00
|
|
|
padding: 11px;
|
2021-04-22 15:29:33 +02:00
|
|
|
text-align: left;
|
2022-01-12 16:47:05 +01:00
|
|
|
border: solid 1px var(--panel);
|
2021-04-22 15:29:33 +02:00
|
|
|
|
|
|
|
&:hover {
|
2022-01-12 16:47:05 +01:00
|
|
|
border-color: var(--inputBorderHover);
|
|
|
|
}
|
|
|
|
|
|
|
|
&.selected {
|
|
|
|
border-color: var(--accent);
|
2021-04-22 15:29:33 +02:00
|
|
|
}
|
2020-01-29 20:37:25 +01:00
|
|
|
|
2021-04-22 15:29:33 +02:00
|
|
|
> .img {
|
|
|
|
width: 42px;
|
|
|
|
height: 42px;
|
|
|
|
}
|
2020-01-29 20:37:25 +01:00
|
|
|
|
2021-04-22 15:29:33 +02:00
|
|
|
> .body {
|
|
|
|
padding: 0 0 0 8px;
|
|
|
|
white-space: nowrap;
|
|
|
|
overflow: hidden;
|
2020-01-29 20:37:25 +01:00
|
|
|
|
2021-04-22 15:29:33 +02:00
|
|
|
> .name {
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
overflow: hidden;
|
|
|
|
}
|
2020-02-13 17:09:39 +01:00
|
|
|
|
2021-04-22 15:29:33 +02:00
|
|
|
> .info {
|
|
|
|
opacity: 0.5;
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
overflow: hidden;
|
2020-01-29 20:37:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-04-22 15:29:33 +02:00
|
|
|
}
|
2020-01-29 20:37:25 +01:00
|
|
|
|
2021-04-22 15:29:33 +02:00
|
|
|
> .remote {
|
2021-12-10 13:41:37 +01:00
|
|
|
.empty {
|
|
|
|
margin: var(--margin);
|
|
|
|
}
|
|
|
|
|
2021-04-22 15:29:33 +02:00
|
|
|
.ldhfsamy {
|
|
|
|
display: grid;
|
|
|
|
grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
|
|
|
|
grid-gap: 12px;
|
2021-12-10 13:41:37 +01:00
|
|
|
margin: var(--margin) 0;
|
2021-04-22 15:29:33 +02:00
|
|
|
|
|
|
|
> .emoji {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
padding: 12px;
|
|
|
|
text-align: left;
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
color: var(--accent);
|
|
|
|
}
|
2020-10-17 13:12:00 +02:00
|
|
|
|
2021-04-22 15:29:33 +02:00
|
|
|
> .img {
|
|
|
|
width: 32px;
|
|
|
|
height: 32px;
|
|
|
|
}
|
2020-01-29 20:37:25 +01:00
|
|
|
|
2021-04-22 15:29:33 +02:00
|
|
|
> .body {
|
|
|
|
padding: 0 0 0 8px;
|
|
|
|
white-space: nowrap;
|
|
|
|
overflow: hidden;
|
2020-01-29 20:37:25 +01:00
|
|
|
|
2021-04-22 15:29:33 +02:00
|
|
|
> .name {
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
overflow: hidden;
|
2020-01-29 20:37:25 +01:00
|
|
|
}
|
|
|
|
|
2021-04-22 15:29:33 +02:00
|
|
|
> .info {
|
|
|
|
opacity: 0.5;
|
|
|
|
font-size: 90%;
|
|
|
|
text-overflow: ellipsis;
|
2021-03-02 14:57:16 +01:00
|
|
|
overflow: hidden;
|
2020-01-29 20:37:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|