From 4ceb28e7efda73e5bc2dd4a384c8018d73e16fd6 Mon Sep 17 00:00:00 2001 From: Peter Howell Date: Thu, 15 Jan 2026 20:02:46 +0000 Subject: [PATCH] k --- index.php | 2 +- js/dir_app.js | 146 ++++++++++++++++++++++++++++++++++++++++++-------- layout.php | 4 +- 3 files changed, 128 insertions(+), 24 deletions(-) diff --git a/index.php b/index.php index c59a1d0..e6b1e07 100644 --- a/index.php +++ b/index.php @@ -3,5 +3,5 @@ $MY_TITLE = "Schedule & Sessions"; $MY_CRUMB = "My Schedule"; $timeslot_config = file_exists('schedule_timeslots.json') ? json_decode(file_get_contents('schedule_timeslots.json'), true) : []; $config_js = ''; -$CONTENT = $config_js . ''; +$CONTENT = ''; include 'layout.php'; diff --git a/js/dir_app.js b/js/dir_app.js index c59c7d3..c675f25 100644 --- a/js/dir_app.js +++ b/js/dir_app.js @@ -872,11 +872,16 @@ const ActivityList = Vue.component('activitylist', { data: function () { return { activities:[], mysessions:[], search:'', sortby:'starttime', reversed:false, my_ses_ids:[], my_host_ids:[], show_filters: 'all', expanded: 1, editing: -1, active:-1, hosts:{}, selectedSlotKey: null, - hosts_by_sesid: {}, options:{}, conference:{}, ay:{}, conf:-1, survey_on:0, zoom_on:1, cancelingIds:[], timeslotConfig:null, } }, + hosts_by_sesid: {}, options:{}, conference:{}, ay:{}, conf:-1, survey_on:0, zoom_on:1, + cancelingIds:[], timeslotConfig:null, expandedDesc:{}, collapsedDays:{}, } }, mounted: function() { this.fetch_myevents() }, methods: { + normalizeId: function(id) { + var parsed = parseInt(id, 10); + return Number.isNaN(parsed) ? id : parsed; + }, special_signup: function(activity_id) { if (activity_id==1462 || activity_id==1455) { return true; @@ -896,12 +901,45 @@ const ActivityList = Vue.component('activitylist', { group.classList.toggle('hidden'); btn.textContent = group.classList.contains('hidden') ? 'Expand Day' : 'Collapse Day'; }, + toggleDaySlots: function(dayKey) { + var isCollapsed = !!this.collapsedDays[dayKey]; + this.$set(this.collapsedDays, dayKey, !isCollapsed); + }, + isDayCollapsed: function(dayKey) { + return !!this.collapsedDays[dayKey]; + }, toggleDescription: function(id) { const para = document.getElementById(id); const btn = document.getElementById(id + '-btn'); para.classList.toggle('line-clamp-2'); btn.textContent = para.classList.contains('line-clamp-2') ? 'Show More' : 'Show Less'; }, + descPlain: function(desc) { + if (!desc) { return ''; } + return String(desc) + .replace(/<[^>]*>/g, ' ') + .replace(/\s+/g, ' ') + .trim(); + }, + descPreview: function(desc) { + var text = this.descPlain(desc); + var limit = 200; + if (text.length <= limit) { return text; } + var slice = text.slice(0, limit + 1); + var cutoff = slice.lastIndexOf(' '); + if (cutoff < 0) { cutoff = limit; } + return text.slice(0, cutoff).trim() + '...'; + }, + descIsTruncated: function(desc) { + return this.descPlain(desc).length > 200; + }, + isDescExpanded: function(id) { + return this.expandedDesc && this.expandedDesc[id]; + }, + toggleDesc: function(id) { + if (!this.expandedDesc) { this.expandedDesc = {}; } + this.$set(this.expandedDesc, id, !this.expandedDesc[id]); + }, slotKeyFromStart: function(starttime) { if (!starttime) { return null; } return this.$root.$dj(starttime).format('YYYY-MM-DDTHH:mm'); @@ -952,7 +990,9 @@ const ActivityList = Vue.component('activitylist', { basic_get('api2.php?query=app', function(r2) { self.mysessions = r2.mysessions - self.my_ses_ids = _.pluck(r2.mysessions, 'id') + self.my_ses_ids = _.map(_.pluck(r2.mysessions, 'id'), function(val) { + return self.normalizeId(val); + }) self.activities = r2.sessions if (r2.host != null) { self.my_host_ids = r2.host } else { self.my_host_ids = [] } @@ -971,20 +1011,35 @@ const ActivityList = Vue.component('activitylist', { }, joinme: function(id) { var self = this + id = self.normalizeId(id) basic_get('dir_api.php?a=signup/' + id, function(r2) { - self.mysessions.push(_.findWhere(self.activities, {'id':id})) - self.my_ses_ids.push(id) + if (!self.my_ses_ids.includes(id)) { self.my_ses_ids.push(id) } + var existing = _.find(self.mysessions, function(s) { + return self.normalizeId(s.id) === id; + }); + if (!existing) { + var activity = _.find(self.activities, function(a) { + return self.normalizeId(a.id) === id; + }); + if (activity) { self.mysessions.push(activity) } + } + self.$forceUpdate() alert_message("Added activity") }) }, dumpme: function(id) { var self = this + id = self.normalizeId(id) if (!self.cancelingIds.includes(id)) { self.cancelingIds.push(id) } basic_get('dir_api.php?a=signdown/' + id, function(r2) { setTimeout(function() { - self.mysessions = _.without( self.mysessions, _.findWhere(self.activities, {'id':id})) - self.my_ses_ids = _.without( self.my_ses_ids, id) + self.mysessions = _.filter(self.mysessions, function(s) { + return self.normalizeId(s.id) !== id; + }); + self.my_ses_ids = _.filter(self.my_ses_ids, function(sid) { + return self.normalizeId(sid) !== id; + }); self.cancelingIds = _.without(self.cancelingIds, id) self.$forceUpdate() alert_message("Removed activity") @@ -1008,6 +1063,18 @@ const ActivityList = Vue.component('activitylist', { }, slotPresets: function(slot) { return slot.presetSessions || []; }, slotHasPreset: function(slot) { return (slot.presetSessions && slot.presetSessions.length>0); }, + canJoin: function(activity) { + if (this.zoom_on !== 1) { return false; } + return activity && (activity.mode === 'online' || activity.mode === 'hybrid'); + }, + canSurvey: function(activity) { + if (this.survey_on !== 1) { return false; } + return !!activity; + }, + hasJoinLink: function(activity) { + if (!activity || !activity.location) { return false; } + return String(activity.location).trim().length > 0; + }, loadTimeslots: function() { var self=this; if (window.TIMESLOT_CONFIG) { @@ -1134,8 +1201,14 @@ const ActivityList = Vue.component('activitylist', {
-

{{ mmyy }} {{ get_day_title(mmyy) }}

-
+
+ +

{{ mmyy }} {{ get_day_title(mmyy) }}

+
+
{{ slot.startLabel }}
@@ -1160,13 +1233,28 @@ const ActivityList = Vue.component('activitylist', {
{{ sel.title }}
- {{ $root.$dj(sel.starttime).format('h:mma') }} · {{ mode_string(sel) }} +
+ {{ $root.$dj(sel.starttime).format('h:mma') }} - {{ addTime(sel.starttime, sel.length) }} · {{ mode_string(sel) }} + · + {{ sel.location_irl }} + (location TBD) + +
+
+ JOIN Online + [missing zoom link] + TAKE Survey + +
-
- +
@@ -1187,15 +1275,28 @@ const ActivityList = Vue.component('activitylist', {
{{ a.title }}
-
{{ mode_string(a) }}
+
- In person at {{ a.location_irl }} or online - In person at {{ a.location_irl }} + In person at {{ a.location_irl }} or online + In person at {{ a.location_irl }} location TBD Online
+
+ + {{ descPreview(a.desc) }} + + + + + + +
-