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

layer menu #2934

Merged
merged 3 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions appv2/src/UI/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { LayerPickerBasic } from './Map/LayerPickerBasic';
import { NewRecord } from './Map/Buttons/NewRecord';
import NewRecordDialog from './Map/Buttons/NewRecordDialog';
import AccessRequestPage from './Overlay/AccessRequest/AccessRequestPage';
import CustomizeLayerMenu from './Map/Buttons/CustomizeLayerDialog';

// URL listener so that the auth saga can redirect to the correct page
const URL_LISTENER = (props) => {
Expand Down Expand Up @@ -200,6 +201,7 @@ const App: React.FC = () => {
</Overlay>
<Footer />
<NewRecordDialog/>
<CustomizeLayerMenu/>
</div>
);
};
Expand Down
194 changes: 194 additions & 0 deletions appv2/src/UI/Map/Buttons/CustomizeLayerDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
import {
Box,
Button,
Dialog,
DialogActions,
DialogTitle,
FormControl,
InputLabel,
MenuItem,
Select,
TextField,
Theme
} from '@mui/material';
import makeStyles from '@mui/styles/makeStyles';
import { set } from 'lodash';
import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useHistory } from 'react-router-dom';
import { TOGGLE_CUSTOMIZE_LAYERS } from 'state/actions';
import KMLShapesUpload from './KMLShapesUpload';

const useStyles = makeStyles((theme: Theme) => ({
formContainer: {
display: 'flex',
flexDirection: 'column',
justifyContent: 'start',
alignItems: 'center',
gap: 10,
paddingBlock: 10,
paddingInline: 8
},
select: {
minWidth: 200,
maxWidth: 400,
width: 'auto'
},
syncSuccessful: {
color: 'green'
},
dialogActionsBox: {
display: 'flex',
justifyContent: 'space-between'
}
}));

const CustomizeLayerMenu = (props) => {
const dispatch = useDispatch();

const classes = useStyles();
const history = useHistory();

const accessRoles = useSelector((state: any) => state.Auth.accessRoles);
const dialogueOpen = useSelector((state: any) => state.Map.customizeLayersToggle);

//menu options
const newLayerTypeOptions = ['Draw', 'Upload KML/KMZ', 'WMS Link', 'WFS Link'];
const [optionVal, setOptionVal] = useState('Draw');
const [subMenuType, setSubMenuType] = useState('Init');
const [newLayerName, setNewLayerName] = useState('');
const [layerToDelete, setLayerToDelete] = useState(null);


// two of each type
const customLayers = [{ id: 1, type: 'Drawn', label: 'banana', data: '' }, {id: 2, type: 'Drawn', label: 'apple', data: ''}, {id: 3, type: 'WMS', label: 'orange', data: ''}, {id: 4, type: 'WMS', label: 'grape', data: ''}, {id: 5, type: 'WFS', label: 'pear', data: ''}, {id: 6, type: 'WFS', label: 'peach', data: ''}];

const cleanup = () => {
setSubMenuType('Init');
setOptionVal('Draw');
setLayerToDelete(null);
setNewLayerName('');
};

const onKMLDone = () => {
cleanup();
dispatch({ type: TOGGLE_CUSTOMIZE_LAYERS });
};

return (
<Dialog open={dialogueOpen}>
<DialogTitle>Add or remove a custom layer</DialogTitle>

<Box className={classes.formContainer}>
{
{
New: (
<FormControl>
<InputLabel>New Layer type</InputLabel>
<Select
className={classes.select}
value={optionVal}
onChange={(e) => setOptionVal(e.target.value)}
label="Choose new Layer type">
{newLayerTypeOptions.map((option) => (
<MenuItem disabled={['WMS Link', 'WFS Link'].includes(option)} key={Math.random()} value={option}>
{option}
</MenuItem>
))}
</Select>
<TextField
className={classes.select}
value={newLayerName}
onChange={(e) => setNewLayerName(e.target.value)}
label="Name your new layer"></TextField>
</FormControl>
),
Remove: (
<FormControl>
<InputLabel>Remove Layer</InputLabel>
<Select
className={classes.select}
value={optionVal}
onChange={(e) => setLayerToDelete(e.target.value)}
label="Choose Layer to remove">
{customLayers.map((option) => (
<MenuItem key={Math.random()} value={option.id}>
{option.label + ' - ' + option.type}
</MenuItem>
))}
</Select>
</FormControl>
),
Upload: <KMLShapesUpload title={newLayerName} open={subMenuType === 'Upload'} whenDone={onKMLDone} />,
Init: <></>
}[subMenuType]
}
</Box>

<DialogActions className={classes.dialogActionsBox}>
{
{
Init: (
<>
<Button
onClick={() => {
setSubMenuType('New');
}}>
Add new
</Button>
<Button
onClick={() => {
setSubMenuType('Remove');
}}>
Remove existing
</Button>
</>
),
New: (
<>
<Button
onClick={() => {
if (optionVal === 'Upload KML/KMZ') {
setSubMenuType('Upload');
} else {
cleanup();
}
}}>
Create
</Button>
<Button
onClick={() => {
cleanup();
}}>
Back
</Button>
</>
),
Remove: (
<>
<Button disabled={layerToDelete === null} onClick={() => {}}>
Remove
</Button>
<Button
onClick={() => {
cleanup();
}}>
Back
</Button>
</>
)
}[subMenuType]
}
<Button
onClick={() => {
dispatch({ type: TOGGLE_CUSTOMIZE_LAYERS });
cleanup();
}}>
Exit
</Button>
</DialogActions>
</Dialog>
);
};

