Skip to content

Commit

Permalink
Example: dataset operations (#63)
Browse files Browse the repository at this point in the history
  • Loading branch information
distefanodevinj authored Sep 7, 2023
1 parent 5eed86e commit 4e09e00
Show file tree
Hide file tree
Showing 15 changed files with 3,411 additions and 0 deletions.
16 changes: 16 additions & 0 deletions map-sdk/data-example/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/** @type import('eslint').Linter.Config */
module.exports = {
root: true,
env: {browser: true, es2020: true},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended'
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': ['warn', {allowConstantExport: true}]
}
};
24 changes: 24 additions & 0 deletions map-sdk/data-example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*
.yarn
1 change: 1 addition & 0 deletions map-sdk/data-example/.yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nodeLinker: node-modules
33 changes: 33 additions & 0 deletions map-sdk/data-example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Map SDK example template

This is an example template for Foursquare's [Map SDK](https://location.foursquare.com/developer/docs/studio-map-sdk-introduction) that allows you to programmatically render [Foursquare Studio](https://studio.foursquare.com/) maps within your website and with your own data.

The project was bootstrapped with [Vite](https://vitejs.dev/guide/).

## Available Scripts

In the project directory, you can run:

### `yarn dev`

Runs the app in the development mode.\
By default, the app is available at [http://localhost:5173](http://localhost:5173/) in your browser.

The page will reload when you make edits.\
You will also see any lint errors in the console.

### `yarn build`

Builds and bundles the app for production into the `dist` folder.

### `yarn preview`

Runs a server to locally preview the production build.

If you don't use `yarn dev`, you likely would want to use `yarn build` and `yarn preview` together.

## Learn More

You can learn more about [setting up a React app with Vite](https://react.dev/learn/add-react-to-an-existing-project) and on the official [Vite webiste](https://vitejs.dev/guide/).

To learn React, check out the [React documentation](https://react.dev/).
15 changes: 15 additions & 0 deletions map-sdk/data-example/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8" />
<link rel="icon" href="/fsq-favicon.png" />
<title>Data Example</title>
</head>

<body>
<script type="module" src="/src/index.tsx"></script>
<div id="root"></div>
</body>

</html>
30 changes: 30 additions & 0 deletions map-sdk/data-example/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "data-example",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"dependencies": {
"@unfolded/map-sdk": "^1.9.1",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/eslint": "^8.44.2",
"@types/react": "^18.2.18",
"@types/react-dom": "^18.2.7",
"@typescript-eslint/eslint-plugin": "^6.2.1",
"@typescript-eslint/parser": "^6.2.1",
"@vitejs/plugin-react": "^4.0.4",
"eslint": "^8.46.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"typescript": "^5.2.2",
"vite": "^4.4.9"
}
}
Binary file added map-sdk/data-example/public/fsq-favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
118 changes: 118 additions & 0 deletions map-sdk/data-example/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import {FC, useEffect, useMemo, useRef, useState} from 'react';
import {createMap, Dataset, MapApi} from '@unfolded/map-sdk';
import {SampleDataItem, fetchSampleData} from './sample-data';

const getFirstDataset = (map: MapApi): Dataset => {
const dataset = map.getDatasets()[0];
if (!dataset) {
throw new Error('No dataset.');
} else {
return dataset;
}
};

export const App: FC = () => {
const containerRef = useRef<HTMLDivElement>(null);
const [map, setMap] = useState<MapApi | null>(null);
const [dispalyedDataset, setDisplayedDataset] = useState<unknown | null>(null);
const [sampleData, setSampleData] = useState<[SampleDataItem, SampleDataItem] | null>(null);

useEffect(() => {
const loadData = async () => {
setSampleData(await fetchSampleData());
};

const initMap = async () => {
const map = await createMap({
container: containerRef.current!
});

setMap(map);
};

initMap();
loadData();
}, []);

const handlers = useMemo(() => {
if (!sampleData) {
console.log('Data not yet loaded.');
return null;
}

if (!map) {
console.log('Map not yet initialized.');
return null;
}

return {
addDataset: () => {
if (map.getDatasets().length > 0) {
console.log('Dataset already added to the map. (Example is limited to one dataset).');
return;
}

map.addDataset(sampleData[0]);
},
updateDataset: () => {
const dataset = getFirstDataset(map);
const updatedLabel = 'Updated Dataset';
const updatedColor = [
Math.floor(Math.random() * 256),
Math.floor(Math.random() * 256),
Math.floor(Math.random() * 256)
] as [number, number, number];

map.updateDataset(dataset.id, {
label: updatedLabel,
color: updatedColor
});
},
replaceDataset: () => {
map.replaceDataset(sampleData[0].id, {
id: sampleData[1].id,
label: sampleData[1].label,
data: sampleData[1].data
});

// round robin swap
setSampleData([sampleData[1], sampleData[0]]);
},
displayDataset: () => {
const dataset = getFirstDataset(map);
const datasetData = map.getDatasetWithData(dataset.id);
setDisplayedDataset(datasetData);
},
removeDataset: () => {
const dataset = getFirstDataset(map);
map.removeDataset(dataset.id);
}
};
}, [map, sampleData]);

return (
<>
<div id="map-container" ref={containerRef}></div>
{!!handlers && (
<div className="controls">
{/* Buttons for various dataset operations */}
<button onClick={handlers.addDataset}>Add Dataset</button>
<button onClick={handlers.updateDataset}>Update Dataset</button>
<button onClick={handlers.replaceDataset}>Replace Dataset</button>
<button onClick={handlers.displayDataset}>Get Dataset</button>
<button onClick={handlers.removeDataset}>Remove Dataset</button>
</div>
)}

{/* JSON popup */}
{!!dispalyedDataset && (
<div className="json-popup">
<div className="json-popup-content">
<button onClick={() => setDisplayedDataset(null)}>Close</button>
<pre>{JSON.stringify(dispalyedDataset, null, 2)}</pre>
</div>
</div>
)}
</>
);
};
63 changes: 63 additions & 0 deletions map-sdk/data-example/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
body {
margin: 0;
padding: 0;
}

#map-container {
width: 100vw;
height: 100vh;
overflow: hidden;
}

.controls {
position: fixed;
right: 0;
bottom: 0;
margin: 20px;
display: flex;
gap: 5px;
flex-direction: column;
}

/* Styles for the JSON popup container */
.json-popup {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7); /* Semi-transparent black background */
display: flex;
justify-content: center;
align-items: center;
overflow: auto; /* Enable scrolling for the popup container */
}

.json-popup-content {
background-color: white;
padding: 20px;
border-radius: 5px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
width: 66.67%; /* Two-thirds of the viewport width */
height: 66.67%; /* Two-thirds of the viewport height */
overflow: auto; /* Enable scrolling for the popup content */
position: relative; /* Required for positioning the close button */
}

.json-popup-content button {
position: sticky;
top: 10px;
right: 10px;
background: none;
border: none;
cursor: pointer;
font-size: 16px;
color: red;
z-index: 1;
}

.json-popup-content pre {
white-space: pre-wrap;
font-family: monospace;
font-size: 14px;
}
5 changes: 5 additions & 0 deletions map-sdk/data-example/src/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import {createRoot} from 'react-dom/client';
import './index.css';
import {App} from './App';

createRoot(document.getElementById('root')!).render(<App />);
28 changes: 28 additions & 0 deletions map-sdk/data-example/src/sample-data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const BASE_URL = `https://4sq-studio-public.s3.us-west-2.amazonaws.com/sdk/examples/sample-data`;

export type SampleDataItem = {
id: string;
label: string;
data: object;
};

export const fetchSampleData = async (): Promise<[SampleDataItem, SampleDataItem]> => {
const responses = await Promise.all([
fetch(`${BASE_URL}/california-cities.json`),
fetch(`${BASE_URL}/arizona-cities.json`)
]);

const data = await Promise.all(responses.map(r => r.json()));
return [
{
id: 'california-cities',
label: 'California cities',
data: data[0]
},
{
id: 'arizona-cities',
label: 'Arizona cities',
data: data[1]
}
];
};
25 changes: 25 additions & 0 deletions map-sdk/data-example/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,

/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",

/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}
10 changes: 10 additions & 0 deletions map-sdk/data-example/tsconfig.node.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}
7 changes: 7 additions & 0 deletions map-sdk/data-example/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {defineConfig} from 'vite';
import react from '@vitejs/plugin-react';

// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()]
});
Loading

0 comments on commit 4e09e00

Please sign in to comment.