@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Conpherence - make the calendar have a better calendar looking view up top

Summary: Ref T2400 and M14.

Test Plan: had a few conpherences with various status set amongst participants; views were sensical.

Reviewers: epriestley, chad

Reviewed By: chad

CC: aran, Korvin

Maniphest Tasks: T2400

Differential Revision: https://secure.phabricator.com/D5541

+254 -56
+155 -52
src/applications/conpherence/controller/ConpherenceWidgetController.php
··· 279 279 $user = $this->getRequest()->getUser(); 280 280 281 281 $conpherence = $this->getConpherence(); 282 + $participants = $conpherence->getParticipants(); 282 283 $widget_data = $conpherence->getWidgetData(); 283 284 $statuses = $widget_data['statuses']; 284 285 $handles = $conpherence->getHandles(); 285 286 $content = array(); 287 + $layout = id(new AphrontMultiColumnView()) 288 + ->setFluidLayout(true); 286 289 $timestamps = $this->getCalendarWidgetWeekTimestamps(); 290 + $today = $timestamps['today']; 291 + $weekstamps = $timestamps['weekstamps']; 287 292 $one_day = 24 * 60 * 60; 288 - foreach ($timestamps as $time => $day) { 293 + foreach ($weekstamps as $time => $day) { 289 294 // build a header for the new day 290 - $content[] = id(new PhabricatorHeaderView()) 291 - ->setHeader($day->format('l')) 292 - ->render(); 295 + $content[] = phutil_tag( 296 + 'div', 297 + array( 298 + 'class' => 'day-header' 299 + ), 300 + array( 301 + phutil_tag( 302 + 'div', 303 + array( 304 + 'class' => 'day-name' 305 + ), 306 + $day->format('l')), 307 + phutil_tag( 308 + 'div', 309 + array( 310 + 'class' => 'day-date' 311 + ), 312 + $day->format('m/d/y')) 313 + )); 314 + 315 + $week_day_number = $day->format('w'); 316 + 293 317 294 318 $day->setTime(0, 0, 0); 295 319 $epoch_start = $day->format('U'); 296 - $day->modify('+1 day'); 297 - $epoch_end = $day->format('U'); 320 + $next_day = clone $day; 321 + $next_day->modify('+1 day'); 322 + $epoch_end = $next_day->format('U'); 298 323 324 + $first_status_of_the_day = true; 325 + $statuses_of_the_day = array(); 299 326 // keep looking through statuses where we last left off 300 327 foreach ($statuses as $status) { 301 328 if ($status->getDateFrom() >= $epoch_end) { 302 329 // This list is sorted, so we can stop looking. 303 330 break; 304 331 } 332 + if (!$first_status_of_the_day) { 333 + $content[] = phutil_tag( 334 + 'div', 335 + array( 336 + 'class' => 'divider' 337 + ), 338 + ''); 339 + } 305 340 if ($status->getDateFrom() < $epoch_end && 306 - $status->getDateTo() > $epoch_start) { 307 - $timespan = $status->getDateTo() - $status->getDateFrom(); 308 - if ($timespan > $one_day) { 309 - $time_str = 'm/d'; 310 - } else { 311 - $time_str = 'h:i A'; 312 - } 313 - $epoch_range = phabricator_format_local_time( 314 - $status->getDateFrom(), 341 + $status->getDateTo() > $epoch_start) { 342 + $statuses_of_the_day[$status->getUserPHID()] = $status; 343 + $timespan = $status->getDateTo() - $status->getDateFrom(); 344 + if ($timespan > $one_day) { 345 + $time_str = 'm/d'; 346 + } else { 347 + $time_str = 'h:i A'; 348 + } 349 + $epoch_range = phabricator_format_local_time( 350 + $status->getDateFrom(), 351 + $user, 352 + $time_str) . ' - ' . phabricator_format_local_time( 353 + $status->getDateTo(), 315 354 $user, 316 - $time_str) . ' - ' . phabricator_format_local_time( 317 - $status->getDateTo(), 318 - $user, 319 - $time_str); 355 + $time_str); 320 356 321 - $content[] = phutil_tag( 357 + $content[] = phutil_tag( 358 + 'div', 359 + array( 360 + 'class' => 'user-status '.$status->getTextStatus(), 361 + ), 362 + array( 363 + phutil_tag( 364 + 'div', 365 + array( 366 + 'class' => 'epoch-range' 367 + ), 368 + $epoch_range), 369 + phutil_tag( 370 + 'div', 371 + array( 372 + 'class' => 'icon', 373 + ), 374 + ''), 375 + phutil_tag( 376 + 'div', 377 + array( 378 + 'class' => 'description' 379 + ), 380 + $status->getTerseSummary($user)), 381 + phutil_tag( 382 + 'div', 383 + array( 384 + 'class' => 'participant' 385 + ), 386 + $handles[$status->getUserPHID()]->getName()) 387 + )); 388 + $first_status_of_the_day = false; 389 + } 390 + } 391 + // we didn't get a status on this day so add a spacer 392 + if ($first_status_of_the_day) { 393 + $content[] = phutil_tag( 394 + 'div', 395 + array( 396 + 'class' => 'spacer' 397 + ), 398 + ''); 399 + } 400 + if ($week_day_number > 0 && $week_day_number < 6) { 401 + if ($week_day_number == $today->format('w')) { 402 + $active_class = '-active'; 403 + } else { 404 + $active_class = ''; 405 + } 406 + $inner_layout = array(); 407 + foreach ($participants as $phid => $participant) { 408 + $status = idx($statuses_of_the_day, $phid, false); 409 + if ($status) { 410 + $inner_layout[] = phutil_tag( 322 411 'div', 323 412 array( 324 - 'class' => 'user-status '.$status->getTextStatus(), 413 + 'class' => $status->getTextStatus() 325 414 ), 415 + ''); 416 + } else { 417 + $inner_layout[] = phutil_tag( 418 + 'div', 326 419 array( 327 - phutil_tag( 328 - 'div', 329 - array( 330 - 'class' => 'epoch-range' 331 - ), 332 - $epoch_range), 333 - phutil_tag( 334 - 'div', 335 - array( 336 - 'class' => 'icon', 337 - ), 338 - ''), 339 - phutil_tag( 340 - 'div', 341 - array( 342 - 'class' => 'description' 343 - ), 344 - $status->getTerseSummary($user)), 345 - phutil_tag( 346 - 'div', 347 - array( 348 - 'class' => 'participant' 349 - ), 350 - $handles[$status->getUserPHID()]->getName()) 351 - )); 420 + 'class' => 'present' 421 + ), 422 + ''); 352 423 } 424 + } 425 + $layout->addColumn( 426 + phutil_tag( 427 + 'div', 428 + array( 429 + 'class' => 'day-column'.$active_class 430 + ), 431 + array( 432 + phutil_tag( 433 + 'div', 434 + array( 435 + 'class' => 'day-name' 436 + ), 437 + $day->format('D')), 438 + phutil_tag( 439 + 'div', 440 + array( 441 + 'class' => 'day-number', 442 + ), 443 + $day->format('j')), 444 + $inner_layout 445 + ))); 353 446 } 354 447 } 355 448 356 - return new PhutilSafeHTML(implode('', $content)); 449 + return 450 + array( 451 + $layout, 452 + $content 453 + ); 357 454 } 358 455 359 456 private function getCalendarWidgetWeekTimestamps() { 360 457 $user = $this->getRequest()->getUser(); 361 458 $timezone = new DateTimeZone($user->getTimezoneIdentifier()); 362 459 460 + $today = id(new DateTime('now', $timezone)); 461 + $monday = clone $today; 462 + $monday 463 + ->modify('+1 day') 464 + ->modify('last monday'); 363 465 $timestamps = array(); 364 466 for ($day = 0; $day < 7; $day++) { 365 - $timestamps[] = new DateTime( 366 - sprintf('today +%d days', $day), 367 - $timezone 368 - ); 467 + $timestamp = clone $monday; 468 + $timestamps[] = $timestamp->modify(sprintf('+%d days', $day)); 369 469 } 370 470 371 - return $timestamps; 471 + return array( 472 + 'today' => $today, 473 + 'weekstamps' => $timestamps 474 + ); 372 475 } 373 476 374 477 private function getWidgetURI() {
+2 -2
src/applications/conpherence/query/ConpherenceThreadQuery.php
··· 173 173 // statuses of everyone currently in the conpherence 174 174 // for a rolling one week window 175 175 $start_of_week = phabricator_format_local_time( 176 - strtotime('today'), 176 + strtotime('last monday', strtotime('tomorrow')), 177 177 $this->getViewer(), 178 178 'U'); 179 179 $end_of_week = phabricator_format_local_time( 180 - strtotime('midnight +1 week'), 180 + strtotime('last monday +1 week', strtotime('tomorrow')), 181 181 $this->getViewer(), 182 182 'U'); 183 183 $statuses = id(new PhabricatorUserStatus())
+97 -2
webroot/rsrc/css/application/conpherence/widget-pane.css
··· 133 133 margin: 8px 0px 0px 50px; 134 134 border: 1px dashed #bfbfbf; 135 135 } 136 + 136 137 /* calendar widget */ 137 138 139 + .conpherence-widget-pane #widgets-calendar .aphront-multi-column-view { 140 + margin: 2px 0px 0px 0px; 141 + width: 280px; 142 + } 143 + .conpherence-widget-pane #widgets-calendar .aphront-multi-column-view 144 + .aphront-multi-column-column { 145 + background: white; 146 + border-right: 1px solid #bfbfbf; 147 + text-align: center; 148 + } 149 + .conpherence-widget-pane #widgets-calendar .aphront-multi-column-view 150 + .aphront-multi-column-column-last { 151 + border-right: 0; 152 + } 153 + .conpherence-widget-pane #widgets-calendar .aphront-multi-column-view 154 + .aphront-multi-column-column .day-column, 155 + .conpherence-widget-pane #widgets-calendar .aphront-multi-column-view 156 + .aphront-multi-column-column .day-column-active { 157 + color: #bfbfbf; 158 + background-color: white; 159 + font-weight: bold; 160 + padding: 0px 0px 10px 0px; 161 + } 162 + .conpherence-widget-pane #widgets-calendar .aphront-multi-column-view 163 + .aphront-multi-column-column .day-column-active { 164 + color: black; 165 + } 166 + .conpherence-widget-pane #widgets-calendar .aphront-multi-column-view 167 + .aphront-multi-column-column .present , 168 + .conpherence-widget-pane #widgets-calendar .aphront-multi-column-view 169 + .aphront-multi-column-column .sporadic , 170 + .conpherence-widget-pane #widgets-calendar .aphront-multi-column-view 171 + .aphront-multi-column-column .away { 172 + height: 10px; 173 + margin: 5px 0px 5px 0px; 174 + width: 100%; 175 + } 176 + .conpherence-widget-pane #widgets-calendar .aphront-multi-column-view 177 + .aphront-multi-column-column .present { 178 + background-color: white; 179 + } 180 + .conpherence-widget-pane #widgets-calendar .aphront-multi-column-view 181 + .aphront-multi-column-column .sporadic { 182 + background-color: rgb(222, 226, 232); 183 + } 184 + .conpherence-widget-pane #widgets-calendar .aphront-multi-column-view 185 + .aphront-multi-column-column .away { 186 + background-color: rgb(102, 204, 255); 187 + } 188 + .conpherence-widget-pane #widgets-calendar .aphront-multi-column-view 189 + .aphront-multi-column-column .day-name { 190 + padding: 5px 0px 0px 0px; 191 + font-size: 12px; 192 + } 193 + .conpherence-widget-pane #widgets-calendar .aphront-multi-column-view 194 + .aphront-multi-column-column .day-number { 195 + font-size: 16px; 196 + padding: 5px 0px 5px 0px; 197 + } 198 + .conpherence-widget-pane #widgets-calendar .day-header { 199 + float: left; 200 + clear: both; 201 + background-color: #d8dce2; 202 + border-top: 1px solid #bfbfbf; 203 + border-bottom: 1px solid #bfbfbf; 204 + padding: 5px 10px 5px 10px; 205 + width: 260px; 206 + } 207 + .conpherence-widget-pane #widgets-calendar .day-header .day-name { 208 + float: left; 209 + clear: none; 210 + } 211 + .conpherence-widget-pane #widgets-calendar .day-header .day-date { 212 + float: right; 213 + clear: none; 214 + } 215 + 216 + .conpherence-widget-pane #widgets-calendar .divider { 217 + float: left; 218 + clear: both; 219 + width: 260px; 220 + margin: 0px 0px 0px 10px; 221 + border: 1px dashed #bfbfbf; 222 + } 223 + .conpherence-widget-pane #widgets-calendar .spacer { 224 + float: left; 225 + clear: both; 226 + height: 10px; 227 + width: 100%; 228 + } 229 + 138 230 .conpherence-widget-pane #widgets-calendar .user-status { 231 + float: left; 232 + clear: both; 139 233 height: 60px; 234 + width: 280px; 140 235 } 141 236 142 237 .conpherence-widget-pane #widgets-calendar .user-status .icon { 143 238 border-radius: 10px; 144 239 position: relative; 145 240 top: 24px; 146 - left: 12px; 241 + left: 10px; 147 242 height: 16px; 148 243 width: 16px; 149 244 box-shadow: 0px 0px 1px #000; ··· 162 257 font-style: italic; 163 258 position: relative; 164 259 top: 24px; 165 - right: 8px; 260 + right: 10px; 166 261 font-size: 11px; 167 262 } 168 263