Merge branch 'main' into type-auth

This commit is contained in:
Ulf Gebhardt 2025-02-19 15:59:46 +01:00 committed by GitHub
commit c5a9d211c7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
56 changed files with 6278 additions and 2515 deletions

View File

@ -32,7 +32,6 @@ jobs:
run: |
npm install
npm run build
npm link
working-directory: ./
build-examples:
@ -42,20 +41,17 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
app: [examples/1-basic-map, examples/2-static-layers] # Aktualisierte Pfade der Beispiel-Apps
app: [examples/1-basic-map, examples/2-static-layers, examples/3-tags ]
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Set Up Node.js
uses: actions/setup-node@v3
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.1.7
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.0.3
with:
node-version: 18
node-version-file: './.tool-versions'
- name: Link Utopia-UI in Example App
run: |
npm install
npm run build
cd ${{ matrix.app }}
npm install
npm link utopia-ui
npm run build

View File

@ -60,6 +60,20 @@ jobs:
run: npm install && npm run lint
working-directory: ./examples/2-static-layers
lint-example-3-tags:
if: needs.files-changed.outputs.lint == 'true'
name: Lint Example 3 - Tags
needs: files-changed
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.1.7
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.0.3
with:
node-version-file: './.tool-versions'
- name: Lint
run: npm install && npm run lint
working-directory: ./examples/3-tags
# unit:
# if: needs.files-changed.outputs.frontend == 'true'
# name: Unit - Frontend

View File

