Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a0be322d2 | ||
|
|
3116696a79 | ||
|
|
f01587a4f7 | ||
|
|
56064d672f | ||
|
|
77ed6e0869 | ||
|
|
2c22601cd6 | ||
|
|
1a06080a82 | ||
|
|
a631b31341 | ||
|
|
c533d8a39e |
@@ -49,3 +49,80 @@ Als Quelltext-Editor / IDE kommt VSCode zum Einsatz.
|
||||
|
||||
### DBeaver
|
||||
Ist der Datenbank-Editor
|
||||
|
||||
## Technische Dokumentation
|
||||
|
||||
### 20.09.2026 Grundsätzliche technische Entscheidungen
|
||||
#### Systeme:
|
||||
- Programmiersprache : - GO
|
||||
- Javascript
|
||||
- SQL
|
||||
- Datenbank: Postgresql
|
||||
- Webtechnologie: HTMX
|
||||
|
||||
#### Grundlegende technische Entscheidungen
|
||||
- Jedes relevante Objekt (z.B. Produkte) hat eine Darstellung als:
|
||||
- Node (Raumdarstellung)
|
||||
- Form (Darstellung des Objektes und Editiermöglichkeit) - List (Listen /Tabellensicht
|
||||
- Alle Objekte werden in der API über ihre eindeutige ID angesprochen. Über die ID kann ich den Typ des Objektes herausfinden
|
||||
- Objekte werden nur bei Bedarf aus der Datenbank geladen.
|
||||
- Objekte werden nach dem Laden oder Anlegen gechached!
|
||||
- Weboberflächen zur Pflege der Daten aber auch die Seiten zur Nutzung des CPQ müssen responsive sein!
|
||||
- Nutzung des 12- Spalten loyouts!
|
||||
- Alle Images haben einen Alternativen Text
|
||||
- Struktur der Oberfläche und die Darstellung werden strikt getrennt (HTML + CSS)
|
||||
- Die Entwicklung erfolgt über die Definition von Tickets
|
||||
- Jedes Ticket verursacht ein Brauch und einen Merge!
|
||||
|
||||
### Open Source - Pakete
|
||||
|
||||
#### Go:
|
||||
|
||||
##### Viper
|
||||
|
||||
Viper dient zum Laden uns Auswerten von Config-Dateien. In diesem Case werden die HTTP-Servereinstellungen und die Datenbankverbindung ausgewertet.
|
||||
|
||||
````
|
||||
go get github.com/spf13/viper
|
||||
````
|
||||
|
||||
##### PostgreSQL
|
||||
|
||||
Die Datenbank des Systems ist in dem Datenbankmanagementsystem PostgreSQL abgelegt. Zum einen braucht es eine Installation des Systems, auf dem die Software Zugriff hat und zum anderen benötigt das System die entsprechenden PostgreSQL Treiber für Go.
|
||||
|
||||
````
|
||||
go get github.com/lib/pq
|
||||
````
|
||||
|
||||
##### Gin Gonic
|
||||
|
||||
Webserver Library zum Routing der API.
|
||||
|
||||
````
|
||||
go get -u github.com/gin-gonic/gin
|
||||
go get github.com/gin-contrib/cors
|
||||
go get github.com/gin-contrib/sessions
|
||||
````
|
||||
|
||||
##### Go Air
|
||||
|
||||
Go Air ist ein Live-Reload-Tool für Go-Anwendungen, das die Entwicklungsproduktivität erhöht.
|
||||
|
||||
````
|
||||
go install github.com/air-verse/air@latest
|
||||
export PATH="$PATH:$(go env GOPATH)/bin"
|
||||
````
|
||||
|
||||
Den Export ggf. in der .bashrc oder .zshrc hinzufügen.
|
||||
|
||||
#### HTML Erweiterungen
|
||||
|
||||
ggf. später lokal runter laden ...
|
||||
|
||||
##### HTMX
|
||||
|
||||
HTMX ist eine JavaScript-Bibliothek, die es ermöglicht, HTML direkt über AJAX-Anfragen zu aktualisieren.
|
||||
|
||||
````
|
||||
<script src="https://unpkg.com/htmx.org@1.9.2"></script>
|
||||
````
|
||||
|
||||
@@ -49,7 +49,7 @@ func InitHttpServer(config *viper.Viper, dbHandler *sql.DB) HttpServer {
|
||||
router := gin.Default()
|
||||
|
||||
// initialize templates
|
||||
//router.LoadHTMLGlob("../templates/**/*.html")
|
||||
router.LoadHTMLGlob("../templates/**/*.html")
|
||||
|
||||
router.Use(cors.Default())
|
||||
|
||||
|
||||
@@ -18,4 +18,5 @@ func NewMainHandler(p *services.PropertyTypeService) *MainHandler {
|
||||
|
||||
func (h *MainHandler) Home(ctx *gin.Context) {
|
||||
// Implement the logic for the main handler's home endpoint here
|
||||
ctx.HTML(200, "index.html", nil)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
main {
|
||||
padding: var(--main-content-padding);
|
||||
margin: 16px;
|
||||
height: calc(100vh - var(--header-height) - var(--footer-height) - 4 * var(--main-content-padding) - 64px);
|
||||
height: calc(100vh - var(--header-height) - var(--footer-height) - 4 * var(--main-content-padding));
|
||||
/* 32px für die Margen */
|
||||
overflow-y: auto;
|
||||
/* Scrollbar, wenn der Inhalt zu groß ist */
|
||||
@@ -11,8 +11,49 @@ main {
|
||||
border-radius: var(--box-border-radius);
|
||||
}
|
||||
|
||||
nav {
|
||||
height: calc(100vh - var(--header-height) - var(--footer-height) - 4 * var(--main-content-padding));
|
||||
overflow-y: auto;
|
||||
/* Scrollbar, wenn der Inhalt zu groß ist */
|
||||
display: flex; /* Macht die Liste horizontal */
|
||||
justify-content: flex-start; /* Elemente am Anfang ausrichten */
|
||||
flex-direction: column; /* Elemente vertikal anordnen */
|
||||
border: 1px solid var(--secondary-color);
|
||||
border-radius: var(--box-border-radius);
|
||||
margin-left: 16px;
|
||||
@media (max-width: 768px) {
|
||||
height: 100%;
|
||||
}
|
||||
padding: 5px;
|
||||
background-color: var(--primary-color);
|
||||
color: var(--secondary-font-color);
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style-type: none; /* Entfernt die Standard-Aufzählungszeichen */
|
||||
|
||||
flex-wrap: wrap; /* Elemente umbrechen, wenn der Platz nicht ausreicht */
|
||||
gap: 20px; /* Abstand zwischen den Listenelementen */
|
||||
}
|
||||
|
||||
nav ul li a {
|
||||
text-decoration: none; /* Entfernt die Unterstreichung */
|
||||
color: var(--secondary-font-color); /* Setzt die Schriftfarbe */
|
||||
}
|
||||
nav ul li a:hover {
|
||||
text-decoration: underline; /* Unterstreichung beim Überfahren mit der Maus */
|
||||
font-weight: bold; /* Macht den Text fett */
|
||||
}
|
||||
|
||||
.rootNode {
|
||||
padding-top: 28px;
|
||||
/* Einrückung für die Wurzelknoten */
|
||||
color: var(--primary-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.editor-container {
|
||||
height: calc(100vh - var(--header-height) - var(--footer-height) - 4 * var(--main-content-padding) - 132px);
|
||||
height: calc(100vh - var(--header-height) - var(--footer-height) - 4 * var(--main-content-padding) - 96px);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
/* Elemente horizontal anordnen */
|
||||
@@ -48,13 +89,12 @@ main {
|
||||
}
|
||||
|
||||
.leaf {
|
||||
padding-left: 20px;
|
||||
padding-left: 28px;
|
||||
/* Einrückung für Blätter */
|
||||
color: var(--primary-color);
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
|
||||
/* form styles */
|
||||
.cform {
|
||||
display: flex;
|
||||
@@ -100,4 +140,29 @@ main {
|
||||
|
||||
.mt-16 {
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Table styles */
|
||||
table {
|
||||
margin: 16px;
|
||||
width: 80%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
table, th, td {
|
||||
border: 1px solid var(--primary-color);
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
td {
|
||||
background-color: var(--data-background-color);
|
||||
}
|
||||
|
||||
th {
|
||||
color: var(--primary-color);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@@ -7,5 +7,18 @@ footer {
|
||||
border-radius: var(--box-border-radius);
|
||||
color: var(--secondary-font-color);
|
||||
margin: 16px;
|
||||
padding: 10px;
|
||||
@media (max-width: 768px) {
|
||||
padding: 0px; /* Adjust the padding for smaller screens */
|
||||
margin: 8px; /* Adjust the margin for smaller screens */
|
||||
}
|
||||
}
|
||||
|
||||
footer a {
|
||||
text-decoration: none; /* Entfernt die Unterstreichung */
|
||||
color: var(--secondary-font-color); /* Setzt die Schriftfarbe */
|
||||
}
|
||||
footer a:hover {
|
||||
text-decoration: underline; /* Unterstreichung beim Überfahren mit der Maus */
|
||||
font-weight: bold; /* Macht den Text fett */
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
--data-background-color: #ffffff;
|
||||
|
||||
/* Dimensions */
|
||||
--header-height: 32px;
|
||||
--header-height: 64px;
|
||||
--footer-height: 32px;
|
||||
--main-content-padding: 20px;
|
||||
--box-border-radius: 10px;
|
||||
@@ -32,8 +32,60 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
// 12 Spalten Grid System
|
||||
.row::after {
|
||||
content: "";
|
||||
clear: both;
|
||||
display: table;
|
||||
}
|
||||
|
||||
[class*="col-"] {
|
||||
float: left;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
/* Responsive Anpassungen Handy */
|
||||
[class*="col-"] {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Responsive Anpassungen Tablet */
|
||||
@media screen and (min-width: 600px) {
|
||||
.col-s-1 {width: 8.33%;}
|
||||
.col-s-2 {width: 16.66%;}
|
||||
.col-s-3 {width: 25%;}
|
||||
.col-s-4 {width: 33.33%;}
|
||||
.col-s-5 {width: 41.66%;}
|
||||
.col-s-6 {width: 50%;}
|
||||
.col-s-7 {width: 58.33%;}
|
||||
.col-s-8 {width: 66.66%;}
|
||||
.col-s-9 {width: 75%;}
|
||||
.col-s-10 {width: 83.33%;}
|
||||
.col-s-11 {width: 91.66%;}
|
||||
.col-s-12 {width: 100%;}
|
||||
}
|
||||
|
||||
/* Spaltenbreiten für 12 Spalten Grid */
|
||||
@media screen and (min-width: 768px) {
|
||||
.col-1 {width: 8.33%;}
|
||||
.col-2 {width: 16.66%;}
|
||||
.col-3 {width: 25%;}
|
||||
.col-4 {width: 33.33%;}
|
||||
.col-5 {width: 41.66%;}
|
||||
.col-6 {width: 50%;}
|
||||
.col-7 {width: 58.33%;}
|
||||
.col-8 {width: 66.66%;}
|
||||
.col-9 {width: 75%;}
|
||||
.col-10 {width: 83.33%;}
|
||||
.col-11 {width: 91.66%;}
|
||||
.col-12 {width: 100%;}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 2. Schriftart anwenden und Ränder entfernen*/
|
||||
body {
|
||||
font-family: 'Inter', Arial, sans-serif;
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
header {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
flex-direction: row;
|
||||
@media (max-width: 768px) {
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
align-items: center;
|
||||
|
||||
height: var(--header-height);
|
||||
@@ -21,28 +27,22 @@ header img {
|
||||
padding-right: 16px; /* Space between the image and the header text */
|
||||
}
|
||||
|
||||
header h1 {
|
||||
font-weight: 600;
|
||||
font-size: 2em; /* Adjust the font size as needed */
|
||||
margin-left: 5px;
|
||||
padding: 16px;
|
||||
@media (max-width: 768px) {
|
||||
font-size: 1em; /* Adjust the font size for smaller screens */
|
||||
padding: 0px; /* Adjust the padding for smaller screens */
|
||||
}
|
||||
}
|
||||
|
||||
header p {
|
||||
font-weight: 100;
|
||||
margin-left: 16px;
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
nav {
|
||||
margin: 16px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style-type: none; /* Entfernt die Standard-Aufzählungszeichen */
|
||||
display: flex; /* Macht die Liste horizontal */
|
||||
gap: 20px; /* Abstand zwischen den Listenelementen */
|
||||
}
|
||||
|
||||
nav ul li a {
|
||||
text-decoration: none; /* Entfernt die Unterstreichung */
|
||||
color: var(--secondary-font-color); /* Setzt die Schriftfarbe */
|
||||
}
|
||||
nav ul li a:hover {
|
||||
text-decoration: underline; /* Unterstreichung beim Überfahren mit der Maus */
|
||||
font-weight: bold; /* Macht den Text fett */
|
||||
}
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="/static/css/scpq_global.css">
|
||||
<link rel="stylesheet" href="/static/css/scpq_header.css">
|
||||
<link rel="stylesheet" href="/static/css/scpq_footer.css">
|
||||
<link rel="stylesheet" href="/static/css/scpq_content.css">
|
||||
<title>Simply CPQ Material Editor V2</title>
|
||||
</head>
|
||||
<body>
|
||||
<header class="row">
|
||||
<div class="col-8 col-s-12">
|
||||
<h1>Simply CPQ Material Editor V2</h1>
|
||||
</div>
|
||||
</header>
|
||||
<div class="row">
|
||||
<nav class="col-2 col-s-12">
|
||||
<ul>
|
||||
<li>
|
||||
<ul>
|
||||
<details closed>
|
||||
<summary>
|
||||
Eigenschaften
|
||||
</summary>
|
||||
<ul class="node">
|
||||
<li class="leaf"><a href="#">Unterpunkt 1</a></li>
|
||||
<li class="leaf"><a href="#">Unterpunkt 2</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<ul>
|
||||
<details closed>
|
||||
<summary>
|
||||
Produkte
|
||||
</summary>
|
||||
<ul class="node">
|
||||
<li class="leaf"><a href="#">Unterpunkt 1</a></li>
|
||||
<li class="leaf"><a href="#">Unterpunkt 2</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<ul>
|
||||
<details closed>
|
||||
<summary>
|
||||
Regeln
|
||||
</summary>
|
||||
<ul class="node">
|
||||
<li class="leaf"><a href="#">Unterpunkt 1</a></li>
|
||||
<li class="leaf"><a href="#">Unterpunkt 2</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<ul>
|
||||
<details closed>
|
||||
<summary>
|
||||
Preiskalkulation
|
||||
</summary>
|
||||
<ul class="node">
|
||||
<li class="leaf"><a href="#">Unterpunkt 1</a></li>
|
||||
<li class="leaf"><a href="#">Unterpunkt 2</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<ul>
|
||||
<details closed>
|
||||
<summary>
|
||||
Übersetzungen
|
||||
</summary>
|
||||
<ul class="node">
|
||||
<li class="leaf"><a href="#">Unterpunkt 1</a></li>
|
||||
<li class="leaf"><a href="#">Unterpunkt 2</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<main>
|
||||
<div class="col-6 col-s-6">
|
||||
<h3>Property-Type Group </h3>
|
||||
<section class="editor-view">
|
||||
<section id="PropertyTypeGroupData">
|
||||
<form class="cform" method="post" action="/updatePropertyTypeGroup">
|
||||
<label for="propertyTypeGroupID">ID:</label>
|
||||
<input type="text" id="propertyTypeGroupID" name="propertyTypeGroupID" value="{PropertyTypeGroupID}" disabled>
|
||||
<label for="propertyTypeGroupName">Name:</label>
|
||||
<input type="text" id="propertyTypeGroupName" name="propertyTypeGroupName" value="{PropertyTypeGroupName}">
|
||||
<label for="propertyTypeGroupDescription">Beschreibung:</label>
|
||||
<textarea id="propertyTypeGroupDescription" name="propertyTypeGroupDescription">{PropertyTypeGroupDescription}</textarea>
|
||||
<div class="button_row">
|
||||
<button type="submit">Speichern</button>
|
||||
<button type="submit">Neu</button>
|
||||
<button type="submit">Löschen</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-6 col-s-12">
|
||||
<div class="aside">
|
||||
<h3>Values für {PropertyTypeName}</h3>
|
||||
<section class="editor-view">
|
||||
<section id="ValueData">
|
||||
<table>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>Value 1</td>
|
||||
<td>Description 1</td>
|
||||
<td>
|
||||
<div class="button_row">
|
||||
<button type="button">Edit</button>
|
||||
<button type="button">Delete</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>Value 2</td>
|
||||
<td>Description 2</td>
|
||||
<td>
|
||||
<div class="button_row">
|
||||
<button type="button">Edit</button>
|
||||
<button type="button">Delete</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</section>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div> <!-- Closing the initial row div -->
|
||||
<footer class="row">
|
||||
<div class="col-12 col-s-12">
|
||||
<h6>© 2026 Simply CPQ - All rights reserved - contact: <a href="mailto:Thomas.Sindt@gmx.de">Thomas.Sindt@gmx.de</a></h6>
|
||||
</div>
|
||||
</footer> <!-- Closing the footer row div -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user