Initial working marker display in shadow dom
This commit is contained in:
parent
bea7c28af2
commit
b94d09696e
7 changed files with 208 additions and 39 deletions
112
db/sql/publicreport_image_with_json_by_quick_id.bob.go
Normal file
112
db/sql/publicreport_image_with_json_by_quick_id.bob.go
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
// Code generated by BobGen psql v0.42.1. DO NOT EDIT.
|
||||||
|
// This file is meant to be re-generated in place and/or deleted at any time.
|
||||||
|
|
||||||
|
package sql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
_ "embed"
|
||||||
|
"io"
|
||||||
|
"iter"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aarondl/opt/null"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/stephenafamo/bob"
|
||||||
|
"github.com/stephenafamo/bob/dialect/psql"
|
||||||
|
"github.com/stephenafamo/bob/dialect/psql/dialect"
|
||||||
|
"github.com/stephenafamo/bob/orm"
|
||||||
|
"github.com/stephenafamo/scan"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed publicreport_image_with_json_by_quick_id.bob.sql
|
||||||
|
var formattedQueries_publicreport_image_with_json_by_quick_id string
|
||||||
|
|
||||||
|
var publicreportImageWithJSONByQuickIDSQL = formattedQueries_publicreport_image_with_json_by_quick_id[172:965]
|
||||||
|
|
||||||
|
type PublicreportImageWithJSONByQuickIDQuery = orm.ModQuery[*dialect.SelectQuery, publicreportImageWithJSONByQuickID, PublicreportImageWithJSONByQuickIDRow, []PublicreportImageWithJSONByQuickIDRow, publicreportImageWithJSONByQuickIDTransformer]
|
||||||
|
|
||||||
|
func PublicreportImageWithJSONByQuickID(QuickID int32) *PublicreportImageWithJSONByQuickIDQuery {
|
||||||
|
var expressionTypArgs publicreportImageWithJSONByQuickID
|
||||||
|
|
||||||
|
expressionTypArgs.QuickID = psql.Arg(QuickID)
|
||||||
|
|
||||||
|
return &PublicreportImageWithJSONByQuickIDQuery{
|
||||||
|
Query: orm.Query[publicreportImageWithJSONByQuickID, PublicreportImageWithJSONByQuickIDRow, []PublicreportImageWithJSONByQuickIDRow, publicreportImageWithJSONByQuickIDTransformer]{
|
||||||
|
ExecQuery: orm.ExecQuery[publicreportImageWithJSONByQuickID]{
|
||||||
|
BaseQuery: bob.BaseQuery[publicreportImageWithJSONByQuickID]{
|
||||||
|
Expression: expressionTypArgs,
|
||||||
|
Dialect: dialect.Dialect,
|
||||||
|
QueryType: bob.QueryTypeSelect,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Scanner: func(context.Context, []string) (func(*scan.Row) (any, error), func(any) (PublicreportImageWithJSONByQuickIDRow, error)) {
|
||||||
|
return func(row *scan.Row) (any, error) {
|
||||||
|
var t PublicreportImageWithJSONByQuickIDRow
|
||||||
|
row.ScheduleScanByIndex(0, &t.ID)
|
||||||
|
row.ScheduleScanByIndex(1, &t.ContentType)
|
||||||
|
row.ScheduleScanByIndex(2, &t.Created)
|
||||||
|
row.ScheduleScanByIndex(3, &t.Location)
|
||||||
|
row.ScheduleScanByIndex(4, &t.LocationJSON)
|
||||||
|
row.ScheduleScanByIndex(5, &t.ResolutionX)
|
||||||
|
row.ScheduleScanByIndex(6, &t.ResolutionY)
|
||||||
|
row.ScheduleScanByIndex(7, &t.StorageUUID)
|
||||||
|
row.ScheduleScanByIndex(8, &t.StorageSize)
|
||||||
|
row.ScheduleScanByIndex(9, &t.UploadedFilename)
|
||||||
|
return &t, nil
|
||||||
|
}, func(v any) (PublicreportImageWithJSONByQuickIDRow, error) {
|
||||||
|
return *(v.(*PublicreportImageWithJSONByQuickIDRow)), nil
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Mod: bob.ModFunc[*dialect.SelectQuery](func(q *dialect.SelectQuery) {
|
||||||
|
q.AppendSelect(expressionTypArgs.subExpr(9, 549))
|
||||||
|
q.SetTable(expressionTypArgs.subExpr(555, 742))
|
||||||
|
q.AppendWhere(expressionTypArgs.subExpr(750, 792))
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type PublicreportImageWithJSONByQuickIDRow = struct {
|
||||||
|
ID int32 `db:"id"`
|
||||||
|
ContentType string `db:"content_type"`
|
||||||
|
Created time.Time `db:"created"`
|
||||||
|
Location null.Val[string] `db:"location"`
|
||||||
|
LocationJSON string `db:"location_json"`
|
||||||
|
ResolutionX int32 `db:"resolution_x"`
|
||||||
|
ResolutionY int32 `db:"resolution_y"`
|
||||||
|
StorageUUID uuid.UUID `db:"storage_uuid"`
|
||||||
|
StorageSize int64 `db:"storage_size"`
|
||||||
|
UploadedFilename string `db:"uploaded_filename"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type publicreportImageWithJSONByQuickIDTransformer = bob.SliceTransformer[PublicreportImageWithJSONByQuickIDRow, []PublicreportImageWithJSONByQuickIDRow]
|
||||||
|
|
||||||
|
type publicreportImageWithJSONByQuickID struct {
|
||||||
|
QuickID bob.Expression
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o publicreportImageWithJSONByQuickID) args() iter.Seq[orm.ArgWithPosition] {
|
||||||
|
return func(yield func(arg orm.ArgWithPosition) bool) {
|
||||||
|
if !yield(orm.ArgWithPosition{
|
||||||
|
Name: "quickID",
|
||||||
|
Start: 790,
|
||||||
|
Stop: 792,
|
||||||
|
Expression: o.QuickID,
|
||||||
|
}) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o publicreportImageWithJSONByQuickID) raw(from, to int) string {
|
||||||
|
return publicreportImageWithJSONByQuickIDSQL[from:to]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o publicreportImageWithJSONByQuickID) subExpr(from, to int) bob.Expression {
|
||||||
|
return orm.ArgsToExpression(publicreportImageWithJSONByQuickIDSQL, from, to, o.args())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o publicreportImageWithJSONByQuickID) WriteSQL(ctx context.Context, w io.StringWriter, d bob.Dialect, start int) ([]any, error) {
|
||||||
|
return o.subExpr(0, len(publicreportImageWithJSONByQuickIDSQL)).WriteSQL(ctx, w, d, start)
|
||||||
|
}
|
||||||
18
db/sql/publicreport_image_with_json_by_quick_id.bob.sql
Normal file
18
db/sql/publicreport_image_with_json_by_quick_id.bob.sql
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
-- Code generated by BobGen psql v0.42.1. DO NOT EDIT.
|
||||||
|
-- This file is meant to be re-generated in place and/or deleted at any time.
|
||||||
|
|
||||||
|
-- PublicreportImageWithJSONByQuickID
|
||||||
|
SELECT
|
||||||
|
"publicreport.image"."id" AS "id",
|
||||||
|
"publicreport.image"."content_type" AS "content_type",
|
||||||
|
"publicreport.image"."created" AS "created",
|
||||||
|
"publicreport.image"."location" AS "location",
|
||||||
|
ST_AsGeoJSON("publicreport.image"."location") AS "location_json",
|
||||||
|
"publicreport.image"."resolution_x" AS "resolution_x",
|
||||||
|
"publicreport.image"."resolution_y" AS "resolution_y",
|
||||||
|
"publicreport.image"."storage_uuid" AS "storage_uuid",
|
||||||
|
"publicreport.image"."storage_size" AS "storage_size",
|
||||||
|
"publicreport.image"."uploaded_filename" AS "uploaded_filename"
|
||||||
|
FROM "publicreport"."image" AS "publicreport.image"
|
||||||
|
INNER JOIN "publicreport"."quick_image" AS "publicreport.quick_image" ON ("publicreport.image"."id" = "publicreport.quick_image"."image_id")
|
||||||
|
WHERE ("publicreport.quick_image"."quick_id" = $1);
|
||||||
15
db/sql/publicreport_image_with_json_by_quick_id.sql
Normal file
15
db/sql/publicreport_image_with_json_by_quick_id.sql
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
-- PublicreportImageWithJSONByQuickID
|
||||||
|
SELECT
|
||||||
|
"publicreport.image"."id" AS "id",
|
||||||
|
"publicreport.image"."content_type" AS "content_type",
|
||||||
|
"publicreport.image"."created" AS "created",
|
||||||
|
"publicreport.image"."location" AS "location",
|
||||||
|
ST_AsGeoJSON("publicreport.image"."location") AS "location_json",
|
||||||
|
"publicreport.image"."resolution_x" AS "resolution_x",
|
||||||
|
"publicreport.image"."resolution_y" AS "resolution_y",
|
||||||
|
"publicreport.image"."storage_uuid" AS "storage_uuid",
|
||||||
|
"publicreport.image"."storage_size" AS "storage_size",
|
||||||
|
"publicreport.image"."uploaded_filename" AS "uploaded_filename"
|
||||||
|
FROM "publicreport"."image" AS "publicreport.image"
|
||||||
|
INNER JOIN "publicreport"."quick_image" AS "publicreport.quick_image" ON ("publicreport.image"."id" = "publicreport.quick_image"."image_id")
|
||||||
|
WHERE ("publicreport.quick_image"."quick_id" = $1)
|
||||||
|
|
@ -110,6 +110,8 @@ func bigNumber(n int) string {
|
||||||
func makeFuncMap() template.FuncMap {
|
func makeFuncMap() template.FuncMap {
|
||||||
funcMap := template.FuncMap{
|
funcMap := template.FuncMap{
|
||||||
"bigNumber": bigNumber,
|
"bigNumber": bigNumber,
|
||||||
|
"html": unescapeHTML,
|
||||||
|
"json": unescapeJS,
|
||||||
"GISStatement": gisStatement,
|
"GISStatement": gisStatement,
|
||||||
"latLngDisplay": latLngDisplay,
|
"latLngDisplay": latLngDisplay,
|
||||||
"publicReportID": publicReportID,
|
"publicReportID": publicReportID,
|
||||||
|
|
@ -291,6 +293,12 @@ func timeSince(t time.Time) string {
|
||||||
return fmt.Sprintf("%d days ago", int(days))
|
return fmt.Sprintf("%d days ago", int(days))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func unescapeHTML(s string) template.HTML {
|
||||||
|
return template.HTML(s)
|
||||||
|
}
|
||||||
|
func unescapeJS(s string) template.JS {
|
||||||
|
return template.JS(s)
|
||||||
|
}
|
||||||
func uuidShort(uuid uuid.UUID) string {
|
func uuidShort(uuid uuid.UUID) string {
|
||||||
s := uuid.String()
|
s := uuid.String()
|
||||||
if len(s) < 7 {
|
if len(s) < 7 {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
var map = null;
|
var map = null;
|
||||||
// A map that just shows a single point location, and can't be moved
|
// A map that just shows a bunch of markers, it can't change them
|
||||||
class MapSinglePoint extends HTMLElement {
|
class MapWithMarkers extends HTMLElement {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
|
@ -10,8 +10,10 @@ class MapSinglePoint extends HTMLElement {
|
||||||
// Initial render
|
// Initial render
|
||||||
this.render();
|
this.render();
|
||||||
|
|
||||||
|
this._map = null;
|
||||||
|
|
||||||
// markers shown on the map. Should be none or 1, generally.
|
// markers shown on the map. Should be none or 1, generally.
|
||||||
this._markers = null;
|
this._markers = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lifecycle: when element is added to the DOM
|
// Lifecycle: when element is added to the DOM
|
||||||
|
|
@ -35,7 +37,7 @@ class MapSinglePoint extends HTMLElement {
|
||||||
|
|
||||||
mapboxgl.accessToken = apiKey;
|
mapboxgl.accessToken = apiKey;
|
||||||
const mapElement = this.shadowRoot.querySelector("#map");
|
const mapElement = this.shadowRoot.querySelector("#map");
|
||||||
map = new mapboxgl.Map({
|
this._map = new mapboxgl.Map({
|
||||||
container: mapElement,
|
container: mapElement,
|
||||||
center: {
|
center: {
|
||||||
lat: lat,
|
lat: lat,
|
||||||
|
|
@ -44,7 +46,8 @@ class MapSinglePoint extends HTMLElement {
|
||||||
style: 'mapbox://styles/mapbox/streets-v12', // style URL
|
style: 'mapbox://styles/mapbox/streets-v12', // style URL
|
||||||
zoom: zoom,
|
zoom: zoom,
|
||||||
});
|
});
|
||||||
map.on("load", function() {
|
this._map.on("load", () => {
|
||||||
|
console.log("map loaded");
|
||||||
this.dispatchEvent(new CustomEvent('load'), {
|
this.dispatchEvent(new CustomEvent('load'), {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
composed: true, // Allows event to cross shadow DOM boundary
|
composed: true, // Allows event to cross shadow DOM boundary
|
||||||
|
|
@ -53,11 +56,13 @@ class MapSinglePoint extends HTMLElement {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
this._markers = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initial render of component
|
// Initial render of component
|
||||||
render() {
|
render() {
|
||||||
this.shadowRoot.innerHTML = `
|
this.shadowRoot.innerHTML = `
|
||||||
|
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.53.0/mapbox-gl.css' rel='stylesheet' />
|
||||||
<style>
|
<style>
|
||||||
.map-container {
|
.map-container {
|
||||||
background-color: #e9ecef;
|
background-color: #e9ecef;
|
||||||
|
|
@ -91,28 +96,16 @@ class MapSinglePoint extends HTMLElement {
|
||||||
this._map.jumpTo(args);
|
this._map.jumpTo(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
setMarker(coords) {
|
clearMarkers() {
|
||||||
console.log("Setting map marker", coords);
|
|
||||||
this._map.jumpTo({
|
|
||||||
center: coords,
|
|
||||||
zoom: 14,
|
|
||||||
});
|
|
||||||
this._markers.forEach((marker) => marker.remove());
|
this._markers.forEach((marker) => marker.remove());
|
||||||
|
}
|
||||||
const marker = new mapboxgl.Marker({
|
addMarker(coords, color) {
|
||||||
color: "#FF0000",
|
console.log("Add marker", coords, color);
|
||||||
draggable: true
|
const el = document.createElement("div");
|
||||||
}).setLngLat(coords).addTo(map);
|
el.id = "marker";
|
||||||
marker.on('dragend', function(e) {
|
const marker = new mapboxgl.Marker().setLngLat(coords).addTo(this._map);
|
||||||
const markerDraggedEvent = new CustomEvent("markerdragend", {
|
this._markers.push(marker);
|
||||||
detail: {
|
|
||||||
marker: marker
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mapContainer.dispatchEvent(markerDraggedEvent);
|
|
||||||
});
|
|
||||||
this._markers = [marker];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define('map-single-point', MapSinglePoint);
|
customElements.define('map-with-markers', MapWithMarkers);
|
||||||
|
|
@ -19,8 +19,6 @@ import (
|
||||||
"github.com/stephenafamo/bob/dialect/psql/sm"
|
"github.com/stephenafamo/bob/dialect/psql/sm"
|
||||||
"github.com/stephenafamo/scan"
|
"github.com/stephenafamo/scan"
|
||||||
/*
|
/*
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/Gleipnir-Technology/nidus-sync/db"
|
"github.com/Gleipnir-Technology/nidus-sync/db"
|
||||||
"github.com/Gleipnir-Technology/nidus-sync/h3utils"
|
"github.com/Gleipnir-Technology/nidus-sync/h3utils"
|
||||||
"github.com/aarondl/opt/omit"
|
"github.com/aarondl/opt/omit"
|
||||||
|
|
@ -33,7 +31,8 @@ type Contact struct {
|
||||||
Phone string
|
Phone string
|
||||||
}
|
}
|
||||||
type Image struct {
|
type Image struct {
|
||||||
URL string
|
Location string
|
||||||
|
URL string
|
||||||
}
|
}
|
||||||
type Report struct {
|
type Report struct {
|
||||||
Address string
|
Address string
|
||||||
|
|
@ -167,7 +166,7 @@ func contentFromQuick(ctx context.Context, report_id string) (result ContentStat
|
||||||
return result, fmt.Errorf("Failed to query nuisance %s: %w", report_id, err)
|
return result, fmt.Errorf("Failed to query nuisance %s: %w", report_id, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
images, err := quick.Images().All(ctx, db.PGInstance.BobDB)
|
images, err := sql.PublicreportImageWithJSONByQuickID(quick.ID).All(ctx, db.PGInstance.BobDB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, fmt.Errorf("Failed to get images %s: %w", report_id, err)
|
return result, fmt.Errorf("Failed to get images %s: %w", report_id, err)
|
||||||
}
|
}
|
||||||
|
|
@ -183,23 +182,24 @@ func contentFromQuick(ctx context.Context, report_id string) (result ContentStat
|
||||||
|
|
||||||
for _, image := range images {
|
for _, image := range images {
|
||||||
result.Report.Images = append(result.Report.Images, Image{
|
result.Report.Images = append(result.Report.Images, Image{
|
||||||
URL: fmt.Sprintf("https://%s/image/%s", config.RMODomain, image.StorageUUID),
|
Location: image.LocationJSON,
|
||||||
|
URL: fmt.Sprintf("https://%s/image/%s", config.RMODomain, image.StorageUUID),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
type LocationGeoJSON struct {
|
type LocationGeoJSON struct {
|
||||||
Location string
|
Location string
|
||||||
}
|
}
|
||||||
row, err := bob.One(ctx, db.PGInstance.BobDB, psql.Select(
|
location, err := bob.One(ctx, db.PGInstance.BobDB, psql.Select(
|
||||||
sm.Columns(
|
sm.Columns(
|
||||||
psql.F("ST_AsGeoJSON", "location"),
|
psql.F("ST_AsGeoJSON", "location"),
|
||||||
),
|
),
|
||||||
sm.From("publicreport.quick"),
|
sm.From("publicreport.quick"),
|
||||||
sm.Where(psql.Quote("public_id").EQ(psql.Arg(report_id))),
|
sm.Where(psql.Quote("public_id").EQ(psql.Arg(report_id))),
|
||||||
), scan.StructMapper[LocationGeoJSON]())
|
), scan.SingleColumnMapper[string])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, fmt.Errorf("Failed to query nuisance %s: %w", report_id, err)
|
return result, fmt.Errorf("Failed to query nuisance %s: %w", report_id, err)
|
||||||
}
|
}
|
||||||
result.Report.Location = row.Location
|
result.Report.Location = location
|
||||||
|
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
{{define "title"}}Status of report {{.Report.ID|publicReportID}}{{end}}
|
{{define "title"}}Status of report {{.Report.ID|publicReportID}}{{end}}
|
||||||
{{define "extraheader"}}
|
{{define "extraheader"}}
|
||||||
<script src="/static/js/map-single-point.js"></script>
|
<script src='https://api.mapbox.com/mapbox-gl-js/v3.17.0-beta.1/mapbox-gl.js'></script>
|
||||||
|
<script src="/static/js/map-with-markers.js"></script>
|
||||||
<style>
|
<style>
|
||||||
.timeline {
|
.timeline {
|
||||||
border-left: 3px solid #dee2e6;
|
border-left: 3px solid #dee2e6;
|
||||||
|
|
@ -39,6 +40,25 @@
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
<script>
|
||||||
|
const GEOJSON_LOCATION = {{.Report.Location|json}};
|
||||||
|
const GEOJSON_IMAGE_LOCATIONS = [
|
||||||
|
{{ range .Report.Images }}
|
||||||
|
{{ .Location|json }},
|
||||||
|
{{ end }}
|
||||||
|
];
|
||||||
|
function onLoad() {
|
||||||
|
const map = document.querySelector("map-with-markers");
|
||||||
|
map.addEventListener("load", (event) => {
|
||||||
|
map.jumpTo({
|
||||||
|
center: GEOJSON_LOCATION.coordinates,
|
||||||
|
zoom: 14,
|
||||||
|
});
|
||||||
|
map.addMarker(GEOJSON_LOCATION.coordinates, "#FF0000");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
document.addEventListener("DOMContentLoaded", onLoad);
|
||||||
|
</script>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<div class="container my-4">
|
<div class="container my-4">
|
||||||
|
|
@ -101,7 +121,9 @@
|
||||||
<h5 class="mb-0"><i class="fas fa-history me-2"></i>Report Detail</h5>
|
<h5 class="mb-0"><i class="fas fa-history me-2"></i>Report Detail</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<p><strong>Foo:</strong>Bar</p>
|
{{ if not (eq .Report.Comments "") }}
|
||||||
|
<p><strong>Comments:</strong>{{ .Report.Comments }}</p>
|
||||||
|
{{ end }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -111,10 +133,9 @@
|
||||||
<h5 class="mb-0"><i class="fas fa-map-marked-alt me-2"></i>Location Map</h5>
|
<h5 class="mb-0"><i class="fas fa-map-marked-alt me-2"></i>Location Map</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-0">
|
<div class="card-body p-0">
|
||||||
<map-single-point
|
<map-with-markers
|
||||||
api-key="{{ .MapboxToken }}"
|
api-key="{{ .MapboxToken }}"
|
||||||
geojson="{{ .Report.Location }}"
|
zoom="14"/>
|
||||||
zoom="14"></map-single-point>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -134,6 +155,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- History Timeline -->
|
<!-- History Timeline -->
|
||||||
|
<!--
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header bg-success text-white">
|
<div class="card-header bg-success text-white">
|
||||||
<h5 class="mb-0"><i class="fas fa-history me-2"></i>Request History</h5>
|
<h5 class="mb-0"><i class="fas fa-history me-2"></i>Request History</h5>
|
||||||
|
|
@ -163,5 +185,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
-->
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue