Finished off the agenda and minutes features in the adm page. Added another six events to the calendar.
This commit is contained in:
@@ -7,13 +7,7 @@ if ( in_array("cmd", array_keys($_GET)) and $_GET["cmd"] == "get" ) {
|
|||||||
} elseif ( $_POST["cmd"] == "put" ) {
|
} elseif ( $_POST["cmd"] == "put" ) {
|
||||||
$json = base64_decode($_POST["payload"]);
|
$json = base64_decode($_POST["payload"]);
|
||||||
$events = json_decode($json, true);
|
$events = json_decode($json, true);
|
||||||
for ( $i = 0; $i < count($events); $i++ ) {
|
putEvents($events);
|
||||||
foreach ( array( "hours", "agenda", "minutes" ) as $field ) {
|
|
||||||
unset($events[$i][$field]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$json = json_encode($events, JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT);
|
|
||||||
file_put_contents("dat/events.json", $json);
|
|
||||||
$ret = getEvents();
|
$ret = getEvents();
|
||||||
}
|
}
|
||||||
print(json_encode($ret));
|
print(json_encode($ret));
|
||||||
|
|||||||
@@ -71,3 +71,9 @@ body { display: none; }
|
|||||||
border-bottom-left-radius: 8px;
|
border-bottom-left-radius: 8px;
|
||||||
border-bottom-right-radius: 8px;
|
border-bottom-right-radius: 8px;
|
||||||
}
|
}
|
||||||
|
textarea {
|
||||||
|
font-family: monospace;
|
||||||
|
background-color: #000000;
|
||||||
|
color: #ffffff;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|||||||
17
adm/index.js
17
adm/index.js
@@ -1,7 +1,8 @@
|
|||||||
|
var dbg = null;
|
||||||
Vue.createApp({
|
Vue.createApp({
|
||||||
data: function() {
|
data: function() {
|
||||||
return { 'events': null
|
return { 'events': null
|
||||||
, 'frm': { 'e': null, 'modal': null }
|
, 'frm': { 'e': null, 'modal': null, 'tab': 'agenda' }
|
||||||
, '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{0,2}$' ], 'default': '' }
|
, 'start': { 'patterns': [ '^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:?\\d{0,2}$' ], 'default': '' }
|
||||||
@@ -22,6 +23,19 @@ Vue.createApp({
|
|||||||
var ret = moment(dt).format(fmt);
|
var ret = moment(dt).format(fmt);
|
||||||
return ret;
|
return ret;
|
||||||
},
|
},
|
||||||
|
tabEnabled: function(e, tab) {
|
||||||
|
var ret = ( Object.keys(this.events[e]).indexOf(tab) >= 0 );
|
||||||
|
return ret;
|
||||||
|
},
|
||||||
|
toggleMD: function(evt) {
|
||||||
|
evt.preventDefault();
|
||||||
|
if ( this.events[this.frm.e][this.frm.tab] == undefined ) {
|
||||||
|
this.events[this.frm.e][this.frm.tab] = '';
|
||||||
|
} else {
|
||||||
|
delete this.events[this.frm.e][this.frm.tab];
|
||||||
|
}
|
||||||
|
this.events = JSON.parse(JSON.stringify(this.events));
|
||||||
|
},
|
||||||
hoursDiff: function(d1, d2) {
|
hoursDiff: function(d1, d2) {
|
||||||
return moment(d2).diff(moment(d1), 'hours', true);
|
return moment(d2).diff(moment(d1), 'hours', true);
|
||||||
},
|
},
|
||||||
@@ -125,6 +139,7 @@ Vue.createApp({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted: function() {
|
mounted: function() {
|
||||||
|
dbg = this;
|
||||||
this.load();
|
this.load();
|
||||||
}
|
}
|
||||||
}).mount('#app')
|
}).mount('#app')
|
||||||
|
|||||||
@@ -80,15 +80,16 @@
|
|||||||
<input type="text" class="form-control" v-model="events[frm.e].coordinates" v-on:keyup="validateEvents">
|
<input type="text" class="form-control" v-model="events[frm.e].coordinates" v-on:keyup="validateEvents">
|
||||||
</div>
|
</div>
|
||||||
<ul class="nav nav-tabs">
|
<ul class="nav nav-tabs">
|
||||||
<li class="nav-item">
|
<li class="nav-item" v-for="lbl, tab in { 'agenda': 'Agenda', 'minutes': 'Minutes' }">
|
||||||
<a class="nav-link active" aria-current="page" href="#">Agenda <input type="checkbox" /></a>
|
<a class="nav-link" :class="{ 'active': frm.tab == tab }" aria-current="page" href="#" v-on:click="frm.tab = tab">{{lbl}} <span v-if="tabEnabled(frm.e, tab)">🟢</span><span v-else>🔴</span></a>
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="#">Minutes <input type="checkbox" /></a>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="tabbody">
|
<div class="tabbody">
|
||||||
<textarea class="form-control" rows="10"></textarea>
|
<button class="btn btn-success mb-1" v-on:click="toggleMD" v-if="tabEnabled(frm.e, frm.tab)">Enabled</button>
|
||||||
|
<button class="btn btn-danger mb-1" v-on:click="toggleMD" v-else >Disabled</button>
|
||||||
|
<template v-if="Object.keys(events[frm.e]).indexOf(frm.tab) != -1">
|
||||||
|
<textarea class="form-control" rows="10" v-if="events[frm.e][frm.tab] != undefined" v-model="events[frm.e][frm.tab]"></textarea>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-danger btn-lg form-control mt-2" v-on:click="deleteEvent">Delete</button>
|
<button class="btn btn-danger btn-lg form-control mt-2" v-on:click="deleteEvent">Delete</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
- 6.30 pm - Welcome
|
1. 7.30 pm - Welcome
|
||||||
- 6.35 pm - Agreement on Agenda Items
|
2. 7.35 pm - Agreement on Agenda Items
|
||||||
- 6.40 pm - Administrivia (if any)
|
3. 7.40 pm - Administrivia (if any)
|
||||||
- 6.45 pm - Presentation 1: James: Git
|
1. OK with default Privacy Policy and Terms of Service
|
||||||
- 7.15 pm - Presentation 2: Terry?: Fossil?
|
2. Logos: JD to use images supplied to attempt producing something in Gimp
|
||||||
- 7.45 pm - Loose (Discourse) Threads
|
4. 7.45 pm - Presentation 1 - James: Git
|
||||||
|
5. 8.45 pm - Loose (Discourse) Threads
|
||||||
|
1. Meshtastic: Dirk has seen JD's node, but we haven't successfully exchanged messages yet.
|
||||||
|
5. Next meeting
|
||||||
|
1. JD to book next three months of meetings. One more at Chermside, then two at Carindale.
|
||||||
|
|||||||
@@ -1,20 +1,66 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"coordinates": "-27.50129,153.1027015",
|
||||||
|
"start": "2025-10-23T18:30",
|
||||||
|
"end": "2025-10-23T21:00",
|
||||||
|
"title": "October 2025 In Person Catch Up",
|
||||||
|
"description": "Monthly In Person Get Together",
|
||||||
|
"location": "Carindale Library"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"coordinates": "",
|
||||||
|
"start": "2025-10-07T19:00",
|
||||||
|
"end": "2025-10-07T21:00",
|
||||||
|
"title": "October 2025 Online Catch Up",
|
||||||
|
"description": "Monthly Online Jitsi Get Together",
|
||||||
|
"location": "Jitsi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"coordinates": "-27.50129,153.1027015",
|
||||||
|
"start": "2025-09-25T18:30",
|
||||||
|
"end": "2025-09-25T21:00",
|
||||||
|
"title": "September 2025 In Person Catch Up",
|
||||||
|
"description": "Monthly In Person Get Together",
|
||||||
|
"location": "Carindale Library"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"coordinates": "",
|
||||||
|
"start": "2025-09-09T19:00",
|
||||||
|
"end": "2025-09-09T21:00",
|
||||||
|
"title": "September 2025 Online Catch Up",
|
||||||
|
"description": "Monthly Online Jitsi Get Together",
|
||||||
|
"location": "Jitsi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"coordinates": "-27.38621539644283,153.0351689206467",
|
||||||
|
"start": "2025-08-28T18:30",
|
||||||
|
"end": "2025-08-28T21:00",
|
||||||
|
"title": "August 2025 In Person Catch Up",
|
||||||
|
"description": "Monthly In Person Get Together",
|
||||||
|
"location": "Chermside Library"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"coordinates": "",
|
||||||
|
"start": "2025-08-12T19:00",
|
||||||
|
"end": "2025-08-12T21:00",
|
||||||
|
"title": "August 2025 Online Catch Up",
|
||||||
|
"description": "Monthly Online Jitsi Get Together",
|
||||||
|
"location": "Jitsi"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"start": "2025-07-24T18:30:00",
|
"start": "2025-07-24T18:30:00",
|
||||||
"end": "2025-07-24T21:00",
|
"end": "2025-07-24T21:00",
|
||||||
"title": "July 2025 In Person Catch Up",
|
"title": "July 2025 In Person Catch Up",
|
||||||
"description": "Monthly In Person Get Together",
|
"description": "Monthly In Person Get Together",
|
||||||
"location": "Chermside Library",
|
"location": "Chermside Library",
|
||||||
"coordinates": "-27.38621539644283,153.0351689206467",
|
"coordinates": "-27.38621539644283,153.0351689206467"
|
||||||
"ctl": "202507241830"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"start": "2025-07-08T19:00:00",
|
"start": "2025-07-08T19:00:00",
|
||||||
"end": "2025-07-08T21:00",
|
"end": "2025-07-08T21:00",
|
||||||
"title": "July 2025 Online Catch Up",
|
"title": "July 2025 Online Catch Up",
|
||||||
"description": "Monthly Online Jitsi Get Together",
|
"description": "Monthly Online Jitsi Get Together",
|
||||||
"location": "Jitsi",
|
"location": "Jitsi"
|
||||||
"ctl": "202507081900"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"start": "2025-06-19T18:30:00",
|
"start": "2025-06-19T18:30:00",
|
||||||
@@ -22,15 +68,13 @@
|
|||||||
"title": "June 2025 In Person Catch Up",
|
"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.",
|
"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",
|
"location": "Chermside Library",
|
||||||
"coordinates": "-27.38621539644283,153.0351689206467",
|
"coordinates": "-27.38621539644283,153.0351689206467"
|
||||||
"ctl": "202506191830"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"start": "2025-06-10T19:00:00",
|
"start": "2025-06-10T19:00:00",
|
||||||
"end": "2025-06-10T21:00",
|
"end": "2025-06-10T21:00",
|
||||||
"title": "June 2025 Online Catch Up",
|
"title": "June 2025 Online Catch Up",
|
||||||
"description": "Getting started with meshtastic",
|
"description": "Getting started with meshtastic",
|
||||||
"location": "Jitsi",
|
"location": "Jitsi"
|
||||||
"ctl": "202506101900"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
28
lib/main.php
28
lib/main.php
@@ -33,4 +33,32 @@ function getEvents() {
|
|||||||
return($entries);
|
return($entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function putEvents($events) {
|
||||||
|
for ( $i = 0; $i < count($events); $i++ ) {
|
||||||
|
$entry = $events[$i];
|
||||||
|
$dt = new DateTime( $entry["start"] );
|
||||||
|
$start = new DateTime($entry["start"]);
|
||||||
|
$datestamp = $dt -> format("Ymd");
|
||||||
|
$files = array( "agenda" => sprintf("dat/agenda/%d.md", $datestamp)
|
||||||
|
, "minutes" => sprintf("dat/minutes/%d.md", $datestamp)
|
||||||
|
);
|
||||||
|
foreach ( $files as $key => $path ) {
|
||||||
|
if ( in_array($key, array_keys($entry)) ) {
|
||||||
|
$fout = fopen($path, "wt");
|
||||||
|
fwrite($fout, $entry[$key]);
|
||||||
|
fclose($fout);
|
||||||
|
} else {
|
||||||
|
if ( file_exists($path) ) {
|
||||||
|
unlink($path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ( array( "ctl", "hours", "agenda", "minutes" ) as $field ) {
|
||||||
|
unset($events[$i][$field]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$json = json_encode($events, JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT);
|
||||||
|
file_put_contents("dat/events.json", $json);
|
||||||
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
Reference in New Issue
Block a user