diff --git a/buttons.json b/buttons.json
new file mode 100644
index 0000000..c0bf857
--- /dev/null
+++ b/buttons.json
@@ -0,0 +1,45 @@
+{
+ "COLS": [
+ "Normal Announcements",
+ "Emergency Announcements"
+ ],
+ "ROWS": [
+ {
+ "text": "Live Page",
+ "btnClass": "btn-primary",
+ "name": "LivePage",
+ "doubleHeight": true,
+ "context": {
+ "context": "custom-emergency.9001.1",
+ "timeout": 30000,
+ "cid": "Live Page"
+ }
+ },
+ {
+ "text": "Emergency Announcement",
+ "btnClass": "btn-danger",
+ "name": "EmergencyAnnouncement",
+ "doubleHeight": true,
+ "faIcon": "fa-solid fa-octagon",
+ "context": {
+ "context": "custom-emergency.9002.1",
+ "timeout": 30000,
+ "cid": "Emergency Announcement"
+ }
+ },
+ {},
+ {
+ "text": "Weather Alert",
+ "btnClass": "btn-warning",
+ "name": "WeatherAlert",
+ "faIcon": "fa-regular fa-cloud-bolt",
+ "doubleHeight": false,
+ "context": {
+ "context": "custom-emergency.9003.1",
+ "timeout": 30000,
+ "cid": "\"Weather Alert\" <9000>",
+ "dial": "9000"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/index.ejs b/index.ejs
new file mode 100644
index 0000000..d18ef3c
--- /dev/null
+++ b/index.ejs
@@ -0,0 +1,64 @@
+<%
+// buttons is provided to this template
+const numCols = (buttons && buttons.COLS && buttons.COLS.length) || 1;
+const colWidth = (12 / numCols) >= 1 ? Math.floor(12 / numCols) : null;
+
+// chunk the flat ROWS array into logical rows of numCols items
+const chunks = [];
+for (let i = 0; i < (buttons.ROWS || []).length; i += numCols) {
+ chunks.push((buttons.ROWS || []).slice(i, i + numCols));
+}
+%>
+
+
+
+
+
+
+ <% for (let c = 0; c < numCols; c++) { %>
+
+
<%= buttons.COLS[c] || '' %>
+
+ <% } %>
+
+
+
+
+ <% chunks.forEach(function(row) { %>
+
+ <% for (let c = 0; c < numCols; c++) {
+ const cell = row[c];
+ const isEmpty = !cell || Object.keys(cell).length === 0;
+ const colClass = '<%= colWidth ? "col-' + colWidth + '" : "col" %>'; // placeholder for layout below
+ %>
+
+ <% if (isEmpty) { %>
+
+ <% } else {
+ // build data attributes from context if present
+ const ctx = cell.context || {};
+ const dataAttrs = [];
+ if (ctx.context) dataAttrs.push('data-context="' + ctx.context + '"');
+ if (ctx.timeout) dataAttrs.push('data-timeout="' + ctx.timeout + '"');
+ if (ctx.cid) dataAttrs.push('data-cid="' + ctx.cid + '"');
+ if (ctx.dial) dataAttrs.push('data-dial="' + ctx.dial + '"');
+ %>
+
+ <% } %>
+
+ <% } %>
+
+ <% }); %>
+
+
\ No newline at end of file
diff --git a/index.js b/index.js
index ba19f5e..97a1c89 100644
--- a/index.js
+++ b/index.js
@@ -3,32 +3,34 @@ const { exec } = require('child_process');
require('dotenv').config();
-const contexts = {
- "A1": {
- context: 'custom-emergency.9001.1',
- timeout: 30000,
- cid: 'Live Page'
- },
- "E1": {
- context: 'custom-emergency.9002.1',
- timeout: 30000,
- cid: 'Emergency Live Page'
- },
- "E2": { // Weather
- context: 'custom-emergency.9003.1',
- timeout: 30000,
- cid: '"Emergency 2" <2100>',
- number: process.env.PAGING_ADAPTER_EXT // Direct to page group, no phone needed
- }
+const phonesCfg = require('./phones.json');
+const buttonsCfg = require('./buttons.json');
+
+const contexts = {};
+
+// Generate contexts from buttonsCfg
+if (buttonsCfg && buttonsCfg.ROWS) {
+ buttonsCfg.ROWS.forEach(button => {
+ if (button.name && button.context) {
+ contexts[button.name] = {
+ context: button.context.context,
+ timeout: button.context.timeout,
+ cid: button.context.cid,
+ ...(button.context.dial && { dial: button.context.dial })
+ };
+ }
+ });
}
+console.log('Generated contexts:', contexts);
+
function trigCall(pageType, phone) {
// If contexts[pageType] does not exist, return an error
if (!contexts[pageType]) {
throw new Error(`Invalid page type: ${pageType}`);
}
- const { context, timeout, cid, number } = contexts[pageType];
- const targetNumber = number || phone;
+ const { context, timeout, cid, dial } = contexts[pageType];
+ const targetNumber = dial || phone;
if (!targetNumber) {
throw new Error(`Phone number is required for page type: ${pageType}`);
}
@@ -90,7 +92,7 @@ function auth(req, res, next) {
}
app.get('/', (req, res) => {
- res.render('index', { session: req.session });
+ res.render('index', { session: req.session, phones: phonesCfg, buttons: require("./buttons.json") });
});
app.post('/trig', async (req, res) => {
diff --git a/phones.json b/phones.json
new file mode 100644
index 0000000..29747e1
--- /dev/null
+++ b/phones.json
@@ -0,0 +1,6 @@
+{
+ "Front Desk": "2120",
+ "Cam": "2113",
+ "Cam 2": "2112",
+ "Ryan": "2100"
+}
\ No newline at end of file
diff --git a/views/index.ejs b/views/index.ejs
index fa0a6e6..812ac95 100644
--- a/views/index.ejs
+++ b/views/index.ejs
@@ -1,74 +1,121 @@
+
-
-
-
- Funny goofy test page!!!!!1!
+
+
+
+
+ Funny goofy test page!!!!!1!
+
+
-
-
-
-
-
-
-
-
- Normal Announcements |
- Emergency Announcements |
-
-
-
-
- |
-
- |
-
-
- |
-
-
- |
-
- |
-
-
- |
-
-
- |
-
- |
-
-
- |
-
-
-
-
-
-
-
-
+
+
+
+
+ <%
+ // determine columns and chunk rows
+ const cols = (buttons && buttons.COLS) || [''];
+ const numCols = Math.max(1, cols.length);
+ const rowsFlat = (buttons && buttons.ROWS) || [];
+ const chunks = [];
+ for (let i = 0; i < rowsFlat.length; i += numCols) {
+ const slice = rowsFlat.slice(i, i + numCols);
+ // pad short slice with empty objects so layout stays consistent
+ while (slice.length < numCols) slice.push({});
+ chunks.push(slice);
+ }
+ %>
+
+
+
+
+
+
+ <% for (let c = 0; c < numCols; c++) { %>
+
+ <%= cols[c] || '' %>
+ |
+ <% } %>
+
+
+
+ <% chunks.forEach((row) => { %>
+
+ <% for (let c = 0; c < numCols; c++) {
+ const cell = row[c] || {};
+ const isBlank = Object.keys(cell).length === 0;
+ %>
+ |
+ <% if (isBlank) { %>
+
+ <% } else {
+ const ctx = cell.context || {};
+ %>
+
+ <% } %>
+ |
+ <% } %>
+
+ <% }); %>
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file