Add revision to new events from new users
This commit is contained in:
parent
a8849fb1d0
commit
cbac3ac64b
|
@ -27,6 +27,7 @@ declare namespace GQL {
|
|||
me: IUser | null;
|
||||
occurrence: IEventOccurrence | null;
|
||||
occurrences: Array<IEventOccurrence | null> | null;
|
||||
revisions: Array<IEventRevision | null> | null;
|
||||
tags: Array<IEventTag | null> | null;
|
||||
user: IUser | null;
|
||||
}
|
||||
|
@ -47,6 +48,10 @@ declare namespace GQL {
|
|||
filter: IOccurrencesQueryFilter;
|
||||
}
|
||||
|
||||
interface IRevisionsOnQueryArguments {
|
||||
filter: IRevisionsQueryFilter;
|
||||
}
|
||||
|
||||
interface IUserOnQueryArguments {
|
||||
id: string;
|
||||
}
|
||||
|
@ -133,6 +138,7 @@ declare namespace GQL {
|
|||
dismissedBy: IUser | null;
|
||||
event: ICalendarEvent;
|
||||
id: string;
|
||||
lastChangedAt: any;
|
||||
submittedAt: any | null;
|
||||
}
|
||||
|
||||
|
@ -178,6 +184,10 @@ declare namespace GQL {
|
|||
to?: any | null;
|
||||
}
|
||||
|
||||
interface IRevisionsQueryFilter {
|
||||
limit?: number | null;
|
||||
}
|
||||
|
||||
interface IMutation {
|
||||
__typename: 'Mutation';
|
||||
addEventGalleryImages: ICalendarEvent | null;
|
||||
|
|
|
@ -4,5 +4,7 @@ import CrossNoIcon from "@material-ui/icons/HighlightOff"
|
|||
import PlayIcon from "@material-ui/icons/PlayCircleOutline"
|
||||
import StopIcon from '@material-ui/icons/Stop';
|
||||
import DeleteForeverIcon from '@material-ui/icons/DeleteForever';
|
||||
import ReplayIcon from '@material-ui/icons/Replay';
|
||||
|
||||
export { TagIcon, CheckIcon, CrossNoIcon, PlayIcon, StopIcon, DeleteForeverIcon }
|
||||
|
||||
export { TagIcon, CheckIcon, CrossNoIcon, PlayIcon, StopIcon, DeleteForeverIcon, ReplayIcon }
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
import styled from "@emotion/styled"
|
||||
import { ReplayIcon, IconButton, ListItem, ListItemText } from "qpa-components"
|
||||
import { useMessageCenter } from "qpa-message-center"
|
||||
import * as React from "react"
|
||||
import { Link } from "react-router-dom"
|
||||
import { EventRevisionState } from "../Event/useEventDetailsQuery"
|
||||
import { PastRevisionData } from "./usePastRevisionsQuery"
|
||||
import intl from "react-intl-universal"
|
||||
import useRequestNewRevisionMutation from "./useRequestNewRevisionMutation"
|
||||
import css from "@emotion/css"
|
||||
interface Props {
|
||||
revision: PastRevisionData
|
||||
language: string
|
||||
onRefetchPendingEvents: () => void
|
||||
}
|
||||
|
||||
const PastRevisionListItem = (props: Props) => {
|
||||
const event = props.revision.event
|
||||
const { notifyError } = useMessageCenter()
|
||||
const languageIndex = event.infos.findIndex(
|
||||
info => info.language === props.language
|
||||
)
|
||||
const [
|
||||
requestNewRevision,
|
||||
{
|
||||
data: requestNewRevisionData,
|
||||
loading: requestNewRevisionLoading,
|
||||
error: requestNewRevisionError,
|
||||
},
|
||||
] = useRequestNewRevisionMutation({
|
||||
variables: {
|
||||
input: { eventId: event.id },
|
||||
},
|
||||
onError: notifyError,
|
||||
})
|
||||
const eventInfo = props.revision.event.infos[languageIndex || 0]
|
||||
const eventIsPendingRevision = [
|
||||
EventRevisionState.PENDING_SUGGESTED_REVISION,
|
||||
EventRevisionState.PENDING_MANDATORY_REVISION,
|
||||
].includes(event.revisionState)
|
||||
|
||||
return (
|
||||
<ListItem>
|
||||
<ListItemText>
|
||||
<Link to={`/e/aaa/${event.id}`}>{eventInfo.title}</Link>
|
||||
<div>
|
||||
{props.revision.dismissedBy
|
||||
? intl.get("dismissed-by", {
|
||||
name: props.revision.dismissedBy.name,
|
||||
})
|
||||
: props.revision.conclusion}
|
||||
</div>
|
||||
<div
|
||||
css={css`
|
||||
font-size: 12px;
|
||||
`}
|
||||
>
|
||||
{intl.get("last-change")}: {props.revision.lastChangedAt}
|
||||
</div>
|
||||
</ListItemText>
|
||||
<ActionItems>
|
||||
<IconButton
|
||||
edge="end"
|
||||
aria-label="request new revision"
|
||||
label={intl.get("request-new-revision")}
|
||||
onClick={() => requestNewRevision()}
|
||||
disabled={eventIsPendingRevision}
|
||||
>
|
||||
<ReplayIcon />
|
||||
</IconButton>
|
||||
</ActionItems>
|
||||
</ListItem>
|
||||
)
|
||||
}
|
||||
|
||||
const ActionItems = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
> *:not(:first-of-type) {
|
||||
margin-left: 8px;
|
||||
}
|
||||
`
|
||||
|
||||
export default PastRevisionListItem
|
|
@ -1,8 +1,16 @@
|
|||
{
|
||||
"en-GB": {
|
||||
"revision-successful": "Revision was submitted successfully"
|
||||
"revision-successful": "Revision was submitted successfully",
|
||||
"events-pending-revision": "Events pending revision",
|
||||
"dismissed-by": "Dismissed by {name}",
|
||||
"request-new-revision": "Resubmit",
|
||||
"last-change": "Last change"
|
||||
},
|
||||
"es-ES": {
|
||||
"revision-successful": "Event ha sido revisado correctamente"
|
||||
"revision-successful": "Event ha sido revisado correctamente",
|
||||
"events-pending-revision": "Eventos pendientes a revisar",
|
||||
"dismissed-by": "Anulado por {name}",
|
||||
"request-new-revision": "Solicitar",
|
||||
"last-change": "Última actualisación"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,47 +1,106 @@
|
|||
import {Checkbox, ListItem, ListItemSecondaryAction, ListItemText, Spinner} from "qpa-components"
|
||||
import {List} from "qpa-components/List"
|
||||
import * as React from 'react'
|
||||
import {RouteComponentProps, withRouter} from "react-router"
|
||||
import {useAppContext} from "../Context/AppContext"
|
||||
import {
|
||||
Checkbox,
|
||||
ListItem,
|
||||
ListItemSecondaryAction,
|
||||
ListItemText,
|
||||
Spinner,
|
||||
} from "qpa-components"
|
||||
import { List } from "qpa-components/List"
|
||||
import * as React from "react"
|
||||
import { RouteComponentProps, withRouter } from "react-router"
|
||||
import { useAppContext } from "../Context/AppContext"
|
||||
import PastRevisionListItem from "./PastRevisionListItem"
|
||||
import ReviseListItem from "./ReviseListItem"
|
||||
import useEventsPendingRevisionQuery from "./useEventsPendingRevisionQuery"
|
||||
import messages from './ReviseEvents.msg.json'
|
||||
import intl from 'react-intl-universal'
|
||||
import messages from "./ReviseEvents.msg.json"
|
||||
import intl from "react-intl-universal"
|
||||
import styled from "@emotion/styled"
|
||||
import usePastRevisionsQuery from "./usePastRevisionsQuery"
|
||||
|
||||
interface Props extends RouteComponentProps {
|
||||
|
||||
}
|
||||
interface Props extends RouteComponentProps {}
|
||||
|
||||
const ReviseEvents = (props: Props) => {
|
||||
intl.load(messages)
|
||||
const {data,loading,error} = useEventsPendingRevisionQuery()
|
||||
const { language } = useAppContext()
|
||||
const [selectedIds, setSelectedIds] = React.useState(new Set<string>())
|
||||
if (loading) {
|
||||
return <Spinner />
|
||||
}
|
||||
if (error) {
|
||||
return <p>{error.message}</p>
|
||||
}
|
||||
return <List>
|
||||
{
|
||||
data.events.map(event => {
|
||||
const isChecked = selectedIds.has(event.id)
|
||||
return (
|
||||
<ReviseListItem key={event.id} isChecked={isChecked} event={event} language={language} onCheckedChange={() => {
|
||||
const newSelectedIds = new Set(selectedIds)
|
||||
if (isChecked) {
|
||||
newSelectedIds.delete(event.id)
|
||||
} else {
|
||||
newSelectedIds.add(event.id)
|
||||
}
|
||||
setSelectedIds(newSelectedIds)
|
||||
}}/>
|
||||
)
|
||||
})
|
||||
}
|
||||
</List>
|
||||
intl.load(messages)
|
||||
const {
|
||||
data: pendingEventsData,
|
||||
loading: pendingEventsLoading,
|
||||
error: pendingEventsError,
|
||||
refetch: pendingEventsRefetch,
|
||||
} = useEventsPendingRevisionQuery()
|
||||
const {
|
||||
data: pastRevisionsData,
|
||||
loading: pastRevisionsLoading,
|
||||
error: pastRevisionsError,
|
||||
} = usePastRevisionsQuery()
|
||||
|
||||
const { language } = useAppContext()
|
||||
const [selectedIds, setSelectedIds] = React.useState(new Set<string>())
|
||||
if (pendingEventsLoading) {
|
||||
return <Spinner />
|
||||
}
|
||||
if (pendingEventsError) {
|
||||
return <p>{pendingEventsError.message}</p>
|
||||
}
|
||||
return (
|
||||
<Root>
|
||||
<Section>
|
||||
<Title>{intl.get("events-pending-revision")}</Title>
|
||||
{pendingEventsLoading ? (
|
||||
<Spinner />
|
||||
) : (
|
||||
<List>
|
||||
{pendingEventsData.events.map(event => {
|
||||
const isChecked = selectedIds.has(event.id)
|
||||
return (
|
||||
<ReviseListItem
|
||||
key={event.id}
|
||||
isChecked={isChecked}
|
||||
event={event}
|
||||
language={language}
|
||||
onCheckedChange={() => {
|
||||
const newSelectedIds = new Set(selectedIds)
|
||||
if (isChecked) {
|
||||
newSelectedIds.delete(event.id)
|
||||
} else {
|
||||
newSelectedIds.add(event.id)
|
||||
}
|
||||
setSelectedIds(newSelectedIds)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</List>
|
||||
)}
|
||||
</Section>
|
||||
<Section>
|
||||
<Title>Past revisions</Title>
|
||||
{pastRevisionsLoading ? (
|
||||
<Spinner />
|
||||
) : (
|
||||
<List>
|
||||
{pastRevisionsData.revisions?.map(revision => {
|
||||
return (
|
||||
<PastRevisionListItem
|
||||
revision={revision}
|
||||
language={language}
|
||||
key={revision.id}
|
||||
onRefetchPendingEvents={() => pendingEventsRefetch()}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</List>
|
||||
)}
|
||||
</Section>
|
||||
</Root>
|
||||
)
|
||||
}
|
||||
|
||||
const Root = styled.div`
|
||||
padding: 24px;
|
||||
`
|
||||
const Section = styled.section``
|
||||
const Title = styled.div`
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
font-size: 1.5em;
|
||||
`
|
||||
export default withRouter(ReviseEvents)
|
||||
|
|
|
@ -1,7 +1,25 @@
|
|||
import { QueryHookOptions, useQuery } from "@apollo/react-hooks"
|
||||
import gql from "graphql-tag"
|
||||
|
||||
export const RevisionFragment = gql`
|
||||
fragment RevisionData on EventRevision {
|
||||
id
|
||||
author {
|
||||
id
|
||||
name
|
||||
}
|
||||
createdAt
|
||||
submittedAt
|
||||
conclusion
|
||||
lastChangedAt
|
||||
dismissedBy {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
`
|
||||
export const RevisionPendingEventFragment = gql`
|
||||
${RevisionFragment}
|
||||
fragment PendingEvent on CalendarEvent {
|
||||
id
|
||||
infos {
|
||||
|
@ -10,17 +28,7 @@ export const RevisionPendingEventFragment = gql`
|
|||
}
|
||||
revisionState
|
||||
revisions {
|
||||
id
|
||||
author {
|
||||
id
|
||||
name
|
||||
}
|
||||
createdAt
|
||||
submittedAt
|
||||
dismissedBy {
|
||||
id
|
||||
name
|
||||
}
|
||||
...RevisionData
|
||||
}
|
||||
}
|
||||
`
|
||||
|
@ -32,7 +40,7 @@ const query = gql`
|
|||
}
|
||||
}
|
||||
`
|
||||
interface RevisionData {
|
||||
export interface RevisionData {
|
||||
id: string
|
||||
author: {
|
||||
id: string
|
||||
|
@ -40,6 +48,8 @@ interface RevisionData {
|
|||
}
|
||||
createdAt: Date
|
||||
submittedAt?: Date
|
||||
lastChangedAt: Date
|
||||
conclusion?: string
|
||||
dismissedBy?: RevisionDismissingUserData
|
||||
}
|
||||
interface RevisionDismissingUserData {
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
import {QueryHookOptions, useQuery} from "@apollo/react-hooks"
|
||||
import gql from "graphql-tag"
|
||||
import {EventRevisionState} from "../Event/useEventDetailsQuery"
|
||||
import {RevisionData, RevisionFragment} from "./useEventsPendingRevisionQuery"
|
||||
|
||||
const query = gql`
|
||||
${RevisionFragment}
|
||||
query PastRevisions($limit: Int) {
|
||||
revisions(filter: {limit: $limit}) {
|
||||
...RevisionData
|
||||
dismissedBy {
|
||||
id
|
||||
name
|
||||
}
|
||||
event {
|
||||
id
|
||||
revisionState
|
||||
infos {
|
||||
title
|
||||
language
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
export interface PastRevisionData extends RevisionData{
|
||||
dismissedBy?: {
|
||||
id: string
|
||||
name: string
|
||||
}
|
||||
event: {
|
||||
revisionState: EventRevisionState
|
||||
id: string
|
||||
infos: Array<{
|
||||
language: string
|
||||
title: string
|
||||
}>
|
||||
}
|
||||
}
|
||||
interface Data {
|
||||
revisions: PastRevisionData[]
|
||||
}
|
||||
interface Variables {
|
||||
limit?: number
|
||||
}
|
||||
const usePastRevisionsQuery = (options?: QueryHookOptions<Data, Variables>) => useQuery<Data,Variables>(query, options)
|
||||
|
||||
export default usePastRevisionsQuery
|
|
@ -0,0 +1,25 @@
|
|||
import { QueryHookOptions, useMutation } from "@apollo/react-hooks"
|
||||
import gql from "graphql-tag"
|
||||
import {
|
||||
RevisionPendingEventFragment,
|
||||
RevisionPendingEventData,
|
||||
} from "./useEventsPendingRevisionQuery"
|
||||
|
||||
const mutation = gql`
|
||||
${RevisionPendingEventFragment}
|
||||
mutation RequestNewRevision($input: RequestRevisionInput!) {
|
||||
requestEventRevision(input: $input) {
|
||||
...PendingEvent
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
interface Data extends RevisionPendingEventData {}
|
||||
interface Variables {
|
||||
input: GQL.IRequestRevisionInput
|
||||
}
|
||||
const useRequestNewRevisionMutation = (
|
||||
options?: QueryHookOptions<Data, Variables>
|
||||
) => useMutation<Data, Variables>(mutation, options)
|
||||
|
||||
export default useRequestNewRevisionMutation
|
|
@ -60,6 +60,7 @@ type EventRevision {
|
|||
dismissedBy: User
|
||||
event: CalendarEvent!
|
||||
id: ID!
|
||||
lastChangedAt: Date!
|
||||
submittedAt: Date
|
||||
}
|
||||
|
||||
|
@ -117,6 +118,7 @@ type Query {
|
|||
me: User
|
||||
occurrence(id: ID!): EventOccurrence
|
||||
occurrences(filter: OccurrencesQueryFilter!): [EventOccurrence]
|
||||
revisions(filter: RevisionsQueryFilter!): [EventRevision]
|
||||
tags: [EventTag]
|
||||
user(id: ID!): User
|
||||
}
|
||||
|
@ -241,6 +243,10 @@ input ReviseEventInput {
|
|||
revisionId: ID!
|
||||
}
|
||||
|
||||
input RevisionsQueryFilter {
|
||||
limit: Int
|
||||
}
|
||||
|
||||
input RevokeRoleInput {
|
||||
roleType: RoleType!
|
||||
userId: ID!
|
||||
|
|
Loading…
Reference in New Issue