Page MenuHomePhabricator

D7374.id16593.diff

D7374.id16593.diff

diff --git a/resources/sql/patches/20131020.col1.sql b/resources/sql/patches/20131020.col1.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/patches/20131020.col1.sql
@@ -0,0 +1,9 @@
+CREATE TABLE {$NAMESPACE}_project.project_column (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ phid VARCHAR(64) NOT NULL COLLATE utf8_bin,
+ name VARCHAR(255) NOT NULL,
+ sequence INT UNSIGNED NOT NULL,
+ projectPHID VARCHAR(64) NOT NULL COLLATE utf8_bin,
+ UNIQUE KEY `key_sequence` (projectPHID, sequence),
+ UNIQUE KEY `key_phid` (phid)
+) ENGINE=InnoDB, COLLATE utf8_general_ci;
diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php
--- a/src/__celerity_resource_map__.php
+++ b/src/__celerity_resource_map__.php
@@ -3966,7 +3966,7 @@
),
'phui-workboard-view-css' =>
array(
- 'uri' => '/res/628679e5/rsrc/css/phui/phui-workboard-view.css',
+ 'uri' => '/res/445c7c7e/rsrc/css/phui/phui-workboard-view.css',
'type' => 'css',
'requires' =>
array(
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1509,6 +1509,9 @@
'PhabricatorPolicyTestObject' => 'applications/policy/__tests__/PhabricatorPolicyTestObject.php',
'PhabricatorPolicyType' => 'applications/policy/constants/PhabricatorPolicyType.php',
'PhabricatorProject' => 'applications/project/storage/PhabricatorProject.php',
+ 'PhabricatorProjectBoardController' => 'applications/project/controller/PhabricatorProjectBoardController.php',
+ 'PhabricatorProjectColumn' => 'applications/project/storage/PhabricatorProjectColumn.php',
+ 'PhabricatorProjectColumnQuery' => 'applications/project/query/PhabricatorProjectColumnQuery.php',
'PhabricatorProjectConstants' => 'applications/project/constants/PhabricatorProjectConstants.php',
'PhabricatorProjectController' => 'applications/project/controller/PhabricatorProjectController.php',
'PhabricatorProjectCreateController' => 'applications/project/controller/PhabricatorProjectCreateController.php',
@@ -1518,6 +1521,7 @@
'PhabricatorProjectListController' => 'applications/project/controller/PhabricatorProjectListController.php',
'PhabricatorProjectMembersEditController' => 'applications/project/controller/PhabricatorProjectMembersEditController.php',
'PhabricatorProjectNameCollisionException' => 'applications/project/exception/PhabricatorProjectNameCollisionException.php',
+ 'PhabricatorProjectPHIDTypeColumn' => 'applications/project/phid/PhabricatorProjectPHIDTypeColumn.php',
'PhabricatorProjectPHIDTypeProject' => 'applications/project/phid/PhabricatorProjectPHIDTypeProject.php',
'PhabricatorProjectProfile' => 'applications/project/storage/PhabricatorProjectProfile.php',
'PhabricatorProjectProfileController' => 'applications/project/controller/PhabricatorProjectProfileController.php',
@@ -3720,6 +3724,13 @@
0 => 'PhabricatorProjectDAO',
1 => 'PhabricatorPolicyInterface',
),
+ 'PhabricatorProjectBoardController' => 'PhabricatorProjectController',
+ 'PhabricatorProjectColumn' =>
+ array(
+ 0 => 'PhabricatorProjectDAO',
+ 1 => 'PhabricatorPolicyInterface',
+ ),
+ 'PhabricatorProjectColumnQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorProjectController' => 'PhabricatorController',
'PhabricatorProjectCreateController' => 'PhabricatorProjectController',
'PhabricatorProjectDAO' => 'PhabricatorLiskDAO',
@@ -3732,6 +3743,7 @@
),
'PhabricatorProjectMembersEditController' => 'PhabricatorProjectController',
'PhabricatorProjectNameCollisionException' => 'Exception',
+ 'PhabricatorProjectPHIDTypeColumn' => 'PhabricatorPHIDType',
'PhabricatorProjectPHIDTypeProject' => 'PhabricatorPHIDType',
'PhabricatorProjectProfile' => 'PhabricatorProjectDAO',
'PhabricatorProjectProfileController' => 'PhabricatorProjectController',
diff --git a/src/applications/maniphest/controller/ManiphestTaskEditController.php b/src/applications/maniphest/controller/ManiphestTaskEditController.php
--- a/src/applications/maniphest/controller/ManiphestTaskEditController.php
+++ b/src/applications/maniphest/controller/ManiphestTaskEditController.php
@@ -570,7 +570,7 @@
->setPreviewURI($this->getApplicationURI('task/descriptionpreview/'));
if ($task->getID()) {
- $page_objects = array( $task->getPHID() );
+ $page_objects = array($task->getPHID());
} else {
$page_objects = array();
}
diff --git a/src/applications/project/application/PhabricatorApplicationProject.php b/src/applications/project/application/PhabricatorApplicationProject.php
--- a/src/applications/project/application/PhabricatorApplicationProject.php
+++ b/src/applications/project/application/PhabricatorApplicationProject.php
@@ -45,6 +45,7 @@
'picture/(?P<id>[1-9]\d*)/' =>
'PhabricatorProjectProfilePictureController',
'create/' => 'PhabricatorProjectCreateController',
+ 'board/(?P<id>[1-9]\d*)/' => 'PhabricatorProjectBoardController',
'update/(?P<id>[1-9]\d*)/(?P<action>[^/]+)/'
=> 'PhabricatorProjectUpdateController',
),
diff --git a/src/applications/project/controller/PhabricatorProjectBoardController.php b/src/applications/project/controller/PhabricatorProjectBoardController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/project/controller/PhabricatorProjectBoardController.php
@@ -0,0 +1,152 @@
+<?php
+
+final class PhabricatorProjectBoardController
+ extends PhabricatorProjectController {
+
+ private $id;
+
+ public function shouldAllowPublic() {
+ return true;
+ }
+
+ public function willProcessRequest(array $data) {
+ $this->id = $data['id'];
+ }
+
+ public function processRequest() {
+ $request = $this->getRequest();
+ $viewer = $request->getUser();
+
+ $project = id(new PhabricatorProjectQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($this->id))
+ ->executeOne();
+ if (!$project) {
+ return new Aphront404Response();
+ }
+
+ $columns = id(new PhabricatorProjectColumnQuery())
+ ->setViewer($viewer)
+ ->withProjectPHIDs(array($project->getPHID()))
+ ->execute();
+
+ // TODO: Completely making this part up.
+ $columns[] = id(new PhabricatorProjectColumn())
+ ->setName('Backlog')
+ ->setPHID(0)
+ ->setSequence(0);
+
+ $columns[] = id(new PhabricatorProjectColumn())
+ ->setName('Assigned')
+ ->setPHID(1)
+ ->setSequence(1);
+
+ $columns[] = id(new PhabricatorProjectColumn())
+ ->setName('In Progress')
+ ->setPHID(2)
+ ->setSequence(2);
+
+ $columns[] = id(new PhabricatorProjectColumn())
+ ->setName('Completed')
+ ->setPHID(3)
+ ->setSequence(3);
+
+ msort($columns, 'getSequence');
+
+ $tasks = id(new ManiphestTaskQuery())
+ ->setViewer($viewer)
+ ->withAllProjects(array($project->getPHID()))
+ ->withStatus(ManiphestTaskQuery::STATUS_OPEN)
+ ->setOrderBy(ManiphestTaskQuery::ORDER_PRIORITY)
+ ->execute();
+ $tasks = mpull($tasks, null, 'getPHID');
+
+ // TODO: This is also made up.
+ $task_map = array();
+ foreach ($tasks as $task) {
+ $task_map[mt_rand(0, 3)][] = $task->getPHID();
+ }
+
+ $board = id(new PHUIWorkboardView())
+ ->setUser($viewer);
+
+ foreach ($columns as $column) {
+ $panel = id(new PHUIWorkpanelView())
+ ->setHeader($column->getName());
+
+ $cards = id(new PHUIObjectItemListView())
+ ->setUser($viewer)
+ ->setCards(true)
+ ->setFlush(true);
+ $task_phids = idx($task_map, $column->getPHID(), array());
+ foreach (array_select_keys($tasks, $task_phids) as $task) {
+ $cards->addItem($this->renderTaskCard($task));
+ }
+ $panel->setCards($cards);
+
+ $board->addPanel($panel);
+ }
+
+ $crumbs = $this->buildApplicationCrumbs();
+
+ $actions = id(new PhabricatorActionListView())
+ ->setUser($viewer)
+ ->addAction(
+ id(new PhabricatorActionView())
+ ->setName(pht('Add Column/Milestone/Sprint'))
+ ->setHref($this->getApplicationURI('board/'.$this->id.'/edit/'))
+ ->setIcon('create'));
+
+ $plist = id(new PHUIPropertyListView());
+ // TODO: Need this to get actions to render.
+ $plist->addProperty(pht('Ignore'), pht('This Property'));
+ $plist->setActionList($actions);
+
+ $header = id(new PHUIObjectBoxView())
+ ->setHeaderText($project->getName())
+ ->addPropertyList($plist);
+
+ $board_box = id(new PHUIBoxView())
+ ->appendChild($board)
+ ->addMargin(PHUI::MARGIN_LARGE);
+
+ return $this->buildApplicationPage(
+ array(
+ $crumbs,
+ $header,
+ $board_box,
+ ),
+ array(
+ 'title' => pht('Board'),
+ 'device' => true,
+ ));
+ }
+
+ private function renderTaskCard(ManiphestTask $task) {
+ $request = $this->getRequest();
+ $viewer = $request->getUser();
+
+ $color_map = ManiphestTaskPriority::getColorMap();
+ $bar_color = idx($color_map, $task->getPriority(), 'grey');
+
+ // TODO: Batch this earlier on.
+ $can_edit = PhabricatorPolicyFilter::hasCapability(
+ $viewer,
+ $task,
+ PhabricatorPolicyCapability::CAN_EDIT);
+
+ return id(new PHUIObjectItemView())
+ ->setObjectName('T'.$task->getID())
+ ->setHeader($task->getTitle())
+ ->setGrippable($can_edit)
+ ->setHref('/T'.$task->getID())
+ ->addAction(
+ id(new PHUIListItemView())
+ ->setName(pht('Edit'))
+ ->setIcon('edit')
+ ->setHref('/maniphest/task/edit/'.$task->getID().'/')
+ ->setWorkflow(true))
+ ->setBarColor($bar_color);
+ }
+
+}
diff --git a/src/applications/project/phid/PhabricatorProjectPHIDTypeColumn.php b/src/applications/project/phid/PhabricatorProjectPHIDTypeColumn.php
new file mode 100644
--- /dev/null
+++ b/src/applications/project/phid/PhabricatorProjectPHIDTypeColumn.php
@@ -0,0 +1,42 @@
+<?php
+
+final class PhabricatorProjectPHIDTypeColumn extends PhabricatorPHIDType {
+
+ const TYPECONST = 'PCOL';
+
+ public function getTypeConstant() {
+ return self::TYPECONST;
+ }
+
+ public function getTypeName() {
+ return pht('Project Column');
+ }
+
+ public function newObject() {
+ return new PhabricatorProjectColumn();
+ }
+
+ public function loadObjects(
+ PhabricatorObjectQuery $query,
+ array $phids) {
+
+ return id(new PhabricatorProjectColumnQuery())
+ ->setViewer($query->getViewer())
+ ->setParentQuery($query)
+ ->withPHIDs($phids)
+ ->execute();
+ }
+
+ public function loadHandles(
+ PhabricatorHandleQuery $query,
+ array $handles,
+ array $objects) {
+
+ foreach ($handles as $phid => $handle) {
+ $column = $objects[$phid];
+
+ $handle->setName($column->getName());
+ }
+ }
+
+}
diff --git a/src/applications/project/query/PhabricatorProjectColumnQuery.php b/src/applications/project/query/PhabricatorProjectColumnQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/project/query/PhabricatorProjectColumnQuery.php
@@ -0,0 +1,95 @@
+<?php
+
+final class PhabricatorProjectColumnQuery
+ extends PhabricatorCursorPagedPolicyAwareQuery {
+
+ private $ids;
+ private $phids;
+ private $projectPHIDs;
+
+ public function withIDs(array $ids) {
+ $this->ids = $ids;
+ return $this;
+ }
+
+ public function withPHIDs(array $phids) {
+ $this->phids = $phids;
+ return $this;
+ }
+
+ public function withProjectPHIDs(array $project_phids) {
+ $this->projectPHIDs = $project_phids;
+ return $this;
+ }
+
+ protected function loadPage() {
+ $table = new PhabricatorProjectColumn();
+ $conn_r = $table->establishConnection('r');
+
+ $data = queryfx_all(
+ $conn_r,
+ 'SELECT * FROM %T %Q %Q %Q',
+ $table->getTableName(),
+ $this->buildWhereClause($conn_r),
+ $this->buildOrderClause($conn_r),
+ $this->buildLimitClause($conn_r));
+
+ return $table->loadAllFromArray($data);
+ }
+
+ protected function willFilterPage(array $page) {
+ $projects = array();
+
+ $project_phids = array_filter(mpull($page, 'getProjectPHID'));
+ if ($project_phids) {
+ $projects = id(new PhabricatorProjectQuery())
+ ->setParentQuery($this)
+ ->setViewer($this->getViewer())
+ ->withPHIDs($project_phids)
+ ->execute();
+ $projects = mpull($projects, null, 'getPHID');
+ }
+
+ foreach ($page as $key => $column) {
+ $phid = $column->getProjectPHID();
+ $project = idx($projects, $phid);
+ if (!$project) {
+ unset($page[$key]);
+ continue;
+ }
+ $column->attachProject($project);
+ }
+
+ return $page;
+ }
+
+ private function buildWhereClause($conn_r) {
+ $where = array();
+
+ if ($this->ids) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'id IN (%Ld)',
+ $this->ids);
+ }
+
+ if ($this->phids) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'phid IN (%Ls)',
+ $this->phids);
+ }
+
+ if ($this->projectPHIDs) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'projectPHID IN (%Ls)',
+ $this->projectPHIDs);
+ }
+
+ $where[] = $this->buildPagingClause($conn_r);
+
+ return $this->formatWhereClause($where);
+ }
+
+}
diff --git a/src/applications/project/storage/PhabricatorProjectColumn.php b/src/applications/project/storage/PhabricatorProjectColumn.php
new file mode 100644
--- /dev/null
+++ b/src/applications/project/storage/PhabricatorProjectColumn.php
@@ -0,0 +1,58 @@
+<?php
+
+final class PhabricatorProjectColumn
+ extends PhabricatorProjectDAO
+ implements PhabricatorPolicyInterface {
+
+ protected $name;
+ protected $projectPHID;
+ protected $sequence;
+
+ private $project = self::ATTACHABLE;
+
+ public function getConfiguration() {
+ return array(
+ self::CONFIG_AUX_PHID => true,
+ ) + parent::getConfiguration();
+ }
+
+ public function generatePHID() {
+ return PhabricatorPHID::generateNewPHID(
+ PhabricatorProjectPHIDTypeColumn::TYPECONST);
+ }
+
+ public function attachProject(PhabricatorProject $project) {
+ $this->project = $project;
+ return $this;
+ }
+
+ public function getProject() {
+ return $this->assertAttached($this->project);
+ }
+
+
+/* -( PhabricatorPolicyInterface )----------------------------------------- */
+
+
+ public function getCapabilities() {
+ return array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ );
+ }
+
+ public function getPolicy($capability) {
+ return $this->getProject()->getPolicy($capability);
+ }
+
+ public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
+ return $this->getProject()->hasAutomaticCapability(
+ $capability,
+ $viewer);
+ }
+
+ public function describeAutomaticCapability($capability) {
+ return pht('Users must be able to see a project to see its board.');
+ }
+
+}
diff --git a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
--- a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
+++ b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
@@ -1684,6 +1684,10 @@
'type' => 'php',
'name' => $this->getPatchPath('20130926.dinline.php'),
),
+ '20131020.col1.sql' => array(
+ 'type' => 'sql',
+ 'name' => $this->getPatchPath('20131020.col1.sql'),
+ ),
);
}
}
diff --git a/src/view/layout/AphrontMultiColumnView.php b/src/view/layout/AphrontMultiColumnView.php
--- a/src/view/layout/AphrontMultiColumnView.php
+++ b/src/view/layout/AphrontMultiColumnView.php
@@ -6,7 +6,7 @@
const GUTTER_MEDIUM = 'mmr';
const GUTTER_LARGE = 'mlr';
- private $column = array();
+ private $columns = array();
private $fluidLayout = false;
private $gutter;
private $shadow;
diff --git a/src/view/phui/PHUIWorkpanelView.php b/src/view/phui/PHUIWorkpanelView.php
--- a/src/view/phui/PHUIWorkpanelView.php
+++ b/src/view/phui/PHUIWorkpanelView.php
@@ -18,6 +18,7 @@
}
public function setHeaderAction($header_action) {
+ // TODO: This doesn't do anything?
$this->headerAction = $header_action;
return $this;
}
diff --git a/webroot/rsrc/css/phui/phui-workboard-view.css b/webroot/rsrc/css/phui/phui-workboard-view.css
--- a/webroot/rsrc/css/phui/phui-workboard-view.css
+++ b/webroot/rsrc/css/phui/phui-workboard-view.css
@@ -9,7 +9,7 @@
.phui-workboard-view-shadow {
padding: 8px;
min-height: 120px;
- overflow-x: scroll;
+ overflow-x: auto;
border-radius: 5px;
background: rgba(150,150,150,.1);
box-shadow: inset 0 0 5px rgba(0,0,0,.5);

File Metadata

Mime Type
text/x-diff
Storage Engine
amazon-s3
Storage Format
Raw Data
Storage Handle
phabricator/el/4z/cvf5x3zl2fuwt2qn
Default Alt Text
D7374.id16593.diff (16 KB)

Event Timeline