mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-09-23 04:34:15 -04:00
(vue) migrate <Header> to composition API with typescript to prevent accessing Nuxt context before it is initialized
This commit is contained in:
parent
065aa2ae42
commit
5b77e76a37
@ -1,3 +1,287 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { DateTime } from 'luxon';
|
||||||
|
import type { RouteLocationRaw } from 'vue-router';
|
||||||
|
|
||||||
|
import useConfig from '../composables/useConfig.ts';
|
||||||
|
import forbidden from '../src/forbidden.ts';
|
||||||
|
import type { User } from '../src/user.ts';
|
||||||
|
import { useMainStore } from '../store/index.ts';
|
||||||
|
|
||||||
|
import type SearchDialogue from '~/components/search/SearchDialogue.vue';
|
||||||
|
import { newDate } from '~/src/helpers.ts';
|
||||||
|
|
||||||
|
type HeaderTo = { link: string; name?: never } | { name: string; link?: never };
|
||||||
|
|
||||||
|
type HeaderLink = HeaderTo & {
|
||||||
|
header?: boolean;
|
||||||
|
avatar?: User | null;
|
||||||
|
icon: string;
|
||||||
|
text: string;
|
||||||
|
textLong?: string;
|
||||||
|
extra?: (string | null)[];
|
||||||
|
desktop?: boolean;
|
||||||
|
mobile?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const NounsNav = useLocaleComponent('nouns', 'NounsNav');
|
||||||
|
|
||||||
|
const { $translator: translator, $isGranted: isGranted } = useNuxtApp();
|
||||||
|
const config = useConfig();
|
||||||
|
|
||||||
|
const hoverItem = ref<HeaderLink | null>(null);
|
||||||
|
const searchDialogue = useTemplateRef<typeof SearchDialogue>('searchDialogue');
|
||||||
|
const hamburgerActive = ref(false);
|
||||||
|
const hamburgerShown = ref(false);
|
||||||
|
const censusDismissed = ref(false);
|
||||||
|
|
||||||
|
const today = newDate();
|
||||||
|
|
||||||
|
const { user } = storeToRefs(useMainStore());
|
||||||
|
const links = computed((): HeaderLink[] => {
|
||||||
|
// remember to modify ~/server/api/search.get.ts, page kind too
|
||||||
|
const links: HeaderLink[] = [];
|
||||||
|
|
||||||
|
links.push({
|
||||||
|
header: true,
|
||||||
|
name: 'index',
|
||||||
|
icon: 'home',
|
||||||
|
text: translator.translate('home.header'),
|
||||||
|
textLong: translator.translate('home.link'),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (config.pronouns.enabled) {
|
||||||
|
const extra = ['all'];
|
||||||
|
const prefixes = [...config.pronouns.sentence ? config.pronouns.sentence.prefixes : [], ''];
|
||||||
|
for (const prefix of prefixes) {
|
||||||
|
extra.push(`${prefix}/${config.pronouns.any}`);
|
||||||
|
extra.push(`${prefix}/${config.pronouns.any}:`);
|
||||||
|
if (config.pronouns.null && config.pronouns.null.routes) {
|
||||||
|
for (const route of config.pronouns.null.routes) {
|
||||||
|
extra.push(`${prefix}/${route}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (config.pronouns.mirror) {
|
||||||
|
extra.push(`${prefix}/${config.pronouns.mirror.route}`);
|
||||||
|
}
|
||||||
|
if (config.pronouns.ask) {
|
||||||
|
for (const route of config.pronouns.ask.routes) {
|
||||||
|
extra.push(`pronouns-${route}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
links.push({
|
||||||
|
name: 'pronouns',
|
||||||
|
icon: 'tags',
|
||||||
|
text: translator.translate('pronouns.header'),
|
||||||
|
textLong: translator.translate('pronouns.headerLong').replace(/(<([^>]+)>)/ig, ''),
|
||||||
|
extra,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.nouns.enabled) {
|
||||||
|
const extras = [];
|
||||||
|
for (const subroute of config.nouns.subroutes || []) {
|
||||||
|
extras.push(`/${subroute}`);
|
||||||
|
}
|
||||||
|
links.push({
|
||||||
|
name: 'nouns',
|
||||||
|
icon: 'book',
|
||||||
|
text: translator.translate('nouns.header'),
|
||||||
|
textLong: translator.translate('nouns.headerLong'),
|
||||||
|
extra: extras,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.sources.enabled) {
|
||||||
|
links.push({
|
||||||
|
name: 'sources',
|
||||||
|
icon: 'books',
|
||||||
|
text: translator.translate('sources.header'),
|
||||||
|
textLong: translator.translate('sources.headerLong'),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.faq.enabled && !config.links.split) {
|
||||||
|
links.push({
|
||||||
|
name: 'faq',
|
||||||
|
icon: 'map-marker-question',
|
||||||
|
text: translator.translate('faq.header'),
|
||||||
|
textLong: translator.translate('faq.headerLong'),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.links.enabled) {
|
||||||
|
links.push({
|
||||||
|
name: 'links',
|
||||||
|
icon: 'bookmark',
|
||||||
|
text: translator.translate('links.header'),
|
||||||
|
textLong: translator.translate('links.headerLong'),
|
||||||
|
extra: [
|
||||||
|
config.links.academicRoute ? `/${config.links.academicRoute}` : '',
|
||||||
|
config.links.translinguisticsRoute ? `/${config.links.translinguisticsRoute}` : '',
|
||||||
|
config.links.splitBlog ? '' : 'blog',
|
||||||
|
config.links.splitBlog ? '' : 'blogEntry',
|
||||||
|
config.links.splitBlog ? '' : 'blogEntryShortcut',
|
||||||
|
config.links.mediaRoute ? `/${config.links.mediaRoute}` : '',
|
||||||
|
config.links.split ? 'faq' : '',
|
||||||
|
config.english && config.english.enabled ? 'english' : '',
|
||||||
|
config.links.zine && config.links.zine.enabled ? `/${config.links.zine.route}` : '',
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (config.links.blog && config.links.splitBlog) {
|
||||||
|
links.push({
|
||||||
|
name: 'blog',
|
||||||
|
icon: 'pen-nib',
|
||||||
|
text: translator.translate('links.blog'),
|
||||||
|
extra: ['blogEntry', 'blogEntryShortcut'],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((config.terminology.enabled && config.terminology.published) ||
|
||||||
|
config.calendar?.enabled ||
|
||||||
|
config.census?.enabled ||
|
||||||
|
config.inclusive?.enabled ||
|
||||||
|
config.people?.enabled ||
|
||||||
|
(config.contact && config.contact.team?.enabled)
|
||||||
|
) {
|
||||||
|
const extra = [
|
||||||
|
config.terminology.enabled && config.terminology.published ? 'terminology' : '',
|
||||||
|
config.calendar?.enabled ? 'calendar' : '',
|
||||||
|
config.calendar?.enabled ? 'calendarDay' : '',
|
||||||
|
config.census.enabled ? 'census' : '',
|
||||||
|
config.inclusive.enabled ? 'inclusive' : '',
|
||||||
|
config.names.enabled && config.names.published ? 'names' : '',
|
||||||
|
config.people.enabled ? 'people' : '',
|
||||||
|
config.contact.enabled ? 'team' : '',
|
||||||
|
config.workshops?.enabled ? 'workshops' : '',
|
||||||
|
];
|
||||||
|
|
||||||
|
if (config.community) {
|
||||||
|
links.push({
|
||||||
|
link: `/${encodeURIComponent(config.community.route)}`,
|
||||||
|
icon: 'users',
|
||||||
|
text: translator.translate('community.header'),
|
||||||
|
textLong: translator.translate('community.headerLong'),
|
||||||
|
extra,
|
||||||
|
});
|
||||||
|
} else if (config.calendar && config.calendar.enabled) {
|
||||||
|
links.push({
|
||||||
|
name: 'calendar',
|
||||||
|
icon: 'calendar-star',
|
||||||
|
text: translator.translate('calendar.header'),
|
||||||
|
textLong: translator.translate('calendar.headerLong'),
|
||||||
|
extra,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.contact.enabled) {
|
||||||
|
links.push({
|
||||||
|
name: 'contact',
|
||||||
|
icon: 'comment-alt-smile',
|
||||||
|
text: translator.translate('contact.header'),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
links.push({
|
||||||
|
link: 'https://shop.pronouns.page',
|
||||||
|
icon: 'shopping-bag',
|
||||||
|
text: translator.translate('contact.groups.shop'),
|
||||||
|
desktop: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (config.user.enabled) {
|
||||||
|
links.push({
|
||||||
|
name: 'user',
|
||||||
|
avatar: user.value,
|
||||||
|
icon: 'user',
|
||||||
|
text: user.value ? `@${user.value.username}` : translator.translate('user.header'),
|
||||||
|
textLong: user.value ? `@${user.value.username}` : translator.translate('user.headerLong'),
|
||||||
|
extra: ['/editor', user.value ? `/@${user.value.username}` : null],
|
||||||
|
});
|
||||||
|
if (isGranted('panel')) {
|
||||||
|
links.push({
|
||||||
|
name: 'admin',
|
||||||
|
icon: 'user-cog',
|
||||||
|
text: translator.translate('admin.header'),
|
||||||
|
textLong: translator.translate('admin.header'),
|
||||||
|
extra: [
|
||||||
|
'/admin/users',
|
||||||
|
'/admin/profiles',
|
||||||
|
'/admin/timesheets',
|
||||||
|
'/admin/moderation',
|
||||||
|
'/admin/abuse-reports',
|
||||||
|
'/admin/pending-bans',
|
||||||
|
'/admin/translations/missing',
|
||||||
|
'/admin/translations/awaiting',
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return links;
|
||||||
|
});
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const showCensus = computed((): boolean => {
|
||||||
|
if (!import.meta.client) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const finished = !!parseInt(window.localStorage.getItem(`census-${config.census.edition}-finished`) || '0');
|
||||||
|
const dismissed = !!parseInt(window.localStorage.getItem(`census-${config.census.edition}-dismissed`) || '0');
|
||||||
|
const alreadyIn = route.name === 'census';
|
||||||
|
const isHomepage = route.name === 'index';
|
||||||
|
if (!config.census.enabled || !isHomepage && (finished || dismissed) || censusDismissed.value || alreadyIn) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const start = DateTime.fromISO(config.census.start).toLocal();
|
||||||
|
const end = DateTime.fromISO(config.census.end).toLocal();
|
||||||
|
const now = DateTime.utc().setZone(config.format?.timezone ?? 'utc');
|
||||||
|
return now >= start && now <= end;
|
||||||
|
});
|
||||||
|
|
||||||
|
const buildRoute = (link: HeaderLink): RouteLocationRaw => {
|
||||||
|
if (link.name !== undefined) {
|
||||||
|
return { name: link.name };
|
||||||
|
}
|
||||||
|
return link.link;
|
||||||
|
};
|
||||||
|
const isActiveRoute = (link: HeaderLink) => {
|
||||||
|
return route.name === link.name ||
|
||||||
|
link.extra && route.name && link.extra.includes((route.name as string).split(':')[0]) ||
|
||||||
|
(link.extra || []).includes(decodeURIComponent(route.path)) ||
|
||||||
|
(link.extra || []).filter((x) => x && (
|
||||||
|
decodeURIComponent(route.path).startsWith(`${x}/`) ||
|
||||||
|
decodeURIComponent(route.path).startsWith(`${x}:`))).length;
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
document.addEventListener('click', documentClicked);
|
||||||
|
updateShown();
|
||||||
|
window.addEventListener('scroll', updateShown);
|
||||||
|
});
|
||||||
|
onUnmounted(() => {
|
||||||
|
document.removeEventListener('click', documentClicked);
|
||||||
|
document.removeEventListener('scroll', updateShown);
|
||||||
|
});
|
||||||
|
|
||||||
|
const documentClicked = (): void => {
|
||||||
|
if (hamburgerActive.value) {
|
||||||
|
hamburgerActive.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const updateShown = (): void => {
|
||||||
|
const st = document.body.scrollTop || document.querySelector('html')!.scrollTop;
|
||||||
|
hamburgerShown.value = st > 300;
|
||||||
|
};
|
||||||
|
const dismissCensus = (): void => {
|
||||||
|
window.localStorage.setItem(`census-${config.census.edition}-dismissed`, '1');
|
||||||
|
censusDismissed.value = true;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="config.header" class="mb-lg-4">
|
<div v-if="config.header" class="mb-lg-4">
|
||||||
<header @mouseleave="hoverItem = null">
|
<header @mouseleave="hoverItem = null">
|
||||||
@ -249,302 +533,6 @@
|
|||||||
</ClientOnly>
|
</ClientOnly>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { DateTime } from 'luxon';
|
|
||||||
import { mapState } from 'pinia';
|
|
||||||
import type { RouteLocationRaw } from 'vue-router';
|
|
||||||
|
|
||||||
import useConfig from '../composables/useConfig.ts';
|
|
||||||
import forbidden from '../src/forbidden.ts';
|
|
||||||
import { newDate } from '../src/helpers.ts';
|
|
||||||
import type { User } from '../src/user.ts';
|
|
||||||
import { useMainStore } from '../store/index.ts';
|
|
||||||
|
|
||||||
import type SearchDialogue from '~/components/search/SearchDialogue.vue';
|
|
||||||
|
|
||||||
type HeaderTo = { link: string; name?: never } | { name: string; link?: never };
|
|
||||||
|
|
||||||
type HeaderLink = HeaderTo & {
|
|
||||||
header?: boolean;
|
|
||||||
avatar?: User | null;
|
|
||||||
icon: string;
|
|
||||||
text: string;
|
|
||||||
textLong?: string;
|
|
||||||
extra?: (string | null)[];
|
|
||||||
desktop?: boolean;
|
|
||||||
mobile?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
components: { NounsNav: useLocaleComponent('nouns', 'NounsNav') },
|
|
||||||
setup() {
|
|
||||||
const hoverItem = ref<HeaderLink | null>(null);
|
|
||||||
return {
|
|
||||||
config: useConfig(),
|
|
||||||
hoverItem,
|
|
||||||
searchDialogue: useTemplateRef<typeof SearchDialogue>('searchDialogue'),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
today: newDate(),
|
|
||||||
hamburgerActive: false,
|
|
||||||
hamburgerShown: false,
|
|
||||||
censusDismissed: false,
|
|
||||||
forbidden,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapState(useMainStore, [
|
|
||||||
'user',
|
|
||||||
'darkMode',
|
|
||||||
]),
|
|
||||||
links(): HeaderLink[] {
|
|
||||||
// remember to modify ~/server/api/search.get.ts, page kind too
|
|
||||||
|
|
||||||
const links: HeaderLink[] = [];
|
|
||||||
|
|
||||||
links.push({
|
|
||||||
header: true,
|
|
||||||
name: 'index',
|
|
||||||
icon: 'home',
|
|
||||||
text: this.$t('home.header'),
|
|
||||||
textLong: this.$t('home.link'),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.config.pronouns.enabled) {
|
|
||||||
const extra = ['all'];
|
|
||||||
const prefixes = [...this.config.pronouns.sentence ? this.config.pronouns.sentence.prefixes : [], ''];
|
|
||||||
for (const prefix of prefixes) {
|
|
||||||
extra.push(`${prefix}/${this.config.pronouns.any}`);
|
|
||||||
extra.push(`${prefix}/${this.config.pronouns.any}:`);
|
|
||||||
if (this.config.pronouns.null && this.config.pronouns.null.routes) {
|
|
||||||
for (const route of this.config.pronouns.null.routes) {
|
|
||||||
extra.push(`${prefix}/${route}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.config.pronouns.mirror) {
|
|
||||||
extra.push(`${prefix}/${this.config.pronouns.mirror.route}`);
|
|
||||||
}
|
|
||||||
if (this.config.pronouns.ask) {
|
|
||||||
for (const route of this.config.pronouns.ask.routes) {
|
|
||||||
extra.push(`pronouns-${route}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
links.push({
|
|
||||||
name: 'pronouns',
|
|
||||||
icon: 'tags',
|
|
||||||
text: this.$t('pronouns.header'),
|
|
||||||
textLong: this.$t('pronouns.headerLong').replace(/(<([^>]+)>)/ig, ''),
|
|
||||||
extra,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.config.nouns.enabled) {
|
|
||||||
const extras = [];
|
|
||||||
for (const subroute of this.config.nouns.subroutes || []) {
|
|
||||||
extras.push(`/${subroute}`);
|
|
||||||
}
|
|
||||||
links.push({
|
|
||||||
name: 'nouns',
|
|
||||||
icon: 'book',
|
|
||||||
text: this.$t('nouns.header'),
|
|
||||||
textLong: this.$t('nouns.headerLong'),
|
|
||||||
extra: extras,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.config.sources.enabled) {
|
|
||||||
links.push({
|
|
||||||
name: 'sources',
|
|
||||||
icon: 'books',
|
|
||||||
text: this.$t('sources.header'),
|
|
||||||
textLong: this.$t('sources.headerLong'),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.config.faq.enabled && !this.config.links.split) {
|
|
||||||
links.push({
|
|
||||||
name: 'faq',
|
|
||||||
icon: 'map-marker-question',
|
|
||||||
text: this.$t('faq.header'),
|
|
||||||
textLong: this.$t('faq.headerLong'),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.config.links.enabled) {
|
|
||||||
links.push({
|
|
||||||
name: 'links',
|
|
||||||
icon: 'bookmark',
|
|
||||||
text: this.$t('links.header'),
|
|
||||||
textLong: this.$t('links.headerLong'),
|
|
||||||
extra: [
|
|
||||||
this.config.links.academicRoute ? `/${this.config.links.academicRoute}` : '',
|
|
||||||
this.config.links.translinguisticsRoute ? `/${this.config.links.translinguisticsRoute}` : '',
|
|
||||||
this.config.links.splitBlog ? '' : 'blog',
|
|
||||||
this.config.links.splitBlog ? '' : 'blogEntry',
|
|
||||||
this.config.links.splitBlog ? '' : 'blogEntryShortcut',
|
|
||||||
this.config.links.mediaRoute ? `/${this.config.links.mediaRoute}` : '',
|
|
||||||
this.config.links.split ? 'faq' : '',
|
|
||||||
this.config.english && this.config.english.enabled ? 'english' : '',
|
|
||||||
this.config.links.zine && this.config.links.zine.enabled ? `/${this.config.links.zine.route}` : '',
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.config.links.blog && this.config.links.splitBlog) {
|
|
||||||
links.push({
|
|
||||||
name: 'blog',
|
|
||||||
icon: 'pen-nib',
|
|
||||||
text: this.$t('links.blog'),
|
|
||||||
extra: ['blogEntry', 'blogEntryShortcut'],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.config.terminology.enabled && this.config.terminology.published ||
|
|
||||||
this.config.calendar && this.config.calendar.enabled ||
|
|
||||||
this.config.census && this.config.census.enabled ||
|
|
||||||
this.config.inclusive && this.config.inclusive.enabled ||
|
|
||||||
this.config.people && this.config.people.enabled ||
|
|
||||||
this.config.contact && this.config.contact.team && this.config.contact.team.enabled
|
|
||||||
) {
|
|
||||||
const extra = [
|
|
||||||
this.config.terminology.enabled && this.config.terminology.published ? 'terminology' : '',
|
|
||||||
this.config.calendar?.enabled ? 'calendar' : '',
|
|
||||||
this.config.calendar?.enabled ? 'calendarDay' : '',
|
|
||||||
this.config.census.enabled ? 'census' : '',
|
|
||||||
this.config.inclusive.enabled ? 'inclusive' : '',
|
|
||||||
this.config.names.enabled && this.config.names.published ? 'names' : '',
|
|
||||||
this.config.people.enabled ? 'people' : '',
|
|
||||||
this.config.contact.enabled ? 'team' : '',
|
|
||||||
this.config.workshops?.enabled ? 'workshops' : '',
|
|
||||||
];
|
|
||||||
|
|
||||||
if (this.config.community) {
|
|
||||||
links.push({
|
|
||||||
link: `/${encodeURIComponent(this.config.community.route)}`,
|
|
||||||
icon: 'users',
|
|
||||||
text: this.$t('community.header'),
|
|
||||||
textLong: this.$t('community.headerLong'),
|
|
||||||
extra,
|
|
||||||
});
|
|
||||||
} else if (this.config.calendar && this.config.calendar.enabled) {
|
|
||||||
links.push({
|
|
||||||
name: 'calendar',
|
|
||||||
icon: 'calendar-star',
|
|
||||||
text: this.$t('calendar.header'),
|
|
||||||
textLong: this.$t('calendar.headerLong'),
|
|
||||||
extra,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.config.contact.enabled) {
|
|
||||||
links.push({
|
|
||||||
name: 'contact',
|
|
||||||
icon: 'comment-alt-smile',
|
|
||||||
text: this.$t('contact.header'),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
links.push({
|
|
||||||
link: 'https://shop.pronouns.page',
|
|
||||||
icon: 'shopping-bag',
|
|
||||||
text: this.$t('contact.groups.shop'),
|
|
||||||
desktop: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.config.user.enabled) {
|
|
||||||
const user = this.$user();
|
|
||||||
links.push({
|
|
||||||
name: 'user',
|
|
||||||
avatar: this.$user(),
|
|
||||||
icon: 'user',
|
|
||||||
text: this.user ? `@${this.user.username}` : this.$t('user.header'),
|
|
||||||
textLong: this.user ? `@${this.user.username}` : this.$t('user.headerLong'),
|
|
||||||
extra: ['/editor', user ? `/@${user.username}` : null],
|
|
||||||
});
|
|
||||||
if (this.$isGranted('panel')) {
|
|
||||||
links.push({
|
|
||||||
name: 'admin',
|
|
||||||
icon: 'user-cog',
|
|
||||||
text: this.$t('admin.header'),
|
|
||||||
textLong: this.$t('admin.header'),
|
|
||||||
extra: [
|
|
||||||
'/admin/users',
|
|
||||||
'/admin/profiles',
|
|
||||||
'/admin/timesheets',
|
|
||||||
'/admin/moderation',
|
|
||||||
'/admin/abuse-reports',
|
|
||||||
'/admin/pending-bans',
|
|
||||||
'/admin/translations/missing',
|
|
||||||
'/admin/translations/awaiting',
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return links;
|
|
||||||
},
|
|
||||||
showCensus(): boolean {
|
|
||||||
if (!import.meta.client) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const finished = !!parseInt(window.localStorage.getItem(`census-${this.config.census.edition}-finished`) || '0');
|
|
||||||
const dismissed = !!parseInt(window.localStorage.getItem(`census-${this.config.census.edition}-dismissed`) || '0');
|
|
||||||
const alreadyIn = this.$route.name === 'census';
|
|
||||||
const isHomepage = this.$route.name === 'index';
|
|
||||||
if (!this.config.census.enabled || !isHomepage && (finished || dismissed) || this.censusDismissed || alreadyIn) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const start = DateTime.fromISO(this.config.census.start).toLocal();
|
|
||||||
const end = DateTime.fromISO(this.config.census.end).toLocal();
|
|
||||||
const now = DateTime.utc().setZone(this.config.format?.timezone ?? 'utc');
|
|
||||||
return now >= start && now <= end;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
document.addEventListener('click', this.documentClicked);
|
|
||||||
this.updateShown();
|
|
||||||
window.addEventListener('scroll', this.updateShown);
|
|
||||||
},
|
|
||||||
unmounted() {
|
|
||||||
document.removeEventListener('click', this.documentClicked);
|
|
||||||
document.removeEventListener('scroll', this.updateShown);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
buildRoute(link: HeaderLink): RouteLocationRaw {
|
|
||||||
if (link.name !== undefined) {
|
|
||||||
return { name: link.name };
|
|
||||||
}
|
|
||||||
return link.link;
|
|
||||||
},
|
|
||||||
isActiveRoute(link: HeaderLink) {
|
|
||||||
return this.$route.name === link.name ||
|
|
||||||
link.extra && this.$route.name && link.extra.includes((this.$route.name as string).split(':')[0]) ||
|
|
||||||
(link.extra || []).includes(decodeURIComponent(this.$route.path)) ||
|
|
||||||
(link.extra || []).filter((x) => x && (
|
|
||||||
decodeURIComponent(this.$route.path).startsWith(`${x}/`) ||
|
|
||||||
decodeURIComponent(this.$route.path).startsWith(`${x}:`))).length;
|
|
||||||
},
|
|
||||||
documentClicked(): void {
|
|
||||||
if (this.hamburgerActive) {
|
|
||||||
this.hamburgerActive = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateShown(): void {
|
|
||||||
const st = document.body.scrollTop || document.querySelector('html')!.scrollTop;
|
|
||||||
this.hamburgerShown = st > 300;
|
|
||||||
},
|
|
||||||
dismissCensus(): void {
|
|
||||||
window.localStorage.setItem(`census-${this.config.census.edition}-dismissed`, '1');
|
|
||||||
this.censusDismissed = true;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import "assets/variables";
|
@import "assets/variables";
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user