Migrate frontend to pnpm+parcel with JS modules
This commit is contained in:
parent
4d8b7d6e62
commit
0b8fbea6c3
30 changed files with 2289 additions and 404 deletions
22
frontend/src/account-manage.js
Normal file
22
frontend/src/account-manage.js
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import $ from "jquery";
|
||||
|
||||
$(() => {
|
||||
var path = window.location.pathname;
|
||||
if (path === "/account/manage") {
|
||||
initModule();
|
||||
}
|
||||
});
|
||||
|
||||
function initModule() {
|
||||
$("#password").on("input", function () {
|
||||
var enable = false;
|
||||
if ($(this).val().length > 0) {
|
||||
enable = true;
|
||||
}
|
||||
|
||||
$("#password-verify").prop("disabled", !enable);
|
||||
$("#password-verify").prop("required", enable);
|
||||
});
|
||||
|
||||
$("#password").trigger("input");
|
||||
}
|
||||
52
frontend/src/color-mode.js
Normal file
52
frontend/src/color-mode.js
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
import $ from "jquery";
|
||||
|
||||
// Function to toggle light/dark mode
|
||||
function setColorMode(color) {
|
||||
if (color == "dark") {
|
||||
$(".toggle-dark-mode").children("i").removeClass("bi-moon");
|
||||
$(".toggle-dark-mode").children("i").addClass("bi-sun");
|
||||
} else {
|
||||
$(".toggle-dark-mode").children("i").removeClass("bi-sun");
|
||||
$(".toggle-dark-mode").children("i").addClass("bi-moon");
|
||||
}
|
||||
|
||||
$("html").attr("data-bs-theme", color);
|
||||
localStorage.setItem("color-mode", color);
|
||||
$.post("/set-color-mode", { color_mode: color });
|
||||
}
|
||||
|
||||
// Listen for click on light/dark mode button
|
||||
$(() => {
|
||||
$(".toggle-dark-mode").on("click", () => {
|
||||
var currentState = $("html").attr("data-bs-theme");
|
||||
|
||||
var newState = "dark";
|
||||
if (currentState === "dark") {
|
||||
newState = "light";
|
||||
}
|
||||
|
||||
setColorMode(newState);
|
||||
});
|
||||
});
|
||||
|
||||
// On page load: automatic light/dark toggle
|
||||
$(() => {
|
||||
var currentState = $("html").attr("data-bs-theme");
|
||||
var storedState = localStorage.getItem("color-mode");
|
||||
|
||||
if (storedState && storedState !== currentState) {
|
||||
return setColorMode(storedState);
|
||||
}
|
||||
|
||||
if (currentState === "auto") {
|
||||
var newState = "light";
|
||||
if (
|
||||
window.matchMedia &&
|
||||
window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||
) {
|
||||
newState = "dark";
|
||||
}
|
||||
|
||||
return setColorMode(newState);
|
||||
}
|
||||
});
|
||||
26
frontend/src/fields.js
Normal file
26
frontend/src/fields.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import $ from "jquery";
|
||||
|
||||
$(() => {
|
||||
var path = window.location.pathname;
|
||||
if (path.startsWith("/admin/fields/")) {
|
||||
initModule();
|
||||
}
|
||||
});
|
||||
|
||||
function initModule() {
|
||||
$("#field_type").on("change", function () {
|
||||
var enable = false;
|
||||
if ($(this).val() === "list") {
|
||||
enable = true;
|
||||
|
||||
$("#list").children(".list-disabled").remove();
|
||||
} else {
|
||||
$("#list").append(`<option class="list-disabled" selected></option>`);
|
||||
}
|
||||
|
||||
$("#list").prop("disabled", !enable);
|
||||
$("#list").prop("required", enable);
|
||||
});
|
||||
|
||||
$("#field_type").trigger("change");
|
||||
}
|
||||
233
frontend/src/search.js
Normal file
233
frontend/src/search.js
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
import $ from "jquery";
|
||||
|
||||
$(() => {
|
||||
var path = window.location.pathname;
|
||||
if (path === "/members" || path === "/contacts") {
|
||||
initSearch();
|
||||
}
|
||||
});
|
||||
|
||||
function initSearch() {
|
||||
$("#search").on("click", () => {
|
||||
search();
|
||||
});
|
||||
|
||||
$("#advanced").on("click", function () {
|
||||
if ($(this).data("state") === "true") {
|
||||
$(this).find("i").removeClass("bi-arrow-up");
|
||||
$(this).find("i").addClass("bi-arrow-down");
|
||||
$("#advanced-section").addClass("d-none");
|
||||
$(this).data("state", "false");
|
||||
} else {
|
||||
$(this).find("i").removeClass("bi-arrow-down");
|
||||
$(this).find("i").addClass("bi-arrow-up");
|
||||
$("#advanced-section").removeClass("d-none");
|
||||
$(this).data("state", "true");
|
||||
}
|
||||
});
|
||||
|
||||
$("#reset-search").on("click", function () {
|
||||
$("#search-json").val("");
|
||||
$("#search-page").val("1");
|
||||
$("#search-form").trigger("submit");
|
||||
});
|
||||
|
||||
$("#search-container").on("change", ".field-select", function () {
|
||||
var lastField = $(this).attr("data-last-field");
|
||||
var isInitial = $(this).attr("data-is-initial");
|
||||
var initialValue = $(this).attr("data-initial-value");
|
||||
|
||||
var field = $(this).val();
|
||||
if (field == "") {
|
||||
$(this).parents(".row").remove();
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
(lastField === undefined || lastField.length === 0) &&
|
||||
(isInitial === undefined || isInitial !== "yes")
|
||||
) {
|
||||
createFieldSelection();
|
||||
}
|
||||
|
||||
$(this).attr("data-last-field", field);
|
||||
|
||||
$(this).parents(".row").find(".end-col").find("input").remove();
|
||||
$(this).parents(".row").find(".end-col").find("select").remove();
|
||||
|
||||
$(elem)
|
||||
.parents(".row")
|
||||
.find(".end-col")
|
||||
.append(
|
||||
$("<input>", {
|
||||
class: "form-control",
|
||||
type: "text",
|
||||
disabled: true,
|
||||
}),
|
||||
);
|
||||
|
||||
var elem = $(this);
|
||||
$.getJSON("/fields/" + field, function (data) {
|
||||
$(this).parents(".row").find(".end-col").find("input").remove();
|
||||
|
||||
if (data.FieldType === "list") {
|
||||
var select = $("<select>", {
|
||||
class: "form-select",
|
||||
"data-optional-field": field,
|
||||
"data-search-type": "int",
|
||||
});
|
||||
$(elem).parents(".row").find(".end-col").append(select);
|
||||
|
||||
for (const [_, value] of Object.entries(data.List.ListItems)) {
|
||||
$(select).append(
|
||||
$("<option>", {
|
||||
value: value.ID,
|
||||
text: value.Value,
|
||||
}),
|
||||
);
|
||||
}
|
||||
} else if (data.FieldType === "number") {
|
||||
$(elem)
|
||||
.parents(".row")
|
||||
.find(".end-col")
|
||||
.append(
|
||||
$("<input>", {
|
||||
class: "form-control",
|
||||
type: "number",
|
||||
"data-optional-field": field,
|
||||
"data-search-type": "int",
|
||||
}),
|
||||
);
|
||||
} else if (data.FieldType === "date") {
|
||||
$(elem)
|
||||
.parents(".row")
|
||||
.find(".end-col")
|
||||
.append(
|
||||
$("<input>", {
|
||||
class: "form-control",
|
||||
type: "date",
|
||||
"data-optional-field": field,
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
$(elem)
|
||||
.parents(".row")
|
||||
.find(".end-col")
|
||||
.append(
|
||||
$("<input>", {
|
||||
class: "form-control",
|
||||
type: "text",
|
||||
"data-optional-field": field,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (initialValue !== undefined && initialValue.length > 0) {
|
||||
$(elem).parents(".row").find("[data-optional-field]").val(initialValue);
|
||||
$(elem).attr("data-initial-value", null);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("#search-container").on("keyup", "input[type=text]", function (e) {
|
||||
if (e.key === "Enter") {
|
||||
search();
|
||||
}
|
||||
});
|
||||
|
||||
var json = $("#search-json").val();
|
||||
if (json.length > 0) {
|
||||
var searchData = JSON.parse(json);
|
||||
|
||||
for (const [key, value] of Object.entries(searchData)) {
|
||||
if (key === "advanced") {
|
||||
if (value) $("#advanced").trigger("click");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (key === "fields") {
|
||||
for (const [field_id, field_values] of Object.entries(value)) {
|
||||
for (const field_value of field_values) {
|
||||
createFieldSelection(field_id, field_value);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (typeof value === "boolean") {
|
||||
$("[data-search-field=" + key + "]").prop("checked", value);
|
||||
} else {
|
||||
$("[data-search-field=" + key + "]").val(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createFieldSelection();
|
||||
}
|
||||
|
||||
function createFieldSelection(field, value) {
|
||||
var elem = $("#search-fields-model").clone().appendTo("#search-fields");
|
||||
$(elem).attr("id", null);
|
||||
$(elem).removeClass("d-none");
|
||||
$(elem).addClass("search-fields-count");
|
||||
|
||||
if (field !== undefined && field.length > 0) {
|
||||
$(elem).find(".field-select").attr("data-initial-value", value);
|
||||
$(elem).find(".field-select").attr("data-is-initial", "yes");
|
||||
$(elem).find(".field-select").val(field);
|
||||
$(elem).find(".field-select").trigger("change");
|
||||
}
|
||||
}
|
||||
|
||||
function search() {
|
||||
var advancedSearch = $("#advanced").data("state") === "true";
|
||||
var searchData = {
|
||||
advanced: advancedSearch,
|
||||
};
|
||||
|
||||
$("[data-search-field]").each(function () {
|
||||
var advancedField = $(this).data("search-advanced");
|
||||
if (!advancedSearch && advancedField) {
|
||||
return;
|
||||
}
|
||||
|
||||
var index = $(this).data("search-field");
|
||||
var value = $(this).val();
|
||||
|
||||
if ($(this).data("search-type") === "int") {
|
||||
value = parseInt(value);
|
||||
if (isNaN(value)) return;
|
||||
} else if ($(this).attr("type") === "checkbox") {
|
||||
value = $(this).prop("checked");
|
||||
}
|
||||
|
||||
searchData[index] = value;
|
||||
});
|
||||
|
||||
var fields = {};
|
||||
$("[data-optional-field]:not(:disabled)").each(function () {
|
||||
if (!advancedSearch) {
|
||||
return;
|
||||
}
|
||||
|
||||
var index = $(this).attr("data-optional-field");
|
||||
var value = $(this).val();
|
||||
|
||||
if ($(this).data("search-type") === "int") {
|
||||
value = parseInt(value);
|
||||
if (isNaN(value)) return;
|
||||
}
|
||||
|
||||
if (fields[index] !== undefined) {
|
||||
fields[index].push(value);
|
||||
} else {
|
||||
fields[index] = [value];
|
||||
}
|
||||
});
|
||||
searchData["fields"] = fields;
|
||||
|
||||
var json = JSON.stringify(searchData);
|
||||
$("#search-json").val(json);
|
||||
$("#search-page").val("1");
|
||||
$("#search-form").trigger("submit");
|
||||
}
|
||||
11
frontend/src/tooltip.js
Normal file
11
frontend/src/tooltip.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import $ from "jquery";
|
||||
import { Tooltip } from "bootstrap";
|
||||
|
||||
$(() => {
|
||||
const tooltipTriggerList = document.querySelectorAll(
|
||||
'[data-bs-toggle="tooltip"]',
|
||||
);
|
||||
const tooltipList = [...tooltipTriggerList].map(
|
||||
(tooltipTriggerEl) => new Tooltip(tooltipTriggerEl),
|
||||
);
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue