Skip to content

Commit

Permalink
187810830 edit attr prop modal tuneup (#1336)
Browse files Browse the repository at this point in the history
* Updates modals to have a gray background and inputs have white background.

* Capitalizes edit atrribute form labels

* Tunes up edit attribute properties modal styling

* Adds default button color

* Adds attribute icon to eidt attribute modal

* Tunes up formula modal styling

* Closes the edit attribute modal and applies the changes when user types "Enter" in the inputs or text area.

* Makes input fields more responsive

* Handle Escape key down
  • Loading branch information
eireland authored Jul 11, 2024
1 parent 355a892 commit b9ead1c
Show file tree
Hide file tree
Showing 11 changed files with 202 additions and 120 deletions.
10 changes: 10 additions & 0 deletions v3/src/assets/icons/attribute-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions v3/src/components/case-table/attribute-menu/attribute-menu.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Edit Attribute Modal Styles
.edit-attribute-form-row {
display: flex !important;
flex-direction: row;
align-items: center;
justify-content: space-between;

input, .chakra-select__wrapper {
margin-left: 10px;
}
input {
padding: 0 8px;
}
}
.edit-attribute-form-row.editable {
justify-content: flex-start;
.chakra-radio-group {
margin-left: 10px;
}
}

// Formula Editor Styles
.formula-form-control {
input {
max-width: 270px;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import { updateAttributesNotification } from "../../../models/data/data-set-noti
import { uniqueName } from "../../../utilities/js-utils"
import { t } from "../../../utilities/translation/translate"
import { CodapModal } from "../../codap-modal"
import AttributeIcon from "../../../assets/icons/attribute-icon.svg"

import "./attribute-menu.scss"

// for use in menus of attribute types
const selectableAttributeTypes = ["none", ...attributeTypes] as const
Expand Down Expand Up @@ -78,90 +81,105 @@ export const EditAttributePropertiesModal = ({ attributeId, isOpen, onClose }: I
onClose()
}

const handleKeyDown = (e: React.KeyboardEvent) => {
e.stopPropagation()
if (e.key === "Escape") {
closeModal()
}
if (e.key === "Enter") {
applyChanges()
}
}

const buttons = [
{
label: t("DG.AttrFormView.cancelBtnTitle"), tooltip: t("DG.AttrFormView.cancelBtnTooltip"), onClick: closeModal
},
{ label: t("DG.AttrFormView.applyBtnTitle"), onClick: applyChanges }
{ label: t("DG.AttrFormView.applyBtnTitle"), onClick: applyChanges, default: true }
]

return (
<CodapModal
isOpen={isOpen}
onClose={closeModal}
modalWidth={"350px"}
modalWidth={"265px"}
modalHeight={"300px"}
>
<ModalHeader h="30" className="codap-modal-header" fontSize="md" data-testid="codap-modal-header">
<div className="codap-modal-icon-container" />
<div className="codap-modal-icon-container">
<AttributeIcon className="codap-modal-icon" />
</div>
<div className="codap-header-title">{t("DG.TableController.attributeEditor.title")}</div>
<ModalCloseButton onClick={closeModal} data-testid="modal-close-button"/>
</ModalHeader>
<ModalBody>
<FormControl display="flex" flexDirection="column">
<FormLabel display="flex" flexDirection="row">{t("DG.CaseTable.attributeEditor.name")}
<Input size="xs" ml={5} placeholder="attribute" value={attributeName} onFocus={(e) => e.target.select()}
onChange={event => setAttributeName(event.target.value)} data-testid="attr-name-input"
onKeyDown={(e) => e.stopPropagation()}
/>
</FormLabel>
<FormLabel>{t("DG.CaseTable.attributeEditor.description")}
<Textarea size="xs" placeholder="Describe the attribute" value={description}
onFocus={(e) => e.target.select()} onKeyDown={(e) => e.stopPropagation()}
onChange={event => setDescription(event.target.value)} data-testid="attr-description-input"
/>
</FormLabel>
<FormLabel display="flex" flexDirection="row" mr={5}>{t("DG.CaseTable.attributeEditor.type")}
<Select size="xs" ml={5} value={userType} data-testid="attr-type-select"
onChange={(e) => setUserType(e.target.value as AttributeType)}>
{selectableAttributeTypes.map(aType => {
return (<option key={aType} value={aType} data-testid="attr-type-option">
{t(`DG.CaseTable.attribute.type.${aType}`)}
</option>)
})}
</Select>
</FormLabel>
<FormLabel display="flex" flexDirection="row">{t("DG.CaseTable.attributeEditor.unit")}
<Input size="xs" placeholder="unit" ml={5} value={units} onFocus={(e) => e.target.select()}
onChange={event => setUnits(event.target.value)} data-testid="attr-unit-input"
onKeyDown={(e) => e.stopPropagation()}
/>
</FormLabel>
<FormLabel display="flex" flexDirection="row" mr={5}>{t("DG.CaseTable.attributeEditor.precision")}
<Select size="xs" ml={5} value={precision} data-testid="attr-precision-select"
onChange={(e) => setPrecision(e.target.value)}>
<option value={""}></option>
<option value={"0"} data-testid="attr-precision-option">0</option>
<option value={"1"} data-testid="attr-precision-option">1</option>
<option value={"2"} data-testid="attr-precision-option">2</option>
<option value={"3"} data-testid="attr-precision-option">3</option>
<option value={"4"} data-testid="attr-precision-option">4</option>
<option value={"5"} data-testid="attr-precision-option">5</option>
<option value={"6"} data-testid="attr-precision-option">6</option>
<option value={"7"} data-testid="attr-precision-option">7</option>
<option value={"8"} data-testid="attr-precision-option">8</option>
<option value={"9"} data-testid="attr-precision-option">9</option>
</Select>
</FormLabel>
<FormLabel display="flex" flexDirection="row">{t("DG.CaseTable.attributeEditor.editable")}
<RadioGroup value={editable} ml={5} data-testid="attr-editable-radio"
onChange={(value) => setEditable(value as YesNoValue)}
onKeyDown={(e) => e.stopPropagation()}>
<HStack>
<Radio value="yes">{t("V3.general.yes")}</Radio>
<Radio value="no">{t("V3.general.no")}</Radio>
</HStack>
</RadioGroup>
</FormLabel>
</FormControl>
<FormControl display="flex" flexDirection="column">
<FormLabel className="edit-attribute-form-row">
{t("DG.CaseTable.attributeEditor.name")}
<Input size="xs" ml={5} placeholder="attribute" value={attributeName} onFocus={(e) => e.target.select()}
onChange={event => setAttributeName(event.target.value)} data-testid="attr-name-input"
onKeyDown={handleKeyDown}
/>
</FormLabel>
<FormLabel>{t("DG.CaseTable.attributeEditor.description")}
<Textarea size="xs" placeholder="Describe the attribute" value={description}
onFocus={(e) => e.target.select()} onKeyDown={handleKeyDown}
onChange={event => setDescription(event.target.value)} data-testid="attr-description-input"
/>
</FormLabel>
<FormLabel mr={5} className="edit-attribute-form-row">{t("DG.CaseTable.attributeEditor.type")}
<Select size="xs" ml={5} value={userType} data-testid="attr-type-select"
onChange={(e) => setUserType(e.target.value as AttributeType)}>
{selectableAttributeTypes.map(aType => {
return (<option key={aType} value={aType} data-testid="attr-type-option">
{t(`DG.CaseTable.attribute.type.${aType}`)}
</option>)
})}
</Select>
</FormLabel>
<FormLabel className="edit-attribute-form-row">{t("DG.CaseTable.attributeEditor.unit")}
<Input size="xs" placeholder="unit" ml={5} value={units} onFocus={(e) => e.target.select()}
onChange={event => setUnits(event.target.value)} data-testid="attr-unit-input"
onKeyDown={handleKeyDown}
/>
</FormLabel>
<FormLabel className="edit-attribute-form-row" mr={5}>{t("DG.CaseTable.attributeEditor.precision")}
<Select size="xs" ml={5} value={precision} data-testid="attr-precision-select"
onChange={(e) => setPrecision(e.target.value)}>
<option value={""}></option>
<option value={"0"} data-testid="attr-precision-option">0</option>
<option value={"1"} data-testid="attr-precision-option">1</option>
<option value={"2"} data-testid="attr-precision-option">2</option>
<option value={"3"} data-testid="attr-precision-option">3</option>
<option value={"4"} data-testid="attr-precision-option">4</option>
<option value={"5"} data-testid="attr-precision-option">5</option>
<option value={"6"} data-testid="attr-precision-option">6</option>
<option value={"7"} data-testid="attr-precision-option">7</option>
<option value={"8"} data-testid="attr-precision-option">8</option>
<option value={"9"} data-testid="attr-precision-option">9</option>
</Select>
</FormLabel>
<FormLabel className="edit-attribute-form-row editable">{t("DG.CaseTable.attributeEditor.editable")}
<RadioGroup value={editable} ml={5} data-testid="attr-editable-radio"
onChange={(value) => setEditable(value as YesNoValue)}
onKeyDown={handleKeyDown}>
<HStack>
<Radio value="yes">{t("V3.general.yes")}</Radio>
<Radio value="no">{t("V3.general.no")}</Radio>
</HStack>
</RadioGroup>
</FormLabel>
</FormControl>
</ModalBody>
<ModalFooter mt="-5">
{buttons.map((b: any, i)=>{
const key = `${i}-${b.className}`
const key = `${i}-${b.label}`
return (
<Tooltip key={key} label={b.tooltip} h="20px" fontSize="12px"
color="white" openDelay={1000} placement="bottom" bottom="15px" left="15px"
data-testid="modal-tooltip">
<Button key={key} size="xs" variant="ghost" ml="5" onClick={b.onClick} data-testid={`${b.label}-button`}>
<Button key={key} size="xs" variant={`${b.default ? "default" : ""}`} ml="5" onClick={b.onClick}
_hover={{backgroundColor: "#72bfca", color: "white"}} data-testid={`${b.label}-button`}>
{b.label}
</Button>
</Tooltip>
Expand Down
32 changes: 20 additions & 12 deletions v3/src/components/case-table/attribute-menu/edit-formula-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { updateAttributesNotification, updateCasesNotification } from "../../../
import { t } from "../../../utilities/translation/translate"
import { CodapModal } from "../../codap-modal"

import "./attribute-menu.scss"

interface IProps {
attributeId: string
isOpen: boolean
Expand Down Expand Up @@ -53,22 +55,24 @@ export const EditFormulaModal = observer(function EditFormulaModal({ attributeId
onClick: closeModal
}, {
label: t("DG.AttrFormView.applyBtnTitle"),
onClick: applyFormula
onClick: applyFormula,
default: true
}]

return (
<CodapModal
isOpen={isOpen}
onClose={onClose}
modalWidth={"350px"}
modalWidth={"400px"}
modalHeight={"180px"}
>
<ModalHeader h="30" className="codap-modal-header" fontSize="md" data-testid="codap-modal-header">
<div className="codap-modal-icon-container" />
<div className="codap-header-title" />
<ModalCloseButton onClick={onClose} data-testid="modal-close-button" />
</ModalHeader>
<ModalBody>
<FormControl display="flex" flexDirection="column">
<FormControl display="flex" flexDirection="column" className="formula-form-control">
<FormLabel display="flex" flexDirection="row">{t("DG.AttrFormView.attrNamePrompt")}
<Input
size="xs" ml={5} placeholder="attribute" value={attribute?.name} data-testid="attr-name-input" disabled
Expand All @@ -82,15 +86,19 @@ export const EditFormulaModal = observer(function EditFormulaModal({ attributeId
</ModalBody>
<ModalFooter mt="-5">
{
buttons.map((b, idx) => (
<Tooltip key={idx} label={b.tooltip} h="20px" fontSize="12px" color="white" openDelay={1000}
placement="bottom" bottom="15px" left="15px" data-testid="modal-tooltip"
>
<Button size="xs" variant="ghost" ml="5" onClick={b.onClick} data-testid={`${b.label}-button`}>
{b.label}
</Button>
</Tooltip>
))
buttons.map((b, idx) => {
const key = `${idx}-${b.label}`
return (
<Tooltip key={idx} label={b.tooltip} h="20px" fontSize="12px" color="white" openDelay={1000}
placement="bottom" bottom="15px" left="15px" data-testid="modal-tooltip"
>
<Button key={key} size="xs" variant={`${b.default ? "default" : ""}`} ml="5" onClick={b.onClick}
_hover={{backgroundColor: "#72bfca", color: "white"}} data-testid={`${b.label}-button`}>
{b.label}
</Button>
</Tooltip>
)
})
}
</ModalFooter>
</CodapModal>
Expand Down
21 changes: 20 additions & 1 deletion v3/src/components/codap-modal.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@ $header-height: 30px;
flex-direction: row;
align-items: center;
box-shadow: none;
background-color: #f0f0f0;

.codap-modal-icon-container {
width: 30px;
height: 30px;
background-color: $teal-dark;
top: 0;
left: 0;
display: flex;
align-items: center;
justify-content: center;
}

.codap-header-title {
Expand All @@ -41,7 +45,22 @@ $header-height: 30px;
}
}

.chakra-modal__body {
background-color: #f0f0f0;
padding: 0 8px;
box-sizing: border-box;
width: inherit;
}

.chakra-modal__footer {
background-color: #f0f0f0;
}

.chakra-form__label {
align-items: center !important;
align-items: center;
margin-inline-end: 0;
}
input, textarea, select, .chakra-radio__control {
background-color: white;
}
}
14 changes: 7 additions & 7 deletions v3/src/utilities/translation/lang/en-US.json5
Original file line number Diff line number Diff line change
Expand Up @@ -767,16 +767,16 @@
"DG.CaseTable.attribute.type.qualitative": "qualitative",
"DG.CaseTable.attribute.type.boundary": "boundary",
"DG.CaseTable.attribute.type.checkbox": "checkbox",
"DG.CaseTable.attributeEditor.name": "name",
"DG.CaseTable.attributeEditor.description": "description",
"DG.CaseTable.attributeEditor.type": "type",
"DG.CaseTable.attributeEditor.unit": "unit",
"DG.CaseTable.attributeEditor.precision": "precision",
"DG.CaseTable.attributeEditor.name": "Name",
"DG.CaseTable.attributeEditor.description": "Description",
"DG.CaseTable.attributeEditor.type": "Type",
"DG.CaseTable.attributeEditor.unit": "Unit",
"DG.CaseTable.attributeEditor.precision": "Precision",
"DG.CaseTable.attributeEditor.datePrecisionOptions": "year month day hour minute second millisecond",
"DG.CaseTable.attributeEditor.editable": "editable",
"DG.CaseTable.attributeEditor.editable": "Editable",
"DG.CaseTable.insertCasesDialog.title": "Insert Cases",
"DG.CaseTable.insertCasesDialog.numCasesPrompt": "# cases to insert:",
"DG.CaseTable.insertCasesDialog.beforeAfter.prompt": "location:",
"DG.CaseTable.insertCasesDialog.beforeAfter.prompt": "Location:",
"DG.CaseTable.insertCasesDialog.beforeAfter.before": "before",
"DG.CaseTable.insertCasesDialog.beforeAfter.after": "after",
"DG.CaseTable.insertCasesDialog.applyBtnTitle": "Insert Cases",
Expand Down
14 changes: 7 additions & 7 deletions v3/src/utilities/translation/lang/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -460,15 +460,15 @@
"DG.CaseTable.attribute.type.date": "fecha",
"DG.CaseTable.attribute.type.qualitative": "cualitativo",
"DG.CaseTable.attribute.type.boundary": "límite",
"DG.CaseTable.attributeEditor.name": "nombre",
"DG.CaseTable.attributeEditor.description": "descripción",
"DG.CaseTable.attributeEditor.type": "tipo",
"DG.CaseTable.attributeEditor.unit": "unidad",
"DG.CaseTable.attributeEditor.precision": "precisión",
"DG.CaseTable.attributeEditor.editable": "editable",
"DG.CaseTable.attributeEditor.name": "Nombre",
"DG.CaseTable.attributeEditor.description": "Descripción",
"DG.CaseTable.attributeEditor.type": "Tipo",
"DG.CaseTable.attributeEditor.unit": "Unidad",
"DG.CaseTable.attributeEditor.precision": "Precisión",
"DG.CaseTable.attributeEditor.editable": "Editable",
"DG.CaseTable.insertCasesDialog.title": "Insertar Casos",
"DG.CaseTable.insertCasesDialog.numCasesPrompt": "# de casos a insertar:",
"DG.CaseTable.insertCasesDialog.beforeAfter.prompt": "ubicación:",
"DG.CaseTable.insertCasesDialog.beforeAfter.prompt": "Ubicación:",
"DG.CaseTable.insertCasesDialog.beforeAfter.before": "antes",
"DG.CaseTable.insertCasesDialog.beforeAfter.after": "después",
"DG.CaseTable.insertCasesDialog.applyBtnTitle": "Insertar Casos",
Expand Down
Loading

0 comments on commit b9ead1c

Please sign in to comment.