Show notice when event pending mandatory revision
This commit is contained in:
parent
8b6065baf0
commit
b84555dcae
|
@ -4,7 +4,7 @@
|
|||
"extensions": {
|
||||
"endpoints": {
|
||||
"Default GraphQL Endpoint": {
|
||||
"url": "https://alpha.quepasaalpujarra.com/graphql",
|
||||
"url": "http://localhost:4000/graphql",
|
||||
"headers": {
|
||||
"user-agent": "JS GraphQL"
|
||||
},
|
||||
|
|
|
@ -60,6 +60,7 @@ declare namespace GQL {
|
|||
location: ILocation;
|
||||
occurrences: Array<IEventOccurrence | null> | null;
|
||||
owner: IUser;
|
||||
publishedState: any;
|
||||
status: any;
|
||||
tags: Array<IEventTag | null> | null;
|
||||
time: IEventTime;
|
||||
|
@ -72,6 +73,7 @@ declare namespace GQL {
|
|||
interface IEventImages {
|
||||
__typename: 'EventImages';
|
||||
cover: IEventImage | null;
|
||||
event: ICalendarEvent | null;
|
||||
gallery: Array<IEventImage> | null;
|
||||
poster: IEventImage | null;
|
||||
thumb: IEventImage | null;
|
||||
|
@ -170,13 +172,17 @@ declare namespace GQL {
|
|||
createEventTag: IEventTag | null;
|
||||
deleteEvent: IUser;
|
||||
deleteEventTag: Array<IEventTag | null> | null;
|
||||
dismissOpenEventRevision: IEventRevision | null;
|
||||
grantRole: IUser;
|
||||
removeEventGalleryImages: ICalendarEvent | null;
|
||||
requestEventRevision: ICalendarEvent | null;
|
||||
requestInvite: boolean;
|
||||
revokeRole: IUser;
|
||||
setEventImage: ICalendarEvent | null;
|
||||
signin: IUserSession;
|
||||
signup: Array<IError | null> | null;
|
||||
startEventRevision: IEventRevision | null;
|
||||
submitEventRevision: IEventRevision | null;
|
||||
unsetEventImage: ICalendarEvent | null;
|
||||
updateEvent: ICalendarEvent | null;
|
||||
updateEventTag: IEventTag | null;
|
||||
|
@ -202,6 +208,10 @@ declare namespace GQL {
|
|||
input: IDeleteEventTagInput;
|
||||
}
|
||||
|
||||
interface IDismissOpenEventRevisionOnMutationArguments {
|
||||
input: IEventRevisionInput;
|
||||
}
|
||||
|
||||
interface IGrantRoleOnMutationArguments {
|
||||
input: IGrantRoleInput;
|
||||
}
|
||||
|
@ -210,6 +220,10 @@ declare namespace GQL {
|
|||
input: IEventGalleryImagesInput;
|
||||
}
|
||||
|
||||
interface IRequestEventRevisionOnMutationArguments {
|
||||
input: IRequestRevisionInput;
|
||||
}
|
||||
|
||||
interface IRequestInviteOnMutationArguments {
|
||||
input: IRequestInviteInput;
|
||||
}
|
||||
|
@ -230,6 +244,14 @@ declare namespace GQL {
|
|||
input: ISignupInput;
|
||||
}
|
||||
|
||||
interface IStartEventRevisionOnMutationArguments {
|
||||
input: IStartEventRevisionInput;
|
||||
}
|
||||
|
||||
interface ISubmitEventRevisionOnMutationArguments {
|
||||
input: IReviseEventInput;
|
||||
}
|
||||
|
||||
interface IUnsetEventImageOnMutationArguments {
|
||||
id: IUnsetEventImageInput;
|
||||
}
|
||||
|
@ -250,7 +272,7 @@ declare namespace GQL {
|
|||
interface ICreateEventInput {
|
||||
infos: Array<IEventInformationInput | null>;
|
||||
location: IEventLocationInput;
|
||||
status: string;
|
||||
publishedState: any;
|
||||
tagNames: Array<string>;
|
||||
time: IEventTimeInput;
|
||||
}
|
||||
|
@ -288,6 +310,23 @@ declare namespace GQL {
|
|||
id: string;
|
||||
}
|
||||
|
||||
interface IEventRevisionInput {
|
||||
revisionId: string;
|
||||
}
|
||||
|
||||
interface IEventRevision {
|
||||
__typename: 'EventRevision';
|
||||
accepting: boolean | null;
|
||||
author: IUser;
|
||||
comment: string | null;
|
||||
createdAt: any;
|
||||
denying: boolean | null;
|
||||
event: ICalendarEvent;
|
||||
id: string;
|
||||
spam: boolean | null;
|
||||
submittedAt: any | null;
|
||||
}
|
||||
|
||||
interface IGrantRoleInput {
|
||||
roleType: any;
|
||||
userId: string;
|
||||
|
@ -298,6 +337,10 @@ declare namespace GQL {
|
|||
imageIds: Array<string>;
|
||||
}
|
||||
|
||||
interface IRequestRevisionInput {
|
||||
eventId: string;
|
||||
}
|
||||
|
||||
interface IRequestInviteInput {
|
||||
email: string;
|
||||
}
|
||||
|
@ -332,6 +375,18 @@ declare namespace GQL {
|
|||
path: string;
|
||||
}
|
||||
|
||||
interface IStartEventRevisionInput {
|
||||
eventId: string;
|
||||
}
|
||||
|
||||
interface IReviseEventInput {
|
||||
accepting: boolean;
|
||||
comment?: string | null;
|
||||
denying: boolean;
|
||||
revisionId: string;
|
||||
spam: boolean;
|
||||
}
|
||||
|
||||
interface IUnsetEventImageInput {
|
||||
eventId: string;
|
||||
imageType?: any | null;
|
||||
|
@ -341,6 +396,7 @@ declare namespace GQL {
|
|||
id: string;
|
||||
infos?: Array<IEventInformationInput> | null;
|
||||
location?: IEventLocationInput | null;
|
||||
publishedState: any;
|
||||
status?: string | null;
|
||||
tagNames: Array<string>;
|
||||
time?: IEventTimeInput | null;
|
||||
|
|
|
@ -2,3 +2,8 @@ export type EventStatus = "confirmed" | "canceled"
|
|||
export type EventImageType = "cover" | "thumb" | "gallery" | "poster"
|
||||
declare module "*.png"
|
||||
declare module "*.svg"
|
||||
|
||||
export enum EventPublishedState {
|
||||
PUBLISHED = "published",
|
||||
DRAFT = "draft",
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
{
|
||||
"en-GB": {
|
||||
"upload-cover-image": "Upload cover image",
|
||||
"upload-poster-image": "Upload poster image"
|
||||
"upload-poster-image": "Upload poster image",
|
||||
"event-awaiting-mandatory-revision": "This event is pending revision. Our team will soon revise this event and set it online!"
|
||||
},
|
||||
"es-ES": {
|
||||
"upload-cover-image": "Subir imagen de fondo",
|
||||
"upload-poster-image": "Subir imagen de cartel"
|
||||
"upload-poster-image": "Subir imagen de cartel",
|
||||
"event-awaiting-mandatory-revision": "Este evento está pendiente de una revisión. ¡Nuestro equipo revisará este evento pronto y lo publicarémos!"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,22 @@
|
|||
import { format } from "date-fns"
|
||||
import styled, { css } from "qpa-emotion"
|
||||
import { Button } from "qpa-components"
|
||||
import styled, { css, useTheme } from "qpa-emotion"
|
||||
import * as React from "react"
|
||||
import { hot } from "react-hot-loader"
|
||||
import intl from "react-intl-universal"
|
||||
import { RouteComponentProps, withRouter } from "react-router"
|
||||
import { OccurrenceData } from "../../Event/useOccurrencesQuery"
|
||||
import EventTags from "../../EventTags/EventTags"
|
||||
import { useAppContext } from "../Context/AppContext"
|
||||
import { EventDetailsData } from "./useEventDetailsQuery"
|
||||
import EventImageUpload from "./EventImageUpload"
|
||||
import intl from "react-intl-universal"
|
||||
import messages from "./EventDetails.msg.json"
|
||||
import EventImageUpload from "./EventImageUpload"
|
||||
import { EventDetailsData, EventRevisionState } from "./useEventDetailsQuery"
|
||||
|
||||
interface Props extends RouteComponentProps {
|
||||
interface Params {
|
||||
eventId: string
|
||||
}
|
||||
|
||||
interface Props extends RouteComponentProps<Params> {
|
||||
event: EventDetailsData
|
||||
occurrence?: OccurrenceData
|
||||
}
|
||||
|
@ -22,6 +26,7 @@ const EventDetails = (props: Props) => {
|
|||
|
||||
const { me, language } = useAppContext()
|
||||
const event = props.event
|
||||
const theme = useTheme()
|
||||
|
||||
const meIsOwner = me && me.id === event.owner.id
|
||||
const canEdit =
|
||||
|
@ -32,6 +37,16 @@ const EventDetails = (props: Props) => {
|
|||
event.infos.find(info => info.language === language) || event.infos[0]
|
||||
return (
|
||||
<Root>
|
||||
{event.revisionState ===
|
||||
EventRevisionState.PENDING_MANDATORY_REVISION && (
|
||||
<CommentToPublishedState
|
||||
css={css`
|
||||
color: ${theme.colors.lead};
|
||||
`}
|
||||
>
|
||||
{intl.get("event-awaiting-mandatory-revision")}
|
||||
</CommentToPublishedState>
|
||||
)}
|
||||
{canEdit ? (
|
||||
<EditButton
|
||||
onClick={() => props.history.push(`/event/${event.id}/edit`)}
|
||||
|
@ -83,7 +98,6 @@ const EditButton = styled(Button)`
|
|||
const Title = styled.div`
|
||||
grid-column: content;
|
||||
font-size: 32px;
|
||||
grid-row: 1/1;
|
||||
`
|
||||
|
||||
const Info = styled.div`
|
||||
|
@ -128,4 +142,16 @@ const StyledEventTags = styled(EventTags)`
|
|||
const OccurrenceTime = styled.div`
|
||||
grid-column: content;
|
||||
`
|
||||
|
||||
const CommentToPublishedState = styled.div`
|
||||
grid-column: content;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
border: dashed yellow 2px;
|
||||
border-radius: 3px;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 14px;
|
||||
`
|
||||
export default hot(module)(withRouter(EventDetails))
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
import { Spinner } from "qpa-components"
|
||||
import * as React from "react"
|
||||
import { RouteComponentProps, withRouter } from "react-router"
|
||||
import { useAppContext } from "../Context/AppContext"
|
||||
import EventDetails from "./EventDetails"
|
||||
import useEventDetailsQuery from "./useEventDetailsQuery"
|
||||
|
||||
interface Params {
|
||||
eventId: string
|
||||
}
|
||||
|
||||
interface Props extends RouteComponentProps<Params> {}
|
||||
|
||||
const EventDetailsRoute = (props: Props) => {
|
||||
const { language } = useAppContext()
|
||||
const { data, loading, error } = useEventDetailsQuery({
|
||||
variables: {
|
||||
eventId: props.match.params.eventId,
|
||||
language,
|
||||
},
|
||||
})
|
||||
|
||||
if (loading) {
|
||||
return <Spinner />
|
||||
}
|
||||
if (error) {
|
||||
return <p>{error.message}</p>
|
||||
}
|
||||
return <EventDetails event={data.event} />
|
||||
}
|
||||
|
||||
export default withRouter(EventDetailsRoute)
|
|
@ -1,5 +1,6 @@
|
|||
import { QueryHookOptions, useQuery } from "@apollo/react-hooks"
|
||||
import gql from "graphql-tag"
|
||||
import {EventPublishedState} from "../../../../@types"
|
||||
import {
|
||||
EventTagTranslatedData,
|
||||
TranslationDataFragment,
|
||||
|
@ -10,6 +11,15 @@ export const EventImageDataFragment = gql`
|
|||
url,
|
||||
}
|
||||
`
|
||||
export enum EventRevisionState {
|
||||
PENDING_SUGGESTED_REVISION = "pending_suggested_revision",
|
||||
PENDING_MANDATORY_REVISION = "pending_mandatory_revision",
|
||||
CHANGES_REQUIRED = "changes_required",
|
||||
ACCEPTED = "accepted",
|
||||
DENIED = "denied",
|
||||
SPAM = "spam",
|
||||
}
|
||||
|
||||
export interface EventImageData {
|
||||
url: string
|
||||
}
|
||||
|
@ -35,6 +45,8 @@ export const EventDetailsDataFragment = gql`
|
|||
start
|
||||
end
|
||||
}
|
||||
publishedState
|
||||
revisionState
|
||||
images {
|
||||
cover {
|
||||
...EventImageData
|
||||
|
@ -79,6 +91,8 @@ export interface EventDetailsData {
|
|||
language
|
||||
title
|
||||
}>
|
||||
revisionState: EventRevisionState
|
||||
publishedState: EventPublishedState
|
||||
images: EventImagesData
|
||||
occurrences: {
|
||||
id: string
|
||||
|
|
|
@ -11,11 +11,13 @@ import Login from "./Auth/Login"
|
|||
import Signout from "./Auth/Signout"
|
||||
import Signup from "./Auth/Signup"
|
||||
import { useAppContext } from "./Context/AppContext"
|
||||
import EventDetails from "./Event/EventDetails"
|
||||
import EventDetailsRoute from "./Event/EventDetailsRoute"
|
||||
import OccurrenceDetails from "./Event/OccurrenceDetails"
|
||||
|
||||
const Routes = () => {
|
||||
const { me } = useAppContext()
|
||||
const roles = me?.roles?.map(role => role.type)
|
||||
const roles = me?.roles?.map(role => role.type)
|
||||
return (
|
||||
<Switch>
|
||||
<Route path="/create" component={roles ? CreateEvent : Signup} />
|
||||
|
@ -29,6 +31,10 @@ const Routes = () => {
|
|||
path="/o/:sanitizedEventName/:occurrenceId"
|
||||
component={OccurrenceDetails}
|
||||
/>
|
||||
<Route
|
||||
path="/e/:sanitizedEventName/:eventId"
|
||||
component={EventDetailsRoute}
|
||||
/>
|
||||
<Route path="/init-session/:hash" component={InitializeSession} />
|
||||
<Route path="/login" component={Login} />
|
||||
<Route path="/signup" component={Signup} />
|
||||
|
|
|
@ -16,8 +16,11 @@ const CreateEvent = (props: RouteComponentProps) => {
|
|||
type: "success",
|
||||
text: intl.get("event-create-success"),
|
||||
})
|
||||
props.history.push(`/o/aaa/${data.createEvent.occurrences[0].id}`)
|
||||
|
||||
if (data.createEvent.occurrences.length) {
|
||||
props.history.push(`/o/aaa/${data.createEvent.occurrences[0].id}`)
|
||||
} else {
|
||||
props.history.push(`/e/aaa/${data.createEvent.id}`)
|
||||
}
|
||||
},
|
||||
onError: error => {
|
||||
addMessage({
|
||||
|
@ -40,7 +43,7 @@ const CreateEvent = (props: RouteComponentProps) => {
|
|||
...values.time,
|
||||
timeZone: "Europe/Madrid",
|
||||
},
|
||||
status: "confirmed",
|
||||
publishedState: values.publishedState,
|
||||
tagNames: values.tagNames,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -11,7 +11,7 @@ import {
|
|||
import * as React from "react"
|
||||
import styled from "@emotion/styled"
|
||||
import { hot } from "react-hot-loader"
|
||||
import { EventStatus } from "../../../@types"
|
||||
import {EventPublishedState, EventStatus} from "../../../@types"
|
||||
import * as intl from "react-intl-universal"
|
||||
import TagSelector from "../EventTags/TagsSelector"
|
||||
import messages from "./EventForm.msg.json"
|
||||
|
@ -47,6 +47,7 @@ export interface EventFormData {
|
|||
}
|
||||
status: EventStatus
|
||||
tagNames: string[]
|
||||
publishedState: EventPublishedState
|
||||
}
|
||||
|
||||
const todayMidday = new Date()
|
||||
|
@ -106,6 +107,7 @@ const EventForm = (props: Props) => {
|
|||
},
|
||||
tagNames: [],
|
||||
status: "confirmed",
|
||||
publishedState: "published"
|
||||
} as EventFormData)
|
||||
}
|
||||
validate={(values: EventFormData) => {
|
||||
|
|
|
@ -13,6 +13,8 @@ type CalendarEvent {
|
|||
location: Location!
|
||||
occurrences: [EventOccurrence]
|
||||
owner: User!
|
||||
publishedState: EventPublishedState!
|
||||
revisionState: EventRevisionState!
|
||||
status: EventStatus!
|
||||
tags: [EventTag]
|
||||
time: EventTime!
|
||||
|
@ -29,6 +31,7 @@ type EventImage {
|
|||
|
||||
type EventImages {
|
||||
cover: EventImage
|
||||
event: CalendarEvent
|
||||
gallery: [EventImage!]
|
||||
poster: EventImage
|
||||
thumb: EventImage
|
||||
|
@ -47,6 +50,18 @@ type EventOccurrence {
|
|||
start: String!
|
||||
}
|
||||
|
||||
type EventRevision {
|
||||
accepting: Boolean
|
||||
author: User!
|
||||
comment: String
|
||||
createdAt: Date!
|
||||
denying: Boolean
|
||||
event: CalendarEvent!
|
||||
id: ID!
|
||||
spam: Boolean
|
||||
submittedAt: Date
|
||||
}
|
||||
|
||||
type EventTag {
|
||||
id: ID!
|
||||
name: String!
|
||||
|
@ -79,13 +94,17 @@ type Mutation {
|
|||
createEventTag(input: CreateEventTagInput!): EventTag
|
||||
deleteEvent(id: ID!): User!
|
||||
deleteEventTag(input: DeleteEventTagInput!): [EventTag]
|
||||
dismissOpenEventRevision(input: EventRevisionInput!): EventRevision
|
||||
grantRole(input: GrantRoleInput!): User!
|
||||
removeEventGalleryImages(input: EventGalleryImagesInput!): CalendarEvent
|
||||
requestEventRevision(input: RequestRevisionInput!): CalendarEvent
|
||||
requestInvite(input: RequestInviteInput!): Boolean!
|
||||
revokeRole(input: GrantRoleInput!): User!
|
||||
setEventImage(input: EventImageUploadInput!): CalendarEvent
|
||||
signin(input: SigninInput!): UserSession!
|
||||
signup(input: SignupInput!): [Error]
|
||||
startEventRevision(input: StartEventRevisionInput!): EventRevision
|
||||
submitEventRevision(input: ReviseEventInput!): EventRevision
|
||||
unsetEventImage(id: UnsetEventImageInput!): CalendarEvent
|
||||
updateEvent(input: UpdateEventInput!): CalendarEvent
|
||||
updateEventTag(input: UpdateEventTagInput!): EventTag
|
||||
|
@ -130,7 +149,7 @@ enum CacheControlScope {
|
|||
input CreateEventInput {
|
||||
infos: [EventInformationInput]!
|
||||
location: EventLocationInput!
|
||||
status: String!
|
||||
publishedState: EventPublishedState!
|
||||
tagNames: [String!]!
|
||||
time: EventTimeInput!
|
||||
}
|
||||
|
@ -176,6 +195,10 @@ input EventLocationInput {
|
|||
name: String
|
||||
}
|
||||
|
||||
input EventRevisionInput {
|
||||
revisionId: ID!
|
||||
}
|
||||
|
||||
input EventTimeInput {
|
||||
end: Timestamp!
|
||||
exceptions: String
|
||||
|
@ -209,6 +232,18 @@ input RequestInviteInput {
|
|||
email: String!
|
||||
}
|
||||
|
||||
input RequestRevisionInput {
|
||||
eventId: ID!
|
||||
}
|
||||
|
||||
input ReviseEventInput {
|
||||
accepting: Boolean!
|
||||
comment: String
|
||||
denying: Boolean!
|
||||
revisionId: ID!
|
||||
spam: Boolean!
|
||||
}
|
||||
|
||||
input RevokeRoleInput {
|
||||
roleType: RoleType!
|
||||
userId: ID!
|
||||
|
@ -224,6 +259,10 @@ input SignupInput {
|
|||
username: String!
|
||||
}
|
||||
|
||||
input StartEventRevisionInput {
|
||||
eventId: ID!
|
||||
}
|
||||
|
||||
input UnsetEventImageInput {
|
||||
eventId: ID!
|
||||
imageType: EventImageType
|
||||
|
@ -233,6 +272,7 @@ input UpdateEventInput {
|
|||
id: ID!
|
||||
infos: [EventInformationInput!]
|
||||
location: EventLocationInput
|
||||
publishedState: EventPublishedState!
|
||||
status: String
|
||||
tagNames: [String!]!
|
||||
time: EventTimeInput
|
||||
|
@ -251,6 +291,10 @@ scalar Timestamp
|
|||
|
||||
scalar EventStatus
|
||||
|
||||
scalar EventPublishedState
|
||||
|
||||
scalar EventRevisionState
|
||||
|
||||
scalar RoleType
|
||||
|
||||
scalar Category
|
||||
|
|
Loading…
Reference in New Issue