Refactor picture-upload and take into account picture size limits
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
947d0b0cdb
commit
e2721af456
|
@ -1,15 +1,35 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="root">
|
<div class="root">
|
||||||
<figure class="image" v-if="imageSrc">
|
<figure class="image" v-if="imageSrc && !imagePreviewLoadingError">
|
||||||
<img :src="imageSrc" />
|
<img :src="imageSrc" @error="showImageLoadingError" />
|
||||||
</figure>
|
</figure>
|
||||||
<figure class="image is-128x128" v-else>
|
<figure class="image is-128x128" v-else>
|
||||||
<div class="image-placeholder">
|
<div
|
||||||
<span class="has-text-centered">{{ textFallback }}</span>
|
class="image-placeholder"
|
||||||
|
:class="{ error: imagePreviewLoadingError }"
|
||||||
|
>
|
||||||
|
<span class="has-text-centered" v-if="imagePreviewLoadingError">{{
|
||||||
|
$t("Error while loading the preview")
|
||||||
|
}}</span>
|
||||||
|
<span class="has-text-centered" v-else>{{ textFallback }}</span>
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
<div class="action-buttons">
|
<div class="action-buttons">
|
||||||
|
<p v-if="pictureFile" class="metadata">
|
||||||
|
<span class="name" :title="pictureFile.name">{{
|
||||||
|
pictureFile.name
|
||||||
|
}}</span>
|
||||||
|
<span class="size">({{ formatBytes(pictureFile.size) }})</span>
|
||||||
|
</p>
|
||||||
|
<p v-if="pictureTooBig" class="picture-too-big">
|
||||||
|
{{
|
||||||
|
$t(
|
||||||
|
"The selected picture is too heavy. You need to select a file smaller than {size}.",
|
||||||
|
{ size: formatBytes(maxSize) }
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
<b-field class="file is-primary">
|
<b-field class="file is-primary">
|
||||||
<b-upload @input="onFileChanged" :accept="accept" class="file-label">
|
<b-upload @input="onFileChanged" :accept="accept" class="file-label">
|
||||||
<span class="file-cta">
|
<span class="file-cta">
|
||||||
|
@ -47,6 +67,10 @@ figure.image {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
border: 2px solid red;
|
||||||
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
color: #eee;
|
color: #eee;
|
||||||
|
@ -56,6 +80,27 @@ figure.image {
|
||||||
.action-buttons {
|
.action-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
|
.file {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadata {
|
||||||
|
display: inline-flex;
|
||||||
|
|
||||||
|
.name {
|
||||||
|
max-width: 200px;
|
||||||
|
display: block;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.picture-too-big {
|
||||||
|
color: $danger;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
@ -87,30 +132,32 @@ export default class PictureUpload extends Vue {
|
||||||
})
|
})
|
||||||
textFallback!: string;
|
textFallback!: string;
|
||||||
|
|
||||||
imageSrc: string | null = this.defaultImage ? this.defaultImage.url : null;
|
@Prop({ type: Number, required: false, default: 10_485_760 })
|
||||||
|
maxSize!: number;
|
||||||
|
|
||||||
file!: File | null;
|
file!: File | null;
|
||||||
|
|
||||||
mounted(): void {
|
imagePreviewLoadingError = false;
|
||||||
if (this.pictureFile) {
|
|
||||||
this.updatePreview(this.pictureFile);
|
get pictureTooBig(): boolean {
|
||||||
}
|
return this.pictureFile?.size > this.maxSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Watch("pictureFile")
|
get imageSrc(): string | null {
|
||||||
onPictureFileChanged(val: File): void {
|
if (this.pictureFile !== undefined) {
|
||||||
this.updatePreview(val);
|
if (this.pictureFile === null) return null;
|
||||||
|
try {
|
||||||
|
return URL.createObjectURL(this.pictureFile);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@Watch("defaultImage")
|
return this.defaultImage ? this.defaultImage.url : null;
|
||||||
onDefaultImageChange(defaultImage: IMedia): void {
|
|
||||||
this.imageSrc = defaultImage ? defaultImage.url : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onFileChanged(file: File | null): void {
|
onFileChanged(file: File | null): void {
|
||||||
this.$emit("change", file);
|
this.$emit("change", file);
|
||||||
|
|
||||||
this.updatePreview(file);
|
|
||||||
this.file = file;
|
this.file = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,13 +165,23 @@ export default class PictureUpload extends Vue {
|
||||||
this.onFileChanged(null);
|
this.onFileChanged(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private updatePreview(file?: File | null) {
|
@Watch("imageSrc")
|
||||||
if (file) {
|
resetImageLoadingError(): void {
|
||||||
this.imageSrc = URL.createObjectURL(file);
|
this.imagePreviewLoadingError = false;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.imageSrc = null;
|
showImageLoadingError(): void {
|
||||||
|
this.imagePreviewLoadingError = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://gist.github.com/zentala/1e6f72438796d74531803cc3833c039c
|
||||||
|
formatBytes(bytes: number, decimals: number): string {
|
||||||
|
if (bytes == 0) return "0 Bytes";
|
||||||
|
const k = 1024,
|
||||||
|
dm = decimals || 2,
|
||||||
|
sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"],
|
||||||
|
i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -979,5 +979,10 @@
|
||||||
"Personal feeds": "Personal feeds",
|
"Personal feeds": "Personal feeds",
|
||||||
"These feeds contain event data for the events for which any of your profiles is a participant or creator. You should keep these private. You can find feeds for specific profiles on each profile edition page.": "These feeds contain event data for the events for which any of your profiles is a participant or creator. You should keep these private. You can find feeds for specific profiles on each profile edition page.",
|
"These feeds contain event data for the events for which any of your profiles is a participant or creator. You should keep these private. You can find feeds for specific profiles on each profile edition page.": "These feeds contain event data for the events for which any of your profiles is a participant or creator. You should keep these private. You can find feeds for specific profiles on each profile edition page.",
|
||||||
"The event will show as attributed to this profile.": "The event will show as attributed to this profile.",
|
"The event will show as attributed to this profile.": "The event will show as attributed to this profile.",
|
||||||
"You may show some members as contacts.": "You may show some members as contacts."
|
"You may show some members as contacts.": "You may show some members as contacts.",
|
||||||
|
"The selected picture is too heavy. You need to select a file smaller than {size}.": "The selected picture is too heavy. You need to select a file smaller than {size}.",
|
||||||
|
"Unable to create the group. One of the pictures may be too heavy.": "Unable to create the group. One of the pictures may be too heavy.",
|
||||||
|
"Unable to update the profile. The avatar picture may be too heavy.": "Unable to update the profile. The avatar picture may be too heavy.",
|
||||||
|
"Unable to create the profile. The avatar picture may be too heavy.": "Unable to create the profile. The avatar picture may be too heavy.",
|
||||||
|
"Error while loading the preview": "Error while loading the preview"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1073,5 +1073,10 @@
|
||||||
"Personal feeds": "Flux personnels",
|
"Personal feeds": "Flux personnels",
|
||||||
"These feeds contain event data for the events for which any of your profiles is a participant or creator. You should keep these private. You can find feeds for specific profiles on each profile edition page.": "Ces flux contiennent des informations sur les événements pour lesquels n'importe lequel de vos profils est un⋅e participant⋅e ou un⋅e créateur⋅ice. Vous devriez les garder privés. Vous pouvez trouver des flux spécifiques à chaque profil sur la page d'édition des profils.",
|
"These feeds contain event data for the events for which any of your profiles is a participant or creator. You should keep these private. You can find feeds for specific profiles on each profile edition page.": "Ces flux contiennent des informations sur les événements pour lesquels n'importe lequel de vos profils est un⋅e participant⋅e ou un⋅e créateur⋅ice. Vous devriez les garder privés. Vous pouvez trouver des flux spécifiques à chaque profil sur la page d'édition des profils.",
|
||||||
"The event will show as attributed to this profile.": "L'événement sera affiché comme attribué à ce profil.",
|
"The event will show as attributed to this profile.": "L'événement sera affiché comme attribué à ce profil.",
|
||||||
"You may show some members as contacts.": "Vous pouvez afficher certain⋅es membres en tant que contacts."
|
"You may show some members as contacts.": "Vous pouvez afficher certain⋅es membres en tant que contacts.",
|
||||||
|
"The selected picture is too heavy. You need to select a file smaller than {size}.": "L'image sélectionnée est trop lourde. Vous devez sélectionner un fichier de moins de {size}.",
|
||||||
|
"Unable to create the group. One of the pictures may be too heavy.": "Impossible de créer le groupe. Une des images est trop lourde.",
|
||||||
|
"Unable to update the profile. The avatar picture may be too heavy.": "Impossible de mettre à jour le profil. L'image d'avatar est probablement trop lourde.",
|
||||||
|
"Unable to create the profile. The avatar picture may be too heavy.": "Impossible de créer le profil. L'image d'avatar est probablement trop lourde.",
|
||||||
|
"Error while loading the preview": "Erreur lors du chargement de l'aperçu"
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
<picture-upload
|
<picture-upload
|
||||||
v-model="avatarFile"
|
v-model="avatarFile"
|
||||||
:defaultImage="identity.avatar"
|
:defaultImage="identity.avatar"
|
||||||
|
:maxSize="avatarMaxSize"
|
||||||
class="picture-upload"
|
class="picture-upload"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -231,6 +232,9 @@ import {
|
||||||
DELETE_FEED_TOKEN,
|
DELETE_FEED_TOKEN,
|
||||||
} from "@/graphql/feed_tokens";
|
} from "@/graphql/feed_tokens";
|
||||||
import { IFeedToken } from "@/types/feedtoken.model";
|
import { IFeedToken } from "@/types/feedtoken.model";
|
||||||
|
import { ServerParseError } from "apollo-link-http-common";
|
||||||
|
import { IConfig } from "@/types/config.model";
|
||||||
|
import { CONFIG } from "@/graphql/config";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
|
@ -256,6 +260,7 @@ import { IFeedToken } from "@/types/feedtoken.model";
|
||||||
this.handleErrors(graphQLErrors);
|
this.handleErrors(graphQLErrors);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
config: CONFIG,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
export default class EditIdentity extends mixins(identityEditionMixin) {
|
export default class EditIdentity extends mixins(identityEditionMixin) {
|
||||||
|
@ -263,6 +268,8 @@ export default class EditIdentity extends mixins(identityEditionMixin) {
|
||||||
|
|
||||||
@Prop({ type: String }) identityName!: string;
|
@Prop({ type: String }) identityName!: string;
|
||||||
|
|
||||||
|
config!: IConfig;
|
||||||
|
|
||||||
errors: string[] = [];
|
errors: string[] = [];
|
||||||
|
|
||||||
avatarFile: File | null = null;
|
avatarFile: File | null = null;
|
||||||
|
@ -450,6 +457,10 @@ export default class EditIdentity extends mixins(identityEditionMixin) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get avatarMaxSize(): number | undefined {
|
||||||
|
return this?.config?.uploadLimits?.avatar;
|
||||||
|
}
|
||||||
|
|
||||||
async generateFeedTokens(): Promise<void> {
|
async generateFeedTokens(): Promise<void> {
|
||||||
const newToken = await this.createNewFeedToken();
|
const newToken = await this.createNewFeedToken();
|
||||||
this.identity.feedTokens.push(newToken);
|
this.identity.feedTokens.push(newToken);
|
||||||
|
@ -528,6 +539,21 @@ export default class EditIdentity extends mixins(identityEditionMixin) {
|
||||||
private handleError(err: any) {
|
private handleError(err: any) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
||||||
|
if (err?.networkError?.name === "ServerParseError") {
|
||||||
|
const error = err?.networkError as ServerParseError;
|
||||||
|
|
||||||
|
if (error?.response?.status === 413) {
|
||||||
|
const errorMessage = this.isUpdate
|
||||||
|
? this.$t(
|
||||||
|
"Unable to update the profile. The avatar picture may be too heavy."
|
||||||
|
)
|
||||||
|
: this.$t(
|
||||||
|
"Unable to create the profile. The avatar picture may be too heavy."
|
||||||
|
);
|
||||||
|
this.errors.push(errorMessage as string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (err.graphQLErrors !== undefined) {
|
if (err.graphQLErrors !== undefined) {
|
||||||
err.graphQLErrors.forEach(({ message }: { message: string }) => {
|
err.graphQLErrors.forEach(({ message }: { message: string }) => {
|
||||||
this.$notifier.error(message);
|
this.$notifier.error(message);
|
||||||
|
|
|
@ -58,12 +58,20 @@
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<b>{{ $t("Avatar") }}</b>
|
<b>{{ $t("Avatar") }}</b>
|
||||||
<picture-upload :textFallback="$t('Avatar')" v-model="avatarFile" />
|
<picture-upload
|
||||||
|
:textFallback="$t('Avatar')"
|
||||||
|
v-model="avatarFile"
|
||||||
|
:maxSize="avatarMaxSize"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<b>{{ $t("Banner") }}</b>
|
<b>{{ $t("Banner") }}</b>
|
||||||
<picture-upload :textFallback="$t('Banner')" v-model="bannerFile" />
|
<picture-upload
|
||||||
|
:textFallback="$t('Banner')"
|
||||||
|
v-model="bannerFile"
|
||||||
|
:maxSize="bannerMaxSize"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="button is-primary" native-type="submit">
|
<button class="button is-primary" native-type="submit">
|
||||||
|
@ -84,6 +92,10 @@ import { MemberRole } from "@/types/enums";
|
||||||
import RouteName from "../../router/name";
|
import RouteName from "../../router/name";
|
||||||
import { convertToUsername } from "../../utils/username";
|
import { convertToUsername } from "../../utils/username";
|
||||||
import PictureUpload from "../../components/PictureUpload.vue";
|
import PictureUpload from "../../components/PictureUpload.vue";
|
||||||
|
import { ErrorResponse } from "apollo-link-error";
|
||||||
|
import { ServerParseError } from "apollo-link-http-common";
|
||||||
|
import { CONFIG } from "@/graphql/config";
|
||||||
|
import { IConfig } from "@/types/config.model";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
|
@ -93,6 +105,7 @@ import PictureUpload from "../../components/PictureUpload.vue";
|
||||||
currentActor: {
|
currentActor: {
|
||||||
query: CURRENT_ACTOR_CLIENT,
|
query: CURRENT_ACTOR_CLIENT,
|
||||||
},
|
},
|
||||||
|
config: CONFIG,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
export default class CreateGroup extends mixins(IdentityEditionMixin) {
|
export default class CreateGroup extends mixins(IdentityEditionMixin) {
|
||||||
|
@ -100,6 +113,8 @@ export default class CreateGroup extends mixins(IdentityEditionMixin) {
|
||||||
|
|
||||||
group = new Group();
|
group = new Group();
|
||||||
|
|
||||||
|
config!: IConfig;
|
||||||
|
|
||||||
avatarFile: File | null = null;
|
avatarFile: File | null = null;
|
||||||
|
|
||||||
bannerFile: File | null = null;
|
bannerFile: File | null = null;
|
||||||
|
@ -110,6 +125,7 @@ export default class CreateGroup extends mixins(IdentityEditionMixin) {
|
||||||
|
|
||||||
async createGroup(): Promise<void> {
|
async createGroup(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
|
this.errors = [];
|
||||||
await this.$apollo.mutate({
|
await this.$apollo.mutate({
|
||||||
mutation: CREATE_GROUP,
|
mutation: CREATE_GROUP,
|
||||||
variables: this.buildVariables(),
|
variables: this.buildVariables(),
|
||||||
|
@ -154,6 +170,14 @@ export default class CreateGroup extends mixins(IdentityEditionMixin) {
|
||||||
return window.location.hostname;
|
return window.location.hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get avatarMaxSize(): number | undefined {
|
||||||
|
return this?.config?.uploadLimits?.avatar;
|
||||||
|
}
|
||||||
|
|
||||||
|
get bannerMaxSize(): number | undefined {
|
||||||
|
return this?.config?.uploadLimits?.banner;
|
||||||
|
}
|
||||||
|
|
||||||
@Watch("group.name")
|
@Watch("group.name")
|
||||||
updateUsername(groupName: string): void {
|
updateUsername(groupName: string): void {
|
||||||
this.group.preferredUsername = convertToUsername(groupName);
|
this.group.preferredUsername = convertToUsername(groupName);
|
||||||
|
@ -194,9 +218,22 @@ export default class CreateGroup extends mixins(IdentityEditionMixin) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleError(err: any) {
|
private handleError(err: ErrorResponse) {
|
||||||
|
if (err?.networkError?.name === "ServerParseError") {
|
||||||
|
const error = err?.networkError as ServerParseError;
|
||||||
|
|
||||||
|
if (error?.response?.status === 413) {
|
||||||
this.errors.push(
|
this.errors.push(
|
||||||
...err.graphQLErrors.map(({ message }: { message: string }) => message)
|
this.$t(
|
||||||
|
"Unable to create the group. One of the pictures may be too heavy."
|
||||||
|
) as string
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.errors.push(
|
||||||
|
...(err.graphQLErrors || []).map(
|
||||||
|
({ message }: { message: string }) => message
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
:textFallback="$t('Avatar')"
|
:textFallback="$t('Avatar')"
|
||||||
v-model="avatarFile"
|
v-model="avatarFile"
|
||||||
:defaultImage="group.avatar"
|
:defaultImage="group.avatar"
|
||||||
|
:maxSize="avatarMaxSize"
|
||||||
/>
|
/>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
||||||
|
@ -55,6 +56,7 @@
|
||||||
:textFallback="$t('Banner')"
|
:textFallback="$t('Banner')"
|
||||||
v-model="bannerFile"
|
v-model="bannerFile"
|
||||||
:defaultImage="group.banner"
|
:defaultImage="group.banner"
|
||||||
|
:maxSize="bannerMaxSize"
|
||||||
/>
|
/>
|
||||||
</b-field>
|
</b-field>
|
||||||
<p class="label">{{ $t("Group visibility") }}</p>
|
<p class="label">{{ $t("Group visibility") }}</p>
|
||||||
|
@ -158,6 +160,9 @@
|
||||||
}}</b-button>
|
}}</b-button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
<b-message type="is-danger" v-for="(value, index) in errors" :key="index">
|
||||||
|
{{ value }}
|
||||||
|
</b-message>
|
||||||
</section>
|
</section>
|
||||||
<b-message v-else>
|
<b-message v-else>
|
||||||
{{ $t("You are not an administrator for this group.") }}
|
{{ $t("You are not an administrator for this group.") }}
|
||||||
|
@ -177,6 +182,10 @@ import RouteName from "../../router/name";
|
||||||
import { UPDATE_GROUP, DELETE_GROUP } from "../../graphql/group";
|
import { UPDATE_GROUP, DELETE_GROUP } from "../../graphql/group";
|
||||||
import { IGroup, usernameWithDomain } from "../../types/actor";
|
import { IGroup, usernameWithDomain } from "../../types/actor";
|
||||||
import { Address, IAddress } from "../../types/address.model";
|
import { Address, IAddress } from "../../types/address.model";
|
||||||
|
import { CONFIG } from "@/graphql/config";
|
||||||
|
import { IConfig } from "@/types/config.model";
|
||||||
|
import { ErrorResponse } from "apollo-link-error";
|
||||||
|
import { ServerParseError } from "apollo-link-http-common";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
|
@ -184,14 +193,21 @@ import { Address, IAddress } from "../../types/address.model";
|
||||||
PictureUpload,
|
PictureUpload,
|
||||||
editor: () => import("../../components/Editor.vue"),
|
editor: () => import("../../components/Editor.vue"),
|
||||||
},
|
},
|
||||||
|
apollo: {
|
||||||
|
config: CONFIG,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
export default class GroupSettings extends mixins(GroupMixin) {
|
export default class GroupSettings extends mixins(GroupMixin) {
|
||||||
loading = true;
|
loading = true;
|
||||||
|
|
||||||
RouteName = RouteName;
|
RouteName = RouteName;
|
||||||
|
|
||||||
|
config!: IConfig;
|
||||||
|
|
||||||
newMemberUsername = "";
|
newMemberUsername = "";
|
||||||
|
|
||||||
|
errors: string[] = [];
|
||||||
|
|
||||||
avatarFile: File | null = null;
|
avatarFile: File | null = null;
|
||||||
|
|
||||||
bannerFile: File | null = null;
|
bannerFile: File | null = null;
|
||||||
|
@ -205,12 +221,16 @@ export default class GroupSettings extends mixins(GroupMixin) {
|
||||||
showCopiedTooltip = false;
|
showCopiedTooltip = false;
|
||||||
|
|
||||||
async updateGroup(): Promise<void> {
|
async updateGroup(): Promise<void> {
|
||||||
|
try {
|
||||||
const variables = this.buildVariables();
|
const variables = this.buildVariables();
|
||||||
await this.$apollo.mutate<{ updateGroup: IGroup }>({
|
await this.$apollo.mutate<{ updateGroup: IGroup }>({
|
||||||
mutation: UPDATE_GROUP,
|
mutation: UPDATE_GROUP,
|
||||||
variables,
|
variables,
|
||||||
});
|
});
|
||||||
this.$notifier.success(this.$t("Group settings saved") as string);
|
this.$notifier.success(this.$t("Group settings saved") as string);
|
||||||
|
} catch (err) {
|
||||||
|
this.handleError(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
confirmDeleteGroup(): void {
|
confirmDeleteGroup(): void {
|
||||||
|
@ -299,5 +319,32 @@ export default class GroupSettings extends mixins(GroupMixin) {
|
||||||
get currentAddress(): IAddress {
|
get currentAddress(): IAddress {
|
||||||
return new Address(this.group.physicalAddress);
|
return new Address(this.group.physicalAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get avatarMaxSize(): number | undefined {
|
||||||
|
return this?.config?.uploadLimits?.avatar;
|
||||||
|
}
|
||||||
|
|
||||||
|
get bannerMaxSize(): number | undefined {
|
||||||
|
return this?.config?.uploadLimits?.banner;
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleError(err: ErrorResponse) {
|
||||||
|
if (err?.networkError?.name === "ServerParseError") {
|
||||||
|
const error = err?.networkError as ServerParseError;
|
||||||
|
|
||||||
|
if (error?.response?.status === 413) {
|
||||||
|
this.errors.push(
|
||||||
|
this.$t(
|
||||||
|
"Unable to create the group. One of the pictures may be too heavy."
|
||||||
|
) as string
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.errors.push(
|
||||||
|
...(err.graphQLErrors || []).map(
|
||||||
|
({ message }: { message: string }) => message
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in a new issue