Skip to content

Commit

Permalink
Merge pull request #549 from PAWECOGmbH/development
Browse files Browse the repository at this point in the history
Dev to Staging
  • Loading branch information
ptruessel authored Nov 15, 2024
2 parents 956ef08 + 127b213 commit 2cad34d
Show file tree
Hide file tree
Showing 27 changed files with 962 additions and 5 deletions.
5 changes: 0 additions & 5 deletions .gitattributes

This file was deleted.

3 changes: 3 additions & 0 deletions config/example.config.cfm
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
// Datasource
variables.datasource = "saaster";
// Theme (default_theme or custom_theme)
variables.activeTheme = "default_theme";
// Environment
variables.environment = "prod" // "dev" or "prod"
Expand Down
10 changes: 10 additions & 0 deletions www/frontend/custom_theme/css/css-include.cfm
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

<cfoutput>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css">
<cfif fileExists("/frontend/#application.activeTheme#/css/styles-min.css")>
<link rel="stylesheet" type="text/css" href="/frontend/#application.activeTheme#/css/styles-min.css?v=123456789" />
<cfelse>
<link rel="stylesheet" type="text/css" href="/frontend/#application.activeTheme#/css/styles.css" />
</cfif>
</cfoutput>
18 changes: 18 additions & 0 deletions www/frontend/custom_theme/css/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.planDescription ul {
list-style: none;
padding: 0;
margin: 0;
}

.planDescription ul li {
position: relative;
padding-left: 25px;
}

.planDescription ul li::before {
content: "\2713";
font-family: "Bootstrap Icons";
position: absolute;
left: 0;
color: green;
}
Binary file added www/frontend/custom_theme/images/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions www/frontend/custom_theme/js/js-include.cfm
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

<cfoutput>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
<cfif fileExists("/frontend/#application.activeTheme#/js/scripts-min.js")>
<script src="/frontend/#application.activeTheme#/js/scripts-min.js?v=1.0.0"></script>
<cfelse>
<script src="/frontend/#application.activeTheme#/js/scripts.js"></script>
</cfif>
</cfoutput>
220 changes: 220 additions & 0 deletions www/frontend/custom_theme/js/scripts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@

/**
* Toggles the visibility of price boxes and switches the active class on the selected plan.
*
* This function listens to changes in the "monthly" and "yearly" radio buttons and updates
* both the displayed pricing boxes and the focus (visual highlight) of the active label.
*/
document.addEventListener('DOMContentLoaded', function() {

// Radio buttons
const monthlyRadio = document.getElementById('monthly');
const yearlyRadio = document.getElementById('yearly');

// Check if the elements are present on the page
if (!monthlyRadio || !yearlyRadio) {
return; // Exit if either element is missing
}

// Labels for styling
const monthlyLabel = document.querySelector('label[for="monthly"]');
const yearlyLabel = document.querySelector('label[for="yearly"]');

// Price box elements
const monthlyBoxes = document.querySelectorAll('.price_box.monthly');
const yearlyBoxes = document.querySelectorAll('.price_box.yearly');

// Select all booking buttons
const bookingButtons = document.querySelectorAll('.bookingButton');

// Function to toggle visibility and button focus, and update each booking button's link
function togglePriceBoxes() {

if (monthlyRadio.checked) {

// Show monthly boxes, hide yearly boxes
monthlyBoxes.forEach(box => box.style.display = 'block');
yearlyBoxes.forEach(box => box.style.display = 'none');

// Add active class to monthly, remove from yearly
monthlyLabel.classList.add('active');
yearlyLabel.classList.remove('active');

// Update href for all booking buttons to the monthly link
bookingButtons.forEach(button => {
const monthlyLink = button.getAttribute('data-monthly');
button.setAttribute('href', monthlyLink);
});

} else if (yearlyRadio.checked) {

// Show yearly boxes, hide monthly boxes
monthlyBoxes.forEach(box => box.style.display = 'none');
yearlyBoxes.forEach(box => box.style.display = 'block');

// Add active class to yearly, remove from monthly
yearlyLabel.classList.add('active');
monthlyLabel.classList.remove('active');

// Update href for all booking buttons to the yearly link
bookingButtons.forEach(button => {
const yearlyLink = button.getAttribute('data-yearly');
button.setAttribute('href', yearlyLink);
});

}

}

// Add event listeners to both radio buttons
monthlyRadio.addEventListener('change', togglePriceBoxes);
yearlyRadio.addEventListener('change', togglePriceBoxes);

// Initial toggle based on the default selection
togglePriceBoxes();

});



/**
* This script manages the 6-digit MFA code input, handling numeric validation,
* focus shifting, and form submission upon completion.
*/
document.addEventListener('DOMContentLoaded', function () {
const form = document.getElementById('mfa_form');

// Check if the form exists on the page
if (!form) {
return; // Exit if the form is not present
}

const inputs = form.querySelectorAll('.code-input');

// Set focus on the first input with the class `.code-input`
const firstInput = document.querySelector('.code-input');
if (firstInput) {
firstInput.focus();
}

/**
* Restricts input to numeric characters only.
*
* @param {Event} event - The keypress event triggered when the user types a character.
*/
function onlyDigits(event) {
const charCode = event.which || event.keyCode;
if (charCode < 48 || charCode > 57) {
event.preventDefault();
}
}

/**
* Checks if all input fields are filled and submits the form if they are.
*/
function checkAndSubmit() {
const code = Array.from(inputs).map(input => input.value).join('');
if (code.length === 6) {
form.submit();
}
}

/**
* Event handling for each input field: numeric-only restriction, focus shifts,
* and backspace handling.
*/
inputs.forEach((input, index) => {
input.addEventListener('keypress', onlyDigits);

input.addEventListener('input', function (event) {
const value = event.target.value;

if (value.length === 1 && index < inputs.length - 1) {
inputs[index + 1].focus(); // Move focus to the next field
} else if (value.length > 1) {
// Handle paste or multiple characters
const values = value.split('');
values.forEach((val, i) => {
if (index + i < inputs.length) {
inputs[index + i].value = val;
}
});
if (index + values.length < inputs.length) {
inputs[index + values.length].focus();
}
}

checkAndSubmit(); // Submit if all fields are filled
});

input.addEventListener('keydown', function (event) {
if (event.key === 'Backspace' && input.value === '' && index > 0) {
inputs[index - 1].focus();
}
});
});

/**
* Handles paste of a full 6-digit code into the first field.
*/
inputs[0].addEventListener('paste', function (event) {
const paste = event.clipboardData.getData('text');
if (/^\d{6}$/.test(paste)) {
paste.split('').forEach((char, i) => {
if (i < inputs.length) {
inputs[i].value = char;
}
});
checkAndSubmit();
}
event.preventDefault(); // Prevent default paste action
});



});



/**
* Prevents the user from navigating back using the browser's back button
* after logging out. This script runs only when `isLogout` is true.
*
* @param {Window} global - The global window object.
*/
(function (global) {
if (typeof (global) === "undefined") {
throw new Error("window is undefined");
}

// Check if the user has logged out
if (typeof isLogout !== "undefined" && isLogout) {

/**
* Disables the browser's back navigation by manipulating the history state.
*/
var noBackPlease = function () {
global.history.pushState(null, null, global.location.href);
global.addEventListener('popstate', function () {
global.history.pushState(null, null, global.location.href);
});
};

/**
* Runs when the page is fully loaded.
* Calls the function to disable the back button and prevents backspace key navigation.
*/
global.onload = function () {
noBackPlease();

// Prevent the backspace key from navigating back when not in an input or textarea
document.body.onkeydown = function (e) {
var elm = e.target.nodeName.toLowerCase();
if (e.which === 8 && (elm !== 'input' && elm !== 'textarea')) {
e.preventDefault();
}
e.stopPropagation();
};
};
}
})(window);
4 changes: 4 additions & 0 deletions www/frontend/custom_theme/templates/footer.cfm
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

