From 4bc501714251c1d93b1eb003984bd3276caf6468 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 2 Sep 2019 14:35:50 +0200 Subject: [PATCH] Prepare front to edit events --- js/src/graphql/event.ts | 18 +- js/src/main.ts | 1 + js/src/router/event.ts | 10 +- js/src/types/event.model.ts | 95 ++++++++--- js/src/types/picture.model.ts | 15 +- js/src/utils/image.ts | 24 +++ js/src/utils/object.ts | 5 + .../views/Account/children/EditIdentity.vue | 25 +-- js/src/views/Event/{Create.vue => Edit.vue} | 161 ++++++++++-------- js/src/vue-apollo.ts | 4 +- 10 files changed, 213 insertions(+), 145 deletions(-) create mode 100644 js/src/utils/image.ts create mode 100644 js/src/utils/object.ts rename js/src/views/Event/{Create.vue => Edit.vue} (62%) diff --git a/js/src/graphql/event.ts b/js/src/graphql/event.ts index 3779894bd..6f7c10d45 100644 --- a/js/src/graphql/event.ts +++ b/js/src/graphql/event.ts @@ -139,15 +139,15 @@ export const FETCH_EVENTS = gql` export const CREATE_EVENT = gql` mutation CreateEvent( - $title: String!, - $description: String!, - $organizerActorId: ID!, - $category: String, - $beginsOn: DateTime!, - $picture: PictureInput, - $tags: [String], - $physicalAddress: AddressInput, - $visibility: EventVisibility + $title: String!, + $description: String!, + $organizerActorId: ID!, + $category: String, + $beginsOn: DateTime!, + $picture: PictureInput, + $tags: [String], + $physicalAddress: AddressInput, + $visibility: EventVisibility ) { createEvent( title: $title, diff --git a/js/src/main.ts b/js/src/main.ts index d4fc48765..25a5e6068 100644 --- a/js/src/main.ts +++ b/js/src/main.ts @@ -20,6 +20,7 @@ const language = (window.navigator as any).userLanguage || window.navigator.lang Vue.use(GetTextPlugin, { translations, defaultLanguage: 'en_US', + silent: true, }); Vue.config.language = language.replace('-', '_'); diff --git a/js/src/router/event.ts b/js/src/router/event.ts index 928119b1b..7b6f75741 100644 --- a/js/src/router/event.ts +++ b/js/src/router/event.ts @@ -3,7 +3,7 @@ import Location from '@/views/Location.vue'; import { RouteConfig } from 'vue-router'; // tslint:disable:space-in-parens -const createEvent = () => import(/* webpackChunkName: "create-event" */ '@/views/Event/Create.vue'); +const editEvent = () => import(/* webpackChunkName: "create-event" */ '@/views/Event/Edit.vue'); const event = () => import(/* webpackChunkName: "event" */ '@/views/Event/Event.vue'); // tslint:enable @@ -25,15 +25,15 @@ export const eventRoutes: RouteConfig[] = [ { path: '/events/create', name: EventRouteName.CREATE_EVENT, - component: createEvent, + component: editEvent, meta: { requiredAuth: true }, }, { - path: '/events/:id/edit', + path: '/events/edit/:eventId', name: EventRouteName.EDIT_EVENT, - component: createEvent, - props: true, + component: editEvent, meta: { requiredAuth: true }, + props: { isUpdate: true }, }, { path: '/location/new', diff --git a/js/src/types/event.model.ts b/js/src/types/event.model.ts index 841e092bb..57f875bfe 100644 --- a/js/src/types/event.model.ts +++ b/js/src/types/event.model.ts @@ -1,7 +1,7 @@ import { Actor, IActor } from './actor'; import { IAddress } from '@/types/address.model'; import { ITag } from '@/types/tag.model'; -import { IAbstractPicture, IPicture } from '@/types/picture.model'; +import { IPicture } from '@/types/picture.model'; export enum EventStatus { TENTATIVE, @@ -53,10 +53,10 @@ export interface IEvent { title: string; slug: string; description: string; - category: Category|null; + category: Category | null; beginsOn: Date; - endsOn: Date; + endsOn: Date | null; publishAt: Date; status: EventStatus; @@ -64,7 +64,7 @@ export interface IEvent { joinOptions: EventJoinOptions; - picture: IAbstractPicture|null; + picture: IPicture | null; organizerActor: IActor; attributedTo: IActor; @@ -79,27 +79,76 @@ export interface IEvent { tags: ITag[]; } - export class EventModel implements IEvent { - beginsOn: Date = new Date(); - category: Category = Category.MEETING; - slug: string = ''; - description: string = ''; - endsOn: Date = new Date(); - joinOptions: EventJoinOptions = EventJoinOptions.FREE; - local: boolean = true; + id?: number; + + beginsOn = new Date(); + endsOn: Date | null = new Date(); + + title = ''; + url = ''; + uuid = ''; + slug = ''; + description = ''; + local = true; + + onlineAddress: string | undefined = ''; + phoneAddress: string | undefined = ''; + physicalAddress?: IAddress; + + picture: IPicture | null = null; + + visibility = EventVisibility.PUBLIC; + category: Category | null = Category.MEETING; + joinOptions = EventJoinOptions.FREE; + status = EventStatus.CONFIRMED; + + publishAt = new Date(); + participants: IParticipant[] = []; - publishAt: Date = new Date(); - status: EventStatus = EventStatus.CONFIRMED; - title: string = ''; - url: string = ''; - uuid: string = ''; - visibility: EventVisibility = EventVisibility.PUBLIC; - attributedTo: IActor = new Actor(); - organizerActor: IActor = new Actor(); + relatedEvents: IEvent[] = []; - onlineAddress: string = ''; - phoneAddress: string = ''; - picture: IAbstractPicture|null = null; + + attributedTo = new Actor(); + organizerActor = new Actor(); + tags: ITag[] = []; + + constructor(hash?: IEvent) { + if (!hash) return; + + this.id = hash.id; + this.uuid = hash.uuid; + this.url = hash.url; + this.local = hash.local; + + this.title = hash.title; + this.slug = hash.slug; + this.description = hash.description; + this.category = hash.category; + + this.beginsOn = new Date(hash.beginsOn); + if (hash.endsOn) this.endsOn = new Date(hash.endsOn); + + this.publishAt = new Date(hash.publishAt); + + this.status = hash.status; + this.visibility = hash.visibility; + + this.joinOptions = hash.joinOptions; + + this.picture = hash.picture; + + this.organizerActor = new Actor(hash.organizerActor); + this.attributedTo = new Actor(hash.attributedTo); + this.participants = hash.participants; + + this.relatedEvents = hash.relatedEvents; + + this.onlineAddress = hash.onlineAddress; + this.phoneAddress = hash.phoneAddress; + this.physicalAddress = hash.physicalAddress; + + this.tags = hash.tags; + } } diff --git a/js/src/types/picture.model.ts b/js/src/types/picture.model.ts index 7311c6463..3670db29f 100644 --- a/js/src/types/picture.model.ts +++ b/js/src/types/picture.model.ts @@ -1,16 +1,11 @@ -export interface IAbstractPicture { - name; - alt; -} - export interface IPicture { - url; - name; - alt; + url: string; + name: string; + alt: string; } export interface IPictureUpload { file: File; - name: String; - alt: String|null; + name: string; + alt: string | null; } diff --git a/js/src/utils/image.ts b/js/src/utils/image.ts new file mode 100644 index 000000000..8eeba866b --- /dev/null +++ b/js/src/utils/image.ts @@ -0,0 +1,24 @@ +import { IPicture } from '@/types/picture.model'; + +export async function buildFileFromIPicture(obj: IPicture | null) { + if (!obj) return null; + + const response = await fetch(obj.url); + const blob = await response.blob(); + + return new File([blob], obj.name); +} + +export function buildFileVariable(file: File | null, name: string, alt?: string) { + if (!file) return {}; + + return { + [name]: { + picture: { + name: file.name, + alt: alt || file.name, + file, + }, + }, + }; +} diff --git a/js/src/utils/object.ts b/js/src/utils/object.ts new file mode 100644 index 000000000..aac64fa05 --- /dev/null +++ b/js/src/utils/object.ts @@ -0,0 +1,5 @@ +export function buildObjectCollection(collection: T[] | undefined, builder: (new (p: T) => U)) { + if (!collection || Array.isArray(collection) === false) return []; + + return collection.map(v => new builder(v)); +} diff --git a/js/src/views/Account/children/EditIdentity.vue b/js/src/views/Account/children/EditIdentity.vue index 117ffcd02..ce13c540b 100644 --- a/js/src/views/Account/children/EditIdentity.vue +++ b/js/src/views/Account/children/EditIdentity.vue @@ -76,6 +76,7 @@ import PictureUpload from '@/components/PictureUpload.vue'; import { MOBILIZON_INSTANCE_HOST } from '@/api/_entrypoint'; import { Dialog } from 'buefy/dist/components/dialog'; import { RouteName } from '@/router'; +import { buildFileFromIPicture, buildFileVariable } from '@/utils/image'; @Component({ components: { @@ -113,7 +114,7 @@ export default class EditIdentity extends Vue { if (this.identityName) { this.identity = await this.getIdentity(); - this.avatarFile = await this.getAvatarFileFromIdentity(this.identity); + this.avatarFile = await buildFileFromIPicture(this.identity.avatar); } } @@ -259,15 +260,6 @@ export default class EditIdentity extends Vue { return new Person(result.data.person); } - private async getAvatarFileFromIdentity(identity: IPerson) { - if (!identity.avatar) return null; - - const response = await fetch(identity.avatar.url); - const blob = await response.blob(); - - return new File([blob], identity.avatar.name); - } - private handleError(err: any) { console.error(err); @@ -285,18 +277,7 @@ export default class EditIdentity extends Vue { } private buildVariables() { - let avatarObj = {}; - if (this.avatarFile) { - avatarObj = { - avatar: { - picture: { - name: this.avatarFile.name, - alt: `${this.identity.preferredUsername}'s avatar`, - file: this.avatarFile, - }, - }, - }; - } + const avatarObj = buildFileVariable(this.avatarFile, 'avatar', `${this.identity.preferredUsername}'s avatar`); return Object.assign({}, this.identity, avatarObj); } diff --git a/js/src/views/Event/Create.vue b/js/src/views/Event/Edit.vue similarity index 62% rename from js/src/views/Event/Create.vue rename to js/src/views/Event/Edit.vue index b3c73c416..b605936af 100644 --- a/js/src/views/Event/Create.vue +++ b/js/src/views/Event/Edit.vue @@ -1,14 +1,17 @@ \ No newline at end of file + diff --git a/js/src/vue-apollo.ts b/js/src/vue-apollo.ts index d39a67361..699755eb3 100644 --- a/js/src/vue-apollo.ts +++ b/js/src/vue-apollo.ts @@ -6,10 +6,8 @@ import { onError } from 'apollo-link-error'; import { createLink } from 'apollo-absinthe-upload-link'; import { GRAPHQL_API_ENDPOINT, GRAPHQL_API_FULL_PATH } from './api/_entrypoint'; import { ApolloClient } from 'apollo-client'; -import { DollarApollo } from 'vue-apollo/types/vue-apollo'; import { buildCurrentUserResolver } from '@/apollo/user'; import { isServerError } from '@/types/apollo'; -import { inspect } from 'util'; import { REFRESH_TOKEN } from '@/graphql/auth'; import { AUTH_ACCESS_TOKEN, AUTH_REFRESH_TOKEN } from '@/constants'; import { logout, saveTokenData } from '@/utils/auth'; @@ -107,7 +105,7 @@ const apolloClient = new ApolloClient({ cache, link, connectToDevTools: true, - resolvers: buildCurrentUserResolver(cache) + resolvers: buildCurrentUserResolver(cache), }); export const apolloProvider = new VueApollo({