diff --git a/.vscode/settings.json b/.vscode/settings.json index 662beba..dff3352 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,6 +2,7 @@ "cSpell.words": [ "EPSG", "NCCRD", + "REIPPP", "STAs", "cdmes", "cdmm", diff --git a/src/api/src/graphql/schema/type-defs/adaptation.graphql b/src/api/src/graphql/schema/type-defs/adaptation.graphql index 022ff51..d95dce2 100644 --- a/src/api/src/graphql/schema/type-defs/adaptation.graphql +++ b/src/api/src/graphql/schema/type-defs/adaptation.graphql @@ -4,16 +4,16 @@ input AdaptationInput { # Sector description :: Please describe the sector otherAdaptationSector: String # National policy :: Indicate the national policy or strategy that the measure is responding to :: adaptationPolicies - nationalPolicy: ControlledVocabularyInput + nationalPolicy: [ControlledVocabularyInput] # National policy description :: Please describe the policy otherNationalPolicy: String # Provincial or Municipal policy :: Indicate the provincial or municipal policy or strategy that the measure is responding to :: adaptationPolicies - regionalPolicy: ControlledVocabularyInput + regionalPolicy: [ControlledVocabularyInput] # Regional policy description :: Please describe the policy otherRegionalPolicy: String # Indicate the corresponding intervention, goal, or target :: Please select an appropriate value based on your other form inputs above :: adaptationPolicies - target: ControlledVocabularyInput - # Other corresponding intervention, goal, or target :: Please describe based on your other form inputs above + target: [ControlledVocabularyInput] + # Other corresponding intervention(s), goal(s), or target(s) :: Please describe based on your other form inputs above otherTarget: String # Hazard :: Select hazard :: hazards diff --git a/src/api/src/graphql/schema/type-defs/mitigation.graphql b/src/api/src/graphql/schema/type-defs/mitigation.graphql index 1aa6648..d7a4242 100644 --- a/src/api/src/graphql/schema/type-defs/mitigation.graphql +++ b/src/api/src/graphql/schema/type-defs/mitigation.graphql @@ -14,12 +14,12 @@ input MitigationInput { # Select the mitigation program the project is linked to :: A programme is a high level support measure that support mitigation actions/project types above e.g 1A1 REIPPP :: mitigationProgramme mitigationProgramme: ControlledVocabularyInput # National policy :: Indicate the national policy or strategy that the measure is responding to :: mitigationPolicies - nationalPolicy: ControlledVocabularyInput - # National policy description :: Please describe the policy + nationalPolicy: [ControlledVocabularyInput] + # (Other) national policy(ies) description :: Please describe the policy(ies) otherNationalPolicy: String # Provincial or Municipal policy :: Indicate the provincial or municipal policy or strategy that the measure is responding to :: mitigationPolicies - regionalPolicy: ControlledVocabularyInput - # Regional policy description :: Please describe the policy + regionalPolicy: [ControlledVocabularyInput] + # (Other) regional policy(ies) description :: Please describe the policy(ies) otherRegionalPolicy: String # Primary intended outcome :: Primary intended outcome (Indicate the expected or achieved goals) primaryIntendedOutcome: String diff --git a/src/api/src/graphql/schema/type-defs/project.graphql b/src/api/src/graphql/schema/type-defs/project.graphql index 9563266..2882eec 100644 --- a/src/api/src/graphql/schema/type-defs/project.graphql +++ b/src/api/src/graphql/schema/type-defs/project.graphql @@ -37,13 +37,13 @@ input ProjectInput { # Estimated budget range :: If you don't know the actual budget, please provide a range estimate :: budgetRanges estimatedBudget: ControlledVocabularyInput # Indicate the type of measure :: Mitigation measures are defined as 'actions aimed at reducing the extent or likelihood of global climate change through the reduction or displacement of greenhouse gas emissions (GHGs) (e.g. through emission reduction, energy efficiency or renewable energy projects'.

Adaptation measures are defined as 'actions preventing or minimising the negative effects and taking advantage of positive effects of global warming in addition to actions which would have occurred naturally or as a matter of course.

Cross-cutting Measures that contain elements of both adaptation and mitigation :: interventionTypes - interventionType: ControlledVocabularyInput! + interventionType: ControlledVocabularyInput # Implementation status :: Operational - Ongoing project
Planned project - Project has not begun but is being constructed or has been registered/approved/funded
Complete - The project has been finalized
Discontinued - planned project terminated :: actionStatus implementationStatus: ControlledVocabularyInput # Type of funding :: Any financial resources that is spent on supporting either mitigation and adaption efforts in South Africa. Climate finance refers to domestic (drawn from local public or private organisations), International (bilateral or multilateral grants or loans). Bilateral funding describes money which is given directly from one government to another, whereas multilateral funding comes from numerous different governments and organisations and is usually arranged by an international organisation such as the World Bank or the UN :: fundingTypes fundingType: ControlledVocabularyInput # Province :: Select province(s) :: regions - province: [ControlledVocabularyInput] + province: [ControlledVocabularyInput]! # District municipality :: Select district municipality(s) :: regions districtMunicipality: [ControlledVocabularyInput] # Local municipality :: Select local municipality(s) :: regions diff --git a/src/client/src/components/multiselect/index.jsx b/src/client/src/components/multiselect/index.jsx index 3df1cd3..7dd0539 100644 --- a/src/client/src/components/multiselect/index.jsx +++ b/src/client/src/components/multiselect/index.jsx @@ -37,7 +37,7 @@ export default ({ const theme = useTheme() return ( -
+
{selected.map(value => { @@ -90,6 +91,7 @@ export default ({ key={value} label={value} style={{ + maxWidth: '100%', ...style, }} {...props} @@ -102,7 +104,7 @@ export default ({ {options.map(option => ( -1} /> - + ))} {loading ? : null} diff --git a/src/client/src/components/project-form/form/components/locations-picker/list-input.jsx b/src/client/src/components/project-form/form/components/locations-picker/list-input.jsx index ff7da52..9da2f68 100644 --- a/src/client/src/components/project-form/form/components/locations-picker/list-input.jsx +++ b/src/client/src/components/project-form/form/components/locations-picker/list-input.jsx @@ -26,7 +26,7 @@ const NewPointForm = ({ closeFn, points, setPoints }) => { onChange={e => setLat(e.target.value)} label="Latitude" type="number" - helperText="Latitude in degrees" + helperText="Latitude in degrees (East / West)" fullWidth variant="outlined" margin="normal" @@ -36,7 +36,7 @@ const NewPointForm = ({ closeFn, points, setPoints }) => { onChange={e => setLng(e.target.value)} label="Longitude" type="number" - helperText="Longitude in degrees" + helperText="Longitude in degrees (North / South)" fullWidth variant="outlined" margin="normal" diff --git a/src/client/src/components/project-form/sections/adaptation-details/_render-field.jsx b/src/client/src/components/project-form/sections/adaptation-details/_render-field.jsx index af61ea1..822c951 100644 --- a/src/client/src/components/project-form/sections/adaptation-details/_render-field.jsx +++ b/src/client/src/components/project-form/sections/adaptation-details/_render-field.jsx @@ -1,5 +1,9 @@ import { useContext, lazy, Suspense } from 'react' -import { GqlBoundFormInput, ControlledVocabularySelect } from '../../form' +import { + GqlBoundFormInput, + ControlledVocabularySelect, + ControlledVocabularySelectMultiple, +} from '../../form' import { context as formContext } from '../../context' import Loading from '../../../loading' @@ -22,9 +26,9 @@ export default ({ field, formName }) => { useContext(formContext) const { name: fieldName, description, type } = field let [placeholder, helperText, tree] = description?.split('::').map(s => s.trim()) || [] - const { name: inputType } = type - const isRequired = !inputType - const value = form[fieldName] + const { kind } = type + const isRequired = kind === 'NON_NULL' + const value = form?.[fieldName] || undefined if (helperText === '') { helperText = ` ` @@ -49,36 +53,36 @@ export default ({ field, formName }) => { */ if (fieldName === 'nationalPolicy') { return ( - updateForm({ [fieldName]: val, target: undefined, otherTarget: undefined }) } - placeholder={placeholder} + label={placeholder} helperText={helperText} /> ) } else if (fieldName === 'otherNationalPolicy') { - if (!form?.nationalPolicy?.term?.match(/^Other\s/)) { + if (!form?.nationalPolicy?.find(({ term }) => term?.match(/^Other\s/))) { return null } } else if (fieldName === 'target') { if (form.nationalPolicy) { return ( - term)} name={fieldName} value={value} error={isRequired && !value} onChange={val => updateForm({ [fieldName]: val, otherTarget: undefined })} - placeholder={placeholder} + label={placeholder} helperText={helperText} /> ) @@ -86,27 +90,27 @@ export default ({ field, formName }) => { return null } } else if (fieldName === 'otherTarget') { - if (!form?.target || !form.target.term?.match(/^Other/)) { + if (!form?.target || !form.target?.find(({ term }) => term?.match(/^Other/))) { return null } } if (fieldName === 'regionalPolicy') { return ( - updateForm({ [fieldName]: val, otherRegionalPolicy: undefined })} - placeholder={placeholder} + label={placeholder} helperText={helperText} /> ) } else if (fieldName === 'otherRegionalPolicy') { - if (!form?.regionalPolicy?.term?.match(/^Other\s/)) { + if (!form?.regionalPolicy?.find(({ term }) => term?.match(/^Other\s/))) { return null } } diff --git a/src/client/src/components/project-form/sections/mitigation-details/_render-field.jsx b/src/client/src/components/project-form/sections/mitigation-details/_render-field.jsx index 5ad5ac2..f93e3c3 100644 --- a/src/client/src/components/project-form/sections/mitigation-details/_render-field.jsx +++ b/src/client/src/components/project-form/sections/mitigation-details/_render-field.jsx @@ -1,6 +1,10 @@ import { useContext, lazy, Suspense } from 'react' import Loading from '../../../loading' -import { GqlBoundFormInput, ControlledVocabularySelect } from '../../form' +import { + GqlBoundFormInput, + ControlledVocabularySelect, + ControlledVocabularySelectMultiple, +} from '../../form' import { context as formContext } from '../../context' const EnergyCalculator = lazy(() => import('../../form/components/calculators/energy')) @@ -35,9 +39,9 @@ export default ({ field, formName }) => { useContext(formContext) const { name: fieldName, description, type } = field let [placeholder, helperText, tree] = description?.split('::').map(s => s.trim()) || [] - const { name: inputType } = type - const isRequired = !inputType - const value = form[fieldName] + const { kind } = type + const isRequired = kind === 'NON_NULL' + const value = form?.[fieldName] || undefined if (helperText === '') { helperText = ` ` @@ -193,20 +197,20 @@ export default ({ field, formName }) => { */ if (fieldName === 'nationalPolicy') { return ( - updateForm({ [fieldName]: val, otherNationalPolicy: undefined })} - placeholder={placeholder} + label={placeholder} helperText={helperText} /> ) } else if (fieldName === 'otherNationalPolicy') { - if (!form?.nationalPolicy?.term?.match(/^Other\s/)) { + if (!form?.nationalPolicy?.find(({ term }) => term?.match(/^Other\s/))) { return null } } @@ -216,20 +220,20 @@ export default ({ field, formName }) => { */ if (fieldName === 'regionalPolicy') { return ( - updateForm({ [fieldName]: val, otherRegionalPolicy: undefined })} - placeholder={placeholder} + label={placeholder} helperText={helperText} /> ) } else if (fieldName === 'otherRegionalPolicy') { - if (!form?.regionalPolicy?.term?.match(/^Other\s/)) { + if (!form?.regionalPolicy?.find(({ term }) => term?.match(/^Other\s/))) { return null } } @@ -311,7 +315,7 @@ export default ({ field, formName }) => { } if (carbonCreditsFields.includes(fieldName)) { - if (!(form.carbonCredit || '').toBoolean()) { + if (!`'${form.carbonCredit}'`.toBoolean()) { return null } }