From f67cafdae58bc8b743817d129ef0dfd35d683de9 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 9 Sep 2019 11:21:42 +0200 Subject: [PATCH] Edit events fixes and update cache --- config/dev.exs | 2 +- js/src/components/PictureUpload.vue | 6 +- js/src/graphql/event.ts | 204 ++++++++++++------ js/src/types/event.model.ts | 33 ++- js/src/views/Event/Edit.vue | 37 ++-- js/src/vue-apollo.ts | 4 +- lib/mobilizon_web/api/utils.ex | 2 +- lib/mobilizon_web/resolvers/event.ex | 10 +- lib/mobilizon_web/schema/event.ex | 14 +- schema.graphql | 24 +-- .../resolvers/event_resolver_test.exs | 2 - 11 files changed, 202 insertions(+), 136 deletions(-) diff --git a/config/dev.exs b/config/dev.exs index 21c109e0b..db854ff92 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -12,7 +12,7 @@ config :mobilizon, MobilizonWeb.Endpoint, ], url: [ host: System.get_env("MOBILIZON_INSTANCE_HOST") || "mobilizon.local", - port: 80, + port: System.get_env("MOBILIZON_INSTANCE_PORT") || 4000, scheme: "http" ], debug_errors: true, diff --git a/js/src/components/PictureUpload.vue b/js/src/components/PictureUpload.vue index 5d5e8c518..138b91202 100644 --- a/js/src/components/PictureUpload.vue +++ b/js/src/components/PictureUpload.vue @@ -41,8 +41,12 @@ export default class PictureUpload extends Vue { imageSrc: string | null = null; + mounted() { + this.updatePreview(this.pictureFile); + } + @Watch('pictureFile') - onPictureFileChanged (val: File) { + onPictureFileChanged(val: File) { this.updatePreview(val); } diff --git a/js/src/graphql/event.ts b/js/src/graphql/event.ts index eac64045d..0c4af8f67 100644 --- a/js/src/graphql/event.ts +++ b/js/src/graphql/event.ts @@ -12,6 +12,43 @@ const participantQuery = ` } `; +const physicalAddressQuery = ` + description, + floor, + street, + locality, + postalCode, + region, + country, + geom +`; + +const tagsQuery = ` + id, + slug, + title +`; + +const optionsQuery = ` + maximumAttendeeCapacity, + remainingAttendeeCapacity, + showRemainingAttendeeCapacity, + offers { + price, + priceCurrency, + url + }, + participationConditions { + title, + content, + url + }, + attendees, + program, + commentModeration, + showParticipationPrice +`; + export const FETCH_EVENT = gql` query($uuid:UUID!) { event(uuid: $uuid) { @@ -29,20 +66,14 @@ export const FETCH_EVENT = gql` picture { id url + name }, publishAt, category, - # online_address, - # phone_address, + online_address, + phone_address, physicalAddress { - description, - floor, - street, - locality, - postalCode, - region, - country, - geom + ${physicalAddressQuery} } organizerActor { avatar { @@ -65,9 +96,7 @@ export const FETCH_EVENT = gql` ${participantQuery} }, tags { - id, - slug, - title + ${tagsQuery} }, relatedEvents { uuid, @@ -86,23 +115,7 @@ export const FETCH_EVENT = gql` } }, options { - maximumAttendeeCapacity, - remainingAttendeeCapacity, - showRemainingAttendeeCapacity, - offers { - price, - priceCurrency, - url - }, - participationConditions { - title, - content, - url - }, - attendees, - program, - commentModeration, - showParticipationPrice + ${optionsQuery} } } } @@ -159,37 +172,62 @@ export const FETCH_EVENTS = gql` `; export const CREATE_EVENT = gql` - mutation CreateEvent( + mutation createEvent( + $organizerActorId: ID!, $title: String!, $description: String!, - $organizerActorId: ID!, - $category: String, $beginsOn: DateTime!, $endsOn: DateTime, - $picture: PictureInput, - $tags: [String], - $options: EventOptionsInput, - $physicalAddress: AddressInput, + $status: EventStatus, $visibility: EventVisibility + $tags: [String], + $picture: PictureInput, + $onlineAddress: String, + $phoneAddress: String, + $category: String, + $physicalAddress: AddressInput, + $options: EventOptionsInput, ) { createEvent( + organizerActorId: $organizerActorId, title: $title, description: $description, beginsOn: $beginsOn, endsOn: $endsOn, - organizerActorId: $organizerActorId, - category: $category, - options: $options, - picture: $picture, + status: $status, + visibility: $visibility, tags: $tags, - physicalAddress: $physicalAddress, - visibility: $visibility + picture: $picture, + onlineAddress: $onlineAddress, + phoneAddress: $phoneAddress, + category: $category, + physicalAddress: $physicalAddress + options: $options, ) { id, uuid, title, + description, + beginsOn, + endsOn, + status, + visibility, picture { + id url + }, + publishAt, + category, + online_address, + phone_address, + physicalAddress { + ${physicalAddressQuery} + }, + tags { + ${tagsQuery} + }, + options { + ${optionsQuery} } } } @@ -197,32 +235,62 @@ export const CREATE_EVENT = gql` export const EDIT_EVENT = gql` mutation updateEvent( - $id: ID!, - $title: String!, - $description: String!, - $organizerActorId: ID!, - $category: String, - $beginsOn: DateTime!, - $endsOn: DateTime, - $picture: PictureInput, - $tags: [String], - $options: EventOptionsInput, - $physicalAddress: AddressInput, - $visibility: EventVisibility + $id: ID!, + $title: String, + $description: String, + $beginsOn: DateTime, + $endsOn: DateTime, + $status: Int, + $visibility: EventVisibility + $tags: [String], + $picture: PictureInput, + $onlineAddress: String, + $phoneAddress: String, + $category: String, + $physicalAddress: AddressInput, + $options: EventOptionsInput, ) { - updateEvent(eventId: $id, - title: $title, - description: $description, - beginsOn: $beginsOn, - endsOn: $endsOn, - organizerActorId: $organizerActorId, - category: $category, - options: $options, - picture: $picture, - tags: $tags, - physicalAddress: $physicalAddress, - visibility: $visibility) { - uuid + updateEvent( + eventId: $id, + title: $title, + description: $description, + beginsOn: $beginsOn, + endsOn: $endsOn, + status: $status, + visibility: $visibility, + tags: $tags, + picture: $picture, + onlineAddress: $onlineAddress, + phoneAddress: $phoneAddress, + category: $category, + physicalAddress: $physicalAddress + options: $options, + ) { + id, + uuid, + title, + description, + beginsOn, + endsOn, + status, + visibility, + picture { + id + url + }, + publishAt, + category, + online_address, + phone_address, + physicalAddress { + ${physicalAddressQuery} + }, + tags { + ${tagsQuery} + }, + options { + ${optionsQuery} + } } } `; diff --git a/js/src/types/event.model.ts b/js/src/types/event.model.ts index b92244dde..84caf6bc3 100644 --- a/js/src/types/event.model.ts +++ b/js/src/types/event.model.ts @@ -117,15 +117,15 @@ export interface IEventOptions { } export class EventOptions implements IEventOptions { - maximumAttendeeCapacity: number = 0; - remainingAttendeeCapacity: number = 0; - showRemainingAttendeeCapacity: boolean = false; + maximumAttendeeCapacity = 0; + remainingAttendeeCapacity = 0; + showRemainingAttendeeCapacity = false; offers: IOffer[] = []; participationConditions: IParticipationCondition[] = []; attendees: string[] = []; - program: string = ''; - commentModeration: CommentModeration = CommentModeration.ALLOW_ALL; - showParticipationPrice: boolean = false; + program = ''; + commentModeration = CommentModeration.ALLOW_ALL; + showParticipationPrice = false; } export class EventModel implements IEvent { @@ -200,6 +200,25 @@ export class EventModel implements IEvent { this.physicalAddress = hash.physicalAddress; this.tags = hash.tags; - this.options = hash.options; + if (hash.options) this.options = hash.options; + } + + toEditJSON () { + return { + id: this.id, + title: this.title, + description: this.description, + beginsOn: this.beginsOn.toISOString(), + endsOn: this.endsOn ? this.endsOn.toISOString() : null, + status: this.status, + visibility: this.visibility, + tags: this.tags.map(t => t.title), + picture: this.picture, + onlineAddress: this.onlineAddress, + phoneAddress: this.phoneAddress, + category: this.category, + physicalAddress: this.physicalAddress, + options: this.options, + }; } } diff --git a/js/src/views/Event/Edit.vue b/js/src/views/Event/Edit.vue index 56bf130b9..4c3c25c5e 100644 --- a/js/src/views/Event/Edit.vue +++ b/js/src/views/Event/Edit.vue @@ -174,10 +174,24 @@ + + - diff --git a/js/src/vue-apollo.ts b/js/src/vue-apollo.ts index 699755eb3..56b700cf8 100644 --- a/js/src/vue-apollo.ts +++ b/js/src/vue-apollo.ts @@ -99,7 +99,9 @@ const link = authMiddleware .concat(errorLink) .concat(uploadLink); -const cache = new InMemoryCache({ fragmentMatcher }); +const cache = new InMemoryCache({ + fragmentMatcher, +}); const apolloClient = new ApolloClient({ cache, diff --git a/lib/mobilizon_web/api/utils.ex b/lib/mobilizon_web/api/utils.ex index 6c983e447..9de90689b 100644 --- a/lib/mobilizon_web/api/utils.ex +++ b/lib/mobilizon_web/api/utils.ex @@ -135,7 +135,7 @@ defmodule MobilizonWeb.API.Utils do end def prepare_content(actor, content, visibility, tags, in_reply_to) do - with content <- String.trim(content), + with content <- String.trim(content || ""), {content_html, mentions, tags} <- make_content_html( content, diff --git a/lib/mobilizon_web/resolvers/event.ex b/lib/mobilizon_web/resolvers/event.ex index 8eadf44a6..869a91e93 100644 --- a/lib/mobilizon_web/resolvers/event.ex +++ b/lib/mobilizon_web/resolvers/event.ex @@ -196,9 +196,9 @@ defmodule MobilizonWeb.Resolvers.Event do # See https://github.com/absinthe-graphql/absinthe/issues/490 with args <- Map.put(args, :options, args[:options] || %{}), {:is_owned, true, organizer_actor} <- User.owns_actor(user, organizer_actor_id), - {:ok, args} <- save_attached_picture(args), - {:ok, args} <- save_physical_address(args), args_with_organizer <- Map.put(args, :organizer_actor, organizer_actor), + {:ok, args_with_organizer} <- save_attached_picture(args_with_organizer), + {:ok, args_with_organizer} <- save_physical_address(args_with_organizer), { :ok, %Activity{ @@ -236,9 +236,9 @@ defmodule MobilizonWeb.Resolvers.Event do with args <- Map.put(args, :options, args[:options] || %{}), {:ok, %Event{} = event} <- Mobilizon.Events.get_event_full(event_id), {:is_owned, true, organizer_actor} <- User.owns_actor(user, event.organizer_actor_id), + args <- Map.put(args, :organizer_actor, organizer_actor), {:ok, args} <- save_attached_picture(args), {:ok, args} <- save_physical_address(args), - args <- Map.put(args, :organizer_actor, organizer_actor), { :ok, %Activity{ @@ -274,7 +274,7 @@ defmodule MobilizonWeb.Resolvers.Event do } } = args ) do - {:ok, Map.put(args, :picture, Map.put(all_pic, :actor_id, args.organizer_actor_id))} + {:ok, Map.put(args, :picture, Map.put(all_pic, :actor_id, args.organizer_actor.id))} end # Otherwise if we use a previously uploaded picture we need to fetch it from database @@ -310,7 +310,7 @@ defmodule MobilizonWeb.Resolvers.Event do end @spec save_physical_address(map()) :: {:ok, map()} - defp save_physical_address(%{physical_address: address} = args) do + defp save_physical_address(%{physical_address: address} = args) when address != nil do with {:ok, %Address{} = address} <- Addresses.create_address(address), args <- Map.put(args, :physical_address, address.url) do {:ok, args} diff --git a/lib/mobilizon_web/schema/event.ex b/lib/mobilizon_web/schema/event.ex index f5d2020b3..e1c15161b 100644 --- a/lib/mobilizon_web/schema/event.ex +++ b/lib/mobilizon_web/schema/event.ex @@ -36,8 +36,8 @@ defmodule MobilizonWeb.Schema.EventType do description: "The type of the event's address" ) - field(:online_address, :online_address, description: "Online address of the event") - field(:phone_address, :phone_address, description: "Phone address for the event") + field(:online_address, :string, description: "Online address of the event") + field(:phone_address, :string, description: "Phone address for the event") field(:organizer_actor, :actor, resolve: dataloader(Actors), @@ -208,9 +208,7 @@ defmodule MobilizonWeb.Schema.EventType do arg(:description, non_null(:string)) arg(:begins_on, non_null(:datetime)) arg(:ends_on, :datetime) - arg(:state, :integer) - arg(:status, :integer) - arg(:public, :boolean) + arg(:status, :event_status) arg(:visibility, :event_visibility, default_value: :private) arg(:tags, list_of(:string), @@ -242,11 +240,8 @@ defmodule MobilizonWeb.Schema.EventType do arg(:description, :string) arg(:begins_on, :datetime) arg(:ends_on, :datetime) - arg(:state, :integer) - arg(:status, :integer) - arg(:public, :boolean) + arg(:status, :event_status) arg(:visibility, :event_visibility) - arg(:organizer_actor_id, :id) arg(:tags, list_of(:string), description: "The list of tags associated to the event") @@ -255,7 +250,6 @@ defmodule MobilizonWeb.Schema.EventType do "The picture for the event, either as an object or directly the ID of an existing Picture" ) - arg(:publish_at, :datetime) arg(:online_address, :string) arg(:phone_address, :string) arg(:category, :string) diff --git a/schema.graphql b/schema.graphql index a3ac11790..b0951bde2 100644 --- a/schema.graphql +++ b/schema.graphql @@ -1,5 +1,5 @@ # source: http://localhost:4000/api -# timestamp: Thu Sep 05 2019 13:00:10 GMT+0200 (GMT+02:00) +# timestamp: Mon Sep 09 2019 11:37:31 GMT+0200 (heure d’été d’Europe centrale) schema { query: RootQueryType @@ -243,7 +243,7 @@ type Event { local: Boolean """Online address of the event""" - onlineAddress: OnlineAddress + onlineAddress: String """The event options""" options: EventOptions @@ -255,7 +255,7 @@ type Event { participants: [Participant] """Phone address for the event""" - phoneAddress: PhoneAddress + phoneAddress: String """The type of the event's address""" physicalAddress: Address @@ -591,11 +591,6 @@ type Member { role: Int } -type OnlineAddress { - info: String - url: String -} - """ Describes how an actor is opened to follows @@ -704,11 +699,6 @@ type Persons { total: Int! } -type PhoneAddress { - info: String - phone: String -} - """A picture""" type Picture { """The picture's alternative text""" @@ -836,9 +826,7 @@ type RootMutationType { The picture for the event, either as an object or directly the ID of an existing Picture """ picture: PictureInput - public: Boolean publishAt: DateTime - state: Int status: Int """The list of tags associated to the event""" @@ -976,7 +964,6 @@ type RootMutationType { eventId: ID! onlineAddress: String options: EventOptionsInput - organizerActorId: ID phoneAddress: String physicalAddress: AddressInput @@ -984,10 +971,7 @@ type RootMutationType { The picture for the event, either as an object or directly the ID of an existing Picture """ picture: PictureInput - public: Boolean - publishAt: DateTime - state: Int - status: Int + status: EventStatus """The list of tags associated to the event""" tags: [String] diff --git a/test/mobilizon_web/resolvers/event_resolver_test.exs b/test/mobilizon_web/resolvers/event_resolver_test.exs index c01f9d0fd..b6ce817d2 100644 --- a/test/mobilizon_web/resolvers/event_resolver_test.exs +++ b/test/mobilizon_web/resolvers/event_resolver_test.exs @@ -486,7 +486,6 @@ defmodule MobilizonWeb.Resolvers.EventResolverTest do description: "description updated", begins_on: "#{begins_on}", event_id: #{event.id}, - organizer_actor_id: "#{actor.id}", category: "birthday", tags: ["tag1_updated", "tag2_updated"] ) { @@ -533,7 +532,6 @@ defmodule MobilizonWeb.Resolvers.EventResolverTest do description: "description updated", begins_on: "#{begins_on}", event_id: #{event.id}, - organizer_actor_id: "#{actor.id}", category: "birthday", picture: { picture: {