Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 13 additions & 12 deletions html/_generic.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
<tal xmlns:tal="http://xml.zope.org/namespaces/tal" tal:omit-tag="true">
<tal:block tal:omit-tag="true">
{
<tal xmlns:tal="http://xml.zope.org/namespaces/tal" tal:omit-tag="true"
><tal:x tal:replace="python:request.client.additional_headers.update(
{'Content-Type':'application/vnd.roundup.translation+json'}
)"></tal:x>{
"Apply": "<tal:x tal:replace="python:i18n.gettext('Apply')" />",
"Cancel": "<tal:x tal:replace="python:i18n.gettext('Cancel')" />",
"Next": "<tal:x tal:replace="python:i18n.gettext('Next')" />",
"Prev": "<tal:x tal:replace="python:i18n.gettext('Prev')" />",
"Search": "<tal:x tal:replace="python:i18n.gettext('Search')" />",
"Reset": "<tal:x tal:replace="python:i18n.gettext('Reset')" />",
"Submit": "<tal:x tal:replace="python:i18n.gettext('Login')" />",
"Hello World - \"New Programmer\"": "<tal:x tal:replace="python:i18n.gettext('Hello World - &quot;New Programmer&quot;')" />",
<tal:loop tal:omit-tag="true" tal:repeat="field python:request.form['properties'].value.split(',')">
"<tal:x tal:replace="field" />": "<tal:x tal:replace="python:i18n.gettext(field)" />"
<tal:x tal:condition="python:not repeat['field'].end" tal:content="string:," />
</tal:loop>
}
</tal:block>
"Reset": "<tal:x tal:replace="python:i18n.gettext('Reset')" />"<tal:block
tal:condition="request/form/properties/value | false"
><tal:loop tal:repeat="field
python:request.form['properties'].value.split(',')"
><tal:x tal:condition="field"
tal:replace="python:',\n \x22%s\x22: \x22%s\x22' % (
field, i18n.gettext(field))"
/></tal:loop></tal:block>
}
</tal>
117 changes: 89 additions & 28 deletions html/classhelper.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
const TRANSLATIONS = {
apply: "Apply",
cancel: "Cancel",
next: "Next",
previous: "Previous",
search: "Search",
reset: "Reset"
}

