mirror of
https://github.com/Theodor-Springmann-Stiftung/lenz-web.git
synced 2025-10-28 16:55:32 +00:00
entwurf kennzeichnen
This commit is contained in:
5
helpers/functions/math.go
Normal file
5
helpers/functions/math.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package functions
|
||||
|
||||
func Minus(a, b int) int {
|
||||
return a - b
|
||||
}
|
||||
@@ -124,6 +124,9 @@ func (e *Engine) funcs() error {
|
||||
e.AddFunc("Today", functions.Today)
|
||||
e.AddFunc("GetMonth", functions.GetMonth)
|
||||
|
||||
// Math
|
||||
e.AddFunc("Minus", functions.Minus)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -15370,76 +15370,6 @@ class Previewer {
|
||||
}
|
||||
}
|
||||
EventEmitter(Previewer.prototype);
|
||||
const ATTR_XSLT_ONLOAD = "script[xslt-onload]", ATTR_XSLT_TEMPLATE = "xslt-template", ATTR_XSLT_STATE = "xslt-transformed", SCROLL_BUTTON_ELEMENT = "scroll-button", TOOLTIP_ELEMENT = "tool-tip";
|
||||
var ji, oa, ro;
|
||||
class XSLTParseProcess {
|
||||
constructor() {
|
||||
Da(this, oa);
|
||||
Da(this, ji);
|
||||
eo(this, ji, /* @__PURE__ */ new Map());
|
||||
}
|
||||
setup() {
|
||||
let ze = htmx.findAll(ATTR_XSLT_ONLOAD);
|
||||
for (let Wr of ze)
|
||||
to(this, oa, ro).call(this, Wr);
|
||||
}
|
||||
hookupHTMX() {
|
||||
htmx.on("htmx:load", (ze) => {
|
||||
this.setup();
|
||||
});
|
||||
}
|
||||
}
|
||||
ji = new WeakMap(), oa = new WeakSet(), ro = function(ze) {
|
||||
if (ze.getAttribute(ATTR_XSLT_STATE) === "true" || !ze.hasAttribute(ATTR_XSLT_TEMPLATE))
|
||||
return;
|
||||
let Wr = "#" + ze.getAttribute(ATTR_XSLT_TEMPLATE), Yr = Na(this, ji).get(Wr);
|
||||
if (!Yr) {
|
||||
let en = htmx.find(Wr);
|
||||
if (en) {
|
||||
let tn = en.innerHTML ? new DOMParser().parseFromString(en.innerHTML, "application/xml") : en.contentDocument;
|
||||
Yr = new XSLTProcessor(), Yr.importStylesheet(tn), Na(this, ji).set(Wr, Yr);
|
||||
} else
|
||||
throw new Error("Unknown XSLT template: " + Wr);
|
||||
}
|
||||
let Qr = new DOMParser().parseFromString(ze.innerHTML, "application/xml"), Kr = Yr.transformToFragment(Qr, document), Zr = new XMLSerializer().serializeToString(Kr);
|
||||
ze.outerHTML = Zr;
|
||||
};
|
||||
class ScrollButton extends HTMLElement {
|
||||
constructor() {
|
||||
super(), this.handleScroll = this.handleScroll.bind(this), this.scrollToTop = this.scrollToTop.bind(this);
|
||||
}
|
||||
connectedCallback() {
|
||||
this.innerHTML = `
|
||||
<button
|
||||
class="
|
||||
scroll-to-top
|
||||
fixed bottom-5 right-5
|
||||
hidden
|
||||
bg-gray-800 text-white
|
||||
p-2
|
||||
rounded-md
|
||||
cursor-pointer
|
||||
text-2xl
|
||||
hover:opacity-80
|
||||
transition-opacity
|
||||
border-0
|
||||
"
|
||||
aria-label="Scroll to top"
|
||||
>
|
||||
<i class="ri-arrow-up-double-line"></i>
|
||||
</button>
|
||||
`, this._button = this.querySelector(".scroll-to-top"), window.addEventListener("scroll", this.handleScroll), this._button.addEventListener("click", this.scrollToTop);
|
||||
}
|
||||
disconnectedCallback() {
|
||||
window.removeEventListener("scroll", this.handleScroll), this._button.removeEventListener("click", this.scrollToTop);
|
||||
}
|
||||
handleScroll() {
|
||||
(window.scrollY || document.documentElement.scrollTop) > 300 ? this._button.classList.remove("hidden") : this._button.classList.add("hidden");
|
||||
}
|
||||
scrollToTop() {
|
||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||
}
|
||||
}
|
||||
class ToolTip extends HTMLElement {
|
||||
static get observedAttributes() {
|
||||
return ["position", "timeout"];
|
||||
@@ -15448,14 +15378,7 @@ class ToolTip extends HTMLElement {
|
||||
super(), this._tooltipBox = null, this._timeout = 200, this._hideTimeout = null, this._hiddenTimeout = null;
|
||||
}
|
||||
connectedCallback() {
|
||||
this.classList.add(
|
||||
"w-full",
|
||||
"h-full",
|
||||
"relative",
|
||||
"block",
|
||||
"leading-none",
|
||||
"[&>*]:leading-normal"
|
||||
);
|
||||
this.classList.add("relative", "block", "leading-none", "[&>*]:leading-normal");
|
||||
const ze = this.querySelector(".data-tip"), Wr = ze ? ze.innerHTML : "Tooltip";
|
||||
ze && ze.classList.add("hidden"), this._tooltipBox = document.createElement("div"), this._tooltipBox.innerHTML = Wr, this._tooltipBox.className = [
|
||||
"opacity-0",
|
||||
@@ -15548,6 +15471,76 @@ class ToolTip extends HTMLElement {
|
||||
}
|
||||
}
|
||||
}
|
||||
const ATTR_XSLT_ONLOAD = "script[xslt-onload]", ATTR_XSLT_TEMPLATE = "xslt-template", ATTR_XSLT_STATE = "xslt-transformed", SCROLL_BUTTON_ELEMENT = "scroll-button", TOOLTIP_ELEMENT = "tool-tip";
|
||||
var ji, oa, ro;
|
||||
class XSLTParseProcess {
|
||||
constructor() {
|
||||
Da(this, oa);
|
||||
Da(this, ji);
|
||||
eo(this, ji, /* @__PURE__ */ new Map());
|
||||
}
|
||||
setup() {
|
||||
let ze = htmx.findAll(ATTR_XSLT_ONLOAD);
|
||||
for (let Wr of ze)
|
||||
to(this, oa, ro).call(this, Wr);
|
||||
}
|
||||
hookupHTMX() {
|
||||
htmx.on("htmx:load", (ze) => {
|
||||
this.setup();
|
||||
});
|
||||
}
|
||||
}
|
||||
ji = new WeakMap(), oa = new WeakSet(), ro = function(ze) {
|
||||
if (ze.getAttribute(ATTR_XSLT_STATE) === "true" || !ze.hasAttribute(ATTR_XSLT_TEMPLATE))
|
||||
return;
|
||||
let Wr = "#" + ze.getAttribute(ATTR_XSLT_TEMPLATE), Yr = Na(this, ji).get(Wr);
|
||||
if (!Yr) {
|
||||
let en = htmx.find(Wr);
|
||||
if (en) {
|
||||
let tn = en.innerHTML ? new DOMParser().parseFromString(en.innerHTML, "application/xml") : en.contentDocument;
|
||||
Yr = new XSLTProcessor(), Yr.importStylesheet(tn), Na(this, ji).set(Wr, Yr);
|
||||
} else
|
||||
throw new Error("Unknown XSLT template: " + Wr);
|
||||
}
|
||||
let Qr = new DOMParser().parseFromString(ze.innerHTML, "application/xml"), Kr = Yr.transformToFragment(Qr, document), Zr = new XMLSerializer().serializeToString(Kr);
|
||||
ze.outerHTML = Zr;
|
||||
};
|
||||
class ScrollButton extends HTMLElement {
|
||||
constructor() {
|
||||
super(), this.handleScroll = this.handleScroll.bind(this), this.scrollToTop = this.scrollToTop.bind(this);
|
||||
}
|
||||
connectedCallback() {
|
||||
this.innerHTML = `
|
||||
<button
|
||||
class="
|
||||
scroll-to-top
|
||||
fixed bottom-5 right-5
|
||||
hidden
|
||||
bg-gray-800 text-white
|
||||
p-2
|
||||
rounded-md
|
||||
cursor-pointer
|
||||
text-2xl
|
||||
hover:opacity-80
|
||||
transition-opacity
|
||||
border-0
|
||||
"
|
||||
aria-label="Scroll to top"
|
||||
>
|
||||
<i class="ri-arrow-up-double-line"></i>
|
||||
</button>
|
||||
`, this._button = this.querySelector(".scroll-to-top"), window.addEventListener("scroll", this.handleScroll), this._button.addEventListener("click", this.scrollToTop);
|
||||
}
|
||||
disconnectedCallback() {
|
||||
window.removeEventListener("scroll", this.handleScroll), this._button.removeEventListener("click", this.scrollToTop);
|
||||
}
|
||||
handleScroll() {
|
||||
(window.scrollY || document.documentElement.scrollTop) > 300 ? this._button.classList.remove("hidden") : this._button.classList.add("hidden");
|
||||
}
|
||||
scrollToTop() {
|
||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||
}
|
||||
}
|
||||
function Startup() {
|
||||
let Gr = null;
|
||||
const ze = [];
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -6,31 +6,47 @@
|
||||
<div class="mr-4 text-6xl">{{ $model.Letter }}</div>
|
||||
-->
|
||||
<div class="pt-0.5">
|
||||
<div class="italic">{{ $model.Earliest.Text -}}</div>
|
||||
<div class="flex flex-row">
|
||||
<div class="italic">{{ $model.Earliest.Text -}}</div>
|
||||
{{- if $model.IsDraft.IsTrue -}}
|
||||
<tool-tip position="top">
|
||||
<div class="ml-3 text-gray-500 align-middle"><i class="ri-draft-line"></i></div>
|
||||
<div class="data-tip">Entwurf</div>
|
||||
</tool-tip>
|
||||
{{- end -}}
|
||||
</div>
|
||||
{{- range $sr := $model.SendReceivedPairs -}}
|
||||
<div class="flex flex-row">
|
||||
<div>
|
||||
{{- range $i, $p := $sr.Sent.Persons -}}
|
||||
<div class="inline-block">
|
||||
{{- if $i -}}
|
||||
,
|
||||
{{ end -}}
|
||||
{{- $person := Person $p.Reference -}}
|
||||
{{- $person.Name -}}
|
||||
</div>
|
||||
{{ if and $i (eq $i (Minus (len $sr.Sent.Persons) 1)) }}
|
||||
und
|
||||
{{ else if $i }}
|
||||
,
|
||||
{{ end }}
|
||||
{{- $person := Person $p.Reference -}}
|
||||
{{- $person.Name -}}
|
||||
{{- end -}}
|
||||
</div>
|
||||
<div class="mx-3">
|
||||
{{- if $model.IsDraft.IsTrue -}}
|
||||
<div class="diagonal-strike">
|
||||
<i class="ri-arrow-right-long-line"></i>
|
||||
</div>
|
||||
{{- else -}}
|
||||
<i class="ri-arrow-right-long-line"></i>
|
||||
{{- end -}}
|
||||
</div>
|
||||
<div class="mx-2"><i class="ri-arrow-right-long-line"></i></div>
|
||||
{{- if $sr.Received -}}
|
||||
<div>
|
||||
{{- range $i, $p := $sr.Received.Persons -}}
|
||||
<div class="inline-block">
|
||||
{{- if $i -}}
|
||||
,
|
||||
{{ end -}}
|
||||
{{- $person := Person $p.Reference -}}
|
||||
{{- $person.Name -}}
|
||||
</div>
|
||||
{{ if and $i (eq $i (Minus (len $sr.Received.Persons) 1)) }}
|
||||
und
|
||||
{{ else if $i }}
|
||||
,
|
||||
{{ end }}
|
||||
{{- $person := Person $p.Reference -}}
|
||||
{{- $person.Name -}}
|
||||
{{- end -}}
|
||||
</div>
|
||||
{{- else -}}
|
||||
|
||||
@@ -5,6 +5,7 @@ import "../public/js/alpine.min.js";
|
||||
import "../public/js/htmx.min.js";
|
||||
import "../public/js/htmx-response-targets.js";
|
||||
import { Previewer } from "pagedjs";
|
||||
import { ToolTip } from "./tool-tip.js";
|
||||
|
||||
const ATTR_XSLT_ONLOAD = "script[xslt-onload]";
|
||||
const ATTR_XSLT_TEMPLATE = "xslt-template";
|
||||
@@ -157,152 +158,6 @@ class ScrollButton extends HTMLElement {
|
||||
}
|
||||
}
|
||||
|
||||
class ToolTip extends HTMLElement {
|
||||
static get observedAttributes() {
|
||||
return ["position", "timeout"];
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._tooltipBox = null;
|
||||
this._timeout = 200;
|
||||
this._hideTimeout = null;
|
||||
this._hiddenTimeout = null;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.classList.add(
|
||||
"w-full",
|
||||
"h-full",
|
||||
"relative",
|
||||
"block",
|
||||
"leading-none",
|
||||
"[&>*]:leading-normal",
|
||||
);
|
||||
const dataTipElem = this.querySelector(".data-tip");
|
||||
const tipContent = dataTipElem ? dataTipElem.innerHTML : "Tooltip";
|
||||
|
||||
if (dataTipElem) {
|
||||
dataTipElem.classList.add("hidden");
|
||||
}
|
||||
|
||||
this._tooltipBox = document.createElement("div");
|
||||
this._tooltipBox.innerHTML = tipContent;
|
||||
this._tooltipBox.className = [
|
||||
"opacity-0",
|
||||
"hidden",
|
||||
"absolute",
|
||||
"px-2",
|
||||
"py-1",
|
||||
"text-sm",
|
||||
"text-white",
|
||||
"bg-gray-900",
|
||||
"rounded",
|
||||
"shadow",
|
||||
"z-10",
|
||||
"whitespace-nowrap",
|
||||
"transition-all",
|
||||
"duration-200",
|
||||
"font-sans",
|
||||
].join(" ");
|
||||
|
||||
this.appendChild(this._tooltipBox);
|
||||
|
||||
this._updatePosition();
|
||||
|
||||
this.addEventListener("mouseenter", () => this._showTooltip());
|
||||
this.addEventListener("mouseleave", () => this._hideTooltip());
|
||||
}
|
||||
|
||||
attributeChangedCallback(name, oldValue, newValue) {
|
||||
if (name === "position" && this._tooltipBox) {
|
||||
this._updatePosition();
|
||||
}
|
||||
if (name === "timeout" && newValue) {
|
||||
this._timeout = parseInt(newValue) || 200;
|
||||
}
|
||||
}
|
||||
|
||||
_showTooltip() {
|
||||
clearTimeout(this._hideTimeout);
|
||||
clearTimeout(this._hiddenTimeout);
|
||||
this._tooltipBox.classList.remove("hidden");
|
||||
setTimeout(() => {
|
||||
this._tooltipBox.classList.remove("opacity-0");
|
||||
this._tooltipBox.classList.add("opacity-100");
|
||||
}, 16);
|
||||
}
|
||||
|
||||
_hideTooltip() {
|
||||
this._hideTimeout = setTimeout(() => {
|
||||
this._tooltipBox.classList.remove("opacity-100");
|
||||
this._tooltipBox.classList.add("opacity-0");
|
||||
this._hiddenTimeout = setTimeout(() => {
|
||||
this._tooltipBox.classList.add("hidden");
|
||||
}, this._timeout + 100);
|
||||
}, this._timeout);
|
||||
}
|
||||
|
||||
_updatePosition() {
|
||||
this._tooltipBox.classList.remove(
|
||||
"bottom-full",
|
||||
"left-1/2",
|
||||
"-translate-x-1/2",
|
||||
"mb-2", // top
|
||||
"top-full",
|
||||
"mt-2", // bottom
|
||||
"right-full",
|
||||
"-translate-y-1/2",
|
||||
"mr-2",
|
||||
"top-1/2", // left
|
||||
"left-full",
|
||||
"ml-2", // right
|
||||
);
|
||||
|
||||
const pos = this.getAttribute("position") || "top";
|
||||
|
||||
switch (pos) {
|
||||
case "bottom":
|
||||
this._tooltipBox.classList.add(
|
||||
"top-full",
|
||||
"left-1/2",
|
||||
"transform",
|
||||
"-translate-x-1/2",
|
||||
"mt-0.5",
|
||||
);
|
||||
break;
|
||||
case "left":
|
||||
this._tooltipBox.classList.add(
|
||||
"right-full",
|
||||
"top-1/2",
|
||||
"transform",
|
||||
"-translate-y-1/2",
|
||||
"mr-0.5",
|
||||
);
|
||||
break;
|
||||
case "right":
|
||||
this._tooltipBox.classList.add(
|
||||
"left-full",
|
||||
"top-1/2",
|
||||
"transform",
|
||||
"-translate-y-1/2",
|
||||
"ml-0.5",
|
||||
);
|
||||
break;
|
||||
case "top":
|
||||
default:
|
||||
// top as default
|
||||
this._tooltipBox.classList.add(
|
||||
"bottom-full",
|
||||
"left-1/2",
|
||||
"transform",
|
||||
"-translate-x-1/2",
|
||||
"mb-0.5",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Startup() {
|
||||
let pagedPreviewer = null;
|
||||
const positionedIntervals = [];
|
||||
|
||||
@@ -87,6 +87,26 @@
|
||||
@apply font-bold text-red-500;
|
||||
}
|
||||
|
||||
.diagonal-strike {
|
||||
@apply relative inline-block;
|
||||
}
|
||||
|
||||
.diagonal-strike::before {
|
||||
@apply border-slate-50 border-t-[3px];
|
||||
position: absolute;
|
||||
content: "";
|
||||
left: 10%;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
width: 60%;
|
||||
|
||||
-webkit-transform: rotate(-65deg);
|
||||
-moz-transform: rotate(-65deg);
|
||||
-ms-transform: rotate(-65deg);
|
||||
-o-transform: rotate(-65deg);
|
||||
transform: rotate(-65deg);
|
||||
}
|
||||
|
||||
.text {
|
||||
@apply font-serif relative;
|
||||
}
|
||||
|
||||
138
views/transform/tool-tip.js
Normal file
138
views/transform/tool-tip.js
Normal file
@@ -0,0 +1,138 @@
|
||||
export class ToolTip extends HTMLElement {
|
||||
static get observedAttributes() {
|
||||
return ["position", "timeout"];
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._tooltipBox = null;
|
||||
this._timeout = 200;
|
||||
this._hideTimeout = null;
|
||||
this._hiddenTimeout = null;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.classList.add("relative", "block", "leading-none", "[&>*]:leading-normal");
|
||||
const dataTipElem = this.querySelector(".data-tip");
|
||||
const tipContent = dataTipElem ? dataTipElem.innerHTML : "Tooltip";
|
||||
|
||||
if (dataTipElem) {
|
||||
dataTipElem.classList.add("hidden");
|
||||
}
|
||||
|
||||
this._tooltipBox = document.createElement("div");
|
||||
this._tooltipBox.innerHTML = tipContent;
|
||||
this._tooltipBox.className = [
|
||||
"opacity-0",
|
||||
"hidden",
|
||||
"absolute",
|
||||
"px-2",
|
||||
"py-1",
|
||||
"text-sm",
|
||||
"text-white",
|
||||
"bg-gray-900",
|
||||
"rounded",
|
||||
"shadow",
|
||||
"z-10",
|
||||
"whitespace-nowrap",
|
||||
"transition-all",
|
||||
"duration-200",
|
||||
"font-sans",
|
||||
].join(" ");
|
||||
|
||||
this.appendChild(this._tooltipBox);
|
||||
|
||||
this._updatePosition();
|
||||
|
||||
this.addEventListener("mouseenter", () => this._showTooltip());
|
||||
this.addEventListener("mouseleave", () => this._hideTooltip());
|
||||
}
|
||||
|
||||
attributeChangedCallback(name, oldValue, newValue) {
|
||||
if (name === "position" && this._tooltipBox) {
|
||||
this._updatePosition();
|
||||
}
|
||||
if (name === "timeout" && newValue) {
|
||||
this._timeout = parseInt(newValue) || 200;
|
||||
}
|
||||
}
|
||||
|
||||
_showTooltip() {
|
||||
clearTimeout(this._hideTimeout);
|
||||
clearTimeout(this._hiddenTimeout);
|
||||
this._tooltipBox.classList.remove("hidden");
|
||||
setTimeout(() => {
|
||||
this._tooltipBox.classList.remove("opacity-0");
|
||||
this._tooltipBox.classList.add("opacity-100");
|
||||
}, 16);
|
||||
}
|
||||
|
||||
_hideTooltip() {
|
||||
this._hideTimeout = setTimeout(() => {
|
||||
this._tooltipBox.classList.remove("opacity-100");
|
||||
this._tooltipBox.classList.add("opacity-0");
|
||||
this._hiddenTimeout = setTimeout(() => {
|
||||
this._tooltipBox.classList.add("hidden");
|
||||
}, this._timeout + 100);
|
||||
}, this._timeout);
|
||||
}
|
||||
|
||||
_updatePosition() {
|
||||
this._tooltipBox.classList.remove(
|
||||
"bottom-full",
|
||||
"left-1/2",
|
||||
"-translate-x-1/2",
|
||||
"mb-2", // top
|
||||
"top-full",
|
||||
"mt-2", // bottom
|
||||
"right-full",
|
||||
"-translate-y-1/2",
|
||||
"mr-2",
|
||||
"top-1/2", // left
|
||||
"left-full",
|
||||
"ml-2", // right
|
||||
);
|
||||
|
||||
const pos = this.getAttribute("position") || "top";
|
||||
|
||||
switch (pos) {
|
||||
case "bottom":
|
||||
this._tooltipBox.classList.add(
|
||||
"top-full",
|
||||
"left-1/2",
|
||||
"transform",
|
||||
"-translate-x-1/2",
|
||||
"mt-0.5",
|
||||
);
|
||||
break;
|
||||
case "left":
|
||||
this._tooltipBox.classList.add(
|
||||
"right-full",
|
||||
"top-1/2",
|
||||
"transform",
|
||||
"-translate-y-1/2",
|
||||
"mr-0.5",
|
||||
);
|
||||
break;
|
||||
case "right":
|
||||
this._tooltipBox.classList.add(
|
||||
"left-full",
|
||||
"top-1/2",
|
||||
"transform",
|
||||
"-translate-y-1/2",
|
||||
"ml-0.5",
|
||||
);
|
||||
break;
|
||||
case "top":
|
||||
default:
|
||||
// top as default
|
||||
this._tooltipBox.classList.add(
|
||||
"bottom-full",
|
||||
"left-1/2",
|
||||
"transform",
|
||||
"-translate-x-1/2",
|
||||
"mb-0.5",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,14 @@ const (
|
||||
False
|
||||
)
|
||||
|
||||
func (b OptionalBool) IsTrue() bool {
|
||||
return b == True
|
||||
}
|
||||
|
||||
func (b OptionalBool) IsFalse() bool {
|
||||
return b == False || b == Unspecified
|
||||
}
|
||||
|
||||
func (b *OptionalBool) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
var attr struct {
|
||||
Value string `xml:"value,attr"`
|
||||
|
||||
Reference in New Issue
Block a user