Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15285136
D20364.id48619.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
40 KB
Referenced Files
None
Subscribers
None
D20364.id48619.diff
View Options
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' => 'a747b035',
'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',
@@ -1369,9 +1369,6 @@
'javelin-dom',
'javelin-fx',
),
- '534f1757' => array(
- 'phui-oi-list-view-css',
- ),
'541f81c3' => array(
'javelin-install',
),
@@ -2175,6 +2172,9 @@
'phabricator-keyboard-shortcut',
'conpherence-thread-manager',
),
+ 'fa74cc35' => array(
+ 'phui-oi-list-view-css',
+ ),
'fce5d170' => array(
'javelin-magical-init',
'javelin-util',
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',
@@ -8864,6 +8872,7 @@
),
'PhabricatorDashboardAddPanelController' => 'PhabricatorDashboardController',
'PhabricatorDashboardApplication' => 'PhabricatorApplication',
+ 'PhabricatorDashboardApplicationInstallWorkflow' => 'PhabricatorDashboardInstallWorkflow',
'PhabricatorDashboardArchiveController' => 'PhabricatorDashboardController',
'PhabricatorDashboardConsoleController' => 'PhabricatorDashboardController',
'PhabricatorDashboardController' => 'PhabricatorController',
@@ -8872,13 +8881,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',
@@ -8922,10 +8935,12 @@
'PhabricatorDestructibleInterface',
),
'PhabricatorDashboardPortalController' => 'PhabricatorDashboardController',
+ 'PhabricatorDashboardPortalDatasource' => 'PhabricatorTypeaheadDatasource',
'PhabricatorDashboardPortalEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'PhabricatorDashboardPortalEditController' => 'PhabricatorDashboardPortalController',
'PhabricatorDashboardPortalEditEngine' => 'PhabricatorEditEngine',
'PhabricatorDashboardPortalEditor' => 'PhabricatorApplicationTransactionEditor',
+ 'PhabricatorDashboardPortalInstallWorkflow' => 'PhabricatorDashboardObjectInstallWorkflow',
'PhabricatorDashboardPortalListController' => 'PhabricatorDashboardPortalController',
'PhabricatorDashboardPortalMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorDashboardPortalNameTransaction' => 'PhabricatorDashboardPortalTransactionType',
@@ -8941,6 +8956,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
Details
Attached
Mime Type
text/plain
Expires
Wed, Mar 5, 11:43 AM (2 w, 5 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7225417
Default Alt Text
D20364.id48619.diff (40 KB)
Attached To
Mode
D20364: Make the "Install Dashboard" flow smoother
Attached
Detach File
Event Timeline
Log In to Comment