diff --git a/adm/index.js b/adm/index.js
index a5361d4..0929519 100755
--- a/adm/index.js
+++ b/adm/index.js
@@ -4,10 +4,10 @@ Vue.createApp({
, 'frm': { 'e': null, 'modal': null }
, 'faults': null
, 'fields': { 'coordinates': { 'patterns': [ '^$', '^-?\\d{1,3}(?:\\.\\d+)?,-?\\d{1,3}(?:\\.\\d+)?$' ], 'default': '-27.38621539644283,153.0351689206467' }
- , 'start': { 'patterns': [ '^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$' ], 'default': '' }
- , 'end': { 'patterns': [ '^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$' ], 'default': '' }
- , 'title': { 'patterns': [ '^.{20,50}$' ], 'default': 'Event Title' }
- , 'description': { 'patterns': [ '^.{20,}$' ], 'default': 'Event Description' }
+ , 'start': { 'patterns': [ '^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:?\\d{0,2}$' ], 'default': '' }
+ , 'end': { 'patterns': [ '^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:?\\d{0,2}$' ], 'default': '' }
+ , 'title': { 'patterns': [ '^.{10,50}$' ], 'default': 'Event Title' }
+ , 'description': { 'patterns': [ '^.{16,}$' ], 'default': 'Event Description' }
, 'location': { 'patterns': [ '^.{5,100}$' ], 'default': 'Event Location' }
}
}
@@ -17,11 +17,14 @@ Vue.createApp({
var m = moment(dt);
var t = m.hour() * 3600 + m.minute() * 60 + m.second();
if ( t > 0 ) {
- fmt = 'DD MMM YYYY, HH:mm:ss';
+ fmt = ' ddd DD MMM YYYY, h:mm A';
}
var ret = moment(dt).format(fmt);
return ret;
},
+ hoursDiff: function(d1, d2) {
+ return moment(d2).diff(moment(d1), 'hours', true);
+ },
createEvent: function() {
var event = {};
for ( var k in this.fields ) {
@@ -33,8 +36,8 @@ Vue.createApp({
next7pm.add(1, 'day');
}
const twoHoursLater = moment(next7pm).add(2, 'hours');
- event.start = next7pm.format('YYYY-MM-DDTHH:mm:ss');
- event.end = twoHoursLater.format('YYYY-MM-DDTHH:mm:ss');
+ event.start = next7pm.format('YYYY-MM-DDTHH:mm');
+ event.end = twoHoursLater.format('YYYY-MM-DDTHH:mm');
this.events.unshift(event);
this.frm.e = 0;
},
@@ -47,6 +50,7 @@ Vue.createApp({
}
, function(data) {
app.events = data;
+ app.frm.e = null;
app.validateEvents();
}
);
@@ -73,9 +77,20 @@ Vue.createApp({
fault.e = e;
fault.k = k;
fault.v = value;
+ fault.msg = 'Bad format for ' + k + '.';
faults.push(fault);
}
}
+ var d1 = moment(this.events[e].start);
+ var d2 = moment(this.events[e].end);
+ if ( d2.isSameOrBefore(d1) ) {
+ var fault = {};
+ fault.e = e;
+ fault.k = 'end';
+ fault.v = this.formatDate(d2);
+ fault.msg = 'Event ends before start.';
+ faults.push(fault);
+ }
}
this.faults = ( faults.length == 0 ? null : faults );
},
@@ -95,7 +110,15 @@ Vue.createApp({
d.property = property;
d.value = this.events[this.frm.e][property];
this.frm.modal = d;
- }
+ },
+ modalUpdate: function() {
+ this.events[this.frm.e][this.frm.modal.property] = this.frm.modal.value;
+ this.frm.modal = null;
+ this.validateEvents();
+ },
+ modalCancel: function() {
+ frm.modal = null;
+ }
},
mounted: function() {
this.load();
diff --git a/adm/index.php b/adm/index.php
index b66e3e3..b76a878 100755
--- a/adm/index.php
+++ b/adm/index.php
@@ -21,8 +21,8 @@
-
-
+
+
@@ -32,9 +32,11 @@
- | {{ e + 1 }} |
+
+ {{ e + 1 }}
+ {{ hoursDiff( event.start, event.end) }} hrs
+ |
{{ formatDate(event.start) }} |
- {{ formatDate(event.end) }} |
@@ -42,11 +44,19 @@
-
- {{ parseInt(fault.e) + 1 }} {{fault.k}}
+ {{ parseInt(fault.e) + 1 }} {{fault.msg}}
+
+ Title
+
+
+
+ Description
+
+
Start
@@ -57,14 +67,6 @@
-
- Title
-
-
-
- Description
-
-
Location
diff --git a/dat.live/events.json b/dat.live/events.json
index 99397e7..7c01faf 100755
--- a/dat.live/events.json
+++ b/dat.live/events.json
@@ -1,33 +1 @@
-[
- {
- "start": "2025-06-10T19:00:00",
- "end": "2025-06-10T21:00:00",
- "title": "June 2025 Online Catch Up",
- "description": "Getting started with meshtastic",
- "location": "Jitsi"
- },
- {
- "start": "2025-06-19T18:30:00",
- "end": "2025-06-19T21:00:00",
- "title": "June 2025 In Person Catch Up",
- "description": "Social get-together. Discussion about large language models and meshtastic experiments. Clumsy attempt at adhering to an agenda and taking minutes.",
- "location": "Chermside Library",
- "coordinates": "-27.38621539644283,153.0351689206467"
- },
- {
- "start": "2025-07-08T19:00:00",
- "end": "2025-07-08T21:00:00",
- "title": "July 2025 Online Catch Up",
- "description": "Monthly Online Jitsi Get Together",
- "location": "Jitsi"
- },
- {
- "start": "2025-07-24T18:30:00",
- "end": "2025-07-24T21:00:00",
- "title": "July 2025 In Person Catch Up",
- "description": "Monthly In Person Get Together",
- "location": "Chermside Library",
- "coordinates": "-27.38621539644283,153.0351689206467"
- }
-]
-
+[{"start":"2025-07-24T18:30:00","end":"2025-07-24T21:00:00","title":"July 2025 In Person Catch Up","description":"Monthly In Person Get Together","location":"Chermside Library","coordinates":"-27.38621539644283,153.0351689206467","ctl":"202507241830","agenda":"- 6.30 pm - Welcome\n- 6.35 pm - Agreement on Agenda Items\n- 6.40 pm - Administrivia (if any)\n- 6.45 pm - Presentation 1: James: Git\n- 7.15 pm - Presentation 2: Terry?: Fossil?\n- 7.45 pm - Loose (Discourse) Threads\n"},{"coordinates":"-27.38621539644283,153.0351689206467","start":"2025-07-11T18:30","end":"2025-07-11T21:00","title":"Event Title3","description":"Event Description","location":"Event Location","ctl":"202507111830"},{"start":"2025-07-08T19:00:00","end":"2025-07-08T21:00:00","title":"July 2025 Online Catch Up","description":"Monthly Online Jitsi Get Together","location":"Jitsi","ctl":"202507081900","agenda":"- 7.30 pm - Welcome\n- 7.35 pm - Agreement on Agenda Items\n- 7.40 pm - Administrivia (if any)\n- 7.45 pm - Presentation 1 - James: Git\n- 8.15 pm - Presentation 2 - Terry?: Fossil?\n- 8.45 pm - Loose (Discourse) Threads\n"},{"start":"2025-06-19T18:30:00","end":"2025-06-19T21:00:00","title":"June 2025 In Person Catch Up","description":"Social get-together. Discussion about large language models and meshtastic experiments. Clumsy attempt at adhering to an agenda and taking minutes.","location":"Chermside Library","coordinates":"-27.38621539644283,153.0351689206467","ctl":"202506191830","minutes":"- Admin\n\t- ToS and Privacy Policy doesn't need to be hosted on the main page. It's already got a publicly accessible presence in Discourse.\n\t- James to formalise agenda procedure\n\t- James to render cal.php on main page\n\t- James to publish \"subscribe\" link for calendar\n- Recap from Last Month\n\t- Hardware Donations for Education\n\t\t- Substation 33, in Kingston or Logan?\n\t\t- Dirk has a carload of stuff to offload\n- Discourse Themes\n\t- LLMs\n\t- Hardware for LLMs\n\t- Tiny11\n- Agenda\n\t- Motioneye\n\t- Meshtastic\n- Next Month\n\t- Location Requests\n"},{"start":"2025-06-10T19:00:00","end":"2025-06-10T21:00:00","title":"June 2025 Online Catch Up","description":"Getting started with meshtastic","location":"Jitsi","ctl":"202506101900"}]
\ No newline at end of file
diff --git a/docker-compose.yaml b/docker-compose.yaml
index 9f2b5cc..d483172 100755
--- a/docker-compose.yaml
+++ b/docker-compose.yaml
@@ -15,6 +15,7 @@
services:
app:
image: php:8.2-apache
+ hostname: app
container_name: app
ports:
- "8080:80"
@@ -22,10 +23,13 @@ services:
- ./app/:/var/www/html:Z
- ./lib:/var/www/html/lib:Z
- ./${HLBDAT:-dat.live}:/var/www/html/dat:Z
+ - ./entrypoint.sh:/entrypoint.sh:Z
+ entrypoint: ["bash", "/entrypoint.sh"]
networks:
- labnet
adm:
image: php:8.2-apache
+ hostname: adm
container_name: adm
ports:
- "8081:80"
@@ -33,6 +37,8 @@ services:
- ./adm/:/var/www/html:Z
- ./lib:/var/www/html/lib:Z
- ./${HLBDAT:-dat.live}:/var/www/html/dat:Z
+ - ./entrypoint.sh:/entrypoint.sh:Z
+ entrypoint: ["bash", "/entrypoint.sh"]
networks:
- labnet
networks:
diff --git a/entrypoint.sh b/entrypoint.sh
new file mode 100644
index 0000000..ab18858
--- /dev/null
+++ b/entrypoint.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+set -e
+
+echo "Custom entrypoint.sh: `hostname -s`!"
+chmod -Rfv ugo+w /var/www/html/dat
+
+exec docker-php-entrypoint apache2-foreground
+