Skip to content

Commit

Permalink
wip proof of concept mapbox key flow
Browse files Browse the repository at this point in the history
user provides key value, value is saved to txt file in assets
  • Loading branch information
buckhalt committed Jan 9, 2025
1 parent bd4e44c commit e29e07e
Show file tree
Hide file tree
Showing 7 changed files with 211 additions and 55 deletions.
1 change: 1 addition & 0 deletions src/components/AssetBrowser/withAssetActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const connectActions = connect(
null,
{
deleteAsset: assetActions.deleteAsset,
importAsset: assetActions.importAsset,
openDialog: dialogActions.openDialog,
},
);
Expand Down
35 changes: 0 additions & 35 deletions src/components/Form/Fields/GeoAPIKey.js

This file was deleted.

146 changes: 146 additions & 0 deletions src/components/Form/Fields/Geospatial/CreateKeyWindow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import React from 'react';
import PropTypes from 'prop-types';
import { AnimatePresence, motion } from 'framer-motion';
import * as Fields from '@codaco/ui/lib/components/Fields';

import { createPortal } from 'react-dom';
import Button from '@codaco/ui/lib/components/Button';
import { Layout, Section } from '@components/EditorLayout';
import ControlBar from '@components/ControlBar';
import Screen from '@components/Screen/Screen';
import { screenVariants } from '@components/Screens/Screens';
import ValidatedField from '@components/Form/ValidatedField';
import { reduxForm } from 'redux-form';
import withAssetActions from '@components/AssetBrowser/withAssetActions';
import { compose } from 'recompose';
import fs from 'fs'; // Node.js file system module
import path from 'path'; // Node.js path module
import { remote } from 'electron'; // Electron's remote module (if needed for paths)

const CreateKeyWindow = ({
show,
close,
submitting,
handleSubmit,
importAsset,
}) => {
const handleCreateFile = (values) => {
// TODO: implement editing the file
const fileContents = values.mapboxAPIKey;

const tempFilePath = path.join(remote.app.getPath('temp'), 'architect', 'mapbox.txt');

fs.writeFile(tempFilePath, fileContents, (err) => {
if (err) {
console.error('Error writing the file:', err);

Check failure on line 35 in src/components/Form/Fields/Geospatial/CreateKeyWindow.js

View workflow job for this annotation

GitHub Actions / test

Unexpected console statement
return;
}
importAsset(tempFilePath);

close();
});
};

const cancelButton = (
<Button
color="platinum"
onClick={close} // TODO: implement with closing dialog
key="cancel"
>
Cancel
</Button>
);

const saveButton = (
<Button
key="save"
onClick={handleSubmit(handleCreateFile)}
iconPosition="right"
icon="arrow-right"
disabled={submitting}
>
Finished Editing
</Button>
);

if (!show) { return null; }

return createPortal(
<AnimatePresence>
{ show && (
<motion.div
variants={screenVariants}
initial="hidden"
animate="visible"
exit="hidden"
className="screens-container"
>
<Screen
header={(
<div className="stage-heading stage-heading--collapsed stage-heading--shadow">
<Layout>
<h2>Create Mapbox API Key</h2>
</Layout>
</div>
)}
footer={(
<ControlBar
buttons={[cancelButton, saveButton]}
/>
)}
>
<Layout>
<Section
title="API Key"
summary={(
<p>
This interface requires a Mapbox API Key to render maps. To get one, visit
{' '}
<a href="https://mapbox.com" target="_blank" rel="noopener noreferrer">mapbox.com</a>
{' '}
or read our documentation on the interface.
</p>
)}
>

<div data-name="Mapbox API Key" />
<ValidatedField
component={Fields.Text}
label="API Key"
type="text"
placeholder="Enter a Mapbox token..."
name="mapboxAPIKey"
validation={{ required: true }}
/>
</Section>
</Layout>
</Screen>
</motion.div>
)}
</AnimatePresence>,
document.body,
);
};

CreateKeyWindow.propTypes = {
show: PropTypes.bool,
type: PropTypes.string,
selected: PropTypes.string,
onSelect: PropTypes.func,
onCancel: PropTypes.func,
};

