Skip to content

Commit

Permalink
Add common frontend workspace
Browse files Browse the repository at this point in the history
  • Loading branch information
Skrypt committed Jan 11, 2025
1 parent 42f5c7a commit bdb9cfa
Show file tree
Hide file tree
Showing 11 changed files with 264 additions and 225 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
},
"workspaces": [
".scripts/assets-build-tool",
"src/lib/",
"src/Frontend/",
"src/OrchardCore.Modules/*",
"src/OrchardCore.Modules/*/Assets/",
"src/OrchardCore.Themes/*",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
export default function strength(element, options) {
/**
* This function initializes a password strength checker on a given input element.
* It evaluates the password based on specified requirements such as minimum length,
* presence of uppercase, lowercase, digits, and special characters.
* A visual progress bar is displayed to indicate the strength level of the password.
*
* @param {HTMLElement} element - The input element to which the strength checker is applied.
* @param {Object} options - Configuration options for password requirements and display settings.
* @param {number} options.requiredLength - Minimum required length of the password.
* @param {boolean} options.requireUppercase - Whether an uppercase letter is required.
* @param {boolean} options.requireLowercase - Whether a lowercase letter is required.
* @param {boolean} options.requireDigit - Whether a digit is required.
* @param {boolean} options.requireNonAlphanumeric - Whether a special character is required.
* @param {string} options.target - CSS selector for the element where the strength progress bar is displayed.
* @param {string} options.style - CSS style string for the progress bar.
*/
export default function strength(element: HTMLInputElement, options: any) {

const settings = Object.assign({
requiredLength: 8,
Expand All @@ -22,11 +38,11 @@ export default function strength(element, options) {

let valid = false;

function getPercentage(a, b) {
function getPercentage(a: number, b: number) {
return (b / a) * 100;
}

function getLevel(value) {
function getLevel(value: number) {

if (value >= 100) {
return "bg-success";
Expand All @@ -43,7 +59,7 @@ export default function strength(element, options) {
return "bg-danger";
}

function checkStrength(value) {
function checkStrength(value: string) {

const minLength = value.length >= settings.requiredLength ? 1 : 0;
capitalletters = !settings.requireUppercase || value.match(upperCase) ? 1 : 0;
Expand All @@ -59,7 +75,7 @@ export default function strength(element, options) {
createProgressBar(percentage, getLevel(percentage));
}

function createProgressBar(percentage, level) {
function createProgressBar(percentage: string | number, level: string) {
const el = document.createElement("div");
el.className = "progress";
el.setAttribute("value", percentage.toString());
Expand All @@ -75,15 +91,15 @@ export default function strength(element, options) {
target.appendChild(el);
}

element.addEventListener("keyup", (event) => checkStrength(element.value));
element.addEventListener("keydown", (event) => checkStrength(element.value));
element.addEventListener("change", (event) => checkStrength(element.value));
element.addEventListener("keyup", () => checkStrength(element.value));
element.addEventListener("keydown", () => checkStrength(element.value));
element.addEventListener("change", () => checkStrength(element.value));
element.addEventListener("drop", (event) => {
event.preventDefault();
checkStrength(event.dataTransfer.getData("text"));
checkStrength(event.dataTransfer?.getData("text") ?? "");
});

element.form.addEventListener("submit", (event) => {
element.form?.addEventListener("submit", (event) => {
checkStrength(element.value);
if (!valid) {
event.preventDefault();
Expand Down
5 changes: 5 additions & 0 deletions src/Frontend/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "@orchardcore/frontend",
"version": "1.0.0",
"type": "module"
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Large diffs are not rendered by default.

223 changes: 114 additions & 109 deletions src/OrchardCore.Modules/OrchardCore.Setup/Assets/ts/setup.ts
Original file line number Diff line number Diff line change
@@ -1,103 +1,7 @@
import strenght from "./strength";

document.addEventListener("DOMContentLoaded", function () {
toggleConnectionStringAndPrefix();

// Show hide the connection string when a provider is selected
document
.getElementById("DatabaseProvider")
?.addEventListener("change", function () {
toggleConnectionStringAndPrefix();
});

// Refresh the recipe description
document.querySelectorAll("#recipes div a").forEach(function (element) {
element.addEventListener("click", function () {
refreshDescription(this);
});
});

const passwordElement = document.getElementById("Password");
const options = JSON.parse(passwordElement?.dataset.strength ?? "") ?? {
requiredLength: 6,
requiredUniqueChars: 1,
requireNonAlphanumeric: true,
requireLowercase: true,
requireUppercase: true,
requireDigit: true,
};

strenght(passwordElement, options);

if (passwordElement) {
passwordElement.addEventListener("focus", function () {
const popover = document.createElement("div");
popover.className = "popover bs-popover-top";
popover.role = "tooltip";
popover.innerHTML = `<div class="popover-header">Password requirements: </div><div class="popover-body"><ul><li>Minimum length: ${
options.requiredLength
}</li><li>Unique Chars: ${
options.requiredUniqueChars
}</li><li>Uppercase: ${
options.requireUppercase ? "required" : "not required"
}</li><li>Lowercase: ${
options.requireLowercase ? "required" : "not required"
}</li><li>Digit: ${
options.requireDigit ? "required" : "not required"
}</li><li>Non alphanumeric: ${
options.requireNonAlphanumeric ? "required" : "not required"
}</li></ul></div>`;

const rect = passwordElement.getBoundingClientRect();
popover.style.position = "absolute";
popover.style.top = `${rect.top + 53}px`;
popover.style.left = `${rect.left}px`;
document.body.appendChild(popover);

function removePopover() {
popover.remove();
passwordElement?.removeEventListener("blur", removePopover);
}

passwordElement.addEventListener("blur", removePopover);
});
}

const toggleConnectionString = document.querySelector(
"#toggleConnectionString"
);
if (toggleConnectionString) {
toggleConnectionString.addEventListener("click", function (e) {
togglePasswordVisibility(
document.querySelector("#ConnectionString"),
document.querySelector("#toggleConnectionString")
);
});
}

const togglePassword = document.querySelector("#togglePassword");
togglePassword?.addEventListener("click", function (e) {
togglePasswordVisibility(
document.querySelector("#Password"),
document.querySelector("#togglePassword")
);
});

const togglePasswordConfirmation = document.querySelector(
"#togglePasswordConfirmation"
);
togglePasswordConfirmation?.addEventListener("click", function (e) {
togglePasswordVisibility(
document.querySelector("#PasswordConfirmation"),
document.querySelector("#togglePasswordConfirmation")
);
});

setLocalizationUrl();
});
import strenght from "@orchardcore/frontend/components/strength";

// Show or hide the connection string or table prefix section when the database provider is selected
function toggleConnectionStringAndPrefix() {
const toggleConnectionStringAndPrefix = () => {
const selectedOption = document.querySelector(
"#DatabaseProvider option:checked"
);
Expand Down Expand Up @@ -139,10 +43,9 @@ function toggleConnectionStringAndPrefix() {
"";
}
}
}
};

// Show the recipe description
function refreshDescription(target: Element) {
const refreshDescription = (target: Element) => {
const recipeName = target.getAttribute("data-recipe-name");
const recipeDisplayName = target.getAttribute("data-recipe-display-name");
const recipeDescription = target.getAttribute("data-recipe-description");
Expand All @@ -158,9 +61,9 @@ function refreshDescription(target: Element) {
recipeButton.setAttribute("title", recipeDescription || "");
recipeButton.focus();
}
}
};

function setLocalizationUrl() {
const setLocalizationUrl = () => {
const culturesList = document.getElementById(
"culturesList"
) as HTMLSelectElement;
Expand All @@ -170,14 +73,13 @@ function setLocalizationUrl() {
if (selectedOption) {
window.location.href = selectedOption.dataset.url || "";
}
})

}
});
};

function togglePasswordVisibility(
const togglePasswordVisibility = (
passwordCtl: HTMLInputElement | null,
togglePasswordCtl: HTMLElement | null
) {
) => {
if (!passwordCtl || !togglePasswordCtl) {
return;
}
Expand All @@ -202,4 +104,107 @@ function togglePasswordVisibility(
icon.classList.toggle("fa-eye-slash", type !== "password");
}
}
}
};

const init = () => {
toggleConnectionStringAndPrefix();

// Show hide the connection string when a provider is selected
document
.getElementById("DatabaseProvider")
?.addEventListener("change", function () {
toggleConnectionStringAndPrefix();
});

// Refresh the recipe description
document.querySelectorAll("#recipes div a").forEach(function (element) {
element.addEventListener("click", function () {
refreshDescription(this);
});
});

const passwordElement = <HTMLInputElement>(
document.getElementById("Password")
);

const options = JSON.parse(passwordElement?.dataset.strength ?? "") ?? {
requiredLength: 6,
requiredUniqueChars: 1,
requireNonAlphanumeric: true,
requireLowercase: true,
requireUppercase: true,
requireDigit: true,
};

if (passwordElement) {
strenght(passwordElement, options);
}

if (passwordElement) {
passwordElement.addEventListener("focus", function () {
const popover = document.createElement("div");
popover.className = "popover bs-popover-top";
popover.role = "tooltip";
popover.innerHTML = `<div class="popover-header">Password requirements: </div><div class="popover-body"><ul><li>Minimum length: ${
options.requiredLength
}</li><li>Unique Chars: ${
options.requiredUniqueChars
}</li><li>Uppercase: ${
options.requireUppercase ? "required" : "not required"
}</li><li>Lowercase: ${
options.requireLowercase ? "required" : "not required"
}</li><li>Digit: ${
options.requireDigit ? "required" : "not required"
}</li><li>Non alphanumeric: ${
options.requireNonAlphanumeric ? "required" : "not required"
}</li></ul></div>`;

const rect = passwordElement.getBoundingClientRect();
popover.style.position = "absolute";
popover.style.top = `${rect.top + 53}px`;
popover.style.left = `${rect.left}px`;
document.body.appendChild(popover);

function removePopover() {
popover.remove();
passwordElement?.removeEventListener("blur", removePopover);
}

passwordElement.addEventListener("blur", removePopover);
});
}

const toggleConnectionString = document.querySelector(
"#toggleConnectionString"
);
if (toggleConnectionString) {
toggleConnectionString.addEventListener("click", function (e) {
togglePasswordVisibility(
document.querySelector("#ConnectionString"),
document.querySelector("#toggleConnectionString")
);
});
}

const togglePassword = document.querySelector("#togglePassword");
togglePassword?.addEventListener("click", function (e) {
togglePasswordVisibility(
document.querySelector("#Password"),
document.querySelector("#togglePassword")
);
});

const togglePasswordConfirmation = document.querySelector(
"#togglePasswordConfirmation"
);
togglePasswordConfirmation?.addEventListener("click", function (e) {
togglePasswordVisibility(
document.querySelector("#PasswordConfirmation"),
document.querySelector("#togglePasswordConfirmation")
);
});

setLocalizationUrl();
};

init();
Loading

0 comments on commit bdb9cfa

Please sign in to comment.