diff --git a/index.html b/index.html
index 0f54feed..412bf111 100644
--- a/index.html
+++ b/index.html
@@ -3,12 +3,13 @@
-
-
- Moos Ecosystem
-
-
+
+
+ Utopia Map
+
+
+
diff --git a/package-lock.json b/package-lock.json
index 9d797f6b..9cf54888 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,7 +8,7 @@
"name": "utopia-game",
"version": "0.0.0",
"dependencies": {
- "@directus/sdk": "^12.0.1",
+ "@directus/sdk": "^13.0.2",
"@heroicons/react": "^2.1.1",
"@types/geojson": "^7946.0.10",
"axios": "^1.6.5",
@@ -17,11 +17,11 @@
"react-dom": "^18.2.0",
"react-rnd": "^10.4.1",
"react-router-dom": "^6.11.2",
- "utopia-ui": "^3.0.0-alpha.118"
+ "utopia-ui": "^3.0.0-alpha.126"
},
"devDependencies": {
- "@types/react": "^18.2.60",
- "@types/react-dom": "^18.0.11",
+ "@types/react": "^18.2.79",
+ "@types/react-dom": "^18.2.25",
"@typescript-eslint/eslint-plugin": "^5.57.1",
"@typescript-eslint/parser": "^5.57.1",
"@vitejs/plugin-react": "^4.0.0",
@@ -1722,8 +1722,9 @@
}
},
"node_modules/@directus/sdk": {
- "version": "12.0.1",
- "license": "MIT",
+ "version": "13.0.2",
+ "resolved": "https://registry.npmjs.org/@directus/sdk/-/sdk-13.0.2.tgz",
+ "integrity": "sha512-KECQM0w8xlgr5EklX+Jb9+dIzXyvJFjRfhiIAI7l/b0WEtVaCfvRMIrJXR3XsLeVW9u2nu+b/TffOyTMSLjm2w==",
"engines": {
"node": ">=18.0.0"
},
@@ -1967,20 +1968,20 @@
}
},
"node_modules/@tanstack/query-core": {
- "version": "5.28.9",
- "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.28.9.tgz",
- "integrity": "sha512-hNlfCiqZevr3GRVPXS3MhaGW5hjcxvCsIQ4q6ff7EPlvFwYZaS+0d9EIIgofnegDaU2BbCDlyURoYfRl5rmzow==",
+ "version": "5.32.0",
+ "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.32.0.tgz",
+ "integrity": "sha512-Z3flEgCat55DRXU5UMwYU1U+DgFZKA3iufyOKs+II7iRAo0uXkeU7PH5e6sOH1CGEag0IpKmZxlUFpCg6roSKw==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@tanstack/react-query": {
- "version": "5.28.9",
- "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.28.9.tgz",
- "integrity": "sha512-vwifBkGXsydsLxFOBMe3+f8kvtDoqDRDwUNjPHVDDt+FoBetCbOWAUHgZn4k+CVeZgLmy7bx6aKeDbe3e8koOQ==",
+ "version": "5.32.0",
+ "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.32.0.tgz",
+ "integrity": "sha512-+E3UudQtarnx9A6xhpgMZapyF+aJfNBGFMgI459FnduEZqT/9KhOWnMOneZahLRt52yzskSA0AuOyLkXHK0yBA==",
"dependencies": {
- "@tanstack/query-core": "5.28.9"
+ "@tanstack/query-core": "5.32.0"
},
"funding": {
"type": "github",
@@ -2055,19 +2056,19 @@
"license": "MIT"
},
"node_modules/@types/react": {
- "version": "18.2.60",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.60.tgz",
- "integrity": "sha512-dfiPj9+k20jJrLGOu9Nf6eqxm2EyJRrq2NvwOFsfbb7sFExZ9WELPs67UImHj3Ayxg8ruTtKtNnbjaF8olPq0A==",
+ "version": "18.2.79",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.79.tgz",
+ "integrity": "sha512-RwGAGXPl9kSXwdNTafkOEuFrTBD5SA2B3iEB96xi8+xu5ddUa/cpvyVCSNn+asgLCTHkb5ZxN8gbuibYJi4s1w==",
"dependencies": {
"@types/prop-types": "*",
- "@types/scheduler": "*",
"csstype": "^3.0.2"
}
},
"node_modules/@types/react-dom": {
- "version": "18.2.4",
+ "version": "18.2.25",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.25.tgz",
+ "integrity": "sha512-o/V48vf4MQh7juIKZU2QGDfli6p1+OOi5oXx36Hffpc9adsHeXjVp8rHuPkjd8VT8sOJ2Zp05HR7CdpGTIUFUA==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@types/react": "*"
}
@@ -2080,10 +2081,6 @@
"@types/node": "*"
}
},
- "node_modules/@types/scheduler": {
- "version": "0.16.3",
- "license": "MIT"
- },
"node_modules/@types/semver": {
"version": "7.5.0",
"dev": true,
@@ -3706,6 +3703,19 @@
"version": "1.0.0",
"license": "ISC"
},
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
"node_modules/function-bind": {
"version": "1.1.1",
"license": "MIT"
@@ -4921,9 +4931,9 @@
}
},
"node_modules/micromark-core-commonmark": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.0.tgz",
- "integrity": "sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.1.tgz",
+ "integrity": "sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==",
"funding": [
{
"type": "GitHub Sponsors",
@@ -5257,9 +5267,9 @@
}
},
"node_modules/micromark-util-subtokenize": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.0.tgz",
- "integrity": "sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.1.tgz",
+ "integrity": "sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==",
"funding": [
{
"type": "GitHub Sponsors",
@@ -5755,9 +5765,9 @@
}
},
"node_modules/property-information": {
- "version": "6.4.1",
- "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.4.1.tgz",
- "integrity": "sha512-OHYtXfu5aI2sS2LWFSN5rgJjrQ4pCy8i1jubJLe2QvMF8JJ++HXTUIVWFLfXJoaOfvYYjk2SN8J2wFUWIGXT4w==",
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz",
+ "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
@@ -6481,9 +6491,9 @@
}
},
"node_modules/stringify-entities": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.3.tgz",
- "integrity": "sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==",
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz",
+ "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==",
"dependencies": {
"character-entities-html4": "^2.0.0",
"character-entities-legacy": "^3.0.0"
@@ -7005,9 +7015,10 @@
}
},
"node_modules/typescript": {
- "version": "5.0.4",
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz",
+ "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==",
"dev": true,
- "license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -7230,9 +7241,9 @@
"license": "MIT"
},
"node_modules/utopia-ui": {
- "version": "3.0.0-alpha.118",
- "resolved": "https://registry.npmjs.org/utopia-ui/-/utopia-ui-3.0.0-alpha.118.tgz",
- "integrity": "sha512-LKMSRCPr190sK3oFdt+AsL2jcLK3iOG4DZyaA/5LcpwjZypeMjSpakLrPrISdpECJExOm3HvrtT19ByI3BXBdQ==",
+ "version": "3.0.0-alpha.126",
+ "resolved": "https://registry.npmjs.org/utopia-ui/-/utopia-ui-3.0.0-alpha.126.tgz",
+ "integrity": "sha512-RM4N4NNwLp+5fUwcboD/8Y7V/ocu9X3qEH/F5Isz45M7q3qymeshMn/ytQEvFdPKJq5aWBplvbnCYzfSUELqHw==",
"dependencies": {
"@heroicons/react": "^2.0.17",
"@tanstack/react-query": "^5.17.8",
@@ -7287,9 +7298,10 @@
}
},
"node_modules/vite": {
- "version": "4.5.2",
+ "version": "4.5.3",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.3.tgz",
+ "integrity": "sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg==",
"dev": true,
- "license": "MIT",
"dependencies": {
"esbuild": "^0.18.10",
"postcss": "^8.4.27",
diff --git a/package.json b/package.json
index 1c2653ba..d90c5519 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
- "@directus/sdk": "^12.0.1",
+ "@directus/sdk": "^13.0.2",
"@heroicons/react": "^2.1.1",
"@types/geojson": "^7946.0.10",
"axios": "^1.6.5",
@@ -19,11 +19,11 @@
"react-dom": "^18.2.0",
"react-rnd": "^10.4.1",
"react-router-dom": "^6.11.2",
- "utopia-ui": "^3.0.0-alpha.118"
+ "utopia-ui": "^3.0.0-alpha.126"
},
"devDependencies": {
- "@types/react": "^18.2.60",
- "@types/react-dom": "^18.0.11",
+ "@types/react": "^18.2.79",
+ "@types/react-dom": "^18.2.25",
"@typescript-eslint/eslint-plugin": "^5.57.1",
"@typescript-eslint/parser": "^5.57.1",
"@vitejs/plugin-react": "^4.0.0",
diff --git a/src/App.tsx b/src/App.tsx
index ac360b2c..a933384b 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -12,6 +12,8 @@ import { useEffect, useState } from 'react'
import { itemsApi } from './api/itemsApi'
import { permissionsApi } from './api/permissionsApi'
import { Tag } from 'utopia-ui/dist/types'
+import { mapApi } from './api/mapApi'
+import { layersApi } from './api/layersApi'
function App() {
@@ -19,31 +21,78 @@ function App() {
const [permissionsApiInstance, setPermissionsApiInstance] = useState();
const [tagsApi, setTagsApi] = useState>();
+ const [mapApiInstance, setMapApiInstance] = useState();
+ const [layersApiInstance, setLayersApiInstance] = useState();
+ const [map, setMap] = useState();
+ const [layers, setLayers] = useState();
+ const [layerPageRoutes, setLayerPageRoutes] = useState();
useEffect(() => {
-
setPermissionsApiInstance(new permissionsApi());
setTagsApi(new itemsApi('tags', undefined, "36fc9ba7-1a6b-4fc2-9db1-39d67aaf6918"));
+ setMapApiInstance(new mapApi(window.location.origin));
}, [])
+ useEffect(() => {
+ mapApiInstance && getMap();
+ }, [mapApiInstance])
- return (
+
+ const getMap = async () => {
+ const map = await mapApiInstance?.getItems();
+ map && setMap(map);
+ map && setLayersApiInstance(new layersApi(map.id));
+ }
+
+ useEffect(() => {
+ layersApiInstance && getLayers();
+ }, [layersApiInstance])
+
+
+ const getLayers = async () => {
+ const layers = await layersApiInstance?.getItems();
+ layers && setLayers(layers);
+ setLayerPageRoutes(layers?.map((l: any) => ({
+ path: '/' + l.name, // url
+ icon:
,
+ name: l.name, // name that appear in Sidebar
+ })));
+ }
+
+ useEffect(() => {
+if(map && map.name){
+ document.title = map?.name && map.name;
+ let link = document.querySelector("link[rel~='icon']") as HTMLLinkElement
+ if (!link) {
+ link = document.createElement('link');
+ link.rel = 'icon';
+ document.getElementsByTagName('head')[0].appendChild(link);
+ }
+ link.href = map?.logo && "https://api.utopia-lab.org/assets/"+map.logo; // Specify the path to your favicon
+
+}
+
+ }, [map])
+
+
+
+ if (map && layers) return (
-
+
-
+
- }>
+ }>
} />
} />
} />
@@ -55,18 +104,26 @@ function App() {
} />
} />
} />
- } />
- } />
- } />
-
+ {
+ layers.map((l: any) =>
+ } />
+ )
+ }
-
)
+
+ else return (
+
+
+
This map does not exist
+
+
+ )
}
export default App
diff --git a/src/api/layersApi.ts b/src/api/layersApi.ts
new file mode 100644
index 00000000..70f9c980
--- /dev/null
+++ b/src/api/layersApi.ts
@@ -0,0 +1,25 @@
+import { readItems } from '@directus/sdk';
+import { directusClient } from './directus';
+
+
+
+export class layersApi {
+ mapId : string
+
+ constructor(mapId: string) {
+ this.mapId = mapId;
+ }
+
+ async getItems() {
+ try {
+ const layers = await directusClient.request(readItems("layers" as any, { fields: ['*', {itemType : ['*']}], filter: { "maps": { "maps_id": { "id": { "_eq": this.mapId } } } }, limit: 500 }));
+ return layers;
+ } catch (error: any) {
+ console.log(error);
+ if (error.errors[0]?.message)
+ throw error.errors[0].message;
+ else throw error;
+ }
+ }
+}
+
diff --git a/src/api/mapApi.ts b/src/api/mapApi.ts
new file mode 100644
index 00000000..33f855b3
--- /dev/null
+++ b/src/api/mapApi.ts
@@ -0,0 +1,25 @@
+import { readItems } from '@directus/sdk';
+import { directusClient } from './directus';
+
+
+
+export class mapApi {
+ url : string
+
+ constructor(url: string) {
+ this.url = url;
+ }
+
+ async getItems() {
+ try {
+ const map = await directusClient.request(readItems("maps" as any, { fields: ['*'], filter: { "url": { "_eq": this.url } } as any, limit: 500 }));
+ return map[0];
+ } catch (error: any) {
+ console.log(error);
+ if (error.errors[0]?.message)
+ throw error.errors[0].message;
+ else throw error;
+ }
+ }
+}
+
diff --git a/src/pages/MapContainer.tsx b/src/pages/MapContainer.tsx
index 8ce022a0..0c715eae 100644
--- a/src/pages/MapContainer.tsx
+++ b/src/pages/MapContainer.tsx
@@ -1,101 +1,73 @@
-import { UtopiaMap, Layer, ItemForm, ItemView, PopupTextAreaInput, PopupTextInput, PopupStartEndInput, TextView, StartEndView, PopupButton } from 'utopia-ui'
+import { UtopiaMap, Layer, ItemView, PopupButton, StartEndView, TextView, ItemForm, PopupStartEndInput, PopupTextAreaInput, PopupTextInput } from 'utopia-ui'
import { itemsApi } from '../api/itemsApi';
-import { Place, Event } from '../api/directus';
+import { Place } from '../api/directus';
import { useEffect, useState } from 'react';
-import { CalendarDaysIcon, MapPinIcon, UserIcon } from '@heroicons/react/20/solid'
+import { LayerProps } from 'utopia-ui/dist/types';
-function MapContainer() {
+type layerApi = {
+ id: string;
+ api: itemsApi
+}
- const [placesApi, setPlacesApi] = useState>();
- const [eventsApi, setEventsApi] = useState>();
- const [updatesApiInstance, setUpdatesApiInstance] = useState>();
+function MapContainer({ layers, map }: { layers: Array, map: any }) {
+ const [apis, setApis] = useState>([]);
useEffect(() => {
- setPlacesApi(new itemsApi('items', undefined, undefined, {"type":{"_eq":"project"}}, {type: "project", autogenerated: "false"}));
- setEventsApi(new itemsApi('items', undefined, undefined, {"type":{"_eq":"event"}}, {type: "event"}));
- setUpdatesApiInstance(new itemsApi('items', undefined, undefined, {"type":{"_eq":"user"}}, {type: "user"}));
- }, []);
+ layers.map(layer => {
+ apis && setApis(current => [...current, { id: layer.id!, api: new itemsApi('items', layer.id) }])
+ })
+ }, [layers])
+
+ useEffect(() => {
+ }, [apis])
- const icon = CalendarDaysIcon;
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Press Save to place your Profile to the Map
-
-
-
+
+ {layers && apis &&
+ layers.map(layer =>
+ api.id === layer.id)?.api}>
+
+ {layer.itemType.show_start_end &&
+
+ }
+ {layer.itemType.show_profile_button &&
+
+ }
+ {layer.itemType.show_text &&
+
+ }
+
+
+ {layer.itemType.show_name_input && }
+ {layer.itemType.show_start_end_input && }
+ {layer.itemType.show_text_input &&}
+ {layer.itemType.custom_text &&
+
Press Save to place your Profile to the Map
+
}
+
+ )
+ }
)
}
diff --git a/src/routes/sidebar.tsx b/src/routes/sidebar.tsx
index beb115a9..2c4535ec 100644
--- a/src/routes/sidebar.tsx
+++ b/src/routes/sidebar.tsx
@@ -1,9 +1,6 @@
-import { RectangleGroupIcon, CalendarDaysIcon, UserGroupIcon } from '@heroicons/react/24/outline'
import { MapIcon } from '@heroicons/react/24/outline'
-//const iconClasses = `h-6 w-6`
-//const submenuIconClasses = `h-5 w-5`
export const routes = [
@@ -11,21 +8,6 @@ export const routes = [
path: '/',
icon: ,
name: 'Map',
- },
- {
- path: '/items', // url
- icon: , // icon component
- name: 'Projects', // name that appear in Sidebar
- },
- {
- path: '/calendar', // url
- icon: , // icon component
- name: 'Calendar', // name that appear in Sidebar
- },
- {
- path: '/community', // url
- icon: , // icon component
- name: 'Community', // name that appear in Sidebar
}/**
{
path: '/people', // url