feat: Add a section in admin SettingsView to manage external links
Related to #1764
This commit is contained in:
@@ -200,6 +200,11 @@ export const ADMIN_SETTINGS_FRAGMENT = gql`
|
||||
instanceLongDescription
|
||||
instanceSlogan
|
||||
contact
|
||||
externalUrls {
|
||||
label
|
||||
url
|
||||
enabled
|
||||
}
|
||||
instanceLogo {
|
||||
uuid
|
||||
url
|
||||
@@ -246,6 +251,7 @@ export const SAVE_ADMIN_SETTINGS = gql`
|
||||
$instanceLongDescription: String
|
||||
$instanceSlogan: String
|
||||
$contact: String
|
||||
$externalUrls: [ExternalUrlInput]
|
||||
$instanceLogo: MediaInput
|
||||
$instanceFavicon: MediaInput
|
||||
$defaultPicture: MediaInput
|
||||
@@ -268,6 +274,7 @@ export const SAVE_ADMIN_SETTINGS = gql`
|
||||
instanceLongDescription: $instanceLongDescription
|
||||
instanceSlogan: $instanceSlogan
|
||||
contact: $contact
|
||||
externalUrls: $externalUrls
|
||||
instanceLogo: $instanceLogo
|
||||
instanceFavicon: $instanceFavicon
|
||||
defaultPicture: $defaultPicture
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
"Add / Remove\u2026": "Add / Remove\u2026",
|
||||
"Add a contact": "Add a contact",
|
||||
"Add a new post": "Add a new post",
|
||||
"Add a new link": "Add a new link",
|
||||
"Add a note": "Add a note",
|
||||
"Add a recipient": "Add a recipient",
|
||||
"Add a todo": "Add a todo",
|
||||
@@ -345,6 +346,7 @@
|
||||
"Delete this discussion": "Delete this discussion",
|
||||
"Delete this identity": "Delete this identity",
|
||||
"Delete your identity": "Delete your identity",
|
||||
"Delete this link": "Delete this link",
|
||||
"Delete {eventTitle}": "Delete {eventTitle}",
|
||||
"Delete {preferredUsername}": "Delete {preferredUsername}",
|
||||
"Deleting comment": "Deleting comment",
|
||||
@@ -453,6 +455,7 @@
|
||||
"Explore events": "Explore events",
|
||||
"Explore!": "Explore!",
|
||||
"Export": "Export",
|
||||
"External links":"External links",
|
||||
"External provider URL": "External provider URL",
|
||||
"External registration": "External registration",
|
||||
"Failed to get location.": "Failed to get location.",
|
||||
@@ -1283,6 +1286,7 @@
|
||||
"This profile is from another instance, the informations shown here may be incomplete.": "This profile is from another instance, the informations shown here may be incomplete.",
|
||||
"This profile is located on this instance, so you need to {access_the_corresponding_account} to suspend it.": "This profile is located on this instance, so you need to {access_the_corresponding_account} to suspend it.",
|
||||
"This profile was not found": "This profile was not found",
|
||||
"This section lets you add links to external websites to the menu.":"This section lets you add links to external websites to the menu.",
|
||||
"This setting will be used to display the website and send you emails in the correct language.": "This setting will be used to display the website and send you emails in the correct language.",
|
||||
"This user doesn't have any profiles": "This user doesn't have any profiles",
|
||||
"This user was not found": "This user was not found",
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
"Add an instance": "Ajouter une instance",
|
||||
"Add a contact": "Ajouter un contact",
|
||||
"Add a new post": "Ajouter un nouveau billet",
|
||||
"Add a new link": "Ajouter un nouveau lien",
|
||||
"Add a note": "Ajouter une note",
|
||||
"Add a recipient": "Ajouter un·e destinataire",
|
||||
"Add a todo": "Ajouter un todo",
|
||||
@@ -337,6 +338,7 @@
|
||||
"Delete this conversation": "Supprimer cette conversation",
|
||||
"Delete this discussion": "Supprimer cette discussion",
|
||||
"Delete this identity": "Supprimer cette identité",
|
||||
"Delete this link": "Supprimer ce lien",
|
||||
"Delete your identity": "Supprimer votre identité",
|
||||
"Delete {eventTitle}": "Supprimer {eventTitle}",
|
||||
"Delete {preferredUsername}": "Supprimer {preferredUsername}",
|
||||
@@ -448,6 +450,7 @@
|
||||
"Explore!": "Explorer !",
|
||||
"Explore": "Explorer",
|
||||
"Export": "Export",
|
||||
"External links":"Liens externes",
|
||||
"External provider URL": "URL du fournisseur externe",
|
||||
"External registration": "Inscription externe",
|
||||
"Ex: mobilizon.fr": "Ex : mobilizon.fr",
|
||||
@@ -1289,6 +1292,7 @@
|
||||
"This profile is from another instance, the informations shown here may be incomplete.": "Ce profil provient d'une autre instance, les informations montrées ici peuvent être incomplètes.",
|
||||
"This profile is located on this instance, so you need to {access_the_corresponding_account} to suspend it.": "Ce profil se situe sur cette instance, vous devez donc {access_the_corresponding_account} afin de le suspendre.",
|
||||
"This profile was not found": "Ce profil n'a pas été trouvé",
|
||||
"This section lets you add links to external websites to the menu.": "Cette section vous permet d'ajouter des liens vers des sites internets externes au menu.",
|
||||
"This setting will be used to display the website and send you emails in the correct language.": "Ce paramètre sera utilisé pour l'affichage du site et pour vous envoyer des courriels dans la bonne langue.",
|
||||
"This URL doesn't seem to be valid": "Cette URL ne semble pas être valide",
|
||||
"This URL is not supported": "Cette URL n'est pas supportée",
|
||||
|
||||
@@ -28,6 +28,7 @@ export interface IAdminSettings {
|
||||
contact: string;
|
||||
instanceLogo: IMedia | null;
|
||||
instanceFavicon: IMedia | null;
|
||||
externalUrls: { url: string; label: string; enabled: boolean }[];
|
||||
defaultPicture: IMedia | null;
|
||||
primaryColor: string;
|
||||
secondaryColor: string;
|
||||
|
||||
@@ -458,6 +458,47 @@
|
||||
</o-field>
|
||||
</section>
|
||||
|
||||
<section class="mt-4 mb-4 p-4 border rounded shadow-sm bg-white">
|
||||
<h2>{{ t("External links") }}</h2>
|
||||
<small>
|
||||
{{
|
||||
t(
|
||||
"This section lets you add links to external websites to the menu."
|
||||
)
|
||||
}}
|
||||
</small>
|
||||
<o-field>
|
||||
<o-button :label="t('Add a new link')" @click="addLink" />
|
||||
</o-field>
|
||||
<div
|
||||
class="mt-5 grid lg:grid-cols-[repeat(auto-fit,minmax(250px,0.5fr))] grid-cols-[repeat(auto-fit,minmax(250px,1fr))] gap-2"
|
||||
v-if="settingsToWrite.externalUrls.length > 0"
|
||||
>
|
||||
<div
|
||||
class="bg-mbz-yellow-alt-100 p-5"
|
||||
v-for="(link, index) in settingsToWrite.externalUrls"
|
||||
:key="index"
|
||||
>
|
||||
<o-field :label="t('URL')" class="!mt-0"
|
||||
><o-input expanded v-model="link.url" type="text"
|
||||
/></o-field>
|
||||
|
||||
<o-field :label="t('Label')"
|
||||
><o-input expanded v-model="link.label" type="text"
|
||||
/></o-field>
|
||||
|
||||
<o-field
|
||||
><o-checkbox v-model="link.enabled" :label="t('Enabled')"
|
||||
/></o-field>
|
||||
<o-field>
|
||||
<o-button
|
||||
:label="t('Delete this link')"
|
||||
variant="danger"
|
||||
@click="deleteLink(index)"
|
||||
/></o-field>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<o-button native-type="submit" variant="primary">{{
|
||||
t("Save instance settings")
|
||||
}}</o-button>
|
||||
@@ -479,7 +520,7 @@ import {
|
||||
import { IAdminSettings, ILanguage } from "@/types/admin.model";
|
||||
import RouteName from "@/router/name";
|
||||
import { useMutation, useQuery } from "@vue/apollo-composable";
|
||||
import { ref, computed, watch, inject } from "vue";
|
||||
import { ref, computed, watch, inject, toRaw } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useHead } from "@/utils/head";
|
||||
import type { Notifier } from "@/plugins/notifier";
|
||||
@@ -515,6 +556,7 @@ const defaultAdminSettings: IAdminSettings = {
|
||||
registrationsOpen: false,
|
||||
registrationsModeration: false,
|
||||
instanceLanguages: [],
|
||||
externalUrls: [],
|
||||
};
|
||||
|
||||
const { onResult: onAdminSettingsResult } = useQuery<{
|
||||
@@ -556,9 +598,25 @@ useHead({
|
||||
const settingsToWrite = ref<IAdminSettings>(defaultAdminSettings);
|
||||
|
||||
watch(adminSettings, () => {
|
||||
settingsToWrite.value = { ...adminSettings.value };
|
||||
// We need to use structuredClone to clone deep properties of adminSettings (like externalUrls)
|
||||
// {... } only shadow clone, so externalUrls is not reactive doing this
|
||||
if (adminSettings.value) {
|
||||
settingsToWrite.value = structuredClone(toRaw(adminSettings.value));
|
||||
}
|
||||
});
|
||||
|
||||
const addLink = () => {
|
||||
settingsToWrite.value.externalUrls.push({
|
||||
url: "",
|
||||
label: "",
|
||||
enabled: false,
|
||||
});
|
||||
};
|
||||
|
||||
const deleteLink = (index: number) => {
|
||||
settingsToWrite.value.externalUrls.splice(index, 1);
|
||||
};
|
||||
|
||||
const filteredLanguages = ref<string[]>([]);
|
||||
|
||||
const registrationsMode = computed({
|
||||
@@ -614,14 +672,15 @@ const {
|
||||
onDone: saveAdminSettingsDone,
|
||||
onError: saveAdminSettingsError,
|
||||
} = useMutation(SAVE_ADMIN_SETTINGS, () => ({
|
||||
// We need to update the cache because we just changed admin settings
|
||||
// We want to update the related query ADMIN_SETTINGS
|
||||
update(cache, { data }) {
|
||||
if (!data?.saveAdminSettings) {
|
||||
console.error("can't acces new admin settings");
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to update the cache because we just changed admin settings
|
||||
// We want to update the related query ADMIN_SETTINGS
|
||||
// Usefull if we comeback to this page
|
||||
cache.writeQuery({
|
||||
query: ADMIN_SETTINGS,
|
||||
data: { adminSettings: data?.saveAdminSettings },
|
||||
|
||||
Reference in New Issue
Block a user