Diff -- /var/www/vhosts/3dshawn.com/affiliate.3dshawn.com/calendar.cgi
Diff

/var/www/vhosts/3dshawn.com/affiliate.3dshawn.com/calendar.cgi

added on local at 2026-07-01 13:47:17

Added
+209
lines
Removed
-0
lines
Context
0
unchanged
Blobs
from
to 25b78fc7f87a
Restore this content →
Unified diff
Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.
1#!/usr/bin/perl
2#======================================================================
3# AffSoft - User calendar (personal scheduling)
4#======================================================================
5use strict; use warnings;
6use lib '/var/www/vhosts/3dshawn.com/affiliate.3dshawn.com';
7use CGI;
8use Time::Local;
9use JSON::PP qw(encode_json);
10use MODS::Template;
11use MODS::DBConnect;
12use MODS::Login;
13use MODS::AffSoft::Config;
14use MODS::AffSoft::Wrapper;
15
16my $q = CGI->new;
17my $form = $q->Vars;
18my $auth = MODS::Login->new;
19my $wrap = MODS::AffSoft::Wrapper->new;
20my $tfile = MODS::Template->new;
21my $db = MODS::DBConnect->new;
22my $cfg = MODS::AffSoft::Config->new;
23my $DB = $cfg->settings('database_name');
24
25my $userinfo = $auth->login_verify();
26if (!$userinfo) { print "Status: 302 Found\nLocation: /login.cgi\n\n"; exit; }
27my $uid = $userinfo->{user_id} || 0;
28$uid =~ s/[^0-9]//g;
29
30my $dbh = $db->db_connect();
31
32# ----- POST: create or delete events -----
33if (($ENV{REQUEST_METHOD} || '') eq 'POST') {
34 my $act = $form->{act} || '';
35 if ($act eq 'create') {
36 my $title = $form->{title} || '';
37 $title =~ s/^\s+|\s+$//g;
38 $title = substr($title, 0, 280);
39 my $kind = $form->{kind} || '';
40 $kind = '' unless $kind =~ /^[a-z_]{1,40}$/;
41 my $date = $form->{event_date} || '';
42 $date = '' unless $date =~ /^\d{4}-\d{2}-\d{2}$/;
43 my $notes = $form->{notes} || '';
44 $notes = substr($notes, 0, 1000);
45 if (length($title) && length($date)) {
46 my $t_sql = $title; $t_sql =~ s/'/\\'/g;
47 my $n_sql = $notes; $n_sql =~ s/'/\\'/g;
48 $db->db_readwrite($dbh, qq~
49 INSERT INTO `${DB}`.calendar_events
50 SET user_id='$uid', event_date='$date',
51 title='$t_sql', kind='$kind', notes='$n_sql'
52 ~, $ENV{SCRIPT_NAME}, __LINE__);
53 }
54 } elsif ($act eq 'delete') {
55 my $eid = $form->{event_id} || 0;
56 $eid =~ s/[^0-9]//g;
57 if ($eid) {
58 $db->db_readwrite($dbh, qq~
59 DELETE FROM `${DB}`.calendar_events WHERE id='$eid' AND user_id='$uid'
60 ~, $ENV{SCRIPT_NAME}, __LINE__);
61 }
62 }
63 my $back = $form->{back} || '/calendar.cgi';
64 print "Status: 302 Found\nLocation: $back\n\n"; exit;
65}
66
67# ----- Month nav -----
68my @now = localtime(time);
69my $y = $form->{y} || ($now[5] + 1900); $y += 0; $y = 2026 if $y < 1970 || $y > 9999;
70my $m = $form->{m} || ($now[4] + 1); $m += 0; $m = 1 if $m < 1 || $m > 12;
71
72my $first = sprintf("%04d-%02d-01", $y, $m);
73my $next_t = timegm(0,0,12, 1, $m-1, $y-1900) + 32*86400;
74my @nx = gmtime($next_t);
75my ($ny, $nm) = ($nx[5]+1900, $nx[4]+1);
76my $next_first = sprintf("%04d-%02d-01", $ny, $nm);
77
78my $prev_t = timegm(0,0,12, 1, $m-1, $y-1900) - 2*86400;
79my @pv = gmtime($prev_t);
80my ($py, $pm) = ($pv[5]+1900, $pv[4]+1);
81
82my $raw_scope = $form->{scope} || 'me';
83$raw_scope = 'me' unless $raw_scope eq 'me' || $raw_scope eq 'my_team' || $raw_scope eq 'division' || $raw_scope eq 'team';
84my $is_admin = ($userinfo->{is_admin} || $userinfo->{is_super_admin}) ? 1 : 0;
85$raw_scope = 'me' if $raw_scope eq 'team' && !$is_admin;
86my $user_team_id = 0;
87{
88 my $dbh_t = $db->db_connect();
89 my $r = $db->db_readwrite($dbh_t, qq~SELECT team_id FROM `${DB}`.users WHERE id='$uid' LIMIT 1~, $ENV{SCRIPT_NAME}, __LINE__);
90 $user_team_id = $r && $r->{team_id} ? $r->{team_id} + 0 : 0;
91 $db->db_disconnect($dbh_t);
92}
93my $has_my_team = $user_team_id ? 1 : 0;
94$raw_scope = 'me' if $raw_scope eq 'my_team' && !$has_my_team;
95my @div_team_ids = ($user_team_id);
96my $has_division = 0;
97if ($user_team_id) {
98 my $dbh_div = $db->db_connect();
99 my @frontier = ($user_team_id);
100 my %seen; $seen{$user_team_id} = 1;
101 for (my $i=0; $i<5; $i++) {
102 last unless @frontier;
103 my $in = join(',', map { "'$_'" } @frontier);
104 my @kids = $db->db_readwrite_multiple($dbh_div, qq~SELECT id FROM `${DB}`.teams WHERE parent_team_id IN ($in)~, $ENV{SCRIPT_NAME}, __LINE__);
105 @frontier = ();
106 foreach my $k (@kids) { next if $seen{$k->{id}}; $seen{$k->{id}}=1; push @frontier, $k->{id}; }
107 }
108 @div_team_ids = keys %seen;
109 $has_division = (scalar(@div_team_ids) > 1) ? 1 : 0; # only show chip if cascade adds something
110 $db->db_disconnect($dbh_div);
111}
112$raw_scope = 'me' if $raw_scope eq 'division' && !$has_division;
113my $scope = $raw_scope;
114
115my $div_in = scalar(@div_team_ids) ? join(',', map { "'$_'" } @div_team_ids) : "''";
116# ----- Fetch events -----
117my @events = $db->db_readwrite_multiple($dbh, qq~
118 SELECT id, event_date, title, kind, notes, color
119 FROM `${DB}`.calendar_events
120 WHERE (
121 CASE WHEN '$scope'='team' THEN
122 user_id IN (SELECT id FROM `${DB}`.users WHERE is_admin=1)
123 WHEN '$scope'='my_team' THEN
124 user_id IN (SELECT id FROM `${DB}`.users WHERE team_id='$user_team_id')
125 WHEN '$scope'='division' THEN
126 user_id IN (SELECT id FROM `${DB}`.users WHERE team_id IN ($div_in))
127 ELSE user_id='$uid' END
128 ) AND event_date BETWEEN '$first' AND '$next_first'
129 ORDER BY event_date ASC, id ASC
130~, $ENV{SCRIPT_NAME}, __LINE__);
131
132$db->db_disconnect($dbh);
133
134my %events_by_day;
135foreach my $e (@events) {
136 $e->{title} = _h($e->{title});
137 $e->{kind} = _h($e->{kind} || '');
138 $e->{color} ||= '#5aa9ff';
139 push @{$events_by_day{$e->{event_date}}}, $e;
140}
141
142# ----- Build grid -----
143my $first_t = timegm(0,0,12, 1, $m-1, $y-1900);
144my @ft = gmtime($first_t);
145my $dow_first = $ft[6];
146my $grid_start = $first_t - $dow_first * 86400;
147
148my @cells;
149my %cells_data;
150my $today = sprintf("%04d-%02d-%02d", $now[5]+1900, $now[4]+1, $now[3]);
151my $month_label = ('January','February','March','April','May','June','July','August','September','October','November','December')[$m-1];
152my $cur_d = $grid_start;
153for (my $i=0; $i<42; $i++) {
154 my @x = gmtime($cur_d);
155 my $d_str = sprintf("%04d-%02d-%02d", $x[5]+1900, $x[4]+1, $x[3]);
156 my $in_month = ($x[4]+1 == $m) ? 1 : 0;
157 my $is_today = ($d_str eq $today) ? 1 : 0;
158 my $is_weekend = ($x[6] == 0 || $x[6] == 6) ? 1 : 0;
159 my $evts = $events_by_day{$d_str} || [];
160 my @top = @$evts > 2 ? @{$evts}[0..1] : @$evts;
161 my $more = @$evts > 2 ? scalar(@$evts) - 2 : 0;
162 push @cells, {
163 d_str => $d_str,
164 day_num => $x[3],
165 in_month => $in_month,
166 is_today => $is_today,
167 is_weekend => $is_weekend,
168 events_top => \@top,
169 more_count => $more,
170 has_events => scalar(@$evts) ? 1 : 0,
171 };
172 $cells_data{$d_str} = { events => $evts };
173 $cur_d += 86400;
174}
175
176my $cells_json = encode_json(\%cells_data);
177
178print "Content-Type: text/html; charset=utf-8\nCache-Control: no-store\n\n";
179my $tvars = {
180 scope => $scope,
181 scope_me => ($scope eq 'me') ? 1 : 0,
182 scope_team => ($scope eq 'team') ? 1 : 0,
183 scope_my_team => ($scope eq 'my_team') ? 1 : 0,
184 has_my_team => $has_my_team,
185 scope_division => ($scope eq 'division') ? 1 : 0,
186 has_division => $has_division,
187 is_admin => $is_admin,
188 y => $y, m => $m, month_label => $month_label,
189 py => $py, pm => $pm, ny => $ny, nm => $nm,
190 cells => \@cells,
191 cells_json => $cells_json,
192};
193my $body = join('', $tfile->template('affsoft_calendar.html', $tvars, $userinfo));
194$wrap->render({
195 userinfo => $userinfo,
196 page_key => 'calendar',
197 title => 'Calendar',
198 body => $body,
199});
200
201sub _h {
202 my $s = shift;
203 return '' unless defined $s;
204 $s =~ s/&/&amp;/g;
205 $s =~ s/</&lt;/g;
206 $s =~ s/>/&gt;/g;
207 $s =~ s/"/&quot;/g;
208 return $s;
209}
Keyboard: j next diff k previous diff g top G bottom r restore c compile-check ? help