Skip to content
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

Open
wants to merge 53 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
6f3ee9f
Changing maps page to cards with modals
Jul 18, 2024
17d26a0
Adding messagesfor map modal
Jul 18, 2024
823b161
Adding licence header
Jul 18, 2024
09b333a
Removing unused line
Jul 18, 2024
8ff0ebe
Fix to allow saves in map modal
Nireves333 Jul 24, 2024
dc87b56
Create and utilize new maps selector
hazeltonbw Jul 28, 2024
c799c95
Class Component to Redux function component update
hazeltonbw Jul 28, 2024
0a941da
Adding ": " to map card descriptors for formatting
Jul 24, 2024
af01ec7
Removing unnecessary button
Jul 24, 2024
b55b672
Adding missing : on a map descriptor
Jul 30, 2024
2b3885d
Removing item name from descriptor (so no map)
Jul 30, 2024
a7e6ddf
Limiting map note to 30 characters.
Jul 31, 2024
6397225
Treating circle size as a positive number
Jul 31, 2024
0fb3b45
Changing the order of descriptors on card to match the modal.
Jul 31, 2024
76ddde9
Removing unused variable
Jul 31, 2024
815f998
Changing the name of the button to upload a new map image file.
Jul 31, 2024
b427cbf
Resolving syntax and jsdoc declaration requirements
Jul 31, 2024
b687569
Resolving syntax and jsdoc declaration requirements
Jul 31, 2024
d57da8c
use useAppDispatch for type safety
hazeltonbw Jul 31, 2024
bc49a65
Remove container props, utilize dispatch for redux actions
hazeltonbw Jul 31, 2024
105395d
Use the new component instead of old container
hazeltonbw Jul 31, 2024
0d0a421
Remove props used for container, removed isEdited and isSubmitting st…
hazeltonbw Jul 31, 2024
75c5609
Delete unused types and only import necessary functions from moment p…
hazeltonbw Jul 31, 2024
8430932
Delete unused props & functions, add new memoized selector
hazeltonbw Jul 31, 2024
6db61de
Treating map file name as an uneditable item
Aug 1, 2024
e775c62
Handling displayable with an enum instead of a boolean and fixing a t…
Aug 1, 2024
4c5f66c
Bug squashing
Aug 1, 2024
09e0738
Aligning modal call function names with other components and limiting…
Aug 2, 2024
811dc66
Update code to use simple selector
hazeltonbw Aug 3, 2024
9641220
Put modal state where it belongs
hazeltonbw Aug 3, 2024
30d7bf7
Merge branch 'development' into Maps-Update
juanjoseguva Aug 3, 2024
1e0b61b
Reverting to treating map displayability variable as a boolean instea…
Aug 3, 2024
51a220f
Add coloring to map Display and add TODO for date internationalization
Nireves333 Aug 3, 2024
d270242
Use memoized createAppSelector instead of directly handling state in …
hazeltonbw Aug 4, 2024
18fa275
Fix linting errors
hazeltonbw Aug 4, 2024
ca08606
Leave TODO notes for future updates
hazeltonbw Aug 5, 2024
9c4513d
Merge remote-tracking branch 'origin/development' into pr/juanjoseguv…
huss Aug 5, 2024
8a276b4
fix linting
huss Aug 5, 2024
21de916
Initial RTKQ Maps
ChrisMart21 Aug 5, 2024
45d0db6
Remove Maps from RootState
ChrisMart21 Aug 11, 2024
17c851e
Comments
ChrisMart21 Aug 11, 2024
5c8dbc1
More Maps Changes
ChrisMart21 Aug 13, 2024
b7a3e56
ReEnable Immutable check
ChrisMart21 Aug 13, 2024
ae28cda
Bug Fix Revert Change.
ChrisMart21 Aug 13, 2024
67d578c
Hot Fix Changes.
ChrisMart21 Aug 13, 2024
66ea48d
Fix Imports
ChrisMart21 Aug 13, 2024
095def8
MapChartSelect Crash Fix
ChrisMart21 Aug 13, 2024
8a53505
Login Invalidation updated.
ChrisMart21 Aug 13, 2024
b71527a
Cleanup Legacy Redux where applicable
ChrisMart21 Aug 13, 2024
90db2c6
Merge branch 'development' into Maps-Update
ChrisMart21 Aug 13, 2024
18b8b6e
Fix Merge Issues / Missing MPL headers
ChrisMart21 Aug 13, 2024
a8237ba
Update Root Reducer, Sanitize Devtools
ChrisMart21 Aug 14, 2024
04ba6a5
Address Unserializable Values In State/Actions.
ChrisMart21 Aug 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/client/app/components/RouteComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { IntlProvider } from 'react-intl';
import { RouterProvider, createBrowserRouter } from 'react-router-dom';
import UploadCSVContainer from '../containers/csv/UploadCSVContainer';
import MapCalibrationContainer from '../containers/maps/MapCalibrationContainer';
import MapsDetailContainer from '../containers/maps/MapsDetailContainer';
import MapsDetailComponent from './maps/MapsDetailComponent';
import { useAppSelector } from '../redux/reduxHooks';
import LocaleTranslationData from '../translations/data';
import { UserRole } from '../types/items';
Expand Down Expand Up @@ -56,7 +56,7 @@ const router = createBrowserRouter([
children: [
{ path: 'admin', element: <AdminComponent /> },
{ path: 'calibration', element: <MapCalibrationContainer /> },
{ path: 'maps', element: <MapsDetailContainer /> },
{ path: 'maps', element: <MapsDetailComponent /> },
{ path: 'users/new', element: <CreateUserComponent /> },
{ path: 'units', element: <UnitsDetailComponent /> },
{ path: 'conversions', element: <ConversionsDetailComponent /> },
Expand Down
82 changes: 82 additions & 0 deletions src/client/app/components/maps/CreateMapModalComponent.tsx
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
Copy link
Member

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.

Copy link
Contributor

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.

* 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) {
Copy link
Member

Choose a reason for hiding this comment

The 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)?

Copy link
Contributor

Choose a reason for hiding this comment

The 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;
160 changes: 160 additions & 0 deletions src/client/app/components/maps/EditMapModalComponent.tsx
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();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note for future to move to newer way. Similar to another comment.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted for future work.

const [nameInput, setNameInput] = useState(map.name);
Copy link
Member

Choose a reason for hiding this comment

The 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 = () => {
Copy link
Member

Choose a reason for hiding this comment

The 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();
}
};

Copy link
Member

@huss huss Aug 1, 2024

Choose a reason for hiding this comment

The 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 = () => {
Copy link
Member

Choose a reason for hiding this comment

The 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;
5 changes: 3 additions & 2 deletions src/client/app/components/maps/MapCalibrationComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import * as React from 'react';
import MapCalibrationChartDisplayContainer from '../../containers/maps/MapCalibrationChartDisplayContainer';
import MapCalibrationInfoDisplayContainer from '../../containers/maps/MapCalibrationInfoDisplayContainer';
import MapCalibrationInitiateContainer from '../../containers/maps/MapCalibrationInitiateContainer';
import MapsDetailContainer from '../../containers/maps/MapsDetailContainer';
//import MapsDetailContainer from '../../containers/maps/MapsDetailContainer';
ChrisMart21 marked this conversation as resolved.
Show resolved Hide resolved
import { CalibrationModeTypes } from '../../types/redux/map';
import MapsDetailComponent from './MapsDetailComponent';

interface MapCalibrationProps {
mode: CalibrationModeTypes;
Expand Down Expand Up @@ -47,7 +48,7 @@ export default class MapCalibrationComponent extends React.Component<MapCalibrat
} else { // preview mode containers
return (
<div className='container-fluid'>
<MapsDetailContainer />
<MapsDetailComponent />
</div>
);
}
Expand Down
Loading