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 @@
+
+ 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 +