diff --git a/src/pages/TemplateSettings/index.tsx b/src/pages/TemplateSettings/index.tsx new file mode 100644 index 0000000..6dcd6d8 --- /dev/null +++ b/src/pages/TemplateSettings/index.tsx @@ -0,0 +1,1077 @@ +import * as Yup from 'yup'; +import { useFormik } from 'formik'; +import { Redirect, useHistory, useParams } from 'react-router'; +import { + useLazyQuery, + useMutation, + useQuery, + useReactiveVar, +} from '@apollo/client'; +import React, { useEffect, useState } from 'react'; +import { roleVar } from '../../graphql/state'; +import { + Box, + Button, + Text, + SectionSelector, + Input, + Alert, + TextArea, + Select, + Spinner, + FeatureCard, + Modal, +} from '../../components'; +import { Wrapper } from './styles'; +import { ArrowLeft, General, Specification, Features } from '../../assets'; +import { + DeleteTemplateMutation, + DeleteTemplateMutationVariables, + FeatureOutput, + GetAllCategoriesQuery, + GetAllCategoriesQueryVariables, + GetAllFeaturesQuery, + GetAllFeaturesQueryVariables, + GetTemplateByIdQuery, + GetTemplateByIdQueryVariables, + TemplateOutput, + UpdateTemplateMutation, + UpdateTemplateMutationVariables, +} from '../../graphql/types'; +import { + DELETE_TEMPLATE, + GET_TEMPLATE_BY_ID, + UPDATE_TEMPLATE, +} from '../../graphql/template.api'; +import { GET_ALL_CATEGORIES } from '../../graphql/category.api'; +import { GET_ALL_FEATURES } from '../../graphql/feature.api'; + +const TemplateSettings = () => { + const history = useHistory(); + const { id } = useParams<{ id: string }>(); + const role = useReactiveVar(roleVar); + const [template, setTemplate] = useState({ + id: '', + name: '', + description: '', + image: { + name: '', + src: '', + }, + category: '', + specification: { + introduction: { + purpose: '', + documentConventions: '', + intendedAudience: '', + projectScope: '', + }, + overallDescription: { + perspective: '', + userCharacteristics: '', + operatingEnvironment: '', + designImplementationConstraints: '', + userDocumentation: '', + assemptionsDependencies: '', + }, + nonFunctionalRequirements: { + performanceRequirements: '', + safetyRequirements: '', + securityRequirements: '', + softwareQualityAttributes: '', + }, + otherRequirements: '', + glossary: '', + analysisModels: '', + issuesList: '', + }, + features: [], + }); + + const [availableFeatures, setAvailableFeatures] = useState< + Array + >(); + + const [selectedSection, setSelectedSection] = useState< + 'general' | 'specification' | 'features' + >('general'); + const [error, setError] = useState(''); + const [success, setSuccess] = useState(false); + + const [deleteTemplateModal, setDeleteTemplateModal] = useState( + false + ); + + const { data: categories, loading: categoriesLoading } = useQuery< + GetAllCategoriesQuery, + GetAllCategoriesQueryVariables + >(GET_ALL_CATEGORIES, { + fetchPolicy: 'network-only', + }); + + const [getFeatures, { loading: featuresLoading }] = useLazyQuery< + GetAllFeaturesQuery, + GetAllFeaturesQueryVariables + >(GET_ALL_FEATURES, { + onCompleted({ getAllFeatures }) { + setAvailableFeatures(getAllFeatures); + }, + fetchPolicy: 'network-only', + }); + + const [getTemplate, { loading: templateLoading }] = useLazyQuery< + GetTemplateByIdQuery, + GetTemplateByIdQueryVariables + >(GET_TEMPLATE_BY_ID, { + onCompleted({ getTemplateById }) { + setTemplate(getTemplateById); + }, + fetchPolicy: 'network-only', + }); + + const [updateTemplate, { loading }] = useMutation< + UpdateTemplateMutation, + UpdateTemplateMutationVariables + >(UPDATE_TEMPLATE, { + onCompleted({ updateTemplate: data }) { + setTemplate(data); + setSuccess(true); + setTimeout(() => setSuccess(false), 3000); + }, + onError({ graphQLErrors }) { + setError(graphQLErrors[0]?.extensions?.info); + setTimeout(() => setError(''), 3000); + }, + }); + + const [deleteTemplate] = useMutation< + DeleteTemplateMutation, + DeleteTemplateMutationVariables + >(DELETE_TEMPLATE, { + onCompleted() { + history.push('/template'); + }, + onError({ graphQLErrors }) { + setError(graphQLErrors[0]?.extensions?.info); + setTimeout(() => setError(''), 3000); + }, + }); + + useEffect(() => { + getTemplate({ variables: { id } }); + getFeatures(); + + // eslint-disable-next-line + }, [id]); + + const generalForm = useFormik({ + initialValues: { + name: template.name || '', + description: template.description || '', + imageName: template.image.name || '', + imageSource: template.image.src || '', + category: template.category || '', + }, + validationSchema: Yup.object().shape({ + name: Yup.string().required('Name is required'), + description: Yup.string().required('Description is required'), + imageName: Yup.string().required('Image is required'), + imageSource: Yup.string().required('Image is required'), + category: Yup.string().required('Category is required'), + }), + onSubmit: ({ name, description, category, imageName, imageSource }) => { + setTemplate({ + ...template, + name, + description, + image: { name: imageName, src: imageSource }, + category, + }); + updateTemplate({ + variables: { + id, + template: { + name, + description, + category, + image: { + name: imageName, + src: imageSource, + }, + features: template.features?.map((feature) => feature.id), + specification: '', + }, + specification: { + introduction: { + purpose: template.specification?.introduction.purpose!, + documentConventions: template.specification?.introduction + .documentConventions!, + intendedAudience: template.specification?.introduction + .intendedAudience!, + projectScope: template.specification?.introduction.projectScope!, + }, + overallDescription: { + perspective: template.specification?.overallDescription + .perspective!, + userCharacteristics: template.specification?.overallDescription + .userCharacteristics!, + operatingEnvironment: template.specification?.overallDescription + .operatingEnvironment!, + designImplementationConstraints: template.specification + ?.overallDescription.designImplementationConstraints!, + userDocumentation: template.specification?.overallDescription + .userDocumentation!, + assemptionsDependencies: template.specification + ?.overallDescription.assemptionsDependencies!, + }, + nonFunctionalRequirements: { + performanceRequirements: template.specification + ?.nonFunctionalRequirements.performanceRequirements!, + safetyRequirements: template.specification + ?.nonFunctionalRequirements.safetyRequirements!, + securityRequirements: template.specification + ?.nonFunctionalRequirements.securityRequirements!, + softwareQualityAttributes: template.specification + ?.nonFunctionalRequirements.softwareQualityAttributes!, + }, + otherRequirements: template.specification?.otherRequirements!, + glossary: template.specification?.glossary!, + analysisModels: template.specification?.analysisModels!, + issuesList: template.specification?.issuesList!, + }, + }, + }); + }, + enableReinitialize: true, + }); + + const specificationForm = useFormik({ + initialValues: { + purpose: template.specification?.introduction.purpose || '', + documentConventions: + template.specification?.introduction.documentConventions || '', + intendedAudience: + template.specification?.introduction.intendedAudience || '', + projectScope: template.specification?.introduction.projectScope || '', + perspective: template.specification?.overallDescription.perspective || '', + userCharacteristics: + template.specification?.overallDescription.userCharacteristics || '', + operatingEnvironment: + template.specification?.overallDescription.operatingEnvironment || '', + designImplementationConstraints: + template.specification?.overallDescription + .designImplementationConstraints || '', + userDocumentation: + template.specification?.overallDescription.userDocumentation || '', + assemptionsDependencies: + template.specification?.overallDescription.assemptionsDependencies || + '', + performanceRequirements: + template.specification?.nonFunctionalRequirements + .performanceRequirements || '', + safetyRequirements: + template.specification?.nonFunctionalRequirements.safetyRequirements || + '', + securityRequirements: + template.specification?.nonFunctionalRequirements + .securityRequirements || '', + softwareQualityAttributes: + template.specification?.nonFunctionalRequirements + .softwareQualityAttributes || '', + otherRequirements: template.specification?.otherRequirements || '', + glossary: template.specification?.glossary || '', + analysisModels: template.specification?.analysisModels || '', + issuesList: template.specification?.issuesList || '', + }, + validationSchema: Yup.object().shape({ + purpose: Yup.string().required('Purpose is required'), + documentConventions: Yup.string().required( + 'Document conventions is required' + ), + intendedAudience: Yup.string().required('Intented audience is required'), + projectScope: Yup.string().required('Project scope is required'), + perspective: Yup.string().required('Perspective is required'), + userCharacteristics: Yup.string().required( + 'User characteristics is required' + ), + operatingEnvironment: Yup.string().required( + 'Operating environment is required' + ), + designImplementationConstraints: Yup.string().required( + 'Design and implementation constraints is required' + ), + userDocumentation: Yup.string().required( + 'User documentation is required' + ), + assemptionsDependencies: Yup.string().required( + 'Assumptions and dependencies is required' + ), + performanceRequirements: Yup.string().required( + 'Performance requirements is required' + ), + safetyRequirements: Yup.string().required( + 'Safety requirements is required' + ), + securityRequirements: Yup.string().required( + 'Security requirements is required' + ), + softwareQualityAttributes: Yup.string().required( + 'Software quality attributes is required' + ), + otherRequirements: Yup.string().required( + 'Other requirements is required' + ), + glossary: Yup.string().required('Glossary is required'), + analysisModels: Yup.string().required('Analysis models is required'), + issuesList: Yup.string().required('Issues list is required'), + }), + onSubmit: ({ + purpose, + documentConventions, + intendedAudience, + projectScope, + perspective, + userCharacteristics, + operatingEnvironment, + designImplementationConstraints, + userDocumentation, + assemptionsDependencies, + performanceRequirements, + safetyRequirements, + securityRequirements, + softwareQualityAttributes, + otherRequirements, + glossary, + analysisModels, + issuesList, + }) => { + setTemplate({ + ...template, + specification: { + introduction: { + purpose, + documentConventions, + intendedAudience, + projectScope, + }, + overallDescription: { + perspective, + userCharacteristics, + operatingEnvironment, + designImplementationConstraints, + userDocumentation, + assemptionsDependencies, + }, + nonFunctionalRequirements: { + performanceRequirements, + safetyRequirements, + securityRequirements, + softwareQualityAttributes, + }, + otherRequirements, + glossary, + analysisModels, + issuesList, + }, + }); + updateTemplate({ + variables: { + id, + template: { + name: template.name, + description: template.description, + category: template.category, + image: { + name: template.image.name, + src: template.image.src, + }, + features: template.features?.map((feature) => feature.id), + specification: '', + }, + specification: { + introduction: { + purpose, + documentConventions, + intendedAudience, + projectScope, + }, + overallDescription: { + perspective, + userCharacteristics, + operatingEnvironment, + designImplementationConstraints, + userDocumentation, + assemptionsDependencies, + }, + nonFunctionalRequirements: { + performanceRequirements, + safetyRequirements, + securityRequirements, + softwareQualityAttributes, + }, + otherRequirements, + glossary, + analysisModels, + issuesList, + }, + }, + }); + setSelectedSection('features'); + }, + enableReinitialize: true, + }); + + const featuresForm = useFormik<{ features: Array }>({ + initialValues: { + features: template.features?.map((feature) => feature.id) || [], + }, + onSubmit: ({ features }) => { + updateTemplate({ + variables: { + id, + template: { + name: template.name, + description: template.description, + category: template.category, + image: { + name: template.image.name, + src: template.image.src, + }, + features, + specification: '', + }, + specification: { + introduction: { + purpose: template.specification?.introduction.purpose!, + documentConventions: template.specification?.introduction + .documentConventions!, + intendedAudience: template.specification?.introduction + .intendedAudience!, + projectScope: template.specification?.introduction.projectScope!, + }, + overallDescription: { + perspective: template.specification?.overallDescription + .perspective!, + userCharacteristics: template.specification?.overallDescription + .userCharacteristics!, + operatingEnvironment: template.specification?.overallDescription + .operatingEnvironment!, + designImplementationConstraints: template.specification + ?.overallDescription.designImplementationConstraints!, + userDocumentation: template.specification?.overallDescription + .userDocumentation!, + assemptionsDependencies: template.specification + ?.overallDescription.assemptionsDependencies!, + }, + nonFunctionalRequirements: { + performanceRequirements: template.specification + ?.nonFunctionalRequirements.performanceRequirements!, + safetyRequirements: template.specification + ?.nonFunctionalRequirements.safetyRequirements!, + securityRequirements: template.specification + ?.nonFunctionalRequirements.securityRequirements!, + softwareQualityAttributes: template.specification + ?.nonFunctionalRequirements.softwareQualityAttributes!, + }, + otherRequirements: template.specification?.otherRequirements!, + glossary: template.specification?.glossary!, + analysisModels: template.specification?.analysisModels!, + issuesList: template.specification?.issuesList!, + }, + }, + }); + }, + enableReinitialize: true, + }); + + return role === 'productOwner' ? ( + + +