Refactor update formik and add tags editor
This commit is contained in:
parent
a14aa875bd
commit
22a5737e8e
|
@ -27,6 +27,8 @@ declare namespace GQL {
|
|||
me: IUser | null;
|
||||
occurrence: IEventOccurrence | null;
|
||||
occurrences: Array<IEventOccurrence | null> | null;
|
||||
tags: Array<IEventTag | null> | null;
|
||||
user: IUser | null;
|
||||
}
|
||||
|
||||
interface IEventOnQueryArguments {
|
||||
|
@ -45,16 +47,20 @@ declare namespace GQL {
|
|||
filter: IOccurrencesQueryFilter;
|
||||
}
|
||||
|
||||
interface IUserOnQueryArguments {
|
||||
id: string;
|
||||
}
|
||||
|
||||
interface ICalendarEvent {
|
||||
__typename: 'CalendarEvent';
|
||||
id: string;
|
||||
info: IEventInformation | null;
|
||||
infos: Array<IEventInformation | null>;
|
||||
location: ILocation;
|
||||
meta: IEventMeta | null;
|
||||
occurrences: Array<IEventOccurrence | null> | null;
|
||||
owner: IUser;
|
||||
status: any;
|
||||
tags: Array<IEventTag | null> | null;
|
||||
time: IEventTime;
|
||||
}
|
||||
|
||||
|
@ -75,11 +81,6 @@ declare namespace GQL {
|
|||
name: string | null;
|
||||
}
|
||||
|
||||
interface IEventMeta {
|
||||
__typename: 'EventMeta';
|
||||
tags: Array<string | null>;
|
||||
}
|
||||
|
||||
interface IEventOccurrence {
|
||||
__typename: 'EventOccurrence';
|
||||
end: string;
|
||||
|
@ -104,6 +105,25 @@ declare namespace GQL {
|
|||
user: IUser;
|
||||
}
|
||||
|
||||
interface IEventTag {
|
||||
__typename: 'EventTag';
|
||||
id: string;
|
||||
name: string;
|
||||
translation: IEventTagTranslation | null;
|
||||
translations: Array<IEventTagTranslation>;
|
||||
}
|
||||
|
||||
interface ITranslationOnEventTagArguments {
|
||||
language: string;
|
||||
}
|
||||
|
||||
interface IEventTagTranslation {
|
||||
__typename: 'EventTagTranslation';
|
||||
id: string;
|
||||
language: string;
|
||||
text: string;
|
||||
}
|
||||
|
||||
interface IEventTime {
|
||||
__typename: 'EventTime';
|
||||
end: any | null;
|
||||
|
@ -132,6 +152,7 @@ declare namespace GQL {
|
|||
interface IMutation {
|
||||
__typename: 'Mutation';
|
||||
createEvent: ICalendarEvent | null;
|
||||
createEventTag: IEventTag | null;
|
||||
deleteEvent: IUser;
|
||||
grantRole: IUser;
|
||||
requestInvite: boolean;
|
||||
|
@ -139,12 +160,17 @@ declare namespace GQL {
|
|||
signin: IUserSession;
|
||||
signup: Array<IError | null> | null;
|
||||
updateEvent: ICalendarEvent | null;
|
||||
updateEventTag: IEventTag | null;
|
||||
}
|
||||
|
||||
interface ICreateEventOnMutationArguments {
|
||||
input: ICreateEventInput;
|
||||
}
|
||||
|
||||
interface ICreateEventTagOnMutationArguments {
|
||||
input: ICreateEventTagInput;
|
||||
}
|
||||
|
||||
interface IDeleteEventOnMutationArguments {
|
||||
id: string;
|
||||
}
|
||||
|
@ -173,11 +199,15 @@ declare namespace GQL {
|
|||
input: IUpdateEventInput;
|
||||
}
|
||||
|
||||
interface IUpdateEventTagOnMutationArguments {
|
||||
input: IUpdateEventTagInput;
|
||||
}
|
||||
|
||||
interface ICreateEventInput {
|
||||
infos: Array<IEventInformationInput | null>;
|
||||
location: IEventLocationInput;
|
||||
meta: IEventMetaInput;
|
||||
status: string;
|
||||
tagNames: Array<string>;
|
||||
time: IEventTimeInput;
|
||||
}
|
||||
|
||||
|
@ -192,10 +222,6 @@ declare namespace GQL {
|
|||
name?: string | null;
|
||||
}
|
||||
|
||||
interface IEventMetaInput {
|
||||
tags: Array<string | null>;
|
||||
}
|
||||
|
||||
interface IEventTimeInput {
|
||||
end: any;
|
||||
exceptions?: string | null;
|
||||
|
@ -204,6 +230,16 @@ declare namespace GQL {
|
|||
timeZone: any;
|
||||
}
|
||||
|
||||
interface ICreateEventTagInput {
|
||||
name: string;
|
||||
translations: Array<ICreateModifyEventTagTranslationInput>;
|
||||
}
|
||||
|
||||
interface ICreateModifyEventTagTranslationInput {
|
||||
language: string;
|
||||
text: string;
|
||||
}
|
||||
|
||||
interface IGrantRoleInput {
|
||||
roleType: any;
|
||||
userId: string;
|
||||
|
@ -241,11 +277,17 @@ declare namespace GQL {
|
|||
id: string;
|
||||
infos?: Array<IEventInformationInput> | null;
|
||||
location?: IEventLocationInput | null;
|
||||
meta?: IEventMetaInput | null;
|
||||
status?: string | null;
|
||||
tagNames: Array<string>;
|
||||
time?: IEventTimeInput | null;
|
||||
}
|
||||
|
||||
interface IUpdateEventTagInput {
|
||||
id: string;
|
||||
name: string;
|
||||
translations: Array<ICreateModifyEventTagTranslationInput>;
|
||||
}
|
||||
|
||||
interface IRevokeRoleInput {
|
||||
roleType: any;
|
||||
userId: string;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
export type EventStatus = "confirmed" | "canceled"
|
||||
declare module "*.png" {
|
||||
|
||||
}
|
||||
declare module "*.png"
|
||||
declare module "*.svg"
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import MUIChip, { ChipProps } from "@material-ui/core/Chip"
|
||||
import * as React from "react"
|
||||
|
||||
interface Props extends ChipProps {
|
||||
}
|
||||
|
||||
const Chip = (props: Props) => {
|
||||
return <MUIChip {...props} />
|
||||
}
|
||||
|
||||
export default Chip
|
|
@ -6,6 +6,7 @@ const TextField = (props: TextFieldProps) => {
|
|||
return <MUITextField {...props} />
|
||||
}
|
||||
export { TextFieldProps }
|
||||
|
||||
export default styled(TextField)`
|
||||
border-radius: 8px;
|
||||
border-color: #5E8036;
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
"emotion": "^10.0.17",
|
||||
"emotion-server": "^10.0.17",
|
||||
"express": "^4.17.1",
|
||||
"formik": "^1.4.1",
|
||||
"graphql": "^14.0.2",
|
||||
"graphql-tag": "^2.9.2",
|
||||
"graphql-tools": "^4.0.3",
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
import * as React from "react"
|
||||
import { withRouter } from "react-router"
|
||||
import {Route, Switch, useRouteMatch, withRouter} from "react-router"
|
||||
import styled from "@emotion/styled"
|
||||
import intl from "react-intl-universal"
|
||||
import EditEventTags from "../../EventTags/EditEventTags"
|
||||
import messages from "./admin.msg.json"
|
||||
|
||||
const Admin = () => {
|
||||
intl.load(messages)
|
||||
let { path } = useRouteMatch();
|
||||
|
||||
intl.load(messages)
|
||||
return (
|
||||
<Root>
|
||||
<Title>{intl.get("admin_title")}</Title>
|
||||
<Switch>
|
||||
<Route path={`${path}/tags`} component={EditEventTags}/>
|
||||
</Switch>
|
||||
</Root>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -65,10 +65,7 @@ const Login = (props: Props) => {
|
|||
>
|
||||
Sign Up
|
||||
</StyledButton>
|
||||
<StyledButton
|
||||
color="secondary"
|
||||
onClick={() => setError(false)}
|
||||
>
|
||||
<StyledButton color="secondary" onClick={() => setError(false)}>
|
||||
Try Again
|
||||
</StyledButton>
|
||||
</Error>
|
||||
|
@ -76,12 +73,12 @@ const Login = (props: Props) => {
|
|||
<Success>
|
||||
<Label>{intl.get("invitation-sent")}</Label>
|
||||
<StyledButton onClick={() => props.history.push("/")}>
|
||||
{intl.get('to-calendar')}
|
||||
{intl.get("to-calendar")}
|
||||
</StyledButton>
|
||||
</Success>
|
||||
) : (
|
||||
<>
|
||||
<EmailTextField
|
||||
<TextField
|
||||
id="email"
|
||||
type="email"
|
||||
value={email}
|
||||
|
@ -91,6 +88,9 @@ const Login = (props: Props) => {
|
|||
setEmail(e.target.value)
|
||||
}}
|
||||
disabled={loading || success}
|
||||
css={css`
|
||||
grid-row: input;
|
||||
`}
|
||||
/>
|
||||
<StyledButton
|
||||
variant="contained"
|
||||
|
@ -117,10 +117,6 @@ const Root = styled.form`
|
|||
[full-end button-end];
|
||||
`
|
||||
|
||||
const EmailTextField = styled(TextField)`
|
||||
grid-row: input;
|
||||
`
|
||||
|
||||
const LogoHolder = styled.div`
|
||||
grid-row: logo;
|
||||
display: flex;
|
||||
|
|
|
@ -14,8 +14,6 @@ interface SignupFormData {
|
|||
name: string
|
||||
}
|
||||
|
||||
class SignupFormik extends Formik<SignupFormData> {}
|
||||
|
||||
const Signup = (props: RouteComponentProps) => {
|
||||
intl.load(messages)
|
||||
const { addMessage } = useMessageCenter()
|
||||
|
@ -44,8 +42,8 @@ const Signup = (props: RouteComponentProps) => {
|
|||
</Button>
|
||||
</Success>
|
||||
) : (
|
||||
<SignupFormik
|
||||
initialValues={{ name: "", email: "" }}
|
||||
<Formik
|
||||
initialValues={{ name: "", email: "" } as SignupFormData}
|
||||
validate={(values: SignupFormData) => {
|
||||
const errors: any = {}
|
||||
if (!values.name) {
|
||||
|
@ -140,7 +138,7 @@ const Signup = (props: RouteComponentProps) => {
|
|||
</GoToLogin>
|
||||
</SForm>
|
||||
)}
|
||||
</SignupFormik>
|
||||
</Formik>
|
||||
)}
|
||||
</Root>
|
||||
)
|
||||
|
|
|
@ -28,6 +28,5 @@
|
|||
"month11":"noviembre",
|
||||
"month12":"deciembre",
|
||||
"no-events": "No hay eventos"
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { addHours, format, isBefore } from "date-fns"
|
||||
import { format, isBefore } from "date-fns"
|
||||
import { Field, Form, Formik } from "formik"
|
||||
import {
|
||||
Button,
|
||||
|
@ -12,6 +12,7 @@ import styled from "@emotion/styled"
|
|||
import { hot } from "react-hot-loader"
|
||||
import { EventStatus } from "../../../@types"
|
||||
import * as intl from "react-intl-universal"
|
||||
import TagSelector from "../EventTags/TagsSelector"
|
||||
import messages from "./EventForm.msg.json"
|
||||
|
||||
interface Props {
|
||||
|
@ -46,8 +47,6 @@ export interface EventFormData {
|
|||
}
|
||||
}
|
||||
|
||||
class EventFormik extends Formik<EventFormData> {}
|
||||
|
||||
const todayMidday = new Date()
|
||||
todayMidday.setUTCHours(12, 0)
|
||||
|
||||
|
@ -62,7 +61,7 @@ const EventForm = (props: Props) => {
|
|||
const isEdit = !!props.values
|
||||
|
||||
return (
|
||||
<EventFormik
|
||||
<Formik
|
||||
onSubmit={props.onSubmit}
|
||||
initialValues={
|
||||
props.values
|
||||
|
@ -91,7 +90,7 @@ const EventForm = (props: Props) => {
|
|||
status: "confirmed",
|
||||
} as EventFormData)
|
||||
}
|
||||
validate={values => {
|
||||
validate={(values: EventFormData) => {
|
||||
const errors: any = {}
|
||||
if (!values.location.address) {
|
||||
errors.location = errors.location || {}
|
||||
|
@ -112,6 +111,7 @@ const EventForm = (props: Props) => {
|
|||
{({ isValid, setFieldValue, values }) => {
|
||||
return (
|
||||
<StyledForm>
|
||||
<TagSelector language="en" onChange={() => {}} />
|
||||
<FormTitle>
|
||||
{props.locales.length > 1
|
||||
? intl.get("EVENT_FORM_DETAILS_FOREWORD_MULTILINGUAL")
|
||||
|
@ -159,42 +159,42 @@ const EventForm = (props: Props) => {
|
|||
<p>{intl.get("START_TIME")}</p>
|
||||
|
||||
<TimeSection>
|
||||
<DatePicker
|
||||
value={values.time.start}
|
||||
onChange={newStartDate => {
|
||||
setFieldValue("time.start", format(newStartDate, "yyyy-MM-dd'T'HH:mm"))
|
||||
<Field name="time.start">
|
||||
{({ field }) => {
|
||||
const timeStartOnChange = newStartDate => {
|
||||
setFieldValue(
|
||||
"time.start" as any,
|
||||
format(newStartDate, "yyyy-MM-dd'T'HH:mm")
|
||||
)
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<DatePicker {...field} onChange={timeStartOnChange} />
|
||||
<TimePicker {...field} onChange={timeStartOnChange} />
|
||||
</>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<TimePicker
|
||||
value={values.time.start}
|
||||
onChange={newStartDate => {
|
||||
format(newStartDate, "yyyy-MM-dd'T'HH:mm")
|
||||
|
||||
setFieldValue("time.start", format(newStartDate, "yyyy-MM-dd'T'HH:mm"))
|
||||
}}
|
||||
/>
|
||||
</Field>
|
||||
</TimeSection>
|
||||
<p>{intl.get("END_TIME")} </p>
|
||||
|
||||
<TimeSection>
|
||||
<DatePicker
|
||||
value={values.time.end}
|
||||
onChange={newEndDate => {
|
||||
setFieldValue(
|
||||
"time.end",
|
||||
format(newEndDate, "yyyy-MM-dd'T'HH:mm")
|
||||
<Field name="time.end">
|
||||
{({ field }) => {
|
||||
const timeEndOnChange = newStartDate => {
|
||||
setFieldValue(
|
||||
"time.end" as any,
|
||||
format(newStartDate, "yyyy-MM-dd'T'HH:mm")
|
||||
)
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<DatePicker {...field} onChange={timeEndOnChange} />
|
||||
<TimePicker {...field} onChange={timeEndOnChange} />
|
||||
</>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<TimePicker
|
||||
value={values.time.end}
|
||||
onChange={newEndDate => {
|
||||
setFieldValue(
|
||||
"time.end",
|
||||
format(newEndDate, "yyyy-MM-dd'T'HH:mm")
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</Field>
|
||||
</TimeSection>
|
||||
</PickersProvider>
|
||||
</Section>
|
||||
|
@ -234,7 +234,7 @@ const EventForm = (props: Props) => {
|
|||
</StyledForm>
|
||||
)
|
||||
}}
|
||||
</EventFormik>
|
||||
</Formik>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -22,8 +22,9 @@ export const EventFragment = gql`
|
|||
exceptions
|
||||
}
|
||||
status
|
||||
meta {
|
||||
tags
|
||||
tags {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
`
|
||||
|
@ -50,10 +51,11 @@ export interface ContactData {
|
|||
languages: string[]
|
||||
name: string
|
||||
}
|
||||
export interface EventMetaData {
|
||||
tags: string[]
|
||||
}
|
||||
|
||||
export interface EventTag {
|
||||
id: string
|
||||
name: string
|
||||
}
|
||||
export interface EventData {
|
||||
id: string
|
||||
infos: EventInfoData[]
|
||||
|
@ -64,7 +66,7 @@ export interface EventData {
|
|||
}
|
||||
time: EventTimeData
|
||||
status: EventStatus
|
||||
meta: EventMetaData
|
||||
tags: EventTag[]
|
||||
}
|
||||
|
||||
interface Data {
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
import { useMessageCenter } from "qpa-message-center"
|
||||
import * as React from "react"
|
||||
import updateEventTagMutation from "./updateEventTagMutation"
|
||||
import { EventTagData } from "./useGetAvaiableTagsQuery"
|
||||
import styled from "@emotion/styled"
|
||||
|
||||
interface Props {
|
||||
eventTag: EventTagData
|
||||
}
|
||||
|
||||
const EditEventTag = (props: Props) => {
|
||||
const { addMessage } = useMessageCenter()
|
||||
const [mutation, { data, loading, error }] = updateEventTagMutation({
|
||||
onCompleted: () => {
|
||||
|
||||
},
|
||||
})
|
||||
return <Root></Root>
|
||||
}
|
||||
|
||||
const Root = styled.div``
|
||||
export default EditEventTag
|
|
@ -0,0 +1,27 @@
|
|||
import {Spinner} from "qpa-components"
|
||||
import * as React from 'react'
|
||||
import {RouteComponentProps, withRouter} from "react-router"
|
||||
import EditEventTag from "./EditEventTag"
|
||||
import {useGetAvailableTagsQuery} from "./useGetAvaiableTagsQuery"
|
||||
import styled from "@emotion/styled"
|
||||
|
||||
interface Props extends RouteComponentProps {}
|
||||
const EditEventTags = (props: Props) => {
|
||||
const {data, loading, error} = useGetAvailableTagsQuery()
|
||||
if (loading) {
|
||||
return <Spinner />
|
||||
}
|
||||
if (error) {
|
||||
return <p>{error.message}</p>
|
||||
}
|
||||
return <Root>
|
||||
{
|
||||
data.tags.map(tag => (
|
||||
<EditEventTag eventTag={tag}/>
|
||||
))
|
||||
}
|
||||
</Root>
|
||||
}
|
||||
|
||||
const Root = styled.div``
|
||||
export default withRouter(EditEventTags)
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"en": {
|
||||
"tag-update-success": "Tag {name} was successfully updated"
|
||||
},
|
||||
"es": {
|
||||
"tag-update-success": "Etiqueta {name} está correctamente actualizada"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
import { TextField } from "qpa-components"
|
||||
import * as React from "react"
|
||||
import { Formik, Field, FieldArray, Form } from "formik"
|
||||
import {
|
||||
EventTagData,
|
||||
EventTagTranslationData,
|
||||
} from "./useGetAvaiableTagsQuery"
|
||||
import messages from "./EventTagForm.msg.json"
|
||||
import styled from "@emotion/styled"
|
||||
import intl from "react-intl-universal"
|
||||
|
||||
interface EventTagFormData extends EventTagData {
|
||||
name: string
|
||||
translations: EventTagTranslationData[]
|
||||
}
|
||||
|
||||
interface Props {
|
||||
onSubmit: (values: EventTagFormData) => void
|
||||
tag: EventTagData
|
||||
}
|
||||
|
||||
const initialValue = {
|
||||
name: '',
|
||||
translations: [{language:"", text: ""}],
|
||||
}
|
||||
const EventTagForm = (props: Props) => {
|
||||
intl.load({
|
||||
"es-ES": messages.es,
|
||||
"en-GB": messages.en,
|
||||
})
|
||||
return (
|
||||
<Formik initialValues={initialValue} onSubmit={props.onSubmit}>
|
||||
{({values: EventTagFormData}) => (
|
||||
<Root>
|
||||
<Field name="name">{field => <TextField {...field} />}</Field>
|
||||
{
|
||||
}
|
||||
</Root>
|
||||
)}
|
||||
</Formik>
|
||||
)
|
||||
}
|
||||
|
||||
const Root = styled(Form)``
|
||||
|
||||
export default EventTagForm
|
|
@ -0,0 +1,35 @@
|
|||
import {Spinner} from "qpa-components"
|
||||
import Chip from "qpa-components/Chip"
|
||||
import * as React from "react"
|
||||
import { useGetAvailableTagsQuery } from "./useGetAvaiableTagsQuery"
|
||||
import styled from "@emotion/styled"
|
||||
|
||||
interface Props {
|
||||
language: string
|
||||
selectedNames?: string[]
|
||||
onChange: (selectedNames: string[]) => void
|
||||
className?: string
|
||||
}
|
||||
|
||||
const TagSelector = (props: Props) => {
|
||||
const [selectedNames, setSelectedNames] = React.useState(
|
||||
props.selectedNames || []
|
||||
)
|
||||
const { loading, error, data } = useGetAvailableTagsQuery({
|
||||
variables: {
|
||||
language: props.language,
|
||||
},
|
||||
})
|
||||
|
||||
return <Root>
|
||||
{
|
||||
loading ? <Spinner /> : error ? <p>Error: {error.message} </p> : data.tags.map(
|
||||
tag => <Chip key={tag.id} label={tag.translation.text || tag.name} />
|
||||
)
|
||||
}
|
||||
</Root>
|
||||
}
|
||||
|
||||
const Root = styled.div``
|
||||
|
||||
export default TagSelector
|
|
@ -0,0 +1,29 @@
|
|||
import { useMutation, MutationHookOptions } from "react-apollo"
|
||||
import gql from "graphql-tag"
|
||||
import {
|
||||
EventTagFullData,
|
||||
EventTagFullDataFragment,
|
||||
} from "./useGetAllTagsWithTranslationsQuery"
|
||||
import { EventTagTranslationData } from "./useGetAvaiableTagsQuery"
|
||||
|
||||
const mutation = gql`
|
||||
${EventTagFullDataFragment}
|
||||
mutation UpdateEventTag($input: UpdateEventTagInput!) {
|
||||
updateEventTag(input: $input) {
|
||||
...EventTagFullData
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
interface Data {
|
||||
updateEventTag: EventTagFullData
|
||||
}
|
||||
interface Variables {
|
||||
input: GQL.IModifyEventTagInput
|
||||
}
|
||||
|
||||
const updateEventTagMutation = (
|
||||
options: MutationHookOptions<Data, Variables>
|
||||
) => useMutation<Data, Variables>(mutation, options)
|
||||
|
||||
export default updateEventTagMutation
|
|
@ -0,0 +1,37 @@
|
|||
import gql from "graphql-tag"
|
||||
import { QueryHookOptions, useQuery } from "react-apollo"
|
||||
import {
|
||||
EventTagTranslationData,
|
||||
TranslationDataFragment,
|
||||
} from "./useGetAvaiableTagsQuery"
|
||||
|
||||
export const EventTagFullDataFragment = gql`
|
||||
${TranslationDataFragment}
|
||||
fragment EventTagFullData on EventTag {
|
||||
id
|
||||
name
|
||||
translations {
|
||||
...TranslationData
|
||||
}
|
||||
}
|
||||
`
|
||||
const query = gql`
|
||||
${EventTagFullDataFragment}
|
||||
query GetAllTagsWithTranslations {
|
||||
tags {
|
||||
...EventTagFullData
|
||||
}
|
||||
}
|
||||
`
|
||||
export interface EventTagFullData {
|
||||
id: string
|
||||
name: string
|
||||
translations: EventTagTranslationData[]
|
||||
}
|
||||
interface Data {
|
||||
tags: EventTagFullData[]
|
||||
}
|
||||
|
||||
const useGetAllTagsWithTranslationsQuery = (options?: QueryHookOptions<Data>) =>
|
||||
useQuery<Data>(query, options)
|
||||
export default useGetAllTagsWithTranslationsQuery
|
|
@ -0,0 +1,43 @@
|
|||
import {QueryHookOptions, useQuery} from "@apollo/react-hooks"
|
||||
import gql from "graphql-tag"
|
||||
|
||||
export const TranslationDataFragment = gql`
|
||||
fragment TranslationData on EventTagTranslation {
|
||||
id
|
||||
language
|
||||
text
|
||||
}
|
||||
`
|
||||
|
||||
const query = gql`
|
||||
${TranslationDataFragment}
|
||||
query GetTagsForLanguage($language: String!) {
|
||||
tags {
|
||||
id
|
||||
name
|
||||
translation(language: $language) {
|
||||
...TranslationData
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
export interface EventTagTranslationData {
|
||||
id: string
|
||||
language: string
|
||||
text: string
|
||||
}
|
||||
export interface EventTagData {
|
||||
id: string
|
||||
name: string
|
||||
translation: EventTagTranslationData
|
||||
}
|
||||
|
||||
export interface Data {
|
||||
tags: EventTagData[]
|
||||
}
|
||||
|
||||
interface Variables {
|
||||
language: string
|
||||
}
|
||||
|
||||
export const useGetAvailableTagsQuery = (options?: QueryHookOptions<Data, Variables>) => useQuery<Data, Variables>(query, options)
|
|
@ -21,7 +21,7 @@
|
|||
"date-fns": "^2.4.1",
|
||||
"express": "^4.17.1",
|
||||
"file-loader": "^4.2.0",
|
||||
"formik": "^1.4.1",
|
||||
"formik": "^2.0.3",
|
||||
"graphql": "^14.0.2",
|
||||
"graphql-tag": "^2.9.2",
|
||||
"graphql-tools": "^4.0.3",
|
||||
|
|
|
@ -38,6 +38,7 @@ type EventOccurrence {
|
|||
type EventTag {
|
||||
id: ID!
|
||||
name: String!
|
||||
translation(language: String!): EventTagTranslation
|
||||
translations: [EventTagTranslation!]!
|
||||
}
|
||||
|
||||
|
@ -65,12 +66,12 @@ type Mutation {
|
|||
createEventTag(input: CreateEventTagInput!): EventTag
|
||||
deleteEvent(id: ID!): User!
|
||||
grantRole(input: GrantRoleInput!): User!
|
||||
modifyEventTag(input: ModifyEventTagInput!): EventTag
|
||||
requestInvite(input: RequestInviteInput!): Boolean!
|
||||
revokeRole(input: GrantRoleInput!): User!
|
||||
signin(input: SigninInput!): UserSession!
|
||||
signup(input: SignupInput!): [Error]
|
||||
updateEvent(input: UpdateEventInput!): CalendarEvent
|
||||
updateEventTag(input: UpdateEventTagInput!): EventTag
|
||||
}
|
||||
|
||||
type Query {
|
||||
|
@ -79,20 +80,10 @@ type Query {
|
|||
me: User
|
||||
occurrence(id: ID!): EventOccurrence
|
||||
occurrences(filter: OccurrencesQueryFilter!): [EventOccurrence]
|
||||
tags: [EventTag]
|
||||
user(id: ID!): User
|
||||
}
|
||||
|
||||
type Tag {
|
||||
id: ID!
|
||||
name: String!
|
||||
translations: [Translations!]!
|
||||
}
|
||||
|
||||
type TagTranslation {
|
||||
language: String!
|
||||
text: String!
|
||||
}
|
||||
|
||||
type User {
|
||||
email: String!
|
||||
events: [CalendarEvent]!
|
||||
|
@ -164,12 +155,6 @@ input GrantRoleInput {
|
|||
userId: ID!
|
||||
}
|
||||
|
||||
input ModifyEventTagInput {
|
||||
id: ID!
|
||||
name: String!
|
||||
translations: [CreateModifyEventTagTranslationInput!]!
|
||||
}
|
||||
|
||||
input OccurrencesQueryFilter {
|
||||
categories: [Category]
|
||||
from: Timestamp
|
||||
|
@ -206,6 +191,12 @@ input UpdateEventInput {
|
|||
time: EventTimeInput
|
||||
}
|
||||
|
||||
input UpdateEventTagInput {
|
||||
id: ID!
|
||||
name: String!
|
||||
translations: [CreateModifyEventTagTranslationInput!]!
|
||||
}
|
||||
|
||||
|
||||
scalar TimeZone
|
||||
|
||||
|
|
104
yarn.lock
104
yarn.lock
|
@ -2102,11 +2102,6 @@ array-unique@^0.3.2:
|
|||
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
|
||||
integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
|
||||
|
||||
asap@~2.0.3:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
|
||||
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
|
||||
|
||||
asn1.js@^4.0.0:
|
||||
version "4.10.1"
|
||||
resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0"
|
||||
|
@ -2966,11 +2961,6 @@ core-js-compat@^3.1.1:
|
|||
browserslist "^4.7.0"
|
||||
semver "^6.3.0"
|
||||
|
||||
core-js@^1.0.0:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
|
||||
integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=
|
||||
|
||||
core-js@^3.2.1:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.3.2.tgz#cd42da1d7b0bb33ef11326be3a721934277ceb42"
|
||||
|
@ -3049,14 +3039,6 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
|
|||
safe-buffer "^5.0.1"
|
||||
sha.js "^2.4.8"
|
||||
|
||||
create-react-context@^0.2.2:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/create-react-context/-/create-react-context-0.2.3.tgz#9ec140a6914a22ef04b8b09b7771de89567cb6f3"
|
||||
integrity sha512-CQBmD0+QGgTaxDL3OX1IDXYqjkp2It4RIbcb99jS6AEg27Ga+a9G3JtK6SIu0HBwPLZlmwt9F7UwWA4Bn92Rag==
|
||||
dependencies:
|
||||
fbjs "^0.8.0"
|
||||
gud "^1.0.0"
|
||||
|
||||
cross-spawn@6.0.5, cross-spawn@^6.0.0:
|
||||
version "6.0.5"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
|
||||
|
@ -3590,13 +3572,6 @@ encodeurl@~1.0.2:
|
|||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
||||
integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
|
||||
|
||||
encoding@^0.1.11:
|
||||
version "0.1.12"
|
||||
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
|
||||
integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=
|
||||
dependencies:
|
||||
iconv-lite "~0.4.13"
|
||||
|
||||
end-of-stream@^1.0.0, end-of-stream@^1.1.0:
|
||||
version "1.4.4"
|
||||
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
|
||||
|
@ -3958,19 +3933,6 @@ fb-watchman@^2.0.0:
|
|||
dependencies:
|
||||
bser "^2.0.0"
|
||||
|
||||
fbjs@^0.8.0:
|
||||
version "0.8.17"
|
||||
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd"
|
||||
integrity sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=
|
||||
dependencies:
|
||||
core-js "^1.0.0"
|
||||
isomorphic-fetch "^2.1.1"
|
||||
loose-envify "^1.0.0"
|
||||
object-assign "^4.1.0"
|
||||
promise "^7.1.1"
|
||||
setimmediate "^1.0.5"
|
||||
ua-parser-js "^0.7.18"
|
||||
|
||||
figgy-pudding@^3.5.1:
|
||||
version "3.5.1"
|
||||
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
|
||||
|
@ -4072,18 +4034,17 @@ form-data@~2.3.2:
|
|||
combined-stream "^1.0.6"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
formik@^1.4.1:
|
||||
version "1.5.8"
|
||||
resolved "https://registry.yarnpkg.com/formik/-/formik-1.5.8.tgz#eee8cd345effe46839bc748c7f920486f12f14b0"
|
||||
integrity sha512-fNvPe+ddbh+7xiByT25vuso2p2hseG/Yvuj211fV1DbCjljUEG9OpgRpcb7g7O3kxHX/q31cbZDzMxJXPWSNwA==
|
||||
formik@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/formik/-/formik-2.0.3.tgz#7cf088b1a6e0ba21782b73a90453a78426959168"
|
||||
integrity sha512-kYBvcxlsYSncY8OiJHD49C0UmoWXbgmIc9V1g3N1WwBJ7SMLk34QpcJDgroYd42K1cH+mSJlXhB7PlgTXTzlWg==
|
||||
dependencies:
|
||||
create-react-context "^0.2.2"
|
||||
deepmerge "^2.1.1"
|
||||
hoist-non-react-statics "^3.3.0"
|
||||
lodash "^4.17.14"
|
||||
lodash-es "^4.17.14"
|
||||
prop-types "^15.6.1"
|
||||
react-fast-compare "^2.0.1"
|
||||
scheduler "^0.14.0"
|
||||
tiny-warning "^1.0.2"
|
||||
tslib "^1.9.3"
|
||||
|
||||
|
@ -4652,7 +4613,7 @@ hyphenate-style-name@^1.0.3:
|
|||
resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz#097bb7fa0b8f1a9cf0bd5c734cf95899981a9b48"
|
||||
integrity sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ==
|
||||
|
||||
iconv-lite@0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
|
||||
iconv-lite@0.4.24, iconv-lite@^0.4.4:
|
||||
version "0.4.24"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
|
||||
|
@ -5044,7 +5005,7 @@ is-retry-allowed@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4"
|
||||
integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==
|
||||
|
||||
is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0:
|
||||
is-stream@^1.0.0, is-stream@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
|
||||
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
|
||||
|
@ -5103,14 +5064,6 @@ isobject@^4.0.0:
|
|||
resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0"
|
||||
integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==
|
||||
|
||||
isomorphic-fetch@^2.1.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
|
||||
integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=
|
||||
dependencies:
|
||||
node-fetch "^1.0.1"
|
||||
whatwg-fetch ">=0.10.0"
|
||||
|
||||
isstream@~0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
|
||||
|
@ -6275,14 +6228,6 @@ node-environment-flags@^1.0.5:
|
|||
object.getownpropertydescriptors "^2.0.3"
|
||||
semver "^5.7.0"
|
||||
|
||||
node-fetch@^1.0.1:
|
||||
version "1.7.3"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
|
||||
integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==
|
||||
dependencies:
|
||||
encoding "^0.1.11"
|
||||
is-stream "^1.0.1"
|
||||
|
||||
node-fetch@^2.6.0:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
|
||||
|
@ -6992,13 +6937,6 @@ promise-inflight@^1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
|
||||
integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
|
||||
|
||||
promise@^7.1.1:
|
||||
version "7.3.1"
|
||||
resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
|
||||
integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==
|
||||
dependencies:
|
||||
asap "~2.0.3"
|
||||
|
||||
prompts@^2.0.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.2.1.tgz#f901dd2a2dfee080359c0e20059b24188d75ad35"
|
||||
|
@ -7691,6 +7629,14 @@ sax@^1.2.4, sax@~1.2.4:
|
|||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
|
||||
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
|
||||
|
||||
scheduler@^0.14.0:
|
||||
version "0.14.0"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.14.0.tgz#b392c23c9c14bfa2933d4740ad5603cc0d59ea5b"
|
||||
integrity sha512-9CgbS06Kki2f4R9FjLSITjZo5BZxPsryiRNyL3LpvrM9WxcVmhlqAOc9E+KQbeI2nqej4JIIbOsfdL51cNb4Iw==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
scheduler@^0.16.2:
|
||||
version "0.16.2"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.16.2.tgz#f74cd9d33eff6fc554edfb79864868e4819132c1"
|
||||
|
@ -7807,7 +7753,7 @@ set-value@^2.0.0, set-value@^2.0.1:
|
|||
is-plain-object "^2.0.3"
|
||||
split-string "^3.0.1"
|
||||
|
||||
setimmediate@^1.0.4, setimmediate@^1.0.5:
|
||||
setimmediate@^1.0.4:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
|
||||
integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=
|
||||
|
@ -8570,15 +8516,10 @@ typeface-fira-sans@^0.0.75:
|
|||
resolved "https://registry.yarnpkg.com/typeface-fira-sans/-/typeface-fira-sans-0.0.75.tgz#6caaa7c7298f34838476af3c37dc57d2f1621132"
|
||||
integrity sha512-PeaE4JCzBxbrp3oJzLjz+EVMjMIvrqnpmC7cp+HKYgPFbd9j4TAjGWRCEeaY/j9PRbTMICbrTuvanQFCmcjrYQ==
|
||||
|
||||
typescript@^3.6.4:
|
||||
version "3.6.4"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.6.4.tgz#b18752bb3792bc1a0281335f7f6ebf1bbfc5b91d"
|
||||
integrity sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg==
|
||||
|
||||
ua-parser-js@^0.7.18:
|
||||
version "0.7.20"
|
||||
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.20.tgz#7527178b82f6a62a0f243d1f94fd30e3e3c21098"
|
||||
integrity sha512-8OaIKfzL5cpx8eCMAhhvTlft8GYF8b2eQr6JkCyVdrgjcytyOmPCXrqXFcUnhonRpLlh5yxEZVohm6mzaowUOw==
|
||||
typescript@^3.7.2:
|
||||
version "3.7.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.2.tgz#27e489b95fa5909445e9fef5ee48d81697ad18fb"
|
||||
integrity sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ==
|
||||
|
||||
uglify-js@3.4.x:
|
||||
version "3.4.10"
|
||||
|
@ -9009,11 +8950,6 @@ whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3:
|
|||
dependencies:
|
||||
iconv-lite "0.4.24"
|
||||
|
||||
whatwg-fetch@>=0.10.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb"
|
||||
integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==
|
||||
|
||||
whatwg-mimetype@^2.1.0, whatwg-mimetype@^2.2.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"
|
||||
|
|
Loading…
Reference in New Issue