@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
<title>Utopia-UI Example 1</title>
</head>
<body>
<div id="root"></div>

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
{
"name": "tutorial-1-basic-map",
"name": "1-basic-map",
"private": true,
"version": "0.0.0",
"type": "module",
@ -12,7 +12,7 @@
"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1",
"utopia-ui": "^3.0.35"
"utopia-ui": "../../"
},
"devDependencies": {
"@eslint/js": "^9.17.0",

View File

@ -1,62 +1,81 @@
# Example 2: Static Layers
[Example 1](/1-basic-map) shows us how we create a basic map app with [utopia-ui](https://github.com/utopia-os/utopia-ui). Now we add some static layer.
In [Example 1](/1-basic-map), we learned how to create a basic map app using [utopia-ui](https://github.com/utopia-os/utopia-ui). Now, we'll add **static layers** to our map.
First we put some sample data in a new file called `src/sample-data.ts`
### Adding Sample Data
First, we create a new file called `src/sample-data.ts` and define some sample data:
```javascript
export const places = [{
export const places = [
{
"id": 51,
"name": "Stadtgemüse",
"text": "Stadtgemüse Fulda ist eine Gemüsegärtnerei in Maberzell, die es sich zur Aufgabe gemacht hat, die Stadt und seine Bewohner:innen mit regionalem, frischem und natürlich angebautem Gemüse mittels Gemüsekisten zu versorgen. Es gibt also jede Woche, von Frühjahr bis Herbst, angepasst an die Saison eine Kiste mit schmackhaftem und frischem Gemüse für euch, welche ihr direkt vor Ort abholen könnt. \r\n\r\nhttps://stadtgemuese-fulda.de",
"position": { "type": "Point", "coordinates": [9.632435, 50.560342] },
"text": "Stadtgemüse Fulda ist eine Gemüsegärtnerei in Maberzell, die es sich zur Aufgabe gemacht hat, die Stadt und seine Bewohner:innen mit regionalem, frischem und natürlich angebautem Gemüse mittels Gemüsekisten zu versorgen. Es gibt also jede Woche, von Frühjahr bis Herbst, angepasst an die Saison eine Kiste mit schmackhaftem und frischem Gemüse für euch, welche ihr direkt vor Ort abholen könnt.\r\n\r\nhttps://stadtgemuese-fulda.de",
"position": { "type": "Point", "coordinates": [9.632435, 50.560342] }
},
{
"id": 166,
"name": "Weidendom",
"text": "free camping",
"position": { "type": "Point", "coordinates": [9.438793, 50.560112] },
}];
export const events = [
{
"id": 423,
"name": "Hackathon",
"text": "still in progress",
"position": { "type": "Point", "coordinates": [10.5, 51.62] },
"start": "2022-03-25T12:00:00",
"end": "2022-05-12T12:00:00",
}
]
"text": "Free camping",
"position": { "type": "Point", "coordinates": [9.438793, 50.560112] }
}
];
export const events = [
{
"id": 423,
"name": "Hackathon",
"text": "Still in progress",
"position": { "type": "Point", "coordinates": [10.5, 51.62] },
"start": "2022-03-25T12:00:00",
"end": "2022-05-12T12:00:00"
}
];
```
We want to create two Layers. One we want to call *Places* and the other *Events*
### Creating Layers
we import our sample data to the `src/App.tsx`
We want to create **two layers**:
- A **"Places"** layer for locations
- An **"Events"** layer for scheduled activities.
First, we import our sample data into `src/App.tsx`:
```tsx
import { events, places } from "./sample-data"
```
and than we create our two `<Layer>` inside of our `<UtopiaMap>` component
```tsx
<UtopiaMap center={[50.6, 15.5]} zoom={5} height='100dvh' width="100dvw">
<Layer
name='events'
markerIcon='calendar'
markerShape='square'
markerDefaultColor='#700'
data={events} />
<Layer
name='places'
markerIcon='point'
markerShape='circle'
markerDefaultColor='#007'
data={places} />
</UtopiaMap>
import { events, places } from "./sample-data";
```
And we see our map with two layers:
### Adding Layers to `<UtopiaMap>`
Next, we define our `<Layer>` components inside `<UtopiaMap>`:
```tsx
<UtopiaMap center={[50.6, 15.5]} zoom={5} height="100dvh" width="100dvw">
<Layer
name="events"
markerIcon="calendar"
markerShape="square"
markerDefaultColor="#700"
data={events}
/>
<Layer
name="places"
markerIcon="point"
markerShape="circle"
markerDefaultColor="#007"
data={places}
/>
</UtopiaMap>
```
### Running the Application
Finally, we start our development server to see the **map with two layers**:
```shell
npm run dev
```
➡️ In [Example 3](../3-tags/), we'll add **tags** to our map.

View File

@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
<title>Utopia-UI Example 2</title>
</head>
<body>
<div id="root"></div>

View File

@ -9,10 +9,12 @@
"version": "0.0.0",
"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1"
"react-dom": "^18.3.1",
"utopia-ui": "../../"
},
"devDependencies": {
"@eslint/js": "^9.17.0",
"@types/geojson": "^7946.0.16",
"@types/react": "^18.3.18",
"@types/react-dom": "^18.3.5",
"@vitejs/plugin-react": "^4.3.4",
@ -25,6 +27,87 @@
"vite": "^6.0.5"
}
},
"../..": {
"version": "3.0.59",
"license": "GPL-3.0-only",
"dependencies": {
"@heroicons/react": "^2.0.17",
"@tanstack/react-query": "^5.17.8",
"@types/offscreencanvas": "^2019.7.1",
"axios": "^1.6.5",
"date-fns": "^3.3.1",
"leaflet": "^1.9.4",
"leaflet.locatecontrol": "^0.79.0",
"prop-types": "^15.8.1",
"radash": "^12.1.0",
"react-colorful": "^5.6.1",
"react-image-crop": "^10.1.8",
"react-leaflet": "^4.2.1",
"react-leaflet-cluster": "^2.1.0",
"react-markdown": "^9.0.1",
"react-photo-album": "^3.0.2",
"react-router-dom": "^6.16.0",
"react-string-replace": "^1.1.1",
"react-toastify": "^9.1.3",
"remark-breaks": "^4.0.0",
"tw-elements": "^1.0.0",
"yet-another-react-lightbox": "^3.21.7"
},
"devDependencies": {
"@eslint-community/eslint-plugin-eslint-comments": "^4.4.1",
"@rollup/plugin-alias": "^5.1.1",
"@rollup/plugin-node-resolve": "^16.0.0",
"@rollup/plugin-typescript": "^12.1.2",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.2.0",
"@types/geojson": "^7946.0.14",
"@types/leaflet": "^1.7.11",
"@types/leaflet.markercluster": "^1.5.5",
"@types/react": "^18.2.0",
"@types/react-dom": "^18.0.5",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"@vitejs/plugin-react": "^4.3.4",
"@vitest/coverage-v8": "^3.0.5",
"autoprefixer": "^10.4.14",
"cypress": "^14.0.3",
"daisyui": "^4.6.1",
"eslint": "^8.24.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-standard": "^17.1.0",
"eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-json": "^3.1.0",
"eslint-plugin-no-catch-all": "^1.1.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-react": "^7.31.8",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.18",
"eslint-plugin-security": "^3.0.1",
"eslint-plugin-yml": "^1.14.0",
"globals": "^15.14.0",
"happy-dom": "^16.8.1",
"postcss": "^8.4.21",
"prettier": "^3.3.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"rollup": "^4.34.6",
"rollup-plugin-dts": "^6.1.1",
"rollup-plugin-postcss": "^4.0.2",
"tailwindcss": "^3.3.1",
"typedoc": "^0.27.6",
"typedoc-plugin-coverage": "^3.4.1",
"typedoc-plugin-missing-exports": "^3.1.0",
"typescript": "^5.7.3",
"vite": "^6.0.11",
"vitest": "^3.0.5"
},
"peerDependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
},
"node_modules/@ampproject/remapping": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
@ -1270,6 +1353,13 @@
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
"dev": true
},
"node_modules/@types/geojson": {
"version": "7946.0.16",
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz",
"integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/json-schema": {
"version": "7.0.15",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
@ -2901,6 +2991,10 @@
"punycode": "^2.1.0"
}
},
"node_modules/utopia-ui": {
"resolved": "../..",
"link": true
},
"node_modules/vite": {
"version": "6.0.11",
"resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz",

View File

@ -1,5 +1,5 @@
{
"name": "tutorial-2-static-layer",
"name": "2-static-layer",
"private": true,
"version": "0.0.0",
"type": "module",
@ -11,10 +11,12 @@
},
"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1"
"react-dom": "^18.3.1",
"utopia-ui": "../../"
},
"devDependencies": {
"@eslint/js": "^9.17.0",
"@types/geojson": "^7946.0.16",
"@types/react": "^18.3.18",
"@types/react-dom": "^18.3.5",
"@vitejs/plugin-react": "^4.3.4",

View File

@ -1,6 +1,40 @@
import { UtopiaMap, Layer } from "utopia-ui"
import { events, places } from "./sample-data"
const itemTypeEvent = {
name: "event",
show_name_input: false,
show_profile_button: false,
show_start_end: false,
show_start_end_input: false,
show_text: false,
show_text_input: false,
custom_text: "",
profileTemplate: [],
offers_and_needs: false,
icon_as_labels: null,
relations: false,
template: "TODO",
questlog: false,
}
const itemTypePlace = {
name: "event",
show_name_input: false,
show_profile_button: false,
show_start_end: false,
show_start_end_input: false,
show_text: false,
show_text_input: false,
custom_text: "",
profileTemplate: [],
offers_and_needs: false,
icon_as_labels: null,
relations: false,
template: "TODO",
questlog: false,
}
function App() {
return (
<UtopiaMap center={[50.6, 15.5]} zoom={5} height='100dvh' width="100dvw">
@ -9,13 +43,23 @@ function App() {
markerIcon='calendar'
markerShape='square'
markerDefaultColor='#700'
data={events} />
data={events}
menuIcon="calendar"
menuColor="#700"
menuText="events"
itemType={itemTypeEvent}
/>
<Layer
name='places'
markerIcon='point'
markerShape='circle'
markerDefaultColor='#007'
data={places} />
data={places}
menuIcon="point"
menuColor="#007"
menuText="places"
itemType={itemTypePlace}
/>
</UtopiaMap>
)
}

View File

@ -1,22 +1,24 @@
import { Point } from "utopia-ui";
export const places = [{
"id": 51,
"id": "062a1176-f7ee-458d-adba-4a0b3b1ce2a0",
"name": "Stadtgemüse",
"text": "Stadtgemüse Fulda ist eine Gemüsegärtnerei in Maberzell, die es sich zur Aufgabe gemacht hat, die Stadt und seine Bewohner:innen mit regionalem, frischem und natürlich angebautem Gemüse mittels Gemüsekisten zu versorgen. Es gibt also jede Woche, von Frühjahr bis Herbst, angepasst an die Saison eine Kiste mit schmackhaftem und frischem Gemüse für euch, welche ihr direkt vor Ort abholen könnt. \r\n\r\nhttps://stadtgemuese-fulda.de",
"position": { "type": "Point", "coordinates": [9.632435, 50.560342] },
"text": "Stadtgemüse Fulda ist eine Gemüsegärtnerei in Maberzell, die es sich zur Aufgabe gemacht hat, die Stadt und seine Bewohner:innen mit regionalem, frischem und natürlich angebautem Gemüse mittels Gemüsekisten zu versorgen. Es gibt also jede Woche, von Frühjahr bis Herbst, angepasst an die Saison eine Kiste mit schmackhaftem und frischem Gemüse für euch, welche ihr direkt vor Ort abholen könnt. \r\n\r\nhttps://stadtgemuese-fulda.de #food #permaculture #nature",
"position": { "type": "Point", "coordinates": [9.632435, 50.560342] } as Point,
},
{
"id": 166,
"id": "144e379c-b719-4334-9f0e-de277d3b6d0f",
"name": "Weidendom",
"text": "free camping",
"position": { "type": "Point", "coordinates": [9.438793, 50.560112] },
"text": "free camping #nature",
"position": { "type": "Point", "coordinates": [9.438793, 50.560112] } as Point,
}];
export const events = [
{
"id": 423,
"id": "efe00aaa-8b14-47b5-a032-3e0560980c1e",
"name": "Hackathon",
"text": "still in progress",
"position": { "type": "Point", "coordinates": [10.5, 51.62] },
"text": "still in progress #utopia #map",
"position": { "type": "Point", "coordinates": [10.5, 51.62] } as Point,
"start": "2022-03-25T12:00:00",
"end": "2022-05-12T12:00:00",
}

24
examples/3-tags/.gitignore vendored Normal file
View File

@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

1
examples/3-tags/.nvmrc Normal file
View File

@ -0,0 +1 @@
v18.19.1

76
examples/3-tags/README.md Normal file
View File

@ -0,0 +1,76 @@
# Example 3: Tags
In [Example 2](/2-static-layers), we learned how to add layers with static data to our map.
Now, we'll introduce **tags** to structure our items and bring some color to the map. Tags allow us to categorize items using a simple **hash syntax**, such as `#utopia #map`, in the text field.
With tags, we can **filter the map** by clicking on them or searching for keywords in the search bar.
### Adding Tags to Our Data
To implement tags, we first define them in our `src/sample-data.ts` file:
```javascript
export const tags: Tag[] = [
{
"id": "e19f46a7-77a4-4a50-99a2-a942dce843a3",
"name": "nature",
"color": "#9bc53d"
},
{
"id": "2c2099a6-23ac-4308-b91c-86eefeff3a1d",
"name": "utopia",
"color": "#c3423f"
},
{
"id": "48b2de97-2b9e-432b-b230-7bdc9a5fb6c0",
"name": "map",
"color": "#5bc0eb"
},
{
"id": "c88f52e6-357b-45fb-a171-9c2b1dceeb8e",
"name": "food",
"color": "#6761a8"
},
{
"id": "8928cb92-a3c1-4d83-9495-c2eb4fac0bbe",
"name": "permaculture",
"color": "#44344f"
},
];
```
and we add some hash tags to our sample items.
### Importing the Tags into Our App
Next, we import our sample data into `src/App.tsx`:
```tsx
import { tags } from "./sample-data";
```
### Integrating Tags into `<UtopiaMap>`
We then add the `<Tags>` component inside `<UtopiaMap>` and pass our `tags` from `sample-data.ts`:
```tsx
function App() {
return (
<UtopiaMap center={[50.6, 15.5]} zoom={5} height="100dvh" width="100dvw">
...
<Tags data={tags} />
</UtopiaMap>
);
}
export default App;
```
### Running the Application
Finally, we start our development server to see the **enhanced map** with tags:
```shell
npm run dev
```

View File

@ -0,0 +1,25 @@
import js from '@eslint/js'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import globals from 'globals'
import tseslint from 'typescript-eslint'
export default tseslint.config(
{ ignores: ['dist'] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ['**/*.{ts,tsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
},
},
)

View File

@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Utopia-UI Example 3</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

5490
examples/3-tags/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,30 @@
{
"name": "3-tags",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1",
"utopia-ui": "latest"
},
"devDependencies": {
"@eslint/js": "^9.17.0",
"@types/react": "^18.3.18",
"@types/react-dom": "^18.3.5",
"@vitejs/plugin-react": "^4.3.4",
"eslint": "^9.17.0",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.16",
"globals": "^15.14.0",
"typescript": "~5.6.2",
"typescript-eslint": "^8.18.2",
"vite": "^6.0.5"
}
}

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,24 @@
import { UtopiaMap, Layer, Tags } from "utopia-ui"
import { events, places, tags } from "./sample-data"
function App() {
return (
<UtopiaMap center={[50.6, 15.5]} zoom={5} height='100dvh' width="100dvw">
<Layer
name='events'
markerIcon='calendar'
markerShape='square'
markerDefaultColor='#700'
data={events} />
<Layer
name='places'
markerIcon='point'
markerShape='circle'
markerDefaultColor='#007'
data={places} />
<Tags data={tags}/>
</UtopiaMap>
)
}
export default App

View File

@ -0,0 +1,9 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.tsx'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>,
)

View File

@ -0,0 +1,54 @@
import { Tag } from "utopia-ui";
export const places = [{
"id": "062a1176-f7ee-458d-adba-4a0b3b1ce2a0",
"name": "Stadtgemüse",
"text": "Stadtgemüse Fulda ist eine Gemüsegärtnerei in Maberzell, die es sich zur Aufgabe gemacht hat, die Stadt und seine Bewohner:innen mit regionalem, frischem und natürlich angebautem Gemüse mittels Gemüsekisten zu versorgen. Es gibt also jede Woche, von Frühjahr bis Herbst, angepasst an die Saison eine Kiste mit schmackhaftem und frischem Gemüse für euch, welche ihr direkt vor Ort abholen könnt. \r\n\r\nhttps://stadtgemuese-fulda.de #food #permaculture #nature",
"position": { "type": "Point", "coordinates": [9.632435, 50.560342] },
},
{
"id": "144e379c-b719-4334-9f0e-de277d3b6d0f",
"name": "Weidendom",
"text": "free camping #nature",
"position": { "type": "Point", "coordinates": [9.438793, 50.560112] },
}];
export const events = [
{
"id": "efe00aaa-8b14-47b5-a032-3e0560980c1e",
"name": "Hackathon",
"text": "still in progress #utopia #map",
"position": { "type": "Point", "coordinates": [10.5, 51.62] },
"start": "2022-03-25T12:00:00",
"end": "2022-05-12T12:00:00",
}
]
export const tags : Tag[]= [
{
"id": "e19f46a7-77a4-4a50-99a2-a942dce843a3",
"name": "nature",
"color": "#9bc53d"
},
{
"id": "2c2099a6-23ac-4308-b91c-86eefeff3a1d",
"name": "utopia",
"color": "#c3423f"
},
{
"id": "48b2de97-2b9e-432b-b230-7bdc9a5fb6c0",
"name": "map",
"color": "#5bc0eb"
},
{
"id": "c88f52e6-357b-45fb-a171-9c2b1dceeb8e",
"name": "food",
"color": "#6761a8"
},
{
"id": "8928cb92-a3c1-4d83-9495-c2eb4fac0bbe",
"name": "permaculture",
"color": "#44344f"
},
]

1
examples/3-tags/src/vite-env.d.ts vendored Normal file
View File

@ -0,0 +1 @@
/// <reference types="vite/client" />

View File

@ -0,0 +1,26 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["src"]
}

