diff --git a/core/i18n/resources/en.js b/core/i18n/resources/en.js index f24891d416..fdfd8955cb 100644 --- a/core/i18n/resources/en.js +++ b/core/i18n/resources/en.js @@ -1153,6 +1153,16 @@ E.g. this.region = region_attribute_name other: 'Other', }, }, + formHeaderProps: { + headerColorLabel: 'Header color', + headerColor: { + blue: 'Blue', + green: 'Green', + orange: 'Orange', + red: 'Red', + yellow: 'Yellow', + }, + }, textProps: { textInputType: 'Text input type', textInputTypes: { @@ -1236,6 +1246,8 @@ E.g. this.region = region_attribute_name taxon: 'Taxon', text: 'Text', time: 'Time', + // layout elments + formHeader: 'Form Header', }, clone: `Clone '{{nodeDefLabel}}'`, compressFormItems: `Compress form items for '{{nodeDefLabel}}'`, diff --git a/core/survey/_survey/surveyNodeDefs.js b/core/survey/_survey/surveyNodeDefs.js index c0d6b08e34..9c6dbaa364 100644 --- a/core/survey/_survey/surveyNodeDefs.js +++ b/core/survey/_survey/surveyNodeDefs.js @@ -42,26 +42,31 @@ const filterNodeDefsWithoutSiblings = (nodeDefs) => ) export const getNodeDefChildren = - (nodeDef, includeAnalysis = true) => + (nodeDef, includeAnalysis = true, includeLayoutElements = false) => (survey) => { const surveyIndexed = survey.nodeDefsIndex ? survey : SurveyNodeDefsIndex.initAndAssocNodeDefsIndex(survey) - let childDefs = Surveys.getNodeDefChildren({ survey: surveyIndexed, nodeDef, includeAnalysis }) + let childDefs = Surveys.getNodeDefChildren({ + survey: surveyIndexed, + nodeDef, + includeAnalysis, + includeLayoutElements, + }) childDefs = filterNodeDefsWithoutSiblings(childDefs) return childDefs } export const getNodeDefChildrenSorted = - ({ nodeDef, includeAnalysis = false, cycle = null }) => + ({ nodeDef, includeAnalysis = false, cycle = null, includeLayoutElements = false }) => (survey) => { - let childDefs = Surveys.getNodeDefChildrenSorted({ survey, nodeDef, includeAnalysis, cycle }) + let childDefs = Surveys.getNodeDefChildrenSorted({ survey, cycle, nodeDef, includeAnalysis, includeLayoutElements }) childDefs = filterNodeDefsWithoutSiblings(childDefs) return childDefs } export const getNodeDefChildrenInOwnPage = - ({ nodeDef, cycle }) => + ({ nodeDef, cycle, includeAnalysis = true, includeLayoutElements = false }) => (survey) => { - const children = getNodeDefChildren(nodeDef)(survey) + const children = getNodeDefChildren(nodeDef, includeAnalysis, includeLayoutElements)(survey) const childrenInOwnPage = children.filter(NodeDefLayout.hasPage(cycle)) const childrenIndex = NodeDefLayout.getIndexChildren(cycle)(nodeDef) if (childrenIndex.length === 0) return childrenInOwnPage diff --git a/core/survey/nodeDef.js b/core/survey/nodeDef.js index 6dbd36b0c0..07056294e6 100644 --- a/core/survey/nodeDef.js +++ b/core/survey/nodeDef.js @@ -20,6 +20,8 @@ import { valuePropsTaxon } from './nodeValueProps' export { nodeDefType } +export const NodeDefLayoutElementTypes = [nodeDefType.formHeader] + export const keys = { id: ObjectUtils.keys.id, uuid: ObjectUtils.keys.uuid, @@ -87,6 +89,9 @@ export const propKeys = { includeAccuracy: 'includeAccuracy', includeAltitude: 'includeAltitude', includeAltitudeAccuracy: 'includeAltitudeAccuracy', + + // layout elements + headerColor: 'headerColor', } export const textInputTypes = { @@ -203,6 +208,8 @@ export const isInteger = isType(nodeDefType.integer) export const isTaxon = isType(nodeDefType.taxon) export const isText = isType(nodeDefType.text) export const isTime = isType(nodeDefType.time) +// layout elments +export const isFormHeader = isType(nodeDefType.formHeader) export const isReadOnly = getProp(propKeys.readOnly, false) export const isHidden = getProp(propKeys.hidden, false) @@ -250,6 +257,11 @@ export const getTextTransform = getProp(propKeys.textTransform, textTransformVal export const getTextTransformFunction = (nodeDef) => TextUtils.transform({ transformFunction: getTextTransform(nodeDef) }) +// layout elements + +export const getHeaderColor = getProp(propKeys.headerColor) +export const isLayoutElement = isFormHeader + // ==== READ meta export const getMeta = R.propOr({}, keys.meta) export const getMetaHierarchy = R.pathOr([], [keys.meta, metaKeys.h]) @@ -502,8 +514,9 @@ export const keepOnlyOneCycle = export const canNodeDefBeMultiple = (nodeDef) => // Entity def but not root (isEntity(nodeDef) && !isRoot(nodeDef)) || - // Attribute def but not analysis - (!isAnalysis(nodeDef) && + // Attribute def but not layout element and not analysis + (!isLayoutElement(nodeDef) && + !isAnalysis(nodeDef) && R.includes(getType(nodeDef), [ nodeDefType.decimal, nodeDefType.code, @@ -523,7 +536,8 @@ export const canNodeDefTypeBeKey = (type) => nodeDefType.time, ]) -export const canNodeDefBeKey = (nodeDef) => !isAnalysis(nodeDef) && canNodeDefTypeBeKey(getType(nodeDef)) +export const canNodeDefBeKey = (nodeDef) => + !isLayoutElement(nodeDef) && !isAnalysis(nodeDef) && canNodeDefTypeBeKey(getType(nodeDef)) export const canHaveDefaultValue = (nodeDef) => isSingleAttribute(nodeDef) && diff --git a/core/survey/nodeDefType.js b/core/survey/nodeDefType.js index 631625d827..b657e97082 100644 --- a/core/survey/nodeDefType.js +++ b/core/survey/nodeDefType.js @@ -10,4 +10,6 @@ export const nodeDefType = { taxon: 'taxon', file: 'file', entity: 'entity', + // layout elements + formHeader: 'formHeader', } diff --git a/package.json b/package.json index 2507ccf58a..9c2fb3e5cd 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,7 @@ "@mui/material": "^5.14.18", "@mui/x-data-grid": "^6.18.1", "@mui/x-date-pickers": "^6.18.1", - "@openforis/arena-core": "^0.0.175", + "@openforis/arena-core": "^0.0.177", "@openforis/arena-server": "^0.1.30", "@sendgrid/mail": "^7.7.0", "@shopify/draggable": "^1.1.3", diff --git a/server/modules/record/service/update/thread/recordsUpdateThread.js b/server/modules/record/service/update/thread/recordsUpdateThread.js index 19e9476a3c..05ded6916a 100644 --- a/server/modules/record/service/update/thread/recordsUpdateThread.js +++ b/server/modules/record/service/update/thread/recordsUpdateThread.js @@ -160,8 +160,11 @@ class RecordsUpdateThread extends Thread { const { survey, recordsCache } = await this.getOrFetchSurveyData(msg) + console.log('===init record', recordUuid) let record = await RecordManager.fetchRecordAndNodesByUuid({ surveyId, recordUuid }) + console.log('===record1', record) + record = await RecordManager.initNewRecord({ user, survey, @@ -170,6 +173,7 @@ class RecordsUpdateThread extends Thread { nodesUpdateListener: (updatedNodes) => this.handleNodesUpdated.bind(this)({ record, updatedNodes }), nodesValidationListener: (validations) => this.handleNodesValidationUpdated.bind(this)({ record, validations }), }) + console.log('===record2', record) recordsCache.set(recordUuid, record) } diff --git a/test/e2e/tests/login.js b/test/e2e/tests/login.js index d62fe9e856..0771de7820 100644 --- a/test/e2e/tests/login.js +++ b/test/e2e/tests/login.js @@ -25,7 +25,7 @@ export default () => page.click('text="Login"'), ]) - const header = await page.$('.header') + const header = await page.$('.app-header') await expect(header).not.toBe(null) }) }) diff --git a/test/e2e/tests/utils/formUtils.js b/test/e2e/tests/utils/formUtils.js index f0569112ea..efae2150cc 100644 --- a/test/e2e/tests/utils/formUtils.js +++ b/test/e2e/tests/utils/formUtils.js @@ -61,7 +61,7 @@ const expectDropdownValue = async ({ testId = null, parentSelector = '', value } const waitForLoaderToDisappear = async () => page.waitForSelector('.loader', { state: 'hidden', timeout: 5000 }) const waitForHeaderLoaderToDisappear = async () => - page.waitForSelector('.header__loader-wrapper', { state: 'hidden', timeout: 5000 }) + page.waitForSelector('.app-header__loader-wrapper', { state: 'hidden', timeout: 5000 }) export const FormUtils = { selectDropdownItem, diff --git a/webapp/components/form/buttonGroup.js b/webapp/components/form/buttonGroup.js index 7a3e075d52..4a2f1b7097 100644 --- a/webapp/components/form/buttonGroup.js +++ b/webapp/components/form/buttonGroup.js @@ -5,36 +5,54 @@ import PropTypes from 'prop-types' import * as R from 'ramda' -const ButtonGroup = ({ items, groupName, multiple, selectedItemKey, onChange, disabled, deselectable, className }) => ( +const ButtonGroup = ({ + items, + groupName, + multiple, + selectedItemKey, + onChange, + disabled: disabledProp, + deselectable, + className, +}) => (
{items.map((item) => { - const selected = selectedItemKey === item.key || (multiple && R.includes(item.key, selectedItemKey)) + const { key, disabled, icon, label } = item + const selected = selectedItemKey === key || (multiple && R.includes(key, selectedItemKey)) return ( ) })}
) +export const toButtonGroupItems = ({ i18n, object, labelPrefix, icon = null }) => + Object.keys(object).map((key) => ({ + key, + label: i18n.t(`${labelPrefix}${key}`), + icon, + })) + ButtonGroup.propTypes = { items: PropTypes.array, groupName: PropTypes.string, diff --git a/webapp/components/survey/NodeDefDetails/BasicProps/BasicProps.js b/webapp/components/survey/NodeDefDetails/BasicProps/BasicProps.js index e4c38d1665..a5eb5ebbea 100644 --- a/webapp/components/survey/NodeDefDetails/BasicProps/BasicProps.js +++ b/webapp/components/survey/NodeDefDetails/BasicProps/BasicProps.js @@ -27,6 +27,7 @@ import CodeProps from '../CodeProps' import CoordinateProps from '../CoordinateProps' import DecimalProps from '../DecimalProps' import FileProps from '../FileProps' +import FormHeaderProps from '../FormHeaderProps' import TaxonProps from '../TaxonProps' import TextProps from '../TextProps' import AnalysisProps from '../AnalysisProps' @@ -37,6 +38,7 @@ const basicPropsComponentByType = { [NodeDef.nodeDefType.coordinate]: CoordinateProps, [NodeDef.nodeDefType.decimal]: DecimalProps, [NodeDef.nodeDefType.file]: FileProps, + [NodeDef.nodeDefType.formHeader]: FormHeaderProps, [NodeDef.nodeDefType.taxon]: TaxonProps, [NodeDef.nodeDefType.text]: TextProps, } diff --git a/webapp/components/survey/NodeDefDetails/FormHeaderProps.js b/webapp/components/survey/NodeDefDetails/FormHeaderProps.js new file mode 100644 index 0000000000..bb258c326d --- /dev/null +++ b/webapp/components/survey/NodeDefDetails/FormHeaderProps.js @@ -0,0 +1,61 @@ +import './FormHeaderProps.scss' + +import React, { useCallback } from 'react' +import PropTypes from 'prop-types' + +import { FormHeaderColor } from '@openforis/arena-core' + +import * as NodeDef from '@core/survey/nodeDef' + +import { useI18n } from '@webapp/store/system' +import { FormItem } from '@webapp/components/form/Input' +import ButtonGroup, { toButtonGroupItems } from '@webapp/components/form/buttonGroup' + +import { headerColorRgbCodesByColor } from '@webapp/components/survey/SurveyForm/nodeDefs/nodeDefUIProps' + +import { State } from './store' + +const headerColorItems = ({ i18n }) => + toButtonGroupItems({ + i18n, + object: FormHeaderColor, + labelPrefix: 'nodeDefEdit.formHeaderProps.headerColor.', + icon: ({ key }) => ( + + ), + }) + +const FormHeaderProps = (props) => { + const { state, Actions } = props + + const i18n = useI18n() + + const nodeDef = State.getNodeDef(state) + + const headerColor = NodeDef.getHeaderColor(nodeDef) + + const onHeaderColorChange = useCallback( + (value) => { + Actions.setProp({ state, key: NodeDef.propKeys.headerColor, value: FormHeaderColor[value] }) + }, + [Actions, state] + ) + + return ( + + + + ) +} + +FormHeaderProps.propTypes = { + state: PropTypes.object.isRequired, + Actions: PropTypes.object.isRequired, +} + +export default FormHeaderProps diff --git a/webapp/components/survey/NodeDefDetails/FormHeaderProps.scss b/webapp/components/survey/NodeDefDetails/FormHeaderProps.scss new file mode 100644 index 0000000000..c77d674582 --- /dev/null +++ b/webapp/components/survey/NodeDefDetails/FormHeaderProps.scss @@ -0,0 +1,11 @@ +.btn-group.form-header-color-btn-group { + button { + display: flex; + gap: 1rem; + + .form-header-color-icon { + height: 1rem; + width: 1rem; + } + } +} diff --git a/webapp/components/survey/NodeDefDetails/NodeDefDetails.js b/webapp/components/survey/NodeDefDetails/NodeDefDetails.js index a67ddf65e4..adad293ec4 100644 --- a/webapp/components/survey/NodeDefDetails/NodeDefDetails.js +++ b/webapp/components/survey/NodeDefDetails/NodeDefDetails.js @@ -53,12 +53,12 @@ const NodeDefDetails = () => { } />
- {nodeDefType} {NodeDefUIProps.getIconByType(nodeDefType)} + {i18n.t(`surveyForm.addChildToTypes.${nodeDefType}`)} {NodeDefUIProps.getIconByType(nodeDefType)}
- Object.keys(NodeDef.textInputTypes).map((key) => ({ - key, - label: i18n.t(`nodeDefEdit.textProps.textInputTypes.${key}`), - })) + toButtonGroupItems({ i18n, object: NodeDef.textInputTypes, labelPrefix: 'nodeDefEdit.textProps.textInputTypes.' }) const textTransformTypes = ({ i18n }) => - Object.keys(NodeDef.textTransformValues).map((labelKey) => ({ - key: labelKey, - label: i18n.t(`nodeDefEdit.textProps.textTransformTypes.${labelKey}`), - })) + toButtonGroupItems({ + i18n, + object: NodeDef.textTransformValues, + labelPrefix: 'nodeDefEdit.textProps.textTransformTypes.', + }) const TextProps = (props) => { const { state, Actions } = props @@ -30,25 +26,19 @@ const TextProps = (props) => { const nodeDef = State.getNodeDef(state) - const selectLabelValue = useCallback( + const onLabelValueChange = useCallback( (value) => { Actions.setProp({ state, key: NodeDef.propKeys.textTransform, value }) }, - [state] + [Actions, state] ) - useEffect(() => { - if (A.isEmpty(NodeDef.getTextTransform(nodeDef))) { - selectLabelValue(NodeDef.textTransformValues.none) - } - }, []) - return ( <> diff --git a/webapp/components/survey/SurveyForm/components/addNodeDefPanel.js b/webapp/components/survey/SurveyForm/components/addNodeDefPanel.js index cf6e717dd6..ec8137515d 100644 --- a/webapp/components/survey/SurveyForm/components/addNodeDefPanel.js +++ b/webapp/components/survey/SurveyForm/components/addNodeDefPanel.js @@ -2,7 +2,6 @@ import './addNodeDefPanel.scss' import React from 'react' import { connect } from 'react-redux' -import * as R from 'ramda' import { useNavigate } from 'react-router' import { useI18n } from '@webapp/store/system' @@ -22,7 +21,7 @@ const AddNodeDefButtons = (props) => { return ( <> - {R.values(NodeDef.nodeDefType).map((type) => { + {Object.values(NodeDef.nodeDefType).map((type) => { const nodeDefProps = NodeDefUIProps.getDefaultPropsByType(type, surveyCycleKey) // Cannot add entities when entity is rendered as table diff --git a/webapp/components/survey/SurveyForm/components/addNodeDefPanel.scss b/webapp/components/survey/SurveyForm/components/addNodeDefPanel.scss index 03177e9658..93c2a0fe19 100644 --- a/webapp/components/survey/SurveyForm/components/addNodeDefPanel.scss +++ b/webapp/components/survey/SurveyForm/components/addNodeDefPanel.scss @@ -25,7 +25,8 @@ background-color: rgba($green, 0.85); } - &.entity { + &.entity, + &.formHeader { margin-top: 0.7rem; } } diff --git a/webapp/components/survey/SurveyForm/nodeDefs/components/NodeDefFormItem/NodeDefFormItem.js b/webapp/components/survey/SurveyForm/nodeDefs/components/NodeDefFormItem/NodeDefFormItem.js index 181d613aa4..15e538708d 100644 --- a/webapp/components/survey/SurveyForm/nodeDefs/components/NodeDefFormItem/NodeDefFormItem.js +++ b/webapp/components/survey/SurveyForm/nodeDefs/components/NodeDefFormItem/NodeDefFormItem.js @@ -12,7 +12,7 @@ const NodeDefFormItem = (props) => { const { edit, entry, label, lang, nodeDef, nodes, parentNode } = props const nodeDefComponent = React.createElement(NodeDefUiProps.getComponent(nodeDef), { ...props }) - if (NodeDef.isEntity(nodeDef)) { + if (NodeDef.isEntity(nodeDef) || NodeDef.isFormHeader(nodeDef)) { return nodeDefComponent } diff --git a/webapp/components/survey/SurveyForm/nodeDefs/components/types/nodeDefEntitySwitch.js b/webapp/components/survey/SurveyForm/nodeDefs/components/types/nodeDefEntitySwitch.js index 81d2f3d385..6ab7bfd49d 100644 --- a/webapp/components/survey/SurveyForm/nodeDefs/components/types/nodeDefEntitySwitch.js +++ b/webapp/components/survey/SurveyForm/nodeDefs/components/types/nodeDefEntitySwitch.js @@ -27,8 +27,11 @@ const NodeDefEntitySwitch = (props) => { return null } - const includeAnalysis = false - const childDefs = Survey.getNodeDefChildrenSorted({ nodeDef, includeAnalysis, cycle: surveyCycleKey })(survey) + const childDefs = Survey.getNodeDefChildrenSorted({ + nodeDef, + cycle: surveyCycleKey, + includeLayoutElements: true, + })(survey) const nodeDefName = NodeDef.getName(nodeDef) const childUuids = NodeDefLayout.getLayoutChildrenUuids(surveyCycleKey)(nodeDef) diff --git a/webapp/components/survey/SurveyForm/nodeDefs/components/types/nodeDefFormHeader.js b/webapp/components/survey/SurveyForm/nodeDefs/components/types/nodeDefFormHeader.js new file mode 100644 index 0000000000..9dc68b1863 --- /dev/null +++ b/webapp/components/survey/SurveyForm/nodeDefs/components/types/nodeDefFormHeader.js @@ -0,0 +1,31 @@ +import './nodeDefFormHeader.scss' + +import React from 'react' +import PropTypes from 'prop-types' + +import * as NodeDef from '@core/survey/nodeDef' + +import Markdown from '@webapp/components/markdown' +import * as NodeDefUIProps from '@webapp/components/survey/SurveyForm/nodeDefs/nodeDefUIProps' + +import { useSurveyPreferredLang } from '@webapp/store/survey' + +const NodeDefFormHeader = (props) => { + const { nodeDef } = props + + const lang = useSurveyPreferredLang() + + const backgroundColor = NodeDefUIProps.headerColorRgbCodesByColor[NodeDef.getHeaderColor(nodeDef)] + + return ( +
+ +
+ ) +} + +NodeDefFormHeader.propTypes = { + nodeDef: PropTypes.object.isRequired, +} + +export default NodeDefFormHeader diff --git a/webapp/components/survey/SurveyForm/nodeDefs/components/types/nodeDefFormHeader.scss b/webapp/components/survey/SurveyForm/nodeDefs/components/types/nodeDefFormHeader.scss new file mode 100644 index 0000000000..110719f8e5 --- /dev/null +++ b/webapp/components/survey/SurveyForm/nodeDefs/components/types/nodeDefFormHeader.scss @@ -0,0 +1,10 @@ +@import '../../../SurveyFormVars'; + +.survey-form__node-def-form-header { + border: $formBorder; + padding: 0.3rem; + display: flex; + align-items: center; + font-size: 1.1rem; + font-weight: bold; +} diff --git a/webapp/components/survey/SurveyForm/nodeDefs/components/types/nodeDefText.js b/webapp/components/survey/SurveyForm/nodeDefs/components/types/nodeDefText.js index da93458169..c5250ebe01 100644 --- a/webapp/components/survey/SurveyForm/nodeDefs/components/types/nodeDefText.js +++ b/webapp/components/survey/SurveyForm/nodeDefs/components/types/nodeDefText.js @@ -3,12 +3,12 @@ import './nodeDefText.scss' import React from 'react' import classNames from 'classnames' -import { Input } from '@webapp/components/form/Input' -import * as NodeDefUIProps from '@webapp/components/survey/SurveyForm/nodeDefs/nodeDefUIProps' - import * as NodeDef from '@core/survey/nodeDef' import * as Node from '@core/record/node' +import { Input } from '@webapp/components/form/Input' +import * as NodeDefUIProps from '@webapp/components/survey/SurveyForm/nodeDefs/nodeDefUIProps' + import NodeDefErrorBadge from '../nodeDefErrorBadge' import NodeDeleteButton from '../nodeDeleteButton' @@ -59,13 +59,13 @@ const MultipleTextInput = (props) => { const NodeDefText = (props) => { const { edit, entryDataQuery, nodeDef, nodes } = props - return edit ? ( - - ) : NodeDef.isMultiple(nodeDef) && !entryDataQuery ? ( - - ) : ( - - ) + if (edit) { + return + } + if (NodeDef.isMultiple(nodeDef) && !entryDataQuery) { + return + } + return } export default NodeDefText diff --git a/webapp/components/survey/SurveyForm/nodeDefs/components/types/nodeDefText.scss b/webapp/components/survey/SurveyForm/nodeDefs/components/types/nodeDefText.scss index 2dded45c10..641eaacfdc 100644 --- a/webapp/components/survey/SurveyForm/nodeDefs/components/types/nodeDefText.scss +++ b/webapp/components/survey/SurveyForm/nodeDefs/components/types/nodeDefText.scss @@ -39,3 +39,10 @@ background-color: $blueLightFocus; } } + +.survey-form__node-def-header { + border: $formBorder; + padding: 0.3rem; + display: flex; + align-items: center; +} diff --git a/webapp/components/survey/SurveyForm/nodeDefs/nodeDefUIProps.js b/webapp/components/survey/SurveyForm/nodeDefs/nodeDefUIProps.js index 6e58496786..3f9c8afd6c 100644 --- a/webapp/components/survey/SurveyForm/nodeDefs/nodeDefUIProps.js +++ b/webapp/components/survey/SurveyForm/nodeDefs/nodeDefUIProps.js @@ -1,23 +1,35 @@ import React from 'react' import * as R from 'ramda' +import { FormHeaderColor } from '@openforis/arena-core' + import * as NodeDef from '@core/survey/nodeDef' import * as NodeDefLayout from '@core/survey/nodeDefLayout' import { valuePropsCoordinate, valuePropsTaxon } from '@core/survey/nodeValueProps' import { NumberFormats } from '@webapp/components/form/Input' +import NodeDefBoolean from './components/types/nodeDefBoolean' +import NodeDefCode from './components/types/NodeDefCode' +import NodeDefCoordinate from './components/types/nodeDefCoordinate' +import NodeDefDate from './components/types/nodeDefDate' import NodeDefEntitySwitch from './components/types/nodeDefEntitySwitch' import NodeDefFile from './components/types/nodeDefFile' +import NodeDefFormHeader from './components/types/nodeDefFormHeader' import NodeDefTaxon from './components/types/nodeDefTaxon' -import NodeDefCoordinate from './components/types/nodeDefCoordinate' -import NodeDefCode from './components/types/NodeDefCode' -import NodeDefBoolean from './components/types/nodeDefBoolean' import NodeDefText from './components/types/nodeDefText' -import NodeDefDate from './components/types/nodeDefDate' import NodeDefTime from './components/types/nodeDefTime' -const { integer, decimal, text, date, time, boolean, code, coordinate, taxon, file, entity } = NodeDef.nodeDefType +const { integer, decimal, text, date, time, boolean, code, coordinate, taxon, file, entity, formHeader } = + NodeDef.nodeDefType + +export const headerColorRgbCodesByColor = { + [FormHeaderColor.blue]: '#b3e5fc', + [FormHeaderColor.green]: '#b2dfdb', + [FormHeaderColor.orange]: '#ffb38a', + [FormHeaderColor.red]: '#f97c7c', + [FormHeaderColor.yellow]: '#fffdaf', +} const propsUI = { [integer]: { @@ -121,6 +133,14 @@ const propsUI = { [NodeDefLayout.keys.layout]: NodeDefLayout.newLayout(cycle, NodeDefLayout.renderType.table), }), }, + + [formHeader]: { + component: NodeDefFormHeader, + icon: , + defaultProps: () => ({ + [NodeDef.propKeys.headerColor]: FormHeaderColor.blue, + }), + }, } const getPropByType = diff --git a/webapp/views/App/Header/Header.js b/webapp/views/App/Header/Header.js index 0f6506849a..5f9164e2b6 100644 --- a/webapp/views/App/Header/Header.js +++ b/webapp/views/App/Header/Header.js @@ -51,8 +51,8 @@ const Header = () => { const surveyTitle = surveyLabel ? `${surveyLabel} [${surveyName}]` : surveyName return ( -
-
+
+
Open Foris @@ -60,7 +60,7 @@ const Header = () => { -
+
{Survey.isValid(surveyInfo) && ( <> { to={appModuleUri(homeModules.surveyInfo)} className="btn-s btn-transparent" > - + { /> {canEditSurvey && Survey.isDraft(surveyInfo) && } -
{appSaving && }
+
{appSaving && }
)}
@@ -89,7 +89,7 @@ const Header = () => {