<cfinclude template="../js/js-include.cfm">
</body>
</html>
43 changes: 43 additions & 0 deletions www/frontend/custom_theme/templates/forms/login.cfm
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<cfoutput>

<div class="container py-4 px-3 mx-auto w-25">

<div class="card wd-50">

<div class="card-header">
#getTrans('formSignIn')#
</div>

<form id="submit_form" method="post" action="#application.mainURL#/logincheck">
<input type="hidden" name="login_btn">
<div class="card-body">
<cfif structKeyExists(session, "alert")>
#session.alert#
</cfif>
<div class="mb-3">
<label class="form-label">#getTrans('formEmailAddress')#</label>
<input type="email" name="email" class="form-control" value="#session.email#" required <cfif not len(trim(session.email))>autofocus</cfif>>
</div>
<div class="mb-3">
<label class="form-label">#getTrans('formPassword')#</label>
<div class="input-group input-group-flat">
<input type="password" name="password" class="form-control" required <cfif len(trim(session.email))>autofocus</cfif>>
</div>
</div>
<div class="form-footer">
<button type="submit" id="sumbit_button" class="btn btn-primary w-100">#getTrans('formSignIn')#</button>
</div>
</div>
<div class="text-center mt-2">
#getTrans('formRegisterText')# <a href="#application.mainURL#/register">#getTrans('formSignUp')#</a>
</div>
<div class="text-center mt-1 mb-4">
#getTrans('formForgotPassword')# <a href="#application.mainURL#/password">#getTrans('formReset')#</a>
</div>
</form>

</div>

</div>

</cfoutput>
43 changes: 43 additions & 0 deletions www/frontend/custom_theme/templates/forms/mfa.cfm
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<cfoutput>

<div class="container-sm py-4 px-3 mx-auto w-25">

<div class="card">

<div class="card-header">
#getTrans('titMfa')#
</div>

<form id="mfa_form" method="post" action="#application.mainURL#/logincheck?uuid=#uuid#">
<input type="hidden" name="mfa_btn">
<div class="card-body">
<cfif structKeyExists(session, "alert")>
#session.alert#
</cfif>
<cfif structKeyExists(session, "mfaCheckCount") and session.mfaCheckCount lt 3>
<div class="d-flex justify-content-center align-items-center">
<div class="p-3 bg-light rounded">
<p class="text-center mb-3">#getTrans('txtmfaLead')#</p>
<div class="d-flex otp-field justify-content-center">
<input type="text" name="mfa_1" maxlength="1" class="form-control text-center mx-1 code-input" style="width: 45px; height: 50px;">
<input type="text" name="mfa_2" maxlength="1" class="form-control text-center mx-1 code-input" style="width: 45px; height: 50px;">
<input type="text" name="mfa_3" maxlength="1" class="form-control text-center mx-1 code-input" style="width: 45px; height: 50px;">
<input type="text" name="mfa_4" maxlength="1" class="form-control text-center mx-1 code-input" style="width: 45px; height: 50px;">
<input type="text" name="mfa_5" maxlength="1" class="form-control text-center mx-1 code-input" style="width: 45px; height: 50px;">
<input type="text" name="mfa_6" maxlength="1" class="form-control text-center mx-1 code-input" style="width: 45px; height: 50px;">
</div>
</div>
</div>
</cfif>
</div>
</form>

<div class="form-footer text-center mb-3">
<a role="button" href="#application.mainURL#/logincheck?resend=1&uuid=#uuid#">#getTrans('txtResendMfa')#</a>
</div>

</div>

</div>

</cfoutput>
Loading

0 comments on commit 2cad34d

Please sign in to comment.