Added a custom entrypoint script and finished off the saving feature of the admin page.
This commit is contained in:
37
adm/index.js
37
adm/index.js
@@ -4,10 +4,10 @@ Vue.createApp({
|
|||||||
, 'frm': { 'e': null, 'modal': null }
|
, 'frm': { 'e': null, 'modal': null }
|
||||||
, 'faults': null
|
, 'faults': null
|
||||||
, 'fields': { 'coordinates': { 'patterns': [ '^$', '^-?\\d{1,3}(?:\\.\\d+)?,-?\\d{1,3}(?:\\.\\d+)?$' ], 'default': '-27.38621539644283,153.0351689206467' }
|
, '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': '' }
|
, '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{2}$' ], 'default': '' }
|
, 'end': { 'patterns': [ '^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:?\\d{0,2}$' ], 'default': '' }
|
||||||
, 'title': { 'patterns': [ '^.{20,50}$' ], 'default': 'Event Title' }
|
, 'title': { 'patterns': [ '^.{10,50}$' ], 'default': 'Event Title' }
|
||||||
, 'description': { 'patterns': [ '^.{20,}$' ], 'default': 'Event Description' }
|
, 'description': { 'patterns': [ '^.{16,}$' ], 'default': 'Event Description' }
|
||||||
, 'location': { 'patterns': [ '^.{5,100}$' ], 'default': 'Event Location' }
|
, 'location': { 'patterns': [ '^.{5,100}$' ], 'default': 'Event Location' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,11 +17,14 @@ Vue.createApp({
|
|||||||
var m = moment(dt);
|
var m = moment(dt);
|
||||||
var t = m.hour() * 3600 + m.minute() * 60 + m.second();
|
var t = m.hour() * 3600 + m.minute() * 60 + m.second();
|
||||||
if ( t > 0 ) {
|
if ( t > 0 ) {
|
||||||
fmt = 'DD MMM YYYY, HH:mm:ss';
|
fmt = ' ddd DD MMM YYYY, h:mm A';
|
||||||
}
|
}
|
||||||
var ret = moment(dt).format(fmt);
|
var ret = moment(dt).format(fmt);
|
||||||
return ret;
|
return ret;
|
||||||
},
|
},
|
||||||
|
hoursDiff: function(d1, d2) {
|
||||||
|
return moment(d2).diff(moment(d1), 'hours', true);
|
||||||
|
},
|
||||||
createEvent: function() {
|
createEvent: function() {
|
||||||
var event = {};
|
var event = {};
|
||||||
for ( var k in this.fields ) {
|
for ( var k in this.fields ) {
|
||||||
@@ -33,8 +36,8 @@ Vue.createApp({
|
|||||||
next7pm.add(1, 'day');
|
next7pm.add(1, 'day');
|
||||||
}
|
}
|
||||||
const twoHoursLater = moment(next7pm).add(2, 'hours');
|
const twoHoursLater = moment(next7pm).add(2, 'hours');
|
||||||
event.start = next7pm.format('YYYY-MM-DDTHH:mm:ss');
|
event.start = next7pm.format('YYYY-MM-DDTHH:mm');
|
||||||
event.end = twoHoursLater.format('YYYY-MM-DDTHH:mm:ss');
|
event.end = twoHoursLater.format('YYYY-MM-DDTHH:mm');
|
||||||
this.events.unshift(event);
|
this.events.unshift(event);
|
||||||
this.frm.e = 0;
|
this.frm.e = 0;
|
||||||
},
|
},
|
||||||
@@ -47,6 +50,7 @@ Vue.createApp({
|
|||||||
}
|
}
|
||||||
, function(data) {
|
, function(data) {
|
||||||
app.events = data;
|
app.events = data;
|
||||||
|
app.frm.e = null;
|
||||||
app.validateEvents();
|
app.validateEvents();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -73,9 +77,20 @@ Vue.createApp({
|
|||||||
fault.e = e;
|
fault.e = e;
|
||||||
fault.k = k;
|
fault.k = k;
|
||||||
fault.v = value;
|
fault.v = value;
|
||||||
|
fault.msg = 'Bad format for ' + k + '.';
|
||||||
faults.push(fault);
|
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 );
|
this.faults = ( faults.length == 0 ? null : faults );
|
||||||
},
|
},
|
||||||
@@ -95,6 +110,14 @@ Vue.createApp({
|
|||||||
d.property = property;
|
d.property = property;
|
||||||
d.value = this.events[this.frm.e][property];
|
d.value = this.events[this.frm.e][property];
|
||||||
this.frm.modal = d;
|
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() {
|
mounted: function() {
|
||||||
|
|||||||
@@ -21,8 +21,8 @@
|
|||||||
<input class="form-control" v-if="[ 'start', 'end' ].indexOf(frm.modal.property) != -1" type="datetime-local" v-model="frm.modal.value">
|
<input class="form-control" v-if="[ 'start', 'end' ].indexOf(frm.modal.property) != -1" type="datetime-local" v-model="frm.modal.value">
|
||||||
<hr />
|
<hr />
|
||||||
<div class="btn-group" role="group" style="width: 100%;">
|
<div class="btn-group" role="group" style="width: 100%;">
|
||||||
<button type="button" class="btn btn-warning" v-on:click="frm.modal = null;">Cancel</button>
|
<button type="button" class="btn btn-warning" v-on:click="modalCancel">Cancel</button>
|
||||||
<button type="button" class="btn btn-success" v-on:click="events[frm.e][frm.modal.property] = frm.modal.value; frm.modal = null;">Update</button>
|
<button type="button" class="btn btn-success" v-on:click="modalUpdate">Update</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -32,9 +32,11 @@
|
|||||||
<table class="table events mb-2">
|
<table class="table events mb-2">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="event, e in events" v-on:click="frm.e = e" :class="{ 'selection': frm.e == e }">
|
<tr v-for="event, e in events" v-on:click="frm.e = e" :class="{ 'selection': frm.e == e }">
|
||||||
<td><span class="badge text-bg-info">{{ e + 1 }}</span></td>
|
<td style="padding-top: 9px;">
|
||||||
|
<span class="badge text-bg-info" style="float: left;">{{ e + 1 }}</span>
|
||||||
|
<span class="badge text-bg-success" style="float: right;">{{ hoursDiff( event.start, event.end) }} hrs</span>
|
||||||
|
</td>
|
||||||
<td class="dt">{{ formatDate(event.start) }}</td>
|
<td class="dt">{{ formatDate(event.start) }}</td>
|
||||||
<td class="dt">{{ formatDate(event.end) }}</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@@ -42,11 +44,19 @@
|
|||||||
<button v-if="faults == null" class="btn btn-primary form-control" v-on:click="saveEvents">Save</button>
|
<button v-if="faults == null" class="btn btn-primary form-control" v-on:click="saveEvents">Save</button>
|
||||||
<ul v-else>
|
<ul v-else>
|
||||||
<li v-for="fault, f in faults">
|
<li v-for="fault, f in faults">
|
||||||
<span class="badge text-bg-info">{{ parseInt(fault.e) + 1 }}</span> <span class="tt">{{fault.k}}</span></span>
|
<span class="badge text-bg-info">{{ parseInt(fault.e) + 1 }}</span> <span class="tt">{{fault.msg}}</span></span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-8" v-if="frm.e != null">
|
<div class="col-8" v-if="frm.e != null">
|
||||||
|
<div class="input-group mb-1">
|
||||||
|
<span class="input-group-text">Title</span>
|
||||||
|
<input type="text" class="form-control" v-model="events[frm.e].title" v-on:keyup="validateEvents">
|
||||||
|
</div>
|
||||||
|
<div class="input-group mb-1">
|
||||||
|
<span class="input-group-text">Description</span>
|
||||||
|
<input type="text" class="form-control" v-model="events[frm.e].description" v-on:keyup="validateEvents">
|
||||||
|
</div>
|
||||||
<div class="input-group mb-1">
|
<div class="input-group mb-1">
|
||||||
<span class="input-group-text">Start</span>
|
<span class="input-group-text">Start</span>
|
||||||
<input type="text" disabled class="form-control" :value="formatDate(events[frm.e].start)" v-on:keyup="validateEvents">
|
<input type="text" disabled class="form-control" :value="formatDate(events[frm.e].start)" v-on:keyup="validateEvents">
|
||||||
@@ -57,14 +67,6 @@
|
|||||||
<input type="text" disabled class="form-control" :value="formatDate(events[frm.e].end)" v-on:keyup="validateEvents">
|
<input type="text" disabled class="form-control" :value="formatDate(events[frm.e].end)" v-on:keyup="validateEvents">
|
||||||
<button class="btn btn-outline-secondary" type="button" v-on:click="modal('end')">...</button>
|
<button class="btn btn-outline-secondary" type="button" v-on:click="modal('end')">...</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group mb-1">
|
|
||||||
<span class="input-group-text">Title</span>
|
|
||||||
<input type="text" class="form-control" v-model="events[frm.e].title" v-on:keyup="validateEvents">
|
|
||||||
</div>
|
|
||||||
<div class="input-group mb-1">
|
|
||||||
<span class="input-group-text">Description</span>
|
|
||||||
<input type="text" class="form-control" v-model="events[frm.e].description" v-on:keyup="validateEvents">
|
|
||||||
</div>
|
|
||||||
<div class="input-group mb-1">
|
<div class="input-group mb-1">
|
||||||
<span class="input-group-text">Location</span>
|
<span class="input-group-text">Location</span>
|
||||||
<input type="text" class="form-control" v-model="events[frm.e].location" v-on:keyup="validateEvents">
|
<input type="text" class="form-control" v-model="events[frm.e].location" v-on:keyup="validateEvents">
|
||||||
|
|||||||
@@ -1,33 +1 @@
|
|||||||
[
|
[{"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"}]
|
||||||
{
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
image: php:8.2-apache
|
image: php:8.2-apache
|
||||||
|
hostname: app
|
||||||
container_name: app
|
container_name: app
|
||||||
ports:
|
ports:
|
||||||
- "8080:80"
|
- "8080:80"
|
||||||
@@ -22,10 +23,13 @@ services:
|
|||||||
- ./app/:/var/www/html:Z
|
- ./app/:/var/www/html:Z
|
||||||
- ./lib:/var/www/html/lib:Z
|
- ./lib:/var/www/html/lib:Z
|
||||||
- ./${HLBDAT:-dat.live}:/var/www/html/dat:Z
|
- ./${HLBDAT:-dat.live}:/var/www/html/dat:Z
|
||||||
|
- ./entrypoint.sh:/entrypoint.sh:Z
|
||||||
|
entrypoint: ["bash", "/entrypoint.sh"]
|
||||||
networks:
|
networks:
|
||||||
- labnet
|
- labnet
|
||||||
adm:
|
adm:
|
||||||
image: php:8.2-apache
|
image: php:8.2-apache
|
||||||
|
hostname: adm
|
||||||
container_name: adm
|
container_name: adm
|
||||||
ports:
|
ports:
|
||||||
- "8081:80"
|
- "8081:80"
|
||||||
@@ -33,6 +37,8 @@ services:
|
|||||||
- ./adm/:/var/www/html:Z
|
- ./adm/:/var/www/html:Z
|
||||||
- ./lib:/var/www/html/lib:Z
|
- ./lib:/var/www/html/lib:Z
|
||||||
- ./${HLBDAT:-dat.live}:/var/www/html/dat:Z
|
- ./${HLBDAT:-dat.live}:/var/www/html/dat:Z
|
||||||
|
- ./entrypoint.sh:/entrypoint.sh:Z
|
||||||
|
entrypoint: ["bash", "/entrypoint.sh"]
|
||||||
networks:
|
networks:
|
||||||
- labnet
|
- labnet
|
||||||
networks:
|
networks:
|
||||||
|
|||||||
8
entrypoint.sh
Normal file
8
entrypoint.sh
Normal file
@@ -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
|
||||||
|
|
||||||
Reference in New Issue
Block a user