class ClassHelper extends HTMLElement {
/** @type {Window} */
popupRef = null;
static translations = null;

connectedCallback() {
let links = this.querySelectorAll("a");
Expand All @@ -22,29 +14,69 @@ class ClassHelper extends HTMLElement {
const linkProp = ClassHelper.parseLink(link);
const apiURL = ClassHelper.getRestURL(linkProp);

ClassHelper.fetchTranslations();

// Listeners
link.addEventListener("click", (event) => {
event.preventDefault();
this.openPopUp(apiURL, linkProp);
});
this.addEventListener("nextPage", (event) => {
this.pageChange(event.detail.url, linkProp);
this.pageChange(event.detail.value, linkProp);
});
this.addEventListener("prevPage", (event) => {
this.pageChange(event.detail.url, linkProp);
this.pageChange(event.detail.value, linkProp);
});
this.addEventListener("valueSelected", (event) => {
this.valueSelected(linkProp, event.detail.value);
});
this.addEventListener("search", (event) => {
const searchURL = ClassHelper.getSearchURL(linkProp, event.detail.data);
const searchURL = ClassHelper.getSearchURL(linkProp, event.detail.value);
this.searchEvent(searchURL, linkProp);
});
this.addEventListener("selection", (event) => {
this.selectionEvent(event.detail.value);
});
}

attributeChangedCallback(name, oldValue, newValue) {
if (name === "searchWith") {
if (oldValue === null) {
return;
}
let oldForm = this.popupRef.document.getElementById("popup-search");
let newForm = this.getSearchFragment();
this.popupRef.document.body.replaceChild(newForm, oldForm);
}
}

static async fetchTranslations() {
if (ClassHelper.translations != null) {
return;
}

let translations = {
"Apply": "",
"Cancel": "",
"Next": "",
"Prev": "",
"Search": "",
"Reset": "",
"Out": ""
};

let tracker = window.location.pathname.split('/')[1];
let url = new URL(window.location.origin + "/" + tracker);
url.searchParams.append("@template", "json");
url.searchParams.append("properties", Object.keys(translations).join(','));

let resp = await fetch(url);
if (!resp.ok) {
throw new Error("error fetching translations from roundup rest api");
}
ClassHelper.translations = await resp.json();
}

/**
* @param {HTMLAnchorElement} link
*/
Expand Down Expand Up @@ -190,19 +222,19 @@ class ClassHelper extends HTMLElement {
buttonCell.colSpan = 2;

const search = document.createElement("button");
search.textContent = TRANSLATIONS.search;
search.textContent = ClassHelper.translations["Search"];
search.addEventListener("click", (e) => {
e.preventDefault();
let fd = new FormData(form);
this.dispatchEvent(new CustomEvent("search", {
detail: {
data: fd
value: fd
}
}));
});

const reset = document.createElement("button");
reset.textContent = TRANSLATIONS.reset;
reset.textContent = ClassHelper.translations["Reset"];
reset.addEventListener("click", (e) => {
e.preventDefault();
form.reset();
Expand Down Expand Up @@ -230,11 +262,11 @@ class ClassHelper extends HTMLElement {
a.addEventListener("click", () => {
this.dispatchEvent(new CustomEvent("prevPage", {
detail: {
url: prevUrl
value: prevUrl
}
}));
});
a.textContent = "<<" + TRANSLATIONS.previous;
a.textContent = ClassHelper.translations["Prev"];
prev.appendChild(a);
}
const info = document.createElement('td');
Expand All @@ -245,11 +277,11 @@ class ClassHelper extends HTMLElement {
a.addEventListener("click", () => {
this.dispatchEvent(new CustomEvent("nextPage", {
detail: {
url: nextUrl
value: nextUrl
}
}));
});
a.textContent = TRANSLATIONS.next + ">>";
a.textContent = ClassHelper.translations["Next"];
next.appendChild(a);
}

Expand All @@ -259,7 +291,7 @@ class ClassHelper extends HTMLElement {
return fragment;
}

getAccumulatorFragment() {
getAccumulatorFragment(preSelectedValues) {
const fragment = document.createDocumentFragment();
const div = document.createElement("div");
div.setAttribute("id", "popup-control");
Expand All @@ -268,15 +300,22 @@ class ClassHelper extends HTMLElement {
preview.setAttribute("id", "popup-preview");
preview.type = "text";
preview.name = "preview";
if (preSelectedValues.length > 0) {
preview.value = preSelectedValues.join(',');
}

const cancel = document.createElement("button");
cancel.textContent = TRANSLATIONS.cancel;
cancel.textContent = ClassHelper.translations["Cancel"];
cancel.addEventListener("click", () => {
preview.value = "";
this.dispatchEvent(new CustomEvent("valueSelected", {
detail: {
value: preview.value
}
}));
})

const apply = document.createElement("button");
apply.textContent = TRANSLATIONS.apply;
apply.textContent = ClassHelper.translations["Apply"];
apply.style.fontWeight = "bold";
apply.addEventListener("click", () => {
this.dispatchEvent(new CustomEvent("valueSelected", {
Expand Down Expand Up @@ -325,7 +364,7 @@ class ClassHelper extends HTMLElement {
* @param {Object.<string, any>[]} data
* @returns
*/
getTableFragment(headers, data) {
getTableFragment(headers, data, preSelectedValues) {
const fragment = document.createDocumentFragment();
const table = document.createElement('table');
table.setAttribute("id", "popup-table");
Expand Down Expand Up @@ -354,6 +393,9 @@ class ClassHelper extends HTMLElement {
checkbox.setAttribute("type", "checkbox");
row.appendChild(checkbox);
row.style.cursor = "pointer";
if (preSelectedValues.includes(entry[headers[0]])) {
checkbox.checked = true;
}

headers.forEach(header => {
const td = document.createElement('td');
Expand Down Expand Up @@ -448,6 +490,12 @@ class ClassHelper extends HTMLElement {

this.popupRef = window.open("about:blank", "_blank", popupFeatures);

const input = document.getElementsByName(props.formProperty)[0];
let preSelectedValues = [];
if (input.value) {
preSelectedValues = input.value.split(',');
}

const json = fetch(apiURL).then(resp => {
if (!resp.ok) {
throw new Error("error fetching data from roundup rest api");
Expand All @@ -474,13 +522,15 @@ class ClassHelper extends HTMLElement {
b.appendChild(this.getSearchFragment());
}
b.appendChild(this.getPaginationFragment(prevURL, nextURL, props.pageIndex, props.pageSize));
b.appendChild(this.getTableFragment(props.fields, data.collection));
b.appendChild(this.getAccumulatorFragment());
b.appendChild(this.getTableFragment(props.fields, data.collection, preSelectedValues));
b.appendChild(this.getAccumulatorFragment(preSelectedValues));
})

}

pageChange(apiURL, props) {
let preSelectedValues = this.popupRef.document.getElementById("popup-preview").value.split(",");

fetch(apiURL).then(resp => resp.json()).then(({ data }) => {
const b = this.popupRef.document.body;
let prevURL = data["@links"].prev ?? null;
Expand All @@ -497,7 +547,7 @@ class ClassHelper extends HTMLElement {
let oldPagination = this.popupRef.document.getElementById("popup-pagination");
b.replaceChild(this.getPaginationFragment(prevURL, nextURL, props.pageIndex, props.pageSize), oldPagination);
let oldTable = this.popupRef.document.getElementById("popup-table");
b.replaceChild(this.getTableFragment(props.fields, data.collection), oldTable);
b.replaceChild(this.getTableFragment(props.fields, data.collection, preSelectedValues), oldTable);
});
}

Expand Down Expand Up @@ -533,4 +583,15 @@ class ClassHelper extends HTMLElement {
}
}

customElements.define("roundup-classhelper", ClassHelper);
function enableClassHelper() {
if (document.URL.endsWith("#classhelper-wc-toggle")) {
return;
}

/**@todo - make api call? get 404 then early return? */
// http://localhost/demo/rest

customElements.define("roundup-classhelper", ClassHelper);
}

enableClassHelper();
2 changes: 1 addition & 1 deletion html/issue.item.html
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
<roundup-classhelper>
<span tal:condition="context/is_edit_ok" tal:replace="structure python:db.issue.classhelp('id,title', property='superseder', pagesize=10)" />
</roundup-classhelper>
<span tal:condition="context/is_edit_ok" tal:replace="structure python:db.issue.classhelp('id,title', property='superseder')" />
<span tal:condition="context/is_edit_ok" tal:replace="structure python:db.issue.classhelp('id,title', property='superseder', pagesize=10)" />
<span tal:condition="context/superseder">
<br><span i18n:translate="">View:</span>
<a tal:repeat="sup context/superseder"
Expand Down
28 changes: 26 additions & 2 deletions locale/de.po
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: Roundup 2.3.0\n"
"Report-Msgid-Bugs-To: [email protected]\n"
"POT-Creation-Date: 2023-07-12 22:51-0400\n"
"PO-Revision-Date: 2016-04-11 09:13+0200\n"
"Last-Translator: Tobias Herp <[email protected]>\n"
"Language-Team: German Translators <[email protected]>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Poedit-Bookmarks: 75,-1,-1,-1,-1,-1,-1,-1,-1,-1\n"

msgid "Submit"
msgstr "gehen"

Expand All @@ -7,5 +22,14 @@ msgstr ">"
msgid "Prev"
msgstr "<"

msgid "Hello World - \"New Programmer\""
msgstr "Hallo Welt - \"neuer Programmierer\""
msgid "Apply"
msgstr "anwenden"

msgid "Cancel"
msgstr "stornieren"

msgid "Search"
msgstr "suchen"

msgid "Reset"
msgstr "zurücksetzen"