export default CustomizeLayerMenu;
131 changes: 131 additions & 0 deletions appv2/src/UI/Map/Buttons/KMLShapesUpload.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import React, { useState, useContext } from 'react';
import { Box, Button, Theme, Typography } from '@mui/material';
import { DropzoneDialog } from 'mui-file-dropzone';
import makeStyles from '@mui/styles/makeStyles';

export interface IShapeUploadRequest {
data: string;
type: 'kml' | 'kmz';
user_id: string;
title: string;
}

const useStyles = makeStyles((theme: Theme) => ({
itemsContainer: { display: 'flex', justifyContent: 'start', alignItems: 'center', width: '100%', flexWrap: 'wrap' },
buttonsContainer: { display: 'flex', justifyContent: 'stretch' },
button: { flexGrow: 1, marginLeft: 10, marginRight: 10 },
componentContainer: { maxWidth: '500px', padding: 7 },
messageContainer: {
padding: 7,
width: '100%'
}
}));

// var extension = input?.name?.split('.').pop();
export const KMLShapesUpload: React.FC<any> = (props) => {
const classes = useStyles();
const [uploadRequests, setUploadRequests] = useState([]);
const [dialogOpen, setDialogOpen] = React.useState(false);
//const api = useInvasivesApi();
const [resultMessage, setResultMessage] = useState('');
const [uploadClicked, setUploadClicked] = useState(false);


const doUpload = async () => {
let response;
try {
for (let i = 0; i < uploadRequests.length; i++) {
console.log();
//response = await api.postAdminUploadShape(uploadRequests[i]);
console.log(response);
if (response.code !== 201) {
throw new Error(response.message);
}
setUploadRequests((prev) => {
if (prev.length < 2) {
return [];
} else {
return [...prev].splice(i, 1);
}
});
}
setResultMessage('Files uploaded successfully');
setUploadClicked(false);
setTimeout(() => {
setResultMessage('');
if (props?.callback) props.callback();
}, 2000);
} catch (err) {
setUploadRequests([]);
setResultMessage('There was an error: ' + err);
setUploadClicked(false);
setTimeout(() => {
setResultMessage('');
}, 2000);
}
Promise.resolve();
};

const acceptFiles = (files: File[]) => {
setUploadRequests([]);
if (files.length < 1) {
return;
}

files.forEach((file) => {
let status: string;
const defaultTitle = file.name.split('.')[0];

let fileType: string;
fileType = file.name.split('.').pop();

const reader = new FileReader();

reader.onabort = () => (status = 'file reading was aborted');
reader.onerror = () => (status = 'file reading has failed');
reader.onload = () => {
const encodedString = btoa(reader.result as string);

setUploadRequests((prev) => {
const newRequest = [...prev];
newRequest.push({
type: fileType,
data: encodedString,
// user_id: extendedInfo.user_id,
title: defaultTitle,
status: status
});
return newRequest;
});
};

reader.readAsBinaryString(file);
});
};

return (
<Box className={classes.componentContainer}>
<DropzoneDialog
acceptedFiles={['.kml,.kmz']}
filesLimit={1}
cancelButtonText={'cancel'}
submitButtonText={'Upload to InvasivesBC'}
open={props.open}
onSave={(files: any) => {
acceptFiles(files);
doUpload().then(() => {
props.whenDone();
console.log('done')
});
}}
showPreviews={true}
previewText={'File will be uploaded to InvasivesBC as ' + props.title}
maxFileSize={10485760}
/>

{resultMessage && <Box className={classes.messageContainer}>{resultMessage}</Box>}
</Box>
);
};

