Compare commits
30 Commits
v1.3.1
...
f6819b6a2b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6819b6a2b | ||
|
|
cfccd4cdcc | ||
|
|
4602de7a38 | ||
|
|
ca26f1e733 | ||
|
|
3b57ca4594 | ||
|
|
210ef9d99e | ||
|
|
08a66095e6 | ||
|
|
ecc9003a73 | ||
|
|
a53f77c97c | ||
|
|
fdd928720a | ||
|
|
5adadd246e | ||
|
|
4b92df8fea | ||
|
|
9b96de0a21 | ||
|
|
902e730cd3 | ||
|
|
1f891ab057 | ||
|
|
165109fc65 | ||
|
|
b6fbe38f60 | ||
|
|
053ae3729a | ||
|
|
8207366362 | ||
|
|
29217e883b | ||
|
|
0f635033c2 | ||
|
|
805559efc3 | ||
|
|
5d46200905 | ||
|
|
5c353a0da8 | ||
|
|
ba6f095dc0 | ||
|
|
362a7e4666 | ||
|
|
63a57dcb7c | ||
|
|
62a5a56dea | ||
|
|
eb8566423f | ||
|
|
1f508bca74 |
@@ -1,7 +1,7 @@
|
||||
node_modules
|
||||
.next
|
||||
.git
|
||||
Signaturen
|
||||
/Signaturen/
|
||||
*.tar
|
||||
*.pdf
|
||||
*.py
|
||||
|
||||
13
.env.docker
Normal file
@@ -0,0 +1,13 @@
|
||||
# Dummy environment for Docker build stage
|
||||
# These values are only needed so Next.js can compile during docker build
|
||||
# Runtime values are injected via docker-compose environment
|
||||
DATABASE_URL=postgresql://lageplan:lageplan_secret@db:5432/lageplan
|
||||
NEXTAUTH_URL=http://localhost:3000
|
||||
NEXTAUTH_SECRET=build-time-secret-not-used-at-runtime
|
||||
MINIO_ENDPOINT=minio
|
||||
MINIO_PORT=9000
|
||||
MINIO_ACCESS_KEY=minioadmin
|
||||
MINIO_SECRET_KEY=minioadmin123
|
||||
MINIO_BUCKET=lageplan-icons
|
||||
MINIO_USE_SSL=false
|
||||
MINIO_PUBLIC_URL=http://localhost:9000
|
||||
@@ -27,3 +27,8 @@ MINIO_PUBLIC_URL=http://localhost:9002
|
||||
# Web App
|
||||
WEB_PORT=3000
|
||||
NODE_ENV=development
|
||||
|
||||
# --- CI/CD / Registry (nur für Portainer Deployment) ---
|
||||
# Gitea Registry Login für Watchtower (automatische Image-Updates)
|
||||
GITEA_REGISTRY_USER=adminpepe
|
||||
GITEA_REGISTRY_PASS=dein_gitea_token_oder_passwort
|
||||
|
||||
49
.gitea/workflows/deploy.yml
Normal file
@@ -0,0 +1,49 @@
|
||||
name: Build and Push Docker Image
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
REGISTRY: git.purepixel.ch
|
||||
IMAGE: git.purepixel.ch/adminpepe/lageplan
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Gitea Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ secrets.REGISTRY_USER }}
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.IMAGE }}
|
||||
tags: |
|
||||
type=raw,value=latest
|
||||
type=sha,prefix=,suffix=,format=short
|
||||
|
||||
- name: Build and push
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=registry,ref=${{ env.IMAGE }}:cache
|
||||
cache-to: type=registry,ref=${{ env.IMAGE }}:cache,mode=max
|
||||
12
.gitignore
vendored
@@ -49,13 +49,19 @@ prisma/migrations/*
|
||||
# Large binary files (do not commit)
|
||||
*.tar
|
||||
*.zip
|
||||
*.mp4
|
||||
# Allow MP4s in public folder (used by the app)
|
||||
!public/*.mp4
|
||||
!public/**/*.mp4
|
||||
lageplan-web.tar
|
||||
|
||||
# Reference materials (keep locally, not in git)
|
||||
Signaturen/
|
||||
/Signaturen/
|
||||
Reglement_*/
|
||||
|
||||
# Allow FKS SVG signatures in public folder (used by seed scripts)
|
||||
!public/signaturen/
|
||||
!public/signaturen/*.svg
|
||||
!public/**/*.svg
|
||||
|
||||
# Stack env (contains secrets)
|
||||
stack.env
|
||||
.env.docker
|
||||
|
||||
39
CHANGELOG.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Changelog
|
||||
|
||||
Alle nennenswerten Änderungen an diesem Projekt werden in dieser Datei dokumentiert.
|
||||
Das Format basiert auf [Keep a Changelog](https://keepachangelog.com/de/1.0.0/).
|
||||
|
||||
## [1.4.0] – 2026-05-20 — Phase 1: Symbol-Architektur Redesign
|
||||
|
||||
### Neu
|
||||
- **SymbolTemplate** — globale, read-only Vorlagen-Pakete aus `public/signaturen/*.svg`
|
||||
- **TenantCategory** — mandantenspezifische, frei anlegbare Kategorien für Symbole
|
||||
- **TenantSymbol Refactor** — Symbole sind jetzt vollständig mandantenspezifisch (`name`, `svgPath`, `categoryId`, `isUploaded`)
|
||||
- Upload-Dialog für eigene SVG/PNG/JPEG-Symbole mit Drag & Drop
|
||||
- Import-Dialog für Vorlagen-Pakete (z.B. "Feuerwehr Schweiz")
|
||||
|
||||
### APIs
|
||||
- `GET /api/templates` — listet verfügbare Template-Pakete mit Vorschau
|
||||
- `POST /api/templates/import` — importiert ein Paket als TenantSymbols
|
||||
- `GET/POST/PATCH/DELETE /api/tenant/categories` — CRUD für Tenant-Kategorien
|
||||
- `GET/POST/PATCH/DELETE /api/tenant/symbols` — erweitert: Gruppierung, Upload, JSON-Import
|
||||
- `GET /api/tenant/symbols/[id]/image` — liefert TenantSymbol-Bilder aus MinIO oder `public/`
|
||||
- `GET /api/icons/[id]/image` — TenantSymbol-First Lookup, dann Legacy-Fallback
|
||||
- `GET /api/icons` — liefert jetzt auch `tenantSymbols` und `tenantSymbolGroups`
|
||||
|
||||
### UI
|
||||
- **Admin → Symbol-Manager**: komplett neues Layout mit 3 Tabs (Symbole, Kategorien, Import)
|
||||
- **Sidebar (RightSidebar)**: zeigt Tenant-Symbole jetzt nach Kategorie gruppiert an
|
||||
|
||||
### Migration & Seed
|
||||
- `prisma/migrations/20260520_symbol_architecture/migration.sql`
|
||||
- `prisma/seed-symbol-templates.ts`
|
||||
- `prisma/migrate-tenant-symbols.ts`
|
||||
- Alle Seeds idempotent (`upsert` statt `deleteMany`)
|
||||
|
||||
---
|
||||
|
||||
## [1.3.5] – vor 2026-05-20
|
||||
|
||||
### Bestehende Features
|
||||
- Karten-Zeichenwerkzeuge, Journal, Einsatzrapport, Projekte, Benutzerverwaltung, Mandantenverwaltung
|
||||
47
Dockerfile
@@ -26,34 +26,41 @@ RUN npm run build
|
||||
# Stage 3: Runner
|
||||
FROM node:20-alpine AS runner
|
||||
RUN apk add --no-cache openssl
|
||||
WORKDIR /app
|
||||
|
||||
ENV NODE_ENV production
|
||||
ENV NEXT_TELEMETRY_DISABLED 1
|
||||
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 nextjs
|
||||
RUN addgroup --system --gid 1001 nodejs && \
|
||||
adduser --system --uid 1001 nextjs
|
||||
|
||||
COPY --from=builder /app/public ./public
|
||||
COPY --from=builder /app/.next/standalone ./
|
||||
COPY --from=builder /app/.next/static ./.next/static
|
||||
COPY --from=builder /app/.env ./.env
|
||||
COPY --from=builder /app/prisma ./prisma
|
||||
COPY --from=builder /app/node_modules/.prisma ./node_modules/.prisma
|
||||
COPY --from=builder /app/node_modules/prisma ./node_modules/prisma
|
||||
COPY --from=builder /app/node_modules/@prisma ./node_modules/@prisma
|
||||
COPY --from=builder /app/node_modules/.bin/prisma ./node_modules/.bin/prisma
|
||||
COPY --from=builder /app/node_modules/bcryptjs ./node_modules/bcryptjs
|
||||
COPY --from=builder /app/node_modules/stripe ./node_modules/stripe
|
||||
COPY --from=builder /app/package.json ./package.json
|
||||
RUN npm install --omit=dev --legacy-peer-deps socket.io@4.7.4 @react-pdf/renderer@4.3.2 qrcode@1.5.4 --no-save
|
||||
COPY server-custom.js ./server-custom.js
|
||||
COPY docker-entrypoint.sh ./docker-entrypoint.sh
|
||||
|
||||
RUN chown -R nextjs:nodejs /app/node_modules
|
||||
WORKDIR /app
|
||||
# Fast: only chown the /app directory itself, not recursively
|
||||
RUN chown nextjs:nodejs /app
|
||||
|
||||
USER nextjs
|
||||
|
||||
# Install only the unbundled runtime deps needed by the custom server.
|
||||
# Running as USER nextjs means files are already correctly owned — no slow chown -R needed afterwards.
|
||||
RUN npm install --omit=dev --legacy-peer-deps socket.io@4.7.4 @react-pdf/renderer@4.3.2 qrcode@1.5.4 --no-save
|
||||
|
||||
COPY --chown=nextjs:nodejs --from=builder /app/.next/standalone ./
|
||||
COPY --chown=nextjs:nodejs --from=builder /app/.next/static ./.next/static
|
||||
# Ensure all public files (videos, images, etc.) are present in the runtime image
|
||||
COPY --chown=nextjs:nodejs --from=builder /app/public ./public
|
||||
COPY --chown=nextjs:nodejs --from=builder /app/.env ./.env
|
||||
COPY --chown=nextjs:nodejs --from=builder /app/prisma ./prisma
|
||||
COPY --chown=nextjs:nodejs --from=builder /app/node_modules/.prisma ./node_modules/.prisma
|
||||
COPY --chown=nextjs:nodejs --from=builder /app/node_modules/prisma ./node_modules/prisma
|
||||
COPY --chown=nextjs:nodejs --from=builder /app/node_modules/@prisma ./node_modules/@prisma
|
||||
COPY --chown=nextjs:nodejs --from=builder /app/node_modules/bcryptjs ./node_modules/bcryptjs
|
||||
COPY --chown=nextjs:nodejs --from=builder /app/node_modules/stripe ./node_modules/stripe
|
||||
COPY --chown=nextjs:nodejs --from=builder /app/node_modules/next ./node_modules/next
|
||||
COPY --chown=nextjs:nodejs --from=builder /app/node_modules/react ./node_modules/react
|
||||
COPY --chown=nextjs:nodejs --from=builder /app/node_modules/react-dom ./node_modules/react-dom
|
||||
COPY --chown=nextjs:nodejs --from=builder /app/package.json ./package.json
|
||||
COPY --chown=nextjs:nodejs server-custom.js ./server-custom.js
|
||||
COPY --chown=nextjs:nodejs docker-entrypoint.sh ./docker-entrypoint.sh
|
||||
|
||||
EXPOSE 3000
|
||||
ENV PORT 3000
|
||||
ENV HOSTNAME "0.0.0.0"
|
||||
|
||||
139
INCIDENT-REPORT-2026-05-20.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# Vorfall-Bericht: Symbol-Verlust (20. Mai 2026)
|
||||
|
||||
## Was ist passiert?
|
||||
|
||||
Alle Symbole in der App zeigen seit heute Morgen einen 404-Fehler (broken image icon). Die Symbole selbst sind aus der Datenbank gelöscht. Bereits erstellte Zeichnungen sind noch vorhanden, aber die Symbole darin sind ebenfalls broken.
|
||||
|
||||
---
|
||||
|
||||
## Chronologie der Ereignisse
|
||||
|
||||
### 1. Phase 1 Planung & Schema-Änderung (vor dem Vorfall)
|
||||
|
||||
Ich habe den Sprint A von **Phase 1 — Symbol-Architektur Redesign** begonnen. Dabei habe ich das Prisma-Schema erweitert:
|
||||
|
||||
- **Neue Tabellen**: `SymbolTemplate`, `TenantCategory`
|
||||
- **Erweiterte Tabelle**: `TenantSymbol` um neue Spalten (`name`, `svgPath`, `isUploaded`, `categoryId`, etc.)
|
||||
|
||||
Diese Änderungen waren ausschließlich schema-seitig — es gab keine Löschoperationen.
|
||||
|
||||
### 2. Der eigentliche Bug (Cascade Delete)
|
||||
|
||||
Das Problem lag **NICHT** in den Schema-Änderungen, sondern in den bestehenden **Seed-Skripten**, die bei jedem Container-Start laufen:
|
||||
|
||||
**Dateien:**
|
||||
- `prisma/seed.js`
|
||||
- `prisma/seed-icons-only.js`
|
||||
|
||||
**Code (VOR dem Fix):**
|
||||
```javascript
|
||||
// Zeile ~73 in seed-icons-only.js
|
||||
const deleted = await prisma.iconAsset.deleteMany({ where: { isSystem: true } })
|
||||
console.log(`Deleted ${deleted.count} old system icons`)
|
||||
```
|
||||
|
||||
Dieser Code hat **bei jedem Container-Start** alle System-Icons gelöscht und neu erstellt.
|
||||
|
||||
### 3. Warum das alles zerstört hat
|
||||
|
||||
Im Prisma-Schema gibt es folgende Relation:
|
||||
```prisma
|
||||
model TenantSymbol {
|
||||
id String @id @default(uuid())
|
||||
iconId String
|
||||
icon IconAsset @relation(fields: [iconId], references: [id], onDelete: Cascade)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**Die `onDelete: Cascade`-Regel bedeutet:** Wenn ein `IconAsset` gelöscht wird, werden automatisch alle `TenantSymbol`-Einträge, die darauf verweisen, ebenfalls gelöscht.
|
||||
|
||||
**Ablauf bei jedem Container-Start:**
|
||||
1. `seed-icons-only.js` läuft (weil Icon-Zahl < 100)
|
||||
2. `deleteMany({ isSystem: true })` löscht alle System-Icons
|
||||
3. `onDelete: Cascade` löscht alle `TenantSymbol`-Einträge
|
||||
4. Neue Icons werden mit **neuen UUIDs** erstellt
|
||||
5. Bestehende Zeichnungen verweisen noch auf die **alten gelöschten UUIDs** → 404
|
||||
|
||||
### 4. Warum ist das jetzt aufgefallen?
|
||||
|
||||
Der Container wurde neu gestartet (neues Deployment), und das Seed-Skript ist gelaufen. Dabei wurden alle Symbole gelöscht. Dieser Bug existierte bereits vor meinen Änderungen in den Seed-Skripten, ist aber jetzt zum ersten Mal aufgetreten, weil:
|
||||
- Vorher hat das Skript nur selten gegriffen (Icons waren schon genug da)
|
||||
- Jetzt wurde der Container frisch gestartet, und die Bedingung `ICON_COUNT < 100` war true
|
||||
|
||||
---
|
||||
|
||||
## Auswirkungen
|
||||
|
||||
### Was ist weg?
|
||||
- ❌ Alle `IconAsset`-Einträge (System-Symbole)
|
||||
- ❌ Alle `TenantSymbol`-Einträge (mandantenspezifische Symbol-Aktivierungen)
|
||||
- ❌ Alle Icon-Category-Zuordnungen
|
||||
|
||||
### Was ist noch da?
|
||||
- ✅ Alle Projekte (Zeichnungen)
|
||||
- ✅ Alle Features (Linien, Symbole, Texte in den Zeichnungen)
|
||||
- ✅ Alle Journal-Einträge
|
||||
- ✅ Alle Benutzer, Tenants, etc.
|
||||
|
||||
### Was ist mit den Zeichnungen?
|
||||
Die Zeichnungen sind intakt, aber die Symbole darin zeigen 404. Jedes Symbol in einer Zeichnung speichert in den Properties:
|
||||
```json
|
||||
{
|
||||
"iconId": "alte-gelöschte-uuid",
|
||||
"imageUrl": ""
|
||||
}
|
||||
```
|
||||
|
||||
Da die `iconId` auf einen gelöschten Eintrag verweist, kann das Bild nicht mehr geladen werden.
|
||||
|
||||
---
|
||||
|
||||
## Fix (bereits gepusht)
|
||||
|
||||
**Commit:** `5adadd2`
|
||||
|
||||
**Änderungen:**
|
||||
1. `deleteMany` aus `seed.js` und `seed-icons-only.js` entfernt
|
||||
2. Stattdessen **Upsert-Logik**: Update by `fileKey`, create only if missing
|
||||
3. Dadurch bleiben bestehende IDs erhalten, und es gibt keine Cascade-Löschungen mehr
|
||||
4. `prisma/migrate.js` um neue Phase-1-Tabellen erweitert
|
||||
|
||||
**Das verhindert zukünftige Löschungen, stellt aber bereits gelöschte Daten NICHT wieder her.**
|
||||
|
||||
---
|
||||
|
||||
## Wiederherstellung
|
||||
|
||||
Um die Symbole und Zeichnungen wiederherzustellen, gibt es zwei Wege:
|
||||
|
||||
### Option A: Datenbank-Backup (empfohlen)
|
||||
Falls ein `pg_dump` oder Snapshot vor dem 20. Mai existiert, können die Tabellen `icon_assets`, `icon_categories` und `tenant_symbols` daraus restored werden.
|
||||
|
||||
### Option B: Recovery-Skript
|
||||
Ein Skript, das:
|
||||
1. Alle System-Icons aus `public/signaturen/` neu in die DB einspielt
|
||||
2. Für jeden Tenant die Standard-Symbole neu aktiviert
|
||||
3. Die Zeichnungen scannt und die `iconId`-Referenzen auf die neuen IDs updated
|
||||
|
||||
---
|
||||
|
||||
## Lessons Learned
|
||||
|
||||
1. **Seed-Skripte dürfen niemals `deleteMany` auf verknüpfte Daten ausführen**
|
||||
2. `onDelete: Cascade` ist gefährlich bei Daten, die von Benutzern referenziert werden
|
||||
3. Container-Start-Skripte müssen idempotent sein (mehrfaches Ausführen = gleiches Ergebnis)
|
||||
4. Vor Deployment-Änderungen sollte ein DB-Backup gemacht werden
|
||||
|
||||
---
|
||||
|
||||
## Nächste Schritte
|
||||
|
||||
1. [x] Recovery-Skript erstellt: `prisma/recover-symbols.js` (Sidebar/Admin)
|
||||
2. [x] Recovery-Skript erstellt: `prisma/recover-features.js` (Zeichnungen)
|
||||
3. [x] Renderer resilient gemacht: broken Symbole zeigen ⚠️ statt leeres Nichts
|
||||
4. [x] `onDelete: Cascade` → `onDelete: SetNull` auf TenantSymbol.icon geändert
|
||||
5. [x] Seed-Skripte auf Upsert umgestellt (Commit 5adadd2)
|
||||
6. [ ] `recover-symbols.js` auf Server ausführen
|
||||
7. [ ] `recover-features.js --dry-run` auf Server ausführen zur Analyse
|
||||
8. [ ] Falls broken Features: User informieren (Symbole manuell neu platzieren)
|
||||
186
deploy/README.md
@@ -1,102 +1,168 @@
|
||||
# Lageplan — Portainer Deployment
|
||||
# Lageplan — CI/CD & Portainer Deployment
|
||||
|
||||
## Architektur
|
||||
## Übersicht
|
||||
|
||||
```
|
||||
Browser → :3000 (Web App) → intern: db:5432, minio:9000
|
||||
┌─────────────┐ Push ┌─────────────────┐ Build + Push ┌─────────────────┐
|
||||
│ Dein PC │ ────────────► │ Gitea (git) │ ──────────────────► │ Gitea Registry │
|
||||
│ (VS Code) │ │ git.purepixel │ │ (Docker Image) │
|
||||
└─────────────┘ └─────────────────┘ └────────┬────────┘
|
||||
│
|
||||
│ Pull
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ Portainer │
|
||||
│ (Stack Deploy) │
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
Nur **ein Port (3000)** muss exponiert werden. DB und MinIO laufen rein intern im Docker-Netzwerk. Icons werden über die Web-App gestreamt — kein direkter MinIO-Zugriff nötig.
|
||||
1. **Push auf `main`** → Gitea Actions baut Docker Image
|
||||
2. **Image wird gepusht** → Gitea Container Registry (`git.purepixel.ch`)
|
||||
3. **Watchtower (in Portainer)** → prüft alle 60s auf neue Images und startet Container neu
|
||||
|
||||
---
|
||||
|
||||
## Dateien
|
||||
## Voraussetzungen
|
||||
|
||||
| Datei | Beschreibung |
|
||||
|-------|-------------|
|
||||
| `lageplan-web-v1.0.0.tar` | Docker Image (~92 MB) |
|
||||
| `portainer-stack.yml` | Stack YAML für Portainer |
|
||||
| `.env.example` | Environment Variables Vorlage |
|
||||
- Gitea läuft mit Container Registry aktiviert
|
||||
- Gitea Actions Runner ist registriert (`deploy/docker-compose.runner.yml`)
|
||||
- Portainer Stack ist deployed mit korrekten Environment-Variablen
|
||||
|
||||
---
|
||||
|
||||
## Schritt 1: Image auf Server laden
|
||||
## Schritt 1: Gitea Container Registry aktivieren
|
||||
|
||||
```bash
|
||||
# Kopieren
|
||||
scp lageplan-web-v1.0.0.tar user@server:/tmp/
|
||||
In Gitea:
|
||||
1. **Admin-Konsole** → **Konfiguration** → **Pakete**
|
||||
2. **Container Registry** auf `Aktiviert` setzen
|
||||
3. Speichern
|
||||
|
||||
# Auf dem Server laden
|
||||
docker load -i /tmp/lageplan-web-v1.0.0.tar
|
||||
Oder direkt in der `app.ini`:
|
||||
```ini
|
||||
[packages]
|
||||
ENABLED = true
|
||||
|
||||
# Prüfen
|
||||
docker images | grep lageplan
|
||||
[package.container_registry]
|
||||
ENABLED = true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Schritt 2: Stack in Portainer erstellen
|
||||
## Schritt 2: Gitea Actions Runner registrieren
|
||||
|
||||
1. In Gitea: **Admin** → **Actions** → **Runners** → **Neuen Runner erstellen**
|
||||
2. Token kopieren
|
||||
3. In Portainer: Stack `gitea-runner` deployen mit [`deploy/docker-compose.runner.yml`](docker-compose.runner.yml)
|
||||
4. Environment Variable `RUNNER_TOKEN` = das kopierte Token
|
||||
|
||||
---
|
||||
|
||||
## Schritt 3: Gitea Access Token erstellen
|
||||
|
||||
Das CI/CD Workflow braucht einen Token um Images in die Registry zu pushen:
|
||||
|
||||
1. Gitea → **Einstellungen** → **Anwendungen** → **Token erstellen**
|
||||
2. Name: `registry-push`
|
||||
3. Berechtigungen: `package:write` (mindestens)
|
||||
4. Token kopieren und als **Repository Secret** hinterlegen:
|
||||
- Repo → **Einstellungen** → **Secrets** → **Neues Secret**
|
||||
- Name: `GITEA_TOKEN`
|
||||
- Wert: das kopierte Token
|
||||
|
||||
---
|
||||
|
||||
## Schritt 4: Portainer Stack deployen
|
||||
|
||||
1. **Portainer** → `Stacks` → `+ Add stack`
|
||||
2. **Name**: `lageplan`
|
||||
3. **Web editor**: Inhalt von `portainer-stack.yml` einfügen
|
||||
4. **Environment variables** setzen:
|
||||
3. **Build method**: `Repository`
|
||||
4. **Git-URL**: `https://git.purepixel.ch/adminpepe/Lageplan.git`
|
||||
5. **Compose path**: `docker-compose.portainer.yml`
|
||||
6. **GitOps updates**: ✅ Aktivieren
|
||||
7. **Mechanism**: `Webhook`
|
||||
8. **Webhook URL kopieren** (für später)
|
||||
|
||||
| Variable | Wert |
|
||||
|----------|------|
|
||||
| `POSTGRES_USER` | `lageplan` |
|
||||
| `POSTGRES_PASSWORD` | *(sicheres Passwort)* |
|
||||
| `POSTGRES_DB` | `lageplan` |
|
||||
| `MINIO_ROOT_USER` | `minioadmin` |
|
||||
| `MINIO_ROOT_PASSWORD` | *(sicheres Passwort)* |
|
||||
| `MINIO_BUCKET` | `lageplan-icons` |
|
||||
| `WEB_PORT` | `3000` |
|
||||
| `NEXTAUTH_URL` | `http://SERVER_IP:3000` |
|
||||
| `NEXTAUTH_SECRET` | *(langer zufälliger String)* |
|
||||
### Environment Variables setzen:
|
||||
|
||||
> **Tipp**: Secret generieren: `openssl rand -base64 32`
|
||||
| Variable | Wert | Beschreibung |
|
||||
|----------|------|-------------|
|
||||
| `POSTGRES_USER` | `lageplan` | DB User |
|
||||
| `POSTGRES_PASSWORD` | *(sicheres Passwort)* | DB Passwort |
|
||||
| `POSTGRES_DB` | `lageplan` | DB Name |
|
||||
| `NEXTAUTH_URL` | `https://lageplan.ch` | Deine Domain |
|
||||
| `NEXTAUTH_SECRET` | *(openssl rand -base64 32)* | Auth Secret |
|
||||
| `MINIO_ROOT_USER` | `minioadmin` | MinIO User |
|
||||
| `MINIO_ROOT_PASSWORD` | *(sicheres Passwort)* | MinIO Passwort |
|
||||
| `MINIO_BUCKET` | `lageplan-icons` | Bucket Name |
|
||||
| `MINIO_PUBLIC_URL` | `https://s3.deinedomain.ch` | MinIO externe URL |
|
||||
| `GITEA_REGISTRY_USER` | `adminpepe` | Gitea User für Watchtower |
|
||||
| `GITEA_REGISTRY_PASS` | *(Token oder Passwort)* | Gitea Passwort/Token |
|
||||
|
||||
5. **Deploy the stack**
|
||||
9. **Deploy the stack**
|
||||
|
||||
---
|
||||
|
||||
## Schritt 3: Datenbank initialisieren (einmalig)
|
||||
## Schritt 5: Webhook in Gitea eintragen
|
||||
|
||||
In Portainer: Container `web` → Console → `/bin/sh`:
|
||||
Damit Portainer bei jedem Push automatisch neu deployed:
|
||||
|
||||
```bash
|
||||
npx prisma db push
|
||||
npx prisma db seed
|
||||
```
|
||||
|
||||
Oder per SSH:
|
||||
|
||||
```bash
|
||||
docker exec -it lageplan-web-1 npx prisma db push
|
||||
docker exec -it lageplan-web-1 npx prisma db seed
|
||||
```
|
||||
1. Gitea Repo → **Einstellungen** → **Webhooks** → **Neuer Webhook** → `Gitea`
|
||||
2. **Ziel-URL**: Die kopierte Portainer Webhook URL
|
||||
3. **HTTP-Methode**: `POST`
|
||||
4. **Trigger**: Nur `Push events` (oder auch `Branch filter: main`)
|
||||
5. **Webhook aktivieren** → Hinzufügen
|
||||
|
||||
---
|
||||
|
||||
## Schritt 4: Zugriff
|
||||
## Schritt 6: Erstes Deployment testen
|
||||
|
||||
- **Web App**: `http://SERVER_IP:3000`
|
||||
- **Login**: `admin@lageplan.local` / `admin123`
|
||||
1. Lokal einen Push auf `main` machen:
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "Test CI/CD"
|
||||
git push origin main
|
||||
```
|
||||
2. In Gitea: **Actions** Tab → Build-Job sollte laufen
|
||||
3. Wenn grün → Image wurde in Registry gepusht
|
||||
4. Watchtower (in Portainer) holt neues Image innerhalb von 60s
|
||||
5. App ist unter `NEXTAUTH_URL` erreichbar
|
||||
|
||||
---
|
||||
|
||||
## Update
|
||||
## Troubleshooting
|
||||
|
||||
### Gitea Actions startet nicht
|
||||
- Prüfen ob Runner registriert ist: Gitea → Admin → Actions → Runners
|
||||
- Runner muss `Idle` oder `Active` zeigen
|
||||
|
||||
### Image Push schlägt fehl (401 Unauthorized)
|
||||
- `GITEA_TOKEN` Secret im Repo korrekt hinterlegt?
|
||||
- Token hat Berechtigung `package:write`?
|
||||
- Registry in Gitea aktiviert?
|
||||
|
||||
### Watchtower zieht kein neues Image
|
||||
- `GITEA_REGISTRY_USER` und `GITEA_REGISTRY_PASS` in Portainer gesetzt?
|
||||
- Image-Name in `docker-compose.portainer.yml` korrekt?
|
||||
- Watchtower Logs prüfen: Portainer → Container `watchtower` → Logs
|
||||
|
||||
### App startet nicht / DB-Fehler
|
||||
- Environment Variables in Portainer korrekt?
|
||||
- `DATABASE_URL` wird automatisch gebaut, nur `POSTGRES_*` muss gesetzt werden
|
||||
- Bei erstem Start: Prisma Migrations/Seed im Web-Container ausführen:
|
||||
```bash
|
||||
docker exec -it lageplan-web-1 npx prisma db push
|
||||
docker exec -it lageplan-web-1 npx prisma db seed
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Manuelles Update (falls nötig)
|
||||
|
||||
Wenn Watchtower mal nicht greift:
|
||||
```bash
|
||||
# Lokal: neues Image bauen + exportieren
|
||||
docker compose build web
|
||||
docker tag lageplan-web:latest lageplan-web:v1.1.0
|
||||
docker save lageplan-web:v1.1.0 -o deploy/lageplan-web-v1.1.0.tar
|
||||
|
||||
# Server: laden
|
||||
docker load -i lageplan-web-v1.1.0.tar
|
||||
|
||||
# Portainer: Stack → Editor → Image-Tag ändern → Update the stack
|
||||
# Auf dem Portainer-Host
|
||||
docker pull git.purepixel.ch/adminpepe/lageplan:latest
|
||||
docker compose -f docker-compose.portainer.yml up -d web
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
23
deploy/docker-compose.runner.yml
Normal file
@@ -0,0 +1,23 @@
|
||||
##############################################
|
||||
# Gitea Actions Runner — Portainer Stack
|
||||
#
|
||||
# In Portainer deployen:
|
||||
# 1. Stacks → Add Stack → "gitea-runner"
|
||||
# 2. Diese YAML einfügen
|
||||
# 3. Deploy
|
||||
##############################################
|
||||
|
||||
services:
|
||||
runner:
|
||||
image: gitea/act_runner:latest
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
GITEA_INSTANCE_URL: https://git.purepixel.ch
|
||||
GITEA_RUNNER_REGISTRATION_TOKEN: ${RUNNER_TOKEN}
|
||||
GITEA_RUNNER_NAME: lageplan-runner
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- runner_data:/data
|
||||
|
||||
volumes:
|
||||
runner_data:
|
||||
@@ -7,3 +7,8 @@ MINIO_BUCKET=lageplan-icons
|
||||
WEB_PORT=3000
|
||||
NEXTAUTH_URL=http://SERVER_IP:3000
|
||||
NEXTAUTH_SECRET=HIER_LANGEN_ZUFAELLIGEN_STRING_GENERIEREN
|
||||
MINIO_PUBLIC_URL=http://SERVER_IP:9000
|
||||
|
||||
# Gitea Registry Auth für Watchtower (automatische Image-Updates)
|
||||
GITEA_REGISTRY_USER=adminpepe
|
||||
GITEA_REGISTRY_PASS=HIER_GITEA_TOKEN_ODER_PASSWORT_SETZEN
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
##############################################
|
||||
# Gitea — Lightweight Git Server
|
||||
# Gitea — Lightweight Git Server + Container Registry
|
||||
#
|
||||
# Verwendung in Portainer:
|
||||
# 1. Stacks → Add Stack → "Gitea"
|
||||
@@ -12,6 +12,10 @@
|
||||
# 3. Repository "lageplan" erstellen
|
||||
# 4. Vom PC aus: git init → git remote add origin → git push
|
||||
#
|
||||
# Container Registry aktivieren:
|
||||
# 1. Gitea Admin → Konfiguration → Pakete → Container Registry aktivieren
|
||||
# 2. Oder app.ini: [packages] ENABLED = true
|
||||
#
|
||||
# Daten werden in gitea_data persistiert.
|
||||
##############################################
|
||||
|
||||
@@ -27,6 +31,9 @@ services:
|
||||
- GITEA__server__ROOT_URL=https://git.purepixel.ch
|
||||
- GITEA__server__HTTP_PORT=3000
|
||||
- GITEA__server__LFS_START_SERVER=true
|
||||
# Container Registry aktivieren
|
||||
- GITEA__packages__ENABLED=true
|
||||
- GITEA__package__container_registry__ENABLED=true
|
||||
volumes:
|
||||
- gitea_data:/data
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
@@ -43,4 +50,3 @@ volumes:
|
||||
networks:
|
||||
lageplan_lageplan-net:
|
||||
external: true
|
||||
|
||||
|
||||
@@ -1,21 +1,28 @@
|
||||
##############################################
|
||||
# Lageplan — Portainer Stack Configuration
|
||||
# Lageplan — Portainer Stack (Watchtower Auto-Update)
|
||||
#
|
||||
# Verwendung in Portainer:
|
||||
# 1. Stacks → Add Stack
|
||||
# 2. "Upload" oder diesen Inhalt einfügen
|
||||
# 3. Environment-Variablen setzen (siehe unten)
|
||||
# 4. Deploy
|
||||
# Setup in Portainer:
|
||||
# 1. Stacks → Add Stack → "Repository"
|
||||
# 2. Git-URL: https://git.purepixel.ch/adminpepe/Lageplan.git
|
||||
# 3. Compose-Pfad: docker-compose.portainer.yml
|
||||
# 4. "GitOps updates" aktivieren
|
||||
# 5. Environment-Variablen setzen (siehe unten)
|
||||
# 6. Deploy
|
||||
#
|
||||
# Danach: Push auf main → Gitea Actions baut Image →
|
||||
# Watchtower erkennt neues Image und startet Container neu
|
||||
#
|
||||
# Benötigte Environment-Variablen:
|
||||
# POSTGRES_USER (default: lageplan)
|
||||
# POSTGRES_PASSWORD (ÄNDERN!)
|
||||
# POSTGRES_DB (default: lageplan)
|
||||
# NEXTAUTH_SECRET (ÄNDERN! — z.B. openssl rand -base64 32)
|
||||
# NEXTAUTH_URL (z.B. https://lageplan.example.com)
|
||||
# NEXTAUTH_URL (z.B. https://lageplan.ch)
|
||||
# MINIO_ROOT_USER (default: minioadmin)
|
||||
# MINIO_ROOT_PASSWORD (ÄNDERN!)
|
||||
# MINIO_PUBLIC_URL (z.B. https://s3.example.com)
|
||||
# GITEA_REGISTRY_USER (für Watchtower Registry-Auth)
|
||||
# GITEA_REGISTRY_PASS (für Watchtower Registry-Auth)
|
||||
##############################################
|
||||
|
||||
services:
|
||||
@@ -76,8 +83,9 @@ services:
|
||||
- lageplan
|
||||
|
||||
# ─── Lageplan Web App ──────────────────────
|
||||
# Image kommt aus Gitea Container Registry (gebaut via Gitea Actions)
|
||||
web:
|
||||
image: 192.168.1.183:3100/adminpepe/lageplan:latest
|
||||
image: git.purepixel.ch/adminpepe/lageplan:latest
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
DATABASE_URL: postgresql://${POSTGRES_USER:-lageplan}:${POSTGRES_PASSWORD:-lageplan_secret}@db:5432/${POSTGRES_DB:-lageplan}
|
||||
@@ -99,6 +107,25 @@ services:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- lageplan
|
||||
labels:
|
||||
- "com.centurylinklabs.watchtower.enable=true"
|
||||
|
||||
# ─── Watchtower (Auto-Restart bei neuen Images) ─
|
||||
# Überwacht nur Container mit Label com.centurylinklabs.watchtower.enable=true
|
||||
watchtower:
|
||||
image: containrrr/watchtower
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
environment:
|
||||
WATCHTOWER_POLL_INTERVAL: 60
|
||||
WATCHTOWER_CLEANUP: "true"
|
||||
WATCHTOWER_LABEL_ENABLE: "true"
|
||||
# Gitea Registry Auth
|
||||
REPO_USER: ${GITEA_REGISTRY_USER}
|
||||
REPO_PASS: ${GITEA_REGISTRY_PASS}
|
||||
networks:
|
||||
- lageplan
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
|
||||
247
docs/backup-und-seeding.md
Normal file
@@ -0,0 +1,247 @@
|
||||
# Backup & Seeding — Betriebsnotiz Lageplan
|
||||
|
||||
> Stand: 2026-05-20
|
||||
> Autor: Automatisch generiert nach Produktionsvorfall
|
||||
|
||||
## Inhalt
|
||||
|
||||
1. [Wichtige Regeln](#wichtige-regeln)
|
||||
2. [Backup-Strategie](#backup-strategie)
|
||||
3. [Seed-Skripte](#seed-skripte)
|
||||
4. [Post-Deploy Prüfung](#post-deploy-prüfung)
|
||||
5. [Notfall-Recovery](#notfall-recovery)
|
||||
6. [Docker-Build Hinweise](#docker-build-hinweise)
|
||||
|
||||
---
|
||||
|
||||
## Wichtige Regeln
|
||||
|
||||
### Nie löschen
|
||||
|
||||
- **Keine** `deleteMany()`, `DELETE FROM`, `TRUNCATE` oder Cascade-Resets in Production
|
||||
- **Nie** direkt in `icon_assets`, `icon_categories`, `tenant_symbols`, `features`, `projects` löschen
|
||||
- Alle Seed-Skripte müssen **idempotent** sein (`upsert` statt `delete` + `create`)
|
||||
- Vor jedem Seed/Repair in Production: **Databasus-Backup erstellen**
|
||||
|
||||
### Databasus Backup
|
||||
|
||||
- Databasus ist als GUI-Backup eingerichtet
|
||||
- Backups werden gespeichert unter: `/volume1/docker/backups/databasus`
|
||||
- **Nie** das Docker-Volume unter `/volume1/@docker` als einzige Backup-Strategie verwenden
|
||||
|
||||
### Container-Informationen
|
||||
|
||||
| Service | Container-Name |
|
||||
|---------|---------------|
|
||||
| PostgreSQL DB | `lageplan-db-1` |
|
||||
| Web App | `lageplan-web-1` |
|
||||
| DB-Name | `lageplan` |
|
||||
| DB-User | `lageplan` |
|
||||
|
||||
---
|
||||
|
||||
## Backup-Strategie
|
||||
|
||||
### Automatisch (Databasus)
|
||||
|
||||
1. Databasus GUI öffnen
|
||||
2. Datenbank `lageplan` auswählen
|
||||
3. "Backup Now" klicken
|
||||
4. Backup wird unter `/volume1/docker/backups/databasus` abgelegt
|
||||
|
||||
### Manuell (pg_dump)
|
||||
|
||||
```bash
|
||||
# In der NAS-Shell (oder im DB-Container)
|
||||
docker exec lageplan-db-1 pg_dump -U lageplan -d lageplan \
|
||||
--no-owner --no-privileges \
|
||||
> /volume1/docker/backups/databasus/lageplan-manual-$(date +%Y%m%d-%H%M%S).sql
|
||||
```
|
||||
|
||||
### Wiederherstellen
|
||||
|
||||
```bash
|
||||
# 1. Backup-Datei prüfen
|
||||
ls -la /volume1/docker/backups/databasus/
|
||||
|
||||
# 2. App stoppen
|
||||
docker stop lageplan-web-1
|
||||
|
||||
# 3. DB zurückspielen (ACHTUNG: überschreibt aktuelle Daten!)
|
||||
docker exec -i lageplan-db-1 psql -U lageplan -d lageplan \
|
||||
< /volume1/docker/backups/databasus/lageplan-backup-YYYYmmdd-HHMMSS.sql
|
||||
|
||||
# 4. App starten
|
||||
docker start lageplan-web-1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Seed-Skripte
|
||||
|
||||
### Übersicht
|
||||
|
||||
| Skript | Zweck | Sicherheit | Aufruf |
|
||||
|--------|-------|-----------|--------|
|
||||
| `prisma/seed.js` | Vollständiger Seed (Tenant, Users, Icons, HoseTypes, Demo-Projekt) | ✅ Idempotent, nur `upsert` | `npm run db:seed` oder `node prisma/seed.js` |
|
||||
| `prisma/seed-icons-only.js` | Nur Icons aus `public/signaturen/*.svg` | ✅ Idempotent, nur `upsert` | `npm run db:seed:icons` oder `node prisma/seed-icons-only.js` |
|
||||
| `prisma/seed.ts` | Legacy-TypeScript-Seed (korrigiert, aber nicht der Primary) | ✅ Korrigiert | Nicht direkt aufrufen |
|
||||
| `prisma/seed-symbol-templates.ts` | Erstellt `SymbolTemplate`-Einträge | ✅ Nur `findFirst` + `create` (skip if exists) | `npx tsx prisma/seed-symbol-templates.ts` |
|
||||
| `prisma/migrate-tenant-symbols.ts` | Migriert bestehende `TenantSymbol` zu neuem Schema | ✅ Nur `findFirst`, `create`, `update` | `npx tsx prisma/migrate-tenant-symbols.ts` |
|
||||
| `prisma/recover-symbols.js` | Recovery: Icons + TenantSymbols wiederherstellen | ✅ Dry-Run/Apply Modus | `npm run recover:symbols:dry-run` / `npm run recover:symbols:apply` |
|
||||
| `prisma/repair-features.js` | Repariert kaputte `iconId`-Referenzen in Features | ✅ Dry-Run/Apply Modus + Backup | `npm run repair:features:dry-run` / `npm run repair:features:apply` |
|
||||
| `prisma/migrate.js` | DB-Migrationen (Raw SQL, idempotent) | ✅ Keine Deletes auf User-Daten | Wird automatisch beim Container-Start ausgeführt |
|
||||
|
||||
### Empfohlene Seed-Strategie
|
||||
|
||||
1. **Neue Umgebung** (erstmalig):
|
||||
```bash
|
||||
node prisma/seed.js
|
||||
```
|
||||
|
||||
2. **Nur Icons aktualisieren** (z.B. nach SVG-Update):
|
||||
```bash
|
||||
node prisma/seed-icons-only.js
|
||||
```
|
||||
|
||||
3. **Recovery nach Icon-Verlust**:
|
||||
```bash
|
||||
# 1. Erst Databasus-Backup erstellen!
|
||||
# 2. Dann:
|
||||
node prisma/recover-symbols.js --dry-run # Analyse
|
||||
node prisma/recover-symbols.js --apply # Anwenden
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Post-Deploy Prüfung
|
||||
|
||||
### 1. SVG-Dateien im Container
|
||||
|
||||
```bash
|
||||
docker exec -it lageplan-web-1 sh -c 'find /app/public/signaturen -type f -name "*.svg" | wc -l'
|
||||
```
|
||||
**Erwartung:** ca. 117
|
||||
|
||||
### 2. Icons seeden
|
||||
|
||||
```bash
|
||||
docker exec -it lageplan-web-1 node prisma/seed-icons-only.js
|
||||
```
|
||||
**Erwartung:**
|
||||
```
|
||||
✅ 10 icon categories upserted
|
||||
✅ FKS Signaturen: X created, Y updated (117 total SVGs)
|
||||
```
|
||||
|
||||
### 3. Datenbank-Prüfung
|
||||
|
||||
```bash
|
||||
docker exec -it lageplan-db-1 psql -U lageplan -d lageplan -c "
|
||||
SELECT 'icon_categories' AS table_name, COUNT(*) AS count FROM icon_categories
|
||||
UNION ALL
|
||||
SELECT 'icon_assets' AS table_name, COUNT(*) AS count FROM icon_assets
|
||||
UNION ALL
|
||||
SELECT 'tenant_symbols' AS table_name, COUNT(*) AS count FROM tenant_symbols
|
||||
UNION ALL
|
||||
SELECT 'features' AS table_name, COUNT(*) AS count FROM features
|
||||
UNION ALL
|
||||
SELECT 'projects' AS table_name, COUNT(*) AS count FROM projects;
|
||||
"
|
||||
```
|
||||
|
||||
### 4. Logs prüfen
|
||||
|
||||
```bash
|
||||
docker logs --tail=100 lageplan-web-1
|
||||
```
|
||||
**Keine** der folgenden Fehler sollen auftreten:
|
||||
- `404` für `/signaturen/*.svg`
|
||||
- `Prisma error` wegen `tenant_symbols.categoryId`
|
||||
- `Seed failed`
|
||||
|
||||
---
|
||||
|
||||
## Notfall-Recovery
|
||||
|
||||
### Szenario: Symbole sind verschwunden (404)
|
||||
|
||||
**Ursache:** `IconAsset`-Einträge wurden gelöscht (z.B. durch altes Seed-Skript mit `deleteMany`)
|
||||
|
||||
**Lösung:**
|
||||
|
||||
```bash
|
||||
# 1. Backup erstellen (Databasus GUI oder pg_dump)
|
||||
|
||||
# 2. Container-Status prüfen
|
||||
docker exec -it lageplan-web-1 sh -c 'ls -la /app/public/signaturen/ | head -5'
|
||||
# → Sollte SVG-Dateien anzeigen
|
||||
|
||||
# 3. Icons neu seeden (idempotent, sicher)
|
||||
docker exec -it lageplan-web-1 node prisma/seed-icons-only.js
|
||||
|
||||
# 4. Tenant-Symbols wiederherstellen (falls auch gelöscht)
|
||||
docker exec -it lageplan-web-1 node prisma/recover-symbols.js --dry-run
|
||||
docker exec -it lageplan-web-1 node prisma/recover-symbols.js --apply
|
||||
|
||||
# 5. Prüfen
|
||||
docker exec -it lageplan-web-1 node -e "
|
||||
const {PrismaClient} = require('@prisma/client');
|
||||
const p = new PrismaClient();
|
||||
p.iconAsset.count({where:{isSystem:true}}).then(c=>console.log('System-Icons:',c));
|
||||
p.tenantSymbol.count().then(c=>console.log('TenantSymbols:',c));
|
||||
"
|
||||
```
|
||||
|
||||
### Szenario: Features haben kaputte iconId-Referenzen
|
||||
|
||||
**Ursache:** Alte `iconId`-UUIDs in `Feature.properties` zeigen auf gelöschte `IconAsset`s
|
||||
|
||||
**Lösung:**
|
||||
|
||||
```bash
|
||||
# 1. Dry-Run: Analyse
|
||||
docker exec -it lageplan-web-1 node prisma/repair-features.js --dry-run
|
||||
|
||||
# 2. Apply: Reparatur (erstellt automatisch JSON-Backup)
|
||||
docker exec -it lageplan-web-1 node prisma/repair-features.js --apply
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Docker-Build Hinweise
|
||||
|
||||
### public/signaturen muss im Image sein
|
||||
|
||||
- `public/signaturen/*.svg` muss im Git-Index sein (`.gitignore` erlaubt es explizit)
|
||||
- `.dockerignore` darf `public/signaturen/` **nicht** ausschliessen
|
||||
- `Dockerfile` kopiert `public/` in die Runtime-Stage:
|
||||
```dockerfile
|
||||
COPY --from=builder /app/public ./public
|
||||
```
|
||||
|
||||
### Next.js standalone
|
||||
|
||||
- `next.config.js` hat `output: 'standalone'`
|
||||
- Der Build erzeugt `.next/standalone/` (minimaler Server)
|
||||
- `public/` wird explizit in die Runtime-Stage kopiert
|
||||
|
||||
### Multi-Stage Build
|
||||
|
||||
1. **deps**: `npm ci` (nur Dependencies)
|
||||
2. **builder**: `npm run build` (inkl. Prisma Generate)
|
||||
3. **runner**: Runtime-Image mit `public/`, `.next/standalone/`, Prisma-Client
|
||||
|
||||
---
|
||||
|
||||
## Änderungshistorie
|
||||
|
||||
| Datum | Änderung |
|
||||
|-------|----------|
|
||||
| 2026-05-20 | `.gitignore` korrigiert: `Signaturen/` → `/Signaturen/` (Root-only), `public/signaturen/*.svg` erlaubt |
|
||||
| 2026-05-20 | 117 SVG-Dateien force-added zum Git-Index |
|
||||
| 2026-05-20 | `.dockerignore` korrigiert: `Signaturen` → `/Signaturen/` |
|
||||
| 2026-05-20 | `package.json`: `db:seed` zeigt jetzt auf `prisma/seed.js` statt broken `seed.ts` |
|
||||
| 2026-05-20 | `seed.ts` korrigiert: Role-Enums + stabile IDs für `iconCategory.upsert` |
|
||||
| 2026-05-20 | Alle Seed-Skripte auf `deleteMany`-Freiheit geprüft |
|
||||
| 2026-05-20 | Dokumentation `docs/backup-und-seeding.md` erstellt |
|
||||
273
docs/roadmap-feedback-fabian.md
Normal file
@@ -0,0 +1,273 @@
|
||||
# Roadmap — Feedback Fabian (Mai 2026)
|
||||
|
||||
> **Quelle**: User-Feedback von Fabian, Führungsoffizier / Übungsleiter Feuerwehr.
|
||||
> **Erhalten**: 20.05.2026
|
||||
> **Status**: Geplant, noch nicht umgesetzt.
|
||||
|
||||
Dieses Dokument ist die strukturierte Roadmap aus Fabians Feedback. Jede KI / jeder Entwickler der an Lageplan arbeitet, soll diese Datei vor Beginn lesen, um Kontext und Priorisierung zu kennen.
|
||||
|
||||
---
|
||||
|
||||
## Originalfeedback (Zusammenfassung)
|
||||
|
||||
Fabian sucht eine Lösung um **Einsätze und Übungen einfach zu skizzieren und zu krokieren**. Lobt die App, gibt aber konkrete Verbesserungsvorschläge aus Anwendersicht:
|
||||
|
||||
1. **Einsatz vs. Übung unterscheiden** — bei Übungen kein Journal nötig, dafür Übungsziele/Auswertung
|
||||
2. **Symbol-Bibliothek erweitern** — Warteraum, Rettungsachse, taktische Zeichen
|
||||
3. **Symbol-Schönheitsfehler** — Treppe/Eingang mit Umriss, Absperrung
|
||||
4. **Stockwerke/Geschosse** — eigene Werte eintragen
|
||||
5. **Symbol-Kategorien aufräumen** — Motorspritze unter Organisation statt Geräte; Hydrant/Leitern uneinheitlich
|
||||
6. **Linien mit Typ** — nach Zeichnen wählen: Rettungsachse (gestrichelt + R), Leitung (blau), Schlauch, etc.
|
||||
7. **Multi-User Live** — eine Person zeichnet Karte, andere schreibt Journal gleichzeitig
|
||||
8. **Rapport-/Lageansicht** — separate Sicht mit Pendenzen, aktueller Stand, wichtige Punkte für Führungsunterstützung (FU), darstellbar auf grossem Bildschirm; nicht alle Journaleinträge sichtbar für alle
|
||||
|
||||
---
|
||||
|
||||
## Phasen-Plan
|
||||
|
||||
### Phase 1 — Symbol-Architektur Redesign (3-4 Wochen) ⭐⭐
|
||||
|
||||
**Strategischer Umbau** statt nur Kategorien aufräumen. Begründung:
|
||||
- Fabians Feedback zeigt, dass die aktuelle Kategorisierung uneinheitlich ist
|
||||
- Symbol-Bibliothek ist zu starr — andere Anwender (THW, Sanität, ausländische Wehren) brauchen andere Symbole
|
||||
- Mandantenfähigkeit ist zentrales Versprechen → muss auch für Symbole konsequent durchgezogen werden
|
||||
|
||||
#### 1.1 Neue Symbol-Architektur: Template-Import + 100% mandantenspezifisch
|
||||
|
||||
**Konzept**: Mandant startet mit leerer Bibliothek, importiert beim Onboarding (oder jederzeit) **kuratierte Vorlagen-Pakete** (Feuerwehr CH, THW, Sanität…). Importierte Symbole werden vollständig eigene Mandanten-Daten — umbenennbar, löschbar, kategorisierbar, ergänzbar.
|
||||
|
||||
**Datenmodell**:
|
||||
```
|
||||
TenantCategory (per-tenant, frei definierbar)
|
||||
- id, tenantId, name, sortOrder, icon
|
||||
|
||||
TenantSymbol (per-tenant, ehemals "Meine Symbole")
|
||||
- id, tenantId, categoryId → TenantCategory
|
||||
- name, svgPath, sortOrder, customName
|
||||
|
||||
SymbolTemplate (global, read-only)
|
||||
- id, packageId ("feuerwehr-ch", "thw", "sanitaet")
|
||||
- categoryName, name, svgPath, tags
|
||||
```
|
||||
|
||||
**Tasks**:
|
||||
- [x] Schema-Migration: `TenantCategory` neu, `TenantSymbol.categoryId` ergänzen, `SymbolTemplate` erstellen
|
||||
- [x] Migration SQL + idempotente Raw-SQL-Migration (`prisma/migrate.js`)
|
||||
- [x] Seed-Skript: `public/signaturen/*.svg` → `SymbolTemplate`
|
||||
- [x] Migration bestehender Tenants: `TenantSymbol.name`, `svgPath`, `categoryId` befüllen
|
||||
- [ ] **Auto-Import des `feuerwehr-ch` Pakets beim ersten Login** (oder bei leerer Bibliothek)
|
||||
- [ ] API: CRUD für `TenantCategory` (`GET/POST/PATCH/DELETE /api/tenant/categories`)
|
||||
- [ ] API: `GET /api/templates` — listet verfügbare Pakete
|
||||
- [ ] API: `POST /api/templates/import` — importiert ausgewählte Symbole als TenantSymbols
|
||||
- [ ] API: `TenantSymbol` erweitern — Upload-Endpoint, Kategorie-Zuordnung, gruppierte Liste
|
||||
- **Files**: `prisma/schema.prisma`, `src/app/api/tenant/categories/`, `src/app/api/tenant/symbols/`, `src/app/api/templates/`
|
||||
|
||||
#### 1.2 UX: Symbol-Manager im Admin
|
||||
|
||||
**Sidebar / Symbol-Verwaltung**:
|
||||
```
|
||||
┌─ Meine Symbole ─────────────┐
|
||||
│ ┌ Fahrzeuge ─────────┐ │
|
||||
│ │ 🚒 TLF │ │
|
||||
│ │ 🚒 RW │ │
|
||||
│ │ + Symbol │ │
|
||||
│ └────────────────────┘ │
|
||||
│ ┌ Wasser ────────────┐ │
|
||||
│ │ 🟦 Hydrant │ │
|
||||
│ └────────────────────┘ │
|
||||
│ [+ Kategorie] │
|
||||
│ [📦 Vorlagen importieren] │
|
||||
└─────────────────────────────┘
|
||||
```
|
||||
|
||||
**Tasks**:
|
||||
- [ ] Admin-Tab: Kategorien anlegen/umbenennen/sortieren (Drag & Drop)
|
||||
- [ ] Symbole pro Kategorie verwalten (Drag & Drop zwischen Kategorien)
|
||||
- [ ] Eigene SVG-Uploads direkt einer Kategorie zuordnen
|
||||
- [ ] Import-Dialog: Pakete-Auswahl mit Vorschau, granulare Symbol-Auswahl
|
||||
- [ ] Mehrfach-Import desselben Symbols erlaubt (z.B. "TLF rot" + "TLF blau" auf gleicher SVG-Basis)
|
||||
- **Files**: `src/components/admin/icons-tab.tsx` (umbauen), neuer `import-templates-dialog.tsx`
|
||||
|
||||
#### 1.3 Vorlagen-Pakete kuratieren
|
||||
|
||||
Aus dem aktuellen Symbol-Bestand werden die ersten Pakete:
|
||||
|
||||
- [ ] 📦 **Feuerwehr Schweiz** — taktische Zeichen CH (aktueller Bestand, sauber kategorisiert)
|
||||
- [ ] 📦 **Sanität / Rettungsdienst** — falls Symbole vorhanden, sonst Phase 2
|
||||
- [ ] 📦 **Polizei / Verkehr** — als Stub für später
|
||||
- [ ] Innerhalb der Pakete: **fehlende taktische Zeichen ergänzen**:
|
||||
- Warteraum
|
||||
- Rettungsachse
|
||||
- Sammelplatz
|
||||
- Verletztennest / Eingang Verletzter
|
||||
- Einsatzleitung (EL) / Kommandoposten
|
||||
- Bereitstellungsraum
|
||||
- [ ] **Symbol-Schönheitsfehler im Paket** beheben:
|
||||
- Treppe — Umriss entfernen
|
||||
- Eingang — Umriss entfernen
|
||||
- Absperrung — Seitenlinien aufräumen
|
||||
- **Files**: `prisma/seed/symbol-templates.ts`, `public/icons/`
|
||||
|
||||
#### 1.4 Stockwerke/Geschosse editierbar
|
||||
|
||||
- [ ] Symbol-Property: `instanceLabel` (Freitext, pro Symbol-Instanz auf der Karte)
|
||||
- [ ] Bei Gebäude-Symbolen: optionales Textfeld für Geschosszahl (z.B. "EG+3")
|
||||
- [ ] Anzeige als Badge auf dem Symbol
|
||||
- [ ] Editierbar via Doppelklick oder Sidebar
|
||||
- **Files**: `src/types/`, `map-view.tsx` Symbol-Renderer, ggf. DrawFeature.properties erweitern
|
||||
|
||||
---
|
||||
|
||||
### Phase 1.5 — Quick Polish (parallel oder danach, 1 Woche) 🔥
|
||||
|
||||
Kleinkram der nicht in den Architektur-Umbau passt aber wichtig ist.
|
||||
|
||||
- [ ] Default-Linientyp / -farbe pro Mandant konfigurierbar
|
||||
- [ ] Symbol-Suche im Sidebar (Volltext über Name, Tags, Kategorie)
|
||||
- [ ] Häufig-benutzte Symbole oben anzeigen (Recent / Favoriten)
|
||||
|
||||
---
|
||||
|
||||
### Phase 2 — Übungsmodus (2-3 Wochen) ⭐
|
||||
|
||||
Neuer Projekt-Typ, eigene Logik.
|
||||
|
||||
#### 2.1 Projekt-Typ Auswahl
|
||||
- [ ] Bei "Neues Projekt": Auswahl `Einsatz | Übung`
|
||||
- [ ] DB-Schema: `Project.type: 'einsatz' | 'uebung'`
|
||||
- [ ] UI-Anpassung in `app/page.tsx`
|
||||
|
||||
#### 2.2 Übungs-Metadaten
|
||||
- [ ] Felder: Übungstitel, Datum, **Übungsziele (Liste)**
|
||||
- [ ] Übungsleiter, Teilnehmer (optional)
|
||||
- [ ] Eigene Sidebar-Sektion für Übungsdaten
|
||||
|
||||
#### 2.3 Journal ausblenden bei Übung
|
||||
- [ ] Bei `type === 'uebung'`: Journal-Tab → "Übungsauswertung"
|
||||
- [ ] Karte bleibt voll funktionsfähig
|
||||
- [ ] Krokierung kann **im Voraus** erstellt und mit Übungsleitern geteilt werden (bestehender Share-Link)
|
||||
|
||||
#### 2.4 Übungsauswertung
|
||||
- [ ] Checkliste **Übungsziele** mit Status: `erreicht | teilweise | nicht erreicht`
|
||||
- [ ] Notizen / Erkenntnisse pro Ziel
|
||||
- [ ] Gesamtbewertung / Erkenntnisse
|
||||
- [ ] **PDF-Export** für Debriefing (analog Rapport)
|
||||
- **Files**: neue Komponente `uebungsauswertung-tab.tsx`, neuer PDF-Renderer
|
||||
|
||||
---
|
||||
|
||||
### Phase 3 — Linien mit Typ (1 Woche) ⭐
|
||||
|
||||
Smart Lines mit vordefinierten Stilen.
|
||||
|
||||
#### 3.1 Linientypen definieren
|
||||
- [ ] **Schlauch** (default, aktuelle Linie)
|
||||
- [ ] **Rettungsachse** — gestrichelt, Label "R"
|
||||
- [ ] **Leitung** — blau
|
||||
- [ ] **Absperrung** — rot gestrichelt
|
||||
- [ ] **Frei** — Standard ohne Vorlage
|
||||
|
||||
#### 3.2 UX
|
||||
- [ ] Nach Zeichnen einer Linie: kleines Popup "Was ist das?"
|
||||
- [ ] Auswahl per Klick → Linie wird automatisch gestylt
|
||||
- [ ] In Sidebar pro Linie nachträglich änderbar (Dropdown)
|
||||
- [ ] Tastatur-Shortcut für Typ-Wechsel?
|
||||
|
||||
#### 3.3 Daten-Modell
|
||||
- [ ] `DrawFeature` erweitern: `lineCategory: 'hose' | 'rescue' | 'pipe' | 'barrier' | 'free'`
|
||||
- [ ] Default-Stile als Konstante (Farbe, Strich, Label)
|
||||
- **Files**: `src/types/`, `tool-store.ts`, `map-view.tsx`
|
||||
|
||||
---
|
||||
|
||||
### Phase 4 — Rapport-/Lageansicht (Führungsunterstützung) (2-3 Wochen) ⭐
|
||||
|
||||
Eigenes Modul, hoher Mehrwert für FU.
|
||||
|
||||
#### 4.1 Sichtbarkeits-Stufen pro Journaleintrag
|
||||
- [ ] DB: `JournalEntry.visibility: 'intern' | 'rapport' | 'public'`
|
||||
- [ ] UI: Dropdown beim Erstellen / Editieren
|
||||
- [ ] Migration: bestehende Einträge → `intern` (sicher)
|
||||
|
||||
#### 4.2 Rapport-Modus (Display)
|
||||
- [ ] Neuer Tab/Modus: **Rapport-Ansicht**
|
||||
- [ ] Sektionen:
|
||||
- **Aktuelle Lage** (Freitext, prominentes Feld)
|
||||
- **Pendenzen** (Liste mit Status: offen/erledigt)
|
||||
- **Wichtige Punkte / Befehle**
|
||||
- **Mittel / Personal** (aktueller Stand)
|
||||
- [ ] Grosse Schrift, kontrastreich (Beamer-tauglich)
|
||||
- [ ] Auto-Refresh via Socket.IO
|
||||
|
||||
#### 4.3 Display-Sharing
|
||||
- [ ] Read-only Token-Link (wie bestehende Rapport-URL)
|
||||
- [ ] Vollbild-Modus
|
||||
- [ ] Optional: Auswahl welche Sektionen sichtbar
|
||||
|
||||
#### 4.4 Berechtigungen
|
||||
- [ ] Rolle "Rapport-Viewer" — sieht nur Rapport, nicht Karte / Journal
|
||||
- [ ] Berechtigung pro Projekt vergebbar
|
||||
|
||||
---
|
||||
|
||||
### Phase 5 — Multi-User Live-Editing polish (optional, später)
|
||||
|
||||
Realtime-Sync läuft schon via Socket.IO — hier nur Verbesserungen.
|
||||
|
||||
- [ ] **Live-Cursor** anderer User auf Karte (mit Name)
|
||||
- [ ] **Presence-Anzeige** ("Fabian schreibt im Journal", "Pepe zeichnet")
|
||||
- [ ] **Soft-Locks** während Symbol bewegt wird
|
||||
- [ ] **Conflict Resolution** bei gleichzeitigem Edit testen
|
||||
|
||||
---
|
||||
|
||||
## Priorisierungs-Matrix
|
||||
|
||||
| Phase | Aufwand | Impact | Priorität | Empfohlene Reihenfolge |
|
||||
|-------|---------|--------|-----------|------------------------|
|
||||
| 1 — Symbol-Architektur Redesign | L (3-4 W) | Sehr Hoch | ⭐⭐ Höchste | **1.** |
|
||||
| 1.5 — Quick Polish | S | Mittel | 🔥 Hoch | parallel zu 1 |
|
||||
| 3 — Linien-Typen | M | Hoch | ⭐ Hoch | **2.** |
|
||||
| 4 — Rapport-Ansicht | L | Sehr Hoch (FU) | ⭐ Sehr Hoch | **3.** |
|
||||
| 2 — Übungsmodus | L | Sehr Hoch | ⭐ Sehr Hoch | **4.** |
|
||||
| 5 — Multi-User polish | M | Mittel | 📅 Mittel | später |
|
||||
|
||||
**Begründung der Reihenfolge**:
|
||||
1. **Phase 1 zuerst** — Architektur-Umbau, weil alles andere darauf aufbaut. Sobald TenantSymbols + Kategorien sauber strukturiert sind, sind 1.3 (fehlende Symbole) und 1.4 (Stockwerke) trivial. Auch Phase 2 (Übungsmodus) profitiert: Übungs-Pakete als eigene Templates möglich.
|
||||
2. **Phase 3 (Linien-Typen)** — kleine Erweiterung, hoher UX-Gewinn, unabhängig von Phase 1.
|
||||
3. **Phase 4 (Rapport-Ansicht)** — USP gegenüber anderen Krokier-Tools, FU-Funktion fehlt überall sonst.
|
||||
4. **Phase 2 (Übungsmodus)** — grosses Update; baut konzeptuell auf Phase 4 auf (Übungsauswertung ≈ Rapport).
|
||||
5. **Phase 5** — Polish, kein User wartet darauf.
|
||||
|
||||
**Risiko-Hinweis Phase 1**:
|
||||
- Schema-Migration von `Icon` (global) zu `SymbolTemplate` + Auto-Import muss **wasserdicht** sein, damit existierende Mandanten ihre Symbole nicht verlieren
|
||||
- Vor Deploy: vollständiges DB-Backup (PostgreSQL) und MinIO-Backup (Icon-Files)
|
||||
- Auf Staging testen falls möglich, sonst kleinen Test-Tenant zuerst migrieren
|
||||
|
||||
---
|
||||
|
||||
## Hinweise für Entwickler / KIs
|
||||
|
||||
- **Stack**: Next.js 15, React 19, MapLibre GL JS, Prisma, PostgreSQL, MinIO, Socket.IO, Zustand
|
||||
- **Sprache**: Schweizerdeutsch / Hochdeutsch (Code englisch, UI deutsch)
|
||||
- **Bei Symbol-Änderungen**: SVGs in `public/icons/` + Symbol-Definitionen + ggf. DB-Migration
|
||||
- **Bei Schema-Änderungen**: Prisma Migration erstellen + DB-Backup vor Deploy
|
||||
- **Vor Deploy**: Build testen (`npx next build`), commit + push, Portainer baut automatisch via Webhook
|
||||
- **Realtime**: bei DB-Änderungen, die alle User sehen müssen, Socket-Event triggern
|
||||
|
||||
---
|
||||
|
||||
## Status-Tracking
|
||||
|
||||
> Status pro Aufgabe oben in Checkboxen. Hier kurzer Überblick:
|
||||
|
||||
- [-] **Phase 1** — Sprint A erledigt (Schema, Migration, Seed). Sprint B–D offen.
|
||||
- [ ] **Phase 2** — nicht gestartet
|
||||
- [ ] **Phase 3** — nicht gestartet
|
||||
- [ ] **Phase 4** — nicht gestartet
|
||||
- [ ] **Phase 5** — nicht gestartet
|
||||
|
||||
---
|
||||
|
||||
**Letztes Update**: 2026-05-20
|
||||
**Verantwortlich**: Pepe (adminpepe)
|
||||
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "lageplan",
|
||||
"version": "1.3.1",
|
||||
"version": "1.3.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "lageplan",
|
||||
"version": "1.3.1",
|
||||
"version": "1.3.2",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@dnd-kit/core": "^6.1.0",
|
||||
|
||||
12
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "lageplan",
|
||||
"version": "1.3.1",
|
||||
"version": "1.4.0",
|
||||
"description": "Feuerwehr Lageplan - Krokier-App für Einsatzdokumentation",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
@@ -12,9 +12,15 @@
|
||||
"db:push": "prisma db push",
|
||||
"db:migrate": "prisma migrate dev",
|
||||
"db:migrate:prod": "prisma migrate deploy",
|
||||
"db:seed": "npx tsx prisma/seed.ts",
|
||||
"db:seed": "node prisma/seed.js",
|
||||
"db:studio": "prisma studio",
|
||||
"postinstall": "prisma generate"
|
||||
"postinstall": "prisma generate",
|
||||
"db:seed:icons": "node prisma/seed-icons-only.js",
|
||||
"db:seed:safe": "node prisma/seed.js",
|
||||
"repair:features:dry-run": "node prisma/repair-features.js --dry-run",
|
||||
"repair:features:apply": "node prisma/repair-features.js --apply",
|
||||
"recover:symbols:dry-run": "node prisma/recover-symbols.js --dry-run",
|
||||
"recover:symbols:apply": "node prisma/recover-symbols.js --apply"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dnd-kit/core": "^6.1.0",
|
||||
|
||||
267
plans/phase-1-symbol-architecture.md
Normal file
@@ -0,0 +1,267 @@
|
||||
# Phase 1 — Symbol-Architektur Redesign: Detaillierter Plan
|
||||
|
||||
> Basierend auf: `docs/roadmap-feedback-fabian.md`
|
||||
> Ziel: Mandantenspezifische Symbol-Bibliothek mit Template-Import, eigener Kategorisierung und vollständiger Entkopplung von globalen Icons.
|
||||
> **Status: ABGESCHLOSSEN** ✅ (Sprints A–D implementiert, getestet und gepusht)
|
||||
|
||||
---
|
||||
|
||||
## 1. Ziel & Konzept
|
||||
|
||||
**Problem heute:**
|
||||
- `TenantSymbol` verweist auf `IconAsset` (global). Mandant kann zwar `customName` setzen, aber nicht die Kategorie ändern, das SVG bearbeiten oder Symbole aus verschiedenen Paketen frei mischen.
|
||||
- Kategorien (`IconCategory`) sind global mit `tenantId` Override — uneinheitlich.
|
||||
- Keine Möglichkeit, Vorlagen-Pakete (Feuerwehr CH, THW, Sanität) als Unit zu importieren.
|
||||
|
||||
**Lösung:**
|
||||
- `SymbolTemplate` = globale, read-only Vorlagen (je Paket). Wird einmalig aus bestehenden `public/signaturen/` und `IconAsset` generiert.
|
||||
- `TenantCategory` = pro Mandant, frei anlegbar/umbenennbar/sortierbar.
|
||||
- `TenantSymbol` = pro Mandant, **vollständig eigenständig** (`name`, `svgPath`, `categoryId`). Kein Verweis mehr auf globale `IconAsset`.
|
||||
- Mandant startet mit leerer Bibliothek und importiert Pakete nach Bedarf.
|
||||
|
||||
---
|
||||
|
||||
## 2. Datenmodell-Änderungen
|
||||
|
||||
### 2.1 Neue Modelle
|
||||
|
||||
```prisma
|
||||
model SymbolTemplate {
|
||||
id String @id @default(uuid())
|
||||
packageId String // z.B. "feuerwehr-ch"
|
||||
packageName String // z.B. "Feuerwehr Schweiz"
|
||||
categoryName String // z.B. "Fahrzeuge"
|
||||
name String
|
||||
svgPath String // Relativer Pfad in public/ oder SVG-Inhalt
|
||||
tags String[] @default([])
|
||||
sortOrder Int @default(0)
|
||||
|
||||
@@index([packageId])
|
||||
@@map("symbol_templates")
|
||||
}
|
||||
|
||||
model TenantCategory {
|
||||
id String @id @default(uuid())
|
||||
tenantId String
|
||||
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
||||
name String
|
||||
description String?
|
||||
sortOrder Int @default(0)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
symbols TenantSymbol[]
|
||||
|
||||
@@unique([tenantId, name])
|
||||
@@index([tenantId])
|
||||
@@map("tenant_categories")
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 Bestehendes `TenantSymbol` umbaut
|
||||
|
||||
**Vorher:**
|
||||
```prisma
|
||||
model TenantSymbol {
|
||||
id String @id @default(uuid())
|
||||
customName String?
|
||||
sortOrder Int @default(0)
|
||||
tenantId String
|
||||
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
||||
iconId String
|
||||
icon IconAsset @relation(fields: [iconId], references: [id], onDelete: Cascade)
|
||||
}
|
||||
```
|
||||
|
||||
**Nachher:**
|
||||
```prisma
|
||||
model TenantSymbol {
|
||||
id String @id @default(uuid())
|
||||
tenantId String
|
||||
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
||||
|
||||
categoryId String?
|
||||
category TenantCategory? @relation(fields: [categoryId], references: [id], onDelete: SetNull)
|
||||
|
||||
name String // endgültiger Anzeigename (kann aus Template importiert oder custom sein)
|
||||
svgPath String? // z.B. "signaturen/TLF.svg" oder tenant-spezifischer MinIO-Key
|
||||
sortOrder Int @default(0)
|
||||
isUploaded Boolean @default(false) // true = eigener Upload, false = aus Template importiert
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Legacy-Feld für Migration (kann später entfernt werden)
|
||||
migratedFromIconId String?
|
||||
|
||||
@@index([tenantId])
|
||||
@@index([categoryId])
|
||||
@@map("tenant_symbols")
|
||||
}
|
||||
```
|
||||
|
||||
> **Hinweis:** `IconAsset`, `IconCategory` und `hiddenIconIds` bleiben vorerst bestehen (read-only Legacy), werden aber nicht mehr für neue Features verwendet. In einer späteren Phase können sie entfernt werden.
|
||||
|
||||
---
|
||||
|
||||
## 3. Migration & Seed (Sprint A) ✅
|
||||
|
||||
- `prisma/migrations/20260520_symbol_architecture/migration.sql` — erstellt `symbol_templates`, `tenant_categories`, neue Spalten in `tenant_symbols`
|
||||
- `prisma/seed-symbol-templates.ts` — füllt `SymbolTemplate` aus `public/signaturen/*.svg`
|
||||
- `prisma/migrate-tenant-symbols.ts` — migriert bestehende `TenantSymbol`-Einträge
|
||||
- `prisma/migrate.js` — erweitert um Migrationsschritte für Produktion
|
||||
- Alle Seed-Skripte sind idempotent (`upsert` statt `deleteMany`)
|
||||
|
||||
---
|
||||
|
||||
## 4. API-Design (Sprint B) ✅
|
||||
|
||||
### 4.1 Templates
|
||||
|
||||
```
|
||||
GET /api/templates
|
||||
→ { packages: [{ packageId, packageName, categoryCount, symbolCount, previewSymbols }] }
|
||||
|
||||
POST /api/templates/import
|
||||
Body: { packageId }
|
||||
→ importiert alle Symbole des Pakets als TenantSymbols
|
||||
→ antwortet mit { imported, skipped, message }
|
||||
```
|
||||
|
||||
**Implementiert:**
|
||||
- `src/app/api/templates/route.ts` — GET mit `groupBy` Aggregation und Vorschau
|
||||
- `src/app/api/templates/import/route.ts` — POST mit Auto-Kategorie-Erstellung und Deduplikation
|
||||
|
||||
### 4.2 Tenant Categories
|
||||
|
||||
```
|
||||
GET /api/tenant/categories → [{ id, name, sortOrder, description }]
|
||||
POST /api/tenant/categories Body: { name } → neue Kategorie
|
||||
PATCH /api/tenant/categories Body: { id, name } → umbenennen
|
||||
DELETE /api/tenant/categories?id=... → 204 oder 409 wenn nicht leer
|
||||
```
|
||||
|
||||
**Implementiert:** `src/app/api/tenant/categories/route.ts`
|
||||
|
||||
### 4.3 Tenant Symbols
|
||||
|
||||
```
|
||||
GET /api/tenant/symbols?grouped=true|false
|
||||
→ grouped=true: { groups: [{ category, symbols }], symbols: [...] }
|
||||
→ grouped=false: { symbols: [...] }
|
||||
|
||||
POST /api/tenant/symbols
|
||||
- Multipart: { file, categoryId? } → Upload nach MinIO
|
||||
- JSON: { templateId, categoryId? } → aus SymbolTemplate
|
||||
- JSON: { iconId, customName?, categoryId? } → aus IconAsset (Legacy)
|
||||
|
||||
PATCH /api/tenant/symbols Body: { id, name?, customName?, categoryId?, sortOrder? }
|
||||
|
||||
DELETE /api/tenant/symbols Body: { id } → löscht TenantSymbol
|
||||
```
|
||||
|
||||
**Implementiert:** `src/app/api/tenant/symbols/route.ts` + `src/app/api/tenant/symbols/[id]/image/route.ts`
|
||||
|
||||
### 4.4 Icon-Serving (TenantSymbol-First Lookup)
|
||||
|
||||
```
|
||||
GET /api/icons/:id/image
|
||||
→ 1. TenantSymbol (svgPath aus public/ oder MinIO)
|
||||
→ 2. Fallback: IconAsset (legacy)
|
||||
|
||||
GET /api/tenant/symbols/:id/image
|
||||
→ TenantSymbol-Bild aus MinIO oder public/
|
||||
```
|
||||
|
||||
**Implementiert:**
|
||||
- `src/app/api/icons/[id]/image/route.ts`
|
||||
- `src/app/api/tenant/symbols/[id]/image/route.ts`
|
||||
|
||||
---
|
||||
|
||||
## 5. Frontend-Änderungen (Sprints C + D) ✅
|
||||
|
||||
### 5.1 Admin — Symbol-Manager (`src/components/admin/symbol-manager.tsx`)
|
||||
|
||||
**Tabs:**
|
||||
1. **Meine Symbole** — nach TenantCategory gruppierte Symbol-Liste
|
||||
- Expandable Kategorien
|
||||
- SymbolCard: Bild, Name (inline-edit), Kategorie-Select, Löschen
|
||||
- Suche über alle Symbole
|
||||
2. **Kategorien** — CRUD für TenantCategory
|
||||
- Neue Kategorie erstellen
|
||||
- Umbenennen (inline)
|
||||
- Löschen nur wenn leer
|
||||
3. **Vorlagen importieren** — Template-Pakete als Cards
|
||||
- Vorschau der ersten 4 Symbole
|
||||
- 1-Klick Import
|
||||
|
||||
**Actions:**
|
||||
- Upload-Button → Dialog mit Drag & Drop + Kategorie-Auswahl
|
||||
- Import-Button → Dialog mit allen verfügbaren Paketen
|
||||
|
||||
### 5.2 Sidebar — RightSidebar (`src/components/layout/right-sidebar.tsx`)
|
||||
|
||||
- Verwendet neue `tenantSymbolGroups` aus `/api/icons`
|
||||
- **Meine Symbole** Sektion: nach TenantCategory gruppiert, expandable
|
||||
- **Bibliothek** Sektion: globale IconAsset-Kategorien (Legacy, read-only)
|
||||
- Drag & Drop funktioniert mit neuen TenantSymbol-IDs
|
||||
|
||||
### 5.3 API /icons — Kompatibilität
|
||||
|
||||
`src/app/api/icons/route.ts` liefert:
|
||||
- `categories` — Legacy IconAsset-Kategorien (für alte Clients)
|
||||
- `mySymbols` — Legacy TenantSymbol-Liste (für alte Clients)
|
||||
- `tenantSymbols` — Neue flache TenantSymbol-Liste
|
||||
- `tenantSymbolGroups` — Neue gruppierte Liste für Sidebar
|
||||
|
||||
---
|
||||
|
||||
## 6. Dateien: Create / Modify
|
||||
|
||||
### Neue Dateien ✅
|
||||
| Pfad | Beschreibung |
|
||||
|------|-------------|
|
||||
| `prisma/migrations/20260520_symbol_architecture/migration.sql` | Migration neue Tabellen + Spalten |
|
||||
| `prisma/seed-symbol-templates.ts` | Seed: `public/signaturen/*.svg` → `SymbolTemplate` |
|
||||
| `src/app/api/templates/route.ts` | GET /api/templates |
|
||||
| `src/app/api/templates/import/route.ts` | POST /api/templates/import |
|
||||
| `src/app/api/tenant/categories/route.ts` | CRUD TenantCategory |
|
||||
| `src/app/api/tenant/symbols/[id]/image/route.ts` | TenantSymbol Bild-Serving |
|
||||
|
||||
### Modifizierte Dateien ✅
|
||||
| Pfad | Änderung |
|
||||
|------|----------|
|
||||
| `prisma/schema.prisma` | Neue Modelle + TenantSymbol Refactor |
|
||||
| `src/app/api/tenant/symbols/route.ts` | Refactor: Gruppierung, Upload, CRUD |
|
||||
| `src/app/api/icons/route.ts` | Liefert tenantSymbolGroups |
|
||||
| `src/app/api/icons/[id]/image/route.ts` | TenantSymbol-First Lookup |
|
||||
| `src/components/admin/symbol-manager.tsx` | Vollständiger Umbau mit Kategorien, Import, Upload |
|
||||
| `src/components/layout/right-sidebar.tsx` | Gruppierte TenantSymbol-Anzeige |
|
||||
|
||||
---
|
||||
|
||||
## 7. Ausführungsreihenfolge (Tatsächlich)
|
||||
|
||||
| Sprint | Status | Inhalt |
|
||||
|--------|--------|--------|
|
||||
| **A** | ✅ Fertig | Schema, Migration, Seed, Daten-Migration |
|
||||
| **B** | ✅ Fertig | Templates API, Categories API, Symbols API erweitert |
|
||||
| **C** | ✅ Fertig | Admin UI: Symbol-Manager mit Kategorien, Import, Upload |
|
||||
| **D** | ✅ Fertig | Frontend Sidebar gruppiert nach TenantCategory |
|
||||
|
||||
---
|
||||
|
||||
## 8. Risiken & Entscheidungen (Umgesetzt)
|
||||
|
||||
| Thema | Entscheidung |
|
||||
|-------|-------------|
|
||||
| **SVG-Speicherort** | Templates: `public/signaturen/` Pfade in DB (read-only, kein MinIO-Overhead). Uploads: MinIO `tenant-{id}/symbols/`. |
|
||||
| **Migration alter Tenants** | Vollautomatisch via `prisma/migrate.js` + `prisma/migrate-tenant-symbols.ts`. |
|
||||
| **Sidebar vs SymbolPalette** | `RightSidebar` direkt angepasst, keine separate `SymbolPalette`-Komponente nötig. |
|
||||
| **instanceLabel / Stockwerke** | Nicht in Sprint D enthalten (laut Roadmap Phase 1.4 — kann separat geplant werden). |
|
||||
|
||||
---
|
||||
|
||||
*Plan erstellt: 2026-05-20*
|
||||
*Phase 1 abgeschlossen: 2026-05-20*
|
||||
112
prisma/migrate-tenant-symbols.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* Post-Migration Script: Migrate existing TenantSymbols to new architecture.
|
||||
*
|
||||
* Run AFTER applying the schema migration (20260520_symbol_architecture).
|
||||
*
|
||||
* Steps:
|
||||
* 1. Create a default "Meine Symbole" TenantCategory for each tenant that has TenantSymbols
|
||||
* 2. Migrate existing TenantSymbols: set name, svgPath, categoryId, migratedFromIconId
|
||||
* 3. Verify consistency
|
||||
*
|
||||
* Usage:
|
||||
* npx ts-node prisma/migrate-tenant-symbols.ts
|
||||
*/
|
||||
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
|
||||
const prisma = new PrismaClient()
|
||||
|
||||
async function main() {
|
||||
console.log('🔧 Migrating existing TenantSymbols...')
|
||||
|
||||
// Step 1: Get all tenants that have existing tenantSymbols
|
||||
const tenantsWithSymbols = await (prisma as any).tenantSymbol.groupBy({
|
||||
by: ['tenantId'],
|
||||
_count: { id: true },
|
||||
})
|
||||
|
||||
console.log(`Found ${tenantsWithSymbols.length} tenants with existing symbols`)
|
||||
|
||||
let categoriesCreated = 0
|
||||
let symbolsMigrated = 0
|
||||
|
||||
for (const group of tenantsWithSymbols) {
|
||||
const tenantId = group.tenantId
|
||||
|
||||
// Step 2: Create default category for this tenant
|
||||
let defaultCategory = await (prisma as any).tenantCategory.findFirst({
|
||||
where: { tenantId, name: 'Meine Symbole' },
|
||||
})
|
||||
|
||||
if (!defaultCategory) {
|
||||
defaultCategory = await (prisma as any).tenantCategory.create({
|
||||
data: {
|
||||
tenantId,
|
||||
name: 'Meine Symbole',
|
||||
sortOrder: 0,
|
||||
},
|
||||
})
|
||||
categoriesCreated++
|
||||
}
|
||||
|
||||
// Step 3: Migrate all tenantSymbols for this tenant
|
||||
const tenantSymbols = await (prisma as any).tenantSymbol.findMany({
|
||||
where: { tenantId },
|
||||
include: { icon: true },
|
||||
})
|
||||
|
||||
for (const ts of tenantSymbols) {
|
||||
const updates: any = {}
|
||||
|
||||
// name = customName || icon.name
|
||||
if (!ts.name) {
|
||||
updates.name = ts.customName || ts.icon?.name || 'Unbenannt'
|
||||
}
|
||||
|
||||
// svgPath = icon.fileKey
|
||||
if (!ts.svgPath && ts.icon?.fileKey) {
|
||||
updates.svgPath = ts.icon.fileKey
|
||||
}
|
||||
|
||||
// categoryId = default category
|
||||
if (!ts.categoryId) {
|
||||
updates.categoryId = defaultCategory.id
|
||||
}
|
||||
|
||||
// migratedFromIconId = current iconId
|
||||
if (!ts.migratedFromIconId) {
|
||||
updates.migratedFromIconId = ts.iconId
|
||||
}
|
||||
|
||||
if (Object.keys(updates).length > 0) {
|
||||
await (prisma as any).tenantSymbol.update({
|
||||
where: { id: ts.id },
|
||||
data: updates,
|
||||
})
|
||||
symbolsMigrated++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`✅ Done: ${categoriesCreated} categories created, ${symbolsMigrated} symbols migrated`)
|
||||
|
||||
// Verification
|
||||
const unmappedCount = await (prisma as any).tenantSymbol.count({
|
||||
where: { categoryId: null },
|
||||
})
|
||||
|
||||
if (unmappedCount > 0) {
|
||||
console.warn(`⚠️ ${unmappedCount} tenantSymbols still have no categoryId!`)
|
||||
} else {
|
||||
console.log('✅ All tenantSymbols have a category assigned')
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error(e)
|
||||
process.exit(1)
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect()
|
||||
})
|
||||
@@ -2,6 +2,12 @@
|
||||
* Database migration script using PrismaClient raw SQL.
|
||||
* Does NOT require the Prisma CLI (npx prisma) — only the runtime client.
|
||||
* Safe to run multiple times (all statements are idempotent).
|
||||
*
|
||||
* SAFETY RULES:
|
||||
* - NO deleteMany / DELETE / TRUNCATE on icon_assets, icon_categories,
|
||||
* tenant_symbols, or features. These contain user data.
|
||||
* - All operations must be idempotent (safe to re-run).
|
||||
* - In production, destructive operations are blocked.
|
||||
*/
|
||||
const { PrismaClient } = require('@prisma/client')
|
||||
|
||||
@@ -121,10 +127,9 @@ async function migrate() {
|
||||
await prisma.$executeRawUnsafe(`UPDATE tenants SET "subscriptionStatus" = 'ACTIVE' WHERE "subscriptionStatus" = 'TRIAL'`)
|
||||
} catch (e) { /* ignore */ }
|
||||
|
||||
// ─── Step 6: Clean up orphan users ───
|
||||
console.log(' [6/7] Cleaning up orphan users...')
|
||||
// ─── Step 6: Detect orphan users (log only, no deletion) ───
|
||||
console.log(' [6/7] Checking for orphan users...')
|
||||
try {
|
||||
// Find users who are NOT SERVER_ADMIN and have NO tenant membership
|
||||
const orphans = await prisma.user.findMany({
|
||||
where: {
|
||||
role: { not: 'SERVER_ADMIN' },
|
||||
@@ -133,22 +138,15 @@ async function migrate() {
|
||||
select: { id: true, email: true, name: true },
|
||||
})
|
||||
if (orphans.length > 0) {
|
||||
console.log(` Found ${orphans.length} orphan user(s):`)
|
||||
console.log(` ⚠️ Found ${orphans.length} orphan user(s) (NOT deleting — manual review required):`)
|
||||
for (const o of orphans) {
|
||||
console.log(` - ${o.email} (${o.name})`)
|
||||
}
|
||||
// Delete orphan users and their related data
|
||||
await prisma.user.deleteMany({
|
||||
where: {
|
||||
id: { in: orphans.map(o => o.id) },
|
||||
},
|
||||
})
|
||||
console.log(` 🗑️ ${orphans.length} orphan user(s) removed`)
|
||||
} else {
|
||||
console.log(' No orphan users found')
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(' Orphan cleanup skipped:', e.message)
|
||||
console.log(' Orphan check skipped:', e.message)
|
||||
}
|
||||
|
||||
// ─── Step 7: Backfill logoFileKey from logoUrl ───
|
||||
@@ -222,7 +220,7 @@ async function migrate() {
|
||||
id TEXT PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
"tenantId" TEXT NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
"iconId" TEXT NOT NULL REFERENCES icon_assets(id) ON DELETE CASCADE,
|
||||
"iconId" TEXT REFERENCES icon_assets(id) ON DELETE SET NULL,
|
||||
UNIQUE("tenantId", "iconId")
|
||||
)
|
||||
`)
|
||||
@@ -231,6 +229,98 @@ async function migrate() {
|
||||
console.log(' tenant_symbols table skipped:', e.message)
|
||||
}
|
||||
|
||||
// ─── Step 13: Create symbol_templates table ───
|
||||
console.log(' [13] Creating symbol_templates table...')
|
||||
try {
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE TABLE IF NOT EXISTS symbol_templates (
|
||||
id TEXT PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
"fileKey" TEXT NOT NULL,
|
||||
"originalFilename" TEXT NOT NULL,
|
||||
"displayName" TEXT,
|
||||
"categoryName" TEXT,
|
||||
"svgPath" TEXT,
|
||||
"metadata" JSONB NOT NULL DEFAULT '{}',
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE("fileKey")
|
||||
)
|
||||
`)
|
||||
console.log(' symbol_templates table created (or already exists)')
|
||||
} catch (e) {
|
||||
console.log(' symbol_templates table skipped:', e.message)
|
||||
}
|
||||
|
||||
// ─── Step 14: Create tenant_categories table ───
|
||||
console.log(' [14] Creating tenant_categories table...')
|
||||
try {
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE TABLE IF NOT EXISTS tenant_categories (
|
||||
id TEXT PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"sortOrder" INTEGER NOT NULL DEFAULT 0,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"tenantId" TEXT NOT NULL REFERENCES tenants(id) ON DELETE CASCADE
|
||||
)
|
||||
`)
|
||||
console.log(' tenant_categories table created (or already exists)')
|
||||
} catch (e) {
|
||||
console.log(' tenant_categories table skipped:', e.message)
|
||||
}
|
||||
|
||||
// ─── Step 15: Extend tenant_symbols with Phase 1 columns ───
|
||||
console.log(' [15] Extending tenant_symbols with Phase 1 columns...')
|
||||
const tenantSymbolColumns = [
|
||||
`ALTER TABLE tenant_symbols ADD COLUMN IF NOT EXISTS "name" TEXT`,
|
||||
`ALTER TABLE tenant_symbols ADD COLUMN IF NOT EXISTS "svgPath" TEXT`,
|
||||
`ALTER TABLE tenant_symbols ADD COLUMN IF NOT EXISTS "isUploaded" BOOLEAN NOT NULL DEFAULT false`,
|
||||
`ALTER TABLE tenant_symbols ADD COLUMN IF NOT EXISTS "categoryId" TEXT REFERENCES tenant_categories(id) ON DELETE SET NULL`,
|
||||
`ALTER TABLE tenant_symbols ADD COLUMN IF NOT EXISTS "migratedFromIconId" TEXT`,
|
||||
`ALTER TABLE tenant_symbols ADD COLUMN IF NOT EXISTS "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP`,
|
||||
`ALTER TABLE tenant_symbols ADD COLUMN IF NOT EXISTS "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP`,
|
||||
]
|
||||
let tsAdded = 0
|
||||
for (const sql of tenantSymbolColumns) {
|
||||
try { await prisma.$executeRawUnsafe(sql); tsAdded++ } catch (e) { /* ignore */ }
|
||||
}
|
||||
console.log(` ${tsAdded}/${tenantSymbolColumns.length} tenant_symbol columns added`)
|
||||
|
||||
// ─── Step 16: Fix tenant_symbols FK (CASCADE → SET NULL) ───
|
||||
console.log(' [16] Fixing tenant_symbols.iconId FK (CASCADE → SET NULL)...')
|
||||
try {
|
||||
// Make iconId nullable
|
||||
await prisma.$executeRawUnsafe(`ALTER TABLE tenant_symbols ALTER COLUMN "iconId" DROP NOT NULL`)
|
||||
// Drop old cascade FK and recreate with SET NULL
|
||||
await prisma.$executeRawUnsafe(`
|
||||
DO $$ BEGIN
|
||||
-- Drop existing FK constraint (name varies)
|
||||
ALTER TABLE tenant_symbols DROP CONSTRAINT IF EXISTS "tenant_symbols_iconId_fkey";
|
||||
ALTER TABLE tenant_symbols DROP CONSTRAINT IF EXISTS "tenant_symbols_iconId_icon_assets_id_fk";
|
||||
-- Recreate with SET NULL
|
||||
ALTER TABLE tenant_symbols
|
||||
ADD CONSTRAINT "tenant_symbols_iconId_fkey"
|
||||
FOREIGN KEY ("iconId") REFERENCES icon_assets(id) ON DELETE SET NULL;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE NOTICE 'FK fix skipped: %', SQLERRM;
|
||||
END $$;
|
||||
`)
|
||||
console.log(' ✅ tenant_symbols.iconId FK is now ON DELETE SET NULL')
|
||||
} catch (e) {
|
||||
console.log(' FK fix skipped:', e.message)
|
||||
}
|
||||
|
||||
// ─── Step 17: Drop unique constraint on tenant_symbols(tenantId, iconId) ───
|
||||
console.log(' [17] Dropping UNIQUE(tenantId, iconId) on tenant_symbols...')
|
||||
try {
|
||||
await prisma.$executeRawUnsafe(`ALTER TABLE tenant_symbols DROP CONSTRAINT IF EXISTS "tenant_symbols_tenantId_iconId_key"`)
|
||||
console.log(' ✅ Unique constraint dropped (duplicates now allowed)')
|
||||
} catch (e) {
|
||||
console.log(' Unique constraint drop skipped:', e.message)
|
||||
}
|
||||
|
||||
console.log('✅ Database migrations complete')
|
||||
}
|
||||
|
||||
|
||||
151
prisma/recover-features.js
Normal file
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
* Recovery-Skript für Zeichnungen (Features) nach Symbol-Verlust
|
||||
*
|
||||
* Problem: Features verweisen auf gelöschte iconId-UUIDs.
|
||||
* Die imageUrl ist "/api/icons/{alte-uuid}/image" → 404.
|
||||
*
|
||||
* Lösung:
|
||||
* Die alte UUID→SVG-Zuordnung ist verloren. ABER:
|
||||
* - Alle bestehenden IconAssets wurden per Upsert neu erstellt (gleiche fileKeys)
|
||||
* - Jedes Feature hat noch die alte iconId in properties
|
||||
* - Die Sidebar liefert jetzt NEUE iconIds
|
||||
*
|
||||
* Dieses Skript:
|
||||
* 1. Listet alle broken Symbol-Features (iconId zeigt auf gelöschtes Icon)
|
||||
* 2. Für Features wo imageUrl auf /signaturen/ zeigt: direkt fixbar
|
||||
* 3. Für Features mit /api/icons/{uuid}/image: UUID ist verloren → Renderer zeigt ⚠️
|
||||
* 4. Zählt und listet betroffene Projekte
|
||||
*
|
||||
* Der Renderer wurde angepasst (map-view.tsx): broken Symbole zeigen jetzt
|
||||
* ein ⚠️-Platzhalter statt nichts. User können das Symbol manuell ersetzen.
|
||||
*
|
||||
* Ausführung:
|
||||
* DATABASE_URL=... node prisma/recover-features.js [--dry-run]
|
||||
*/
|
||||
|
||||
const { PrismaClient } = require('@prisma/client')
|
||||
const prisma = new PrismaClient()
|
||||
|
||||
const DRY_RUN = process.argv.includes('--dry-run')
|
||||
|
||||
async function main() {
|
||||
console.log('🔧 FEATURE RECOVERY — Analyse & Reparatur')
|
||||
console.log(` Mode: ${DRY_RUN ? '🔍 DRY RUN' : '⚡ LIVE'}`)
|
||||
console.log('')
|
||||
|
||||
// ─── 1. Lade alle aktuellen IconAssets ───
|
||||
const allIcons = await prisma.iconAsset.findMany({
|
||||
select: { id: true, name: true, fileKey: true },
|
||||
})
|
||||
console.log(`📦 ${allIcons.length} IconAssets in der DB`)
|
||||
|
||||
const iconIdSet = new Set(allIcons.map(i => i.id))
|
||||
const fileKeyToIcon = {}
|
||||
for (const icon of allIcons) {
|
||||
fileKeyToIcon[icon.fileKey] = icon
|
||||
}
|
||||
|
||||
// ─── 2. Lade alle Symbol-Features ───
|
||||
const features = await prisma.feature.findMany({
|
||||
where: { type: 'symbol' },
|
||||
include: { project: { select: { id: true, name: true, tenantId: true } } },
|
||||
})
|
||||
console.log(`🖼️ ${features.length} Symbol-Features gefunden`)
|
||||
console.log('')
|
||||
|
||||
let ok = 0
|
||||
let fixedViaFileKey = 0
|
||||
let broken = 0
|
||||
const brokenByProject = {}
|
||||
|
||||
for (const feature of features) {
|
||||
const props = feature.properties || {}
|
||||
const iconId = props.iconId || ''
|
||||
const imageUrl = props.imageUrl || ''
|
||||
|
||||
// ─── Check 1: iconId still exists? ───
|
||||
if (iconId && iconIdSet.has(iconId)) {
|
||||
ok++
|
||||
continue
|
||||
}
|
||||
|
||||
// ─── Check 2: imageUrl points to static /signaturen/ file? ───
|
||||
const sigMatch = imageUrl.match(/\/signaturen\/(.+\.svg)/)
|
||||
if (sigMatch) {
|
||||
const fileKey = `signaturen/${sigMatch[1]}`
|
||||
const matchingIcon = fileKeyToIcon[fileKey]
|
||||
if (matchingIcon) {
|
||||
// Fix: Update iconId to new valid ID
|
||||
const newProps = {
|
||||
...props,
|
||||
iconId: matchingIcon.id,
|
||||
imageUrl: `/api/icons/${matchingIcon.id}/image`,
|
||||
_recovered: true,
|
||||
_oldIconId: iconId,
|
||||
}
|
||||
if (!DRY_RUN) {
|
||||
await prisma.feature.update({
|
||||
where: { id: feature.id },
|
||||
data: { properties: newProps },
|
||||
})
|
||||
}
|
||||
fixedViaFileKey++
|
||||
console.log(` ✅ ${feature.id} → ${matchingIcon.name} (via fileKey)`)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Check 3: imageUrl is /api/icons/{uuid}/image? ───
|
||||
// The uuid in the URL = old iconId = deleted → can't resolve
|
||||
// Mark as broken
|
||||
broken++
|
||||
const projName = feature.project?.name || feature.projectId
|
||||
if (!brokenByProject[projName]) brokenByProject[projName] = []
|
||||
brokenByProject[projName].push({
|
||||
featureId: feature.id,
|
||||
iconId,
|
||||
imageUrl,
|
||||
})
|
||||
}
|
||||
|
||||
console.log('')
|
||||
console.log('═══════════════════════════════════════════')
|
||||
console.log(` ✅ OK (iconId existiert): ${ok}`)
|
||||
console.log(` 🔧 Gefixt (via fileKey): ${fixedViaFileKey}`)
|
||||
console.log(` ❌ Broken (UUID verloren): ${broken}`)
|
||||
console.log(` 📊 Total: ${features.length}`)
|
||||
console.log('═══════════════════════════════════════════')
|
||||
|
||||
if (broken > 0) {
|
||||
console.log('')
|
||||
console.log('❌ BROKEN FEATURES pro Projekt:')
|
||||
for (const [projName, items] of Object.entries(brokenByProject)) {
|
||||
console.log(` 📄 "${projName}": ${items.length} Symbole`)
|
||||
for (const item of items) {
|
||||
console.log(` - Feature ${item.featureId} (iconId: ${item.iconId.substring(0, 8)}...)`)
|
||||
}
|
||||
}
|
||||
console.log('')
|
||||
console.log('💡 Diese Symbole zeigen jetzt ein ⚠️ auf der Karte.')
|
||||
console.log(' User müssen das Symbol manuell löschen und neu platzieren.')
|
||||
console.log(' (Select-Mode → Symbol anklicken → DEL → neues Symbol aus Sidebar ziehen)')
|
||||
}
|
||||
|
||||
if (broken === 0 && fixedViaFileKey === 0) {
|
||||
console.log('')
|
||||
console.log('🎉 Alle Symbol-Features sind OK! Keine Reparatur nötig.')
|
||||
}
|
||||
|
||||
if (DRY_RUN) {
|
||||
console.log('')
|
||||
console.log('🔍 DRY RUN — Keine Änderungen geschrieben.')
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
.then(async () => { await prisma.$disconnect() })
|
||||
.catch(async (e) => {
|
||||
console.error('❌ Fehler:', e)
|
||||
await prisma.$disconnect()
|
||||
process.exit(1)
|
||||
})
|
||||
258
prisma/recover-symbols.js
Normal file
@@ -0,0 +1,258 @@
|
||||
/**
|
||||
* Recovery-Skript für gelöschte/neu erstellte Symbole
|
||||
*
|
||||
* Stellt sicher, dass alle Icons aus public/signaturen/ als IconAssets
|
||||
* in der DB vorhanden sind und für alle Tenants aktiviert sind.
|
||||
*
|
||||
* Unterstützt Dry-Run und Apply-Modus.
|
||||
*
|
||||
* Ausführung:
|
||||
* Analyse: node prisma/recover-symbols.js --dry-run
|
||||
* Anwenden: node prisma/recover-symbols.js --apply
|
||||
*/
|
||||
|
||||
const { PrismaClient } = require('@prisma/client')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
const prisma = new PrismaClient()
|
||||
|
||||
const IS_DRY_RUN = process.argv.includes('--dry-run')
|
||||
const IS_APPLY = process.argv.includes('--apply')
|
||||
const IS_PROD = process.env.NODE_ENV === 'production'
|
||||
|
||||
// ─── Safety Guards ─────────────────────────────────────────────────────────
|
||||
|
||||
if (!IS_DRY_RUN && !IS_APPLY) {
|
||||
console.error('❌ Fehler: Bitte --dry-run oder --apply angeben')
|
||||
console.error('')
|
||||
console.error(' Analyse: node prisma/recover-symbols.js --dry-run')
|
||||
console.error(' Anwenden: node prisma/recover-symbols.js --apply')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (IS_DRY_RUN && IS_APPLY) {
|
||||
console.error('❌ Fehler: --dry-run und --apply können nicht zusammen verwendet werden')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (IS_APPLY && IS_PROD) {
|
||||
console.log('⚠️ Production-Umgebung erkannt. Fortfahren in 3 Sekunden...')
|
||||
await new Promise(r => setTimeout(r, 3000))
|
||||
}
|
||||
|
||||
console.log(IS_DRY_RUN ? '🔍 DRY-RUN MODUS' : '🔧 APPLY-MODUS')
|
||||
|
||||
// ─── Kategorie-Definitionen ────────────────────────────────────────────────
|
||||
|
||||
const catDefs = [
|
||||
{ name: 'Feuer / Brand', description: 'Feuer, Brand, Brandschutz', sortOrder: 1,
|
||||
patterns: ['Feuer', 'Brand', 'Explosion', 'Entrauchung', 'Rauch', 'Kamin', 'Luefter', 'Sprinkler'] },
|
||||
{ name: 'Wasser', description: 'Wasser, Hydranten, Leitungen', sortOrder: 2,
|
||||
patterns: ['Wasser', 'Hydrant', 'Reservoir', 'Druckleitung', 'Druckleistung', 'Transportleitung',
|
||||
'Schieber', 'Wasserloeschposten', 'Wasserversorgung', 'Wasserleitung', 'Ueberschwemmung',
|
||||
'Offener_Wasserverlauf', 'Moeglicher_Wasserbezugsort', 'Stehendes_Gewaesser',
|
||||
'Kleinloeschgeraet', 'Gefahr_durch_Loeschen_mit_Wasser'] },
|
||||
{ name: 'Gefahren / Stoffe', description: 'Gefahrstoffe, Chemie, ABC', sortOrder: 3,
|
||||
patterns: ['Gefaehrlich', 'Chemie', 'Chemikalien', 'Biologisch', 'Radioaktiv', 'Gas', 'Elektri',
|
||||
'Elektrotableau', 'Achtung', 'Leitungsdaehte'] },
|
||||
{ name: 'Rettung / Personen', description: 'Rettung, Sanität, Personen', sortOrder: 4,
|
||||
patterns: ['Rettung', 'Retten', 'Sanitaet', 'Patienten', 'Sammelplatz', 'Sammelstelle',
|
||||
'Totensammelstelle', 'Sprungretter', 'Helikopterlandeplatz'] },
|
||||
{ name: 'Leitern / Geräte', description: 'Leitern, Fahrzeuge, Geräte', sortOrder: 5,
|
||||
patterns: ['Leiter', 'Anhaengeleiter', 'Strebenleiter', 'ADL', 'TLF', 'HRF', 'SWHP'] },
|
||||
{ name: 'Gebäude / Schäden', description: 'Gebäude, Zerstörung, Schäden', sortOrder: 6,
|
||||
patterns: ['Beschaedigung', 'Teilzerstoerung', 'Totalzerstoerung', 'Decke_eingestuerzt',
|
||||
'Umfassungswaende', 'AnzahlGeschosse', 'Eingang', 'Treppen', 'Lift', 'Bruecke',
|
||||
'Rutschgebiet', 'Strasse', 'Bahnlin'] },
|
||||
{ name: 'Einsatzführung', description: 'Führung, Organisation, Kommunikation', sortOrder: 7,
|
||||
patterns: ['Einsatzleiter', 'KP_Font', 'Offizier', 'Beobachtungsposten', 'Kontrollstelle',
|
||||
'Funk', 'Informationszentrum', 'Medienkontaktstelle', 'Fernsignaltableau',
|
||||
'Materialdepot', 'Schluesseldepot', 'Abschnitt', 'Absperrung'] },
|
||||
{ name: 'Organisationen', description: 'Feuerwehr, Polizei, Armee, Zivilschutz', sortOrder: 8,
|
||||
patterns: ['Feuerwehr', 'Polizei', 'Armee', 'Zivilschutz', 'Chemiewehr', 'MS_de', 'Anmarsch'] },
|
||||
{ name: 'Entwicklung / Taktik', description: 'Entwicklungsgrenzen, Ausbreitung', sortOrder: 9,
|
||||
patterns: ['Entwicklungsgrenze', 'Horizontale_Entwicklung', 'Vertikale_Entwicklung',
|
||||
'VertikaleEntwicklung', 'Unfall'] },
|
||||
{ name: 'Verschiedenes', description: 'Weitere Signaturen', sortOrder: 10,
|
||||
patterns: ['Massstab', 'Nordrichtung', 'Windrichtung'] },
|
||||
]
|
||||
|
||||
function findCategory(filename) {
|
||||
for (const def of catDefs) {
|
||||
for (const pattern of def.patterns) {
|
||||
if (filename.includes(pattern)) return def.name
|
||||
}
|
||||
}
|
||||
return 'Verschiedenes'
|
||||
}
|
||||
|
||||
// ─── Main ──────────────────────────────────────────────────────────────────
|
||||
|
||||
async function recover() {
|
||||
console.log('\n🚨 SYMBOL RECOVERY')
|
||||
console.log('────────────────────────────────────────')
|
||||
|
||||
const SVG_DIR = path.join(__dirname, '..', 'public', 'signaturen')
|
||||
if (!fs.existsSync(SVG_DIR)) {
|
||||
console.error('❌ SVG-Verzeichnis nicht gefunden:', SVG_DIR)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const files = fs.readdirSync(SVG_DIR).filter(f => f.endsWith('.svg')).sort()
|
||||
console.log(`\n📁 ${files.length} SVG-Dateien in public/signaturen/ gefunden`)
|
||||
|
||||
// ─── 1. Kategorien Upserten ───
|
||||
console.log('\n[1/4] Kategorien...')
|
||||
const catMap = {}
|
||||
for (const def of catDefs) {
|
||||
const catId = def.name.replace(/[^a-zA-Z0-9]/g, '-').toLowerCase()
|
||||
if (IS_APPLY) {
|
||||
const cat = await prisma.iconCategory.upsert({
|
||||
where: { id: catId },
|
||||
update: { name: def.name, description: def.description, sortOrder: def.sortOrder, isGlobal: true },
|
||||
create: { id: catId, name: def.name, description: def.description, sortOrder: def.sortOrder, isGlobal: true, tenantId: null },
|
||||
})
|
||||
catMap[def.name] = cat.id
|
||||
} else {
|
||||
catMap[def.name] = catId
|
||||
console.log(` 📝 ${def.name} (ID: ${catId})`)
|
||||
}
|
||||
}
|
||||
if (IS_APPLY) console.log(` ✅ ${catDefs.length} Kategorien upserted`)
|
||||
|
||||
// ─── 2. IconAssets Upserten ───
|
||||
console.log('\n[2/4] IconAssets...')
|
||||
const iconMap = {} // fileKey -> { id, name }
|
||||
let created = 0
|
||||
let updated = 0
|
||||
|
||||
for (const file of files) {
|
||||
let name = file.replace('.svg', '')
|
||||
name = name.replace(/_de$/i, '').replace(/_DE$/i, '').replace(/-de$/i, '')
|
||||
name = name.replace(/[_-]/g, ' ').replace(/\s+/g, ' ').trim()
|
||||
|
||||
const fileKey = `signaturen/${file}` // WICHTIG: Gleiches Format wie Seed!
|
||||
const category = findCategory(file)
|
||||
const categoryId = catMap[category]
|
||||
|
||||
if (IS_APPLY) {
|
||||
const existing = await prisma.iconAsset.findFirst({ where: { fileKey } })
|
||||
if (existing) {
|
||||
await prisma.iconAsset.update({
|
||||
where: { id: existing.id },
|
||||
data: { name, categoryId, mimeType: 'image/svg+xml', isSystem: true, isActive: true, width: 48, height: 48 },
|
||||
})
|
||||
iconMap[fileKey] = { id: existing.id, name }
|
||||
updated++
|
||||
} else {
|
||||
const icon = await prisma.iconAsset.create({
|
||||
data: { name, categoryId, fileKey, mimeType: 'image/svg+xml', isSystem: true, width: 48, height: 48 },
|
||||
})
|
||||
iconMap[fileKey] = { id: icon.id, name }
|
||||
created++
|
||||
}
|
||||
} else {
|
||||
// Dry-Run: Simuliere Lookup
|
||||
const existing = await prisma.iconAsset.findFirst({ where: { fileKey }, select: { id: true, name: true } })
|
||||
if (existing) {
|
||||
iconMap[fileKey] = { id: existing.id, name: existing.name }
|
||||
updated++
|
||||
} else {
|
||||
iconMap[fileKey] = { id: `(neu: ${fileKey})`, name }
|
||||
created++
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(` ${IS_APPLY ? '✅' : '📝'} ${created} neu, ${updated} aktualisiert, ${files.length} total`)
|
||||
|
||||
// ─── 3. TenantSymbols erstellen ───
|
||||
console.log('\n[3/4] TenantSymbols...')
|
||||
const tenants = await prisma.tenant.findMany({ select: { id: true, name: true } })
|
||||
let tsCreated = 0
|
||||
let tsExisting = 0
|
||||
|
||||
for (const tenant of tenants) {
|
||||
let tenantNew = 0
|
||||
let tenantExist = 0
|
||||
|
||||
for (const [fileKey, icon] of Object.entries(iconMap)) {
|
||||
if (IS_APPLY) {
|
||||
// Prüfe ob bereits existiert
|
||||
const existing = await prisma.tenantSymbol.findFirst({
|
||||
where: { tenantId: tenant.id, iconId: icon.id },
|
||||
})
|
||||
if (existing) {
|
||||
tenantExist++
|
||||
tsExisting++
|
||||
} else {
|
||||
await prisma.tenantSymbol.create({
|
||||
data: { tenantId: tenant.id, iconId: icon.id, isActive: true },
|
||||
})
|
||||
tenantNew++
|
||||
tsCreated++
|
||||
}
|
||||
} else {
|
||||
// Dry-Run: Prüfe Existenz
|
||||
const existing = await prisma.tenantSymbol.findFirst({
|
||||
where: { tenantId: tenant.id, iconId: icon.id },
|
||||
select: { id: true },
|
||||
})
|
||||
if (existing) {
|
||||
tenantExist++
|
||||
tsExisting++
|
||||
} else {
|
||||
tenantNew++
|
||||
tsCreated++
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(` ${IS_APPLY ? '✅' : '📝'} ${tenant.name}: ${tenantNew} neu, ${tenantExist} bereits vorhanden`)
|
||||
}
|
||||
console.log(` Gesamt: ${tsCreated} neu, ${tsExisting} bereits vorhanden`)
|
||||
|
||||
// ─── 4. Feature-Analyse ───
|
||||
console.log('\n[4/4] Feature-Analyse (Zeichnungen)...')
|
||||
const features = await prisma.feature.findMany({
|
||||
where: { type: 'symbol' },
|
||||
select: { id: true, properties: true, projectId: true },
|
||||
})
|
||||
|
||||
const validIconIds = new Set(Object.values(iconMap).map(i => i.id))
|
||||
let validRefs = 0
|
||||
let brokenRefs = 0
|
||||
|
||||
for (const f of features) {
|
||||
const iconId = f.properties?.iconId
|
||||
if (!iconId) {
|
||||
validRefs++ // Keine Referenz = nicht kaputt
|
||||
} else if (validIconIds.has(iconId)) {
|
||||
validRefs++
|
||||
} else {
|
||||
brokenRefs++
|
||||
}
|
||||
}
|
||||
|
||||
console.log(` 📊 ${features.length} symbol-Features gefunden`)
|
||||
console.log(` ✅ ${validRefs} gültige/keine Referenzen`)
|
||||
console.log(` ❌ ${brokenRefs} kaputte Referenzen (nicht reparierbar ohne Backup)`)
|
||||
|
||||
if (brokenRefs > 0) {
|
||||
console.log('\n ⚠️ HINWEIS: Kaputte Features können NICHT automatisch repariert werden.')
|
||||
console.log(' Die alten iconId-UUIDs sind verloren.')
|
||||
console.log(' Verwende: npm run repair:features:dry-run')
|
||||
}
|
||||
|
||||
console.log('\n✅ RECOVERY ABgeschlossen')
|
||||
if (IS_DRY_RUN) {
|
||||
console.log(' Zum Anwenden: node prisma/recover-symbols.js --apply')
|
||||
}
|
||||
}
|
||||
|
||||
recover()
|
||||
.then(async () => { await prisma.$disconnect() })
|
||||
.catch(async (e) => {
|
||||
console.error('❌ Fehler:', e)
|
||||
await prisma.$disconnect()
|
||||
process.exit(1)
|
||||
})
|
||||
263
prisma/repair-features.js
Normal file
@@ -0,0 +1,263 @@
|
||||
/**
|
||||
* Feature/Symbol-Repair Skript
|
||||
*
|
||||
* Problem: Features (Zeichnungen) speichern Symbol-Referenzen als iconId in
|
||||
* properties JSONB. Nach dem Icon-Verlust zeigen diese auf gelöschte UUIDs.
|
||||
*
|
||||
* Dieses Skript versucht:
|
||||
* 1. Alle symbol-Features zu scannen
|
||||
* 2. Zu prüfen, ob die referenzierte iconId noch existiert
|
||||
* 3. Falls nicht: via migratedFromIconId oder Dateinamen-Matching zu reparieren
|
||||
*
|
||||
* Ausführung:
|
||||
* Dry-Run (nur Analyse, keine Änderungen):
|
||||
* node prisma/repair-features.js --dry-run
|
||||
*
|
||||
* Apply (mit Backup und Reparatur):
|
||||
* node prisma/repair-features.js --apply
|
||||
*
|
||||
* SAFETY:
|
||||
* - In Production (NODE_ENV=production) nur mit --apply möglich
|
||||
* - Vor Apply wird automatisch ein JSON-Backup erstellt
|
||||
* - Keine Features werden gelöscht
|
||||
* - Keine Projekte oder Tenant-Daten werden verändert
|
||||
*/
|
||||
|
||||
const { PrismaClient } = require('@prisma/client')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
const prisma = new PrismaClient()
|
||||
|
||||
const IS_DRY_RUN = process.argv.includes('--dry-run')
|
||||
const IS_APPLY = process.argv.includes('--apply')
|
||||
const IS_PROD = process.env.NODE_ENV === 'production'
|
||||
|
||||
// ─── Safety Guards ─────────────────────────────────────────────────────────
|
||||
|
||||
if (!IS_DRY_RUN && !IS_APPLY) {
|
||||
console.error('❌ Fehler: Bitte --dry-run oder --apply angeben')
|
||||
console.error('')
|
||||
console.error(' Analyse-Modus (keine Änderungen):')
|
||||
console.error(' node prisma/repair-features.js --dry-run')
|
||||
console.error('')
|
||||
console.error(' Reparatur-Modus (mit Backup):')
|
||||
console.error(' node prisma/repair-features.js --apply')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (IS_DRY_RUN && IS_APPLY) {
|
||||
console.error('❌ Fehler: --dry-run und --apply können nicht zusammen verwendet werden')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (IS_APPLY) {
|
||||
console.log('⚠️ REPAIR-MODUS (mit Änderungen)')
|
||||
if (IS_PROD) {
|
||||
console.log(' Production-Umgebung erkannt. Fortfahren in 3 Sekunden...')
|
||||
await new Promise(r => setTimeout(r, 3000))
|
||||
}
|
||||
} else {
|
||||
console.log('🔍 DRY-RUN MODUS (keine Änderungen)')
|
||||
}
|
||||
|
||||
// ─── Statistics ────────────────────────────────────────────────────────────
|
||||
|
||||
const stats = {
|
||||
totalFeatures: 0,
|
||||
validRefs: 0,
|
||||
brokenRefs: 0,
|
||||
repaired: 0,
|
||||
notRepairable: 0,
|
||||
details: [],
|
||||
}
|
||||
|
||||
// ─── Main ──────────────────────────────────────────────────────────────────
|
||||
|
||||
async function repair() {
|
||||
console.log('\n🔧 Feature-Repair gestartet')
|
||||
console.log('────────────────────────────────────────')
|
||||
|
||||
// ─── 1. Lade alle gültigen Icons für schnelle Lookup ───
|
||||
console.log('\n[1/5] Lade Icon-Lookup-Tabellen...')
|
||||
|
||||
const allIcons = await prisma.iconAsset.findMany({
|
||||
select: { id: true, name: true, fileKey: true },
|
||||
})
|
||||
const iconById = new Map(allIcons.map(i => [i.id, i]))
|
||||
const iconByFileKey = new Map(allIcons.map(i => [i.fileKey, i]))
|
||||
|
||||
// tenant_symbols mit migratedFromIconId
|
||||
const tenantSymbols = await prisma.tenantSymbol.findMany({
|
||||
select: { id: true, iconId: true, migratedFromIconId: true, customName: true },
|
||||
})
|
||||
const tsByMigratedId = new Map()
|
||||
for (const ts of tenantSymbols) {
|
||||
if (ts.migratedFromIconId) {
|
||||
tsByMigratedId.set(ts.migratedFromIconId, ts)
|
||||
}
|
||||
}
|
||||
|
||||
console.log(` ✅ ${allIcons.length} IconAssets geladen`)
|
||||
console.log(` ✅ ${tenantSymbols.length} TenantSymbols geladen`)
|
||||
|
||||
// ─── 2. Lade alle symbol-Features ───
|
||||
console.log('\n[2/5] Scanne Features...')
|
||||
|
||||
const features = await prisma.feature.findMany({
|
||||
where: { type: 'symbol' },
|
||||
include: { project: { select: { id: true, title: true, tenantId: true } } },
|
||||
orderBy: { createdAt: 'asc' },
|
||||
})
|
||||
|
||||
stats.totalFeatures = features.length
|
||||
console.log(` 📊 ${features.length} symbol-Features gefunden`)
|
||||
|
||||
// ─── 3. Analysiere jede Feature ───
|
||||
console.log('\n[3/5] Analysiere Symbol-Referenzen...')
|
||||
|
||||
const toRepair = []
|
||||
|
||||
for (const feature of features) {
|
||||
const props = feature.properties || {}
|
||||
const iconId = props.iconId
|
||||
const imageUrl = props.imageUrl || ''
|
||||
|
||||
// Keine iconId → nicht reparierbar, aber auch nicht unbedingt kaputt
|
||||
if (!iconId) {
|
||||
stats.validRefs++ // Oder neutral
|
||||
continue
|
||||
}
|
||||
|
||||
// Prüfe ob iconId noch existiert
|
||||
const icon = iconById.get(iconId)
|
||||
if (icon) {
|
||||
stats.validRefs++
|
||||
continue
|
||||
}
|
||||
|
||||
// ❌ Broken reference
|
||||
stats.brokenRefs++
|
||||
|
||||
// Versuche Reparatur-Strategien
|
||||
let repairedId = null
|
||||
let repairMethod = null
|
||||
|
||||
// Strategie 1: via migratedFromIconId
|
||||
const ts = tsByMigratedId.get(iconId)
|
||||
if (ts && ts.iconId && iconById.has(ts.iconId)) {
|
||||
repairedId = ts.iconId
|
||||
repairMethod = 'migratedFromIconId'
|
||||
}
|
||||
|
||||
// Strategie 2: via imageUrl (extrahiere Dateinamen)
|
||||
if (!repairedId && imageUrl) {
|
||||
const match = imageUrl.match(/\/api\/icons\/([^\/]+)\/image/)
|
||||
if (match) {
|
||||
// Die alte iconId war in der URL, aber die ist ja gelöscht
|
||||
// Wir können hier nicht viel machen
|
||||
}
|
||||
}
|
||||
|
||||
// Strategie 3: via Name-Matching (wenn iconId ein bekannter Name war)
|
||||
// Nicht anwendbar, da iconId eine UUID ist
|
||||
|
||||
if (repairedId) {
|
||||
stats.repaired++
|
||||
toRepair.push({
|
||||
featureId: feature.id,
|
||||
projectId: feature.projectId,
|
||||
projectTitle: feature.project?.title || '(unbekannt)',
|
||||
oldIconId: iconId,
|
||||
newIconId: repairedId,
|
||||
repairMethod,
|
||||
properties: props,
|
||||
})
|
||||
} else {
|
||||
stats.notRepairable++
|
||||
stats.details.push({
|
||||
featureId: feature.id,
|
||||
projectId: feature.projectId,
|
||||
projectTitle: feature.project?.title || '(unbekannt)',
|
||||
iconId,
|
||||
reason: 'Keine Zuordnung möglich (iconId nicht in migratedFromIconId)',
|
||||
properties: JSON.stringify(props).substring(0, 200),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// ─── 4. Ergebnis-Anzeige ───
|
||||
console.log('\n[4/5] Ergebnis-Zusammenfassung')
|
||||
console.log('────────────────────────────────────────')
|
||||
console.log(` Gesamt geprüfte Features: ${stats.totalFeatures}`)
|
||||
console.log(` ✅ Gültige Referenzen: ${stats.validRefs}`)
|
||||
console.log(` ❌ Kaputte Referenzen: ${stats.brokenRefs}`)
|
||||
console.log(` 🔧 Automatisch reparierbar: ${stats.repaired}`)
|
||||
console.log(` ⚠️ Nicht reparierbar: ${stats.notRepairable}`)
|
||||
|
||||
if (stats.details.length > 0) {
|
||||
console.log('\n Nicht reparierbare Features (erste 10):')
|
||||
for (const d of stats.details.slice(0, 10)) {
|
||||
console.log(` - Feature ${d.featureId} in "${d.projectTitle}"`)
|
||||
console.log(` iconId: ${d.iconId}`)
|
||||
console.log(` Grund: ${d.reason}`)
|
||||
}
|
||||
if (stats.details.length > 10) {
|
||||
console.log(` ... und ${stats.details.length - 10} weitere`)
|
||||
}
|
||||
}
|
||||
|
||||
// ─── 5. Apply (nur wenn --apply) ───
|
||||
if (IS_APPLY && toRepair.length > 0) {
|
||||
console.log('\n[5/5] Wende Reparaturen an...')
|
||||
|
||||
// Backup erstellen
|
||||
const backupPath = path.join(__dirname, `feature-backup-${Date.now()}.json`)
|
||||
const backup = toRepair.map(r => ({
|
||||
featureId: r.featureId,
|
||||
oldIconId: r.oldIconId,
|
||||
newIconId: r.newIconId,
|
||||
repairMethod: r.repairMethod,
|
||||
oldProperties: r.properties,
|
||||
}))
|
||||
fs.writeFileSync(backupPath, JSON.stringify(backup, null, 2))
|
||||
console.log(` 💾 Backup erstellt: ${backupPath}`)
|
||||
|
||||
// Reparaturen durchführen
|
||||
let applied = 0
|
||||
for (const r of toRepair) {
|
||||
try {
|
||||
const newProps = {
|
||||
...r.properties,
|
||||
iconId: r.newIconId,
|
||||
}
|
||||
await prisma.feature.update({
|
||||
where: { id: r.featureId },
|
||||
data: { properties: newProps },
|
||||
})
|
||||
applied++
|
||||
console.log(` ✅ Feature ${r.featureId}: ${r.oldIconId} → ${r.newIconId} (${r.repairMethod})`)
|
||||
} catch (e) {
|
||||
console.error(` ❌ Feature ${r.featureId}: Update fehlgeschlagen - ${e.message}`)
|
||||
}
|
||||
}
|
||||
console.log(`\n ✅ ${applied}/${toRepair.length} Reparaturen erfolgreich angewendet`)
|
||||
} else if (IS_APPLY) {
|
||||
console.log('\n[5/5] Keine Reparaturen notwendig.')
|
||||
} else {
|
||||
console.log('\n[5/5] DRY-RUN abgeschlossen (keine Änderungen).')
|
||||
if (toRepair.length > 0) {
|
||||
console.log(` Zum Anwenden: node prisma/repair-features.js --apply`)
|
||||
}
|
||||
}
|
||||
|
||||
console.log('\n✅ Feature-Repair abgeschlossen')
|
||||
}
|
||||
|
||||
repair()
|
||||
.then(async () => { await prisma.$disconnect() })
|
||||
.catch(async (e) => {
|
||||
console.error('❌ Fehler:', e)
|
||||
await prisma.$disconnect()
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -90,6 +90,7 @@ model Tenant {
|
||||
iconCategories IconCategory[]
|
||||
iconAssets IconAsset[]
|
||||
tenantSymbols TenantSymbol[]
|
||||
tenantCategories TenantCategory[]
|
||||
upgradeRequests UpgradeRequest[]
|
||||
dictionaryEntries DictionaryEntry[]
|
||||
rapports Rapport[]
|
||||
@@ -389,13 +390,56 @@ model TenantSymbol {
|
||||
tenantId String
|
||||
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
||||
|
||||
iconId String
|
||||
icon IconAsset @relation(fields: [iconId], references: [id], onDelete: Cascade)
|
||||
iconId String?
|
||||
icon IconAsset? @relation(fields: [iconId], references: [id], onDelete: SetNull)
|
||||
|
||||
// New fields for Phase 1 Symbol Architecture
|
||||
categoryId String?
|
||||
category TenantCategory? @relation(fields: [categoryId], references: [id], onDelete: SetNull)
|
||||
|
||||
name String? // Display name (migrated from customName || icon.name)
|
||||
svgPath String? // e.g. "signaturen/TLF.svg" or tenant-specific MinIO key
|
||||
isUploaded Boolean @default(false)
|
||||
migratedFromIconId String?
|
||||
|
||||
@@index([tenantId])
|
||||
@@index([categoryId])
|
||||
@@map("tenant_symbols")
|
||||
}
|
||||
|
||||
// ─── Symbol Templates (global read-only packages) ─────────
|
||||
|
||||
model SymbolTemplate {
|
||||
id String @id @default(uuid())
|
||||
packageId String // e.g. "feuerwehr-ch"
|
||||
packageName String // e.g. "Feuerwehr Schweiz"
|
||||
categoryName String // e.g. "Fahrzeuge"
|
||||
name String
|
||||
svgPath String // relative path in public/ or MinIO key
|
||||
tags String[] @default([])
|
||||
sortOrder Int @default(0)
|
||||
|
||||
@@index([packageId])
|
||||
@@map("symbol_templates")
|
||||
}
|
||||
|
||||
// ─── Tenant Categories (per-tenant, user-managed) ─────────
|
||||
|
||||
model TenantCategory {
|
||||
id String @id @default(uuid())
|
||||
tenantId String
|
||||
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
||||
name String
|
||||
sortOrder Int @default(0)
|
||||
icon String? // Optional emoji or Lucide icon name for UI
|
||||
|
||||
symbols TenantSymbol[]
|
||||
|
||||
@@unique([tenantId, name])
|
||||
@@index([tenantId])
|
||||
@@map("tenant_categories")
|
||||
}
|
||||
|
||||
// ─── Dictionary (Global + Tenant word library) ────────────
|
||||
|
||||
model DictionaryEntry {
|
||||
|
||||
@@ -44,11 +44,10 @@ async function main() {
|
||||
patterns: ['Massstab', 'Nordrichtung', 'Windrichtung'] },
|
||||
]
|
||||
|
||||
// Delete ALL old system icons (regardless of fileKey pattern)
|
||||
const deleted = await prisma.iconAsset.deleteMany({
|
||||
where: { isSystem: true },
|
||||
})
|
||||
console.log(`🗑️ ${deleted.count} old system icons removed`)
|
||||
// NOTE: We intentionally do NOT delete old system icons here.
|
||||
// TenantSymbol rows reference IconAsset.id via foreign key.
|
||||
// Deleting would either break references (tenant symbols become 404s)
|
||||
// or cascade-delete tenant symbols. Instead we upsert by fileKey.
|
||||
|
||||
// Upsert global categories (preserves tenant categories)
|
||||
const catMap = {}
|
||||
@@ -90,6 +89,7 @@ async function main() {
|
||||
}
|
||||
|
||||
let created = 0
|
||||
let updated = 0
|
||||
for (const file of svgFiles) {
|
||||
let name = file.replace('.svg', '')
|
||||
name = name.replace(/_de$/i, '').replace(/_DE$/i, '').replace(/-de$/i, '')
|
||||
@@ -99,7 +99,21 @@ async function main() {
|
||||
const category = findCategory(file)
|
||||
|
||||
const existing = await prisma.iconAsset.findFirst({ where: { fileKey } })
|
||||
if (!existing) {
|
||||
if (existing) {
|
||||
await prisma.iconAsset.update({
|
||||
where: { id: existing.id },
|
||||
data: {
|
||||
name,
|
||||
categoryId: category.id,
|
||||
mimeType: 'image/svg+xml',
|
||||
isSystem: true,
|
||||
isActive: true,
|
||||
width: 48,
|
||||
height: 48,
|
||||
},
|
||||
})
|
||||
updated++
|
||||
} else {
|
||||
await prisma.iconAsset.create({
|
||||
data: {
|
||||
name,
|
||||
@@ -115,7 +129,7 @@ async function main() {
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`✅ FKS Signaturen: ${created} new SVG icons created (${svgFiles.length} total)`)
|
||||
console.log(`✅ FKS Signaturen: ${created} created, ${updated} updated (${svgFiles.length} total)`)
|
||||
}
|
||||
|
||||
main()
|
||||
|
||||
123
prisma/seed-symbol-templates.ts
Normal file
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* Seed-Skript: Erstellt SymbolTemplate-Einträge aus bestehenden IconAsset (isSystem=true)
|
||||
* oder aus dem Dateisystem (public/signaturen/*.svg).
|
||||
*
|
||||
* Ausführen:
|
||||
* npx ts-node prisma/seed-symbol-templates.ts
|
||||
* oder als Teil des Deployments via npx prisma db seed
|
||||
*
|
||||
* Idempotent: bereits existierende Templates werden übersprungen.
|
||||
*/
|
||||
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
import { readdirSync, statSync } from 'fs'
|
||||
import { join } from 'path'
|
||||
|
||||
const prisma = new PrismaClient()
|
||||
|
||||
const SIGNATUREN_DIR = join(process.cwd(), 'public', 'signaturen')
|
||||
const PACKAGE_ID = 'feuerwehr-ch'
|
||||
const PACKAGE_NAME = 'Feuerwehr Schweiz'
|
||||
|
||||
/**
|
||||
* Versucht Kategorie-Namen aus bestehenden IconAsset / IconCategory abzuleiten.
|
||||
* Fallback: "Sonstiges"
|
||||
*/
|
||||
async function getCategoryMapping(): Promise<Map<string, string>> {
|
||||
const mapping = new Map<string, string>()
|
||||
|
||||
const iconAssets = await (prisma as any).iconAsset.findMany({
|
||||
where: { isSystem: true },
|
||||
include: { category: { select: { name: true } } },
|
||||
})
|
||||
|
||||
for (const asset of iconAssets) {
|
||||
const fileName = asset.fileKey.replace(/^signaturen\//, '').replace(/\.svg$/i, '')
|
||||
const categoryName = asset.category?.name || 'Sonstiges'
|
||||
mapping.set(fileName.toLowerCase(), categoryName)
|
||||
}
|
||||
|
||||
return mapping
|
||||
}
|
||||
|
||||
/**
|
||||
* Liest alle .svg Dateien aus public/signaturen/
|
||||
*/
|
||||
function getSvgFiles(dir: string): string[] {
|
||||
const files: string[] = []
|
||||
try {
|
||||
const entries = readdirSync(dir)
|
||||
for (const entry of entries) {
|
||||
const fullPath = join(dir, entry)
|
||||
const stat = statSync(fullPath)
|
||||
if (stat.isFile() && entry.endsWith('.svg')) {
|
||||
files.push(entry)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('Could not read signaturen directory:', (err as Error).message)
|
||||
}
|
||||
return files.sort()
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('🌱 Seeding SymbolTemplate...')
|
||||
|
||||
const categoryMapping = await getCategoryMapping()
|
||||
const svgFiles = getSvgFiles(SIGNATUREN_DIR)
|
||||
|
||||
console.log(`Found ${svgFiles.length} SVG files in public/signaturen/`)
|
||||
console.log(`IconAsset mapping covers ${categoryMapping.size} entries`)
|
||||
|
||||
let created = 0
|
||||
let skipped = 0
|
||||
|
||||
for (let i = 0; i < svgFiles.length; i++) {
|
||||
const fileName = svgFiles[i]
|
||||
const nameWithoutExt = fileName.replace(/\.svg$/i, '')
|
||||
const displayName = nameWithoutExt
|
||||
.replace(/_/g, ' ')
|
||||
.replace(/-/g, ' ')
|
||||
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
||||
|
||||
const fileKey = `signaturen/${fileName}`
|
||||
|
||||
// Check if already exists
|
||||
const existing = await (prisma as any).symbolTemplate.findFirst({
|
||||
where: { svgPath: fileKey },
|
||||
})
|
||||
|
||||
if (existing) {
|
||||
skipped++
|
||||
continue
|
||||
}
|
||||
|
||||
const categoryName =
|
||||
categoryMapping.get(nameWithoutExt.toLowerCase()) || 'Sonstiges'
|
||||
|
||||
await (prisma as any).symbolTemplate.create({
|
||||
data: {
|
||||
packageId: PACKAGE_ID,
|
||||
packageName: PACKAGE_NAME,
|
||||
categoryName,
|
||||
name: displayName,
|
||||
svgPath: fileKey,
|
||||
tags: [nameWithoutExt.toLowerCase(), categoryName.toLowerCase()],
|
||||
sortOrder: i,
|
||||
},
|
||||
})
|
||||
|
||||
created++
|
||||
}
|
||||
|
||||
console.log(`✅ Done: ${created} created, ${skipped} skipped`)
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error(e)
|
||||
process.exit(1)
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect()
|
||||
})
|
||||
@@ -110,21 +110,15 @@ async function main() {
|
||||
patterns: ['Massstab', 'Nordrichtung', 'Windrichtung'] },
|
||||
]
|
||||
|
||||
// Delete ALL old system icons (regardless of fileKey pattern)
|
||||
const deletedIcons = await prisma.iconAsset.deleteMany({
|
||||
where: { isSystem: true },
|
||||
})
|
||||
console.log(`🗑️ ${deletedIcons.count} old system icons removed`)
|
||||
// NOTE: We intentionally do NOT delete old system icons here.
|
||||
// TenantSymbol rows reference IconAsset.id via foreign key.
|
||||
// Deleting would either break references (tenant symbols become 404s)
|
||||
// or cascade-delete tenant symbols. Instead we upsert by fileKey.
|
||||
|
||||
// Clean up empty global categories
|
||||
const oldGlobalCats = await prisma.iconCategory.findMany({ where: { tenantId: null } })
|
||||
for (const oldCat of oldGlobalCats) {
|
||||
const remaining = await prisma.iconAsset.count({ where: { categoryId: oldCat.id } })
|
||||
if (remaining === 0) {
|
||||
await prisma.iconCategory.delete({ where: { id: oldCat.id } }).catch(() => {})
|
||||
}
|
||||
}
|
||||
// Create new global categories
|
||||
// NOTE: We intentionally do NOT delete any icon categories here.
|
||||
// Tenant-specific categories may reference them, and deleting could
|
||||
// orphan user data. Empty categories are harmless.
|
||||
// Create or update global categories
|
||||
const catMap = {}
|
||||
for (const def of catDefs) {
|
||||
const cat = await prisma.iconCategory.upsert({
|
||||
@@ -163,6 +157,7 @@ async function main() {
|
||||
}
|
||||
|
||||
let created = 0
|
||||
let updated = 0
|
||||
for (const file of svgFiles) {
|
||||
// Clean name: remove .svg, remove _de/_DE suffix
|
||||
let name = file.replace('.svg', '')
|
||||
@@ -173,7 +168,21 @@ async function main() {
|
||||
const category = findCategory(file)
|
||||
|
||||
const existing = await prisma.iconAsset.findFirst({ where: { fileKey } })
|
||||
if (!existing) {
|
||||
if (existing) {
|
||||
await prisma.iconAsset.update({
|
||||
where: { id: existing.id },
|
||||
data: {
|
||||
name,
|
||||
categoryId: category.id,
|
||||
mimeType: 'image/svg+xml',
|
||||
isSystem: true,
|
||||
isActive: true,
|
||||
width: 48,
|
||||
height: 48,
|
||||
},
|
||||
})
|
||||
updated++
|
||||
} else {
|
||||
await prisma.iconAsset.create({
|
||||
data: {
|
||||
name,
|
||||
@@ -189,7 +198,7 @@ async function main() {
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`✅ FKS Signaturen: ${created} new icons created (${svgFiles.length} total SVGs)`)
|
||||
console.log(`✅ FKS Signaturen: ${created} created, ${updated} updated (${svgFiles.length} total SVGs)`)
|
||||
|
||||
// Create a demo project
|
||||
const demoProject = await prisma.project.upsert({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { PrismaClient, Role } from '@prisma/client'
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
import bcrypt from 'bcryptjs'
|
||||
|
||||
const prisma = new PrismaClient()
|
||||
@@ -18,7 +18,7 @@ async function main() {
|
||||
email: 'admin@lageplan.local',
|
||||
name: 'Administrator',
|
||||
password: adminPassword,
|
||||
role: Role.ADMIN,
|
||||
role: 'SERVER_ADMIN',
|
||||
},
|
||||
})
|
||||
|
||||
@@ -29,7 +29,7 @@ async function main() {
|
||||
email: 'editor@lageplan.local',
|
||||
name: 'Einsatzleiter',
|
||||
password: editorPassword,
|
||||
role: Role.EDITOR,
|
||||
role: 'TENANT_ADMIN',
|
||||
},
|
||||
})
|
||||
|
||||
@@ -40,28 +40,28 @@ async function main() {
|
||||
email: 'viewer@lageplan.local',
|
||||
name: 'Beobachter',
|
||||
password: viewerPassword,
|
||||
role: Role.VIEWER,
|
||||
role: 'OPERATOR',
|
||||
},
|
||||
})
|
||||
|
||||
console.log('✅ Users created:', { admin: admin.email, editor: editor.email, viewer: viewer.email })
|
||||
|
||||
// Create icon categories
|
||||
// Create icon categories with stable IDs (same logic as seed.js)
|
||||
const categories = [
|
||||
{ name: 'Feuer', description: 'Brand- und Feuersymbole', sortOrder: 1 },
|
||||
{ name: 'Wasser', description: 'Wasser- und Überflutungssymbole', sortOrder: 2 },
|
||||
{ name: 'Gefahrstoffe', description: 'Chemie- und Gefahrstoffsymbole', sortOrder: 3 },
|
||||
{ name: 'Verkehr', description: 'Verkehrs- und Unfallsymbole', sortOrder: 4 },
|
||||
{ name: 'Personen', description: 'Personen- und Rettungssymbole', sortOrder: 5 },
|
||||
{ name: 'Fahrzeuge', description: 'Einsatzfahrzeuge und Geräte', sortOrder: 6 },
|
||||
{ name: 'Infrastruktur', description: 'Gebäude und Infrastruktursymbole', sortOrder: 7 },
|
||||
{ name: 'Taktik', description: 'Taktische Zeichen und Symbole', sortOrder: 8 },
|
||||
{ name: 'Eigene', description: 'Benutzerdefinierte Symbole', sortOrder: 99 },
|
||||
{ id: 'feuer', name: 'Feuer', description: 'Brand- und Feuersymbole', sortOrder: 1 },
|
||||
{ id: 'wasser', name: 'Wasser', description: 'Wasser- und Überflutungssymbole', sortOrder: 2 },
|
||||
{ id: 'gefahrstoffe', name: 'Gefahrstoffe', description: 'Chemie- und Gefahrstoffsymbole', sortOrder: 3 },
|
||||
{ id: 'verkehr', name: 'Verkehr', description: 'Verkehrs- und Unfallsymbole', sortOrder: 4 },
|
||||
{ id: 'personen', name: 'Personen', description: 'Personen- und Rettungssymbole', sortOrder: 5 },
|
||||
{ id: 'fahrzeuge', name: 'Fahrzeuge', description: 'Einsatzfahrzeuge und Geräte', sortOrder: 6 },
|
||||
{ id: 'infrastruktur', name: 'Infrastruktur', description: 'Gebäude und Infrastruktursymbole', sortOrder: 7 },
|
||||
{ id: 'taktik', name: 'Taktik', description: 'Taktische Zeichen und Symbole', sortOrder: 8 },
|
||||
{ id: 'eigene', name: 'Eigene', description: 'Benutzerdefinierte Symbole', sortOrder: 99 },
|
||||
]
|
||||
|
||||
for (const cat of categories) {
|
||||
await prisma.iconCategory.upsert({
|
||||
where: { name: cat.name },
|
||||
where: { id: cat.id },
|
||||
update: { description: cat.description, sortOrder: cat.sortOrder },
|
||||
create: cat,
|
||||
})
|
||||
@@ -70,14 +70,14 @@ async function main() {
|
||||
console.log('✅ Icon categories created:', categories.length)
|
||||
|
||||
// Get category IDs for system icons
|
||||
const feuerCat = await prisma.iconCategory.findUnique({ where: { name: 'Feuer' } })
|
||||
const wasserCat = await prisma.iconCategory.findUnique({ where: { name: 'Wasser' } })
|
||||
const gefahrstoffeCat = await prisma.iconCategory.findUnique({ where: { name: 'Gefahrstoffe' } })
|
||||
const verkehrCat = await prisma.iconCategory.findUnique({ where: { name: 'Verkehr' } })
|
||||
const personenCat = await prisma.iconCategory.findUnique({ where: { name: 'Personen' } })
|
||||
const fahrzeugeCat = await prisma.iconCategory.findUnique({ where: { name: 'Fahrzeuge' } })
|
||||
const infrastrukturCat = await prisma.iconCategory.findUnique({ where: { name: 'Infrastruktur' } })
|
||||
const taktikCat = await prisma.iconCategory.findUnique({ where: { name: 'Taktik' } })
|
||||
const feuerCat = await prisma.iconCategory.findUnique({ where: { id: 'feuer' } })
|
||||
const wasserCat = await prisma.iconCategory.findUnique({ where: { id: 'wasser' } })
|
||||
const gefahrstoffeCat = await prisma.iconCategory.findUnique({ where: { id: 'gefahrstoffe' } })
|
||||
const verkehrCat = await prisma.iconCategory.findUnique({ where: { id: 'verkehr' } })
|
||||
const personenCat = await prisma.iconCategory.findUnique({ where: { id: 'personen' } })
|
||||
const fahrzeugeCat = await prisma.iconCategory.findUnique({ where: { id: 'fahrzeuge' } })
|
||||
const infrastrukturCat = await prisma.iconCategory.findUnique({ where: { id: 'infrastruktur' } })
|
||||
const taktikCat = await prisma.iconCategory.findUnique({ where: { id: 'taktik' } })
|
||||
|
||||
// Create system icons (these use inline SVG data URIs - in production, upload to MinIO)
|
||||
const systemIcons = [
|
||||
|
||||
BIN
public/Pepe_Avatar.mp4
Normal file
73
public/signaturen/ADL.svg
Normal file
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="75.489105"
|
||||
height="38.344212"
|
||||
viewBox="0 0 75.489106 38.344212"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-4.0682266,-9.1345345)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 591.68,76.1094 H 35.5117 V 353.691 H 591.68 Z"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 427.379,76.1094 V 353.691"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 427.379,352.969 588.219,216.59 427.379,75.5117"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="M 35.5117,276.059 H 427.379"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="M 35.5117,149.352 H 427.379"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path6"
|
||||
d="M 91.7813,149.352 V 276.059"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path7"
|
||||
d="M 150.801,149.352 V 276.059"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path8"
|
||||
d="M 209.82,149.352 V 276.059"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path9"
|
||||
d="M 271.18,149.352 V 276.059"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path10"
|
||||
d="M 330.18,149.352 V 276.059"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path11"
|
||||
d="M 389.219,149.352 V 276.059"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
23
public/signaturen/Abschnitt.svg
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="74.508385"
|
||||
height="39.839844"
|
||||
viewBox="0 0 74.508385 39.839844"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-4.6873163,-8.4297528)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 586.551,175.039 457.031,322.93 127.309,358.73 41.5898,263.578 144.281,123.23 438.648,70.4688 Z"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 778 B |
63
public/signaturen/Absperrung.svg
Normal file
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="78.721375"
|
||||
height="32.409245"
|
||||
viewBox="0 0 78.721375 32.409244"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-2.4348933,-11.840344)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 23.2617,260.91 H 603.672"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 23.2617,193.762 H 603.672"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 261.871,323.91 21.039,9.969"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="m 226.238,141.738 -26.347,13.742 v 136.411 l 32.73,15.5"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="M 284.609,110.34 257.07,124.711"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path6"
|
||||
d="m 212.84,147.961 65.969,0.23 -26.207,-52.8629 -39.762,52.6329"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path7"
|
||||
d="m 212.84,147.961 65.969,0.23 -26.207,-52.8629 z m 20.031,-9.93 29.789,0.11 -11.832,-23.879 -17.957,23.769"
|
||||
style="fill:#00adef;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path8"
|
||||
d="m 276.891,331.641 -39.18,-53.082 -26.789,52.582 65.969,0.5"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path9"
|
||||
d="m 276.891,331.641 -39.18,-53.082 -26.789,52.582 z m -19.93,-10.153 -17.691,-23.968 -12.098,23.742 29.789,0.226"
|
||||
style="fill:#00adef;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
73
public/signaturen/Achtung_de.svg
Normal file
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="49.4916"
|
||||
height="45.740582"
|
||||
viewBox="0 0 49.4916 45.740581"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-16.928133,-4.8954568)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 474.441,139.84 H 150.68 L 311.93,381.5 Z"
|
||||
style="fill:none;stroke:#f47216;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 314.43,180.762 V 325.25"
|
||||
style="fill:none;stroke:#f47216;stroke-width:30;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 126.961,63.3984 h 13.379 v 17.543 h 5.18 c 12.511,0 19.91,6.0391 19.91,16.1797 0,11.2889 -7.192,16.4689 -22.5,16.4689 h -15.969 z m 13.379,40.7036 h 3.449 c 4.602,0 8.27,-1.661 8.27,-6.7622 0,-5.25 -3.668,-6.9101 -8.27,-6.9101 h -3.449 v 13.6723"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="m 170.969,63.3984 h 12.941 v 15.8204 c 0,8.0507 2.738,11.7226 8.059,11.7226 3.519,0 5.972,-2.3828 5.972,-9.4219 V 63.3984 h 12.938 v 23.3711 c 0,7.7618 -4.098,14.9495 -14.309,14.9495 -5.898,0 -11.07,-2.3674 -13.66,-7.7581 h -0.148 v 6.8981 H 170.969 V 63.3984"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="m 256.109,78.3516 v 2.3789 c 0,11.1406 -5.039,20.9885 -18.91,20.9885 -11.648,0 -20.07,-7.1877 -20.07,-19.5588 0,-12.3594 9.422,-19.6289 21.793,-19.6289 4.816,0 9.566,0.7187 13.738,2.3789 v 9.1289 c -3.89,-2.0899 -7.91,-2.8789 -11.441,-2.8789 -6.321,0 -10.278,2.0195 -11,7.1914 z m -26.031,7.3398 c 0.293,4.3086 2.512,7.8281 7.192,7.8281 5.179,0 7.191,-3.5195 7.191,-7.8281 h -14.383"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path6"
|
||||
d="M 302.781,100.859 H 289.828 V 85.0391 c 0,-8.0508 -2.726,-11.7188 -8.047,-11.7188 -3.519,0 -5.972,2.3711 -5.972,9.418 V 100.859 H 262.871 V 77.4883 c 0,-7.7695 4.098,-14.957 14.309,-14.957 5.89,0 11.07,2.3789 13.66,7.7695 h 0.14 v -6.9024 h 11.801 v 37.4606"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path7"
|
||||
d="m 312.34,63.3984 h 12.941 V 117.328 H 312.34 V 63.3984"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path8"
|
||||
d="m 371.23,63.3984 c -0.57,2.9414 -0.718,5.8907 -0.718,8.8399 v 13.9531 c 0,11.4297 -8.274,15.5276 -17.832,15.5276 -5.539,0 -10.36,-0.789 -14.961,-2.6604 l 0.222,-8.7695 c 3.59,2.0117 7.758,2.8007 11.93,2.8007 4.68,0 8.488,-1.3593 8.559,-6.4687 -1.649,0.2891 -3.95,0.5078 -6.039,0.5078 -6.903,0 -19.34,-1.3672 -19.34,-12.8008 0,-8.1289 6.609,-11.7968 14.019,-11.7968 5.321,0 8.918,2.0898 11.871,6.7578 h 0.137 c 0,-1.9375 0.211,-3.8789 0.293,-5.8907 z m -26.101,11.8633 c 0,3.5977 3.449,4.9571 7.84,4.9571 1.941,0 3.812,-0.1407 5.461,-0.2071 0,-4.3906 -3.09,-8.8515 -7.981,-8.8515 -3.019,0 -5.32,1.5117 -5.32,4.1015"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path9"
|
||||
d="M 418.469,100.859 H 406.75 v -6.7574 h -0.141 c -2.73,4.5976 -7.187,7.6174 -12.73,7.6174 -11.649,0 -16.899,-8.3401 -16.899,-19.4807 0,-11.0781 6.399,-18.8399 16.692,-18.8399 5.168,0 9.488,2.0118 12.578,6.4024 h 0.141 v -2.0195 c 0,-7.3321 -4.02,-10.8594 -11.5,-10.8594 -5.391,0 -8.7,1.1484 -12.661,3.0976 l -0.64,-10.2109 c 3.019,-1.0781 8.121,-2.3789 14.308,-2.3789 15.102,0 22.571,4.9609 22.571,20.3516 z m -28.11,-18.4098 c 0,5.1094 2.52,9.3516 7.332,9.3516 5.829,0 8.27,-4.6719 8.27,-8.8516 0,-5.75 -3.672,-9.6289 -8.27,-9.6289 -3.882,0 -7.332,3.3086 -7.332,9.1289"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path10"
|
||||
d="m 463.988,78.3516 v 2.3789 c 0,11.1406 -5.027,20.9885 -18.91,20.9885 -11.648,0 -20.058,-7.1877 -20.058,-19.5588 0,-12.3594 9.421,-19.6289 21.789,-19.6289 4.812,0 9.562,0.7187 13.73,2.3789 v 9.1289 c -3.879,-2.0899 -7.91,-2.8789 -11.43,-2.8789 -6.328,0 -10.289,2.0195 -11.007,7.1914 z m -26.027,7.3398 c 0.289,4.3086 2.519,7.8281 7.187,7.8281 5.18,0 7.192,-3.5195 7.192,-7.8281 h -14.379"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path11"
|
||||
d="m 498.148,101.289 c -1.296,0.223 -2.878,0.43 -4.386,0.43 -5.614,0 -8.84,-3.0198 -11.071,-7.7581 h -0.152 v 6.8981 H 470.75 V 63.3984 h 12.941 v 15.8204 c 0,7.332 3.379,11.7226 9.418,11.7226 1.512,0 2.95,0 4.391,-0.4414 l 0.648,10.789"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.5 KiB |
68
public/signaturen/Anhaengeleiter.svg
Normal file
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="28.357332"
|
||||
height="48.064117"
|
||||
viewBox="0 0 28.357332 48.064117"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-27.697333,-4.490668)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 212.73,33.0391 V 178.07"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 415.41,33.0391 V 178.07"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 241.559,39.1016 V 393.52"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="M 386.59,39.1016 V 393.52"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="M 241.559,84.7891 H 386.59"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path6"
|
||||
d="M 241.559,142.621 H 386.59"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path7"
|
||||
d="M 241.559,199.879 H 386.59"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path8"
|
||||
d="M 241.559,257.172 H 386.59"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path9"
|
||||
d="M 241.559,313.32 H 386.59"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path10"
|
||||
d="M 241.559,369.469 H 386.59"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
58
public/signaturen/Anmarsch-Feuerwehr.svg
Normal file
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="77.460358"
|
||||
height="15.1172"
|
||||
viewBox="0 0 77.460358 15.1172"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-3.0651066,-20.964134)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 22.9883,264.969 H 603.941"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 22.9883,161.59 H 603.941"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 369.191,213.57 H 482.898"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="M 22.9883,213.57 H 186.539"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="m 476.672,187.48 v 52.18 l 99.297,-25.699 -99.297,-26.481"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path6"
|
||||
d="m 223.789,188.98 h 10.09 v 22.04 h 17 v 7.921 h -17 v 12.387 h 17.859 v 7.922 h -27.949 v -50.27"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path7"
|
||||
d="m 259.809,188.98 h 29.82 v 7.918 h -19.738 v 14.122 h 17.937 v 7.921 h -17.937 v 12.387 h 19.589 v 7.922 h -29.671 v -50.27"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path8"
|
||||
d="m 299.5,207.129 c 0,-13.469 7.629,-19.02 20.52,-19.02 12.902,0 20.531,5.551 20.531,19.02 v 32.121 h -10.082 v -29.031 c 0,-8.571 -2.739,-14.188 -10.449,-14.188 -7.7,0 -10.442,5.617 -10.442,14.188 V 239.25 H 299.5 v -32.121"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
58
public/signaturen/Anstell_Schiebeleiter.svg
Normal file
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="19.9772"
|
||||
height="40.640144"
|
||||
viewBox="0 0 19.9772 40.640144"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-31.830666,-8.2026679)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 383.559,60.8789 V 365.68"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 243.73,60.8789 V 365.68"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 243.73,102 H 383.559"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="M 243.73,150.23 H 383.559"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="M 243.73,199.559 H 383.559"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path6"
|
||||
d="M 243.73,248.879 H 383.559"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path7"
|
||||
d="M 243.73,296.211 H 383.559"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path8"
|
||||
d="M 243.73,347.539 H 383.559"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
53
public/signaturen/AnzahlGeschosse.svg
Normal file
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="73.458839"
|
||||
height="43.304184"
|
||||
viewBox="0 0 73.45884 43.304184"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-4.7239599,-6.5370679)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 40.4297,53.3906 V 373.172 H 586.371"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 313.93,373.172 V 235.051 H 40.4297"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 97.4297,293.531 v 9.098 h -21.75 v -9.098 h 21.75"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="m 106.871,320 5.789,-7.52 9.762,7.942 V 275.828 H 134 V 333.57 H 123.738 L 106.871,320"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="m 148.07,274.828 h 8.602 l 20.187,59.731 h -8.609 l -20.18,-59.731"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path6"
|
||||
d="M 199.031,301.059 H 182.32 v -8.61 h 16.711 v -16.621 h 8.598 v 16.621 h 16.711 v 8.61 h -16.711 v 16.632 h -8.598 v -16.632"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path7"
|
||||
d="m 231.871,276.738 c 4.301,-1.25 10.098,-1.91 15.141,-1.91 9.597,0 22.09,3.481 22.09,17.211 0,7.031 -3.641,12.742 -11,13.731 v 0.171 c 5.867,2.231 10.75,5.957 10.75,13.821 0,12.316 -11.911,14.797 -19.032,14.797 -5.949,0 -11.5,-1.071 -16.129,-2.887 l 0.661,-9.274 c 4.058,1.993 8.437,3.063 12.988,3.063 5.211,0 9.93,-1.82 9.93,-7.609 0,-5.043 -5.051,-7.614 -12.821,-7.614 h -5.301 v -9.097 h 5.633 c 7.36,0 12.739,-2.231 12.739,-9.02 0,-5.871 -7.36,-8.191 -12.161,-8.191 -4.55,0 -8.859,1.082 -12.828,2.648 l -0.66,-9.84"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
28
public/signaturen/Armee.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="56.927597"
|
||||
height="37.361401"
|
||||
viewBox="0 0 56.927597 37.361401"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-13.168266,-9.8626678)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 520.719,78.0195 H 103.762 V 348.23 h 416.957 z"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 273.301,177.449 h 19.32 l 5.617,15.231 h 26.782 l 5.308,-15.231 h 20.852 l -27.489,71.34 h -23.3 z m 47.219,28.723 h -17.891 l 9.199,27.906 h 0.211 l 8.481,-27.906"
|
||||
style="fill:#00adef;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
108
public/signaturen/Bahnline-mit-Stasse-Niveauuebergang.svg
Normal file
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="78.605675"
|
||||
height="40.806187"
|
||||
viewBox="0 0 78.605675 40.806187"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-2.3864533,-8.1402679)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 408.422,65.1016 V 361.148"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 287.012,65.1016 V 361.148"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 602.441,217.969 H 22.8984"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="m 554.59,170.66 v 92.399"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="m 522.898,170.66 v 92.399"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path6"
|
||||
d="m 493.102,170.66 v 92.399"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path7"
|
||||
d="m 463.379,170.66 v 92.399"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path8"
|
||||
d="m 433.66,170.66 v 92.399"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path9"
|
||||
d="m 347.949,170.66 v 92.399"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path10"
|
||||
d="m 318.238,170.66 v 92.399"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path11"
|
||||
d="m 378.039,170.66 v 92.399"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path12"
|
||||
d="m 222.172,170.66 v 92.399"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path13"
|
||||
d="m 192.449,170.66 v 92.399"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path14"
|
||||
d="m 252.262,170.66 v 92.399"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path15"
|
||||
d="m 130.359,170.66 v 92.399"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path16"
|
||||
d="m 100.648,170.66 v 92.399"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path17"
|
||||
d="m 70.1406,170.66 v 92.399"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path18"
|
||||
d="m 160.461,170.66 v 92.399"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.5 KiB |
138
public/signaturen/Bahnlinie_mit_Strassenueberfuehrung.svg
Normal file
@@ -0,0 +1,138 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="79.002655"
|
||||
height="31.690386"
|
||||
viewBox="0 0 79.002655 31.690386"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-2.1161466,-12.698134)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 271.629,99.3711 V 326.879"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 352.641,99.3711 V 326.879"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10.17;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 257.691,162.391 h -51.382 l -52.75,-59.629"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="M 257.691,263.871 H 206.309 L 153.559,323.5"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="m 365.449,162.391 h 51.371 l 52.75,-59.629"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path6"
|
||||
d="M 365.449,263.871 H 416.82 L 469.57,323.5"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path7"
|
||||
d="m 352.641,213.121 h 250.75"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path8"
|
||||
d="m 388.719,178.109 v 70.032"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path9"
|
||||
d="m 413.98,178.109 v 70.032"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path10"
|
||||
d="m 439.219,178.109 v 70.032"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path11"
|
||||
d="m 464.469,178.109 v 70.032"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path12"
|
||||
d="m 489.719,178.109 v 70.032"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path13"
|
||||
d="m 514.969,178.109 v 70.032"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path14"
|
||||
d="m 540.23,178.109 v 70.032"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path15"
|
||||
d="m 565.469,178.109 v 70.032"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path16"
|
||||
d="M 271.629,213.121 H 20.8711"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path17"
|
||||
d="M 235.551,248.141 V 178.109"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path18"
|
||||
d="M 210.289,248.141 V 178.109"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path19"
|
||||
d="M 185.051,248.141 V 178.109"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path20"
|
||||
d="M 159.789,248.141 V 178.109"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path21"
|
||||
d="M 134.539,248.141 V 178.109"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path22"
|
||||
d="M 109.289,248.141 V 178.109"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path23"
|
||||
d="M 84.0391,248.141 V 178.109"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path24"
|
||||
d="M 58.8008,248.141 V 178.109"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.3 KiB |
93
public/signaturen/Bahnlinie_mit_Strassenunterfuehrung.svg
Normal file
@@ -0,0 +1,93 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="80.705238"
|
||||
height="42.09684"
|
||||
viewBox="0 0 80.705238 42.09684"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-1.2348933,-7.4949346)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 14.2617,215.441 H 609.551"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 153.23,106.379 55.008,55.012 H 422.98 l 63.7,-63.6996"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 160.469,315.809 54.769,-54.77 H 422.5 l 54.879,54.891"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="M 114.922,175.762 V 245.25"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="M 176.199,175.762 V 245.25"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path6"
|
||||
d="M 238.16,175.762 V 245.25"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path7"
|
||||
d="M 299.93,175.762 V 245.25"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path8"
|
||||
d="M 354,175.762 V 245.25"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path9"
|
||||
d="M 408.078,175.762 V 245.25"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path10"
|
||||
d="M 469.852,175.762 V 245.25"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path11"
|
||||
d="M 523.922,175.762 V 245.25"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path12"
|
||||
d="M 260.84,261.039 V 365.988"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path13"
|
||||
d="M 345.77,261.039 V 365.988"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path14"
|
||||
d="M 260.84,60.2617 V 161.391"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path15"
|
||||
d="M 345.77,60.2617 V 161.391"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.7 KiB |
33
public/signaturen/Beobachtungsposten_de.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="60.768242"
|
||||
height="47.310577"
|
||||
viewBox="0 0 60.768242 47.310577"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-11.286615,-4.6015026)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 536.262,42.8594 H 88.8594 L 307.199,383.578 Z"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 232.422,125.23 h 20.027 v 30.258 h 28.981 v 14.223 h -28.981 v 16.48 h 30.27 v 14.219 h -50.297 v -75.18"
|
||||
style="fill:#00adef;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 303.398,125.23 h 25.961 l 9.911,57.731 h 0.21 l 10.661,-57.731 h 25.75 l 16.8,75.18 h -19.5 l -9.8,-57.73 h -0.211 l -10.559,57.73 h -25.422 l -10.121,-57.73 h -0.219 l -9.687,57.73 h -20.461 l 16.687,-75.18"
|
||||
style="fill:#00adef;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
28
public/signaturen/Beschaedigung.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="44.708492"
|
||||
height="44.678757"
|
||||
viewBox="0 0 44.708492 44.678757"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-19.538916,-6.0484697)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 477.988,50.2813 150.078,378.301"
|
||||
style="fill:none;stroke:#ed1c24;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 150.309,50.2813 478.32,378.301"
|
||||
style="fill:none;stroke:#ed1c24;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1009 B |
23
public/signaturen/Biologische_Stoffe.svg
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="60.768246"
|
||||
height="47.311161"
|
||||
viewBox="0 0 60.768246 47.311161"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-11.286613,-4.5436252)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 536.262,43.2891 H 88.8594 L 307.199,384.012 Z"
|
||||
style="fill:none;stroke:#f47216;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 729 B |
43
public/signaturen/Brandabschnitt-EI180.svg
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="79.704201"
|
||||
height="13.837466"
|
||||
viewBox="0 0 79.704201 13.837466"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-1.9640666,-21.598534)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 14.7305,229.371 H 612.512"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 14.7305,195.148 H 612.512"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 360.781,161.43 V 265.211"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="M 334.531,161.43 V 265.211"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="M 308.281,161.43 V 265.211"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
28
public/signaturen/Brandabschnitt-EI30.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="77.661423"
|
||||
height="13.514667"
|
||||
viewBox="0 0 77.661423 13.514667"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-2.8651066,-21.630801)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 21.4883,214.289 H 603.949"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 317.34,163.609 v 101.36"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 996 B |
33
public/signaturen/Brandabschnitt-EI60.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="80.001503"
|
||||
height="13.889067"
|
||||
viewBox="0 0 80.001503 13.889067"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-1.72396,-21.573601)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 12.9297,213.32 H 612.941"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 330.57,161.23 V 265.398"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 295.301,161.23 V 265.398"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
33
public/signaturen/Brandmeldezentrale.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="62.261425"
|
||||
height="36.760426"
|
||||
viewBox="0 0 62.261425 36.760426"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-10.742706,-10.137068)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 542.531,80.4688 H 85.5703 V 346.172 H 542.531 Z"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 171.309,194.469 V 319.781"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 203.34,144.422 c 0,-17.774 -14.078,-32.16 -31.449,-32.16 -17.36,0 -31.442,14.386 -31.442,32.16 0,17.75 14.082,32.148 31.442,32.148 17.371,0 31.449,-14.398 31.449,-32.148"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
53
public/signaturen/Brandschutztueren.svg
Normal file
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="79.574463"
|
||||
height="16.0308"
|
||||
viewBox="0 0 79.574463 16.0308"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-1.9640666,-20.502668)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 611.539,204.898 H 14.7305"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 205.199,153.199 V 256.602"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 421.059,153.199 V 256.602"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="m 252.641,226.5 h 27.371 v 7.27 h -18.114 v 12.96 h 16.461 V 254 h -16.461 v 11.371 h 17.981 v 7.27 H 252.641 V 226.5"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="m 288.609,226.5 h 9.25 v 46.141 h -9.25 V 226.5"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path6"
|
||||
d="m 305.398,227.23 c 3.442,-1 8.063,-1.531 12.102,-1.531 7.66,0 17.648,2.781 17.648,13.75 0,5.621 -2.91,10.192 -8.796,10.981 v 0.129 c 4.699,1.793 8.597,4.761 8.597,11.043 0,9.847 -9.519,11.828 -15.211,11.828 -4.758,0 -9.187,-0.86 -12.886,-2.309 l 0.527,-7.402 c 3.242,1.582 6.742,2.441 10.383,2.441 4.16,0 7.929,-1.449 7.929,-6.082 0,-4.027 -4.031,-6.078 -10.242,-6.078 h -4.23 v -7.27 h 4.492 c 5.879,0 10.18,-1.789 10.18,-7.21 0,-4.692 -5.879,-6.54 -9.719,-6.54 -3.633,0 -7.07,0.86 -10.242,2.11 l -0.532,-7.86"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path7"
|
||||
d="m 357.488,232.578 c -6.808,0 -6.738,11.043 -6.738,16.863 0,5.95 0,17.118 6.738,17.118 6.883,0 6.883,-11.168 6.883,-17.118 0,-5.82 0.059,-16.863 -6.883,-16.863 z m 0,-6.879 c 13.352,0 16.133,13.031 16.133,23.742 0,10.707 -2.641,23.989 -16.133,23.989 -12.488,0 -16,-12.418 -16,-23.989 0,-9.652 1.793,-23.742 16,-23.742"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
28
public/signaturen/Bruecke.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="62.267014"
|
||||
height="32.830853"
|
||||
viewBox="0 0 62.267014 32.830852"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-10.730922,-11.939098)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 84.0391,334.121 142.23,275.219 h 342.809 l 58.91,58.902"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 84.0391,94.9609 142.23,153.871 h 342.809 l 58.91,-58.9101"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
33
public/signaturen/Chemiewehr_de.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="50.141731"
|
||||
height="49.562439"
|
||||
viewBox="0 0 50.141731 49.562439"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-16.543733,-3.5736013)">
|
||||
<path
|
||||
id="path1"
|
||||
d="m 495.141,214.539 c 0,-99.898 -81.942,-180.8593 -183.039,-180.8593 -101.082,0 -183.024,80.9613 -183.024,180.8593 0,99.891 81.942,180.859 183.024,180.859 101.097,0 183.039,-80.968 183.039,-180.859 z"
|
||||
style="fill:none;stroke:#52afe6;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 282.57,188.359 c -7.14,-2.8 -15.82,-5.039 -24.359,-5.039 -19.039,0 -32.621,11.621 -32.621,30.801 0,18.199 12.039,31.641 30.519,31.641 8.961,0 17.082,-2.242 25.481,-6.864 l 2.101,21.141 c -9.382,2.801 -19.043,5.039 -28.98,5.039 -32.199,0 -56,-16.937 -56,-50.957 0,-36.961 30.098,-50.121 56.141,-50.121 13.296,0 21.558,2.102 28.976,3.922 l -1.258,20.437"
|
||||
style="fill:#00adef;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 309.449,165.68 h 33.742 l 12.879,75.039 h 0.282 l 13.859,-75.039 h 33.461 l 21.84,97.718 h -25.34 L 387.43,188.359 h -0.282 L 373.43,263.398 H 340.391 L 327.23,188.359 h -0.281 l -12.597,75.039 H 287.75 l 21.699,-97.718"
|
||||
style="fill:#00adef;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
28
public/signaturen/Chemikalien.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="60.768242"
|
||||
height="47.310619"
|
||||
viewBox="0 0 60.768242 47.31062"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-11.286615,-4.6865685)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 536.262,44.6211 H 88.8594 L 307.199,385.34 Z"
|
||||
style="fill:none;stroke:#f47216;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 337.129,138.801 c -5.488,-2.153 -12.168,-3.879 -18.738,-3.879 -14.653,0 -25.102,8.937 -25.102,23.699 0,14 9.262,24.34 23.481,24.34 6.902,0 13.14,-1.723 19.601,-5.281 l 1.617,16.269 c -7.218,2.153 -14.648,3.879 -22.289,3.879 -24.777,0 -43.09,-13.039 -43.09,-39.207 0,-28.43 23.161,-38.562 43.192,-38.562 10.23,0 16.59,1.621 22.301,3.019 l -0.973,15.723"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
103
public/signaturen/Decke_eingestuerzt_de.svg
Normal file
@@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="71.71196"
|
||||
height="42.906773"
|
||||
viewBox="0 0 71.71196 42.906773"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-5.9317732,-6.8933346)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 577.328,58.6992 V 325.18 L 514.719,370.5 H 49.4883 V 102.531 L 110.109,58.6992 Z"
|
||||
style="fill:none;stroke:#1b1816;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 84.1289,246.891 h 20.2691 c 18.993,0 32.954,7.257 32.954,28.078 0,21.543 -13.563,27.609 -32.954,27.609 H 84.1289 Z m 14.8399,44.679 h 5.7502 c 10.851,0 17.312,-5.75 17.312,-16.84 0,-11.089 -6.222,-16.832 -17.312,-16.832 h -5.7502 v 33.672"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 186.73,263.48 v 2.641 c 0,12.359 -5.582,23.289 -20.98,23.289 -12.922,0 -22.262,-7.98 -22.262,-21.699 0,-13.723 10.453,-21.781 24.184,-21.781 5.34,0 10.609,0.8 15.226,2.629 v 10.14 c -4.296,-2.32 -8.769,-3.187 -12.679,-3.187 -7.02,0 -11.41,2.226 -12.207,7.968 z m -28.878,8.141 c 0.32,4.789 2.796,8.699 7.976,8.699 5.75,0 7.981,-3.91 7.981,-8.699 h -15.957"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="m 227.82,287.102 c -3.269,1.589 -7.101,2.308 -11.41,2.308 -13.719,0 -24.172,-7.98 -24.172,-21.781 0,-13.719 10.453,-21.699 24.172,-21.699 3.828,0 8.141,0.64 11.731,1.84 l -0.321,10.691 c -2.39,-1.281 -5.66,-2 -8.929,-2 -6.231,0 -11.813,4.309 -11.813,10.93 0,7.179 4.793,11.488 11.012,11.488 3.43,0 6.058,-0.719 8.691,-2.309 l 1.039,10.532"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="m 234.121,246.891 h 14.367 v 20.578 h 0.153 l 11.488,-20.578 h 17.402 l -15.64,22.5 14.437,19.07 H 260.609 L 248.641,270.98 h -0.153 v 35.75 h -14.367 v -59.839"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path6"
|
||||
d="m 324.121,263.48 v 2.641 c 0,12.359 -5.59,23.289 -20.98,23.289 -12.93,0 -22.262,-7.98 -22.262,-21.699 0,-13.723 10.449,-21.781 24.172,-21.781 5.347,0 10.609,0.8 15.238,2.629 v 10.14 c -4.309,-2.32 -8.777,-3.187 -12.687,-3.187 -7.024,0 -11.411,2.226 -12.204,7.968 z m -28.883,8.141 c 0.321,4.789 2.793,8.699 7.981,8.699 5.742,0 7.972,-3.91 7.972,-8.699 h -15.953"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path7"
|
||||
d="m 124.66,167.738 v 2.641 c 0,12.359 -5.582,23.293 -20.98,23.293 -12.9183,0 -22.2581,-7.973 -22.2581,-21.703 0,-13.719 10.4492,-21.778 24.1801,-21.778 5.339,0 10.609,0.797 15.226,2.637 v 10.133 c -4.297,-2.32 -8.769,-3.191 -12.68,-3.191 -7.019,0 -11.4097,2.23 -12.2066,7.968 z m -28.8787,8.141 c 0.3203,4.793 2.789,8.699 7.9807,8.699 5.738,0 7.976,-3.906 7.976,-8.699 H 95.7813"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path8"
|
||||
d="m 133.84,151.148 h 14.359 v 41.571 H 133.84 Z m 14.359,58.883 H 133.84 V 199.5 h 14.359 v 10.531"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path9"
|
||||
d="m 158.809,151.148 h 14.363 v 17.551 c 0,8.942 3.027,13.012 8.937,13.012 3.911,0 6.621,-2.641 6.621,-10.449 v -20.114 h 14.36 v 25.93 c 0,8.621 -4.551,16.594 -15.879,16.594 -6.539,0 -12.281,-2.633 -15.16,-8.613 h -0.16 v 7.66 h -13.082 v -41.571"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path10"
|
||||
d="m 256.059,192.719 h -13 v -7.5 h -0.161 c -3.027,5.101 -7.976,8.453 -14.117,8.453 -12.929,0 -18.75,-9.25 -18.75,-21.621 0,-12.281 7.098,-20.903 18.508,-20.903 5.742,0 10.531,2.231 13.961,7.102 h 0.16 v -2.23 c 0,-8.141 -4.469,-12.051 -12.762,-12.051 -5.988,0 -9.66,1.281 -14.046,3.429 l -0.711,-11.328 c 3.347,-1.199 9.007,-2.629 15.871,-2.629 16.758,0 25.047,5.5 25.047,22.579 z m -31.188,-20.43 c 0,5.672 2.789,10.371 8.141,10.371 6.457,0 9.168,-5.18 9.168,-9.808 0,-6.383 -4.071,-10.692 -9.168,-10.692 -4.313,0 -8.141,3.668 -8.141,10.129"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path11"
|
||||
d="m 306.57,167.738 v 2.641 c 0,12.359 -5.59,23.293 -20.992,23.293 -12.918,0 -22.258,-7.973 -22.258,-21.703 0,-13.719 10.461,-21.778 24.18,-21.778 5.34,0 10.609,0.797 15.238,2.637 v 10.133 c -4.308,-2.32 -8.777,-3.191 -12.687,-3.191 -7.02,0 -11.41,2.23 -12.199,7.968 z m -28.879,8.141 c 0.309,4.793 2.789,8.699 7.969,8.699 5.75,0 7.981,-3.906 7.981,-8.699 h -15.95"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path12"
|
||||
d="m 312.469,152.191 c 4.23,-1.363 8.621,-2 15.082,-2 9.41,0 19.39,2.797 19.39,13.879 0,15.801 -21.39,10.7 -21.39,17.16 0,2.309 3.519,2.872 6.629,2.872 3.59,0 8.129,-0.961 11.172,-2.793 l 1.109,9.972 c -4.621,1.84 -9.652,2.391 -14.602,2.391 -8.289,0 -17.711,-3.91 -17.711,-13.481 0,-15 20.43,-10.05 20.43,-17.07 0,-2.871 -2.879,-3.351 -5.828,-3.351 -5.18,0 -10.129,1.429 -13.48,2.871 l -0.801,-10.45"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path13"
|
||||
d="m 350.289,182.66 h 8.211 v -16.91 c 0,-9.891 3.121,-15.559 15.961,-15.559 3.59,0 6.301,0.481 9.019,0.797 l -0.48,9.34 c -1.441,-0.238 -2.949,-0.558 -4.391,-0.558 -4.55,0 -5.738,2.55 -5.738,7.582 v 15.308 h 10.051 v 10.059 h -10.051 v 13.722 l -14.133,-4.39 v -9.332 h -8.449 V 182.66"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path14"
|
||||
d="M 433.66,192.719 H 419.301 V 175.16 c 0,-8.93 -3.031,-13 -8.942,-13 -3.91,0 -6.621,2.629 -6.621,10.449 v 20.11 h -14.359 v -25.93 c 0,-8.617 4.551,-16.598 15.883,-16.598 6.539,0 12.277,2.637 15.16,8.618 h 0.156 v -7.661 h 13.082 z m -18.75,5.101 h 11.488 v 11.489 H 414.91 Z m -18.191,0 h 11.492 v 11.489 H 396.719 V 197.82"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path15"
|
||||
d="m 472.988,193.199 c -1.429,0.231 -3.187,0.473 -4.859,0.473 -6.231,0 -9.82,-3.352 -12.289,-8.613 h -0.16 v 7.66 h -13.078 v -41.571 h 14.359 v 17.551 c 0,8.141 3.75,13.012 10.449,13.012 1.668,0 3.27,0 4.86,-0.481 l 0.718,11.969"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path16"
|
||||
d="m 475.621,151.148 h 35.75 v 10.532 h -19.312 l 18.992,19.55 v 11.489 H 476.02 v -10.528 h 18.589 l -18.988,-19.55 v -11.493"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path17"
|
||||
d="m 514.238,182.66 h 8.223 v -16.91 c 0,-9.891 3.109,-15.559 15.949,-15.559 3.59,0 6.309,0.481 9.02,0.797 l -0.481,9.34 c -1.437,-0.238 -2.949,-0.558 -4.39,-0.558 -4.547,0 -5.739,2.55 -5.739,7.582 v 15.308 h 10.051 v 10.059 H 536.82 v 13.722 l -14.121,-4.39 v -9.332 h -8.461 V 182.66"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.1 KiB |
48
public/signaturen/Druckleistung.svg
Normal file
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="77.166702"
|
||||
height="31.680225"
|
||||
viewBox="0 0 77.166703 31.680225"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-3.0906266,-12.348001)">
|
||||
<path
|
||||
id="path1"
|
||||
d="m 266.809,262.781 h -69.297 v 69.309 h 69.297 z"
|
||||
style="fill:none;stroke:#52afe6;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 23.1797,238.48 H 555.031"
|
||||
style="fill:none;stroke:#52afe6;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 525.48,192.941 76.45,45.528 -76.45,45.543 v -91.071"
|
||||
style="fill:#52afe6;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="m 136.078,118.75 h -14.406 v -7.422 h 14.406 V 96.9883 h 7.422 v 14.3397 h 14.422 v 7.422 H 143.5 v 14.34 h -7.422 v -14.34"
|
||||
style="fill:#00adef;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="m 197.23,96.9883 v 7.8517 h -20.332 c 8.133,7.988 18.762,17.691 18.762,28.25 0,9.781 -6.129,14.558 -15.621,14.558 -5.07,0 -10.277,-1.289 -14.769,-3.57 l 0.781,-8.277 c 3.277,2.14 7.277,4 11.488,4 4.07,0 8.133,-2.141 8.133,-6.711 0,-9.129 -16.91,-23.262 -21.551,-27.75 v -8.3517 h 33.109"
|
||||
style="fill:#00adef;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path6"
|
||||
d="m 220.051,311.16 4.988,-6.488 8.422,6.848 v -38.461 h 9.988 v 49.8 h -8.847 L 220.051,311.16"
|
||||
style="fill:#00adef;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
53
public/signaturen/Druckleitung_ab_Hydrant.svg
Normal file
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="73.193268"
|
||||
height="47.721371"
|
||||
viewBox="0 0 73.193268 47.721371"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-5.0359332,-4.757068)">
|
||||
<path
|
||||
id="path1"
|
||||
d="m 110.031,289.859 v 33.379 l 17.449,19.141 h 385.071"
|
||||
style="fill:none;stroke:#52afe6;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 497.469,290.852 89.25,51.527 -89.25,51.543 v -103.07"
|
||||
style="fill:#52afe6;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 348.309,87.5391 H 125.98 L 110.031,104.48 v 32.391"
|
||||
style="fill:none;stroke:#52afe6;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="M 333.23,139.07 422.48,87.5391 333.23,36.0117 V 139.07"
|
||||
style="fill:#52afe6;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="m 179.801,213.609 c 0,-38.531 -31.242,-69.757 -69.77,-69.757 -38.5193,0 -69.7615,31.226 -69.7615,69.757 0,38.532 31.2422,69.77 69.7615,69.77 38.528,0 69.77,-31.238 69.77,-69.77 z"
|
||||
style="fill:none;stroke:#52afe6;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path6"
|
||||
d="m 110.031,208.16 v 3.75 m 0,-3.75 v 3.75"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path7"
|
||||
d="m 141.891,213.621 c 0,17.578 -14.27,31.848 -31.86,31.848 -17.5818,0 -31.8513,-14.27 -31.8513,-31.848 0,-17.59 14.2695,-31.859 31.8513,-31.859 17.59,0 31.86,14.269 31.86,31.859"
|
||||
style="fill:#52afe6;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
73
public/signaturen/Eingang.svg
Normal file
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="77.053093"
|
||||
height="43.783798"
|
||||
viewBox="0 0 77.053093 43.783798"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-3.2786399,-6.5602679)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 341.461,103.801 H 27.0898 V 377.898 H 341.461 Z"
|
||||
style="fill:none;stroke:#231f20;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 341.461,103.801 H 599.988 V 272.039 H 341.461"
|
||||
style="fill:none;stroke:#231f20;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 98.6211,103.801 v 56.59 h 65.5779 v -56.59"
|
||||
style="fill:none;stroke:#231f20;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="M 179.641,67.4492 V 121.391"
|
||||
style="fill:none;stroke:#231f20;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="M 229.781,67.4492 V 121.391"
|
||||
style="fill:none;stroke:#231f20;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path6"
|
||||
d="m 309.621,159.172 h 56.508"
|
||||
style="fill:none;stroke:#231f20;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path7"
|
||||
d="m 309.621,224.281 h 56.508"
|
||||
style="fill:none;stroke:#231f20;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path8"
|
||||
d="M 224.711,52.5586 203.762,88.8281 182.809,52.5586 h 41.902"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path9"
|
||||
d="m 363.012,170.93 h 4.769 v 3.808 h 0.098 c 1.332,-2.008 4.402,-4.449 9.223,-4.449 8.16,0 11.597,7.199 11.597,14.621 0,7.262 -3.808,13.668 -11.648,13.668 -4.723,0 -7.422,-1.848 -8.961,-4.34 h -0.102 v 16.422 h -4.976 z m 20.398,13.609 c 0.102,-4.238 -2.121,-10.219 -7.469,-10.219 -5.621,0 -7.953,5.559 -7.953,10.059 0,5.043 2.59,10.172 8,10.172 5.403,0 7.524,-5.129 7.422,-10.012"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path10"
|
||||
d="m 138.199,73.5313 c 2.012,1.6992 5.031,2.7578 7.84,2.7578 4.981,0 6.672,-2.3907 6.672,-7.0508 -1.961,0.1133 -3.332,0.1133 -5.289,0.1133 -5.141,0 -12.563,-2.1211 -12.563,-8.9024 0,-5.8789 4.082,-8.4297 9.911,-8.4297 4.55,0 7.199,2.4922 8.371,4.1289 h 0.097 v -3.4882 h 4.672 c -0.109,0.789 -0.219,2.2187 -0.219,5.3007 v 11.168 c 0,7.3711 -3.121,11.1797 -10.863,11.1797 -3.437,0 -6.406,-1.0586 -8.898,-2.5391 z m 14.512,-10.3829 c 0,-4.0273 -2.59,-7.0976 -7.52,-7.0976 -2.281,0 -5.031,1.539 -5.031,4.3984 0,4.7617 6.668,5.1914 9.371,5.1914 1.059,0 2.117,-0.1093 3.18,-0.1093 v -2.3829"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path11"
|
||||
d="m 119.77,132.211 c 2.64,0.687 5.351,0.898 8.05,0.898 3.918,0 8.211,-1.269 8.211,-5.398 0,-4.723 -3.871,-5.93 -7.472,-5.93 -3.129,0 -6.2,0.629 -9.008,2.008 l -0.16,-8 c 3.019,-0.738 6.257,-1.328 9.91,-1.328 8.269,0 16.269,3.238 16.269,13.57 0,8.16 -6.629,11.438 -14.148,11.438 -0.633,0 -1.543,-0.11 -2.91,-0.207 v 6.136 h 15.629 v 6.68 h -24.11 l -0.261,-19.867"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.5 KiB |
38
public/signaturen/Einsatzleiter.svg
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="26.387999"
|
||||
height="50.766693"
|
||||
viewBox="0 0 26.387999 50.766693"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-28.350533,-3.234668)">
|
||||
<path
|
||||
id="path1"
|
||||
d="m 363.16,101.879 c 0,-39.9298 -32.57,-72.2892 -72.762,-72.2892 -40.179,0 -72.769,32.3594 -72.769,72.2892 0,39.922 32.59,72.269 72.769,72.269 40.192,0 72.762,-32.347 72.762,-72.269 z"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 285.43,174.148 V 400.34 h 125.109"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 285.43,268.828 H 410.539"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="M 285.43,332.539 H 410.539"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
33
public/signaturen/Elektrizitaet.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="60.768246"
|
||||
height="47.311066"
|
||||
viewBox="0 0 60.768246 47.311066"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-11.286613,-4.6197603)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 335.82,267.02 292.738,193 331.781,203.359 286.738,124.34"
|
||||
style="fill:none;stroke:#f47216;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 265.289,146.539 0.32,-59.2577 51.18,29.8987 -51.5,29.359"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 536.262,42.7188 H 88.8594 L 307.199,383.441 Z"
|
||||
style="fill:none;stroke:#f47216;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
33
public/signaturen/Elektrotableau.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="77.012039"
|
||||
height="29.204132"
|
||||
viewBox="0 0 77.01204 29.204132"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-3.1572933,-13.937068)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 596.27,108.641 H 28.6797 V 317.672 H 596.27 Z"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 96.5195,149.238 312.922,266.809 254.328,152.93 427.77,229.199"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 420.629,190.91 517.578,268.691 394.73,249.82 420.629,190.91"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
43
public/signaturen/Entrauchung.svg
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="25.9984"
|
||||
height="49.213737"
|
||||
viewBox="0 0 25.9984 49.213737"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-28.828133,-3.7103276)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 406.199,35.2695 H 221.211 V 229.93 h 184.988 z"
|
||||
style="fill:none;stroke:#100f0d;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 406.199,35.2695 221.211,229.93 V 35.2695 h 184.988"
|
||||
style="fill:#100f0d;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 292.09,244.801 V 360.828"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="M 335.32,244.801 V 363.578"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="m 271.539,334.82 43.07,56.219 41.262,-56.219"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
38
public/signaturen/Entwicklungsgrenze.svg
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="74.721397"
|
||||
height="34.585373"
|
||||
viewBox="0 0 74.721398 34.585373"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-4.3973999,-11.317334)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 37.9805,180.621 H 388.449 v -34.34 l 114.512,66.36 -114.512,66.339 V 244.629 H 37.9805 v -64.008"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 37.9805,180.621 H 388.449 v -34.34 l 114.512,66.36 -114.512,66.339 V 244.629 H 37.9805 Z"
|
||||
style="fill:none;stroke:#1b1816;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 517.371,337.32 h 71.02 V 87.9297 h -71.02 V 337.32"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="m 517.371,337.32 h 71.02 V 87.9297 h -71.02 z"
|
||||
style="fill:none;stroke:#1b1816;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
33
public/signaturen/Explosion.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="60.768242"
|
||||
height="47.310593"
|
||||
viewBox="0 0 60.768242 47.310593"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-11.286615,-4.578569)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 536.262,43.0313 H 88.8594 L 307.199,383.75 Z"
|
||||
style="fill:none;stroke:#f47216;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 250.461,117.91 h 54.18 v 14.211 H 270.5 v 17.02 h 31.121 v 14.218 H 270.5 v 15.512 h 32.949 v 14.219 h -52.988 v -75.18"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 310.781,117.91 h 21.86 l 9.269,17.449 9.371,-17.449 h 23.367 l -18.738,28.75 17.551,27.36 H 352.25 l -8.73,-16.801 -8.29,16.801 H 312.289 L 329.84,146.449 310.781,117.91"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
38
public/signaturen/Fernsignaltableau.svg
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="63.626572"
|
||||
height="37.522346"
|
||||
viewBox="0 0 63.626572 37.522346"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-9.9572931,-9.7788012)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 546.879,77.4414 H 79.6797 V 348.859 H 546.879 Z"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 301.309,210.762 c 0,-47.992 -38.899,-86.891 -86.879,-86.891 -47.981,0 -86.879,38.899 -86.879,86.891 0,47.976 38.898,86.879 86.879,86.879 47.98,0 86.879,-38.903 86.879,-86.879 z"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 276.578,150.051 152.762,271.961"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="M 276.09,271.961 152.281,150.051"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
33
public/signaturen/Feuer-Brandherd.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="50.139999"
|
||||
height="49.564117"
|
||||
viewBox="0 0 50.139999 49.564117"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-16.524,-3.8240013)">
|
||||
<path
|
||||
id="path1"
|
||||
d="m 494.98,212.648 c 0,-99.898 -81.941,-180.8589 -183.031,-180.8589 -101.078,0 -183.019,80.9609 -183.019,180.8589 0,99.891 81.941,180.872 183.019,180.872 101.09,0 183.031,-80.981 183.031,-180.872"
|
||||
style="fill:#ed1c24;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 494.98,212.648 c 0,-99.898 -81.941,-180.8589 -183.031,-180.8589 -101.078,0 -183.019,80.9609 -183.019,180.8589 0,99.891 81.941,180.872 183.019,180.872 101.09,0 183.031,-80.981 183.031,-180.872 z"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 264.809,142.191 h 37.562 v 56.739 h 54.301 v 26.648 h -54.301 v 30.891 h 56.731 v 26.64 H 264.809 V 142.191"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
38
public/signaturen/Feuer-Entwicklungsgrenze.svg
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="74.721397"
|
||||
height="34.585373"
|
||||
viewBox="0 0 74.721398 34.585373"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-4.2692666,-11.317334)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 37.0195,180.621 H 387.48 v -34.34 L 502,212.641 387.48,278.98 V 244.629 H 37.0195 v -64.008"
|
||||
style="fill:#ed1c24;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 37.0195,180.621 H 387.48 v -34.34 L 502,212.641 387.48,278.98 V 244.629 H 37.0195 Z"
|
||||
style="fill:none;stroke:#1b1816;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 516.41,337.32 h 71.02 V 87.9297 H 516.41 V 337.32"
|
||||
style="fill:#ed1c24;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="m 516.41,337.32 h 71.02 V 87.9297 h -71.02 z"
|
||||
style="fill:none;stroke:#1b1816;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
28
public/signaturen/Feuer-Horizontale_Entwicklung.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="71.837395"
|
||||
height="22.173725"
|
||||
viewBox="0 0 71.837395 22.173725"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-5.9984399,-17.259945)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 49.9883,178.66 H 444.77 v -38.551 l 129,74.5 -129,74.481 V 250.531 H 49.9883 V 178.66"
|
||||
style="fill:#ed1c24;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 49.9883,178.66 H 444.77 v -38.551 l 129,74.5 -129,74.481 V 250.531 H 49.9883 Z"
|
||||
style="fill:none;stroke:#1b1816;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
38
public/signaturen/Feuer-Vertikale_Entwicklung.svg
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="70.764389"
|
||||
height="50.089214"
|
||||
viewBox="0 0 70.764389 50.089214"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-6.1946132,-3.5346933)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 93.6719,390.691 V 164.02 H 55.1211 L 129.621,35.0195 204.102,164.02 H 165.539 V 390.691 H 93.6719"
|
||||
style="fill:#ed1c24;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 93.6719,390.691 V 164.02 H 55.1211 L 129.621,35.0195 204.102,164.02 h -38.563 v 226.671 z"
|
||||
style="fill:none;stroke:#1b1816;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 529.98,35.0195 V 261.691 h 38.551 l -74.5,129 -74.48,-129 h 38.558 V 35.0195 h 71.871"
|
||||
style="fill:#ed1c24;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="M 529.98,35.0195 V 261.691 h 38.551 l -74.5,129 -74.48,-129 h 38.558 V 35.0195 Z"
|
||||
style="fill:none;stroke:#1b1816;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
33
public/signaturen/Feuerwehr_de.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="50.141064"
|
||||
height="49.562439"
|
||||
viewBox="0 0 50.141064 49.562439"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-16.622933,-3.6069347)">
|
||||
<path
|
||||
id="path1"
|
||||
d="m 495.73,214.289 c 0,-99.898 -81.949,-180.8593 -183.039,-180.8593 -101.082,0 -183.019,80.9613 -183.019,180.8593 0,99.891 81.937,180.859 183.019,180.859 101.09,0 183.039,-80.968 183.039,-180.859 z"
|
||||
style="fill:none;stroke:#52afe6;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 208.539,165.43 h 26.039 v 39.34 h 37.66 v 18.48 h -37.66 v 21.422 h 39.344 v 18.476 H 208.539 V 165.43"
|
||||
style="fill:#00adef;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 300.801,165.43 h 33.738 l 12.883,75.039 h 0.277 l 13.86,-75.039 h 33.461 l 21.839,97.718 H 391.52 L 378.781,188.109 H 378.5 l -13.719,75.039 h -33.043 l -13.16,-75.039 h -0.277 l -12.602,75.039 h -26.597 l 21.699,-97.718"
|
||||
style="fill:#00adef;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
38
public/signaturen/Funk.svg
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="40.822491"
|
||||
height="51.49313"
|
||||
viewBox="0 0 40.822491 51.49313"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-21.210841,-3.0521347)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 162.691,21.5703 306.941,172.07 204.871,151.23 393.219,334.301"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 427.219,270.012 465.25,404.309 329.93,370.121 427.219,270.012"
|
||||
style="fill:#00adef;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 346.859,154.5 h 11.61 v 19.781 h 0.121 L 372.129,154.5 h 14.793 l -17.352,23.281 16.102,20.27 H 371.699 L 358.59,180.27 h -0.121 v 17.781 h -11.61 V 154.5"
|
||||
style="fill:#00adef;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="m 405.32,154.5 h 11.61 v 43.551 h -10.231 l -14.789,-9.602 5.18,-7.871 8.23,5.871 V 154.5"
|
||||
style="fill:#00adef;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
28
public/signaturen/Gas.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="60.768242"
|
||||
height="47.310577"
|
||||
viewBox="0 0 60.768242 47.310578"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-11.286615,-4.7215026)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 536.262,44.3594 H 88.8594 L 307.199,385.078 Z"
|
||||
style="fill:none;stroke:#f47216;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 348.691,165.672 h -31.132 v -14.223 h 11.742 V 136.59 c -1.832,-0.86 -4.41,-1.301 -7.11,-1.301 -14.64,0 -25.089,8.941 -25.089,23.699 0,17.563 13.347,24.34 29.617,24.34 4.742,0 12.062,-1.18 18.312,-4.848 l 1.61,16.379 c -7.321,2.801 -17.77,3.34 -22.719,3.34 -27.57,0 -47.5,-10.879 -47.5,-39.211 0,-28.429 23.156,-38.558 43.187,-38.558 6.891,0 16.371,0.218 29.082,3.449 v 41.793"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
38
public/signaturen/GefaehrlicheStoffe-Entwicklungsgrenze.svg
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="74.721306"
|
||||
height="34.585373"
|
||||
viewBox="0 0 74.721306 34.585373"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-4.4880266,-11.317334)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 38.6602,180.621 H 389.129 v -34.34 l 114.512,66.36 -114.512,66.339 V 244.629 H 38.6602 v -64.008"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 38.6602,180.621 H 389.129 v -34.34 l 114.512,66.36 -114.512,66.339 V 244.629 H 38.6602 Z"
|
||||
style="fill:none;stroke:#1b1816;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 518.051,337.32 H 589.07 V 87.9297 H 518.051 V 337.32"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="M 518.051,337.32 H 589.07 V 87.9297 h -71.019 z"
|
||||
style="fill:none;stroke:#1b1816;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="71.837311"
|
||||
height="22.173725"
|
||||
viewBox="0 0 71.837311 22.173725"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-6.2171865,-17.259945)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 51.6289,178.66 H 446.41 v -38.551 l 129,74.5 -129,74.481 V 250.531 H 51.6289 V 178.66"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 51.6289,178.66 H 446.41 v -38.551 l 129,74.5 -129,74.481 V 250.531 H 51.6289 Z"
|
||||
style="fill:none;stroke:#1b1816;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="70.764442"
|
||||
height="50.089237"
|
||||
viewBox="0 0 70.764443 50.089237"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-6.4133568,-3.5347)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 95.3086,390.691 V 164.02 H 56.7617 L 131.262,35.0195 205.738,164.02 H 167.18 V 390.691 H 95.3086"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 95.3086,390.691 V 164.02 H 56.7617 L 131.262,35.0195 205.738,164.02 H 167.18 v 226.671 z"
|
||||
style="fill:none;stroke:#1b1816;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 531.621,35.0195 V 261.691 h 38.551 l -74.5,129 -74.481,-129 H 459.75 V 35.0195 h 71.871"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="M 531.621,35.0195 V 261.691 h 38.551 l -74.5,129 -74.481,-129 H 459.75 V 35.0195 Z"
|
||||
style="fill:none;stroke:#1b1816;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
33
public/signaturen/Gefaehrliche_Stoffe.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="50.141598"
|
||||
height="49.564117"
|
||||
viewBox="0 0 50.141598 49.564117"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-16.5292,-3.8240013)">
|
||||
<path
|
||||
id="path1"
|
||||
d="m 495.031,212.648 c 0,-99.898 -81.941,-180.8589 -183.043,-180.8589 -101.078,0 -183.019,80.9609 -183.019,180.8589 0,99.891 81.941,180.872 183.019,180.872 101.102,0 183.043,-80.981 183.043,-180.872"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 495.031,212.648 c 0,-99.898 -81.941,-180.8589 -183.043,-180.8589 -101.078,0 -183.019,80.9609 -183.019,180.8589 0,99.891 81.941,180.872 183.019,180.872 101.102,0 183.043,-80.981 183.043,-180.872 z"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 364.359,174.898 c -10.3,-4.039 -22.82,-7.269 -35.129,-7.269 -27.46,0 -47.039,16.762 -47.039,44.422 0,26.238 17.36,45.629 44.008,45.629 12.922,0 24.629,-3.231 36.75,-9.899 l 3.02,30.489 c -13.52,4.039 -27.449,7.269 -41.789,7.269 -46.43,0 -80.75,-24.43 -80.75,-73.488 0,-53.301 43.398,-72.281 80.949,-72.281 19.18,0 31.101,3.031 41.801,5.652 l -1.821,29.476"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
38
public/signaturen/Gefahr_durch_Loeschen_mit_Wasser.svg
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="60.768242"
|
||||
height="47.310619"
|
||||
viewBox="0 0 60.768242 47.310619"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-11.286615,-4.4332352)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 395.699,91.7109 229.41,170.781"
|
||||
style="fill:none;stroke:#f47216;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 394.879,170.781 230.23,91.7109"
|
||||
style="fill:none;stroke:#f47216;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 276.262,93.6602 h 25.957 l 9.902,57.7308 h 0.219 L 323,93.6602 h 25.738 l 16.813,75.1798 h -19.5 l -9.801,-57.731 h -0.211 L 325.48,168.84 h -25.421 l -10.118,-57.731 h -0.222 l -9.688,57.731 h -20.472 l 16.703,-75.1798"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="M 536.262,44.1211 H 88.8594 L 307.199,384.84 Z"
|
||||
style="fill:none;stroke:#f47216;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
38
public/signaturen/HRF.svg
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="75.185463"
|
||||
height="38.587479"
|
||||
viewBox="0 0 75.185463 38.587479"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-4.2666666,-9.3162679)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 590.891,72.9219 H 37 V 352.328 h 553.891 z"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 429.82,352.328 430.391,72.9219"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 430.391,72.9219 583.891,210.801 429.828,348.129"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="M 78.3008,257.09 305.191,146.461 37,88.3281"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
38
public/signaturen/Helikopterlandeplatz.svg
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="72.734825"
|
||||
height="45.84901"
|
||||
viewBox="0 0 72.734825 45.84901"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-5.2291732,-5.6854679)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 579.73,45.6914 H 44.2188 V 379.559 H 579.73 Z"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 44.2188,211.871 H 579.73"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 308.109,296.09 c 0,0 67.411,48.969 99.629,48.539 32.242,-0.41 46.883,-19.238 46.473,-48.539 -0.41,-29.309 -10.891,-49.41 -38.922,-49.41 -28.059,0 -85.398,34.332 -107.18,49.41 z"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="m 308.109,296.09 c 0,0 -59.859,-36.852 -74.089,-43.539 -14.239,-6.711 -74.098,-25.961 -74.098,38.918 0,64.89 54.008,54.84 75.777,43.543 21.762,-11.301 72.41,-38.922 72.41,-38.922 z"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
28
public/signaturen/Horizontale_Entwicklung.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="71.837273"
|
||||
height="22.173725"
|
||||
viewBox="0 0 71.837273 22.173725"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-6.1265598,-17.259945)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 50.9492,178.66 H 445.73 v -38.551 l 129,74.5 -129,74.481 V 250.531 H 50.9492 V 178.66"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 50.9492,178.66 H 445.73 v -38.551 l 129,74.5 -129,74.481 V 250.531 H 50.9492 Z"
|
||||
style="fill:none;stroke:#1b1816;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
33
public/signaturen/Informationszentrum.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="50.746876"
|
||||
height="50.747902"
|
||||
viewBox="0 0 50.746876 50.747902"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-16.319761,-3.236029)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 312.699,397.93 127.398,212.629 312.699,27.3203 498,212.629 Z"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 312.699,247.43 v 17.492"
|
||||
style="fill:none;stroke:#00adef;stroke-width:15;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 312.699,161.5 v 73.871"
|
||||
style="fill:none;stroke:#00adef;stroke-width:15;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
53
public/signaturen/Innenhydrant_mit_Storzanschluss_DE.svg
Normal file
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="73.323975"
|
||||
height="36.323971"
|
||||
viewBox="0 0 73.323975 36.323971"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-4.5932266,-10.448001)">
|
||||
<path
|
||||
id="path1"
|
||||
d="m 170.66,81.4102 c -72.4803,0 -131.2108,58.7378 -131.2108,131.2188 0,72.461 58.7305,131.211 131.2108,131.211 V 81.4102"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 301.879,212.629 c 0,-72.481 -58.75,-131.2188 -131.219,-131.2188 -72.4803,0 -131.2108,58.7378 -131.2108,131.2188 0,72.461 58.7305,131.211 131.2108,131.211 72.469,0 131.219,-58.75 131.219,-131.211 z"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 382.988,209.879 c 3.871,1 7.821,1.312 11.774,1.312 5.726,0 12,-1.851 12,-7.89 0,-6.903 -5.653,-8.68 -10.922,-8.68 -4.57,0 -9.059,0.93 -13.16,2.949 l -0.231,-11.699 c 4.41,-1.082 9.129,-1.93 14.481,-1.93 12.07,0 23.769,4.719 23.769,19.821 0,11.918 -9.679,16.718 -20.679,16.718 -0.93,0 -2.239,-0.152 -4.258,-0.3 v 8.98 h 22.847 v 9.75 h -35.23 l -0.391,-29.031"
|
||||
style="fill:#0a1323;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="m 430.371,209.879 c 3.879,1 7.82,1.312 11.77,1.312 5.73,0 12,-1.851 12,-7.89 0,-6.903 -5.653,-8.68 -10.911,-8.68 -4.57,0 -9.058,0.93 -13.171,2.949 l -0.231,-11.699 c 4.422,-1.082 9.141,-1.93 14.481,-1.93 12.082,0 23.769,4.719 23.769,19.821 0,11.918 -9.68,16.718 -20.668,16.718 -0.93,0 -2.25,-0.152 -4.262,-0.3 v 8.98 h 22.84 v 9.75 h -35.226 l -0.391,-29.031"
|
||||
style="fill:#0a1323;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="m 470.328,183.941 h 9.75 l 15.024,55.899 h -9.75 l -15.024,-55.899"
|
||||
style="fill:#0a1323;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path6"
|
||||
d="m 501.379,184.871 h 15.48 l 19.36,42.348 v 11.691 h -38.867 v -10.219 h 24.16 l -20.133,-43.82"
|
||||
style="fill:#0a1323;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path7"
|
||||
d="m 546.672,209.879 c 3.867,1 7.816,1.312 11.769,1.312 5.731,0 12,-1.851 12,-7.89 0,-6.903 -5.652,-8.68 -10.921,-8.68 -4.559,0 -9.051,0.93 -13.161,2.949 l -0.23,-11.699 c 4.41,-1.082 9.141,-1.93 14.48,-1.93 12.082,0 23.77,4.719 23.77,19.821 0,11.918 -9.68,16.718 -20.668,16.718 -0.93,0 -2.25,-0.152 -4.262,-0.3 v 8.98 h 22.84 v 9.75 h -35.23 l -0.387,-29.031"
|
||||
style="fill:#0a1323;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
43
public/signaturen/KP_Font.svg
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="34.833794"
|
||||
height="52.252541"
|
||||
viewBox="0 0 34.833794 52.252541"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-24.347406,-2.4305347)">
|
||||
<path
|
||||
id="path1"
|
||||
d="m 438.859,299.648 c 0,-58.929 -47.781,-106.718 -106.711,-106.718 -58.937,0 -106.718,47.789 -106.718,106.718 0,58.942 47.781,106.723 106.718,106.723 58.93,0 106.711,-47.781 106.711,-106.723 z"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 225.43,299.648 V 59.9102"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 266.191,22.9883 186.422,103.852"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="M 266.461,103.578 186.141,23.2617"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="m 311.5,268.789 h 16.449 v 24.852 h 23.781 v 11.668 h -23.781 v 13.531 h 24.84 v 11.672 H 311.5 v -61.723"
|
||||
style="fill:#00adef;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
28
public/signaturen/Kamin.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="49.806267"
|
||||
height="49.806744"
|
||||
viewBox="0 0 49.806267 49.806744"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-16.892133,-3.753468)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 495.238,32.8984 H 131.691 V 396.449 L 495.238,32.8984"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 495.238,32.8984 H 131.691 V 396.449 h 363.547 z"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 963 B |
23
public/signaturen/Kleinloeschgeraet.svg
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="22.575035"
|
||||
height="51.323757"
|
||||
viewBox="0 0 22.575035 51.323757"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-30.331749,-2.9947885)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 232.488,27.2109 H 391.801 L 313.488,402.141 Z"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 730 B |
38
public/signaturen/Kontrollstelle.svg
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="34.509331"
|
||||
height="48.470772"
|
||||
viewBox="0 0 34.509331 48.470772"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-24.621333,-4.4212013)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 438.48,37.9102 H 189.66 V 391.441 h 248.82 z"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 188.031,221.441 c 93.528,65.887 192.989,65.84 250.641,19.368"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 188.031,182.621 c 90,-58.23 187.699,-62.351 250.641,-11.769"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="m 312.488,190.891 c 8.313,0 15.043,6.738 15.043,15.039 0,8.308 -6.73,15.039 -15.043,15.039 -8.297,0 -15.039,-6.731 -15.039,-15.039 0,-8.301 6.742,-15.039 15.039,-15.039"
|
||||
style="fill:#00adef;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
63
public/signaturen/Leitungsdaehte_mit_Spannungsangabe.svg
Normal file
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="78.285355"
|
||||
height="17.689066"
|
||||
viewBox="0 0 78.285355 17.689066"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-2.6786399,-19.348001)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 20.0898,233.039 H 607.23"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 219.762,233.281 c 0,-24.203 -19.672,-43.82 -43.942,-43.82 -24.261,0 -43.929,19.617 -43.929,43.82 0,24.199 19.668,43.809 43.929,43.809 24.27,0 43.942,-19.61 43.942,-43.809"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 219.762,233.281 c 0,-24.203 -19.672,-43.82 -43.942,-43.82 -24.261,0 -43.929,19.617 -43.929,43.82 0,24.199 19.668,43.809 43.929,43.809 24.27,0 43.942,-19.61 43.942,-43.809 z"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="m 495.43,233.281 c 0,-24.203 -19.668,-43.82 -43.942,-43.82 -24.258,0 -43.929,19.617 -43.929,43.82 0,24.199 19.671,43.809 43.929,43.809 24.274,0 43.942,-19.61 43.942,-43.809"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="m 495.43,233.281 c 0,-24.203 -19.668,-43.82 -43.942,-43.82 -24.258,0 -43.929,19.617 -43.929,43.82 0,24.199 19.671,43.809 43.929,43.809 24.274,0 43.942,-19.61 43.942,-43.809 z"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path6"
|
||||
d="m 240.102,150.16 h 11.609 v 43.551 h -10.242 l -14.778,-9.602 5.168,-7.871 8.243,5.871 V 150.16"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path7"
|
||||
d="m 293.879,192.469 c -3.301,1.312 -6.859,1.992 -11.289,1.992 -14.41,0 -19.219,-11.039 -19.219,-24.391 0,-10.922 4.309,-20.648 16.719,-20.648 9.609,0 16.351,6.668 16.351,14.719 0,7.8 -5.05,13.73 -13.043,13.73 -4.367,0 -7.359,-1.5 -9.418,-4.43 h -0.128 c 0.07,7.668 2.437,12.789 10.168,12.789 4.25,0 7.3,-1.058 9.179,-2.308 z m -19.527,-28.891 c 0,3.371 1.878,6.434 5.679,6.434 4.059,0 5.547,-3.313 5.547,-6.934 0,-3.367 -1.93,-6.18 -5.547,-6.18 -3.742,0 -5.679,3.122 -5.679,6.68"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path8"
|
||||
d="m 321.578,150.16 h 11.231 v 16.102 h 0.132 l 8.981,-16.102 h 13.609 l -12.23,17.602 11.289,14.91 h -12.289 l -9.36,-13.66 h -0.132 v 27.949 H 321.578 V 150.16"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path9"
|
||||
d="m 371.43,150.16 h 14.359 l 14.84,43.551 h -11.91 L 378.98,159.52 h -0.121 l -9.668,34.191 H 356.84 l 14.59,-43.551"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
33
public/signaturen/Lift.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="49.546932"
|
||||
height="49.547974"
|
||||
viewBox="0 0 49.546932 49.547974"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-16.9052,-3.7521347)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 493.391,32.4492 H 131.789 V 394.059 h 361.602 z"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 493.391,32.4492 131.789,394.059"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 131.789,32.4492 493.391,394.059"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
43
public/signaturen/Luefter.svg
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="68.655785"
|
||||
height="41.02544"
|
||||
viewBox="0 0 68.655785 41.02544"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-6.9854132,-8.0131316)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 131.68,121.012 H 57.3906 V 308.328 H 131.68 Z"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 206.98,64.4102 -74.449,56.6018 v 187.316 l 74.449,53.774 z"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 260.762,248.219 H 470.539"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="M 260.762,178.289 H 470.539"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="M 457.309,323.281 V 103.219 l 110,110.031 -110,110.031"
|
||||
style="fill:#00adef;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
33
public/signaturen/MS_de.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="47.630798"
|
||||
height="47.630772"
|
||||
viewBox="0 0 47.630799 47.630772"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-17.853066,-4.607868)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 486.129,40.4102 H 138.898 V 387.641 h 347.231 z"
|
||||
style="fill:none;stroke:#52afe6;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 220.039,231.18 h 22.352 l -0.493,65.832 h 0.25 L 263.02,231.18 h 21 l 21.859,65.832 h 0.25 l -0.367,-65.832 h 22.347 v 85.718 H 293.48 l -19.031,-56.976 h -0.25 L 256.02,316.898 H 220.039 V 231.18"
|
||||
style="fill:#00adef;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 341.738,233.391 c 7.621,-2.45 17.571,-3.68 25.551,-3.68 19.031,0 37.699,6.019 37.699,28.238 0,30.949 -40.527,21.621 -40.527,35.5 0,7.492 9.578,7.981 15.348,7.981 6.511,0 13.14,-1.231 19.043,-3.93 l 1.468,17.68 c -5.769,1.968 -13.871,3.199 -22.101,3.199 -17.199,0 -37.34,-5.649 -37.34,-26.289 0,-31.192 40.531,-21.121 40.531,-37.078 0,-6.883 -6.879,-8.352 -14.121,-8.352 -9.461,0 -17.687,2.449 -23.578,5.641 l -1.973,-18.91"
|
||||
style="fill:#00adef;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
43
public/signaturen/Massstab.svg
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="58.059853"
|
||||
height="15.795732"
|
||||
viewBox="0 0 58.059853 15.795732"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-12.616146,-20.628268)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 129.891,155.988 H 160.41 V 270.52 H 133.5 L 94.6211,245.25 108.238,224.578 129.891,240 v -84.012"
|
||||
style="fill:#0a1323;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 195.691,214.898 h 27.559 v 26.582 h -27.559 z m 0,-58.91 h 27.559 v 26.582 h -27.559 v -26.582"
|
||||
style="fill:#0a1323;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 246.879,208.988 c 8.199,2.133 16.57,2.793 24.941,2.793 12.141,0 25.43,-3.941 25.43,-16.742 0,-14.598 -11.98,-18.367 -23.141,-18.367 -9.679,0 -19.187,1.969 -27.89,6.226 l -0.489,-24.769 c 9.348,-2.301 19.36,-4.109 30.68,-4.109 25.602,0 50.371,10.011 50.371,42.011 0,25.258 -20.511,35.438 -43.812,35.438 -1.969,0 -4.75,-0.328 -9.02,-0.66 v 19.031 h 48.403 v 20.68 h -74.653 l -0.82,-61.532"
|
||||
style="fill:#0a1323;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="m 385.191,154.02 c 37.899,0 44.469,29.539 44.469,59.23 0,29.699 -6.57,59.238 -44.469,59.238 -37.902,0 -44.461,-29.539 -44.461,-59.238 0,-29.691 6.559,-59.23 44.461,-59.23 z m 0,20.679 c -13.781,0 -14.929,20.34 -14.929,38.551 0,18.219 1.148,38.559 14.929,38.559 13.778,0 14.93,-20.34 14.93,-38.559 0,-18.211 -1.152,-38.551 -14.93,-38.551"
|
||||
style="fill:#0a1323;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="m 485.602,154.02 c 37.91,0 44.468,29.539 44.468,59.23 0,29.699 -6.558,59.238 -44.468,59.238 -37.903,0 -44.461,-29.539 -44.461,-59.238 0,-29.691 6.558,-59.23 44.461,-59.23 z m 0,20.679 c -13.782,0 -14.93,20.34 -14.93,38.551 0,18.219 1.148,38.559 14.93,38.559 13.789,0 14.937,-20.34 14.937,-38.559 0,-18.211 -1.148,-38.551 -14.937,-38.551"
|
||||
style="fill:#0a1323;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
28
public/signaturen/Materialdepot.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="50.141731"
|
||||
height="49.562546"
|
||||
viewBox="0 0 50.141731 49.562546"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-16.519733,-3.8560013)">
|
||||
<path
|
||||
id="path1"
|
||||
d="m 494.961,214.82 c 0,-99.898 -81.949,-180.8591 -183.039,-180.8591 -101.082,0 -183.024,80.9611 -183.024,180.8591 0,99.879 81.942,180.86 183.024,180.86 101.09,0 183.039,-80.981 183.039,-180.86 z"
|
||||
style="fill:none;stroke:#52afe6;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 250.328,165.961 h 25.481 L 275.25,241 h 0.281 l 23.797,-75.039 H 323.27 L 348.191,241 h 0.278 l -0.418,-75.039 h 25.48 v 97.719 h -39.48 l -21.699,-64.961 h -0.282 l -20.718,64.961 h -41.024 v -97.719"
|
||||
style="fill:#00adef;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,57.28)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
33
public/signaturen/Medienkontaktstelle.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="34.925465"
|
||||
height="50.926559"
|
||||
viewBox="0 0 34.925465 50.926559"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-24.138533,-2.9600013)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 437.98,28.0508 H 186.039 V 400 H 437.98 Z"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 312.012,260.211 V 275.02"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 312.012,184.27 v 68.05"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
28
public/signaturen/Moeglicher_Wasserbezugsort.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="71.030006"
|
||||
height="28.917583"
|
||||
viewBox="0 0 71.030007 28.917583"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-7.0159581,-14.121084)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 581.078,318.629 453.262,109.41 H 188.5 L 56.8516,318.629"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 508.789,202.039 H 129.148 l 58.293,-92.629 h 264.75 l 56.598,92.629"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 987 B |
33
public/signaturen/Nordrichtung.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="12.567733"
|
||||
height="46.999985"
|
||||
viewBox="0 0 12.567733 46.999985"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-35.292132,-4.9772013)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 315.93,37.3711 V 303.488"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 344.262,284.172 315.93,389.871 287.602,284.172 h 56.66"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 264.691,129.371 h 25.11 l -0.879,70.027 h 0.289 l 35.82,-70.027 h 33.918 v 102.481 h -24.961 l 0.442,-69.59 h -0.289 l -34.653,69.59 H 264.691 V 129.371"
|
||||
style="fill:#0a1323;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
28
public/signaturen/Oberflurhydrant.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="50.141197"
|
||||
height="49.563999"
|
||||
viewBox="0 0 50.141197 49.563999"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-16.504133,-3.6960013)">
|
||||
<path
|
||||
id="path1"
|
||||
d="m 311.801,134.82 c 43.527,0 78.808,35.301 78.808,78.809 0,43.512 -35.281,78.781 -78.808,78.781 -43.492,0 -78.789,-35.269 -78.789,-78.781 0,-43.508 35.297,-78.809 78.789,-78.809"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 494.84,213.621 c 0,-99.91 -81.942,-180.871 -183.039,-180.871 -101.071,0 -183.02,80.961 -183.02,180.871 0,99.879 81.949,180.859 183.02,180.859 101.097,0 183.039,-80.98 183.039,-180.859 z"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
38
public/signaturen/Offener_Wasserverlauf.svg
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="77.281334"
|
||||
height="40.984192"
|
||||
viewBox="0 0 77.281334 40.984192"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-3.7134605,-8.1920346)">
|
||||
<path
|
||||
id="path1"
|
||||
d="m 607.461,126.539 c 0,0 -96.402,0 -101.492,0 -5.09,0 -33.469,8.57 -35.61,9.102 -2.14,0.539 -69.097,44.718 -70.961,45.531 -1.878,0.797 -11.519,1.328 -14.468,2.937 -2.942,1.61 -32.668,22.231 -36.68,23.571 -4.02,1.34 -21.77,0 -29.359,2.14 -7.602,2.141 -59.27,12.852 -67.84,15.532 -8.582,2.679 -44.461,23.828 -66.942,42.027 -22.5,18.211 -40.449,31.871 -42.05,32.141 -1.598,0.269 -10.18,3.48 -14.188,6.429 -4.019,2.942 -8.832,2.942 -15.801,3.481 -6.961,0.539 -15.5309,1.609 -23.8317,6.16 -8.3086,4.551 -27.0391,21.949 -38.2969,48.199"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 31.2109,309.969 c 5.6094,-5.09 14.9883,-20.629 20.6094,-34.278 5.6289,-13.66 14.1914,-21.152 21.961,-21.421 7.7578,-0.27 20.8789,1.07 25.1679,-4.02 4.2808,-5.09 9.3708,-4.551 15.8008,-5.09 6.43,-0.539 9.371,2.149 15.789,-6.961 6.43,-9.097 28.133,-23.027 45.531,-38.289 17.399,-15.269 53.821,-38.031 59.45,-39.898 5.621,-1.871 40.429,-6.422 52.21,-5.621 11.782,0.8 17.95,-0.539 22.5,-4.289 4.551,-3.75 18.469,-5.622 22.75,-8.301 4.29,-2.68 6.7,-5.36 13.129,-6.422 6.43,-1.07 9.629,-3.219 11.782,-6.16 2.14,-2.938 12.859,-2.68 17.14,-2.68 4.278,0 7.219,-2.141 15.797,-9.109 8.57,-6.961 49,-38.2894 55.434,-42.0394 6.429,-3.7422 22.218,-7.2304 30.527,-9.9023 8.289,-2.6797 21.152,-2.1367 32.133,-1.6172 10.969,0.5391 70.148,6.6992 78.976,8.3086"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 313.441,181.172 241.41,208.211"
|
||||
style="fill:none;stroke:#231f20;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="M 337.691,207.988 379,157.328 314.48,146.879 337.691,207.988"
|
||||
style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
33
public/signaturen/Offizier.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="30.586933"
|
||||
height="46.779678"
|
||||
viewBox="0 0 30.586933 46.779678"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-26.110399,-5.0881346)">
|
||||
<path
|
||||
id="path1"
|
||||
d="m 368.07,126.809 c 0,-46.1996 -37.441,-83.6176 -83.621,-83.6176 -46.179,0 -83.621,37.418 -83.621,83.6176 0,46.16 37.442,83.613 83.621,83.613 46.18,0 83.621,-37.453 83.621,-83.613 z"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 284.75,210.23 V 384.039 H 425.23"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 425.23,311.699 H 284.75"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
33
public/signaturen/Patientensammelstelle.svg
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="32.627068"
|
||||
height="50.509357"
|
||||
viewBox="0 0 32.627068 50.509357"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-25.277066,-3.1105347)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 429.281,30.0508 H 194.578 V 398.871 h 234.703 z"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 309.871,30.0508 V 398.871"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="M 429.281,215.109 H 194.578"
|
||||
style="fill:none;stroke:#00adef;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
28
public/signaturen/Polizei-de.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="50.141064"
|
||||
height="49.56348"
|
||||
viewBox="0 0 50.141064 49.56348"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-16.534933,-3.6069347)">
|
||||
<path
|
||||
id="path1"
|
||||
d="m 495.07,214.289 c 0,-99.91 -81.949,-180.8671 -183.039,-180.8671 -101.082,0 -183.019,80.9571 -183.019,180.8671 0,99.883 81.937,180.859 183.019,180.859 101.09,0 183.039,-80.976 183.039,-180.859 z"
|
||||
style="fill:none;stroke:#52afe6;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 274.59,165.43 h 26.039 v 34.16 h 10.082 c 24.359,0 38.777,11.762 38.777,31.5 0,21.98 -14,32.058 -43.816,32.058 H 274.59 Z m 26.039,79.242 h 6.723 c 8.957,0 16.097,-3.223 16.097,-13.16 0,-10.223 -7.14,-13.442 -16.097,-13.442 h -6.723 v 26.602"
|
||||
style="fill:#00adef;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
43
public/signaturen/Radioaktive_Stoffe.svg
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="60.767757"
|
||||
height="47.311127"
|
||||
viewBox="0 0 60.767758 47.311127"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-11.354846,-4.4957526)">
|
||||
<path
|
||||
id="path1"
|
||||
d="m 269.281,237.051 c 12.84,7.597 27.809,11.937 43.789,11.937 15.981,0 30.961,-4.359 43.789,-11.937 l -46.05,-69.449 -41.528,69.449"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="m 272.609,86.6914 c -27.218,14.5076 -45.718,43.1366 -45.718,76.1096 0,3.34 0.187,6.64 0.55,9.871 l 83.368,-5.07 -38.2,-80.9106"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 398.699,172.672 c 0.36,-3.231 0.551,-6.531 0.551,-9.871 0,-31.602 -17.02,-59.242 -42.379,-74.2307 l -46.062,79.0317 87.89,5.07"
|
||||
style="fill:#f47216;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="m 399.25,162.801 c 0,-47.582 -38.59,-86.1799 -86.18,-86.1799 -47.601,0 -86.179,38.5979 -86.179,86.1799 0,47.597 38.578,86.187 86.179,86.187 47.59,0 86.18,-38.59 86.18,-86.187 z"
|
||||
style="fill:none;stroke:#f47216;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path5"
|
||||
d="M 536.77,43.6484 H 89.3711 L 307.719,384.371 Z"
|
||||
style="fill:none;stroke:#f47216;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
38
public/signaturen/Rauch-Entwicklungsgrenze.svg
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="74.721413"
|
||||
height="34.585373"
|
||||
viewBox="0 0 74.721413 34.585373"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g1"
|
||||
transform="translate(-4.5145866,-11.317334)">
|
||||
<path
|
||||
id="path1"
|
||||
d="M 38.8594,180.621 H 389.328 v -34.34 l 114.524,66.36 -114.524,66.339 V 244.629 H 38.8594 v -64.008"
|
||||
style="fill:#d3d2d2;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 38.8594,180.621 H 389.328 v -34.34 l 114.524,66.36 -114.524,66.339 V 244.629 H 38.8594 Z"
|
||||
style="fill:none;stroke:#1b1816;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path3"
|
||||
d="m 518.25,337.32 h 71.02 V 87.9297 H 518.25 V 337.32"
|
||||
style="fill:#d3d2d2;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
<path
|
||||
id="path4"
|
||||
d="m 518.25,337.32 h 71.02 V 87.9297 h -71.02 z"
|
||||
style="fill:none;stroke:#1b1816;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="matrix(0.13333333,0,0,-0.13333333,0,56.96)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |