Page MenuHomePhabricator

D8916.id21163.diff
No OneTemporary

D8916.id21163.diff

diff --git a/resources/sql/autopatches/20140430.dash.2.edge.sql b/resources/sql/autopatches/20140430.dash.2.edge.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20140430.dash.2.edge.sql
@@ -0,0 +1,15 @@
+CREATE TABLE {$NAMESPACE}_dashboard.edge (
+ src VARCHAR(64) NOT NULL COLLATE utf8_bin,
+ type VARCHAR(64) NOT NULL COLLATE utf8_bin,
+ dst VARCHAR(64) NOT NULL COLLATE utf8_bin,
+ dateCreated INT UNSIGNED NOT NULL,
+ seq INT UNSIGNED NOT NULL,
+ dataID INT UNSIGNED,
+ PRIMARY KEY (src, type, dst),
+ KEY (src, type, dateCreated, seq)
+) ENGINE=InnoDB, COLLATE utf8_general_ci;
+
+CREATE TABLE {$NAMESPACE}_dashboard.edgedata (
+ id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ data LONGTEXT NOT NULL COLLATE utf8_bin
+) ENGINE=InnoDB, COLLATE utf8_general_ci;
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
@@ -1432,6 +1432,7 @@
'PhabricatorDaemonReference' => 'infrastructure/daemon/control/PhabricatorDaemonReference.php',
'PhabricatorDaemonTaskGarbageCollector' => 'applications/daemon/garbagecollector/PhabricatorDaemonTaskGarbageCollector.php',
'PhabricatorDashboard' => 'applications/dashboard/storage/PhabricatorDashboard.php',
+ 'PhabricatorDashboardAddPanelController' => 'applications/dashboard/controller/PhabricatorDashboardAddPanelController.php',
'PhabricatorDashboardController' => 'applications/dashboard/controller/PhabricatorDashboardController.php',
'PhabricatorDashboardDAO' => 'applications/dashboard/storage/PhabricatorDashboardDAO.php',
'PhabricatorDashboardEditController' => 'applications/dashboard/controller/PhabricatorDashboardEditController.php',
@@ -4232,6 +4233,7 @@
0 => 'PhabricatorDashboardDAO',
1 => 'PhabricatorPolicyInterface',
),
+ 'PhabricatorDashboardAddPanelController' => 'PhabricatorDashboardController',
'PhabricatorDashboardController' => 'PhabricatorController',
'PhabricatorDashboardDAO' => 'PhabricatorLiskDAO',
'PhabricatorDashboardEditController' => 'PhabricatorDashboardController',
diff --git a/src/applications/dashboard/application/PhabricatorApplicationDashboard.php b/src/applications/dashboard/application/PhabricatorApplicationDashboard.php
--- a/src/applications/dashboard/application/PhabricatorApplicationDashboard.php
+++ b/src/applications/dashboard/application/PhabricatorApplicationDashboard.php
@@ -23,6 +23,7 @@
'view/(?P<id>\d+)/' => 'PhabricatorDashboardViewController',
'create/' => 'PhabricatorDashboardEditController',
'edit/(?:(?P<id>\d+)/)?' => 'PhabricatorDashboardEditController',
+ 'addpanel/(?P<id>\d+)/' => 'PhabricatorDashboardAddPanelController',
'panel/' => array(
'(?:query/(?P<queryKey>[^/]+)/)?'
diff --git a/src/applications/dashboard/controller/PhabricatorDashboardAddPanelController.php b/src/applications/dashboard/controller/PhabricatorDashboardAddPanelController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/dashboard/controller/PhabricatorDashboardAddPanelController.php
@@ -0,0 +1,94 @@
+<?php
+
+final class PhabricatorDashboardAddPanelController
+ extends PhabricatorDashboardController {
+
+ private $id;
+
+ public function willProcessRequest(array $data) {
+ $this->id = idx($data, 'id');
+ }
+
+ public function processRequest() {
+ $request = $this->getRequest();
+ $viewer = $request->getUser();
+
+ $dashboard = id(new PhabricatorDashboardQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($this->id))
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->executeOne();
+ if (!$dashboard) {
+ return new Aphront404Response();
+ }
+
+ $dashboard_uri = $this->getApplicationURI('view/'.$dashboard->getID().'/');
+
+ $v_panel = $request->getStr('panel');
+ $e_panel = true;
+ $errors = array();
+ if ($request->isFormPost()) {
+ if (strlen($v_panel)) {
+ $panel = id(new PhabricatorObjectQuery())
+ ->setViewer($viewer)
+ ->withNames(array($v_panel))
+ ->withTypes(array(PhabricatorDashboardPHIDTypePanel::TYPECONST))
+ ->executeOne();
+ if (!$panel) {
+ $errors[] = pht('No such panel!');
+ $e_panel = pht('Invalid');
+ }
+ } else {
+ $errors[] = pht('Name a panel to add.');
+ $e_panel = pht('Required');
+ }
+
+ if (!$errors) {
+ $xactions = array();
+ $xactions[] = id(new PhabricatorDashboardTransaction())
+ ->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
+ ->setMetadataValue(
+ 'edge:type',
+ PhabricatorEdgeConfig::TYPE_DASHBOARD_HAS_PANEL)
+ ->setNewValue(
+ array(
+ '+' => array(
+ $panel->getPHID() => $panel->getPHID(),
+ ),
+ ));
+
+ $editor = id(new PhabricatorDashboardTransactionEditor())
+ ->setActor($viewer)
+ ->setContentSourceFromRequest($request)
+ ->setContinueOnMissingFields(true)
+ ->setContinueOnNoEffect(true)
+ ->applyTransactions($dashboard, $xactions);
+
+ return id(new AphrontRedirectResponse())->setURI($dashboard_uri);
+ }
+ }
+
+ $form = id(new AphrontFormView())
+ ->setUser($viewer)
+ ->appendRemarkupInstructions(
+ pht('Enter a panel monogram like `W123`.'))
+ ->appendChild(
+ id(new AphrontFormTextControl())
+ ->setName('panel')
+ ->setLabel(pht('Panel'))
+ ->setValue($v_panel)
+ ->setError($e_panel));
+
+ return $this->newDialog()
+ ->setTitle(pht('Add Panel'))
+ ->setErrors($errors)
+ ->appendChild($form->buildLayoutView())
+ ->addCancelButton($dashboard_uri)
+ ->addSubmitButton(pht('Add Panel'));
+ }
+
+}
diff --git a/src/applications/dashboard/controller/PhabricatorDashboardPanelViewController.php b/src/applications/dashboard/controller/PhabricatorDashboardPanelViewController.php
--- a/src/applications/dashboard/controller/PhabricatorDashboardPanelViewController.php
+++ b/src/applications/dashboard/controller/PhabricatorDashboardPanelViewController.php
@@ -124,6 +124,15 @@
pht('Editable By'),
$descriptions[PhabricatorPolicyCapability::CAN_EDIT]);
+ $dashboard_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
+ $panel->getPHID(),
+ PhabricatorEdgeConfig::TYPE_PANEL_HAS_DASHBOARD);
+ $this->loadHandles($dashboard_phids);
+
+ $properties->addProperty(
+ pht('Appears On'),
+ $this->renderHandlesForPHIDs($dashboard_phids));
+
return $properties;
}
diff --git a/src/applications/dashboard/controller/PhabricatorDashboardViewController.php b/src/applications/dashboard/controller/PhabricatorDashboardViewController.php
--- a/src/applications/dashboard/controller/PhabricatorDashboardViewController.php
+++ b/src/applications/dashboard/controller/PhabricatorDashboardViewController.php
@@ -16,6 +16,7 @@
$dashboard = id(new PhabricatorDashboardQuery())
->setViewer($viewer)
->withIDs(array($this->id))
+ ->needPanels(true)
->executeOne();
if (!$dashboard) {
return new Aphront404Response();
@@ -77,6 +78,14 @@
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
+ $actions->addAction(
+ id(new PhabricatorActionView())
+ ->setName(pht('Add Panel'))
+ ->setIcon('new')
+ ->setHref($this->getApplicationURI("addpanel/{$id}/"))
+ ->setDisabled(!$can_edit)
+ ->setWorkflow(true));
+
return $actions;
}
@@ -95,6 +104,13 @@
pht('Editable By'),
$descriptions[PhabricatorPolicyCapability::CAN_EDIT]);
+ $panel_phids = $dashboard->getPanelPHIDs();
+ $this->loadHandles($panel_phids);
+
+ $properties->addProperty(
+ pht('Panels'),
+ $this->renderHandlesForPHIDs($panel_phids));
+
return $properties;
}
diff --git a/src/applications/dashboard/editor/PhabricatorDashboardPanelTransactionEditor.php b/src/applications/dashboard/editor/PhabricatorDashboardPanelTransactionEditor.php
--- a/src/applications/dashboard/editor/PhabricatorDashboardPanelTransactionEditor.php
+++ b/src/applications/dashboard/editor/PhabricatorDashboardPanelTransactionEditor.php
@@ -8,6 +8,7 @@
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
+ $types[] = PhabricatorTransactions::TYPE_EDGE;
$types[] = PhabricatorDashboardPanelTransaction::TYPE_NAME;
diff --git a/src/applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php b/src/applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php
--- a/src/applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php
+++ b/src/applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php
@@ -8,6 +8,7 @@
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
+ $types[] = PhabricatorTransactions::TYPE_EDGE;
$types[] = PhabricatorDashboardTransaction::TYPE_NAME;
@@ -51,6 +52,8 @@
case PhabricatorTransactions::TYPE_EDIT_POLICY:
$object->setEditPolicy($xaction->getNewValue());
return;
+ case PhabricatorTransactions::TYPE_EDGE:
+ return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
@@ -63,6 +66,8 @@
switch ($xaction->getTransactionType()) {
case PhabricatorDashboardTransaction::TYPE_NAME:
return;
+ case PhabricatorTransactions::TYPE_EDGE:
+ return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
diff --git a/src/applications/dashboard/query/PhabricatorDashboardQuery.php b/src/applications/dashboard/query/PhabricatorDashboardQuery.php
--- a/src/applications/dashboard/query/PhabricatorDashboardQuery.php
+++ b/src/applications/dashboard/query/PhabricatorDashboardQuery.php
@@ -6,6 +6,8 @@
private $ids;
private $phids;
+ private $needPanels;
+
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
@@ -16,6 +18,11 @@
return $this;
}
+ public function needPanels($need_panels) {
+ $this->needPanels = $need_panels;
+ return $this;
+ }
+
protected function loadPage() {
$table = new PhabricatorDashboard();
$conn_r = $table->establishConnection('r');
@@ -31,6 +38,41 @@
return $table->loadAllFromArray($data);
}
+ protected function didFilterPage(array $dashboards) {
+ if ($this->needPanels) {
+ $edge_query = id(new PhabricatorEdgeQuery())
+ ->withSourcePHIDs(mpull($dashboards, 'getPHID'))
+ ->withEdgeTypes(
+ array(
+ PhabricatorEdgeConfig::TYPE_DASHBOARD_HAS_PANEL,
+ ));
+ $edge_query->execute();
+
+ $panel_phids = $edge_query->getDestinationPHIDs();
+ if ($panel_phids) {
+ $panels = id(new PhabricatorDashboardPanelQuery())
+ ->setParentQuery($this)
+ ->setViewer($this->getViewer())
+ ->withPHIDs($panel_phids)
+ ->execute();
+ $panels = mpull($panels, null, 'getPHID');
+ } else {
+ $panels = array();
+ }
+
+ foreach ($dashboards as $dashboard) {
+ $dashboard_phids = $edge_query->getDestinationPHIDs(
+ array($dashboard->getPHID()));
+ $dashboard_panels = array_select_keys($panels, $dashboard_phids);
+
+ $dashboard->attachPanelPHIDs($dashboard_phids);
+ $dashboard->attachPanels($dashboard_panels);
+ }
+ }
+
+ return $dashboards;
+ }
+
protected function buildWhereClause($conn_r) {
$where = array();
diff --git a/src/applications/dashboard/storage/PhabricatorDashboard.php b/src/applications/dashboard/storage/PhabricatorDashboard.php
--- a/src/applications/dashboard/storage/PhabricatorDashboard.php
+++ b/src/applications/dashboard/storage/PhabricatorDashboard.php
@@ -10,6 +10,9 @@
protected $viewPolicy;
protected $editPolicy;
+ private $panelPHIDs = self::ATTACHABLE;
+ private $panels = self::ATTACHABLE;
+
public static function initializeNewDashboard(PhabricatorUser $actor) {
return id(new PhabricatorDashboard())
->setName('')
@@ -28,6 +31,25 @@
PhabricatorDashboardPHIDTypeDashboard::TYPECONST);
}
+ public function attachPanelPHIDs(array $phids) {
+ $this->panelPHIDs = $phids;
+ return $this;
+ }
+
+ public function getPanelPHIDs() {
+ return $this->assertAttached($this->panelPHIDs);
+ }
+
+ public function attachPanels(array $panels) {
+ assert_instances_of($panels, 'PhabricatorDashboardPanel');
+ $this->panels = $panels;
+ return $this;
+ }
+
+ public function getPanels() {
+ return $this->assertAttached($this->panels);
+ }
+
/* -( PhabricatorPolicyInterface )----------------------------------------- */
diff --git a/src/infrastructure/edges/constants/PhabricatorEdgeConfig.php b/src/infrastructure/edges/constants/PhabricatorEdgeConfig.php
--- a/src/infrastructure/edges/constants/PhabricatorEdgeConfig.php
+++ b/src/infrastructure/edges/constants/PhabricatorEdgeConfig.php
@@ -69,6 +69,9 @@
const TYPE_OBJECT_HAS_COLUMN = 43;
const TYPE_COLUMN_HAS_OBJECT = 44;
+ const TYPE_DASHBOARD_HAS_PANEL = 45;
+ const TYPE_PANEL_HAS_DASHBOARD = 46;
+
const TYPE_TEST_NO_CYCLE = 9000;
const TYPE_PHOB_HAS_ASANATASK = 80001;
@@ -153,6 +156,9 @@
self::TYPE_OBJECT_HAS_COLUMN => self::TYPE_COLUMN_HAS_OBJECT,
self::TYPE_COLUMN_HAS_OBJECT => self::TYPE_OBJECT_HAS_COLUMN,
+
+ self::TYPE_PANEL_HAS_DASHBOARD => self::TYPE_DASHBOARD_HAS_PANEL,
+ self::TYPE_DASHBOARD_HAS_PANEL => self::TYPE_PANEL_HAS_DASHBOARD,
);
return idx($map, $edge_type);
@@ -259,6 +265,10 @@
return '%s edited reviewer(s), added %d: %s; removed %d: %s.';
case self::TYPE_TASK_HAS_MOCK:
return '%s edited mock(s), added %d: %s; removed %d: %s.';
+ case self::TYPE_DASHBOARD_HAS_PANEL:
+ return '%s edited panel(s), added %d: %s; removed %d: %s.';
+ case self::TYPE_PANEL_HAS_DASHBOARD:
+ return '%s edited dashboard(s), added %d: %s; removed %d: %s.';
case self::TYPE_SUBSCRIBED_TO_OBJECT:
case self::TYPE_UNSUBSCRIBED_FROM_OBJECT:
case self::TYPE_FILE_HAS_OBJECT:
@@ -329,6 +339,10 @@
return '%s added %d reviewer(s): %s.';
case self::TYPE_TASK_HAS_MOCK:
return '%s added %d mock(s): %s.';
+ case self::TYPE_DASHBOARD_HAS_PANEL:
+ return '%s added %d panel(s): %s.';
+ case self::TYPE_PANEL_HAS_DASHBOARD:
+ return '%s added %d dashboard(s): %s.';
case self::TYPE_SUBSCRIBED_TO_OBJECT:
case self::TYPE_UNSUBSCRIBED_FROM_OBJECT:
case self::TYPE_FILE_HAS_OBJECT:
@@ -400,6 +414,10 @@
return '%s removed %d reviewer(s): %s.';
case self::TYPE_TASK_HAS_MOCK:
return '%s removed %d mock(s): %s.';
+ case self::TYPE_DASHBOARD_HAS_PANEL:
+ return '%s removed %d panel(s): %s.';
+ case self::TYPE_PANEL_HAS_DASHBOARD:
+ return '%s removed %d dashboard(s): %s.';
case self::TYPE_SUBSCRIBED_TO_OBJECT:
case self::TYPE_UNSUBSCRIBED_FROM_OBJECT:
case self::TYPE_FILE_HAS_OBJECT:
@@ -469,6 +487,10 @@
return '%s updated reviewers of %s.';
case self::TYPE_TASK_HAS_MOCK:
return '%s updated mocks of %s.';
+ case self::TYPE_PANEL_HAS_DASHBOARD:
+ return '%s updated panels for %s.';
+ case self::TYPE_PANEL_HAS_DASHBOARD:
+ return '%s updated dashboards for %s.';
case self::TYPE_SUBSCRIBED_TO_OBJECT:
case self::TYPE_UNSUBSCRIBED_FROM_OBJECT:
case self::TYPE_FILE_HAS_OBJECT:

File Metadata

Mime Type
text/plain
Expires
Thu, Apr 3, 7:34 PM (5 d, 7 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7474095
Default Alt Text
D8916.id21163.diff (15 KB)

Event Timeline