Refactor picture-upload and take into account picture size limits

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2021-04-12 10:43:04 +02:00
parent 947d0b0cdb
commit e2721af456
6 changed files with 214 additions and 37 deletions

View File

@@ -32,6 +32,7 @@
<picture-upload
v-model="avatarFile"
:defaultImage="identity.avatar"
:maxSize="avatarMaxSize"
class="picture-upload"
/>
@@ -231,6 +232,9 @@ import {
DELETE_FEED_TOKEN,
} from "@/graphql/feed_tokens";
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({
components: {
@@ -256,6 +260,7 @@ import { IFeedToken } from "@/types/feedtoken.model";
this.handleErrors(graphQLErrors);
},
},
config: CONFIG,
},
})
export default class EditIdentity extends mixins(identityEditionMixin) {
@@ -263,6 +268,8 @@ export default class EditIdentity extends mixins(identityEditionMixin) {
@Prop({ type: String }) identityName!: string;
config!: IConfig;
errors: string[] = [];
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> {
const newToken = await this.createNewFeedToken();
this.identity.feedTokens.push(newToken);
@@ -528,6 +539,21 @@ export default class EditIdentity extends mixins(identityEditionMixin) {
private handleError(err: any) {
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) {
err.graphQLErrors.forEach(({ message }: { message: string }) => {
this.$notifier.error(message);

View File

@@ -58,12 +58,20 @@
<div>
<b>{{ $t("Avatar") }}</b>
<picture-upload :textFallback="$t('Avatar')" v-model="avatarFile" />
<picture-upload
:textFallback="$t('Avatar')"
v-model="avatarFile"
:maxSize="avatarMaxSize"
/>
</div>
<div>
<b>{{ $t("Banner") }}</b>
<picture-upload :textFallback="$t('Banner')" v-model="bannerFile" />
<picture-upload
:textFallback="$t('Banner')"
v-model="bannerFile"
:maxSize="bannerMaxSize"
/>
</div>
<button class="button is-primary" native-type="submit">
@@ -84,6 +92,10 @@ import { MemberRole } from "@/types/enums";
import RouteName from "../../router/name";
import { convertToUsername } from "../../utils/username";
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({
components: {
@@ -93,6 +105,7 @@ import PictureUpload from "../../components/PictureUpload.vue";
currentActor: {
query: CURRENT_ACTOR_CLIENT,
},
config: CONFIG,
},
})
export default class CreateGroup extends mixins(IdentityEditionMixin) {
@@ -100,6 +113,8 @@ export default class CreateGroup extends mixins(IdentityEditionMixin) {
group = new Group();
config!: IConfig;
avatarFile: File | null = null;
bannerFile: File | null = null;
@@ -110,6 +125,7 @@ export default class CreateGroup extends mixins(IdentityEditionMixin) {
async createGroup(): Promise<void> {
try {
this.errors = [];
await this.$apollo.mutate({
mutation: CREATE_GROUP,
variables: this.buildVariables(),
@@ -154,6 +170,14 @@ export default class CreateGroup extends mixins(IdentityEditionMixin) {
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")
updateUsername(groupName: string): void {
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.$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)
...(err.graphQLErrors || []).map(
({ message }: { message: string }) => message
)
);
}
}

View File

@@ -47,6 +47,7 @@
:textFallback="$t('Avatar')"
v-model="avatarFile"
:defaultImage="group.avatar"
:maxSize="avatarMaxSize"
/>
</b-field>
@@ -55,6 +56,7 @@
:textFallback="$t('Banner')"
v-model="bannerFile"
:defaultImage="group.banner"
:maxSize="bannerMaxSize"
/>
</b-field>
<p class="label">{{ $t("Group visibility") }}</p>
@@ -158,6 +160,9 @@
}}</b-button>
</div>
</form>
<b-message type="is-danger" v-for="(value, index) in errors" :key="index">
{{ value }}
</b-message>
</section>
<b-message v-else>
{{ $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 { IGroup, usernameWithDomain } from "../../types/actor";
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({
components: {
@@ -184,14 +193,21 @@ import { Address, IAddress } from "../../types/address.model";
PictureUpload,
editor: () => import("../../components/Editor.vue"),
},
apollo: {
config: CONFIG,
},
})
export default class GroupSettings extends mixins(GroupMixin) {
loading = true;
RouteName = RouteName;
config!: IConfig;
newMemberUsername = "";
errors: string[] = [];
avatarFile: File | null = null;
bannerFile: File | null = null;
@@ -205,12 +221,16 @@ export default class GroupSettings extends mixins(GroupMixin) {
showCopiedTooltip = false;
async updateGroup(): Promise<void> {
const variables = this.buildVariables();
await this.$apollo.mutate<{ updateGroup: IGroup }>({
mutation: UPDATE_GROUP,
variables,
});
this.$notifier.success(this.$t("Group settings saved") as string);
try {
const variables = this.buildVariables();
await this.$apollo.mutate<{ updateGroup: IGroup }>({
mutation: UPDATE_GROUP,
variables,
});
this.$notifier.success(this.$t("Group settings saved") as string);
} catch (err) {
this.handleError(err);
}
}
confirmDeleteGroup(): void {
@@ -299,5 +319,32 @@ export default class GroupSettings extends mixins(GroupMixin) {
get currentAddress(): IAddress {
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>