View File

@ -0,0 +1,7 @@
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
}

View File

@ -0,0 +1,24 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"target": "ES2022",
"lib": ["ES2023"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["vite.config.ts"]
}

View File

@ -0,0 +1,7 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
})

View File

@ -113,8 +113,8 @@
"imports": {
"#components/*": "./src/Components/*",
"#utils/*": "./src/Utils/*",
"#types/*": "./src/types/*",
"#src/*": "./src/*",
"#types/*": "./types/*",
"#root/*": "./*"
}
}

View File

@ -76,17 +76,16 @@ export default [
],
},
{
input: 'src/index.tsx',
input: 'dist/types/src/index.d.ts',
output: [{ file: 'dist/index.d.ts', format: 'es' }],
plugins: [
aliasConfig,
dts({
respectExternal: true,
compilerOptions: {
skipLibCheck: true,
},
}),
],
external: [/\.css$/, /\.d\.ts$/], // ✅ `.d.ts` als extern behandeln
external: [/\.css$/], //, /\.d\.ts$/
},
]

View File

@ -4,6 +4,8 @@ import { SetAppState } from './SetAppState'
import type { AssetsApi } from '#types/AssetsApi'
export type { AssetsApi } from '#types/AssetsApi'
/**
* @category AppShell
*/

View File

