fix: code review fixes
This commit is contained in:
@@ -0,0 +1,175 @@
|
|||||||
|
const SessionService = require("../../services/SessionService");
|
||||||
|
const app = require("express").Router();
|
||||||
|
const db = require("../../models");
|
||||||
|
const role = 1;
|
||||||
|
|
||||||
|
// List termination configurations
|
||||||
|
app.get(
|
||||||
|
"/admin/termination-config",
|
||||||
|
SessionService.verifySessionMiddleware(role, "admin"),
|
||||||
|
async function (req, res, next) {
|
||||||
|
try {
|
||||||
|
const configs = await db.termination_config.findAll();
|
||||||
|
res.render("admin/Termination_Config", {
|
||||||
|
configs,
|
||||||
|
get_page_name: () => "Termination Configuration",
|
||||||
|
_base_url: "/admin/termination-config",
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
res
|
||||||
|
.status(500)
|
||||||
|
.json({
|
||||||
|
success: false,
|
||||||
|
message: "Failed to fetch termination configurations",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Get termination configuration by ID
|
||||||
|
app.get(
|
||||||
|
"/admin/termination-config/:id",
|
||||||
|
SessionService.verifySessionMiddleware(role, "admin"),
|
||||||
|
async function (req, res, next) {
|
||||||
|
try {
|
||||||
|
const { id } = req.params;
|
||||||
|
const config = await db.termination_config.getByPK(id);
|
||||||
|
if (!config) {
|
||||||
|
return res
|
||||||
|
.status(404)
|
||||||
|
.json({
|
||||||
|
success: false,
|
||||||
|
message: "Termination configuration not found",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return res.json({ success: true, payload: config });
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
return res
|
||||||
|
.status(500)
|
||||||
|
.json({
|
||||||
|
success: false,
|
||||||
|
message: "Failed to fetch termination configuration",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create new termination configuration
|
||||||
|
app.post(
|
||||||
|
"/admin/termination-config",
|
||||||
|
SessionService.verifySessionMiddleware(role, "admin"),
|
||||||
|
async function (req, res, next) {
|
||||||
|
try {
|
||||||
|
const { message, title, counter } = req.body;
|
||||||
|
const config = await db.termination_config.create({
|
||||||
|
message,
|
||||||
|
title,
|
||||||
|
counter: parseInt(counter),
|
||||||
|
});
|
||||||
|
return res.json({
|
||||||
|
success: true,
|
||||||
|
payload: config,
|
||||||
|
message: "Termination configuration created successfully",
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
return res
|
||||||
|
.status(500)
|
||||||
|
.json({
|
||||||
|
success: false,
|
||||||
|
message: "Failed to create termination configuration",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update termination configuration
|
||||||
|
app.put(
|
||||||
|
"/admin/termination-config/:id",
|
||||||
|
SessionService.verifySessionMiddleware(role, "admin"),
|
||||||
|
async function (req, res, next) {
|
||||||
|
try {
|
||||||
|
const { id } = req.params;
|
||||||
|
const { message, title, counter } = req.body;
|
||||||
|
const config = await db.termination_config.edit(
|
||||||
|
{
|
||||||
|
message,
|
||||||
|
title,
|
||||||
|
counter: parseInt(counter),
|
||||||
|
},
|
||||||
|
id
|
||||||
|
);
|
||||||
|
return res.json({
|
||||||
|
success: true,
|
||||||
|
payload: config,
|
||||||
|
message: "Termination configuration updated successfully",
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
return res
|
||||||
|
.status(500)
|
||||||
|
.json({
|
||||||
|
success: false,
|
||||||
|
message: "Failed to update termination configuration",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Delete termination configuration
|
||||||
|
app.delete(
|
||||||
|
"/admin/termination-config/:id",
|
||||||
|
SessionService.verifySessionMiddleware(role, "admin"),
|
||||||
|
async function (req, res, next) {
|
||||||
|
try {
|
||||||
|
const { id } = req.params;
|
||||||
|
await db.termination_config.destroy(id);
|
||||||
|
return res.json({
|
||||||
|
success: true,
|
||||||
|
message: "Termination configuration deleted successfully",
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
return res
|
||||||
|
.status(500)
|
||||||
|
.json({
|
||||||
|
success: false,
|
||||||
|
message: "Failed to delete termination configuration",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Get default termination configuration (for frontend)
|
||||||
|
app.get("/api/termination-config", async function (req, res, next) {
|
||||||
|
try {
|
||||||
|
// Get the first configuration or create a default one
|
||||||
|
let config = await db.termination_config.findOne();
|
||||||
|
if (!config) {
|
||||||
|
// Create default configuration if none exists
|
||||||
|
config = await db.termination_config.create({
|
||||||
|
message:
|
||||||
|
"You have an allergy to one of the main ingredients in our system. Our current system will not suit you.",
|
||||||
|
title: "Quiz will now be terminated",
|
||||||
|
counter: 10,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return res.json({ success: true, payload: config });
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
// Return default values if database fails
|
||||||
|
return res.json({
|
||||||
|
success: true,
|
||||||
|
payload: {
|
||||||
|
message:
|
||||||
|
"You have an allergy to one of the main ingredients in our system. Our current system will not suit you.",
|
||||||
|
title: "Quiz will now be terminated",
|
||||||
|
counter: 10,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = app;
|
||||||
@@ -7,6 +7,7 @@ const AdminActivesController = require("./admin/Admin_actives_controller");
|
|||||||
const AdminOutputVariablesController = require("./admin/Admin_output_variables_controller");
|
const AdminOutputVariablesController = require("./admin/Admin_output_variables_controller");
|
||||||
const AdminResultProfileController = require("./admin/Admin_result_profile_controller");
|
const AdminResultProfileController = require("./admin/Admin_result_profile_controller");
|
||||||
const AdminGetProfileSystem = require("./admin/getProfileSystem");
|
const AdminGetProfileSystem = require("./admin/getProfileSystem");
|
||||||
|
const AdminTerminationConfigController = require("./admin/Admin_termination_config_controller");
|
||||||
const PublicIndex = require("./public/index");
|
const PublicIndex = require("./public/index");
|
||||||
const AdminAnswerController = require("./admin/Admin_answer_controller");
|
const AdminAnswerController = require("./admin/Admin_answer_controller");
|
||||||
const AdminDashboard = require("./admin/Dashboard");
|
const AdminDashboard = require("./admin/Dashboard");
|
||||||
@@ -20,6 +21,7 @@ module.exports = [
|
|||||||
ShopifyWebhook,
|
ShopifyWebhook,
|
||||||
AdminResultProfileController,
|
AdminResultProfileController,
|
||||||
AdminGetProfileSystem,
|
AdminGetProfileSystem,
|
||||||
|
AdminTerminationConfigController,
|
||||||
AdminUserController,
|
AdminUserController,
|
||||||
AdminQuizController,
|
AdminQuizController,
|
||||||
AdminQuestionController,
|
AdminQuestionController,
|
||||||
|
|||||||
@@ -0,0 +1,125 @@
|
|||||||
|
/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/
|
||||||
|
/**
|
||||||
|
* termination_config Model
|
||||||
|
* @copyright 2021 Manaknightdigital Inc.
|
||||||
|
* @link https://manaknightdigital.com
|
||||||
|
* @license Proprietary Software licensing
|
||||||
|
* @author Ryan Wong
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
const moment = require("moment");
|
||||||
|
const bcrypt = require("bcryptjs");
|
||||||
|
const { Op } = require("sequelize");
|
||||||
|
const { intersection } = require("lodash");
|
||||||
|
const coreModel = require("./../core/models");
|
||||||
|
|
||||||
|
module.exports = (sequelize, DataTypes) => {
|
||||||
|
const TerminationConfig = sequelize.define(
|
||||||
|
"termination_config",
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
primaryKey: true,
|
||||||
|
autoIncrement: true,
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
type: DataTypes.TEXT,
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue:
|
||||||
|
"You have an allergy to one of the main ingredients in our system. Our current system will not suit you.",
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue: "Quiz will now be terminated",
|
||||||
|
},
|
||||||
|
counter: {
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue: 10,
|
||||||
|
},
|
||||||
|
created_at: DataTypes.DATEONLY,
|
||||||
|
updated_at: DataTypes.DATE,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
timestamps: true,
|
||||||
|
freezeTableName: true,
|
||||||
|
tableName: "termination_config",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
underscoredAll: false,
|
||||||
|
underscored: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
coreModel.call(this, TerminationConfig);
|
||||||
|
|
||||||
|
TerminationConfig._preCreateProcessing = function (data) {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
TerminationConfig._postCreateProcessing = function (data) {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
TerminationConfig._customCountingConditions = function (data) {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
TerminationConfig._filterAllowKeys = function (data) {
|
||||||
|
let cleanData = {};
|
||||||
|
let allowedFields = TerminationConfig.allowFields();
|
||||||
|
allowedFields.push(TerminationConfig._primaryKey());
|
||||||
|
|
||||||
|
for (const key in data) {
|
||||||
|
if (allowedFields.includes(key)) {
|
||||||
|
cleanData[key] = data[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cleanData;
|
||||||
|
};
|
||||||
|
|
||||||
|
TerminationConfig.associate = function (models) {};
|
||||||
|
|
||||||
|
TerminationConfig.allowFields = function () {
|
||||||
|
return ["id", "message", "title", "counter"];
|
||||||
|
};
|
||||||
|
|
||||||
|
TerminationConfig.labels = function () {
|
||||||
|
return [
|
||||||
|
"ID",
|
||||||
|
"Termination Message",
|
||||||
|
"Termination Title",
|
||||||
|
"Counter (seconds)",
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
TerminationConfig.validationRules = function () {
|
||||||
|
return [
|
||||||
|
["id", "ID", ""],
|
||||||
|
["message", "Termination Message", "required"],
|
||||||
|
["title", "Termination Title", "required"],
|
||||||
|
["counter", "Counter", "required|integer|min:1|max:60"],
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
TerminationConfig.validationEditRules = function () {
|
||||||
|
return [
|
||||||
|
["id", "ID", ""],
|
||||||
|
["message", "Termination Message", "required"],
|
||||||
|
["title", "Termination Title", "required"],
|
||||||
|
["counter", "Counter", "required|integer|min:1|max:60"],
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
// ex
|
||||||
|
TerminationConfig.intersection = function (fields) {
|
||||||
|
if (fields) {
|
||||||
|
return intersection(
|
||||||
|
["id", "message", "title", "counter", "created_at", "updated_at"],
|
||||||
|
Object.keys(fields)
|
||||||
|
);
|
||||||
|
} else return [];
|
||||||
|
};
|
||||||
|
|
||||||
|
return TerminationConfig;
|
||||||
|
};
|
||||||
@@ -906,10 +906,16 @@ input::-ms-input-placeholder {
|
|||||||
#response-timer {
|
#response-timer {
|
||||||
display: block;
|
display: block;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 2rem;
|
font-size: 3.5rem;
|
||||||
margin-top: 24px;
|
margin: 32px auto;
|
||||||
font-weight: bold;
|
font-weight: 700;
|
||||||
color: #222;
|
color: #231f20;
|
||||||
|
font-family: "Necto Mono", monospace;
|
||||||
|
background: #f3f4ee;
|
||||||
|
padding: 16px 32px;
|
||||||
|
border-top: 1px solid #101010;
|
||||||
|
border-radius: 0;
|
||||||
|
width: 70%;
|
||||||
}
|
}
|
||||||
/*page 5 ends here*/
|
/*page 5 ends here*/
|
||||||
|
|
||||||
|
|||||||
@@ -2171,34 +2171,77 @@ function handleImageMissing(self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implement checkAllergie for Quiz 4
|
// Implement checkAllergie for Quiz 4
|
||||||
function checkAllergie(self) {
|
async function checkAllergie(self) {
|
||||||
const value = self.dataset.val || $(self).data("val");
|
const value = self.dataset.val || $(self).data("val");
|
||||||
if (["Banana", "Olive", "Sunflowers"].includes(value)) {
|
if (["Banana", "Olive", "Sunflowers"].includes(value)) {
|
||||||
// Simulate API fetch for message and counter
|
try {
|
||||||
const terminationMessage =
|
// Fetch termination configuration from API
|
||||||
"You have an allergy to one of the main ingredients in our system. Our current system will not suit you.";
|
const response = await fetch("/api/termination-config");
|
||||||
const terminationTitle = "Quiz will now be terminated";
|
const data = await response.json();
|
||||||
let counter = 10; // seconds (simulate API value)
|
|
||||||
$("#termination-overlay .termination-message").text(terminationMessage);
|
if (data.success) {
|
||||||
$("#termination-overlay .termination-title").text(terminationTitle);
|
const config = data.payload;
|
||||||
$("#termination-overlay .termination-counter").text(counter);
|
const terminationMessage = config.message;
|
||||||
$("#termination-overlay").css("display", "flex");
|
const terminationTitle = config.title;
|
||||||
let interval = setInterval(() => {
|
let counter = parseInt(config.counter);
|
||||||
counter--;
|
|
||||||
$("#termination-overlay .termination-counter").text(counter);
|
$("#termination-overlay .termination-message").text(terminationMessage);
|
||||||
if (counter <= 0) {
|
$("#termination-overlay .termination-title").text(terminationTitle);
|
||||||
clearInterval(interval);
|
$("#termination-overlay .termination-counter").text(counter);
|
||||||
window.location.href = "/";
|
$("#termination-overlay").css("display", "flex");
|
||||||
|
|
||||||
|
let interval = setInterval(() => {
|
||||||
|
counter--;
|
||||||
|
$("#termination-overlay .termination-counter").text(counter);
|
||||||
|
if (counter <= 0) {
|
||||||
|
clearInterval(interval);
|
||||||
|
window.location.href = "/";
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
// Block all interaction
|
||||||
|
$("body > *:not(#termination-overlay)").css("pointer-events", "none");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// Fallback to default values if API fails
|
||||||
|
console.error("Failed to fetch termination config:", data.message);
|
||||||
|
showDefaultTermination();
|
||||||
}
|
}
|
||||||
}, 1000);
|
} catch (error) {
|
||||||
// Block all interaction
|
console.error("Error fetching termination config:", error);
|
||||||
$("body > *:not(#termination-overlay)").css("pointer-events", "none");
|
// Fallback to default values if API fails
|
||||||
|
showDefaultTermination();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// If not terminating, proceed as normal (select/deselect logic)
|
// If not terminating, proceed as normal (select/deselect logic)
|
||||||
// (existing selection logic is handled by the .selectionBtn click handler)
|
// (existing selection logic is handled by the .selectionBtn click handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showDefaultTermination() {
|
||||||
|
const terminationMessage =
|
||||||
|
"You have an allergy to one of the main ingredients in our system. Our current system will not suit you.";
|
||||||
|
const terminationTitle = "Quiz will now be terminated";
|
||||||
|
let counter = 10;
|
||||||
|
|
||||||
|
$("#termination-overlay .termination-message").text(terminationMessage);
|
||||||
|
$("#termination-overlay .termination-title").text(terminationTitle);
|
||||||
|
$("#termination-overlay .termination-counter").text(counter);
|
||||||
|
$("#termination-overlay").css("display", "flex");
|
||||||
|
|
||||||
|
let interval = setInterval(() => {
|
||||||
|
counter--;
|
||||||
|
$("#termination-overlay .termination-counter").text(counter);
|
||||||
|
if (counter <= 0) {
|
||||||
|
clearInterval(interval);
|
||||||
|
window.location.href = "/";
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
// Block all interaction
|
||||||
|
$("body > *:not(#termination-overlay)").css("pointer-events", "none");
|
||||||
|
}
|
||||||
|
|
||||||
$(document).on("click", "#resetQuizButton", async function () {
|
$(document).on("click", "#resetQuizButton", async function () {
|
||||||
if (
|
if (
|
||||||
confirm(
|
confirm(
|
||||||
|
|||||||
@@ -0,0 +1,281 @@
|
|||||||
|
<% if(it.layout_clean_mode) {%> <% layout("../layouts/admin/Clean", {get_page_name:()=> "Termination Configuration"}) %><% } else {%> <% layout("../layouts/admin/Main",{get_page_name:()=> "Termination Configuration"}) %><%}%>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.config-form {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
.config-item {
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.form-group label {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.form-control {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.form-control:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: #007bff;
|
||||||
|
box-shadow: 0 0 0 2px rgba(0,123,255,0.25);
|
||||||
|
}
|
||||||
|
textarea.form-control {
|
||||||
|
min-height: 100px;
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
.btn {
|
||||||
|
padding: 10px 20px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.btn-primary {
|
||||||
|
background: #007bff;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.btn-primary:hover {
|
||||||
|
background: #0056b3;
|
||||||
|
}
|
||||||
|
.btn-success {
|
||||||
|
background: #28a745;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.btn-success:hover {
|
||||||
|
background: #1e7e34;
|
||||||
|
}
|
||||||
|
.btn-danger {
|
||||||
|
background: #dc3545;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.btn-danger:hover {
|
||||||
|
background: #c82333;
|
||||||
|
}
|
||||||
|
.alert {
|
||||||
|
padding: 12px 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.alert-success {
|
||||||
|
background: #d4edda;
|
||||||
|
border: 1px solid #c3e6cb;
|
||||||
|
color: #155724;
|
||||||
|
}
|
||||||
|
.alert-danger {
|
||||||
|
background: #f8d7da;
|
||||||
|
border: 1px solid #f5c6cb;
|
||||||
|
color: #721c24;
|
||||||
|
}
|
||||||
|
.config-list {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
.config-header {
|
||||||
|
background: #f8f9fa;
|
||||||
|
padding: 15px 20px;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="tab-content mx-2 my-2 mx-lg-4 my-lg-4 bg-white p-3" id="nav-tabContent">
|
||||||
|
<div class="config-form">
|
||||||
|
<h2 class="mb-4">Termination Configuration</h2>
|
||||||
|
|
||||||
|
<div id="alert-container"></div>
|
||||||
|
|
||||||
|
<!-- Add New Configuration Form -->
|
||||||
|
<div class="config-item">
|
||||||
|
<h4>Add New Configuration</h4>
|
||||||
|
<form id="add-config-form">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="message">Termination Message:</label>
|
||||||
|
<textarea
|
||||||
|
id="message"
|
||||||
|
name="message"
|
||||||
|
class="form-control"
|
||||||
|
placeholder="Enter the message to display when quiz is terminated"
|
||||||
|
required
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="title">Termination Title:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="title"
|
||||||
|
name="title"
|
||||||
|
class="form-control"
|
||||||
|
placeholder="Enter the title to display"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="counter">Counter (seconds):</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
id="counter"
|
||||||
|
name="counter"
|
||||||
|
class="form-control"
|
||||||
|
placeholder="Enter countdown time in seconds"
|
||||||
|
min="1"
|
||||||
|
max="60"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-success">Add Configuration</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Existing Configurations -->
|
||||||
|
<div class="config-list">
|
||||||
|
<h4>Existing Configurations</h4>
|
||||||
|
<div id="configs-container">
|
||||||
|
<% if(it.configs && it.configs.length > 0) { %>
|
||||||
|
<% it.configs.forEach(function(config) { %>
|
||||||
|
<div class="config-item" data-id="<%= config.id %>">
|
||||||
|
<div class="config-header">
|
||||||
|
Configuration #<%= config.id %>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Message:</label>
|
||||||
|
<textarea class="form-control edit-message" data-field="message"><%= config.message %></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Title:</label>
|
||||||
|
<input type="text" class="form-control edit-title" data-field="title" value="<%= config.title %>" />
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Counter:</label>
|
||||||
|
<input type="number" class="form-control edit-counter" data-field="counter" value="<%= config.counter %>" min="1" max="60" />
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<button class="btn btn-primary update-config" data-id="<%= config.id %>">Update</button>
|
||||||
|
<button class="btn btn-danger delete-config" data-id="<%= config.id %>">Delete</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% }); %>
|
||||||
|
<% } else { %>
|
||||||
|
<div class="config-item">
|
||||||
|
<p>No configurations found. Add one above to get started.</p>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(document).ready(function() {
|
||||||
|
// Add new configuration
|
||||||
|
$('#add-config-form').on('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const formData = {
|
||||||
|
message: $('#message').val(),
|
||||||
|
title: $('#title').val(),
|
||||||
|
counter: $('#counter').val()
|
||||||
|
};
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: '/admin/termination-config',
|
||||||
|
method: 'POST',
|
||||||
|
data: formData,
|
||||||
|
success: function(response) {
|
||||||
|
if (response.success) {
|
||||||
|
showAlert('Configuration added successfully!', 'success');
|
||||||
|
$('#add-config-form')[0].reset();
|
||||||
|
// Reload page to show new config
|
||||||
|
setTimeout(() => location.reload(), 1000);
|
||||||
|
} else {
|
||||||
|
showAlert('Failed to add configuration: ' + response.message, 'danger');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
showAlert('Failed to add configuration. Please try again.', 'danger');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update configuration
|
||||||
|
$(document).on('click', '.update-config', function() {
|
||||||
|
const id = $(this).data('id');
|
||||||
|
const configItem = $(this).closest('.config-item');
|
||||||
|
|
||||||
|
const formData = {
|
||||||
|
message: configItem.find('.edit-message').val(),
|
||||||
|
title: configItem.find('.edit-title').val(),
|
||||||
|
counter: configItem.find('.edit-counter').val()
|
||||||
|
};
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: `/admin/termination-config/${id}`,
|
||||||
|
method: 'PUT',
|
||||||
|
data: formData,
|
||||||
|
success: function(response) {
|
||||||
|
if (response.success) {
|
||||||
|
showAlert('Configuration updated successfully!', 'success');
|
||||||
|
} else {
|
||||||
|
showAlert('Failed to update configuration: ' + response.message, 'danger');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
showAlert('Failed to update configuration. Please try again.', 'danger');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Delete configuration
|
||||||
|
$(document).on('click', '.delete-config', function() {
|
||||||
|
if (!confirm('Are you sure you want to delete this configuration?')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const id = $(this).data('id');
|
||||||
|
const configItem = $(this).closest('.config-item');
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: `/admin/termination-config/${id}`,
|
||||||
|
method: 'DELETE',
|
||||||
|
success: function(response) {
|
||||||
|
if (response.success) {
|
||||||
|
showAlert('Configuration deleted successfully!', 'success');
|
||||||
|
configItem.fadeOut();
|
||||||
|
} else {
|
||||||
|
showAlert('Failed to delete configuration: ' + response.message, 'danger');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
showAlert('Failed to delete configuration. Please try again.', 'danger');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function showAlert(message, type) {
|
||||||
|
const alertHtml = `<div class="alert alert-${type}">${message}</div>`;
|
||||||
|
$('#alert-container').html(alertHtml);
|
||||||
|
|
||||||
|
// Auto-hide after 5 seconds
|
||||||
|
setTimeout(() => {
|
||||||
|
$('#alert-container').empty();
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
<li><a href="/admin/actives/0" class="menu-item <%= it._base_url === '/admin/actives' ? 'menu-active':''%>">Actives</a></li>
|
<li><a href="/admin/actives/0" class="menu-item <%= it._base_url === '/admin/actives' ? 'menu-active':''%>">Actives</a></li>
|
||||||
<li><a href="/admin/output-variables/0" class="menu-item <%= it._base_url === '/admin/output-variables' ? 'menu-active':''%>">Output variables</a></li>
|
<li><a href="/admin/output-variables/0" class="menu-item <%= it._base_url === '/admin/output-variables' ? 'menu-active':''%>">Output variables</a></li>
|
||||||
<li><a href="/admin/profile-sections/0" class="menu-item <%= it._base_url === '/admin/profile-sections' ? 'menu-active':''%>">Profile sections</a></li>
|
<li><a href="/admin/profile-sections/0" class="menu-item <%= it._base_url === '/admin/profile-sections' ? 'menu-active':''%>">Profile sections</a></li>
|
||||||
|
<li><a href="/admin/termination-config" class="menu-item <%= it._base_url === '/admin/termination-config' ? 'menu-active':''%>">Termination Config</a></li>
|
||||||
<li><a href="/admin/profile" class="menu-item <%= it._base_url === '/admin/profile' ? 'menu-active':''%>">Profile</a></li>
|
<li><a href="/admin/profile" class="menu-item <%= it._base_url === '/admin/profile' ? 'menu-active':''%>">Profile</a></li>
|
||||||
<li><a href="/admin/logout" class="menu-item <%= it._base_url === '/admin/logout' ? 'menu-active':''%>">Logout</a></li>
|
<li><a href="/admin/logout" class="menu-item <%= it._base_url === '/admin/logout' ? 'menu-active':''%>">Logout</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
Reference in New Issue
Block a user