Add Image API

This commit is contained in:
Moritz Utcke
2023-07-10 19:34:39 +05:00
parent 82db459b4e
commit de47be96d6
14 changed files with 251 additions and 75 deletions

113
README.md
View File

@@ -1,2 +1,113 @@
# IBCornelsen Online Energieausweis [![Contributors][contributors-shield]][contributors-url]
[![Forks][forks-shield]][forks-url]
[![Stargazers][stars-shield]][stars-url]
[![Issues][issues-shield]][issues-url]
[![MIT License][license-shield]][license-url]
<!-- PROJECT LOGO -->
<br />
<div align="center">
<a href="https://github.com/IBCornelsen/database">
<img src="images/logo.png" alt="Logo" width="80" height="80">
</a>
<h3 align="center">IBC Online Energieausweis</h3>
<p align="center">
Online Energieausweis erstellen - IBCornelsen
<br />
<a href="https://docs.ibcornelsen.de/storage/"><strong>Dokumentation »</strong></a>
<br />
<br />
<a href="https://github.com/IBCornelsen/database">Demo</a>
·
<a href="https://github.com/IBCornelsen/database/issues">Bug gefunden?</a>
·
<a href="https://github.com/IBCornelsen/database/issues">Feature Anfordern</a>
</p>
</div>
- [Beschreibung](#beschreibung)
- [Anforderungen](#anforderungen)
- [Installation](#installation)
- [Nächste Schritte](#nächste-schritte)
- [Beiträge zu unserer Arbeit](#beiträge-zu-unserer-arbeit)
- [License](#license)
- [Kontakt](#kontakt)
## Beschreibung
Dies ist das Repository für die Datenbank des IBCornelsen. Eine Demo kann direkt über GitHub heruntergeladen und mit **Docker** gestartet werden.
Momentan arbeiten wir an der Umsetzung einer neuen, verbesserten Datenbankstruktur die aktuelle Probleme mit Hinsicht auf die Skalierung unserer Architektur lösen wird.
Hier eine Veranschaulichung:
![Datenbankstruktur](images/struktur.png)
### Anforderungen
Die meisten unserer Systeme sind für Ubuntu gedacht und darauf getestet worden. Viele Funktionen werden ebenfalls auf Windows verfügbar sein, allerdings können unerwartetes Verhalten und Fehler nicht ausgeschlossen werden.
Für dieses Projekt benötigst du:
* docker
* Installationsanleitungen für **docker** kannst du [hier](https://docs.docker.com/engine/install/) finden.
* NodeJS
* Downloads für Node stehen [hier](https://nodejs.org/en) zur Verfügung.
* Einen Package Manger deiner Wahl, du kannst **NPM**, **pNPM** oder auch **Yarn** verwenden. Wir empfehlen **pNPM** da er in den meisten Situationen schneller ist und dabei das gleiche Feature Set wie **NPM** bietet.
### Installation
1. Klone das Repository
```sh
git clone https://github.com/IBCornelsen/database.git
```
2. Führe `docker-compose` aus.
```bash
docker-compose up --build
```
## Nächste Schritte
* [ ] Verteilte Datenbankstruktur
* [ ] Performance Optimierungen
* [ ] Umstieg auf PostgreSQL
* [ ] Umzug der alten Daten
See the [open issues](https://github.com/IBCornelsen/database/issues) for a full list of proposed features (and known issues).
## Beiträge zu unserer Arbeit
Wenn du Ideen, Vorschläge oder sonstige Anmerkungen haben solltest, schreck' nicht davor zurück dein Feature zu implementieren und eine Pull Request zu erstellen, wir sind **immer** offen für neues!
1. Erstelle einen **Fork** des Repos
2. Erstelle einen neuen Feature Branch (`git checkout -b feature/AmazingFeature`)
3. Committe deine Änderungen (`git commit -m 'Add some AmazingFeature'`)
4. Pushe deine Änderungen auf den neuen Branch (`git push origin feature/AmazingFeature`)
5. Öffne eine Pull Request
## License
Veröffentlicht unter der GPL-3.0 Lizenz. Siehe `LICENSE` für mehr Information.
## Kontakt
IBCornelsen - [info@ibcornelsen.de](mailto://info@ibcornelsen.de)
Organisation: [https://github.com/IBCornelsen/database](https://github.com/IBCornelsen/database)
[contributors-shield]: https://img.shields.io/github/contributors/IBCornelsen/database.svg?style=for-the-badge
[contributors-url]: https://github.com/IBCornelsen/database/graphs/contributors
[forks-shield]: https://img.shields.io/github/forks/IBCornelsen/database.svg?style=for-the-badge
[forks-url]: https://github.com/IBCornelsen/database/network/members
[stars-shield]: https://img.shields.io/github/stars/IBCornelsen/database.svg?style=for-the-badge
[stars-url]: https://github.com/IBCornelsen/database/stargazers
[issues-shield]: https://img.shields.io/github/issues/IBCornelsen/database.svg?style=for-the-badge
[issues-url]: https://github.com/IBCornelsen/database/issues
[license-shield]: https://img.shields.io/github/license/IBCornelsen/database.svg?style=for-the-badge
[license-url]: https://github.com/IBCornelsen/database/blob/master/LICENSE

View File

@@ -47,8 +47,8 @@ echo "CERTIFICATE=$(cat /etc/letsencrypt/live/ibcornelsen.de/fullchain.pem | bas
# Und starten unsere App wieder. # Und starten unsere App wieder.
docker run -d --name $APP_NAME --link $DB_CONTAINER_NAME \ docker run -d --name $APP_NAME --link $DB_CONTAINER_NAME \
-v "${PERSISTENT_DIR}:/persistent" \ -v "${PERSISTENT_DIR}:/persistent" \
-p "$APP_PORT:80" \ -p "${APP_PORT}:80" \
-e DB_CONNECTION=postgresql://$DB_USER:$DB_PASSWORD@${DB_CONTAINER_NAME}:$DB_PORT/$DB_NAME \ -e DB_CONNECTION=postgresql://${DB_USER}:${DB_PASSWORD}@${DB_CONTAINER_NAME}:${DB_PORT}/${DB_NAME} \
-e DB_PORT=$DB_PORT \ -e DB_PORT=${DB_PORT} \
--env-file ~/apps/$APP_NAME/.env \ --env-file ~/apps/${APP_NAME}/.env
$APP_NAME; $APP_NAME;

View File

@@ -5,7 +5,7 @@ services:
container_name: online-energieausweis container_name: online-energieausweis
command: pnpm run dev --host command: pnpm run dev --host
links: links:
- db - database
environment: environment:
PORT: 3000 PORT: 3000
DB_CONNECTION: "postgresql://main:hHMP8cd^N3SnzGRR@database:5432/main" DB_CONNECTION: "postgresql://main:hHMP8cd^N3SnzGRR@database:5432/main"
@@ -18,7 +18,7 @@ services:
- ./persistent:/persistent - ./persistent:/persistent
networks: networks:
- postgres - postgres
db: database:
build: ../database build: ../database
ports: ports:
- "5436:5432" - "5436:5432"

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

@@ -0,0 +1,26 @@
<script lang="ts">
export let heading: string;
export let price: number;
export let href: string;
</script>
<div class="rpt_plan">
<div class="rpt_title">
<img
src="/images/icon_wohnhaus_plan_01.png"
class="rpt_icon rpt_icon_0"
alt="Energieausweis erstellen"
/>
{heading}
</div>
<div class="rpt_head">
<div class="rpt_recurrence">inkl. 19% MwSt</div>
<div class="rpt_price">
<span class="rpt_currency"></span>{price}
</div>
</div>
<slot></slot>
<a target="_self" {href} class="rpt_foot"
>jetzt sofort Energieausweis online erstellen</a
>
</div>

View File

@@ -60,7 +60,7 @@
const dataURL = canvas.toDataURL("image/jpeg", 0.8); const dataURL = canvas.toDataURL("image/jpeg", 0.8);
fetch("/api/image", { fetch("/api/image.json", {
method: "PUT", method: "PUT",
body: JSON.stringify({ body: JSON.stringify({
data: dataURL.split(';base64,')[1], data: dataURL.split(';base64,')[1],

View File

@@ -0,0 +1,25 @@
import type { APIRoute } from "astro";
import {
MissingEntityError,
error,
success,
} from "src/lib/APIResponse";
import { db } from "src/lib/shared";
export const get: APIRoute = async ({ request }) => {
const body = Object.fromEntries(new URLSearchParams(request.url.split("?")[1]))
if (!body.uid) {
return error(["Missing 'uid' in request body."])
}
const gebaeude = await db("gebaeude").where({ uid: body.uid }).first();
if (!gebaeude) {
return MissingEntityError("gebaeude")
}
const images = await db("gebaeude_bilder").where({ gebaeude_id: gebaeude.id }).select("uid", "kategorie");
return success(images);
};

View File

@@ -0,0 +1,45 @@
import type { APIRoute } from "astro";
import {
MissingEntityError,
error,
} from "src/lib/APIResponse";
import { z } from "zod";
import * as path from "path";
import * as fs from "fs";
import { db } from "src/lib/shared";
const ImageUploadChecker = z.object({
data: z.string(),
name: z.string(),
gebaeude_uid: z.string().optional(),
kategorie: z.string(),
});
export const get: APIRoute = async ({ request }) => {
const body = Object.fromEntries(new URLSearchParams(request.url.split("?")[1]))
if (!body.uid) {
return error(["Missing 'uid' in request body."])
}
const image = await db("gebaeude_bilder").where({ uid: body.uid }).select("uid", "kategorie").first();
if (!image) {
return MissingEntityError("image")
}
// Check if the image exists on disk
const location = path.join("/persistent/uploads/images", `${image.uid}.jpg`);
if (!fs.existsSync(location)) {
return MissingEntityError("image")
}
const data = fs.readFileSync(location);
return new Response(data, {
headers: {
"Content-Type": "image/jpeg"
}
});
};

View File

@@ -8,6 +8,7 @@ import {
import * as jimp from "jimp"; import * as jimp from "jimp";
import { z } from "zod"; import { z } from "zod";
import * as path from "path"; import * as path from "path";
import * as fs from "fs";
import { db } from "src/lib/shared"; import { db } from "src/lib/shared";
const ImageUploadChecker = z.object({ const ImageUploadChecker = z.object({
@@ -17,6 +18,31 @@ const ImageUploadChecker = z.object({
kategorie: z.string(), kategorie: z.string(),
}); });
export const get: APIRoute = async ({ request }) => {
const body = Object.fromEntries(new URLSearchParams(request.url.split("?")[1]))
if (!body.uid) {
return error(["Missing 'uid' in request body."])
}
const image = await db("gebaeude_bilder").where({ uid: body.uid }).select("uid", "kategorie").first();
if (!image) {
return MissingEntityError("image")
}
// Check if the image exists on disk
const location = path.join("/persistent/uploads/images", `${image.uid}.jpg`);
if (!fs.existsSync(location)) {
return MissingEntityError("image")
}
const data = fs.readFileSync(location, { encoding: "base64" });
return success(data);
};
/** /**
* Speichert ein Bild auf unserem Server ab und gibt die UID des Bildes zurück * Speichert ein Bild auf unserem Server ab und gibt die UID des Bildes zurück
* @param param0 * @param param0

View File

@@ -2,6 +2,7 @@
import { BoxWithHeading } from "@ibcornelsen/ui"; import { BoxWithHeading } from "@ibcornelsen/ui";
import Widget from "../components/Widget.svelte"; import Widget from "../components/Widget.svelte";
import Layout from "../layouts/Layout.astro"; import Layout from "../layouts/Layout.astro";
import FeatureCard from "~/components/FeatureCard.svelte";
--- ---
<Layout title="Energieausweis online erstellen - Online Energieausweis"> <Layout title="Energieausweis online erstellen - Online Energieausweis">
@@ -105,21 +106,7 @@ import Layout from "../layouts/Layout.astro";
</div> </div>
<hr /> <hr />
<div class="grid grid-cols-3 gap-4"> <div class="grid grid-cols-3 gap-4">
<div class="rpt_plan"> <FeatureCard heading="Verbrauchsausweis Wohngebäude" price={45} href="/verbrauchsausweis">
<div class="rpt_title">
<img
src="/images/icon_wohnhaus_plan_01.png"
class="rpt_icon rpt_icon_0"
alt="Energieausweis erstellen"
/>
Verbrauchsausweis<br />Wohngebäude
</div>
<div class="rpt_head">
<div class="rpt_recurrence">inkl. 19% MwSt</div>
<div class="rpt_price">
<span class="rpt_currency">€</span>45
</div>
</div>
<div class="rpt_feature">Unsere Leistungen:</div> <div class="rpt_feature">Unsere Leistungen:</div>
<div class="rpt_feature">Prüfung durch Diplom Ingenieur</div> <div class="rpt_feature">Prüfung durch Diplom Ingenieur</div>
<div class="rpt_feature">Energieausweis Vorschau als PDF</div> <div class="rpt_feature">Energieausweis Vorschau als PDF</div>
@@ -127,29 +114,9 @@ import Layout from "../layouts/Layout.astro";
<div class="rpt_feature">Registrierung beim DiBt</div> <div class="rpt_feature">Registrierung beim DiBt</div>
<div class="rpt_feature">Bearbeitung innhalb 24h</div> <div class="rpt_feature">Bearbeitung innhalb 24h</div>
<div class="rpt_feature">rechtssicher nach aktueller EnEV</div> <div class="rpt_feature">rechtssicher nach aktueller EnEV</div>
<div class="rpt_feature">telefonische Beratung</div><a <div class="rpt_feature">telefonische Beratung</div>
target="_self" </FeatureCard>
href="/energieausweis-erstellen/verbrauchsausweis-erstellen.php" <FeatureCard heading="Bedarfsausweis Wohngebäude" price={75} href="/bedarfsausweis">
class="rpt_foot">jetzt sofort Energieausweis online erstellen</a
>
</div>
<div class="rpt_plan">
<div class="rpt_title rpt_title_1">
<img
src="/images/icon_wohnhaus_plan_01.png"
class="rpt_icon rpt_icon_1"
alt="Energieausweis erstellen"
/>
Bedarfsausweis<br />Wohngebäude
</div>
<div class="rpt_head rpt_head_1">
<div class="rpt_recurrence rpt_recurrence_1">
inkl. 19% MwSt
</div>
<div class="rpt_price rpt_price_1">
<span class="rpt_currency">€</span>75
</div>
</div>
<div class="rpt_feature">Unsere Leistungen:</div> <div class="rpt_feature">Unsere Leistungen:</div>
<div class="rpt_feature">Prüfung durch Diplom Ingenieur</div> <div class="rpt_feature">Prüfung durch Diplom Ingenieur</div>
<div class="rpt_feature">Energieausweis Vorschau als PDF</div> <div class="rpt_feature">Energieausweis Vorschau als PDF</div>
@@ -157,29 +124,9 @@ import Layout from "../layouts/Layout.astro";
<div class="rpt_feature">Registrierung beim DiBt</div> <div class="rpt_feature">Registrierung beim DiBt</div>
<div class="rpt_feature">Bearbeitung innhalb 24h</div> <div class="rpt_feature">Bearbeitung innhalb 24h</div>
<div class="rpt_feature">rechtssicher nach aktueller EnEV</div> <div class="rpt_feature">rechtssicher nach aktueller EnEV</div>
<div class="rpt_feature rpt_feature_1-7"> <div class="rpt_feature">telefonische Beratung</div>
telefonische Beratung </FeatureCard>
</div><a <FeatureCard heading="Verbrauchsausweis Gewerbe" price={65} href="/verbrauchsausweis-gewerbe">
target="_self"
href="/energieausweis-erstellen/bedarfsausweis-erstellen.php"
class="rpt_foot">jetzt sofort Energieausweis online erstellen</a
>
</div>
<div class="rpt_plan">
<div class="rpt_title rpt_title_2">
<img
src="/images/icon_gewerbe_plan_01.png"
class="rpt_icon rpt_icon_2"
alt="Energieausweis erstellen"
/>
Verbrauchsausweis<br />Gewerbe
</div>
<div class="rpt_head rpt_head_2">
<div class="rpt_recurrence">inkl. 19% MwSt</div>
<div class="rpt_price">
<span class="rpt_currency">€</span>65
</div>
</div>
<div class="rpt_feature">Unsere Leistungen:</div> <div class="rpt_feature">Unsere Leistungen:</div>
<div class="rpt_feature">Prüfung durch Diplom Ingenieur</div> <div class="rpt_feature">Prüfung durch Diplom Ingenieur</div>
<div class="rpt_feature">Energieausweis Vorschau als PDF</div> <div class="rpt_feature">Energieausweis Vorschau als PDF</div>
@@ -187,12 +134,8 @@ import Layout from "../layouts/Layout.astro";
<div class="rpt_feature">Registrierung beim DiBt</div> <div class="rpt_feature">Registrierung beim DiBt</div>
<div class="rpt_feature">Bearbeitung innhalb 24h</div> <div class="rpt_feature">Bearbeitung innhalb 24h</div>
<div class="rpt_feature">rechtssicher nach aktueller EnEV</div> <div class="rpt_feature">rechtssicher nach aktueller EnEV</div>
<div class="rpt_feature">telefonische Beratung</div><a <div class="rpt_feature">telefonische Beratung</div>
target="_self" </FeatureCard>
href="/energieausweis-erstellen/verbrauchsausweis-gewerbe-erstellen.php"
class="rpt_foot">jetzt sofort Energieausweis online erstellen</a
>
</div>
</div> </div>
<hr /> <hr />