-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #303 from bcgov/feat/edit-operator
Feat: edit operator
- Loading branch information
Showing
26 changed files
with
1,018 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { Button } from "@button-inc/bcgov-theme"; | ||
import FormBase from "components/Form/FormBase"; | ||
import operatorSchema from "data/jsonSchemaForm/operatorSchema"; | ||
import { JSONSchema7 } from "json-schema"; | ||
import { FormPageFactoryComponentProps } from "lib/pages/relayFormPageFactory"; | ||
|
||
const OperatorForm: React.FC<FormPageFactoryComponentProps> = (props) => { | ||
return ( | ||
<FormBase {...props} schema={operatorSchema as JSONSchema7} uiSchema={{}}> | ||
<Button type="submit" style={{ marginRight: "1rem" }}> | ||
Submit | ||
</Button> | ||
<Button type="button" variant="secondary" onClick={props.onDiscard}> | ||
Discard Changes | ||
</Button> | ||
</FormBase> | ||
); | ||
}; | ||
|
||
export default OperatorForm; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
const schema = { | ||
$schema: "http://json-schema.org/draft-07/schema", | ||
type: "object", | ||
title: "Operator", | ||
required: ["legalName", "tradeName"], | ||
properties: { | ||
legalName: { | ||
type: "string", | ||
title: "Legal Name", | ||
default: undefined, | ||
}, | ||
tradeName: { | ||
type: "string", | ||
title: "Trade Name", | ||
default: undefined, | ||
}, | ||
bcRegistryId: { | ||
type: "string", | ||
title: "BC Registry ID", | ||
pattern: "^[a-zA-Z]{1,3}[0-9]{7}$", | ||
}, | ||
operatorCode: { | ||
type: "string", | ||
title: "Operator Code", | ||
pattern: "^[A-Z]{4}$", | ||
}, | ||
}, | ||
}; | ||
|
||
export default schema; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
import { RelayProps } from "relay-nextjs"; | ||
import { graphql, usePreloadedQuery } from "react-relay/hooks"; | ||
import { useUpdateFormChange } from "mutations/FormChange/updateFormChange"; | ||
import { useDeleteFormChange } from "mutations/FormChange/deleteFormChange"; | ||
import { useEffect, useMemo } from "react"; | ||
import { useRouter } from "next/router"; | ||
import DefaultLayout from "components/Layout/DefaultLayout"; | ||
import SavingIndicator from "components/Form/SavingIndicator"; | ||
import FormComponentProps from "components/Form/Interfaces/FormComponentProps"; | ||
import { relayFormPageFactoryQuery } from "__generated__/relayFormPageFactoryQuery.graphql"; | ||
import { GraphQLTaggedNode } from "relay-runtime"; | ||
|
||
export interface FormPageFactoryComponentProps extends FormComponentProps { | ||
onDiscard: () => void; | ||
} | ||
|
||
const pageQuery = graphql` | ||
query relayFormPageFactoryQuery($form: ID!) { | ||
session { | ||
...DefaultLayout_session | ||
} | ||
formChange(id: $form) { | ||
id | ||
newFormData | ||
formDataRecordId | ||
updatedAt | ||
} | ||
} | ||
`; | ||
|
||
/** | ||
* A factory function that creates a page component for a form_change record. | ||
* | ||
* It abstracts away the submit, discard and change behaviours from the | ||
* individual forms, as well as the relay form change query, session and layouts. | ||
* | ||
* @param resourceTitle The title of the resource, for which the form is being created (e.g. "Operator") | ||
* @param onSubmitOrDiscardRoute The route to navigate to when the form is submitted or discarded | ||
* @param FormComponent The form component to render | ||
* @returns a tuple [FormPage, query] where FormPage is the page component to render, and query is the relay query. | ||
* it is meant to be used in the withRelay HOC (e.g. withRelay(FormPage, query, withRelayOptions)). | ||
*/ | ||
|
||
const relayFormPageFactory = ( | ||
resourceTitle: string, | ||
onSubmitOrDiscardRoute: any, | ||
FormComponent: React.FC<FormPageFactoryComponentProps> | ||
) => { | ||
function FormPage({ | ||
preloadedQuery, | ||
}: RelayProps<{}, relayFormPageFactoryQuery>) { | ||
const { session, formChange } = usePreloadedQuery( | ||
pageQuery, | ||
preloadedQuery | ||
); | ||
|
||
const [updateFormChange, isUpdatingFormChange] = useUpdateFormChange(); | ||
const [deleteFormChange, isDeletingFormChange] = useDeleteFormChange(); | ||
const router = useRouter(); | ||
|
||
const lastEditedDate = useMemo( | ||
() => new Date(formChange?.updatedAt), | ||
[formChange?.updatedAt] | ||
); | ||
|
||
useEffect(() => { | ||
if (!formChange) router.replace("/404"); | ||
}, [formChange, router]); | ||
if (!formChange) { | ||
return null; | ||
} | ||
|
||
const isEditing = formChange.formDataRecordId !== null; | ||
|
||
const handleChange = ({ formData }) => { | ||
updateFormChange({ | ||
variables: { | ||
input: { | ||
id: formChange.id, | ||
formChangePatch: { | ||
newFormData: formData, | ||
}, | ||
}, | ||
}, | ||
optimisticResponse: { | ||
updateFormChange: { | ||
formChange: { | ||
id: formChange.id, | ||
newFormData: formData, | ||
}, | ||
}, | ||
}, | ||
debounceKey: formChange.id, | ||
onError: (e) => console.log(e), | ||
}); | ||
}; | ||
|
||
const handleSubmit = ({ formData }) => { | ||
updateFormChange({ | ||
variables: { | ||
input: { | ||
id: formChange.id, | ||
formChangePatch: { | ||
newFormData: formData, | ||
changeStatus: "committed", | ||
}, | ||
}, | ||
}, | ||
debounceKey: formChange.id, | ||
onCompleted: () => { | ||
router.push(onSubmitOrDiscardRoute); | ||
}, | ||
onError: (e) => console.log(e), | ||
}); | ||
}; | ||
|
||
const handleDiscard = () => { | ||
deleteFormChange({ | ||
variables: { | ||
input: { | ||
id: formChange.id, | ||
}, | ||
}, | ||
onCompleted: () => { | ||
router.push(onSubmitOrDiscardRoute); | ||
}, | ||
}); | ||
}; | ||
|
||
return ( | ||
<DefaultLayout session={session}> | ||
<header> | ||
<h2> | ||
{isEditing ? "Edit" : "New"} {resourceTitle} | ||
</h2> | ||
<SavingIndicator | ||
isSaved={!isUpdatingFormChange} | ||
lastEdited={lastEditedDate} | ||
/> | ||
</header> | ||
<FormComponent | ||
formData={formChange.newFormData} | ||
disabled={isDeletingFormChange || isUpdatingFormChange} | ||
onChange={handleChange} | ||
onSubmit={handleSubmit} | ||
onDiscard={handleDiscard} | ||
/> | ||
<style jsx>{` | ||
header { | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: start; | ||
} | ||
header h2 { | ||
padding-right: 10px; | ||
} | ||
`}</style> | ||
</DefaultLayout> | ||
); | ||
} | ||
|
||
return [FormPage, pageQuery] as [ | ||
({ | ||
preloadedQuery, | ||
}: RelayProps<{}, relayFormPageFactoryQuery>) => JSX.Element, | ||
GraphQLTaggedNode | ||
]; | ||
}; | ||
|
||
export default relayFormPageFactory; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { useMutation, graphql, Disposable, Environment } from "react-relay"; | ||
import { MutationConfig } from "relay-runtime"; | ||
import { createEditOperatorFormChangeMutation } from "__generated__/createEditOperatorFormChangeMutation.graphql"; | ||
|
||
export const mutation = graphql` | ||
mutation createEditOperatorFormChangeMutation($operatorRowId: Int!) { | ||
createFormChange( | ||
input: { | ||
formDataSchemaName: "cif" | ||
formDataTableName: "operator" | ||
jsonSchemaName: "operator" | ||
operation: UPDATE | ||
changeReason: "Created from operator form" | ||
formDataRecordId: $operatorRowId | ||
} | ||
) { | ||
formChange { | ||
id | ||
} | ||
} | ||
} | ||
`; | ||
|
||
export const useCreateEditOperatorFormChange = ( | ||
commitMutationFn?: ( | ||
environment: Environment, | ||
config: MutationConfig<createEditOperatorFormChangeMutation> | ||
) => Disposable | ||
) => { | ||
return useMutation<createEditOperatorFormChangeMutation>( | ||
mutation, | ||
commitMutationFn | ||
); | ||
}; | ||
|
||
export default useCreateEditOperatorFormChange; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { useMutation, graphql, Disposable, Environment } from "react-relay"; | ||
import { MutationConfig } from "relay-runtime"; | ||
import { createNewOperatorFormChangeMutation } from "__generated__/createNewOperatorFormChangeMutation.graphql"; | ||
|
||
export const mutation = graphql` | ||
mutation createNewOperatorFormChangeMutation { | ||
createFormChange( | ||
input: { | ||
formDataSchemaName: "cif" | ||
formDataTableName: "operator" | ||
jsonSchemaName: "operator" | ||
operation: CREATE | ||
changeReason: "Created from operator form" | ||
} | ||
) { | ||
formChange { | ||
id | ||
} | ||
} | ||
} | ||
`; | ||
|
||
export const useCreateNewOperatorFormChange = ( | ||
commitMutationFn?: ( | ||
environment: Environment, | ||
config: MutationConfig<createNewOperatorFormChangeMutation> | ||
) => Disposable | ||
) => { | ||
return useMutation<createNewOperatorFormChangeMutation>( | ||
mutation, | ||
commitMutationFn | ||
); | ||
}; |
Oops, something went wrong.