-
Notifications
You must be signed in to change notification settings - Fork 318
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Maps Update: Cards and Modals for Maps Components #1314
base: development
Are you sure you want to change the base?
Changes from 36 commits
6f3ee9f
17d26a0
823b161
09b333a
8ff0ebe
dc87b56
c799c95
0a941da
af01ec7
b55b672
2b3885d
a7e6ddf
6397225
0fb3b45
76ddde9
815f998
b427cbf
b687569
d57da8c
bc49a65
105395d
0d0a421
75c5609
8430932
6db61de
e775c62
4c5f66c
09e0738
811dc66
9641220
30d7bf7
1e0b61b
51a220f
d270242
18fa275
ca08606
9c4513d
8a276b4
21de916
45d0db6
17c851e
5c8dbc1
b7a3e56
ae28cda
67d578c
66ea48d
095def8
8a53505
b71527a
90db2c6
18b8b6e
a8237ba
04ba6a5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
||
import * as React from 'react'; | ||
import { useState } from 'react'; | ||
import { FormattedMessage } from 'react-intl'; | ||
import { Button, Modal, ModalHeader, ModalBody, ModalFooter, Form, FormGroup, Label, Input } from 'reactstrap'; | ||
import { Link } from 'react-router-dom'; | ||
|
||
interface CreateMapModalProps { | ||
show: boolean; | ||
handleClose: () => void; | ||
createNewMap: () => void; | ||
} | ||
|
||
/** | ||
* Defines the create map modal form | ||
* @param root0 | ||
huss marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* @param root0.show | ||
* @param root0.handleClose | ||
* @param root0.createNewMap | ||
* @returns Map create element | ||
*/ | ||
function CreateMapModalComponent({ show, handleClose, createNewMap }: CreateMapModalProps) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Other create modals do not pass props. Are these essential or does a change need to happen (maybe outside this PR)? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will be future work, I have left a TODO note. |
||
// TODO: Get rid of props, migrate to RTK, finish modal | ||
// Once modal is finished, it will be used in MapsDetailComponent | ||
const [nameInput, setNameInput] = useState(''); | ||
const [noteInput, setNoteInput] = useState(''); | ||
|
||
const handleCreate = () => { | ||
// TODO: Implement create functionality | ||
createNewMap(); | ||
handleClose(); | ||
}; | ||
|
||
return ( | ||
<Modal isOpen={show} toggle={handleClose}> | ||
<ModalHeader toggle={handleClose}> | ||
<FormattedMessage id="create.map" /> | ||
</ModalHeader> | ||
<ModalBody> | ||
<Form> | ||
<FormGroup> | ||
<Label for="mapName"><FormattedMessage id="map.name" /></Label> | ||
<Input | ||
id="mapName" | ||
value={nameInput} | ||
onChange={e => setNameInput(e.target.value)} | ||
/> | ||
</FormGroup> | ||
<FormGroup> | ||
<Label for="mapNote"><FormattedMessage id="note" /></Label> | ||
<Input | ||
id="mapNote" | ||
type="textarea" | ||
value={noteInput} | ||
onChange={e => setNoteInput(e.target.value)} | ||
/> | ||
</FormGroup> | ||
</Form> | ||
<div> | ||
<Link to='/calibration' onClick={() => createNewMap()}> | ||
<Button color='primary'> | ||
<FormattedMessage id='map.upload.file' /> | ||
</Button> | ||
</Link> | ||
</div> | ||
</ModalBody> | ||
<ModalFooter> | ||
<Button color="secondary" onClick={handleClose}> | ||
<FormattedMessage id="cancel" /> | ||
</Button> | ||
<Button color="primary" onClick={handleCreate}> | ||
<FormattedMessage id="create" /> | ||
</Button> | ||
</ModalFooter> | ||
</Modal> | ||
); | ||
} | ||
|
||
export default CreateMapModalComponent; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
/* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
||
import * as React from 'react'; | ||
import { useState } from 'react'; | ||
import { FormattedMessage, useIntl } from 'react-intl'; | ||
import { Button, Modal, ModalHeader, ModalBody, ModalFooter, Form, FormGroup, Label, Input } from 'reactstrap'; | ||
import { CalibrationModeTypes, MapMetadata } from '../../types/redux/map'; | ||
import { editMapDetails, submitEditedMap, removeMap, setCalibration } from '../../redux/actions/map'; | ||
import { showErrorNotification } from '../../utils/notifications'; | ||
import { useAppDispatch } from '../../redux/reduxHooks'; | ||
import { AppDispatch } from 'store'; | ||
ChrisMart21 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
interface EditMapModalProps { | ||
map: MapMetadata; | ||
} | ||
|
||
// TODO: Migrate to RTK | ||
const EditMapModalComponent: React.FC<EditMapModalProps> = ({ map }) => { | ||
const [showModal, setShowModal] = useState(false); | ||
const handleShow = () => setShowModal(true); | ||
const handleClose = () => setShowModal(false); | ||
const dispatch: AppDispatch = useAppDispatch(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note for future to move to newer way. Similar to another comment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Noted for future work. |
||
const [nameInput, setNameInput] = useState(map.name); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm unclear on why the note could be empty if this is editing an existing note. Can the note be null or something? |
||
const [noteInput, setNoteInput] = useState(map.note || ''); | ||
const [circleInput, setCircleInput] = useState(map.circleSize.toString()); | ||
const [displayable, setDisplayable] = useState(map.displayable); | ||
|
||
const intl = useIntl(); | ||
|
||
const handleSave = () => { | ||
const updatedMap = { | ||
...map, | ||
name: nameInput, | ||
note: noteInput, | ||
circleSize: parseFloat(circleInput), | ||
displayable: displayable | ||
}; | ||
dispatch(editMapDetails(updatedMap)); | ||
dispatch(submitEditedMap(updatedMap.id)); | ||
handleClose(); | ||
}; | ||
|
||
const handleDelete = () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not being done as is the case, for example, with unit. It should be the same. |
||
const consent = window.confirm(intl.formatMessage({ id: 'map.confirm.remove' }, { name: map.name })); | ||
if (consent) { | ||
dispatch(removeMap(map.id)); | ||
handleClose(); | ||
} | ||
}; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe for future TODO and in issue. Most modals use centralized functions for changes and not one for each item. This means you don't dispatch changes until save. |
||
const handleCalibrationSetting = (mode: CalibrationModeTypes) => { | ||
dispatch(setCalibration(mode, map.id)); | ||
handleClose(); | ||
}; | ||
|
||
const toggleCircleEdit = () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This sort of check is now done with input checks on the form in other modals. |
||
const regtest = /^\d+(\.\d+)?$/; | ||
if (regtest.test(circleInput) && parseFloat(circleInput) <= 2.0) { | ||
setCircleInput(circleInput); | ||
} else { | ||
showErrorNotification(intl.formatMessage({ id: 'invalid.number' })); | ||
} | ||
}; | ||
|
||
return ( | ||
<> | ||
<div className="edit-btn"> | ||
<Button color='secondary' onClick={handleShow}> | ||
<FormattedMessage id="edit.map" /> | ||
</Button> | ||
</div> | ||
<Modal isOpen={showModal} toggle={handleClose}> | ||
<ModalHeader toggle={handleClose}> | ||
<FormattedMessage id="edit.map" /> | ||
</ModalHeader> | ||
<ModalBody> | ||
<Form> | ||
<FormGroup> | ||
<Label for="mapName"><FormattedMessage id="map.name" /></Label> | ||
<Input | ||
id="mapName" | ||
value={nameInput} | ||
onChange={e => setNameInput(e.target.value)} | ||
/> | ||
</FormGroup> | ||
<FormGroup> | ||
<Label for='map.displayable'><FormattedMessage id='map.displayable' /></Label> | ||
<Input | ||
id="mapDisplayable" | ||
type="select" | ||
value={displayable.toString()} | ||
onChange={e => setDisplayable(e.target.value === 'true')} | ||
> | ||
<option value="true">{intl.formatMessage({ id: 'map.is.displayable' })}</option> | ||
<option value="false">{intl.formatMessage({ id: 'map.is.not.displayable' })}</option> | ||
</Input> | ||
</FormGroup> | ||
<FormGroup> | ||
<Label for="mapCircleSize"><FormattedMessage id="map.circle.size" /></Label> | ||
<Input | ||
id="mapCircleSize" | ||
type='number' | ||
value={circleInput} | ||
onChange={e => setCircleInput(e.target.value)} | ||
invalid={parseFloat(circleInput) < 0} | ||
onBlur={toggleCircleEdit} | ||
/> | ||
</FormGroup> | ||
<FormGroup> | ||
<Label for="mapNote"><FormattedMessage id="note" /></Label> | ||
<Input | ||
id="mapNote" | ||
type="textarea" | ||
value={noteInput} | ||
onChange={e => setNoteInput(e.target.value.slice(0, 30))} | ||
/> | ||
</FormGroup> | ||
</Form> | ||
<div> | ||
<Label><FormattedMessage id="map.filename" /></Label> | ||
<Input | ||
id='mapFilename' | ||
name='mapFilename' | ||
type='text' | ||
defaultValue={map.filename} | ||
disabled> | ||
</Input> | ||
<Button color='primary' onClick={() => handleCalibrationSetting(CalibrationModeTypes.initiate)}> | ||
<FormattedMessage id='map.upload.new.file' /> | ||
juanjoseguva marked this conversation as resolved.
Show resolved
Hide resolved
|
||
</Button> | ||
</div> | ||
<div> | ||
<Label><FormattedMessage id="map.calibration" /></Label> | ||
<p> | ||
<FormattedMessage id={map.origin && map.opposite ? 'map.is.calibrated' : 'map.is.not.calibrated'} /> | ||
</p> | ||
<Button color='primary' onClick={() => handleCalibrationSetting(CalibrationModeTypes.calibrate)}> | ||
<FormattedMessage id='map.calibrate' /> | ||
</Button> | ||
</div> | ||
</ModalBody> | ||
<ModalFooter> | ||
<Button color="danger" onClick={handleDelete}> | ||
<FormattedMessage id="delete.map" /> | ||
</Button> | ||
<Button color="secondary" onClick={handleClose}> | ||
<FormattedMessage id="cancel" /> | ||
</Button> | ||
<Button color="primary" onClick={handleSave}> | ||
<FormattedMessage id="save.all" /> | ||
</Button> | ||
</ModalFooter> | ||
</Modal> | ||
</> | ||
); | ||
}; | ||
|
||
export default EditMapModalComponent; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm unclear as what this file is used for. When I click create map it goes to the old page. I cannot find it used anywhere. Is it for the future, unneeded or am I missing something? If it is future then a clear TODO/comment is needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is work for the future, as there was not enough time to finish it given our time constraints. I have left TODOs throughout the necessary pieces of code.