CreateKeyWindow.defaultProps = {
show: true,
type: null,
selected: null,
onSelect: () => {},
onCancel: () => {},
};

export default compose(
withAssetActions,
reduxForm({
form: 'createApiKeyForm',
}),
)(CreateKeyWindow);
58 changes: 58 additions & 0 deletions src/components/Form/Fields/Geospatial/GeoAPIKey.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React, { useEffect, useState } from 'react';
import { withState, compose } from 'recompose';
import { fieldPropTypes } from 'redux-form';
import Button from '@codaco/ui/lib/components/Button';
import withAssets from '@components/AssetBrowser/withAssets';
import KeyIcon from '@material-ui/icons/VpnKey';
import CreateKeyWindow from './CreateKeyWindow';

const withSelectAPIKey = withState('selectAPIKey', 'setSelectAPIKey', false);

const GeoAPIKey = (props) => {
const {
input,
assets,

} = props;
const existingAPIKeyFile = assets.find((asset) => asset.name === 'mapbox.txt');

const [showCreateKeyWindow, setShowCreateKeyWindow] = useState(false);

// initialize the data with the existing file if there's no input.value
useEffect(() => {
if (!input.value && existingAPIKeyFile) {
input.onChange(existingAPIKeyFile.id);
}
}, [input.value, existingAPIKeyFile]);

return (
<>
{existingAPIKeyFile && (
<p>
<KeyIcon />
Using existing Mapbox API Key
</p>
)}
<Button
onClick={() => setShowCreateKeyWindow(true)}
color="primary"
size="small"
>
{ !existingAPIKeyFile ? 'Create API Key' : 'Update API Key' }
</Button>
<CreateKeyWindow
show={showCreateKeyWindow}
close={() => setShowCreateKeyWindow(false)}
/>
</>
);
};

GeoAPIKey.propTypes = {
...fieldPropTypes,
};

export default compose(
withSelectAPIKey,
withAssets,
)(GeoAPIKey);
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { withState } from 'recompose';
import { fieldPropTypes } from 'redux-form';
import NetworkThumbnail from '@components/Thumbnail/Network'; // TODO: replace
import File from './File';
import File from '../File';

const withSelectGeoAsset = withState('selectGeoAsset', 'setSelectGeoAsset', false);

Expand Down
22 changes: 4 additions & 18 deletions src/components/sections/MapOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,10 @@ import { Section, Row } from '../EditorLayout';
import ValidatedField from '../Form/ValidatedField';

import ColorPicker from '../Form/Fields/ColorPicker';
import GeoDataSource from '../Form/Fields/GeoDataSource';
import GeoAPIKey from '../Form/Fields/GeoAPIKey';
import GeoDataSource from '../Form/Fields/Geospatial/GeoDataSource';
import GeoAPIKey from '../Form/Fields/Geospatial/GeoAPIKey';
import useVariablesFromExternalData from '../../hooks/useVariablesFromExternalData';

// config map options

/*
mapOptions: {
center: z.tuple([z.number(), z.number()]),
token: z.string(),
initialZoom: z.number().int(),
data: z.string(),
color: z.string(),
propToSelect: z.string(),
},
*/

const MapOptions = (props) => {
const { mapOptions } = props;

Expand All @@ -48,16 +35,15 @@ const MapOptions = (props) => {
<ValidatedField
name="mapOptions.mapboxKey"
component={GeoAPIKey}
label="MapBox API Key"
label="Mapbox API Key"
validation={{ required: true }}
placeholder="Enter your API key..."
/>
</Section>
<Section
title="Data source for map layers"
summary={(
<p>
This stage needs a GeoJSON source for map layers.
This interface requires a GeoJSON source for map layers.
These provide selectable areas for prompts. Select a GeoJSON
file to use.
</p>
Expand Down
2 changes: 1 addition & 1 deletion src/ducks/modules/protocol/assetManifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const importAsset = (filename) => ({
* @param {string} filename - Name of file
* @param {string} fileType - File MIME type
*/
const importAssetComplete = (filename, name, assetType) => ({
export const importAssetComplete = (filename, name, assetType) => ({
id: uuid(),
type: IMPORT_ASSET_COMPLETE,
name,
Expand Down

0 comments on commit e29e07e

Please sign in to comment.