export default KMLShapesUpload;
2 changes: 1 addition & 1 deletion appv2/src/UI/Map/Buttons/NewRecordDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ const NewRecordDialog = (props: INewRecordDialog) => {
<DialogActions className={classes.dialogActionsBox}>
<Button
onClick={() => {
// props.handleDialogClose();
dispatch({ type: CLOSE_NEW_RECORD_MENU });
}}>
Cancel
</Button>
Expand Down
6 changes: 4 additions & 2 deletions appv2/src/UI/Map/LayerPickerBasic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ import { DataBCLayer, LayerMode } from './DataBCRenderLayer';
import 'leaflet/dist/leaflet.css';
import { selectMap } from 'state/reducers/map';
import LayersIcon from '@mui/icons-material/Layers';
import { useSelector } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import { Button } from '@mui/material';
import Control from './CustomMapControl';
import SettingsIcon from '@mui/icons-material/Settings';
import { TOGGLE_CUSTOMIZE_LAYERS } from 'state/actions';

export const LayerPickerBasic = (props) => {
const simplePickerLayers = useSelector((state: any) => state.Map.simplePickerLayers);
Expand All @@ -28,6 +29,7 @@ export const LayerPickerBasic = (props) => {
[51.49, -0.08],
[51.5, -0.06]
];
const dispatch = useDispatch();

const layers = {
'Regional Districts': { layerCode: 'WHSE_LEGAL_ADMIN_BOUNDARIES.ABMS_REGIONAL_DISTRICTS_SP' }
Expand Down Expand Up @@ -243,7 +245,7 @@ export const LayerPickerBasic = (props) => {
sx={{ maxWidth: '15px' }}
variant="contained"
onClick={() => {
console.log('clicked');
dispatch({type: TOGGLE_CUSTOMIZE_LAYERS })
}}>
<LayersIcon sx={{ width: '15px' }} />
<SettingsIcon sx={{ width: '15px' }} />
Expand Down
1 change: 1 addition & 0 deletions appv2/src/state/actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export const ACTIVITY_SAVE_SUCCESS = 'ACTIVITY_SAVE_SUCCESS';
export const ACTIVITY_TOGGLE_NOTIFICATION_REQUEST = "ACTIVITY_TOGGLE_NOTIFICATION_REQUEST";
export const ACTIVITY_TOGGLE_NOTIFICATION_SUCCESS = "ACTIVITY_TOGGLE_NOTIFICATION_SUCCESS";

export const TOGGLE_CUSTOMIZE_LAYERS = 'TOGGLE_CUSTOMIZE_LAYERS'
export const ACTIVITY_PASTE_REQUEST = 'ACTIVITY_PASTE_REQUEST';
export const ACTIVITY_PASTE_SUCCESS = 'ACTIVITY_PASTE_SUCCESS';
export const ACTIVITY_PASTE_FAILURE = 'ACTIVITY_PASTE_FAILURE';
Expand Down
Loading
Loading