mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-28 16:30:59 +01:00
Workboards
Summary: Adds Workboards and workpanels. This is a preliminary diff, I'm still working on mobile and tablet and a few missing features (header actions) Test Plan: FF, Chrome, iOS, iPad, iPhone, IE Reviewers: epriestley Reviewed By: epriestley CC: aran, Korvin Differential Revision: https://secure.phabricator.com/D5455
This commit is contained in:
parent
c3c88fd40c
commit
0bcc76151e
8 changed files with 470 additions and 0 deletions
|
@ -595,6 +595,13 @@ celerity_register_resource_map(array(
|
|||
'disk' => '/rsrc/image/texture/grip.png',
|
||||
'type' => 'png',
|
||||
),
|
||||
'/rsrc/image/texture/panel-header-gradient.png' =>
|
||||
array(
|
||||
'hash' => 'ad9204dd3ef5b12b645d80677d8ccead',
|
||||
'uri' => '/res/ad9204dd/rsrc/image/texture/panel-header-gradient.png',
|
||||
'disk' => '/rsrc/image/texture/panel-header-gradient.png',
|
||||
'type' => 'png',
|
||||
),
|
||||
'/rsrc/image/texture/pholio-background.gif' =>
|
||||
array(
|
||||
'hash' => 'cf4561af116edf393dc583e5119fb412',
|
||||
|
@ -3378,6 +3385,24 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/js/application/uiexample/ReactorSendPropertiesExample.js',
|
||||
),
|
||||
'phabricator-workboard-view-css' =>
|
||||
array(
|
||||
'uri' => '/res/98971c26/rsrc/css/layout/phabricator-workboard-view.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/layout/phabricator-workboard-view.css',
|
||||
),
|
||||
'phabricator-workpanel-view-css' =>
|
||||
array(
|
||||
'uri' => '/res/96a4b5cd/rsrc/css/layout/phabricator-workpanel-view.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/layout/phabricator-workpanel-view.css',
|
||||
),
|
||||
'phabricator-zindex-css' =>
|
||||
array(
|
||||
'uri' => '/res/fcbf82ad/rsrc/css/core/z-index.css',
|
||||
|
|
|
@ -1433,6 +1433,8 @@ phutil_register_library_map(array(
|
|||
'PhabricatorUserStatusInvalidEpochException' => 'applications/people/exception/PhabricatorUserStatusInvalidEpochException.php',
|
||||
'PhabricatorUserStatusOverlapException' => 'applications/people/exception/PhabricatorUserStatusOverlapException.php',
|
||||
'PhabricatorUserTestCase' => 'applications/people/storage/__tests__/PhabricatorUserTestCase.php',
|
||||
'PhabricatorWorkboardExample' => 'applications/uiexample/examples/PhabricatorWorkboardExample.php',
|
||||
'PhabricatorWorkboardView' => 'view/layout/PhabricatorWorkboardView.php',
|
||||
'PhabricatorWorker' => 'infrastructure/daemon/workers/PhabricatorWorker.php',
|
||||
'PhabricatorWorkerActiveTask' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerActiveTask.php',
|
||||
'PhabricatorWorkerArchiveTask' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerArchiveTask.php',
|
||||
|
@ -1444,6 +1446,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorWorkerTaskDetailController' => 'applications/daemon/controller/PhabricatorWorkerTaskDetailController.php',
|
||||
'PhabricatorWorkerTaskUpdateController' => 'applications/daemon/controller/PhabricatorWorkerTaskUpdateController.php',
|
||||
'PhabricatorWorkerTestCase' => 'infrastructure/daemon/workers/__tests__/PhabricatorWorkerTestCase.php',
|
||||
'PhabricatorWorkpanelView' => 'view/layout/PhabricatorWorkpanelView.php',
|
||||
'PhabricatorXHPASTViewController' => 'applications/phpast/controller/PhabricatorXHPASTViewController.php',
|
||||
'PhabricatorXHPASTViewDAO' => 'applications/phpast/storage/PhabricatorXHPASTViewDAO.php',
|
||||
'PhabricatorXHPASTViewFrameController' => 'applications/phpast/controller/PhabricatorXHPASTViewFrameController.php',
|
||||
|
@ -3077,6 +3080,8 @@ phutil_register_library_map(array(
|
|||
'PhabricatorUserStatusInvalidEpochException' => 'Exception',
|
||||
'PhabricatorUserStatusOverlapException' => 'Exception',
|
||||
'PhabricatorUserTestCase' => 'PhabricatorTestCase',
|
||||
'PhabricatorWorkboardExample' => 'PhabricatorUIExample',
|
||||
'PhabricatorWorkboardView' => 'AphrontView',
|
||||
'PhabricatorWorkerActiveTask' => 'PhabricatorWorkerTask',
|
||||
'PhabricatorWorkerArchiveTask' => 'PhabricatorWorkerTask',
|
||||
'PhabricatorWorkerDAO' => 'PhabricatorLiskDAO',
|
||||
|
@ -3087,6 +3092,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorWorkerTaskDetailController' => 'PhabricatorDaemonController',
|
||||
'PhabricatorWorkerTaskUpdateController' => 'PhabricatorDaemonController',
|
||||
'PhabricatorWorkerTestCase' => 'PhabricatorTestCase',
|
||||
'PhabricatorWorkpanelView' => 'AphrontView',
|
||||
'PhabricatorXHPASTViewController' => 'PhabricatorController',
|
||||
'PhabricatorXHPASTViewDAO' => 'PhabricatorLiskDAO',
|
||||
'PhabricatorXHPASTViewFrameController' => 'PhabricatorXHPASTViewController',
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorWorkboardExample extends PhabricatorUIExample {
|
||||
|
||||
public function getName() {
|
||||
return 'Workboard';
|
||||
}
|
||||
|
||||
public function getDescription() {
|
||||
return 'A board for visualizing work. Fixed and Fluid layouts.';
|
||||
}
|
||||
|
||||
public function renderExample() {
|
||||
|
||||
/* List 1 */
|
||||
|
||||
$list = new PhabricatorObjectItemListView();
|
||||
$list->setCards(true);
|
||||
$list->setFlush(true);
|
||||
|
||||
$list->addItem(
|
||||
id(new PhabricatorObjectItemView())
|
||||
->setHeader(pht('Business Card'))
|
||||
->setBarColor('red'));
|
||||
$list->addItem(
|
||||
id(new PhabricatorObjectItemView())
|
||||
->setHeader(pht('Playing Card'))
|
||||
->setBarColor('orange'));
|
||||
$list->addItem(
|
||||
id(new PhabricatorObjectItemView())
|
||||
->setHeader(pht('House of Cards'))
|
||||
->setBarColor('yellow'));
|
||||
$list->addItem(
|
||||
id(new PhabricatorObjectItemView())
|
||||
->setHeader(pht('Cardigan'))
|
||||
->setBarColor('green'));
|
||||
$list->addItem(
|
||||
id(new PhabricatorObjectItemView())
|
||||
->setHeader(pht('Cardamom'))
|
||||
->addFootIcon('highlight-white', 'Spice')
|
||||
->setBarColor('blue'));
|
||||
|
||||
/* List 2 */
|
||||
|
||||
$list2 = new PhabricatorObjectItemListView();
|
||||
$list2->setCards(true);
|
||||
$list2->setFlush(true);
|
||||
|
||||
$list2->addItem(
|
||||
id(new PhabricatorObjectItemView())
|
||||
->setHeader(pht('Business Card'))
|
||||
->setBarColor('red'));
|
||||
$list2->addItem(
|
||||
id(new PhabricatorObjectItemView())
|
||||
->setHeader(pht('Playing Card'))
|
||||
->setBarColor('orange'));
|
||||
|
||||
/* List 3 */
|
||||
|
||||
$list3 = new PhabricatorObjectItemListView();
|
||||
$list3->setCards(true);
|
||||
$list3->setFlush(true);
|
||||
|
||||
$list3->addItem(
|
||||
id(new PhabricatorObjectItemView())
|
||||
->setHeader(pht('Business Card'))
|
||||
->setBarColor('red'));
|
||||
$list3->addItem(
|
||||
id(new PhabricatorObjectItemView())
|
||||
->setHeader(pht('Playing Card'))
|
||||
->setBarColor('orange'));
|
||||
$list3->addItem(
|
||||
id(new PhabricatorObjectItemView())
|
||||
->setHeader(pht('House of Cards'))
|
||||
->setBarColor('yellow'));
|
||||
$list3->addItem(
|
||||
id(new PhabricatorObjectItemView())
|
||||
->setHeader(pht('Cardigan'))
|
||||
->setBarColor('green'));
|
||||
$list3->addItem(
|
||||
id(new PhabricatorObjectItemView())
|
||||
->setHeader(pht('Cardamom'))
|
||||
->addFootIcon('highlight-white', 'Spice')
|
||||
->setBarColor('blue'));
|
||||
$list3->addItem(
|
||||
id(new PhabricatorObjectItemView())
|
||||
->setHeader(pht('Business Card'))
|
||||
->setBarColor('red'));
|
||||
$list3->addItem(
|
||||
id(new PhabricatorObjectItemView())
|
||||
->setHeader(pht('Playing Card'))
|
||||
->setBarColor('orange'));
|
||||
$list3->addItem(
|
||||
id(new PhabricatorObjectItemView())
|
||||
->setHeader(pht('Business Card'))
|
||||
->setBarColor('red'));
|
||||
$list3->addItem(
|
||||
id(new PhabricatorObjectItemView())
|
||||
->setHeader(pht('Playing Card'))
|
||||
->setBarColor('orange'));
|
||||
|
||||
$panel = id(new PhabricatorWorkpanelView)
|
||||
->setCards($list)
|
||||
->setHeader('Business Stuff');
|
||||
|
||||
$panel2 = id(new PhabricatorWorkpanelView)
|
||||
->setCards($list2)
|
||||
->setHeader('Under Duress');
|
||||
|
||||
$panel3 = id(new PhabricatorWorkpanelView)
|
||||
->setCards($list3)
|
||||
->setHeader('Spicy Thai Chicken');
|
||||
|
||||
$board = id(new PhabricatorWorkboardView)
|
||||
->addPanel($panel)
|
||||
->addPanel($panel2)
|
||||
->addPanel($panel2)
|
||||
->addPanel($panel3);
|
||||
|
||||
$board2 = id(new PhabricatorWorkboardView)
|
||||
->setFlexLayout(true)
|
||||
->addPanel($panel)
|
||||
->addPanel($panel2)
|
||||
->addPanel($panel2)
|
||||
->addPanel($panel2)
|
||||
->addPanel($panel2)
|
||||
->addPanel($panel3);
|
||||
|
||||
$head1 = id(new PhabricatorHeaderView())
|
||||
->setHeader(pht('Fixed Panel'));
|
||||
|
||||
$head2 = id(new PhabricatorHeaderView())
|
||||
->setHeader(pht('Fluid Panel'));
|
||||
|
||||
|
||||
$wrap1 = phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'ml'
|
||||
),
|
||||
$board);
|
||||
|
||||
$wrap2 = phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'ml'
|
||||
),
|
||||
$board2);
|
||||
|
||||
return phutil_tag(
|
||||
'div',
|
||||
array(),
|
||||
array(
|
||||
$head1,
|
||||
$wrap1,
|
||||
$head2,
|
||||
$wrap2
|
||||
));
|
||||
}
|
||||
}
|
54
src/view/layout/PhabricatorWorkboardView.php
Normal file
54
src/view/layout/PhabricatorWorkboardView.php
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorWorkboardView extends AphrontView {
|
||||
|
||||
private $panels = array();
|
||||
private $flexLayout = false;
|
||||
|
||||
public function addPanel(PhabricatorWorkpanelView $panel) {
|
||||
$this->panels[] = $panel;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setFlexLayout($layout) {
|
||||
$this->flexLayout = $layout;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
require_celerity_resource('phabricator-workboard-view-css');
|
||||
|
||||
$classes = array();
|
||||
$classes[] = 'phabricator-workboard-view-inner';
|
||||
|
||||
if (count($this->panels) > 6) {
|
||||
throw new Exception("No more than 6 panels per workboard.");
|
||||
}
|
||||
|
||||
$classes[] = 'workboard-'.count($this->panels).'-up';
|
||||
|
||||
$view = phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => implode(' ', $classes),
|
||||
),
|
||||
array(
|
||||
$this->panels,
|
||||
));
|
||||
|
||||
$classes = array();
|
||||
$classes[] = 'phabricator-workboard-view-outer';
|
||||
if ($this->flexLayout) {
|
||||
$classes[] = 'phabricator-workboard-flex';
|
||||
} else {
|
||||
$classes[] = 'phabricator-workboard-fixed';
|
||||
}
|
||||
|
||||
return phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => implode(' ', $classes)
|
||||
),
|
||||
$view);
|
||||
}
|
||||
}
|
78
src/view/layout/PhabricatorWorkpanelView.php
Normal file
78
src/view/layout/PhabricatorWorkpanelView.php
Normal file
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorWorkpanelView extends AphrontView {
|
||||
|
||||
private $cards = array();
|
||||
private $header;
|
||||
private $headerAction;
|
||||
private $footerAction;
|
||||
|
||||
public function setCards(PhabricatorObjectItemListView $cards) {
|
||||
$this->cards[] = $cards;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setHeader($header) {
|
||||
$this->header = $header;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setHeaderAction($header_action) {
|
||||
$this->headerAction = $header_action;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setFooterAction($footer_action) {
|
||||
$this->footerAction = $footer_action;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
require_celerity_resource('phabricator-workpanel-view-css');
|
||||
|
||||
$footer = '';
|
||||
if ($this->footerAction) {
|
||||
$action = $this->footerAction;
|
||||
$footer = javelin_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $action->getHref(),
|
||||
'class' => 'phabricator-workpanel-footer-action',
|
||||
'sigil' => $action->getWorkflow() ? 'workflow' : null,
|
||||
),
|
||||
$action->getName());
|
||||
}
|
||||
|
||||
$header = phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'phabricator-workpanel-header'
|
||||
),
|
||||
$this->header);
|
||||
|
||||
$body = phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'phabricator-workpanel-body'
|
||||
),
|
||||
$this->cards);
|
||||
|
||||
$view = phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'phabricator-workpanel-view-inner',
|
||||
),
|
||||
array(
|
||||
$header,
|
||||
$body,
|
||||
$footer,
|
||||
));
|
||||
|
||||
return phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'phabricator-workpanel-view'
|
||||
),
|
||||
$view);
|
||||
}
|
||||
}
|
54
webroot/rsrc/css/layout/phabricator-workboard-view.css
Normal file
54
webroot/rsrc/css/layout/phabricator-workboard-view.css
Normal file
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* @provides phabricator-workboard-view-css
|
||||
*/
|
||||
|
||||
.phabricator-workboard-view-outer {
|
||||
padding: 8px;
|
||||
overflow-x: scroll;
|
||||
border-radius: 5px;
|
||||
background: rgba(150,150,150,.1);
|
||||
box-shadow: inset 0 0 5px rgba(0,0,0,.5);
|
||||
}
|
||||
|
||||
.device-phone .phabricator-workboard-view-outer {
|
||||
background: none;
|
||||
box-shadow: none;
|
||||
padding: 0;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* math here is based on panel width and margins */
|
||||
.phabricator-workboard-fixed
|
||||
.phabricator-workboard-view-inner.workboard-1-up {
|
||||
width: 310px;
|
||||
}
|
||||
|
||||
.phabricator-workboard-fixed
|
||||
.phabricator-workboard-view-inner.workboard-2-up {
|
||||
width: 620px;
|
||||
}
|
||||
|
||||
.phabricator-workboard-fixed
|
||||
.phabricator-workboard-view-inner.workboard-3-up {
|
||||
width: 930px;
|
||||
}
|
||||
|
||||
.phabricator-workboard-fixed
|
||||
.phabricator-workboard-view-inner.workboard-4-up {
|
||||
width: 1008px;
|
||||
}
|
||||
|
||||
.phabricator-workboard-fixed
|
||||
.phabricator-workboard-view-inner.workboard-5-up {
|
||||
width: 1250px;
|
||||
}
|
||||
|
||||
.phabricator-workboard-fixed
|
||||
.phabricator-workboard-view-inner.workboard-6-up {
|
||||
width: 1500px;
|
||||
}
|
||||
|
||||
.device-phone .phabricator-workboard-fixed .phabricator-workboard-view-inner {
|
||||
width: 100%;
|
||||
}
|
93
webroot/rsrc/css/layout/phabricator-workpanel-view.css
Normal file
93
webroot/rsrc/css/layout/phabricator-workpanel-view.css
Normal file
|
@ -0,0 +1,93 @@
|
|||
/**
|
||||
* @provides phabricator-workpanel-view-css
|
||||
*/
|
||||
|
||||
.phabricator-workpanel-view {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.phabricator-workpanel-view-inner {
|
||||
margin: 0 10px 0 0;
|
||||
}
|
||||
|
||||
.device-phone .phabricator-workpanel-view-inner {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.phabricator-workboard-flex .phabricator-workpanel-view:last-child
|
||||
.phabricator-workpanel-view-inner {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Panels require a fixed width to overflow well. */
|
||||
.phabricator-workboard-fixed .workboard-1-up .phabricator-workpanel-view,
|
||||
.phabricator-workboard-fixed .workboard-2-up .phabricator-workpanel-view,
|
||||
.phabricator-workboard-fixed .workboard-3-up .phabricator-workpanel-view {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.phabricator-workboard-fixed .workboard-4-up .phabricator-workpanel-view,
|
||||
.phabricator-workboard-fixed .workboard-5-up .phabricator-workpanel-view,
|
||||
.phabricator-workboard-fixed .workboard-6-up .phabricator-workpanel-view {
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
.device-phone .phabricator-workboard-view-outer div.phabricator-workpanel-view {
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.phabricator-workpanel-view .phabricator-workpanel-header {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
border: 1px solid #b3b5b6;
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
padding: 8px 10px;
|
||||
background: #f0f0f0 url(/rsrc/image/texture/panel-header-gradient.png) repeat-x;
|
||||
text-shadow: 0 1px 1px #fff;
|
||||
}
|
||||
|
||||
.phabricator-workpanel-view .phabricator-workpanel-header-action {
|
||||
float: right;
|
||||
width: 24px;
|
||||
border-left: 1px solid #b3b5b6;
|
||||
}
|
||||
|
||||
.phabricator-workpanel-view .phabricator-workpanel-body {
|
||||
background: #c4cde0;
|
||||
padding: 5px 5px 1px 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
box-shadow: inset 0 0px 5px rgba(0,0,0,.4);
|
||||
}
|
||||
|
||||
.phabricator-workpanel-view .phabricator-workpanel-footer {
|
||||
padding: 8px 5px;
|
||||
}
|
||||
|
||||
/* fluid/flex styles */
|
||||
.phabricator-workboard-flex .workboard-1-up .phabricator-workpanel-view {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.phabricator-workboard-flex .workboard-2-up .phabricator-workpanel-view {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.phabricator-workboard-flex .workboard-3-up .phabricator-workpanel-view {
|
||||
width: 33.3333%;
|
||||
}
|
||||
|
||||
.phabricator-workboard-flex .workboard-4-up .phabricator-workpanel-view {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.phabricator-workboard-flex .workboard-5-up .phabricator-workpanel-view {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.phabricator-workboard-flex .workboard-6-up .phabricator-workpanel-view {
|
||||
width: 16.6666%;
|
||||
}
|
BIN
webroot/rsrc/image/texture/panel-header-gradient.png
Normal file
BIN
webroot/rsrc/image/texture/panel-header-gradient.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1 KiB |
Loading…
Reference in a new issue