Merge branch 'feature/edit-event2' into 'master'
Edit events fixes and update cache See merge request framasoft/mobilizon!180
This commit is contained in:
commit
b9b668fa67
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -198,31 +236,61 @@ export const CREATE_EVENT = gql`
|
||||
export const EDIT_EVENT = gql`
|
||||
mutation updateEvent(
|
||||
$id: ID!,
|
||||
$title: String!,
|
||||
$description: String!,
|
||||
$organizerActorId: ID!,
|
||||
$category: String,
|
||||
$beginsOn: DateTime!,
|
||||
$title: String,
|
||||
$description: String,
|
||||
$beginsOn: DateTime,
|
||||
$endsOn: DateTime,
|
||||
$picture: PictureInput,
|
||||
$tags: [String],
|
||||
$options: EventOptionsInput,
|
||||
$physicalAddress: AddressInput,
|
||||
$status: Int,
|
||||
$visibility: EventVisibility
|
||||
$tags: [String],
|
||||
$picture: PictureInput,
|
||||
$onlineAddress: String,
|
||||
$phoneAddress: String,
|
||||
$category: String,
|
||||
$physicalAddress: AddressInput,
|
||||
$options: EventOptionsInput,
|
||||
) {
|
||||
updateEvent(eventId: $id,
|
||||
updateEvent(
|
||||
eventId: $id,
|
||||
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) {
|
||||
uuid
|
||||
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}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
@ -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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -174,10 +174,24 @@
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/variables.scss";
|
||||
|
||||
h2.subtitle {
|
||||
margin: 10px 0;
|
||||
|
||||
span {
|
||||
padding: 5px 7px;
|
||||
display: inline;
|
||||
background: $secondary;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import { CREATE_EVENT, EDIT_EVENT, FETCH_EVENT } from '@/graphql/event';
|
||||
import { CREATE_EVENT, EDIT_EVENT, FETCH_EVENT, FETCH_EVENTS } from '@/graphql/event';
|
||||
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
|
||||
import { EventModel, EventStatus, EventVisibility, EventVisibilityJoinOptions, CommentModeration } from '@/types/event.model';
|
||||
import { EventModel, EventStatus, EventVisibility, EventVisibilityJoinOptions, CommentModeration, IEvent } from '@/types/event.model';
|
||||
import { LOGGED_PERSON } from '@/graphql/actor';
|
||||
import { IPerson, Person } from '@/types/actor';
|
||||
import PictureUpload from '@/components/PictureUpload.vue';
|
||||
@ -291,12 +305,7 @@ export default class EditEvent extends Vue {
|
||||
* Build variables for Event GraphQL creation query
|
||||
*/
|
||||
private buildVariables() {
|
||||
const obj = {
|
||||
organizerActorId: this.loggedPerson.id,
|
||||
beginsOn: this.event.beginsOn.toISOString(),
|
||||
tags: this.event.tags.map((tag: ITag) => tag.title),
|
||||
};
|
||||
const res = Object.assign({}, this.event, obj);
|
||||
const res = Object.assign(this.event.toEditJSON(), { organizerActorId: this.loggedPerson.id });
|
||||
|
||||
delete this.event.options['__typename'];
|
||||
|
||||
@ -360,16 +369,4 @@ export default class EditEvent extends Vue {
|
||||
// }
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import "@/variables.scss";
|
||||
|
||||
h2.subtitle {
|
||||
margin: 10px 0;
|
||||
|
||||
span {
|
||||
padding: 5px 7px;
|
||||
display: inline;
|
||||
background: $secondary;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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}
|
||||
|
@ -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)
|
||||
|
@ -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]
|
||||
|
@ -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: {
|
||||
|
Loading…
Reference in New Issue
Block a user