Änderungen an UI, POIs hinzugefügt, Suchlisten, Waren, Schiffsauswahl, Start-, Zielort und Zeitaufwand hinzugefügt.
All checks were successful
release-tag / release-image (push) Successful in 2m47s
All checks were successful
release-tag / release-image (push) Successful in 2m47s
This commit is contained in:
13
Dockerfile
13
Dockerfile
@@ -14,18 +14,23 @@ FROM alpine:3.20
|
|||||||
# HTTPS-Callouts in Alpine brauchen ca-certificates
|
# HTTPS-Callouts in Alpine brauchen ca-certificates
|
||||||
RUN apk add --no-cache ca-certificates
|
RUN apk add --no-cache ca-certificates
|
||||||
RUN mkdir /data
|
RUN mkdir /data
|
||||||
|
RUN mkdir /dynamicsrc
|
||||||
RUN mkdir /tempsrc
|
RUN mkdir /tempsrc
|
||||||
COPY --from=builder /bin/sctradingtool /bin/sctradingtool
|
COPY --from=builder /bin/sctradingtool /bin/sctradingtool
|
||||||
COPY ./static /data/static
|
COPY ./static /data/static
|
||||||
COPY ./static /tempsrc/static
|
COPY ./static /tempsrc/static
|
||||||
|
COPY ./dynamicsrc /dynamicsrc
|
||||||
|
|
||||||
# Default listens on :8080 – siehe main.go
|
# Default listens on :8080 – siehe main.go
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
|
|
||||||
# Environment defaults; können per compose überschrieben werden
|
# Environment defaults; können per compose überschrieben werden
|
||||||
ENV REDIS_ADDR=redis:6379 \
|
ENV KT_USERNAME=admin \
|
||||||
BLOCKLIST_MODE=slave \
|
KT_PASSWORD=admin \
|
||||||
HASH_NAME=bl:manual \
|
KT_MEMBER=guest \
|
||||||
MASTER_URL=https://flod-proxy.send.nrw
|
KT_HASIMPRESSUM=true \
|
||||||
|
KT_IMPRESSUM=https://www.google.de \
|
||||||
|
KT_PRODUCTIVE=true
|
||||||
|
|
||||||
|
|
||||||
ENTRYPOINT ["/bin/sctradingtool"]
|
ENTRYPOINT ["/bin/sctradingtool"]
|
1
dynamicsrc/pois.json
Normal file
1
dynamicsrc/pois.json
Normal file
File diff suppressed because one or more lines are too long
298
main.go
298
main.go
@@ -2,6 +2,8 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"log"
|
"log"
|
||||||
"math"
|
"math"
|
||||||
@@ -15,6 +17,9 @@ import (
|
|||||||
_ "modernc.org/sqlite" // statt github.com/mattn/go-sqlite3
|
_ "modernc.org/sqlite" // statt github.com/mattn/go-sqlite3
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/* Quellen */
|
||||||
|
/* https://starmap.space/api/v3/oc/index.php */
|
||||||
|
|
||||||
func GetENV(k, d string) string {
|
func GetENV(k, d string) string {
|
||||||
if v := os.Getenv(k); v != "" {
|
if v := os.Getenv(k); v != "" {
|
||||||
return v
|
return v
|
||||||
@@ -37,8 +42,74 @@ var (
|
|||||||
productive = Enabled("KT_PRODUCTIVE", false)
|
productive = Enabled("KT_PRODUCTIVE", false)
|
||||||
hasimpressum = Enabled("KT_HASIMPRESSUM", false)
|
hasimpressum = Enabled("KT_HASIMPRESSUM", false)
|
||||||
impressum = GetENV("KT_IMPRESSUM", "")
|
impressum = GetENV("KT_IMPRESSUM", "")
|
||||||
|
orte = []string{}
|
||||||
|
schiffe = []string{
|
||||||
|
"100i", "125a", "135c", "Arrow", "Aurora CL", "Aurora ES", "Aurora LN", "Aurora LX", "Aurora MR",
|
||||||
|
"Avenger Stalker", "Avenger Titan", "Avenger Titan Renegade", "Avenger Warlock",
|
||||||
|
"Blade", "Buccaneer", "C1 Spirit", "C2 Hercules Starlifter", "C8 Pisces", "C8R Pisces Rescue",
|
||||||
|
"C8X Pisces Expedition", "Carrack", "Caterpillar", "Constellation Andromeda",
|
||||||
|
"Constellation Aquila", "Constellation Phoenix", "Constellation Taurus", "Corsair",
|
||||||
|
"Cutlass Black", "Cutlass Blue", "Cutlass Red", "Cutter", "Defender", "Eclipse",
|
||||||
|
"Freelancer", "Freelancer DUR", "Freelancer MAX", "Gladiator", "Gladius", "Glaive",
|
||||||
|
"Hammerhead", "Hawk", "Herald", "Hurricane", "Idris-K", "Idris-M", "Javelin",
|
||||||
|
"Khartu-Al", "Kraken", "M50", "Merchantman", "Mercury Star Runner", "Mustang Alpha",
|
||||||
|
"Mustang Beta", "Mustang Delta", "Mustang Gamma", "Mustang Omega", "Nomad",
|
||||||
|
"Orion", "P-52 Merlin", "P-72 Archimedes", "Prospector", "Prowler", "Prowler Utility", "Raft",
|
||||||
|
"Reclaimer", "Redeemer", "Reliant Kore", "Reliant Mako", "Reliant Sen", "Reliant Tana",
|
||||||
|
"Retaliator Bomber", "Sabre Peregrine", "Starfarer Gemini", "Talon", "Talon Shrike",
|
||||||
|
"Terrapin", "Vulture", "Hull-A", "Hull-C", "Zeus ES", "Zeus CL",
|
||||||
|
// …weitere Capital- und Concept-Schiffe sind ebenfalls bekannt!
|
||||||
|
}
|
||||||
|
waren = []string{"Laranite", "Titanium", "Medical Supplies", "Gold"}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type POI struct {
|
||||||
|
ItemID int `json:"item_id"`
|
||||||
|
System string `json:"System"`
|
||||||
|
Planet string `json:"Planet"`
|
||||||
|
PoiName string `json:"PoiName"`
|
||||||
|
Type string `json:"Type"`
|
||||||
|
Classification string `json:"Classification"`
|
||||||
|
Latitude float64 `json:"Latitude"`
|
||||||
|
Longitude float64 `json:"Longitude"`
|
||||||
|
Longitude360 float64 `json:"Longitude360"`
|
||||||
|
Height float64 `json:"Height"`
|
||||||
|
XCoord float64 `json:"XCoord"`
|
||||||
|
YCoord float64 `json:"YCoord"`
|
||||||
|
ZCoord float64 `json:"ZCoord"`
|
||||||
|
QTMarker int `json:"QTMarker"`
|
||||||
|
NextPOI string `json:"NextPOI"`
|
||||||
|
NextQTMarker string `json:"NextQTMarker"`
|
||||||
|
Comment string `json:"Comment"`
|
||||||
|
Submitted string `json:"Submitted"` // oder time.Time, falls du umwandelst
|
||||||
|
Introduced string `json:"Introduced"` // z. B. "Unknown"
|
||||||
|
GUID string `json:"GUID"`
|
||||||
|
POISize *string `json:"POI_Size"`
|
||||||
|
POIType *string `json:"POI_Type"`
|
||||||
|
POIEntries string `json:"POI_Entries"`
|
||||||
|
POIAccessableFoot string `json:"POI_Accessable_Foot"`
|
||||||
|
POIAccessableVehicle string `json:"POI_Accessable_Vehicle"`
|
||||||
|
POIAccessableShip string `json:"POI_Accessable_Ship"`
|
||||||
|
POIDefenses string `json:"POI_Defenses"`
|
||||||
|
POILandingPads string `json:"POI_LandingPads"`
|
||||||
|
POIVehiclePads string `json:"POI_VehiclePads"`
|
||||||
|
POITerminals string `json:"POI_Terminals"`
|
||||||
|
POIMedBay string `json:"POI_MedBay"`
|
||||||
|
POIServices string `json:"POI_Services"`
|
||||||
|
POIAtmosphere *string `json:"POI_Atmosphere"`
|
||||||
|
POINPCs string `json:"POI_NPCs"`
|
||||||
|
ZoneArmistice int `json:"Zone_Armistice"`
|
||||||
|
ZoneNoFly int `json:"Zone_NoFly"`
|
||||||
|
ZoneTrespassing int `json:"Zone_Trespassing"`
|
||||||
|
ZoneBiome string `json:"Zone_Biome"`
|
||||||
|
ZoneGravitation int `json:"Zone_Gravitation"`
|
||||||
|
ZoneTemperatureMin string `json:"Zone_Temperature_Min"`
|
||||||
|
ZoneTemperatureMax string `json:"Zone_Temperature_Max"`
|
||||||
|
Minerals *string `json:"Minerals"`
|
||||||
|
SpecialLoot string `json:"SpecialLoot"`
|
||||||
|
Missions string `json:"Missions"`
|
||||||
|
}
|
||||||
|
|
||||||
type Entry struct {
|
type Entry struct {
|
||||||
ID int
|
ID int
|
||||||
Anfangsbestand float64
|
Anfangsbestand float64
|
||||||
@@ -48,6 +119,11 @@ type Entry struct {
|
|||||||
Gesamtwert float64
|
Gesamtwert float64
|
||||||
Bezahlt bool
|
Bezahlt bool
|
||||||
CreatedAt string
|
CreatedAt string
|
||||||
|
Startort string
|
||||||
|
Zielort string
|
||||||
|
Schiff string
|
||||||
|
Ware string
|
||||||
|
Zeitaufwand float64
|
||||||
}
|
}
|
||||||
|
|
||||||
type Abteilung struct {
|
type Abteilung struct {
|
||||||
@@ -113,11 +189,37 @@ func main() {
|
|||||||
var (
|
var (
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
err error
|
err error
|
||||||
|
data []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
if productive {
|
if productive {
|
||||||
db, err = sql.Open("sqlite", "/data/data.db")
|
db, err = sql.Open("sqlite", "/data/data.db")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
data, err = os.ReadFile("/dynamicsrc/pois.json")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
db, err = sql.Open("sqlite", "./data.db")
|
db, err = sql.Open("sqlite", "./data.db")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
data, err = os.ReadFile("./dynamicsrc/pois.json")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var pois []POI
|
||||||
|
if err := json.Unmarshal(data, &pois); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, poi := range pois {
|
||||||
|
formatted := fmt.Sprintf("%s - %s - %s (%s)", poi.System, poi.Planet, poi.PoiName, poi.Type)
|
||||||
|
orte = append(orte, formatted)
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -228,8 +330,13 @@ func main() {
|
|||||||
prozent, _ := strconv.ParseFloat(r.FormValue("prozentwert"), 64)
|
prozent, _ := strconv.ParseFloat(r.FormValue("prozentwert"), 64)
|
||||||
diff := ende - anfang
|
diff := ende - anfang
|
||||||
abgabe := (diff / 100) * prozent
|
abgabe := (diff / 100) * prozent
|
||||||
|
startort := r.FormValue("startort")
|
||||||
|
zielort := r.FormValue("zielort")
|
||||||
|
schiff := r.FormValue("schiff")
|
||||||
|
ware := r.FormValue("ware")
|
||||||
|
zeitaufwand, _ := strconv.ParseFloat(r.FormValue("zeitaufwand"), 64)
|
||||||
|
|
||||||
_, err := db.Exec(`INSERT INTO eintraege (anfangsbestand, endbestand, prozentwert, abgabe, created_at) VALUES (?, ?, ?, ?, datetime('now'))`, anfang, ende, prozent, abgabe)
|
_, err := db.Exec(`INSERT INTO eintraege (anfangsbestand, endbestand, prozentwert, abgabe, created_at, startort, zielort, schiff, ware, zeitaufwand) VALUES (?, ?, ?, ?, datetime('now'), ?, ?, ?, ?, ?)`, anfang, ende, prozent, abgabe, startort, zielort, schiff, ware, zeitaufwand)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Fehler beim Einfügen", http.StatusInternalServerError)
|
http.Error(w, "Fehler beim Einfügen", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
@@ -238,7 +345,7 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rows, err := db.Query(`SELECT id, anfangsbestand, endbestand, prozentwert, abgabe, bezahlt, created_at FROM eintraege`)
|
rows, err := db.Query(`SELECT id, anfangsbestand, endbestand, prozentwert, abgabe, bezahlt, created_at, startort, zielort, schiff, ware, zeitaufwand FROM eintraege`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Fehler beim Abrufen", http.StatusInternalServerError)
|
http.Error(w, "Fehler beim Abrufen", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
@@ -252,7 +359,13 @@ func main() {
|
|||||||
var e Entry
|
var e Entry
|
||||||
var bezahlt int
|
var bezahlt int
|
||||||
var createdAt sql.NullString
|
var createdAt sql.NullString
|
||||||
err := rows.Scan(&e.ID, &e.Anfangsbestand, &e.Endbestand, &e.Prozentwert, &e.Abgabe, &bezahlt, &createdAt)
|
var startort sql.NullString
|
||||||
|
var zielort sql.NullString
|
||||||
|
var schiff sql.NullString
|
||||||
|
var ware sql.NullString
|
||||||
|
var zeitaufwand sql.NullFloat64
|
||||||
|
|
||||||
|
err := rows.Scan(&e.ID, &e.Anfangsbestand, &e.Endbestand, &e.Prozentwert, &e.Abgabe, &bezahlt, &createdAt, &startort, &zielort, &schiff, &ware, &zeitaufwand)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Fehler beim Scan:", err)
|
log.Println("Fehler beim Scan:", err)
|
||||||
continue
|
continue
|
||||||
@@ -271,6 +384,36 @@ func main() {
|
|||||||
} else {
|
} else {
|
||||||
e.CreatedAt = "unbekannt"
|
e.CreatedAt = "unbekannt"
|
||||||
}
|
}
|
||||||
|
/**/
|
||||||
|
if startort.Valid {
|
||||||
|
e.Startort = startort.String
|
||||||
|
} else {
|
||||||
|
e.Startort = "unbekannt"
|
||||||
|
}
|
||||||
|
|
||||||
|
if zielort.Valid {
|
||||||
|
e.Zielort = zielort.String
|
||||||
|
} else {
|
||||||
|
e.Zielort = "unbekannt"
|
||||||
|
}
|
||||||
|
|
||||||
|
if schiff.Valid {
|
||||||
|
e.Schiff = schiff.String
|
||||||
|
} else {
|
||||||
|
e.Schiff = "unbekannt"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ware.Valid {
|
||||||
|
e.Ware = ware.String
|
||||||
|
} else {
|
||||||
|
e.Ware = "unbekannt"
|
||||||
|
}
|
||||||
|
|
||||||
|
if zeitaufwand.Valid {
|
||||||
|
e.Zeitaufwand = zeitaufwand.Float64
|
||||||
|
} else {
|
||||||
|
e.Zeitaufwand = 0
|
||||||
|
}
|
||||||
|
|
||||||
eintraege = append(eintraege, e)
|
eintraege = append(eintraege, e)
|
||||||
|
|
||||||
@@ -341,6 +484,9 @@ func main() {
|
|||||||
Member string
|
Member string
|
||||||
HasImpressum bool
|
HasImpressum bool
|
||||||
Impressum string
|
Impressum string
|
||||||
|
Orte []string
|
||||||
|
Schiffe []string
|
||||||
|
Waren []string
|
||||||
}{
|
}{
|
||||||
Entries: eintraege,
|
Entries: eintraege,
|
||||||
Summe: summe,
|
Summe: summe,
|
||||||
@@ -351,7 +497,11 @@ func main() {
|
|||||||
Member: membername,
|
Member: membername,
|
||||||
HasImpressum: hasimpressum,
|
HasImpressum: hasimpressum,
|
||||||
Impressum: impressum,
|
Impressum: impressum,
|
||||||
|
Orte: orte,
|
||||||
|
Schiffe: schiffe,
|
||||||
|
Waren: waren,
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
log.Println("Server läuft auf http://0.0.0.0:8080")
|
log.Println("Server läuft auf http://0.0.0.0:8080")
|
||||||
@@ -366,22 +516,34 @@ func createTable(db *sql.DB) {
|
|||||||
endbestand REAL,
|
endbestand REAL,
|
||||||
prozentwert REAL,
|
prozentwert REAL,
|
||||||
abgabe REAL,
|
abgabe REAL,
|
||||||
bezahlt INTEGER DEFAULT 0
|
bezahlt INTEGER DEFAULT 0,
|
||||||
|
created_at TEXT,
|
||||||
|
startort TEXT,
|
||||||
|
zielort TEXT,
|
||||||
|
schiff TEXT,
|
||||||
|
ware TEXT,
|
||||||
|
zeitaufwand INTEGER
|
||||||
);
|
);
|
||||||
`)
|
`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Falls die Tabelle schon existiert, aber die Spalte "bezahlt" fehlt (z. B. nach Update)
|
// Ergänze ALTER TABLE nur für Migration bestehender Tabellen
|
||||||
_, err = db.Exec(`ALTER TABLE eintraege ADD COLUMN bezahlt INTEGER DEFAULT 0;`)
|
addColumn := func(column, colType string) {
|
||||||
|
_, err := db.Exec(`ALTER TABLE eintraege ADD COLUMN ` + column + ` ` + colType)
|
||||||
if err != nil && !strings.Contains(err.Error(), "duplicate column") {
|
if err != nil && !strings.Contains(err.Error(), "duplicate column") {
|
||||||
log.Fatal(err)
|
log.Fatalf("Fehler beim Hinzufügen der Spalte %s: %v", column, err)
|
||||||
}
|
}
|
||||||
_, err = db.Exec(`ALTER TABLE eintraege ADD COLUMN created_at TEXT`)
|
|
||||||
if err != nil && !strings.Contains(err.Error(), "duplicate column") {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addColumn("bezahlt", "INTEGER DEFAULT 0")
|
||||||
|
addColumn("created_at", "TEXT")
|
||||||
|
addColumn("startort", "TEXT")
|
||||||
|
addColumn("zielort", "TEXT")
|
||||||
|
addColumn("schiff", "TEXT")
|
||||||
|
addColumn("ware", "TEXT")
|
||||||
|
addColumn("zeitaufwand", "INTEGER")
|
||||||
}
|
}
|
||||||
|
|
||||||
const loginForm = `
|
const loginForm = `
|
||||||
@@ -419,6 +581,7 @@ const htmlTemplate = `
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Abgabe-Berechnung</title>
|
<title>Abgabe-Berechnung</title>
|
||||||
<link href="/static/css/bootstrap.min.css" rel="stylesheet">
|
<link href="/static/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link href="/static/css/tom-select.default.min.css" rel="stylesheet">
|
||||||
<link rel="icon" href="/static/favicon.ico" type="image/x-icon">
|
<link rel="icon" href="/static/favicon.ico" type="image/x-icon">
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-light">
|
<body class="bg-light">
|
||||||
@@ -471,6 +634,47 @@ const htmlTemplate = `
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label class="form-label">Startort</label>
|
||||||
|
<select id="startort" name="startort" class="form-select">
|
||||||
|
{{range .Orte}}
|
||||||
|
<option value="{{.}}">{{.}}</option>
|
||||||
|
{{end}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<label class="form-label">Zielort</label>
|
||||||
|
<select id="zielort" name="zielort" class="form-select">
|
||||||
|
{{range .Orte}}
|
||||||
|
<option value="{{.}}">{{.}}</option>
|
||||||
|
{{end}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<label class="form-label">Schiff</label>
|
||||||
|
<select id="schiff" name="schiff" class="form-select">
|
||||||
|
{{range .Schiffe}}
|
||||||
|
<option value="{{.}}">{{.}}</option>
|
||||||
|
{{end}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<label class="form-label">Ware</label>
|
||||||
|
<select id="ware" name="ware" class="form-select">
|
||||||
|
{{range .Waren}}
|
||||||
|
<option value="{{.}}">{{.}}</option>
|
||||||
|
{{end}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<label class="form-label">Zeitaufwand (min)</label>
|
||||||
|
<input type="number" name="zeitaufwand" class="form-control" min="1" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<button type="submit" class="btn btn-primary">Berechnen & Speichern</button>
|
<button type="submit" class="btn btn-primary">Berechnen & Speichern</button>
|
||||||
</form>
|
</form>
|
||||||
{{end}}
|
{{end}}
|
||||||
@@ -488,10 +692,10 @@ const htmlTemplate = `
|
|||||||
<th>Prozent</th>
|
<th>Prozent</th>
|
||||||
<th>UEC Abgabe</th>
|
<th>UEC Abgabe</th>
|
||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
{{if .LoggedIn}}<th>Aktion</th>{{end}}
|
{{if .LoggedIn}}<th>Aktion</th>{{else}}<th>Erweitert</th>{{end}}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody id="eintragsTabelle">
|
||||||
{{range .Entries}}
|
{{range .Entries}}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{.ID}}</td>
|
<td>{{.ID}}</td>
|
||||||
@@ -500,9 +704,7 @@ const htmlTemplate = `
|
|||||||
<td>{{formatNumber .Endbestand}}</td>
|
<td>{{formatNumber .Endbestand}}</td>
|
||||||
<td>{{formatNumber .Gesamtwert}}</td>
|
<td>{{formatNumber .Gesamtwert}}</td>
|
||||||
<td>{{formatNumber .Prozentwert}}%</td>
|
<td>{{formatNumber .Prozentwert}}%</td>
|
||||||
<td>
|
<td>{{formatNumber .Abgabe}}</td>
|
||||||
{{formatNumber .Abgabe}}
|
|
||||||
</td>
|
|
||||||
<td>
|
<td>
|
||||||
{{if .Bezahlt}}
|
{{if .Bezahlt}}
|
||||||
{{if $.LoggedIn}}
|
{{if $.LoggedIn}}
|
||||||
@@ -518,11 +720,43 @@ const htmlTemplate = `
|
|||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
</td>
|
</td>
|
||||||
{{if $.LoggedIn}}
|
|
||||||
<td>
|
<td>
|
||||||
|
<button class="btn btn-sm btn-secondary" type="button" data-bs-toggle="collapse" data-bs-target="#details-{{.ID}}" aria-expanded="false" aria-controls="details-{{.ID}}">
|
||||||
|
Details
|
||||||
|
</button>
|
||||||
|
{{if $.LoggedIn}}
|
||||||
<a href="/delete?id={{.ID}}" class="btn btn-sm btn-danger" onclick="return confirm('Eintrag wirklich löschen?')">Löschen</a>
|
<a href="/delete?id={{.ID}}" class="btn btn-sm btn-danger" onclick="return confirm('Eintrag wirklich löschen?')">Löschen</a>
|
||||||
</td>
|
|
||||||
{{end}}
|
{{end}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="9" class="p-0 border-0">
|
||||||
|
<div class="collapse" id="details-{{.ID}}">
|
||||||
|
<div class="bg-light p-3 border-top">
|
||||||
|
<strong>Interne Infos (Details):</strong>
|
||||||
|
<table class="table table-sm table-bordered mb-0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Startort</th>
|
||||||
|
<th>Zielort</th>
|
||||||
|
<th>Schiff</th>
|
||||||
|
<th>Ware</th>
|
||||||
|
<th>Zeit (min)</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>{{.Startort}}</td>
|
||||||
|
<td>{{.Zielort}}</td>
|
||||||
|
<td>{{.Schiff}}</td>
|
||||||
|
<td>{{.Ware}}</td>
|
||||||
|
<td>{{formatNumber .Zeitaufwand}}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
</tbody>
|
</tbody>
|
||||||
@@ -652,6 +886,36 @@ const htmlTemplate = `
|
|||||||
<hr />
|
<hr />
|
||||||
</div>
|
</div>
|
||||||
<script src="/static/js/bootstrap.bundle.min.js"></script>
|
<script src="/static/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="/static/js/tom-select.complete.min.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
new TomSelect("#zielort", {
|
||||||
|
create: true, // erlaubt Freitext
|
||||||
|
sortField: "text"
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
new TomSelect("#startort", {
|
||||||
|
create: true, // erlaubt Freitext
|
||||||
|
sortField: "text"
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
new TomSelect("#schiff", {
|
||||||
|
create: true, // erlaubt Freitext
|
||||||
|
sortField: "text"
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
new TomSelect("#ware", {
|
||||||
|
create: true, // erlaubt Freitext
|
||||||
|
sortField: "text"
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
const tabKey = "lastActiveTab";
|
const tabKey = "lastActiveTab";
|
||||||
|
2
static/css/tom-select.default.min.css
vendored
Normal file
2
static/css/tom-select.default.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
5021
static/js/tom-select.complete.min.js
vendored
Normal file
5021
static/js/tom-select.complete.min.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user