@ -3,7 +3,7 @@ import { useEffect, useRef, useState } from 'react'
import { Link, useLocation } from 'react-router-dom'
import { toast } from 'react-toastify'
import { useAuth } from '#components/Auth'
import { useAuth } from '#components/Auth/useAuth'
import { useItems } from '#components/Map/hooks/useItems'
import type { Item } from '#types/Item'

View File

@ -1,4 +1,4 @@
export { AppShell } from './AppShell'
export * from './AppShell'
export { SideBar } from './SideBar'
export { Content } from './Content'
export { Sitemap } from './Sitemap'

View File

@ -1,4 +1,4 @@
export { AuthProvider, useAuth } from './useAuth'
export { AuthProvider, UserApi, UserItem } from './useAuth'
export { LoginPage } from './LoginPage'
export { SignupPage } from './SignupPage'
export { RequestPasswordPage } from './RequestPasswordPage'

View File

@ -3,6 +3,9 @@ import { createContext, useState, useContext, useEffect } from 'react'
import type { UserApi } from '#types/UserApi'
import type { UserItem } from '#types/UserItem'
export type { UserApi } from '#types/UserApi'
export type { UserItem } from '#types/UserItem'
interface AuthProviderProps {
userApi: UserApi
children?: React.ReactNode

View File

@ -1,6 +1,6 @@
import { useEffect, useState } from 'react'
import { useAuth } from '#components/Auth'
import { useAuth } from '#components/Auth/useAuth'
import { useItems } from '#components/Map/hooks/useItems'
import { useQuestsOpen, useSetQuestOpen } from './hooks/useQuests'

View File

@ -27,6 +27,12 @@ import type { Tag } from '#types/Tag'
import type { Popup } from 'leaflet'
import type { ReactElement, ReactNode } from 'react'
export type { Point } from 'geojson'
export type { Item } from '#types/Item'
export type { LayerProps } from '#types/LayerProps'
export type { Tag } from '#types/Tag'
export type { Popup } from 'leaflet'
/**
* @category Map
*/

View File

@ -1,6 +1,6 @@
import { useEffect } from 'react'
import { useAuth } from '#components/Auth'
import { useAuth } from '#components/Auth/useAuth'
import { useSetPermissionData, useSetPermissionApi, useSetAdminRole } from './hooks/usePermissions'
@ -8,17 +8,20 @@ import type { ItemsApi } from '#types/ItemsApi'
import type { Permission } from '#types/Permission'
/**
* @category Map
* @category Types
*/
export function Permissions({
data,
api,
adminRole,
}: {
export interface PermissionsProps {
data?: Permission[]
api?: ItemsApi<Permission>
adminRole?: string
}) {
}
export type { Permission } from '#types/Permission'
export type { ItemsApi } from '#types/ItemsApi'
/**
* @category Map
*/
export function Permissions({ data, api, adminRole }: PermissionsProps) {
const setPermissionData = useSetPermissionData()
const setPermissionApi = useSetPermissionApi()
const setAdminRole = useSetAdminRole()

View File

@ -1,6 +1,6 @@
import { useNavigate } from 'react-router-dom'
import { useAuth } from '#components/Auth'
import { useAuth } from '#components/Auth/useAuth'
export const GratitudeControl = () => {
const navigate = useNavigate()

View File

@ -27,12 +27,14 @@ export const TextView = ({
text,
truncate = false,
rawText,
itemTextField,
}: {
item?: Item
itemId: string
itemId?: string
text?: string
truncate?: boolean
rawText?: string
itemTextField?: string
}) => {
if (item) {
text = item.text
@ -40,6 +42,8 @@ export const TextView = ({
}
const tags = useTags()
const addFilterTag = useAddFilterTag()
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const itemTextFieldDummy = itemTextField
let innerText = ''
let replacedText = ''
@ -125,7 +129,7 @@ export const TextView = ({
}: {
children: string
tag: Tag
itemId: string
itemId?: string
}) => {
return (
<a

View File

@ -1,7 +1,7 @@
export { UtopiaMap } from './UtopiaMap'
export { Layer } from './Layer'
export * from './Layer'
export { Tags } from './Tags'
export { Permissions } from './Permissions'
export * from './Permissions'
export { ItemForm } from './ItemForm'
export { ItemView } from './ItemView'
export { PopupTextAreaInput } from './Subcomponents/ItemPopupComponents/PopupTextAreaInput'

View File

@ -5,7 +5,7 @@ import { useEffect, useState } from 'react'
import { useLocation, useNavigate } from 'react-router-dom'
import { useAppState } from '#components/AppShell/hooks/useAppState'
import { useAuth } from '#components/Auth'
import { useAuth } from '#components/Auth/useAuth'
import { useItems, useUpdateItem, useAddItem } from '#components/Map/hooks/useItems'
import { useLayers } from '#components/Map/hooks/useLayers'
import { useHasUserPermission } from '#components/Map/hooks/usePermissions'

View File

@ -3,7 +3,7 @@ import { useEffect, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { toast } from 'react-toastify'
import { useAuth } from '#components/Auth'
import { useAuth } from '#components/Auth/useAuth'
import { TextInput } from '#components/Input'
import { MapOverlayPage } from '#components/Templates'

View File

@ -1,4 +1,4 @@
export { UserSettings } from './UserSettings'
export { PlusButton } from './Subcomponents/PlusButton'
// export { PlusButton } from './Subcomponents/PlusButton'
export { ProfileView } from './ProfileView'
export { ProfileForm } from './ProfileForm'

View File

@ -33,14 +33,18 @@ import type { Item } from '#types/Item'
export const OverlayItemsIndexPage = ({
url,
layerName,
parameterField,
plusButton = true,
}: {
layerName: string
url: string
parameterField?: string
plusButton?: boolean
}) => {
const [loading, setLoading] = useState<boolean>(false)
const [addItemPopupType, setAddItemPopupType] = useState<string>('')
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const parameterFieldDummy = parameterField
const tabRef = useRef<HTMLFormElement>(null)

View File

@ -1,43 +1,12 @@
import './index.css'
export {
UtopiaMap,
Layer,
Tags,
Permissions,
ItemForm,
ItemView,
PopupTextAreaInput,
PopupStartEndInput,
PopupTextInput,
PopupButton,
TextView,
StartEndView,
PopupCheckboxInput,
} from './Components/Map'
export { AppShell, Content, SideBar, Sitemap } from './Components/AppShell'
export {
AuthProvider,
LoginPage,
SignupPage,
RequestPasswordPage,
SetNewPasswordPage,
} from './Components/Auth'
export { UserSettings, ProfileView, ProfileForm } from './Components/Profile'
export { Quests, Modal } from './Components/Gaming'
export {
TitleCard,
CardPage,
MapOverlayPage,
OverlayItemsIndexPage,
MoonCalendar,
SelectUser,
AttestationForm,
MarketView,
} from './Components/Templates'
export { TextInput, TextAreaInput, SelectBox } from './Components/Input'
export * from './types'
export * from './Components/Map'
export * from './Components/AppShell'
export * from './Components/Auth'
export * from './Components/Profile'
export * from './Components/Gaming'
export * from './Components/Templates'
export * from './Components/Input'
declare global {
interface Window {

View File

@ -1,3 +1,6 @@
/**
* @category Types
*/
export interface AssetsApi {
upload(file: Blob, title: string): Promise<{ id: string }>
url: string

3
src/types/Item.d.ts vendored
View File

@ -15,6 +15,9 @@ interface GalleryItem {
}
}
/**
* @category Types
*/
export interface Item {
id: string
name: string

View File

@ -2,14 +2,18 @@ import type { Key } from 'react'
export interface ItemType {
name: string
show_name_input: boolean
show_profile_button: boolean
show_start_end: boolean
show_start_end_input: boolean
show_text: boolean
show_text_input: boolean
custom_text: string
// eslint-disable-next-line @typescript-eslint/no-explicit-any
profileTemplate: { collection: string | number; id: Key | null | undefined; item: any }[]
offers_and_needs: boolean
icon_as_labels: unknown
relations: boolean
template: string
show_start_end_input: boolean
questlog: boolean
}

View File

@ -1,3 +1,6 @@
/**
* @category Types
*/
export interface ItemsApi<T> {
getItems(): Promise<T[]>
getItem?(id: string): Promise<T>

View File

@ -3,6 +3,9 @@ import type { ItemFormPopupProps } from './ItemFormPopupProps'
import type { ItemsApi } from './ItemsApi'
import type { ItemType } from './ItemType'
/**
* @category Types
*/
export interface LayerProps {
id?: string
data?: Item[]

View File

@ -1,6 +1,9 @@
import type { PermissionAction } from './PermissionAction'
import type { PermissionCondition } from './PermissionCondition'
/**
* @category Types
*/
export interface Permission {
id?: string
policy?: { name: string }

3
src/types/Tag.d.ts vendored
View File

@ -1,3 +1,6 @@
/**
* @category Types
*/
export interface Tag {
color: string
id: string

View File

@ -1,5 +1,8 @@
import type { UserItem } from './UserItem'
/**
* @category Types
*/
export interface UserApi {
register(email: string, password: string, userName: string): Promise<void>
login(email: string, password: string): Promise<UserItem | undefined>

View File

@ -1,5 +1,8 @@
import type { Profile } from './Profile'
/**
* @category Types
*/
export interface UserItem {
id?: string
// eslint-disable-next-line @typescript-eslint/no-explicit-any

View File

@ -1,9 +0,0 @@
export type { ItemsApi } from './ItemsApi'
export type { Tag } from './Tag'
export type { Item } from './Item'
export type { Permission } from './Permission'
export type { LayerProps } from './LayerProps'
export type { UserApi } from './UserApi'
export type { UserItem } from './UserItem'
export type { UtopiaMapProps } from './UtopiaMapProps'
export type { AssetsApi } from './AssetsApi'

View File

@ -22,15 +22,15 @@
"paths": {
"#components/*": ["./src/Components/*"],
"#utils/*": ["./src/Utils/*"],
"#src/*": ["./src/*"],
"#types/*": ["./src/types/*"],
"#src/*": ["./src/*"],
"#root/*": ["./*"]
}
},
"include": ["src", "vite.config.ts", "setupTest.ts", "cypress.config.ts", "cypress/support/commands.ts", "cypress/support/component.ts"],
"exclude": ["node_modules", "dist", "example", "rollup.config.mjss"],
"typeRoots": [
"./types",
"./src/types",
"./node_modules/@types/"
]
}