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