Migrate to Vue 3 and Vite
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
</p>
|
||||
</div>
|
||||
<div class="field">
|
||||
<b-checkbox
|
||||
<o-checkbox
|
||||
v-model="notificationOnDay"
|
||||
@input="updateSetting({ notificationOnDay })"
|
||||
>
|
||||
@@ -27,7 +27,7 @@
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
</b-checkbox>
|
||||
</o-checkbox>
|
||||
</div>
|
||||
<p>
|
||||
{{
|
||||
@@ -39,34 +39,34 @@
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component } from "vue-property-decorator";
|
||||
import { SnackbarProgrammatic as Snackbar } from "buefy";
|
||||
import { mixins } from "vue-class-component";
|
||||
import Onboarding from "../../mixins/onboarding";
|
||||
<script lang="ts" setup>
|
||||
// import { SnackbarProgrammatic as Snackbar } from "buefy";
|
||||
import { doUpdateSetting, useUserSettings } from "@/composition/apollo/user";
|
||||
import { onMounted, ref } from "vue";
|
||||
|
||||
@Component
|
||||
export default class NotificationsOnboarding extends mixins(Onboarding) {
|
||||
notificationOnDay = true;
|
||||
const notificationOnDay = ref(true);
|
||||
|
||||
mounted(): void {
|
||||
this.doUpdateSetting({
|
||||
notificationOnDay: true,
|
||||
notificationEachWeek: false,
|
||||
notificationBeforeEvent: false,
|
||||
});
|
||||
const { loggedUser } = useUserSettings();
|
||||
|
||||
const updateSetting = async (
|
||||
variables: Record<string, unknown>
|
||||
): Promise<void> => {
|
||||
try {
|
||||
doUpdateSetting(variables);
|
||||
} catch (e: any) {
|
||||
// Snackbar.open({
|
||||
// message: e.message,
|
||||
// type: "is-danger",
|
||||
// position: "is-bottom",
|
||||
// });
|
||||
}
|
||||
};
|
||||
|
||||
async updateSetting(variables: Record<string, unknown>): Promise<void> {
|
||||
try {
|
||||
this.doUpdateSetting(variables);
|
||||
} catch (e: any) {
|
||||
Snackbar.open({
|
||||
message: e.message,
|
||||
type: "is-danger",
|
||||
position: "is-bottom",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
doUpdateSetting({
|
||||
notificationOnDay: true,
|
||||
notificationEachWeek: false,
|
||||
notificationBeforeEvent: false,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -6,27 +6,26 @@
|
||||
<span v-else>{{ title }}</span>
|
||||
</li>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from "vue-property-decorator";
|
||||
import { Route } from "vue-router";
|
||||
<script lang="ts" setup>
|
||||
import { computed } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
@Component
|
||||
export default class SettingMenuItem extends Vue {
|
||||
@Prop({ required: false, type: String }) title!: string;
|
||||
const props = defineProps<{
|
||||
title?: string;
|
||||
to: { name: string; params?: Record<string, any> };
|
||||
}>();
|
||||
|
||||
@Prop({ required: true, type: Object }) to!: Route;
|
||||
const route = useRoute();
|
||||
|
||||
get isActive(): boolean {
|
||||
if (!this.to) return false;
|
||||
if (this.to.name === this.$route.name) {
|
||||
if (this.to.params) {
|
||||
return this.to.params.identityName === this.$route.params.identityName;
|
||||
}
|
||||
return true;
|
||||
const isActive = computed((): boolean => {
|
||||
if (props.to.name === route.name) {
|
||||
if (props.to.params) {
|
||||
return props.to.params.identityName === route.params.identityName;
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<li :class="{ active: sectionActive }">
|
||||
<li>
|
||||
<router-link v-if="to" :to="to">{{ title }}</router-link>
|
||||
<b v-else>{{ title }}</b>
|
||||
<ul>
|
||||
@@ -7,34 +7,27 @@
|
||||
</ul>
|
||||
</li>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from "vue-property-decorator";
|
||||
import SettingMenuItem from "@/components/Settings/SettingMenuItem.vue";
|
||||
import { Route } from "vue-router";
|
||||
<script lang="ts" setup>
|
||||
defineProps<{
|
||||
title?: string;
|
||||
to: { name: string; params?: Record<string, any> };
|
||||
}>();
|
||||
|
||||
@Component({
|
||||
components: { SettingMenuItem },
|
||||
})
|
||||
export default class SettingMenuSection extends Vue {
|
||||
@Prop({ required: false, type: String }) title!: string;
|
||||
// const route = useRoute();
|
||||
// const slots = useSlots();
|
||||
|
||||
@Prop({ required: true, type: Object }) to!: Route;
|
||||
|
||||
get sectionActive(): boolean {
|
||||
if (this.$slots.default) {
|
||||
return this.$slots.default.some(
|
||||
({
|
||||
componentOptions: {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
propsData: { to },
|
||||
},
|
||||
}) => to && to.name === this.$route.name
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// const sectionActive = computed((): boolean => {
|
||||
// if (slots.default) {
|
||||
// return slots.default.some(
|
||||
// ({
|
||||
// componentOptions: {
|
||||
// propsData: { to },
|
||||
// },
|
||||
// }) => to && to.name === route.name
|
||||
// );
|
||||
// }
|
||||
// return false;
|
||||
// });
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -2,24 +2,24 @@
|
||||
<aside>
|
||||
<ul>
|
||||
<SettingMenuSection
|
||||
:title="$t('Account')"
|
||||
:title="t('Account')"
|
||||
:to="{ name: RouteName.ACCOUNT_SETTINGS }"
|
||||
>
|
||||
<SettingMenuItem
|
||||
:title="this.$t('General')"
|
||||
:title="t('General')"
|
||||
:to="{ name: RouteName.ACCOUNT_SETTINGS_GENERAL }"
|
||||
/>
|
||||
<SettingMenuItem
|
||||
:title="$t('Preferences')"
|
||||
:title="t('Preferences')"
|
||||
:to="{ name: RouteName.PREFERENCES }"
|
||||
/>
|
||||
<SettingMenuItem
|
||||
:title="this.$t('Notifications')"
|
||||
:title="t('Notifications')"
|
||||
:to="{ name: RouteName.NOTIFICATIONS }"
|
||||
/>
|
||||
</SettingMenuSection>
|
||||
<SettingMenuSection
|
||||
:title="$t('Profiles')"
|
||||
:title="t('Profiles')"
|
||||
:to="{ name: RouteName.IDENTITIES }"
|
||||
>
|
||||
<SettingMenuItem
|
||||
@@ -32,95 +32,76 @@
|
||||
}"
|
||||
/>
|
||||
<SettingMenuItem
|
||||
:title="$t('New profile')"
|
||||
:title="t('New profile')"
|
||||
:to="{ name: RouteName.CREATE_IDENTITY }"
|
||||
/>
|
||||
</SettingMenuSection>
|
||||
<SettingMenuSection
|
||||
v-if="
|
||||
currentUser?.role &&
|
||||
[ICurrentUserRole.MODERATOR, ICurrentUserRole.ADMINISTRATOR].includes(
|
||||
this.currentUser.role
|
||||
currentUser?.role
|
||||
)
|
||||
"
|
||||
:title="$t('Moderation')"
|
||||
:title="t('Moderation')"
|
||||
:to="{ name: RouteName.MODERATION }"
|
||||
>
|
||||
<SettingMenuItem
|
||||
:title="$t('Reports')"
|
||||
:title="t('Reports')"
|
||||
:to="{ name: RouteName.REPORTS }"
|
||||
/>
|
||||
<SettingMenuItem
|
||||
:title="$t('Moderation log')"
|
||||
:title="t('Moderation log')"
|
||||
:to="{ name: RouteName.REPORT_LOGS }"
|
||||
/>
|
||||
<SettingMenuItem :title="$t('Users')" :to="{ name: RouteName.USERS }" />
|
||||
<SettingMenuItem :title="t('Users')" :to="{ name: RouteName.USERS }" />
|
||||
<SettingMenuItem
|
||||
:title="$t('Profiles')"
|
||||
:title="t('Profiles')"
|
||||
:to="{ name: RouteName.PROFILES }"
|
||||
/>
|
||||
<SettingMenuItem
|
||||
:title="$t('Groups')"
|
||||
:title="t('Groups')"
|
||||
:to="{ name: RouteName.ADMIN_GROUPS }"
|
||||
/>
|
||||
</SettingMenuSection>
|
||||
<SettingMenuSection
|
||||
v-if="this.currentUser.role == ICurrentUserRole.ADMINISTRATOR"
|
||||
:title="$t('Admin')"
|
||||
v-if="currentUser?.role == ICurrentUserRole.ADMINISTRATOR"
|
||||
:title="t('Admin')"
|
||||
:to="{ name: RouteName.ADMIN }"
|
||||
>
|
||||
<SettingMenuItem
|
||||
:title="$t('Dashboard')"
|
||||
:title="t('Dashboard')"
|
||||
:to="{ name: RouteName.ADMIN_DASHBOARD }"
|
||||
/>
|
||||
<SettingMenuItem
|
||||
:title="$t('Instance settings')"
|
||||
:title="t('Instance settings')"
|
||||
:to="{ name: RouteName.ADMIN_SETTINGS }"
|
||||
/>
|
||||
<SettingMenuItem
|
||||
:title="$t('Federation')"
|
||||
:title="t('Federation')"
|
||||
:to="{ name: RouteName.INSTANCES }"
|
||||
/>
|
||||
</SettingMenuSection>
|
||||
</ul>
|
||||
</aside>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from "vue-property-decorator";
|
||||
<script lang="ts" setup>
|
||||
import { ICurrentUserRole } from "@/types/enums";
|
||||
import SettingMenuSection from "./SettingMenuSection.vue";
|
||||
import SettingMenuItem from "./SettingMenuItem.vue";
|
||||
import { IDENTITIES } from "../../graphql/actor";
|
||||
import { IPerson, Person } from "../../types/actor";
|
||||
import { CURRENT_USER_CLIENT } from "../../graphql/user";
|
||||
import { ICurrentUser } from "../../types/current-user.model";
|
||||
|
||||
import RouteName from "../../router/name";
|
||||
import { useCurrentUserClient } from "@/composition/apollo/user";
|
||||
import { useCurrentUserIdentities } from "@/composition/apollo/actor";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
@Component({
|
||||
components: { SettingMenuSection, SettingMenuItem },
|
||||
apollo: {
|
||||
identities: {
|
||||
query: IDENTITIES,
|
||||
update: (data) =>
|
||||
data.identities.map((identity: IPerson) => new Person(identity)),
|
||||
},
|
||||
currentUser: CURRENT_USER_CLIENT,
|
||||
},
|
||||
})
|
||||
export default class SettingsMenu extends Vue {
|
||||
profiles = [];
|
||||
const { currentUser } = useCurrentUserClient();
|
||||
const { identities } = useCurrentUserIdentities();
|
||||
|
||||
currentUser!: ICurrentUser;
|
||||
|
||||
identities!: IPerson[];
|
||||
|
||||
ICurrentUserRole = ICurrentUserRole;
|
||||
|
||||
RouteName = RouteName;
|
||||
}
|
||||
const { t } = useI18n({ useScope: "global" });
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
::v-deep a {
|
||||
:deep(a) {
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -14,15 +14,15 @@
|
||||
}}
|
||||
</p>
|
||||
<div class="has-text-centered">
|
||||
<b-select
|
||||
:loading="!config || !loggedUser"
|
||||
<o-select
|
||||
:loading="loading"
|
||||
v-model="locale"
|
||||
:placeholder="$t('Select a language')"
|
||||
>
|
||||
<option v-for="(language, lang) in langs" :value="lang" :key="lang">
|
||||
{{ language }}
|
||||
</option>
|
||||
</b-select>
|
||||
</o-select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -39,69 +39,52 @@
|
||||
timezone,
|
||||
})
|
||||
}}
|
||||
<b-message
|
||||
type="is-danger"
|
||||
v-if="!$apollo.loading && !supportedTimezone"
|
||||
<o-notification
|
||||
variant="danger"
|
||||
v-if="!loading && !supportedTimezone"
|
||||
>
|
||||
{{ $t("Your timezone {timezone} isn't supported.", { timezone }) }}
|
||||
</b-message>
|
||||
</o-notification>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Watch } from "vue-property-decorator";
|
||||
import { TIMEZONES } from "@/graphql/config";
|
||||
import { IConfig } from "@/types/config.model";
|
||||
<script lang="ts" setup>
|
||||
import { useTimezones } from "@/composition/apollo/config";
|
||||
import {
|
||||
doUpdateSetting,
|
||||
updateLocale,
|
||||
useUserSettings,
|
||||
} from "@/composition/apollo/user";
|
||||
import { saveLocaleData } from "@/utils/auth";
|
||||
import { mixins } from "vue-class-component";
|
||||
import Onboarding from "@/mixins/onboarding";
|
||||
import { UPDATE_USER_LOCALE } from "../../graphql/user";
|
||||
import { computed, onMounted, watch } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import langs from "../../i18n/langs.json";
|
||||
|
||||
@Component({
|
||||
apollo: {
|
||||
config: TIMEZONES,
|
||||
},
|
||||
})
|
||||
export default class SettingsOnboarding extends mixins(Onboarding) {
|
||||
config!: IConfig;
|
||||
const { timezones, loading } = useTimezones();
|
||||
|
||||
notificationOnDay = true;
|
||||
const { t, locale } = useI18n({ useScope: "global" });
|
||||
|
||||
locale: string | null = this.$i18n.locale;
|
||||
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
|
||||
langs: Record<string, string> = langs;
|
||||
const { loggedUser } = useUserSettings();
|
||||
|
||||
timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
onMounted(() => {
|
||||
updateLocale(locale.value);
|
||||
doUpdateSetting({ timezone });
|
||||
});
|
||||
|
||||
mounted(): void {
|
||||
this.doUpdateLocale(this.$i18n.locale);
|
||||
this.doUpdateSetting({ timezone: this.timezone });
|
||||
watch(locale, () => {
|
||||
if (locale.value) {
|
||||
updateLocale(locale.value);
|
||||
saveLocaleData(locale.value);
|
||||
}
|
||||
});
|
||||
|
||||
@Watch("locale")
|
||||
async updateLocale(): Promise<void> {
|
||||
if (this.locale) {
|
||||
this.doUpdateLocale(this.locale);
|
||||
saveLocaleData(this.locale);
|
||||
}
|
||||
}
|
||||
|
||||
private async doUpdateLocale(locale: string): Promise<void> {
|
||||
await this.$apollo.mutate({
|
||||
mutation: UPDATE_USER_LOCALE,
|
||||
variables: {
|
||||
locale,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
get supportedTimezone(): boolean {
|
||||
return this.config && this.config.timezones.includes(this.timezone);
|
||||
}
|
||||
}
|
||||
const supportedTimezone = computed((): boolean => {
|
||||
return (timezones.value ?? []).includes(timezone);
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
h3 {
|
||||
|
||||
Reference in New Issue
Block a user