Page MenuHomePhabricator

D20364.diff
No OneTemporary

D20364.diff

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -9,7 +9,7 @@
'names' => array(
'conpherence.pkg.css' => '3c8a0668',
'conpherence.pkg.js' => '020aebcf',
- 'core.pkg.css' => 'a1c2d49b',
+ 'core.pkg.css' => '3b565a84',
'core.pkg.js' => 'a568e834',
'differential.pkg.css' => '8d8360fb',
'differential.pkg.js' => '67e02996',
@@ -128,7 +128,7 @@
'rsrc/css/phui/calendar/phui-calendar-list.css' => 'ccd7e4e2',
'rsrc/css/phui/calendar/phui-calendar-month.css' => 'cb758c42',
'rsrc/css/phui/calendar/phui-calendar.css' => 'f11073aa',
- 'rsrc/css/phui/object-item/phui-oi-big-ui.css' => '534f1757',
+ 'rsrc/css/phui/object-item/phui-oi-big-ui.css' => 'fa74cc35',
'rsrc/css/phui/object-item/phui-oi-color.css' => 'b517bfa0',
'rsrc/css/phui/object-item/phui-oi-drag-ui.css' => 'da15d3dc',
'rsrc/css/phui/object-item/phui-oi-flush-ui.css' => '490e2e2e',
@@ -849,7 +849,7 @@
'phui-lightbox-css' => '4ebf22da',
'phui-list-view-css' => '470b1adb',
'phui-object-box-css' => 'f434b6be',
- 'phui-oi-big-ui-css' => '534f1757',
+ 'phui-oi-big-ui-css' => 'fa74cc35',
'phui-oi-color-css' => 'b517bfa0',
'phui-oi-drag-ui-css' => 'da15d3dc',
'phui-oi-flush-ui-css' => '490e2e2e',
@@ -1379,9 +1379,6 @@
'javelin-dom',
'javelin-fx',
),
- '534f1757' => array(
- 'phui-oi-list-view-css',
- ),
'541f81c3' => array(
'javelin-install',
),
@@ -2179,6 +2176,9 @@
'phabricator-keyboard-shortcut',
'conpherence-thread-manager',
),
+ 'fa74cc35' => array(
+ 'phui-oi-list-view-css',
+ ),
'fdc13e4e' => array(
'javelin-install',
),
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
@@ -2905,6 +2905,7 @@
'PhabricatorDashboard' => 'applications/dashboard/storage/PhabricatorDashboard.php',
'PhabricatorDashboardAddPanelController' => 'applications/dashboard/controller/PhabricatorDashboardAddPanelController.php',
'PhabricatorDashboardApplication' => 'applications/dashboard/application/PhabricatorDashboardApplication.php',
+ 'PhabricatorDashboardApplicationInstallWorkflow' => 'applications/dashboard/install/PhabricatorDashboardApplicationInstallWorkflow.php',
'PhabricatorDashboardArchiveController' => 'applications/dashboard/controller/dashboard/PhabricatorDashboardArchiveController.php',
'PhabricatorDashboardConsoleController' => 'applications/dashboard/controller/PhabricatorDashboardConsoleController.php',
'PhabricatorDashboardController' => 'applications/dashboard/controller/PhabricatorDashboardController.php',
@@ -2913,13 +2914,17 @@
'PhabricatorDashboardDashboardPHIDType' => 'applications/dashboard/phid/PhabricatorDashboardDashboardPHIDType.php',
'PhabricatorDashboardDatasource' => 'applications/dashboard/typeahead/PhabricatorDashboardDatasource.php',
'PhabricatorDashboardEditController' => 'applications/dashboard/controller/dashboard/PhabricatorDashboardEditController.php',
+ 'PhabricatorDashboardFavoritesInstallWorkflow' => 'applications/dashboard/install/PhabricatorDashboardFavoritesInstallWorkflow.php',
+ 'PhabricatorDashboardHomeInstallWorkflow' => 'applications/dashboard/install/PhabricatorDashboardHomeInstallWorkflow.php',
'PhabricatorDashboardIconSet' => 'applications/dashboard/icon/PhabricatorDashboardIconSet.php',
'PhabricatorDashboardInstall' => 'applications/dashboard/storage/PhabricatorDashboardInstall.php',
'PhabricatorDashboardInstallController' => 'applications/dashboard/controller/dashboard/PhabricatorDashboardInstallController.php',
+ 'PhabricatorDashboardInstallWorkflow' => 'applications/dashboard/install/PhabricatorDashboardInstallWorkflow.php',
'PhabricatorDashboardLayoutConfig' => 'applications/dashboard/layoutconfig/PhabricatorDashboardLayoutConfig.php',
'PhabricatorDashboardListController' => 'applications/dashboard/controller/PhabricatorDashboardListController.php',
'PhabricatorDashboardMovePanelController' => 'applications/dashboard/controller/PhabricatorDashboardMovePanelController.php',
'PhabricatorDashboardNgrams' => 'applications/dashboard/storage/PhabricatorDashboardNgrams.php',
+ 'PhabricatorDashboardObjectInstallWorkflow' => 'applications/dashboard/install/PhabricatorDashboardObjectInstallWorkflow.php',
'PhabricatorDashboardPanel' => 'applications/dashboard/storage/PhabricatorDashboardPanel.php',
'PhabricatorDashboardPanelArchiveController' => 'applications/dashboard/controller/PhabricatorDashboardPanelArchiveController.php',
'PhabricatorDashboardPanelCoreCustomField' => 'applications/dashboard/customfield/PhabricatorDashboardPanelCoreCustomField.php',
@@ -2947,10 +2952,12 @@
'PhabricatorDashboardPanelViewController' => 'applications/dashboard/controller/PhabricatorDashboardPanelViewController.php',
'PhabricatorDashboardPortal' => 'applications/dashboard/storage/PhabricatorDashboardPortal.php',
'PhabricatorDashboardPortalController' => 'applications/dashboard/controller/portal/PhabricatorDashboardPortalController.php',
+ 'PhabricatorDashboardPortalDatasource' => 'applications/dashboard/typeahead/PhabricatorDashboardPortalDatasource.php',
'PhabricatorDashboardPortalEditConduitAPIMethod' => 'applications/dashboard/conduit/PhabricatorDashboardPortalEditConduitAPIMethod.php',
'PhabricatorDashboardPortalEditController' => 'applications/dashboard/controller/portal/PhabricatorDashboardPortalEditController.php',
'PhabricatorDashboardPortalEditEngine' => 'applications/dashboard/editor/PhabricatorDashboardPortalEditEngine.php',
'PhabricatorDashboardPortalEditor' => 'applications/dashboard/editor/PhabricatorDashboardPortalEditor.php',
+ 'PhabricatorDashboardPortalInstallWorkflow' => 'applications/dashboard/install/PhabricatorDashboardPortalInstallWorkflow.php',
'PhabricatorDashboardPortalListController' => 'applications/dashboard/controller/portal/PhabricatorDashboardPortalListController.php',
'PhabricatorDashboardPortalMenuItem' => 'applications/dashboard/menuitem/PhabricatorDashboardPortalMenuItem.php',
'PhabricatorDashboardPortalNameTransaction' => 'applications/dashboard/xaction/portal/PhabricatorDashboardPortalNameTransaction.php',
@@ -2966,6 +2973,7 @@
'PhabricatorDashboardPortalViewController' => 'applications/dashboard/controller/portal/PhabricatorDashboardPortalViewController.php',
'PhabricatorDashboardProfileController' => 'applications/dashboard/controller/PhabricatorDashboardProfileController.php',
'PhabricatorDashboardProfileMenuItem' => 'applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php',
+ 'PhabricatorDashboardProjectInstallWorkflow' => 'applications/dashboard/install/PhabricatorDashboardProjectInstallWorkflow.php',
'PhabricatorDashboardQuery' => 'applications/dashboard/query/PhabricatorDashboardQuery.php',
'PhabricatorDashboardQueryPanelInstallController' => 'applications/dashboard/controller/PhabricatorDashboardQueryPanelInstallController.php',
'PhabricatorDashboardQueryPanelType' => 'applications/dashboard/paneltype/PhabricatorDashboardQueryPanelType.php',
@@ -8865,6 +8873,7 @@
),
'PhabricatorDashboardAddPanelController' => 'PhabricatorDashboardController',
'PhabricatorDashboardApplication' => 'PhabricatorApplication',
+ 'PhabricatorDashboardApplicationInstallWorkflow' => 'PhabricatorDashboardInstallWorkflow',
'PhabricatorDashboardArchiveController' => 'PhabricatorDashboardController',
'PhabricatorDashboardConsoleController' => 'PhabricatorDashboardController',
'PhabricatorDashboardController' => 'PhabricatorController',
@@ -8873,13 +8882,17 @@
'PhabricatorDashboardDashboardPHIDType' => 'PhabricatorPHIDType',
'PhabricatorDashboardDatasource' => 'PhabricatorTypeaheadDatasource',
'PhabricatorDashboardEditController' => 'PhabricatorDashboardController',
+ 'PhabricatorDashboardFavoritesInstallWorkflow' => 'PhabricatorDashboardApplicationInstallWorkflow',
+ 'PhabricatorDashboardHomeInstallWorkflow' => 'PhabricatorDashboardApplicationInstallWorkflow',
'PhabricatorDashboardIconSet' => 'PhabricatorIconSet',
'PhabricatorDashboardInstall' => 'PhabricatorDashboardDAO',
'PhabricatorDashboardInstallController' => 'PhabricatorDashboardController',
+ 'PhabricatorDashboardInstallWorkflow' => 'Phobject',
'PhabricatorDashboardLayoutConfig' => 'Phobject',
'PhabricatorDashboardListController' => 'PhabricatorDashboardController',
'PhabricatorDashboardMovePanelController' => 'PhabricatorDashboardController',
'PhabricatorDashboardNgrams' => 'PhabricatorSearchNgrams',
+ 'PhabricatorDashboardObjectInstallWorkflow' => 'PhabricatorDashboardInstallWorkflow',
'PhabricatorDashboardPanel' => array(
'PhabricatorDashboardDAO',
'PhabricatorApplicationTransactionInterface',
@@ -8923,10 +8936,12 @@
'PhabricatorDestructibleInterface',
),
'PhabricatorDashboardPortalController' => 'PhabricatorDashboardController',
+ 'PhabricatorDashboardPortalDatasource' => 'PhabricatorTypeaheadDatasource',
'PhabricatorDashboardPortalEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'PhabricatorDashboardPortalEditController' => 'PhabricatorDashboardPortalController',
'PhabricatorDashboardPortalEditEngine' => 'PhabricatorEditEngine',
'PhabricatorDashboardPortalEditor' => 'PhabricatorApplicationTransactionEditor',
+ 'PhabricatorDashboardPortalInstallWorkflow' => 'PhabricatorDashboardObjectInstallWorkflow',
'PhabricatorDashboardPortalListController' => 'PhabricatorDashboardPortalController',
'PhabricatorDashboardPortalMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorDashboardPortalNameTransaction' => 'PhabricatorDashboardPortalTransactionType',
@@ -8942,6 +8957,7 @@
'PhabricatorDashboardPortalViewController' => 'PhabricatorDashboardPortalController',
'PhabricatorDashboardProfileController' => 'PhabricatorController',
'PhabricatorDashboardProfileMenuItem' => 'PhabricatorProfileMenuItem',
+ 'PhabricatorDashboardProjectInstallWorkflow' => 'PhabricatorDashboardObjectInstallWorkflow',
'PhabricatorDashboardQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorDashboardQueryPanelInstallController' => 'PhabricatorDashboardController',
'PhabricatorDashboardQueryPanelType' => 'PhabricatorDashboardPanelType',
diff --git a/src/applications/dashboard/application/PhabricatorDashboardApplication.php b/src/applications/dashboard/application/PhabricatorDashboardApplication.php
--- a/src/applications/dashboard/application/PhabricatorDashboardApplication.php
+++ b/src/applications/dashboard/application/PhabricatorDashboardApplication.php
@@ -43,7 +43,10 @@
'archive/(?P<id>\d+)/' => 'PhabricatorDashboardArchiveController',
'create/' => 'PhabricatorDashboardEditController',
'edit/(?:(?P<id>\d+)/)?' => 'PhabricatorDashboardEditController',
- 'install/(?:(?P<id>\d+)/)?' => 'PhabricatorDashboardInstallController',
+ 'install/(?P<id>\d+)/'.
+ '(?:(?P<workflowKey>[^/]+)/'.
+ '(?:(?P<modeKey>[^/]+)/)?)?' =>
+ 'PhabricatorDashboardInstallController',
'console/' => 'PhabricatorDashboardConsoleController',
'addpanel/(?P<id>\d+)/' => 'PhabricatorDashboardAddPanelController',
'movepanel/(?P<id>\d+)/' => 'PhabricatorDashboardMovePanelController',
diff --git a/src/applications/dashboard/controller/dashboard/PhabricatorDashboardInstallController.php b/src/applications/dashboard/controller/dashboard/PhabricatorDashboardInstallController.php
--- a/src/applications/dashboard/controller/dashboard/PhabricatorDashboardInstallController.php
+++ b/src/applications/dashboard/controller/dashboard/PhabricatorDashboardInstallController.php
@@ -3,6 +3,17 @@
final class PhabricatorDashboardInstallController
extends PhabricatorDashboardController {
+ private $dashboard;
+
+ public function setDashboard(PhabricatorDashboard $dashboard) {
+ $this->dashboard = $dashboard;
+ return $this;
+ }
+
+ public function getDashboard() {
+ return $this->dashboard;
+ }
+
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
@@ -15,126 +26,50 @@
return new Aphront404Response();
}
+ $this->setDashboard($dashboard);
$cancel_uri = $dashboard->getURI();
- $home_app = new PhabricatorHomeApplication();
-
- $options = array();
- $options['home'] = array(
- 'personal' =>
- array(
- 'capability' => PhabricatorPolicyCapability::CAN_VIEW,
- 'application' => $home_app,
- 'name' => pht('Personal Dashboard'),
- 'value' => 'personal',
- 'description' => pht('Places this dashboard as a menu item on home '.
- 'as a personal menu item. It will only be on your personal '.
- 'home.'),
- ),
- 'global' =>
- array(
- 'capability' => PhabricatorPolicyCapability::CAN_EDIT,
- 'application' => $home_app,
- 'name' => pht('Global Dashboard'),
- 'value' => 'global',
- 'description' => pht('Places this dashboard as a menu item on home '.
- 'as a global menu item. It will be available to all users.'),
- ),
- );
-
-
- $errors = array();
- $v_name = null;
- if ($request->isFormPost()) {
- $menuitem = new PhabricatorDashboardProfileMenuItem();
- $dashboard_phid = $dashboard->getPHID();
- $home = new PhabricatorHomeApplication();
- $v_name = $request->getStr('name');
- $v_home = $request->getStr('home');
-
- if ($v_home) {
- $application = $options['home'][$v_home]['application'];
- $capability = $options['home'][$v_home]['capability'];
-
- $can_edit_home = PhabricatorPolicyFilter::hasCapability(
- $viewer,
- $application,
- $capability);
-
- if (!$can_edit_home) {
- $errors[] = pht(
- 'You do not have permission to install a dashboard on home.');
- }
- } else {
- $errors[] = pht(
- 'You must select a destination to install this dashboard.');
- }
-
- $v_phid = $viewer->getPHID();
- if ($v_home == 'global') {
- $v_phid = null;
- }
-
- if (!$errors) {
- $install = PhabricatorProfileMenuItemConfiguration::initializeNewItem(
- $home,
- $menuitem,
- $v_phid);
-
- $install->setMenuItemProperty('dashboardPHID', $dashboard_phid);
- $install->setMenuItemProperty('name', $v_name);
- $install->setMenuItemOrder(1);
-
- $xactions = array();
-
- $editor = id(new PhabricatorProfileMenuEditor())
- ->setActor($viewer)
- ->setContinueOnNoEffect(true)
- ->setContinueOnMissingFields(true)
- ->setContentSourceFromRequest($request);
-
- $editor->applyTransactions($install, $xactions);
-
- $view_uri = '/home/menu/view/'.$install->getID().'/';
-
- return id(new AphrontRedirectResponse())->setURI($view_uri);
- }
- }
+ $workflow_key = $request->getURIData('workflowKey');
- $form = id(new AphrontFormView())
- ->setUser($viewer)
- ->appendChild(
- id(new AphrontFormTextControl())
- ->setLabel(pht('Menu Label'))
- ->setName('name')
- ->setValue($v_name));
-
- $radio = id(new AphrontFormRadioButtonControl())
- ->setLabel(pht('Home Menu'))
- ->setName('home');
-
- foreach ($options['home'] as $type => $option) {
- $can_edit = PhabricatorPolicyFilter::hasCapability(
- $viewer,
- $option['application'],
- $option['capability']);
- if ($can_edit) {
- $radio->addButton(
- $option['value'],
- $option['name'],
- $option['description']);
- }
+ $workflows = PhabricatorDashboardInstallWorkflow::getAllWorkflows();
+ if (!isset($workflows[$workflow_key])) {
+ return $this->newWorkflowDialog($dashboard, $workflows);
}
- $form->appendChild($radio);
+ return id(clone $workflows[$workflow_key])
+ ->setRequest($request)
+ ->setViewer($viewer)
+ ->setDashboard($dashboard)
+ ->setMode($request->getURIData('modeKey'))
+ ->handleRequest($request);
+ }
+
+ private function newWorkflowDialog(
+ PhabricatorDashboard $dashboard,
+ array $workflows) {
+ $viewer = $this->getViewer();
+ $cancel_uri = $dashboard->getURI();
+
+ $menu = id(new PHUIObjectItemListView())
+ ->setViewer($viewer)
+ ->setFlush(true)
+ ->setBig(true);
+
+ foreach ($workflows as $key => $workflow) {
+ $item = $workflow->getWorkflowMenuItem();
+
+ $item_href = urisprintf('install/%d/%s/', $dashboard->getID(), $key);
+ $item_href = $this->getApplicationURI($item_href);
+ $item->setHref($item_href);
+
+ $menu->addItem($item);
+ }
return $this->newDialog()
- ->setTitle(pht('Install Dashboard'))
- ->setErrors($errors)
+ ->setTitle(pht('Add Dashboard to Menu'))
->setWidth(AphrontDialogView::WIDTH_FORM)
- ->appendChild($form->buildLayoutView())
- ->addCancelButton($cancel_uri)
- ->addSubmitButton(pht('Install Dashboard'));
+ ->appendChild($menu)
+ ->addCancelButton($cancel_uri);
}
}
diff --git a/src/applications/dashboard/controller/dashboard/PhabricatorDashboardViewController.php b/src/applications/dashboard/controller/dashboard/PhabricatorDashboardViewController.php
--- a/src/applications/dashboard/controller/dashboard/PhabricatorDashboardViewController.php
+++ b/src/applications/dashboard/controller/dashboard/PhabricatorDashboardViewController.php
@@ -83,7 +83,7 @@
$curtain->addAction(
id(new PhabricatorActionView())
- ->setName(pht('Install Dashboard'))
+ ->setName(pht('Add Dashboard to Menu'))
->setIcon('fa-wrench')
->setHref($this->getApplicationURI("/install/{$id}/"))
->setWorkflow(true));
diff --git a/src/applications/dashboard/install/PhabricatorDashboardApplicationInstallWorkflow.php b/src/applications/dashboard/install/PhabricatorDashboardApplicationInstallWorkflow.php
new file mode 100644
--- /dev/null
+++ b/src/applications/dashboard/install/PhabricatorDashboardApplicationInstallWorkflow.php
@@ -0,0 +1,58 @@
+<?php
+
+abstract class PhabricatorDashboardApplicationInstallWorkflow
+ extends PhabricatorDashboardInstallWorkflow {
+
+ abstract protected function newApplication();
+
+ protected function canInstallToGlobalMenu() {
+ return PhabricatorPolicyFilter::hasCapability(
+ $this->getViewer(),
+ $this->newApplication(),
+ PhabricatorPolicyCapability::CAN_EDIT);
+ }
+
+ public function handleRequest(AphrontRequest $request) {
+ $viewer = $this->getViewer();
+ $application = $this->newApplication();
+ $can_global = $this->canInstallToGlobalMenu();
+
+ switch ($this->getMode()) {
+ case 'global':
+ if (!$can_global) {
+ return $this->newGlobalPermissionDialog();
+ } else if ($request->isFormPost()) {
+ return $this->installDashboard($application, null);
+ } else {
+ return $this->newGlobalConfirmDialog();
+ }
+ case 'personal':
+ if ($request->isFormPost()) {
+ return $this->installDashboard($application, $viewer->getPHID());
+ } else {
+ return $this->newPersonalConfirmDialog();
+ }
+ }
+
+ $global_item = $this->newGlobalMenuItem()
+ ->setDisabled(!$can_global);
+
+ $menu = $this->newMenuFromItemMap(
+ array(
+ 'personal' => $this->newPersonalMenuItem(),
+ 'global' => $global_item,
+ ));
+
+ return $this->newApplicationModeDialog()
+ ->appendChild($menu);
+ }
+
+ abstract protected function newGlobalPermissionDialog();
+ abstract protected function newGlobalConfirmDialog();
+ abstract protected function newPersonalConfirmDialog();
+
+ abstract protected function newPersonalMenuItem();
+ abstract protected function newGlobalMenuItem();
+ abstract protected function newApplicationModeDialog();
+
+}
diff --git a/src/applications/dashboard/install/PhabricatorDashboardFavoritesInstallWorkflow.php b/src/applications/dashboard/install/PhabricatorDashboardFavoritesInstallWorkflow.php
new file mode 100644
--- /dev/null
+++ b/src/applications/dashboard/install/PhabricatorDashboardFavoritesInstallWorkflow.php
@@ -0,0 +1,85 @@
+<?php
+
+final class PhabricatorDashboardFavoritesInstallWorkflow
+ extends PhabricatorDashboardApplicationInstallWorkflow {
+
+ const WORKFLOWKEY = 'favorites';
+
+ public function getOrder() {
+ return 4000;
+ }
+
+ protected function newWorkflowMenuItem() {
+ return $this->newMenuItem()
+ ->setHeader(pht('Add to Favorites Menu'))
+ ->setImageIcon('fa-bookmark')
+ ->addAttribute(
+ pht(
+ 'Add this dashboard to the favorites menu in the main '.
+ 'menu bar.'));
+ }
+
+ protected function newProfileEngine() {
+ return new PhabricatorFavoritesProfileMenuEngine();
+ }
+
+ protected function newApplication() {
+ return new PhabricatorFavoritesApplication();
+ }
+
+ protected function newApplicationModeDialog() {
+ return $this->newDialog()
+ ->setTitle(pht('Add Dashboard to Favorites Menu'));
+ }
+
+ protected function newPersonalMenuItem() {
+ return $this->newMenuItem()
+ ->setHeader(pht('Add to Personal Favorites'))
+ ->setImageIcon('fa-user')
+ ->addAttribute(
+ pht(
+ 'Add this dashboard to your list of personal favorite menu items, '.
+ 'visible to only you.'));
+ }
+
+ protected function newGlobalMenuItem() {
+ return $this->newMenuItem()
+ ->setHeader(pht('Add to Global Favorites'))
+ ->setImageIcon('fa-globe')
+ ->addAttribute(
+ pht(
+ 'Add this dashboard to the global favorites menu, visible to all '.
+ 'users.'));
+ }
+
+ protected function newGlobalPermissionDialog() {
+ return $this->newDialog()
+ ->setTitle(pht('No Permission'))
+ ->appendParagraph(
+ pht(
+ 'You do not have permission to install items on the global '.
+ 'favorites menu.'));
+ }
+
+ protected function newGlobalConfirmDialog() {
+ return $this->newDialog()
+ ->setTitle(pht('Add Dashboard to Global Favorites'))
+ ->appendParagraph(
+ pht(
+ 'Add dashboard %s as a global menu item in the favorites menu?',
+ $this->getDashboardDisplayName()))
+ ->addSubmitButton(pht('Add to Favorites'));
+ }
+
+ protected function newPersonalConfirmDialog() {
+ return $this->newDialog()
+ ->setTitle(pht('Add Dashboard to Personal Favorites'))
+ ->appendParagraph(
+ pht(
+ 'Add dashboard %s as a personal menu item in the favorites menu?',
+ $this->getDashboardDisplayName()))
+ ->addSubmitButton(pht('Add to Favorites'));
+ }
+
+
+}
diff --git a/src/applications/dashboard/install/PhabricatorDashboardHomeInstallWorkflow.php b/src/applications/dashboard/install/PhabricatorDashboardHomeInstallWorkflow.php
new file mode 100644
--- /dev/null
+++ b/src/applications/dashboard/install/PhabricatorDashboardHomeInstallWorkflow.php
@@ -0,0 +1,83 @@
+<?php
+
+final class PhabricatorDashboardHomeInstallWorkflow
+ extends PhabricatorDashboardApplicationInstallWorkflow {
+
+ const WORKFLOWKEY = 'home';
+
+ public function getOrder() {
+ return 1000;
+ }
+
+ protected function newWorkflowMenuItem() {
+ return $this->newMenuItem()
+ ->setHeader(pht('Add to Home Page Menu'))
+ ->setImageIcon('fa-home')
+ ->addAttribute(
+ pht(
+ 'Add this dashboard to the menu on the home page.'));
+ }
+
+ protected function newProfileEngine() {
+ return new PhabricatorHomeProfileMenuEngine();
+ }
+
+ protected function newApplication() {
+ return new PhabricatorHomeApplication();
+ }
+
+ protected function newApplicationModeDialog() {
+ return $this->newDialog()
+ ->setTitle(pht('Add Dashboard to Home Menu'));
+ }
+
+ protected function newPersonalMenuItem() {
+ return $this->newMenuItem()
+ ->setHeader(pht('Add to Personal Home Menu'))
+ ->setImageIcon('fa-user')
+ ->addAttribute(
+ pht(
+ 'Add this dashboard to your list of personal home menu items, '.
+ 'visible to only you.'));
+ }
+
+ protected function newGlobalMenuItem() {
+ return $this->newMenuItem()
+ ->setHeader(pht('Add to Global Home Menu'))
+ ->setImageIcon('fa-globe')
+ ->addAttribute(
+ pht(
+ 'Add this dashboard to the global home menu, visible to all '.
+ 'users.'));
+ }
+
+ protected function newGlobalPermissionDialog() {
+ return $this->newDialog()
+ ->setTitle(pht('No Permission'))
+ ->appendParagraph(
+ pht(
+ 'You do not have permission to install items on the global home '.
+ 'menu.'));
+ }
+
+ protected function newGlobalConfirmDialog() {
+ return $this->newDialog()
+ ->setTitle(pht('Add Dashboard to Global Home Page'))
+ ->appendParagraph(
+ pht(
+ 'Add dashboard %s as a global menu item on the home page?',
+ $this->getDashboardDisplayName()))
+ ->addSubmitButton(pht('Add to Home'));
+ }
+
+ protected function newPersonalConfirmDialog() {
+ return $this->newDialog()
+ ->setTitle(pht('Add Dashboard to Personal Home Page'))
+ ->appendParagraph(
+ pht(
+ 'Add dashboard %s as a personal menu item on your home page?',
+ $this->getDashboardDisplayName()))
+ ->addSubmitButton(pht('Add to Home'));
+ }
+
+}
diff --git a/src/applications/dashboard/install/PhabricatorDashboardInstallWorkflow.php b/src/applications/dashboard/install/PhabricatorDashboardInstallWorkflow.php
new file mode 100644
--- /dev/null
+++ b/src/applications/dashboard/install/PhabricatorDashboardInstallWorkflow.php
@@ -0,0 +1,143 @@
+<?php
+
+abstract class PhabricatorDashboardInstallWorkflow
+ extends Phobject {
+
+ private $request;
+ private $viewer;
+ private $dashboard;
+ private $mode;
+
+ final public function setViewer(PhabricatorUser $viewer) {
+ $this->viewer = $viewer;
+ return $this;
+ }
+
+ final public function getViewer() {
+ return $this->viewer;
+ }
+
+ final public function setDashboard(PhabricatorDashboard $dashboard) {
+ $this->dashboard = $dashboard;
+ return $this;
+ }
+
+ final public function getDashboard() {
+ return $this->dashboard;
+ }
+
+ final public function setMode($mode) {
+ $this->mode = $mode;
+ return $this;
+ }
+
+ final public function getMode() {
+ return $this->mode;
+ }
+
+ final public function setRequest(AphrontRequest $request) {
+ $this->request = $request;
+ return $this;
+ }
+
+ final public function getRequest() {
+ return $this->request;
+ }
+
+ final public function getWorkflowKey() {
+ return $this->getPhobjectClassConstant('WORKFLOWKEY', 32);
+ }
+
+ final public static function getAllWorkflows() {
+ return id(new PhutilClassMapQuery())
+ ->setAncestorClass(__CLASS__)
+ ->setUniqueMethod('getWorkflowKey')
+ ->setSortMethod('getOrder')
+ ->execute();
+ }
+
+ final public function getWorkflowMenuItem() {
+ return $this->newWorkflowMenuItem();
+ }
+
+ abstract public function getOrder();
+ abstract protected function newWorkflowMenuItem();
+
+ final protected function newMenuItem() {
+ return id(new PHUIObjectItemView())
+ ->setClickable(true);
+ }
+
+ abstract public function handleRequest(AphrontRequest $request);
+
+ final protected function newDialog() {
+ $dashboard = $this->getDashboard();
+
+ return id(new AphrontDialogView())
+ ->setViewer($this->getViewer())
+ ->setWidth(AphrontDialogView::WIDTH_FORM)
+ ->addCancelButton($dashboard->getURI());
+ }
+
+ final protected function newMenuFromItemMap(array $map) {
+ $viewer = $this->getViewer();
+ $dashboard = $this->getDashboard();
+
+ $menu = id(new PHUIObjectItemListView())
+ ->setViewer($viewer)
+ ->setFlush(true)
+ ->setBig(true);
+
+ foreach ($map as $key => $item) {
+ $item->setHref(
+ urisprintf(
+ '/dashboard/install/%d/%s/%s/',
+ $dashboard->getID(),
+ $this->getWorkflowKey(),
+ $key));
+
+ $menu->addItem($item);
+ }
+
+ return $menu;
+ }
+
+ abstract protected function newProfileEngine();
+
+ final protected function installDashboard($profile_object, $custom_phid) {
+ $dashboard = $this->getDashboard();
+ $engine = $this->newProfileEngine()
+ ->setProfileObject($profile_object);
+
+ $request = $this->getRequest();
+ $viewer = $this->getViewer();
+
+ $config = PhabricatorProfileMenuItemConfiguration::initializeNewItem(
+ $profile_object,
+ new PhabricatorDashboardProfileMenuItem(),
+ $custom_phid);
+
+ $config->setMenuItemProperty('dashboardPHID', $dashboard->getPHID());
+
+ $xactions = array();
+
+ $editor = id(new PhabricatorProfileMenuEditor())
+ ->setActor($viewer)
+ ->setContinueOnNoEffect(true)
+ ->setContinueOnMissingFields(true)
+ ->setContentSourceFromRequest($request);
+
+ $editor->applyTransactions($config, $xactions);
+
+ $done_uri = $engine->getItemURI(urisprintf('view/%d/', $config->getID()));
+
+ return id(new AphrontRedirectResponse())
+ ->setURI($done_uri);
+ }
+
+ final protected function getDashboardDisplayName() {
+ $dashboard = $this->getDashboard();
+ return phutil_tag('strong', array(), $dashboard->getName());
+ }
+
+}
diff --git a/src/applications/dashboard/install/PhabricatorDashboardObjectInstallWorkflow.php b/src/applications/dashboard/install/PhabricatorDashboardObjectInstallWorkflow.php
new file mode 100644
--- /dev/null
+++ b/src/applications/dashboard/install/PhabricatorDashboardObjectInstallWorkflow.php
@@ -0,0 +1,99 @@
+<?php
+
+abstract class PhabricatorDashboardObjectInstallWorkflow
+ extends PhabricatorDashboardInstallWorkflow {
+
+ abstract protected function newQuery();
+ abstract protected function newConfirmDialog($object);
+ abstract protected function newObjectSelectionForm($object);
+
+ public function handleRequest(AphrontRequest $request) {
+ $viewer = $this->getViewer();
+
+ $target_identifier = null;
+
+ $target_tokens = $request->getArr('target');
+ if ($target_tokens) {
+ $target_identifier = head($target_tokens);
+ }
+
+ if (!strlen($target_identifier)) {
+ $target_identifier = $request->getStr('target');
+ }
+
+ if (!strlen($target_identifier)) {
+ $target_identifier = $this->getMode();
+ }
+
+ $target = null;
+ if (strlen($target_identifier)) {
+ $targets = array();
+
+ if (ctype_digit($target_identifier)) {
+ $targets = $this->newQuery()
+ ->setViewer($viewer)
+ ->withIDs(array((int)$target_identifier))
+ ->execute();
+ }
+
+ if (!$targets) {
+ $targets = $this->newQuery()
+ ->setViewer($viewer)
+ ->withPHIDs(array($target_identifier))
+ ->execute();
+ }
+
+ if ($targets) {
+ $target = head($targets);
+ }
+ }
+
+ if ($target) {
+ $target_phid = $target->getPHID();
+ } else {
+ $target_phid = null;
+ }
+
+ if ($target) {
+ $can_edit = PhabricatorPolicyFilter::hasCapability(
+ $viewer,
+ $target,
+ PhabricatorPolicyCapability::CAN_EDIT);
+ } else {
+ $can_edit = null;
+ }
+
+ if ($request->isFormPost() && $target && $can_edit) {
+ if ($request->getBool('confirm')) {
+ return $this->installDashboard($target, null);
+ } else {
+ return $this->newConfirmDialog($target)
+ ->addHiddenInput('confirm', 1)
+ ->addHiddenInput('target', $target_phid);
+ }
+ }
+
+ $errors = array();
+ if (strlen($target_identifier)) {
+ if (!$target) {
+ $errors[] = pht('Choose a valid object.');
+ } else if (!$can_edit) {
+ $errors[] = pht(
+ 'You do not have permission to edit the selected object. '.
+ 'You can only install dashboards on objects you can edit.');
+ }
+ } else if ($request->getBool('pick')) {
+ $errors[] = pht(
+ 'Choose an object to install this dashboard on.');
+ }
+
+ $form = $this->newObjectSelectionForm($target)
+ ->addHiddenInput('pick', 1);
+
+ return $this->newDialog()
+ ->setTitle(pht('Add Dashboard to Project Menu'))
+ ->setErrors($errors)
+ ->appendForm($form)
+ ->addSubmitButton(pht('Continue'));
+ }
+}
diff --git a/src/applications/dashboard/install/PhabricatorDashboardPortalInstallWorkflow.php b/src/applications/dashboard/install/PhabricatorDashboardPortalInstallWorkflow.php
new file mode 100644
--- /dev/null
+++ b/src/applications/dashboard/install/PhabricatorDashboardPortalInstallWorkflow.php
@@ -0,0 +1,62 @@
+<?php
+
+final class PhabricatorDashboardPortalInstallWorkflow
+ extends PhabricatorDashboardObjectInstallWorkflow {
+
+ const WORKFLOWKEY = 'portal';
+
+ public function getOrder() {
+ return 2000;
+ }
+
+ protected function newWorkflowMenuItem() {
+ return $this->newMenuItem()
+ ->setHeader(pht('Add to Portal Menu'))
+ ->setImageIcon('fa-compass')
+ ->addAttribute(
+ pht('Add this dashboard to the menu on a portal.'));
+ }
+
+ protected function newProfileEngine() {
+ return new PhabricatorDashboardPortalProfileMenuEngine();
+ }
+
+ protected function newQuery() {
+ return new PhabricatorDashboardPortalQuery();
+ }
+
+ protected function newConfirmDialog($object) {
+ return $this->newDialog()
+ ->setTitle(pht('Add Dashboard to Portal Menu'))
+ ->appendParagraph(
+ pht(
+ 'Add the dashboard %s to portal %s?',
+ $this->getDashboardDisplayName(),
+ phutil_tag('strong', array(), $object->getName())))
+ ->addSubmitButton(pht('Add to Portal'));
+ }
+ protected function newObjectSelectionForm($object) {
+ $viewer = $this->getViewer();
+
+ if ($object) {
+ $tokenizer_value = array($object->getPHID());
+ } else {
+ $tokenizer_value = array();
+ }
+
+ return id(new AphrontFormView())
+ ->setViewer($viewer)
+ ->appendInstructions(
+ pht(
+ 'Select which portal you want to add the dashboard %s to.',
+ $this->getDashboardDisplayName()))
+ ->appendControl(
+ id(new AphrontFormTokenizerControl())
+ ->setName('target')
+ ->setLimit(1)
+ ->setLabel(pht('Add to Portal'))
+ ->setValue($tokenizer_value)
+ ->setDatasource(new PhabricatorDashboardPortalDatasource()));
+ }
+
+}
diff --git a/src/applications/dashboard/install/PhabricatorDashboardProjectInstallWorkflow.php b/src/applications/dashboard/install/PhabricatorDashboardProjectInstallWorkflow.php
new file mode 100644
--- /dev/null
+++ b/src/applications/dashboard/install/PhabricatorDashboardProjectInstallWorkflow.php
@@ -0,0 +1,63 @@
+<?php
+
+final class PhabricatorDashboardProjectInstallWorkflow
+ extends PhabricatorDashboardObjectInstallWorkflow {
+
+ const WORKFLOWKEY = 'project';
+
+ public function getOrder() {
+ return 3000;
+ }
+
+ protected function newWorkflowMenuItem() {
+ return $this->newMenuItem()
+ ->setHeader(pht('Add to Project Menu'))
+ ->setImageIcon('fa-briefcase')
+ ->addAttribute(
+ pht('Add this dashboard to the menu for a project.'));
+ }
+
+ protected function newProfileEngine() {
+ return new PhabricatorProjectProfileMenuEngine();
+ }
+
+ protected function newQuery() {
+ return new PhabricatorProjectQuery();
+ }
+
+ protected function newConfirmDialog($object) {
+ return $this->newDialog()
+ ->setTitle(pht('Add Dashboard to Project Menu'))
+ ->appendParagraph(
+ pht(
+ 'Add the dashboard %s to the menu for project %s?',
+ $this->getDashboardDisplayName(),
+ phutil_tag('strong', array(), $object->getName())))
+ ->addSubmitButton(pht('Add to Project'));
+ }
+
+ protected function newObjectSelectionForm($object) {
+ $viewer = $this->getViewer();
+
+ if ($object) {
+ $tokenizer_value = array($object->getPHID());
+ } else {
+ $tokenizer_value = array();
+ }
+
+ return id(new AphrontFormView())
+ ->setViewer($viewer)
+ ->appendInstructions(
+ pht(
+ 'Select which project menu you want to add the dashboard %s to.',
+ $this->getDashboardDisplayName()))
+ ->appendControl(
+ id(new AphrontFormTokenizerControl())
+ ->setName('target')
+ ->setLimit(1)
+ ->setLabel(pht('Add to Project'))
+ ->setValue($tokenizer_value)
+ ->setDatasource(new PhabricatorProjectDatasource()));
+ }
+
+}
diff --git a/src/applications/dashboard/typeahead/PhabricatorDashboardPortalDatasource.php b/src/applications/dashboard/typeahead/PhabricatorDashboardPortalDatasource.php
new file mode 100644
--- /dev/null
+++ b/src/applications/dashboard/typeahead/PhabricatorDashboardPortalDatasource.php
@@ -0,0 +1,47 @@
+<?php
+
+final class PhabricatorDashboardPortalDatasource
+ extends PhabricatorTypeaheadDatasource {
+
+ public function getBrowseTitle() {
+ return pht('Browse Portals');
+ }
+
+ public function getPlaceholderText() {
+ return pht('Type a portal name...');
+ }
+
+ public function getDatasourceApplicationClass() {
+ return 'PhabricatorDashboardApplication';
+ }
+
+ public function loadResults() {
+ $results = $this->buildResults();
+ return $this->filterResultsAgainstTokens($results);
+ }
+
+ protected function renderSpecialTokens(array $values) {
+ return $this->renderTokensFromResults($this->buildResults(), $values);
+ }
+
+ public function buildResults() {
+ $query = new PhabricatorDashboardPortalQuery();
+
+ // TODO: Actually query by name so this scales past 100 portals.
+
+ $portals = $this->executeQuery($query);
+
+ $results = array();
+ foreach ($portals as $portal) {
+ $result = id(new PhabricatorTypeaheadResult())
+ ->setName($portal->getObjectName().' '.$portal->getName())
+ ->setPHID($portal->getPHID())
+ ->setIcon('fa-compass');
+
+ $results[] = $result;
+ }
+
+ return $results;
+ }
+
+}
diff --git a/src/applications/project/menuitem/PhabricatorProjectPointsProfileMenuItem.php b/src/applications/project/menuitem/PhabricatorProjectPointsProfileMenuItem.php
--- a/src/applications/project/menuitem/PhabricatorProjectPointsProfileMenuItem.php
+++ b/src/applications/project/menuitem/PhabricatorProjectPointsProfileMenuItem.php
@@ -165,8 +165,9 @@
),
$bar);
- $item = $this->newItemView()
- ->newProgressBar($bar);
+ $item = $this->newItemView();
+
+ $item->newProgressBar($bar);
return array(
$item,
diff --git a/src/applications/search/menuitem/PhabricatorProfileMenuItem.php b/src/applications/search/menuitem/PhabricatorProfileMenuItem.php
--- a/src/applications/search/menuitem/PhabricatorProfileMenuItem.php
+++ b/src/applications/search/menuitem/PhabricatorProfileMenuItem.php
@@ -5,7 +5,6 @@
private $viewer;
private $engine;
-
public function getMenuItemTypeIcon() {
return null;
}
diff --git a/src/view/phui/PHUIObjectItemView.php b/src/view/phui/PHUIObjectItemView.php
--- a/src/view/phui/PHUIObjectItemView.php
+++ b/src/view/phui/PHUIObjectItemView.php
@@ -299,6 +299,8 @@
if ($this->disabled) {
$item_classes[] = 'phui-oi-disabled';
+ } else {
+ $item_classes[] = 'phui-oi-enabled';
}
switch ($this->effect) {
diff --git a/webroot/rsrc/css/phui/object-item/phui-oi-big-ui.css b/webroot/rsrc/css/phui/object-item/phui-oi-big-ui.css
--- a/webroot/rsrc/css/phui/object-item/phui-oi-big-ui.css
+++ b/webroot/rsrc/css/phui/object-item/phui-oi-big-ui.css
@@ -70,21 +70,29 @@
}
.phui-oi-list-big .phui-oi-linked-container {
- border: 1px solid {$lightblueborder};
+ border-width: 1px;
+ border-style: solid;
border-radius: 4px;
- box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.035);
}
-.phui-oi-list-big .phui-oi-disabled {
- border-radius: 4px;
- background: {$lightgreybackground};
+.phui-oi-list-big .phui-oi-enabled.phui-oi-linked-container {
+ border-color: {$lightblueborder};
+ box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.phui-oi-list-big .phui-oi-disabled.phui-oi-linked-container {
+ border-color: {$greybackground};
+}
+
+.phui-oi-list-big .phui-oi-disabled .phui-oi-image-icon .phui-icon-view {
+ color: {$darkgreybackground};
}
.device-desktop .phui-oi-linked-container {
cursor: pointer;
}
-.device-desktop .phui-oi-linked-container:hover {
+.device-desktop .phui-oi-enabled.phui-oi-linked-container:hover {
background-color: {$hoverblue};
border-color: {$blueborder};
}

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 16, 9:37 AM (2 d, 10 h ago)
Storage Engine
amazon-s3
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
phabricator/secure/mi/5u/xw2zpiejubgrrxzc
Default Alt Text
D20364.diff (40 KB)

Event Timeline