diff --git a/.arclint b/.arclint index 9c2733514b93764dd5f04f0e3aeaa97b37bc79be..90e7595e03146aefa54851640bef4ca5c0bab776 100644 --- a/.arclint +++ b/.arclint @@ -28,9 +28,6 @@ "type": "phutil-library", "include": "(^\\.php$)" }, - "phutil-xhpast": { - "type": "phutil-xhpast" - }, "spelling": { "type": "spelling" }, diff --git a/README.md b/README.md index 7209f0b97c1b6ffd6299931ef08c9a95348e8c70..27c48371a3a358ee2fce2d912292f3dd3ea842c2 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,14 @@ To install the Sprint extension: ./config set load-libraries '{"sprint":"/srv/phab/libext/sprint/src"}' +**Release Notes: Projects v3.0** +As of 13.02.2016, sprint charts now depend on the global maniphest.points field setting being enabled. + +To do this, enter the JSON +{"enabled": true} in the maniphest.points configuration. + +To migrate story points to maniphest.points, see <https://secure.phabricator.com/T10350>. + **BUGS** Report issues by creating a task here: diff --git a/rsrc/behavior-sprint-boards.js b/rsrc/behavior-sprint-boards.js deleted file mode 100644 index 505fb3e9e6fdf9c270c296a9dd4f597d7074683e..0000000000000000000000000000000000000000 --- a/rsrc/behavior-sprint-boards.js +++ /dev/null @@ -1,359 +0,0 @@ -/** - * @provides javelin-behavior-sprint-boards - */ - -JX.behavior('sprint-boards', function(config, statics) { - - function finditems(col) { - return JX.DOM.scry(col, 'li', 'project-card'); - } - - function onupdate(col) { - var data = JX.Stratcom.getData(col); - var cards = finditems(col); - - // Update the count of tasks in the column header. - if (!data.countTagNode) { - data.countTagNode = JX.$(data.countTagID); - JX.DOM.show(data.countTagNode); - } - - var sum = 0; - var ii; - var ii_item; - items = cards; - for (ii = 0; ii < items.length; ii++) { - ii_item = items[ii]; - ii_item_points = JX.Stratcom.getData(ii_item).points; - sum += Number(ii_item_points); - } - - // TODO: This is a little bit hacky, but we don't have a PHUIX version of - // this element yet. - - var over_limit = (data.pointLimit && (sum > data.pointLimit)); - - var display_value = sum; - if (data.pointLimit) { - display_value = sum + ' / ' + data.pointLimit; - } - JX.DOM.setContent(JX.$(data.countTagContentID), display_value); - - var panel_map = { - 'project-panel-empty': !cards.length, - 'project-panel-over-limit': over_limit - }; - var panel = JX.DOM.findAbove(col, 'div', 'workpanel'); - for (var p in panel_map) { - JX.DOM.alterClass(panel, p, !!panel_map[p]); - } - - var color_map = { - 'phui-tag-shade-disabled': (sum === 0), - 'phui-tag-shade-blue': (sum > 0 && !over_limit), - 'phui-tag-shade-red': (over_limit) - }; - for (var c in color_map) { - JX.DOM.alterClass(data.countTagNode, c, !!color_map[c]); - } - } - - function onresponse(response, item, list) { - list.unlock(); - JX.DOM.alterClass(item, 'drag-sending', false); - JX.DOM.replace(item, JX.$H(response.task)); - } - - function getcolumns() { - return JX.DOM.scry(JX.$(statics.boardID), 'ul', 'project-column'); - } - - function colsort(u, v) { - var ud = JX.Stratcom.getData(u).sort || []; - var vd = JX.Stratcom.getData(v).sort || []; - - for (var ii = 0; ii < ud.length; ii++) { - - if (parseInt(ud[ii]) < parseInt(vd[ii])) { - return 1; - } - if (parseInt(ud[ii]) > parseInt(vd[ii])) { - return -1; - } - } - - return 0; - } - - function getcontainer() { - return JX.DOM.find( - JX.$(statics.boardID), - 'div', - 'aphront-multi-column-view'); - } - - function onbegindrag(item) { - // If the longest column on the board is taller than the window, the board - // will scroll vertically. Dragging an item to the longest column may - // make it longer, by the total height of the board, plus the height of - // the drop target. - - // If this happens, the scrollbar will jump around and the scroll position - // can be adjusted in a disorienting way. To reproduce this, drag a task - // to the bottom of the longest column on a scrolling board and wave the - // task in and out of the column. The scroll bar will jump around and - // it will be hard to lock onto a target. - - // To fix this, set the minimum board height to the current board height - // plus the size of the drop target (which is the size of the item plus - // a bit of margin). This makes sure the scroll bar never needs to - // recalculate. - - var item_size = JX.Vector.getDim(item); - var container = getcontainer(); - var container_size = JX.Vector.getDim(container); - - container.style.minHeight = (item_size.y + container_size.y + 12) + 'px'; - } - - function onenddrag() { - getcontainer().style.minHeight = ''; - } - - function ondrop(list, item, after) { - list.lock(); - JX.DOM.alterClass(item, 'drag-sending', true); - - var item_phid = JX.Stratcom.getData(item).objectPHID; - var data = { - objectPHID: item_phid, - columnPHID: JX.Stratcom.getData(list.getRootNode()).columnPHID - }; - - var after_phid = null; - var items = finditems(list.getRootNode()); - if (after) { - after_phid = JX.Stratcom.getData(after).objectPHID; - data.afterPHID = after_phid; - } - var ii; - var ii_item; - var ii_item_phid; - var ii_prev_item_phid = null; - var before_phid = null; - for (ii = 0; ii < items.length; ii++) { - ii_item = items[ii]; - ii_item_phid = JX.Stratcom.getData(ii_item).objectPHID; - if (ii_item_phid == item_phid) { - // skip the item we just dropped - continue; - } - // note this handles when there is no after phid - we are at the top of - // the list - quite nicely - if (ii_prev_item_phid == after_phid) { - before_phid = ii_item_phid; - break; - } - ii_prev_item_phid = ii_item_phid; - } - if (before_phid) { - data.beforePHID = before_phid; - } - - data.order = statics.order; - - var workflow = new JX.Workflow(statics.moveURI, data) - .setHandler(function(response) { - onresponse(response, item, list); - }); - - workflow.start(); - } - - function onedit(column, r) { - var new_card = JX.$H(r.tasks).getNode(); - var new_data = JX.Stratcom.getData(new_card); - var items = finditems(column); - var edited = false; - var remove_index = null; - - for (var ii = 0; ii < items.length; ii++) { - var item = items[ii]; - - var data = JX.Stratcom.getData(item); - var phid = data.objectPHID; - - if (phid == new_data.objectPHID) { - if (r.data.removeFromBoard) { - remove_index = ii; - } - items[ii] = new_card; - data = new_data; - edited = true; - } - - data.sort = r.data.sortMap[data.objectPHID] || data.sort; - } - - // this is an add then...! - if (!edited) { - items[items.length + 1] = new_card; - new_data.sort = r.data.sortMap[new_data.objectPHID] || new_data.sort; - } - - if (remove_index !== null) { - items.splice(remove_index, 1); - } - - items.sort(colsort); - - JX.DOM.setContent(column, items); - - onupdate(column); - }; - - function update_statics(update_config) { - statics.boardID = update_config.boardID; - statics.projectPHID = update_config.projectPHID; - statics.order = update_config.order; - statics.moveURI = update_config.moveURI; - statics.createURI = update_config.createURI; - } - - function init_board() { - var lists = []; - var ii; - var cols = getcolumns(); - - for (ii = 0; ii < cols.length; ii++) { - var list = new JX.DraggableList('project-card', cols[ii]) - .setFindItemsHandler(JX.bind(null, finditems, cols[ii])) - .setOuterContainer(JX.$(config.boardID)) - .setCanDragX(true); - - list.listen('didSend', JX.bind(list, onupdate, cols[ii])); - list.listen('didReceive', JX.bind(list, onupdate, cols[ii])); - - list.listen('didDrop', JX.bind(null, ondrop, list)); - - list.listen('didBeginDrag', JX.bind(null, onbegindrag)); - list.listen('didEndDrag', JX.bind(null, onenddrag)); - - lists.push(list); - - onupdate(cols[ii]); - } - - for (ii = 0; ii < lists.length; ii++) { - lists[ii].setGroup(lists); - } - } - - function setup() { - - JX.Stratcom.listen( - 'click', - ['edit-project-card'], - function(e) { - e.kill(); - var column = e.getNode('project-column'); - var request_data = { - responseType: 'card', - columnPHID: JX.Stratcom.getData(column).columnPHID, - order: statics.order - }; - new JX.Workflow(e.getNode('tag:a').href, request_data) - .setHandler(JX.bind(null, onedit, column)) - .start(); - }); - - JX.Stratcom.listen( - 'click', - ['column-add-task'], - function (e) { - - // We want the 'boards-dropdown-menu' behavior to see this event and - // close the dropdown, but don't want to follow the link. - e.prevent(); - - var column_data = e.getNodeData('column-add-task'); - var column_phid = column_data.columnPHID; - - var request_data = { - responseType: 'card', - columnPHID: column_phid, - projects: column_data.projectPHID, - order: statics.order - }; - - var cols = getcolumns(); - var ii; - var column; - for (ii = 0; ii < cols.length; ii++) { - if (JX.Stratcom.getData(cols[ii]).columnPHID == column_phid) { - column = cols[ii]; - break; - } - } - new JX.Workflow(statics.createURI, request_data) - .setHandler(JX.bind(null, onedit, column)) - .start(); - }); - - JX.Stratcom.listen('click', 'boards-dropdown-menu', function(e) { - var data = e.getNodeData('boards-dropdown-menu'); - if (data.menu) { - return; - } - - e.kill(); - - var list = JX.$H(data.items).getFragment().firstChild; - - var button = e.getNode('boards-dropdown-menu'); - data.menu = new JX.PHUIXDropdownMenu(button); - data.menu.setContent(list); - data.menu.open(); - - JX.DOM.listen(list, 'click', 'tag:a', function(e) { - if (!e.isNormalClick()) { - return; - } - data.menu.close(); - }); - }); - - JX.Stratcom.listen( - 'quicksand-redraw', - null, - function (e) { - var data = e.getData(); - if (!data.newResponse.boardConfig) { - return; - } - var new_config; - if (data.fromServer) { - new_config = data.newResponse.boardConfig; - statics.boardConfigCache[data.newResponseID] = new_config; - } else { - new_config = statics.boardConfigCache[data.newResponseID]; - statics.boardID = new_config.boardID; - } - update_statics(new_config); - if (data.fromServer) { - init_board(); - } - }); - return true; - } - - if (!statics.setup) { - update_statics(config); - var current_page_id = JX.Quicksand.getCurrentPageID(); - statics.boardConfigCache = {}; - statics.boardConfigCache[current_page_id] = config; - init_board(); - statics.setup = setup(); - } - -}); diff --git a/scripts/copy_points.php b/scripts/copy_points.php new file mode 100755 index 0000000000000000000000000000000000000000..13e84081deaa3c76efcdbb98beb123f56ba4fa67 --- /dev/null +++ b/scripts/copy_points.php @@ -0,0 +1,115 @@ +#!/usr/bin/env php +<?php + +// See <https://secure.phabricator.com/T10350> for discussion. + +require_once 'scripts/__init_script__.php'; + +$args = new PhutilArgumentParser($argv); +$args->parseStandardArguments(); +$args->parse( + array( + array( + 'name' => 'field', + 'param' => 'key', + 'help' => pht('Field to migrate.'), + ), + )); + +$task = new ManiphestTask(); +$fields = PhabricatorCustomField::getObjectFields( + $task, + PhabricatorCustomField::ROLE_EDIT); + +$field_map = $fields->getFields(); +$field_list = implode(', ', array_keys($field_map)); + +if (!$field_map) { + throw new PhutilArgumentUsageException( + pht( + 'You do not have any custom fields defined in Maniphest, so there is '. + 'nowhere that points can be copied from.')); +} + +$field_key = $args->getArg('field'); +if (!strlen($field_key)) { + throw new PhutilArgumentUsageException( + pht( + 'Use --field to specify which field to copy points from. Available '. + 'fields are: %s.', + $field_list)); +} + +$field = idx($field_map, $field_key); +if (!$field) { + throw new PhutilArgumentUsageException( + pht( + 'Field "%s" is not a valid field. Available fields are: %s.', + $field_key, + $field_list)); +} + +$proxy = $field->getProxy(); +if (!$proxy) { + throw new PhutilArgumentUsageException( + pht( + 'Field "%s" is not a standard custom field, and can not be migrated.', + $field_key, + $field_list)); +} + +if (!($proxy instanceof PhabricatorStandardCustomFieldText)) { + throw new PhutilArgumentUsageException( + pht( + 'Field "%s" is not an "int" field, and can not be migrated.', + $field_key, + $field_list)); +} + +$storage = $field->newStorageObject(); +$conn_r = $storage->establishConnection('r'); + +$value_rows = queryfx_all( + $conn_r, + 'SELECT objectPHID, fieldValue FROM %T WHERE fieldIndex = %s + AND fieldValue IS NOT NULL', + $storage->getTableName(), + $field->getFieldIndex()); +$value_map = ipull($value_rows, 'fieldValue', 'objectPHID'); + +$id_rows = queryfx_all( + $conn_r, + 'SELECT phid, id, points FROM %T', + $task->getTableName()); +$id_map = ipull($id_rows, null, 'phid'); + +foreach ($value_map as $phid => $value) { + $dict = idx($id_map, $phid, array()); + $id = idx($dict, 'id'); + $current_points = idx($dict, 'points'); + + if (!$id) { + echo 'ID NULL'; + continue; + } + + if ($current_points !== null) { + echo 'HAS POINTS'; + continue; + } + + if ($value === null) { + echo 'VALUE NULL'; + continue; + } + + $sql = qsprintf( + $conn_r, + 'UPDATE %T.%T SET points = %f WHERE id = %d;', + 'phabricator_maniphest', + $task->getTableName(), + $value, + $id); + + echo $sql."\n"; +} diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index b5d65dafce3979e188dc8096080824a9a75d9635..0dadd63d7448cd4dbba193405741e0e816813966 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -13,29 +13,17 @@ phutil_register_library_map(array( 'BoardDataPieView' => 'view/burndown/BoardDataPieView.php', 'BoardDataProvider' => 'storage/BoardDataProvider.php', 'BoardDataTableView' => 'view/burndown/BoardDataTableView.php', - 'BurndownActionMenuEventListener' => 'events/BurndownActionMenuEventListener.php', 'BurndownChartView' => 'view/burndown/BurndownChartView.php', 'BurndownDataDate' => 'util/BurndownDataDate.php', 'CeleritySprintResources' => 'celerity/CeleritySprintResources.php', 'DateIterator' => 'tests/DateIterator.php', 'EventTableView' => 'view/burndown/EventTableView.php', 'OpenTasksView' => 'view/reports/OpenTasksView.php', + 'PhragileProfilePanel' => 'profilepanel/PhragileProfilePanel.php', 'ProjectOpenTasksView' => 'view/reports/ProjectOpenTasksView.php', 'SprintApplication' => 'application/SprintApplication.php', 'SprintApplicationTest' => 'tests/SprintApplicationTest.php', 'SprintBeginDateField' => 'customfield/SprintBeginDateField.php', - 'SprintBoardBatchEditController' => 'controller/board/SprintBoardBatchEditController.php', - 'SprintBoardCardToken' => 'util/SprintBoardCardToken.php', - 'SprintBoardColumnDetailController' => 'controller/board/SprintBoardColumnDetailController.php', - 'SprintBoardColumnEditController' => 'controller/board/SprintBoardColumnEditController.php', - 'SprintBoardColumnHideController' => 'controller/board/SprintBoardColumnHideController.php', - 'SprintBoardController' => 'controller/board/SprintBoardController.php', - 'SprintBoardImportController' => 'controller/board/SprintBoardImportController.php', - 'SprintBoardMoveController' => 'controller/board/SprintBoardMoveController.php', - 'SprintBoardReorderController' => 'controller/board/SprintBoardReorderController.php', - 'SprintBoardTaskCard' => 'view/SprintBoardTaskCard.php', - 'SprintBoardTaskEditController' => 'controller/board/SprintBoardTaskEditController.php', - 'SprintBoardViewController' => 'controller/board/SprintBoardViewController.php', 'SprintColumnTransaction' => 'storage/SprintColumnTransaction.php', 'SprintConduitAPIMethod' => 'conduit/SprintConduitAPIMethod.php', 'SprintConfigOptions' => 'config/SprintConfigOptions.php', @@ -61,15 +49,13 @@ phutil_register_library_map(array( 'SprintListController' => 'controller/SprintListController.php', 'SprintListDataProvider' => 'storage/SprintListDataProvider.php', 'SprintListTableView' => 'view/SprintListTableView.php', - 'SprintManiphestEditEngine' => 'controller/board/SprintManiphestEditEngine.php', 'SprintPoints' => 'util/SprintPoints.php', 'SprintProjectController' => 'controller/SprintProjectController.php', 'SprintProjectCustomField' => 'customfield/SprintProjectCustomField.php', - 'SprintProjectDetailsProfilePanel' => 'profilepanel/SprintProjectDetailsProfilePanel.php', 'SprintProjectProfileController' => 'controller/SprintProjectProfileController.php', + 'SprintProjectProfilePanel' => 'profilepanel/SprintProjectProfilePanel.php', 'SprintProjectProfilePanelEngine' => 'engine/SprintProjectProfilePanelEngine.php', 'SprintProjectViewController' => 'controller/SprintProjectViewController.php', - 'SprintProjectWorkboardProfilePanel' => 'profilepanel/SprintProjectWorkboardProfilePanel.php', 'SprintQuery' => 'query/SprintQuery.php', 'SprintQueryTest' => 'tests/SprintQueryTest.php', 'SprintReportBurnUpView' => 'view/reports/SprintReportBurnUpView.php', @@ -93,28 +79,16 @@ phutil_register_library_map(array( 'xmap' => array( 'BoardDataPieView' => 'Phobject', 'BoardDataTableView' => 'Phobject', - 'BurndownActionMenuEventListener' => 'PhabricatorEventListener', 'BurndownChartView' => 'Phobject', 'BurndownDataDate' => 'Phobject', 'CeleritySprintResources' => 'CelerityResourcesOnDisk', 'DateIterator' => 'Iterator', 'EventTableView' => 'Phobject', + 'PhragileProfilePanel' => 'PhabricatorProfilePanel', 'ProjectOpenTasksView' => 'OpenTasksView', 'SprintApplication' => 'PhabricatorApplication', 'SprintApplicationTest' => 'SprintTestCase', 'SprintBeginDateField' => 'SprintProjectCustomField', - 'SprintBoardBatchEditController' => 'ManiphestController', - 'SprintBoardCardToken' => 'Phobject', - 'SprintBoardColumnDetailController' => 'SprintBoardController', - 'SprintBoardColumnEditController' => 'SprintBoardController', - 'SprintBoardColumnHideController' => 'SprintBoardController', - 'SprintBoardController' => 'SprintProjectController', - 'SprintBoardImportController' => 'SprintBoardController', - 'SprintBoardMoveController' => 'SprintBoardController', - 'SprintBoardReorderController' => 'SprintBoardController', - 'SprintBoardTaskCard' => 'Phobject', - 'SprintBoardTaskEditController' => 'ManiphestController', - 'SprintBoardViewController' => 'SprintBoardController', 'SprintConduitAPIMethod' => 'ConduitAPIMethod', 'SprintConfigOptions' => 'PhabricatorApplicationConfigOptions', 'SprintController' => 'PhabricatorController', @@ -136,18 +110,16 @@ phutil_register_library_map(array( 'SprintIsSprintField' => 'SprintProjectCustomField', 'SprintListController' => 'SprintController', 'SprintListTableView' => 'Phobject', - 'SprintManiphestEditEngine' => 'PhabricatorEditEngine', 'SprintPoints' => 'Phobject', 'SprintProjectController' => 'SprintController', 'SprintProjectCustomField' => array( 'PhabricatorProjectCustomField', 'PhabricatorStandardCustomFieldInterface', ), - 'SprintProjectDetailsProfilePanel' => 'PhabricatorProfilePanel', 'SprintProjectProfileController' => 'SprintProjectController', + 'SprintProjectProfilePanel' => 'PhabricatorProfilePanel', 'SprintProjectProfilePanelEngine' => 'PhabricatorProfilePanelEngine', 'SprintProjectViewController' => 'SprintController', - 'SprintProjectWorkboardProfilePanel' => 'PhabricatorProfilePanel', 'SprintQuery' => 'SprintDAO', 'SprintQueryTest' => 'SprintTestCase', 'SprintReportBurnUpView' => 'SprintView', diff --git a/src/application/SprintApplication.php b/src/application/SprintApplication.php index b337ea7d6be7727dc05fcb2fafabb78f7191fabe..7d429f20a268f4439c0685a0c5bd1c86917cb70e 100644 --- a/src/application/SprintApplication.php +++ b/src/application/SprintApplication.php @@ -1,4 +1,5 @@ <?php + /** * @author Michael Peters * @author Christopher Johnson @@ -23,44 +24,11 @@ final class SprintApplication extends PhabricatorApplication { return 'Build Sprints'; } - public function getEventListeners() { - return array( - new BurndownActionMenuEventListener(), - ); - } - public function getRoutes() { - $enable_board = PhabricatorEnv::getEnvConfig('sprint.enable-sprint-board'); - if ($enable_board == true) { return array( // this is the default application route controller '/project/sprint/' => array( '' => 'SprintListController', - // these are forked controllers for the Sprint Board - 'board/(?P<projectID>[1-9]\d*)/' => array( - 'edit/(?:(?P<id>\d+)/)?' - => 'SprintBoardColumnEditController', - 'hide/(?:(?P<id>\d+)/)?' - => 'SprintBoardColumnHideController', - 'column/(?:(?P<id>\d+)/)?' - => 'SprintBoardColumnDetailController', - 'import/' - => 'SprintBoardImportController', - 'reorder/' - => 'SprintBoardReorderController', - ), - // these allow task creation and editing from a Sprint Board - 'board/task/edit/(?P<id>[1-9]\d*)/' - => 'SprintBoardTaskEditController', - 'board/task/create/' - => 'SprintBoardTaskEditController', - 'board/batch/' - => 'SprintBoardBatchEditController', - // these are for board filters and column queries - 'board/(?P<id>[1-9]\d*)/'. - '(?P<filter>filter/)?'. - '(?:query/(?P<queryKey>[^/]+)/)?' - => 'SprintBoardViewController', // these are native Sprint application controllers 'burn/(?P<id>\d+)/' => 'SprintDataViewController', 'profile/(?P<id>[1-9]\d*)/' @@ -69,93 +37,9 @@ final class SprintApplication extends PhabricatorApplication { 'report/history/' => 'SprintHistoryController', 'report/(?:(?P<view>\w+)/)?' => 'SprintReportController', 'view/(?P<id>\d+)/' => 'SprintDataViewController', - // all routes following point to default controllers - 'archive/(?P<id>[1-9]\d*)/' - => 'PhabricatorProjectArchiveController', - $this->getEditRoutePattern('edit/') - => 'PhabricatorProjectEditController', - 'feed/(?P<id>[1-9]\d*)/' - => 'PhabricatorProjectFeedController', - 'icon/(?P<id>[1-9]\d*)/' - => 'PhabricatorProjectEditIconController', - 'members/(?P<id>[1-9]\d*)/' - => 'PhabricatorProjectMembersEditController', - 'members/(?P<id>[1-9]\d*)/remove/' - => 'PhabricatorProjectMembersRemoveController', - 'milestones/(?P<id>[1-9]\d*)/' - => 'PhabricatorProjectMilestonesController', - 'move/(?P<id>[1-9]\d*)/' => 'SprintBoardMoveController', - 'picture/(?P<id>[1-9]\d*)/' - => 'PhabricatorProjectEditPictureController', - 'subprojects/(?P<id>[1-9]\d*)/' - => 'PhabricatorProjectSubprojectsController', - 'update/(?P<id>[1-9]\d*)/(?P<action>[^/]+)/' - => 'PhabricatorProjectUpdateController', - ), - // primary tag route override - '/tag/' => array( - '(?P<slug>[^/]+)/' => 'SprintProjectViewController', - '(?P<slug>[^/]+)/board/' => 'SprintBoardViewController', - ), - ); - } else { - return array( - // this is the default application route controller - '/project/sprint/' => array( - '' => 'SprintListController', - 'board/(?P<projectID>[1-9]\d*)/' => array( - 'edit/(?:(?P<id>\d+)/)?' - => 'PhabricatorProjectBoardColumnEditController', - 'hide/(?:(?P<id>\d+)/)?' - => 'PhabricatorProjectBoardColumnHideController', - 'column/(?:(?P<id>\d+)/)?' - => 'PhabricatorProjectBoardColumnDetailController', - 'import/' - => 'PhabricatorProjectBoardImportController', - 'reorder/' - => 'PhabricatorProjectBoardReorderController', - ), - // these are for board filters and column queries - 'board/(?P<id>[1-9]\d*)/'. - '(?P<filter>filter/)?'. - '(?:query/(?P<queryKey>[^/]+)/)?' - => 'PhabricatorProjectBoardViewController', - // these are native Sprint application controllers - 'burn/(?P<id>\d+)/' => 'SprintDataViewController', - 'profile/(?P<id>[1-9]\d*)/' - => 'SprintProjectProfileController', - 'report/list/' => 'SprintListController', - 'report/history/' => 'SprintHistoryController', - 'report/(?:(?P<view>\w+)/)?' => 'SprintReportController', - 'view/(?P<id>\d+)/' => 'SprintDataViewController', - // all routes following point to default controllers - 'archive/(?P<id>[1-9]\d*)/' - => 'PhabricatorProjectArchiveController', - 'details/(?P<id>[1-9]\d*)/' - => 'PhabricatorProjectEditDetailsController', - 'feed/(?P<id>[1-9]\d*)/' - => 'PhabricatorProjectFeedController', - 'icon/(?P<id>[1-9]\d*)/' - => 'PhabricatorProjectEditIconController', - 'lock/(?P<id>[1-9]\d*)/' - => 'PhabricatorProjectLockController', - 'members/(?P<id>[1-9]\d*)/' - => 'PhabricatorProjectMembersEditController', - 'members/(?P<id>[1-9]\d*)/remove/' - => 'PhabricatorProjectMembersRemoveController', - 'move/(?P<id>[1-9]\d*)/' => 'SprintBoardMoveController', - 'milestones/(?P<id>[1-9]\d*)/' - => 'PhabricatorProjectMilestonesController', - 'picture/(?P<id>[1-9]\d*)/' - => 'PhabricatorProjectEditPictureController', - 'subprojects/(?P<id>[1-9]\d*)/' - => 'PhabricatorProjectSubprojectsController', - 'update/(?P<id>[1-9]\d*)/(?P<action>[^/]+)/' - => 'PhabricatorProjectUpdateController', ), ); } - } protected function getCustomCapabilities() { return array( diff --git a/src/celerity/map.php b/src/celerity/map.php index 54c921c75813c8f35ff4bb599ded1ba34ad2a038..b443d0a59c2e0941714b0385b243d02493228d4c 100644 --- a/src/celerity/map.php +++ b/src/celerity/map.php @@ -13,7 +13,6 @@ return array( 'behavior-c3-pie.js' => 'ae804fb1', 'behavior-events-table.js' => 'f2c22d32', 'behavior-priority-pie.js' => 'f72c0144', - 'behavior-sprint-boards.js' => '3ea227aa', 'behavior-sprint-history-table.js' => 'b38db637', 'behavior-sprint-table.js' => '7fb99402', 'behavior-tasks-table.js' => '04f4d973', @@ -42,7 +41,6 @@ return array( 'javelin-behavior-c3-pie' => 'ae804fb1', 'javelin-behavior-events-table' => 'f2c22d32', 'javelin-behavior-priority-pie' => 'f72c0144', - 'javelin-behavior-sprint-boards' => '3ea227aa', 'javelin-behavior-sprint-history-table' => 'b38db637', 'javelin-behavior-sprint-table' => '7fb99402', 'javelin-behavior-tasks-table' => '04f4d973', diff --git a/src/config/SprintConfigOptions.php b/src/config/SprintConfigOptions.php index 6758f7f6268bc5e4fb03032f0ae08866c430dd8a..d23df345d45ef704f56e4f48a59179c69ba7179b 100644 --- a/src/config/SprintConfigOptions.php +++ b/src/config/SprintConfigOptions.php @@ -77,17 +77,6 @@ final class SprintConfigOptions pht( "The Pie Charts are optional". "\n\n.")), - $this->newOption('sprint.enable-sprint-board', 'bool', true) - ->setBoolOptions( - array( - pht('Enable Sprint Board'), - pht('Disble Sprint Board'), - )) - ->setSummary(pht('Enable or Disable Sprint Board.')) - ->setDescription( - pht( - "The Sprint Board is optional". - "\n\n.")), $this->newOption('sprint.enable-phragile', 'bool', false) ->setBoolOptions( array( diff --git a/src/constants/SprintConstants.php b/src/constants/SprintConstants.php index 8ad57ecd17e3212e851ac30ed1237a9716fa34a7..69d4a50611700eb23118d07c1adcacaf4bd83298 100644 --- a/src/constants/SprintConstants.php +++ b/src/constants/SprintConstants.php @@ -12,4 +12,8 @@ final class SprintConstants { const TYPE_REVIEW_STATUS_COLUMN = 'Review'; const TYPE_DOING_STATUS_COLUMN = 'Doing'; const TYPE_BACKLOG_STATUS_COLUMN = 'Backlog'; + const PANEL_BURNDOWN = 'project.sprint'; + const PANEL_PHRAGILE = 'project.phragile'; + + } diff --git a/src/controller/SprintController.php b/src/controller/SprintController.php index a05d62535599f5bce1e2f29876be3ffd0ddb64d0..cc07ef5a146a164a7638e5bcac61ab1746066f43 100644 --- a/src/controller/SprintController.php +++ b/src/controller/SprintController.php @@ -1,4 +1,5 @@ <?php + /** * @author Michael Peters * @author Christopher Johnson diff --git a/src/controller/SprintDataViewController.php b/src/controller/SprintDataViewController.php index 5113cfffae4f3821e19b6f1cedcb7c3e7d7bbce2..95066b2b4eb2c3e13bd3a34ceaf1df8212e1daf0 100755 --- a/src/controller/SprintDataViewController.php +++ b/src/controller/SprintDataViewController.php @@ -71,11 +71,6 @@ final class SprintDataViewController extends SprintController { $this->project->getName(), $this->getApplicationURI().'profile/'.$this->projectID); $crumbs->addTextCrumb(pht('Burndown')); - $crumbs->addAction( - id(new PHUIListItemView()) - ->setName(pht('Sprint Board')) - ->setHref($this->getApplicationURI().'board/'.$this->projectID) - ->setIcon('fa-columns')); return $crumbs; } diff --git a/src/controller/SprintProjectController.php b/src/controller/SprintProjectController.php index 0fb1ce547dfabb122e9ed8a9c8f656e23d794c13..f377774c23315496e891663220229f395095df09 100644 --- a/src/controller/SprintProjectController.php +++ b/src/controller/SprintProjectController.php @@ -5,6 +5,8 @@ abstract class SprintProjectController extends SprintController { private $project; private $profileMenu; + const PANEL_BURNDOWN = 'project.sprint'; + protected function setProject(PhabricatorProject $project) { $this->project = $project; return $this; diff --git a/src/controller/SprintProjectProfileController.php b/src/controller/SprintProjectProfileController.php index 6e6139d091fa50b9a9a91c00445d5680b3f96a7b..71ce5e408406368de40fed076337d69b94e3389f 100644 --- a/src/controller/SprintProjectProfileController.php +++ b/src/controller/SprintProjectProfileController.php @@ -28,10 +28,11 @@ final class SprintProjectProfileController ->setType(PHUITagView::TYPE_SHADE); $header = id(new PHUIHeaderView()) - ->setHeader($project->getName()) + ->setHeader(array($project->getDisplayName(), $tag)) ->setUser($viewer) ->setPolicyObject($project) - ->setImage($picture); + ->setImage($picture) + ->setProfileHeader(true); if ($project->getStatus() == PhabricatorProjectStatus::STATUS_ACTIVE) { $header->setStatus('fa-check', 'bluegrey', pht('Active')); @@ -39,197 +40,248 @@ final class SprintProjectProfileController $header->setStatus('fa-ban', 'red', pht('Archived')); } - $actions = $this->buildActionListView($project); - $properties = $this->buildPropertyListView($project, $actions); + $can_edit = PhabricatorPolicyFilter::hasCapability( + $viewer, + $project, + PhabricatorPolicyCapability::CAN_EDIT); - $object_box = id(new PHUIObjectBoxView()) - ->setHeader($header) - ->addPropertyList($properties); + if ($can_edit) { + $header->setImageEditURL($this->getApplicationURI("picture/{$id}/")); + } + + $properties = $this->buildPropertyListView($project); - $timeline = $this->buildTransactionTimeline( - $project, - new PhabricatorProjectTransactionQuery()); - $timeline->setShouldTerminate(true); + $watch_action = $this->renderWatchAction($project); + $header->addActionLink($watch_action); + + $milestone_list = $this->buildMilestoneList($project); + $subproject_list = $this->buildSubprojectList($project); + + $member_list = id(new PhabricatorProjectMemberListView()) + ->setUser($viewer) + ->setProject($project) + ->setLimit(5) + ->setBackground(PHUIBoxView::GREY) + ->setUserPHIDs($project->getMemberPHIDs()); + + $watcher_list = id(new PhabricatorProjectWatcherListView()) + ->setUser($viewer) + ->setProject($project) + ->setLimit(5) + ->setBackground(PHUIBoxView::GREY) + ->setUserPHIDs($project->getWatcherPHIDs()); $nav = $this->getProfileMenu(); $nav->selectFilter(PhabricatorProject::PANEL_PROFILE); + + $stories = id(new PhabricatorFeedQuery()) + ->setViewer($viewer) + ->setFilterPHIDs( + array( + $project->getPHID(), + )) + ->setLimit(50) + ->execute(); + + $feed = $this->renderStories($stories); + $feed = phutil_tag_div('project-view-feed', $feed); + + $columns = id(new PHUITwoColumnView()) + ->setMainColumn( + array( + $properties, + $feed, + )) + ->setSideColumn( + array( + $milestone_list, + $subproject_list, + $member_list, + $watcher_list, + )); + $crumbs = $this->buildApplicationCrumbs(); + $crumbs->setBorder(true); + + require_celerity_resource('project-view-css'); + $home = phutil_tag( + 'div', + array( + 'class' => 'project-view-home', + ), + array( + $header, + $columns, + )); return $this->newPage() - ->setNavigation($nav) - ->setCrumbs($crumbs) - ->setTitle($project->getName()) - ->setPageObjectPHIDs(array($project->getPHID())) - ->appendChild($object_box) - ->appendChild($timeline); + ->setNavigation($nav) + ->setCrumbs($crumbs) + ->setTitle($project->getDisplayName()) + ->setPageObjectPHIDs(array($project->getPHID())) + ->appendChild( + array( + $home, + )); } - private function buildActionListView(PhabricatorProject $project) { + private function buildPropertyListView( + PhabricatorProject $project) { $request = $this->getRequest(); $viewer = $request->getViewer(); - $id = $project->getID(); - - $view = id(new PhabricatorActionListView()) + $view = id(new PHUIPropertyListView()) ->setUser($viewer) ->setObject($project); - $can_edit = PhabricatorPolicyFilter::hasCapability( - $viewer, + $field_list = PhabricatorCustomField::getObjectFields( $project, - PhabricatorPolicyCapability::CAN_EDIT); + PhabricatorCustomField::ROLE_VIEW); + $field_list->appendFieldsToPropertyList($project, $viewer, $view); - $view->addAction( - id(new PhabricatorActionView()) - ->setName(pht('Edit Details')) - ->setIcon('fa-pencil') - ->setHref($this->getApplicationURI("edit/{$id}/")) - ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit)); - - $view->addAction( - id(new PhabricatorActionView()) - ->setName(pht('Edit Picture')) - ->setIcon('fa-picture-o') - ->setHref($this->getApplicationURI("picture/{$id}/")) - ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit)); - - if ($project->isArchived()) { - $view->addAction( - id(new PhabricatorActionView()) - ->setName(pht('Activate Project')) - ->setIcon('fa-check') - ->setHref($this->getApplicationURI("archive/{$id}/")) - ->setDisabled(!$can_edit) - ->setWorkflow(true)); - } else { - $view->addAction( - id(new PhabricatorActionView()) - ->setName(pht('Archive Project')) - ->setIcon('fa-ban') - ->setHref($this->getApplicationURI("archive/{$id}/")) - ->setDisabled(!$can_edit) - ->setWorkflow(true)); + if (!$view->hasAnyProperties()) { + return null; } - $can_lock = $can_edit && $this->hasApplicationCapability( - ProjectCanLockProjectsCapability::CAPABILITY); + $view = id(new PHUIBoxView()) + ->setColor(PHUIBoxView::GREY) + ->appendChild($view) + ->addClass('project-view-properties'); - if ($project->getIsMembershipLocked()) { - $lock_name = pht('Unlock Project'); - $lock_icon = 'fa-unlock'; - } else { - $lock_name = pht('Lock Project'); - $lock_icon = 'fa-lock'; - } + return $view; + } + + private function renderStories(array $stories) { + assert_instances_of($stories, 'PhabricatorFeedStory'); + + $builder = new PhabricatorFeedBuilder($stories); + $builder->setUser($this->getRequest()->getUser()); + $builder->setShowHovercards(true); + $view = $builder->buildView(); + + return $view; + } - $view->addAction( - id(new PhabricatorActionView()) - ->setName($lock_name) - ->setIcon($lock_icon) - ->setHref($this->getApplicationURI("lock/{$id}/")) - ->setDisabled(!$can_lock) - ->setWorkflow(true)); - - $action = null; - if (!$project->isUserMember($viewer->getPHID())) { - $can_join = PhabricatorPolicyFilter::hasCapability( - $viewer, - $project, - PhabricatorPolicyCapability::CAN_JOIN); - - $action = id(new PhabricatorActionView()) - ->setUser($viewer) - ->setRenderAsForm(true) - ->setHref('/project/update/'.$project->getID().'/join/') - ->setIcon('fa-plus') - ->setDisabled(!$can_join) - ->setName(pht('Join Project')); - $view->addAction($action); + private function renderWatchAction(PhabricatorProject $project) { + $viewer = $this->getViewer(); + $viewer_phid = $viewer->getPHID(); + $id = $project->getID(); + + $is_watcher = ($viewer_phid && $project->isUserWatcher($viewer_phid)); + + if (!$is_watcher) { + $watch_icon = 'fa-eye'; + $watch_text = pht('Watch Project'); + $watch_href = "/project/watch/{$id}/?via=profile"; } else { - $action = id(new PhabricatorActionView()) - ->setWorkflow(true) - ->setHref('/project/update/'.$project->getID().'/leave/') - ->setIcon('fa-times') - ->setName(pht('Leave Project...')); - $view->addAction($action); - - if (!$project->isUserWatcher($viewer->getPHID())) { - $action = id(new PhabricatorActionView()) - ->setWorkflow(true) - ->setHref('/project/watch/'.$project->getID().'/') - ->setIcon('fa-eye') - ->setName(pht('Watch Project')); - $view->addAction($action); - } else { - $action = id(new PhabricatorActionView()) - ->setWorkflow(true) - ->setHref('/project/unwatch/'.$project->getID().'/') - ->setIcon('fa-eye-slash') - ->setName(pht('Unwatch Project')); - $view->addAction($action); - } + $watch_icon = 'fa-eye-slash'; + $watch_text = pht('Unwatch Project'); + $watch_href = "/project/unwatch/{$id}/?via=profile"; } - return $view; + $watch_icon = id(new PHUIIconView()) + ->setIcon($watch_icon); + + return id(new PHUIButtonView()) + ->setTag('a') + ->setWorkflow(true) + ->setIcon($watch_icon) + ->setText($watch_text) + ->setHref($watch_href); } - private function buildPropertyListView( - PhabricatorProject $project, - PhabricatorActionListView $actions) { - $request = $this->getRequest(); - $viewer = $request->getViewer(); + private function buildMilestoneList(PhabricatorProject $project) { + if (!$project->getHasMilestones()) { + return null; + } - $view = id(new PHUIPropertyListView()) + $viewer = $this->getViewer(); + $id = $project->getID(); + + $milestones = id(new PhabricatorProjectQuery()) + ->setViewer($viewer) + ->withParentProjectPHIDs(array($project->getPHID())) + ->needImages(true) + ->withIsMilestone(true) + ->withStatuses( + array( + PhabricatorProjectStatus::STATUS_ACTIVE, + )) + ->setOrder('newest') + ->execute(); + if (!$milestones) { + return null; + } + + $milestone_list = id(new PhabricatorProjectListView()) ->setUser($viewer) - ->setObject($project) - ->setActionList($actions); - - $hashtags = array(); - foreach ($project->getSlugs() as $slug) { - $hashtags[] = id(new PHUITagView()) - ->setType(PHUITagView::TYPE_OBJECT) - ->setName('#'.$slug->getSlug()); + ->setProjects($milestones) + ->renderList(); + + $view_all = id(new PHUIButtonView()) + ->setTag('a') + ->setIcon( + id(new PHUIIconView()) + ->setIcon('fa-list-ul')) + ->setText(pht('View All')) + ->setHref("/project/subprojects/{$id}/"); + + $header = id(new PHUIHeaderView()) + ->setHeader(pht('Milestones')) + ->addActionLink($view_all); + + return id(new PHUIObjectBoxView()) + ->setHeader($header) + ->setBackground(PHUIBoxView::GREY) + ->setObjectList($milestone_list); + } + + private function buildSubprojectList(PhabricatorProject $project) { + if (!$project->getHasSubprojects()) { + return null; } - if ($hashtags) { - $view->addProperty(pht('Hashtags'), phutil_implode_html(' ', $hashtags)); + $viewer = $this->getViewer(); + $id = $project->getID(); + + $limit = 25; + + $subprojects = id(new PhabricatorProjectQuery()) + ->setViewer($viewer) + ->withParentProjectPHIDs(array($project->getPHID())) + ->needImages(true) + ->withStatuses( + array( + PhabricatorProjectStatus::STATUS_ACTIVE, + )) + ->withIsMilestone(false) + ->setLimit($limit) + ->execute(); + if (!$subprojects) { + return null; } - $view->addProperty( - pht('Members'), - $project->getMemberPHIDs() - ? $viewer - ->renderHandleList($project->getMemberPHIDs()) - ->setAsInline(true) - : phutil_tag('em', array(), pht('None'))); - - $view->addProperty( - pht('Watchers'), - $project->getWatcherPHIDs() - ? $viewer - ->renderHandleList($project->getWatcherPHIDs()) - ->setAsInline(true) - : phutil_tag('em', array(), pht('None'))); - - $descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions( - $viewer, - $project); - - $view->addProperty( - pht('Looks Like'), - $viewer->renderHandle($project->getPHID())->setAsTag(true)); - - $view->addProperty( - pht('Joinable By'), - $descriptions[PhabricatorPolicyCapability::CAN_JOIN]); + $subproject_list = id(new PhabricatorProjectListView()) + ->setUser($viewer) + ->setProjects($subprojects) + ->renderList(); - $field_list = PhabricatorCustomField::getObjectFields( - $project, - PhabricatorCustomField::ROLE_VIEW); - $field_list->appendFieldsToPropertyList($project, $viewer, $view); + $view_all = id(new PHUIButtonView()) + ->setTag('a') + ->setIcon( + id(new PHUIIconView()) + ->setIcon('fa-list-ul')) + ->setText(pht('View All')) + ->setHref("/project/subprojects/{$id}/"); - return $view; + $header = id(new PHUIHeaderView()) + ->setHeader(pht('Subprojects')) + ->addActionLink($view_all); + + return id(new PHUIObjectBoxView()) + ->setHeader($header) + ->setBackground(PHUIBoxView::GREY) + ->setObjectList($subproject_list); } + } diff --git a/src/controller/board/SprintBoardBatchEditController.php b/src/controller/board/SprintBoardBatchEditController.php deleted file mode 100644 index 49133e9ce5daee4b78c99e3bd3ebfe70374a387a..0000000000000000000000000000000000000000 --- a/src/controller/board/SprintBoardBatchEditController.php +++ /dev/null @@ -1,406 +0,0 @@ -<?php - -final class SprintBoardBatchEditController extends ManiphestController { - - public function handleRequest(AphrontRequest $request) { - $viewer = $this->getViewer(); - - $this->requireApplicationCapability( - ManiphestBulkEditCapability::CAPABILITY); - - $project = null; - $board_id = $request->getInt('board'); - if ($board_id) { - $project = id(new PhabricatorProjectQuery()) - ->setViewer($viewer) - ->withIDs(array($board_id)) - ->executeOne(); - if (!$project) { - return new Aphront404Response(); - } - } - - $task_ids = $request->getArr('batch'); - if (!$task_ids) { - $task_ids = $request->getStrList('batch'); - } - - $tasks = id(new ManiphestTaskQuery()) - ->setViewer($viewer) - ->withIDs($task_ids) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->needSubscriberPHIDs(true) - ->needProjectPHIDs(true) - ->execute(); - - if ($project) { - $cancel_uri = '/project/sprint/board/'.$project->getID().'/'; - $redirect_uri = $cancel_uri; - } else { - $cancel_uri = '/maniphest/'; - $redirect_uri = '/maniphest/?ids='.implode(',', mpull($tasks, 'getID')); - } - - $actions = $request->getStr('actions'); - if ($actions) { - $actions = phutil_json_decode($actions); - } - - if ($request->isFormPost() && is_array($actions)) { - foreach ($tasks as $task) { - $field_list = PhabricatorCustomField::getObjectFields( - $task, - PhabricatorCustomField::ROLE_EDIT); - $field_list->readFieldsFromStorage($task); - - $xactions = $this->buildTransactions($actions, $task); - if ($xactions) { - // TODO: Set content source to "batch edit". - - $editor = id(new ManiphestTransactionEditor()) - ->setActor($viewer) - ->setContentSourceFromRequest($request) - ->setContinueOnNoEffect(true) - ->setContinueOnMissingFields(true) - ->applyTransactions($task, $xactions); - } - } - - return id(new AphrontRedirectResponse())->setURI($redirect_uri); - } - - $handles = ManiphestTaskListView::loadTaskHandles($viewer, $tasks); - - $list = new ManiphestTaskListView(); - $list->setTasks($tasks); - $list->setUser($viewer); - $list->setHandles($handles); - - $template = new AphrontTokenizerTemplateView(); - $template = $template->render(); - - $projects_source = new PhabricatorProjectDatasource(); - $mailable_source = new PhabricatorMetaMTAMailableDatasource(); - $mailable_source->setViewer($viewer); - $owner_source = new ManiphestAssigneeDatasource(); - $owner_source->setViewer($viewer); - - require_celerity_resource('maniphest-batch-editor'); - Javelin::initBehavior( - 'maniphest-batch-editor', - array( - 'root' => 'maniphest-batch-edit-form', - 'tokenizerTemplate' => $template, - 'sources' => array( - 'project' => array( - 'src' => $projects_source->getDatasourceURI(), - 'placeholder' => $projects_source->getPlaceholderText(), - 'browseURI' => $projects_source->getBrowseURI(), - ), - 'owner' => array( - 'src' => $owner_source->getDatasourceURI(), - 'placeholder' => $owner_source->getPlaceholderText(), - 'browseURI' => $owner_source->getBrowseURI(), - 'limit' => 1, - ), - 'cc' => array( - 'src' => $mailable_source->getDatasourceURI(), - 'placeholder' => $mailable_source->getPlaceholderText(), - 'browseURI' => $mailable_source->getBrowseURI(), - ), - ), - 'input' => 'batch-form-actions', - 'priorityMap' => ManiphestTaskPriority::getTaskPriorityMap(), - 'statusMap' => ManiphestTaskStatus::getTaskStatusMap(), - )); - - $form = id(new AphrontFormView()) - ->setUser($viewer) - ->addHiddenInput('board', $board_id) - ->setID('maniphest-batch-edit-form'); - - foreach ($tasks as $task) { - $form->appendChild( - phutil_tag( - 'input', - array( - 'type' => 'hidden', - 'name' => 'batch[]', - 'value' => $task->getID(), - ))); - } - - $form->appendChild( - phutil_tag( - 'input', - array( - 'type' => 'hidden', - 'name' => 'actions', - 'id' => 'batch-form-actions', - ))); - $form->appendChild( - id(new PHUIFormInsetView()) - ->setTitle(pht('Actions')) - ->setRightButton(javelin_tag( - 'a', - array( - 'href' => '#', - 'class' => 'button green', - 'sigil' => 'add-action', - 'mustcapture' => true, - ), - pht('Add Another Action'))) - ->setContent(javelin_tag( - 'table', - array( - 'sigil' => 'maniphest-batch-actions', - 'class' => 'maniphest-batch-actions-table', - ), - ''))) - ->appendChild( - id(new AphrontFormSubmitControl()) - ->setValue(pht('Update Tasks')) - ->addCancelButton($cancel_uri)); - - $title = pht('Batch Editor'); - - $crumbs = $this->buildApplicationCrumbs(); - $crumbs->addTextCrumb($title); - - $task_box = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Selected Tasks')) - ->setObjectList($list); - - $form_box = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Batch Editor')) - ->setForm($form); - - return $this->buildApplicationPage( - array( - $crumbs, - $task_box, - $form_box, - ), - array( - 'title' => $title, - )); - } - - private function buildTransactions($actions, ManiphestTask $task) { - $value_map = array(); - $type_map = array( - 'add_comment' => PhabricatorTransactions::TYPE_COMMENT, - 'assign' => ManiphestTransaction::TYPE_OWNER, - 'status' => ManiphestTransaction::TYPE_STATUS, - 'priority' => ManiphestTransaction::TYPE_PRIORITY, - 'add_project' => PhabricatorTransactions::TYPE_EDGE, - 'remove_project' => PhabricatorTransactions::TYPE_EDGE, - 'add_ccs' => PhabricatorTransactions::TYPE_SUBSCRIBERS, - 'remove_ccs' => PhabricatorTransactions::TYPE_SUBSCRIBERS, - ); - - $edge_edit_types = array( - 'add_project' => true, - 'remove_project' => true, - 'add_ccs' => true, - 'remove_ccs' => true, - ); - - $xactions = array(); - foreach ($actions as $action) { - if (empty($type_map[$action['action']])) { - throw new Exception("Unknown batch edit action '{$action}'!"); - } - - $type = $type_map[$action['action']]; - - // Figure out the current value, possibly after modifications by other - // batch actions of the same type. For example, if the user chooses to - // "Add Comment" twice, we should add both comments. More notably, if the - // user chooses "Remove Project..." and also "Add Project...", we should - // avoid restoring the removed project in the second transaction. - - if (array_key_exists($type, $value_map)) { - $current = $value_map[$type]; - } else { - switch ($type) { - case PhabricatorTransactions::TYPE_COMMENT: - $current = null; - break; - case ManiphestTransaction::TYPE_OWNER: - $current = $task->getOwnerPHID(); - break; - case ManiphestTransaction::TYPE_STATUS: - $current = $task->getStatus(); - break; - case ManiphestTransaction::TYPE_PRIORITY: - $current = $task->getPriority(); - break; - case PhabricatorTransactions::TYPE_EDGE: - $current = $task->getProjectPHIDs(); - break; - case PhabricatorTransactions::TYPE_SUBSCRIBERS: - $current = $task->getSubscriberPHIDs(); - break; - } - } - - // Check if the value is meaningful / provided, and normalize it if - // necessary. This discards, e.g., empty comments and empty owner - // changes. - - $value = $action['value']; - switch ($type) { - case PhabricatorTransactions::TYPE_COMMENT: - if (!strlen($value)) { - continue 2; - } - break; - case ManiphestTransaction::TYPE_OWNER: - if (empty($value)) { - continue 2; - } - $value = head($value); - $no_owner = PhabricatorPeopleNoOwnerDatasource::FUNCTION_TOKEN; - if ($value === $no_owner) { - $value = null; - } - break; - case PhabricatorTransactions::TYPE_EDGE: - if (empty($value)) { - continue 2; - } - break; - case PhabricatorTransactions::TYPE_SUBSCRIBERS: - if (empty($value)) { - continue 2; - } - break; - } - - // If the edit doesn't change anything, go to the next action. This - // check is only valid for changes like "owner", "status", etc, not - // for edge edits, because we should still apply an edit like - // "Remove Projects: A, B" to a task with projects "A, B". - - if (empty($edge_edit_types[$action['action']])) { - if ($value == $current) { - continue; - } - } - - // Apply the value change; for most edits this is just replacement, but - // some need to merge the current and edited values (add/remove project). - - switch ($type) { - case PhabricatorTransactions::TYPE_COMMENT: - if (strlen($current)) { - $value = $current."\n\n".$value; - } - break; - case PhabricatorTransactions::TYPE_EDGE: - $is_remove = $action['action'] == 'remove_project'; - - $current = array_fill_keys($current, true); - $value = array_fill_keys($value, true); - - $new = $current; - $did_something = false; - - if ($is_remove) { - foreach ($value as $phid => $ignored) { - if (isset($new[$phid])) { - unset($new[$phid]); - $did_something = true; - } - } - } else { - foreach ($value as $phid => $ignored) { - if (empty($new[$phid])) { - $new[$phid] = true; - $did_something = true; - } - } - } - - if (!$did_something) { - continue 2; - } - - $value = array_keys($new); - break; - case PhabricatorTransactions::TYPE_SUBSCRIBERS: - $is_remove = $action['action'] == 'remove_ccs'; - - $current = array_fill_keys($current, true); - - $new = array(); - $did_something = false; - - if ($is_remove) { - foreach ($value as $phid) { - if (isset($current[$phid])) { - $new[$phid] = true; - $did_something = true; - } - } - if ($new) { - $value = array('-' => array_keys($new)); - } - } else { - $new = array(); - foreach ($value as $phid) { - $new[$phid] = true; - $did_something = true; - } - if ($new) { - $value = array('+' => array_keys($new)); - } - } - if (!$did_something) { - continue 2; - } - - break; - } - - $value_map[$type] = $value; - } - - $template = new ManiphestTransaction(); - - foreach ($value_map as $type => $value) { - $xaction = clone $template; - $xaction->setTransactionType($type); - - switch ($type) { - case PhabricatorTransactions::TYPE_COMMENT: - $xaction->attachComment( - id(new ManiphestTransactionComment()) - ->setContent($value)); - break; - case PhabricatorTransactions::TYPE_EDGE: - $project_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; - $xaction - ->setMetadataValue('edge:type', $project_type) - ->setNewValue( - array( - '=' => array_fuse($value), - )); - break; - default: - $xaction->setNewValue($value); - break; - } - - $xactions[] = $xaction; - } - - return $xactions; - } - -} diff --git a/src/controller/board/SprintBoardColumnDetailController.php b/src/controller/board/SprintBoardColumnDetailController.php deleted file mode 100644 index 663e307e07c3c6a86b1132da8e91f5b662039a3b..0000000000000000000000000000000000000000 --- a/src/controller/board/SprintBoardColumnDetailController.php +++ /dev/null @@ -1,131 +0,0 @@ -<?php - -final class SprintBoardColumnDetailController - extends SprintBoardController { - - public function handleRequest(AphrontRequest $request) { - $viewer = $request->getViewer(); - $id = $request->getURIData('id'); - $project_id = $request->getURIData('projectID'); - - $project = id(new PhabricatorProjectQuery()) - ->setViewer($viewer) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - )) - ->withIDs(array($project_id)) - ->needImages(true) - ->executeOne(); - - if (!$project) { - return new Aphront404Response(); - } - $this->setProject($project); - - $project_id = $project->getID(); - - $column = id(new PhabricatorProjectColumnQuery()) - ->setViewer($viewer) - ->withIDs(array($id)) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - )) - ->executeOne(); - if (!$column) { - return new Aphront404Response(); - } - - $timeline = $this->buildTransactionTimeline( - $column, - new PhabricatorProjectColumnTransactionQuery()); - $timeline->setShouldTerminate(true); - - $title = $column->getDisplayName(); - - $header = $this->buildHeaderView($column); - $actions = $this->buildActionView($column); - $properties = $this->buildPropertyView($column, $actions); - - $crumbs = $this->buildApplicationCrumbs(); - $crumbs->addTextCrumb(pht('Workboard'), "/project/board/{$project_id}/"); - $crumbs->addTextCrumb(pht('Column: %s', $title)); - - $box = id(new PHUIObjectBoxView()) - ->setHeader($header) - ->addPropertyList($properties); - - $nav = $this->getProfileMenu(); - - return $this->newPage() - ->setTitle($title) - ->setNavigation($nav) - ->setCrumbs($crumbs) - ->appendChild( - array( - $box, - $timeline, - )); - } - - private function buildHeaderView(PhabricatorProjectColumn $column) { - $viewer = $this->getRequest()->getUser(); - - $header = id(new PHUIHeaderView()) - ->setUser($viewer) - ->setHeader($column->getDisplayName()) - ->setPolicyObject($column); - - if ($column->isHidden()) { - $header->setStatus('fa-ban', 'dark', pht('Hidden')); - } - - return $header; - } - - private function buildActionView(PhabricatorProjectColumn $column) { - $viewer = $this->getRequest()->getUser(); - - $id = $column->getID(); - $project_id = $this->getProject()->getID(); - $base_uri = '/board/'.$project_id.'/'; - - $actions = id(new PhabricatorActionListView()) - ->setUser($viewer); - - $can_edit = PhabricatorPolicyFilter::hasCapability( - $viewer, - $column, - PhabricatorPolicyCapability::CAN_EDIT); - - $actions->addAction( - id(new PhabricatorActionView()) - ->setName(pht('Edit Column')) - ->setIcon('fa-pencil') - ->setHref($this->getApplicationURI($base_uri.'edit/'.$id.'/')) - ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit)); - - return $actions; - } - - private function buildPropertyView( - PhabricatorProjectColumn $column, - PhabricatorActionListView $actions) { - $viewer = $this->getRequest()->getUser(); - - $properties = id(new PHUIPropertyListView()) - ->setUser($viewer) - ->setObject($column) - ->setActionList($actions); - - $limit = $column->getPointLimit(); - $properties->addProperty( - pht('Point Limit'), - $limit ? $limit : pht('No Limit')); - - return $properties; - } - -} diff --git a/src/controller/board/SprintBoardColumnEditController.php b/src/controller/board/SprintBoardColumnEditController.php deleted file mode 100644 index 3c2ad54cb9fc74fb976203b8e4ae7c78ab7c49c4..0000000000000000000000000000000000000000 --- a/src/controller/board/SprintBoardColumnEditController.php +++ /dev/null @@ -1,157 +0,0 @@ -<?php - -final class SprintBoardColumnEditController - extends SprintBoardController { - - public function handleRequest(AphrontRequest $request) { - $viewer = $request->getViewer(); - $id = $request->getURIData('id'); - $project_id = $request->getURIData('projectID'); - - $project = id(new PhabricatorProjectQuery()) - ->setViewer($viewer) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->withIDs(array($project_id)) - ->needImages(true) - ->executeOne(); - - if (!$project) { - return new Aphront404Response(); - } - $this->setProject($project); - - $is_new = ($id ? false : true); - - if (!$is_new) { - $column = id(new PhabricatorProjectColumnQuery()) - ->setViewer($viewer) - ->withIDs(array($id)) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->executeOne(); - if (!$column) { - return new Aphront404Response(); - } - } else { - $column = PhabricatorProjectColumn::initializeNewColumn($viewer); - } - - $e_name = null; - $e_limit = null; - - $v_limit = $column->getPointLimit(); - $v_name = $column->getName(); - - $validation_exception = null; - $base_uri = '/board/'.$project_id.'/'; - if ($is_new) { - // we want to go back to the board - $view_uri = $this->getApplicationURI($base_uri); - } else { - $view_uri = $this->getApplicationURI($base_uri.'column/'.$id.'/'); - } - - if ($request->isFormPost()) { - $v_name = $request->getStr('name'); - $v_limit = $request->getStr('limit'); - - if ($is_new) { - $column->setProjectPHID($project->getPHID()); - $column->attachProject($project); - - $columns = id(new PhabricatorProjectColumnQuery()) - ->setViewer($viewer) - ->withProjectPHIDs(array($project->getPHID())) - ->execute(); - - $new_sequence = 1; - if ($columns) { - $values = mpull($columns, 'getSequence'); - $new_sequence = max($values) + 1; - } - $column->setSequence($new_sequence); - } - - $xactions = array(); - - if (!$column->getProxy()) { - $type_name = PhabricatorProjectColumnTransaction::TYPE_NAME; - $xactions[] = id(new PhabricatorProjectColumnTransaction()) - ->setTransactionType($type_name) - ->setNewValue($v_name); - } - - $type_limit = PhabricatorProjectColumnTransaction::TYPE_LIMIT; - $xactions[] = id(new PhabricatorProjectColumnTransaction()) - ->setTransactionType($type_limit) - ->setNewValue($v_limit); - - try { - $editor = id(new PhabricatorProjectColumnTransactionEditor()) - ->setActor($viewer) - ->setContinueOnNoEffect(true) - ->setContentSourceFromRequest($request) - ->applyTransactions($column, $xactions); - return id(new AphrontRedirectResponse())->setURI($view_uri); - } catch (PhabricatorApplicationTransactionValidationException $ex) { - $e_name = $ex->getShortMessage($type_name); - $e_limit = $ex->getShortMessage($type_limit); - $validation_exception = $ex; - } - } - - $form = id(new AphrontFormView()) - ->setUser($request->getUser()); - - if (!$column->getProxy()) { - $form->appendChild( - id(new AphrontFormTextControl()) - ->setValue($v_name) - ->setLabel(pht('Name')) - ->setName('name') - ->setError($e_name)); - } - - $form->appendChild( - id(new AphrontFormTextControl()) - ->setValue($v_limit) - ->setLabel(pht('Point Limit')) - ->setName('limit') - ->setError($e_limit) - ->setCaption( - pht('Maximum number of points of tasks allowed in the column.'))); - - - if ($is_new) { - $title = pht('Create Column'); - $submit = pht('Create Column'); - } else { - $title = pht('Edit %s', $column->getDisplayName()); - $submit = pht('Save Column'); - } - - $form->appendChild( - id(new AphrontFormSubmitControl()) - ->setValue($submit) - ->addCancelButton($view_uri)); - - $form_box = id(new PHUIObjectBoxView()) - ->setHeaderText($title) - ->setValidationException($validation_exception) - ->setForm($form); - - $nav = $this->getProfileMenu(); - - return $this->newPage() - ->setTitle($title) - ->setNavigation($nav) - ->appendChild($form_box); - } -} diff --git a/src/controller/board/SprintBoardColumnHideController.php b/src/controller/board/SprintBoardColumnHideController.php deleted file mode 100644 index cc3f6f5aeff40fef5c2f854270966b6b0e75dd34..0000000000000000000000000000000000000000 --- a/src/controller/board/SprintBoardColumnHideController.php +++ /dev/null @@ -1,107 +0,0 @@ -<?php - -final class SprintBoardColumnHideController - extends SprintBoardController { - - public function handleRequest(AphrontRequest $request) { - $viewer = $request->getViewer(); - $id = $request->getURIData('id'); - $project_id = $request->getURIData('projectID'); - - $project = id(new PhabricatorProjectQuery()) - ->setViewer($viewer) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->withIDs(array($project_id)) - ->executeOne(); - - if (!$project) { - return new Aphront404Response(); - } - $this->setProject($project); - - $column = id(new PhabricatorProjectColumnQuery()) - ->setViewer($viewer) - ->withIDs(array($id)) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->executeOne(); - if (!$column) { - return new Aphront404Response(); - } - - $column_phid = $column->getPHID(); - - $view_uri = $this->getApplicationURI('/board/'.$project_id.'/'); - $view_uri = new PhutilURI($view_uri); - foreach ($request->getPassthroughRequestData() as $key => $value) { - $view_uri->setQueryParam($key, $value); - } - - if ($column->isDefaultColumn()) { - return $this->newDialog() - ->setTitle(pht('Can Not Hide Default Column')) - ->appendParagraph( - pht('You can not hide the default/backlog column on a board.')) - ->addCancelButton($view_uri, pht('Okay')); - } - - if ($request->isFormPost()) { - if ($column->isHidden()) { - $new_status = PhabricatorProjectColumn::STATUS_ACTIVE; - } else { - $new_status = PhabricatorProjectColumn::STATUS_HIDDEN; - } - - $type_status = PhabricatorProjectColumnTransaction::TYPE_STATUS; - $xactions = array( - id(new PhabricatorProjectColumnTransaction()) - ->setTransactionType($type_status) - ->setNewValue($new_status), - ); - - $editor = id(new PhabricatorProjectColumnTransactionEditor()) - ->setActor($viewer) - ->setContinueOnNoEffect(true) - ->setContentSourceFromRequest($request) - ->applyTransactions($column, $xactions); - - return id(new AphrontRedirectResponse())->setURI($view_uri); - } - - if ($column->isHidden()) { - $title = pht('Show Column'); - } else { - $title = pht('Hide Column'); - } - - if ($column->isHidden()) { - $body = pht( - 'Are you sure you want to show this column?'); - } else { - $body = pht( - 'Are you sure you want to hide this column? It will no longer '. - 'appear on the workboard.'); - } - - $dialog = $this->newDialog() - ->setWidth(AphrontDialogView::WIDTH_FORM) - ->setTitle($title) - ->appendChild($body) - ->setDisableWorkflowOnCancel(true) - ->addCancelButton($view_uri) - ->addSubmitButton($title); - - foreach ($request->getPassthroughRequestData() as $key => $value) { - $dialog->addHiddenInput($key, $value); - } - - return $dialog; - } -} diff --git a/src/controller/board/SprintBoardController.php b/src/controller/board/SprintBoardController.php deleted file mode 100644 index 7fd1809f0ab62b8bafaf6f19b59384c6700afea4..0000000000000000000000000000000000000000 --- a/src/controller/board/SprintBoardController.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -abstract class SprintBoardController - extends SprintProjectController { - - private $project; - - protected function setProject(PhabricatorProject $project) { - $this->project = $project; - return $this; - } - protected function getProject() { - return $this->project; - } - - protected function getProfileMenu() { - $menu = parent::getProfileMenu(); - - $menu->selectFilter(PhabricatorProject::PANEL_WORKBOARD); - $menu->addClass('project-board-nav'); - - return $menu; - } -} diff --git a/src/controller/board/SprintBoardImportController.php b/src/controller/board/SprintBoardImportController.php deleted file mode 100644 index 8123a91a77ec420311e763f220d4345486aaeb49..0000000000000000000000000000000000000000 --- a/src/controller/board/SprintBoardImportController.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php - -final class SprintBoardImportController - extends SprintBoardController { - - public function handleRequest(AphrontRequest $request) { - $viewer = $request->getViewer(); - $project_id = $request->getURIData('projectID'); - - $project = id(new PhabricatorProjectQuery()) - ->setViewer($viewer) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->withIDs(array($project_id)) - ->executeOne(); - if (!$project) { - return new Aphront404Response(); - } - $this->setProject($project); - - $columns = id(new PhabricatorProjectColumnQuery()) - ->setViewer($viewer) - ->withProjectPHIDs(array($project->getPHID())) - ->execute(); - if ($columns) { - return new Aphront400Response(); - } - - $project_id = $project->getID(); - $board_uri = $this->getApplicationURI("board/{$project_id}/"); - - if ($request->isFormPost()) { - $import_phid = $request->getArr('importProjectPHID'); - $import_phid = reset($import_phid); - - $import_columns = id(new PhabricatorProjectColumnQuery()) - ->setViewer($viewer) - ->withProjectPHIDs(array($import_phid)) - ->execute(); - if (!$import_columns) { - return new Aphront400Response(); - } - - $table = id(new PhabricatorProjectColumn()) - ->openTransaction(); - foreach ($import_columns as $import_column) { - if ($import_column->isHidden()) { - continue; - } - $new_column = PhabricatorProjectColumn::initializeNewColumn($viewer) - ->setSequence($import_column->getSequence()) - ->setProjectPHID($project->getPHID()) - ->setName($import_column->getName()) - ->setProperties($import_column->getProperties()) - ->save(); - } - $table->saveTransaction(); - - return id(new AphrontRedirectResponse())->setURI($board_uri); - } - - $proj_selector = id(new AphrontFormTokenizerControl()) - ->setName('importProjectPHID') - ->setUser($viewer) - ->setDatasource(id(new PhabricatorProjectDatasource()) - ->setParameters(array('mustHaveColumns' => true)) - ->setLimit(1)); - - return $this->newDialog() - ->setTitle(pht('Import Columns')) - ->setWidth(AphrontDialogView::WIDTH_FORM) - ->appendParagraph(pht('Choose a project to import columns from:')) - ->appendChild($proj_selector) - ->addCancelButton($board_uri) - ->addSubmitButton(pht('Import')); - } - -} diff --git a/src/controller/board/SprintBoardMoveController.php b/src/controller/board/SprintBoardMoveController.php deleted file mode 100644 index 2f7403c88b2d58e15f8f5041a00bece0df1258df..0000000000000000000000000000000000000000 --- a/src/controller/board/SprintBoardMoveController.php +++ /dev/null @@ -1,240 +0,0 @@ -<?php - -final class SprintBoardMoveController - extends SprintBoardController { - - public function handleRequest(AphrontRequest $request) { - $viewer = $request->getViewer(); - $id = $request->getURIData('id'); - - $column_phid = $request->getStr('columnPHID'); - $object_phid = $request->getStr('objectPHID'); - $after_phid = $request->getStr('afterPHID'); - $before_phid = $request->getStr('beforePHID'); - $order = $request->getStr('order', PhabricatorProjectColumn::DEFAULT_ORDER); - - - $project = id(new PhabricatorProjectQuery()) - ->setViewer($viewer) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - )) - ->withIDs(array($id)) - ->executeOne(); - if (!$project) { - return new Aphront404Response(); - } - $is_sprint = $this->isSprint($project); - $board_phid = $project->getPHID(); - - $object = id(new ManiphestTaskQuery()) - ->setViewer($viewer) - ->withPHIDs(array($object_phid)) - ->needProjectPHIDs(true) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->executeOne(); - - if (!$object) { - return new Aphront404Response(); - } - - $columns = id(new PhabricatorProjectColumnQuery()) - ->setViewer($viewer) - ->withProjectPHIDs(array($project->getPHID())) - ->execute(); - - $columns = mpull($columns, null, 'getPHID'); - $column = idx($columns, $column_phid); - if (!$column) { - // User is trying to drop this object into a nonexistent column, just kick - // them out. - return new Aphront404Response(); - } - - $engine = id(new PhabricatorBoardLayoutEngine()) - ->setViewer($viewer) - ->setBoardPHIDs(array($board_phid)) - ->setObjectPHIDs(array($object_phid)) - ->executeLayout(); - - $columns = $engine->getObjectColumns($board_phid, $object_phid); - $old_column_phids = mpull($columns, 'getPHID'); - - $xactions = array(); - - if ($order == PhabricatorProjectColumn::ORDER_NATURAL) { - $order_params = array( - 'afterPHID' => $after_phid, - 'beforePHID' => $before_phid, - ); - } else { - $order_params = array(); - } - - $xactions[] = id(new ManiphestTransaction()) - ->setTransactionType(ManiphestTransaction::TYPE_PROJECT_COLUMN) - ->setNewValue( - array( - 'columnPHIDs' => array($column->getPHID()), - 'projectPHID' => $column->getProjectPHID(), - ) + $order_params) - ->setOldValue( - array( - 'columnPHIDs' => $old_column_phids, - 'projectPHID' => $column->getProjectPHID(), - )); - - $task_phids = array(); - if ($after_phid) { - $task_phids[] = $after_phid; - } - if ($before_phid) { - $task_phids[] = $before_phid; - } - - if ($task_phids && ($order == PhabricatorProjectColumn::ORDER_PRIORITY)) { - $tasks = id(new ManiphestTaskQuery()) - ->setViewer($viewer) - ->withPHIDs($task_phids) - ->needProjectPHIDs(true) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->execute(); - if (count($tasks) != count($task_phids)) { - return new Aphront404Response(); - } - $tasks = mpull($tasks, null, 'getPHID'); - - $try = array( - array($after_phid, true), - array($before_phid, false), - ); - - $pri = null; - $sub = null; - foreach ($try as $spec) { - list($task_phid, $is_after) = $spec; - $task = idx($tasks, $task_phid); - if ($task) { - list($pri, $sub) = ManiphestTransactionEditor::getAdjacentSubpriority( - $task, - $is_after); - break; - } - } - - if ($pri !== null) { - $xactions[] = id(new ManiphestTransaction()) - ->setTransactionType(ManiphestTransaction::TYPE_PRIORITY) - ->setNewValue($pri); - $xactions[] = id(new ManiphestTransaction()) - ->setTransactionType(ManiphestTransaction::TYPE_SUBPRIORITY) - ->setNewValue($sub); - } - } - - $proxy = $column->getProxy(); - if ($proxy) { - // We're moving the task into a subproject or milestone column, so add - // the subproject or milestone. - $add_projects = array($proxy->getPHID()); - } else if ($project->getHasSubprojects() || $project->getHasMilestones()) { - // We're moving the task into the "Backlog" column on the parent project, - // so add the parent explicitly. This gets rid of any subproject or - // milestone tags. - $add_projects = array($project->getPHID()); - } else { - $add_projects = array(); - } - - if ($add_projects) { - $project_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; - - $xactions[] = id(new ManiphestTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) - ->setMetadataValue('edge:type', $project_type) - ->setNewValue( - array( - '+' => array_fuse($add_projects), - )); - } - - $editor = id(new ManiphestTransactionEditor()) - ->setActor($viewer) - ->setContinueOnMissingFields(true) - ->setContinueOnNoEffect(true) - ->setContentSourceFromRequest($request); - - $editor->applyTransactions($object, $xactions); - - $owner = null; - if ($object->getOwnerPHID()) { - $owner = id(new PhabricatorHandleQuery()) - ->setViewer($viewer) - ->withPHIDs(array($object->getOwnerPHID())) - ->executeOne(); - } - - // Reload the object so it reflects edits which have been applied. - $object = id(new ManiphestTaskQuery()) - ->setViewer($viewer) - ->withPHIDs(array($object_phid)) - ->needProjectPHIDs(true) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->executeOne(); - - $except_phids = array($board_phid); - if ($project->getHasSubprojects() || $project->getHasMilestones()) { - $descendants = id(new PhabricatorProjectQuery()) - ->setViewer($viewer) - ->withAncestorProjectPHIDs($except_phids) - ->execute(); - foreach ($descendants as $descendant) { - $except_phids[] = $descendant->getPHID(); - } - } - - $except_phids = array_fuse($except_phids); - $handle_phids = array_fuse($object->getProjectPHIDs()); - $handle_phids = array_diff_key($handle_phids, $except_phids); - - $project_handles = $viewer->loadHandles($handle_phids); - $project_handles = iterator_to_array($project_handles); - - if ($is_sprint == true) { - $card = id(new SprintBoardTaskCard()) - ->setProject($project) - ->setProjectHandles($project_handles) - ->setViewer($viewer) - ->setTask($object) - ->setOwner($owner) - ->setCanEdit(true) - ->getItem(); - } else { - $card = id(new ProjectBoardTaskCard()) - ->setViewer($viewer) - ->setTask($object) - ->setProjectHandles($project_handles) - ->setOwner($owner) - ->setCanEdit(true) - ->getItem(); - } - $card->addClass('phui-workcard'); - - return id(new AphrontAjaxResponse())->setContent( - array('task' => $card)); - } - -} diff --git a/src/controller/board/SprintBoardReorderController.php b/src/controller/board/SprintBoardReorderController.php deleted file mode 100644 index 0090b8c4225aa4bca0795d9c4320630895a7804d..0000000000000000000000000000000000000000 --- a/src/controller/board/SprintBoardReorderController.php +++ /dev/null @@ -1,138 +0,0 @@ -<?php - -final class SprintBoardReorderController - extends SprintBoardController { - - public function handleRequest(AphrontRequest $request) { - $viewer = $request->getViewer(); - $projectid = $request->getURIData('projectID'); - - $project = id(new PhabricatorProjectQuery()) - ->setViewer($viewer) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->withIDs(array($projectid)) - ->executeOne(); - if (!$project) { - return new Aphront404Response(); - } - - $this->setProject($project); - $project_id = $project->getID(); - - $board_uri = $this->getApplicationURI("board/{$project_id}/"); - $reorder_uri = $this->getApplicationURI("board/{$project_id}/reorder/"); - - if ($request->isFormPost()) { - // User clicked "Done", make sure the page reloads to show the new - // column order. - return id(new AphrontRedirectResponse())->setURI($board_uri); - } - - $columns = id(new PhabricatorProjectColumnQuery()) - ->setViewer($viewer) - ->withProjectPHIDs(array($project->getPHID())) - ->execute(); - $columns = msort($columns, 'getSequence'); - - $column_phid = $request->getStr('columnPHID'); - if ($column_phid && $request->validateCSRF()) { - - $columns = mpull($columns, null, 'getPHID'); - if (empty($columns[$column_phid])) { - return new Aphront404Response(); - } - - $target_column = $columns[$column_phid]; - $new_sequence = $request->getInt('sequence'); - if ($new_sequence < 0) { - return new Aphront404Response(); - } - - // TODO: For now, we're not recording any transactions here. We probably - // should, but this sort of edit is extremely trivial. - - // Resequence the columns so that the moved column has the correct - // sequence number. Move columns after it up one place in the sequence. - $new_map = array(); - foreach ($columns as $phid => $column) { - $value = $column->getSequence(); - if ($column->getPHID() == $column_phid) { - $value = $new_sequence; - } else if ($column->getSequence() >= $new_sequence) { - $value = $value + 1; - } - $new_map[$phid] = $value; - } - - // Sort the columns into their new ordering. - asort($new_map); - - // Now, compact the ordering and adjust any columns that need changes. - $project->openTransaction(); - $sequence = 0; - foreach ($new_map as $phid => $ignored) { - $new_value = $sequence++; - $cur_value = $columns[$phid]->getSequence(); - if ($new_value != $cur_value) { - $columns[$phid]->setSequence($new_value)->save(); - } - } - $project->saveTransaction(); - - return id(new AphrontAjaxResponse())->setContent( - array( - 'sequenceMap' => mpull($columns, 'getSequence', 'getPHID'), - )); - } - - $list_id = celerity_generate_unique_node_id(); - - $list = id(new PHUIObjectItemListView()) - ->setUser($viewer) - ->setID($list_id) - ->setFlush(true); - - foreach ($columns as $column) { - $item = id(new PHUIObjectItemView()) - ->setHeader($column->getDisplayName()) - ->addIcon('none', $column->getDisplayType()); - - if ($column->isHidden()) { - $item->setDisabled(true); - } - - $item->setGrippable(true); - $item->addSigil('board-column'); - $item->setMetadata( - array( - 'columnPHID' => $column->getPHID(), - 'columnSequence' => $column->getSequence(), - )); - - $list->addItem($item); - } - - Javelin::initBehavior( - 'reorder-columns', - array( - 'listID' => $list_id, - 'reorderURI' => $reorder_uri, - )); - - $note = id(new PHUIInfoView()) - ->appendChild(pht('Drag and drop columns to reorder them.')) - ->setSeverity(PHUIInfoView::SEVERITY_NOTICE); - - return $this->newDialog() - ->setTitle(pht('Reorder Columns')) - ->setWidth(AphrontDialogView::WIDTH_FORM) - ->appendChild($note) - ->appendChild($list) - ->addSubmitButton(pht('Done')); - } - -} diff --git a/src/controller/board/SprintBoardTaskEditController.php b/src/controller/board/SprintBoardTaskEditController.php deleted file mode 100644 index 755e95fe6c492e5f987156ad61a51b5463c3f322..0000000000000000000000000000000000000000 --- a/src/controller/board/SprintBoardTaskEditController.php +++ /dev/null @@ -1,15 +0,0 @@ -<?php - -final class SprintBoardTaskEditController extends ManiphestController { - - public function handleRequest(AphrontRequest $request) { - return id(new SprintManiphestEditEngine()) - ->setController($this) - ->addContextParameter('ungrippable') - ->addContextParameter('responseType') - ->addContextParameter('columnPHID') - ->addContextParameter('order') - ->buildResponse(); - } - -} diff --git a/src/controller/board/SprintBoardViewController.php b/src/controller/board/SprintBoardViewController.php deleted file mode 100755 index 694e73c68a3029a5b015a0e51cc774c62b81d233..0000000000000000000000000000000000000000 --- a/src/controller/board/SprintBoardViewController.php +++ /dev/null @@ -1,881 +0,0 @@ -<?php - -final class SprintBoardViewController - extends SprintBoardController { - - const BATCH_EDIT_ALL = 'all'; - - private $id; - private $slug; - private $handles; - private $queryKey; - private $filter; - private $sortKey; - private $showHidden; - - public function shouldAllowPublic() { - return true; - } - - public function handleRequest(AphrontRequest $request) { - $viewer = $request->getUser(); - - $response = $this->loadProject(); - if ($response) { - return $response; - } - - $project = $this->getProject(); - - $this->readRequestState(); - - $is_sprint = $this->isSprint($project); - $board_uri = $this->getApplicationURI('board/'.$project->getID().'/'); - - $search_engine = id(new ManiphestTaskSearchEngine()) - ->setViewer($viewer) - ->setBaseURI($board_uri) - ->setIsBoardView(true); - - if ($request->isFormPost() && !$request->getBool('initialize')) { - $saved = $search_engine->buildSavedQueryFromRequest($request); - $search_engine->saveQuery($saved); - $filter_form = id(new AphrontFormView()) - ->setUser($viewer); - $search_engine->buildSearchForm($filter_form, $saved); - if ($search_engine->getErrors()) { - return $this->newDialog() - ->setWidth(AphrontDialogView::WIDTH_FULL) - ->setTitle(pht('Advanced Filter')) - ->appendChild($filter_form->buildLayoutView()) - ->setErrors($search_engine->getErrors()) - ->setSubmitURI($board_uri) - ->addSubmitButton(pht('Apply Filter')) - ->addCancelButton($board_uri); - } - return id(new AphrontRedirectResponse())->setURI( - $this->getURIWithState( - $search_engine->getQueryResultsPageURI($saved->getQueryKey()))); - } - - $query_key = $request->getURIData('queryKey'); - if (!$query_key) { - if ($is_sprint == true) { - $query_key = 'all'; - } else { - $query_key = 'open'; - } - } - $this->queryKey = $query_key; - - $custom_query = null; - if ($search_engine->isBuiltinQuery($query_key)) { - $saved = $search_engine->buildSavedQueryFromBuiltin($query_key); - } else { - $saved = id(new PhabricatorSavedQueryQuery()) - ->setViewer($viewer) - ->withQueryKeys(array($query_key)) - ->executeOne(); - - if (!$saved) { - return new Aphront404Response(); - } - - $custom_query = $saved; - } - - if ($request->getURIData('filter')) { - $filter_form = id(new AphrontFormView()) - ->setUser($viewer); - $search_engine->buildSearchForm($filter_form, $saved); - - return $this->newDialog() - ->setWidth(AphrontDialogView::WIDTH_FULL) - ->setTitle(pht('Advanced Filter')) - ->appendChild($filter_form->buildLayoutView()) - ->setSubmitURI($board_uri) - ->addSubmitButton(pht('Apply Filter')) - ->addCancelButton($board_uri); - } - - $task_query = $search_engine->buildQueryFromSavedQuery($saved); - - $select_phids = array($project->getPHID()); - if ($project->getHasSubprojects() || $project->getHasMilestones()) { - $descendants = id(new PhabricatorProjectQuery()) - ->setViewer($viewer) - ->withAncestorProjectPHIDs($select_phids) - ->execute(); - foreach ($descendants as $descendant) { - $select_phids[] = $descendant->getPHID(); - } - } - - $tasks = $task_query - ->withEdgeLogicPHIDs( - PhabricatorProjectObjectHasProjectEdgeType::EDGECONST, - PhabricatorQueryConstraint::OPERATOR_ANCESTOR, - array($select_phids)) - ->setOrder(ManiphestTaskQuery::ORDER_PRIORITY) - ->setViewer($viewer) - ->execute(); - $tasks = mpull($tasks, null, 'getPHID'); - - $board_phid = $project->getPHID(); - - $layout_engine = id(new PhabricatorBoardLayoutEngine()) - ->setViewer($viewer) - ->setBoardPHIDs(array($board_phid)) - ->setObjectPHIDs(array_keys($tasks)) - ->executeLayout(); - - $columns = $layout_engine->getColumns($board_phid); - if (!$columns) { - $can_edit = PhabricatorPolicyFilter::hasCapability( - $viewer, - $project, - PhabricatorPolicyCapability::CAN_EDIT); - if (!$can_edit) { - $content = $this->buildNoAccessContent($project); - } else { - $content = $this->buildInitializeContent($project); - } - - if ($content instanceof AphrontResponse) { - return $content; - } - - $nav = $this->getProfileMenu(); - $nav->selectFilter(PhabricatorProject::PANEL_WORKBOARD); - - $crumbs = $this->buildApplicationCrumbs(); - $crumbs->addTextCrumb(pht('Workboard')); - - return $this->newPage() - ->setTitle( - array( - pht('Workboard'), - $project->getName(), - )) - ->setNavigation($nav) - ->setCrumbs($crumbs) - ->appendChild($content); - } - - $task_can_edit_map = id(new PhabricatorPolicyFilter()) - ->setViewer($viewer) - ->requireCapabilities(array(PhabricatorPolicyCapability::CAN_EDIT)) - ->apply($tasks); - - // If this is a batch edit, select the editable tasks in the chosen column - // and ship the user into the batch editor. - $batch_edit = $request->getStr('batch'); - if ($batch_edit) { - if ($batch_edit !== self::BATCH_EDIT_ALL) { - $column_id_map = mpull($columns, null, 'getID'); - $batch_column = idx($column_id_map, $batch_edit); - if (!$batch_column) { - return new Aphront404Response(); - } - - $batch_task_phids = $layout_engine->getColumnObjectPHIDs( - $board_phid, - $batch_column->getPHID()); - - foreach ($batch_task_phids as $key => $batch_task_phid) { - if (empty($task_can_edit_map[$batch_task_phid])) { - unset($batch_task_phids[$key]); - } - } - - $batch_tasks = array_select_keys($tasks, $batch_task_phids); - } else { - $batch_tasks = $task_can_edit_map; - } - - if (!$batch_tasks) { - $cancel_uri = $this->getURIWithState($board_uri); - return $this->newDialog() - ->setTitle(pht('No Editable Tasks')) - ->appendParagraph( - pht( - 'The selected column contains no visible tasks which you '. - 'have permission to edit.')) - ->addCancelButton($board_uri); - } - - $batch_ids = mpull($batch_tasks, 'getID'); - $batch_ids = implode(',', $batch_ids); - if ($is_sprint == true) { - $batch_uri = new PhutilURI('/project/sprint/board/batch/'); - } else { - $batch_uri = new PhutilURI('/maniphest/batch/'); - } - $batch_uri->setQueryParam('board', $this->id); - $batch_uri->setQueryParam('batch', $batch_ids); - return id(new AphrontRedirectResponse()) - ->setURI($batch_uri); - } - - $board_id = celerity_generate_unique_node_id(); - - $board = id(new PHUIWorkboardView()) - ->setUser($viewer) - ->setID($board_id); - - if ($is_sprint == true) { - $behavior_config = array( - 'boardID' => $board_id, - 'projectPHID' => $project->getPHID(), - 'moveURI' => $this->getApplicationURI('move/'.$project->getID().'/'), - 'createURI' => '/project/sprint/board/task/create/', - 'order' => $this->sortKey, - ); - $this->initSprintBehavior( - 'sprint-boards', - $behavior_config); - } else { - $behavior_config = array( - 'boardID' => $board_id, - 'projectPHID' => $project->getPHID(), - 'moveURI' => $this->getApplicationURI('move/'.$project->getID().'/'), - 'createURI' => $this->getCreateURI(), - 'order' => $this->sortKey, - ); - $this->initBehavior( - 'project-boards', - $behavior_config); - } - - $this->handles = ManiphestTaskListView::loadTaskHandles($viewer, $tasks); - - $all_project_phids = array(); - foreach ($tasks as $task) { - foreach ($task->getProjectPHIDs() as $project_phid) { - $all_project_phids[$project_phid] = $project_phid; - } - } - - foreach ($select_phids as $phid) { - unset($all_project_phids[$phid]); - } - - $all_handles = $viewer->loadHandles($all_project_phids); - $all_handles = iterator_to_array($all_handles); - - foreach ($columns as $column) { - if (!$this->showHidden) { - if ($column->isHidden()) { - continue; - } - } - - $proxy = $column->getProxy(); - if ($proxy && !$proxy->isMilestone()) { - // TODO: For now, don't show subproject columns because we can't - // handle tasks with multiple positions yet. - continue; - } - - $task_phids = $layout_engine->getColumnObjectPHIDs( - $board_phid, - $column->getPHID()); - - $column_tasks = array_select_keys($tasks, $task_phids); - - // If we aren't using "natural" order, reorder the column by the original - // query order. - if ($this->sortKey != PhabricatorProjectColumn::ORDER_NATURAL) { - $column_tasks = array_select_keys($column_tasks, array_keys($tasks)); - } - - $panel = id(new PHUIWorkpanelView()) - ->setHeader($column->getDisplayName()) - ->setSubHeader($column->getDisplayType()) - ->addSigil('workpanel'); - - $header_icon = $column->getHeaderIcon(); - if ($header_icon) { - $panel->setHeaderIcon($header_icon); - } - - $display_class = $column->getDisplayClass(); - if ($display_class) { - $panel->addClass($display_class); - } - - if ($column->isHidden()) { - $panel->addClass('project-panel-hidden'); - } - - $column_menu = $this->buildColumnMenu($project, $column); - $panel->addHeaderAction($column_menu); - - $tag_id = celerity_generate_unique_node_id(); - $tag_content_id = celerity_generate_unique_node_id(); - - $count_tag = id(new PHUITagView()) - ->setType(PHUITagView::TYPE_SHADE) - ->setShade(PHUITagView::COLOR_BLUE) - ->setID($tag_id) - ->setName(phutil_tag('span', array('id' => $tag_content_id), '-')) - ->setStyle('display: none'); - - $panel->setHeaderTag($count_tag); - - $cards = id(new PHUIObjectItemListView()) - ->setUser($viewer) - ->setFlush(true) - ->setAllowEmptyList(true) - ->addSigil('project-column') - ->setItemClass('phui-workcard') - ->setMetadata( - array( - 'columnPHID' => $column->getPHID(), - 'countTagID' => $tag_id, - 'countTagContentID' => $tag_content_id, - 'pointLimit' => $column->getPointLimit(), - )); - - foreach ($column_tasks as $task) { - $owner = null; - if ($task->getOwnerPHID()) { - $owner = $this->handles[$task->getOwnerPHID()]; - } - $can_edit = idx($task_can_edit_map, $task->getPHID(), false); - $handles = array_select_keys($all_handles, $task->getProjectPHIDs()); - if ($is_sprint == true) { - $cards->addItem(id(new SprintBoardTaskCard()) - ->setProject($project) - ->setProjectHandles($handles) - ->setViewer($viewer) - ->setTask($task) - ->setOwner($owner) - ->setCanEdit($can_edit) - ->getItem()); - } else { - $cards->addItem(id(new ProjectBoardTaskCard()) - ->setViewer($viewer) - ->setProjectHandles($handles) - ->setTask($task) - ->setOwner($owner) - ->setCanEdit($can_edit) - ->getItem()); - } - } - $panel->setCards($cards); - $board->addPanel($panel); - } - - $sort_menu = $this->buildSortMenu( - $viewer, - $this->sortKey); - - $filter_menu = $this->buildFilterMenu( - $viewer, - $custom_query, - $search_engine, - $query_key); - - $manage_menu = $this->buildManageMenu($project, $this->showHidden); - - $header_link = phutil_tag( - 'a', - array( - 'href' => $this->getApplicationURI('profile/'.$project->getID().'/'), - ), - $project->getName()); - - $board_box = id(new PHUIBoxView()) - ->appendChild($board) - ->addClass('project-board-wrapper'); - - $nav = $this->getProfileMenu(); - - $crumbs = $this->buildApplicationCrumbs(); - $crumbs->addTextCrumb(pht('Workboard')); - $crumbs->setBorder(true); - - $crumbs->addAction($sort_menu); - $crumbs->addAction($filter_menu); - $crumbs->addAction($manage_menu); - - return $this->newPage() - ->setTitle(pht('%s Board', $project->getName())) - ->setPageObjectPHIDs(array($project->getPHID())) - ->setShowFooter(false) - ->setNavigation($nav) - ->setCrumbs($crumbs) - ->addQuicksandConfig( - array( - 'boardConfig' => $behavior_config, - )) - ->appendChild( - array( - $board_box, - )); - } - - private function readRequestState() { - $request = $this->getRequest(); - $project = $this->getProject(); - - $this->showHidden = $request->getBool('hidden'); - $this->id = $project->getID(); - - $sort_key = $request->getStr('order'); - switch ($sort_key) { - case PhabricatorProjectColumn::ORDER_NATURAL: - case PhabricatorProjectColumn::ORDER_PRIORITY: - break; - default: - $sort_key = PhabricatorProjectColumn::DEFAULT_ORDER; - break; - } - $this->sortKey = $sort_key; - } - - private function buildSortMenu( - PhabricatorUser $viewer, - $sort_key) { - - $sort_icon = id(new PHUIIconView()) - ->setIcon('fa-sort-amount-asc bluegrey'); - - $named = array( - PhabricatorProjectColumn::ORDER_NATURAL => pht('Natural'), - PhabricatorProjectColumn::ORDER_PRIORITY => pht('Sort by Priority'), - ); - - $base_uri = $this->getURIWithState(); - - $items = array(); - foreach ($named as $key => $name) { - $is_selected = ($key == $sort_key); - if ($is_selected) { - $active_order = $name; - } - - $item = id(new PhabricatorActionView()) - ->setIcon('fa-sort-amount-asc') - ->setSelected($is_selected) - ->setName($name); - - $uri = $base_uri->alter('order', $key); - $item->setHref($uri); - - $items[] = $item; - } - - $sort_menu = id(new PhabricatorActionListView()) - ->setUser($viewer); - foreach ($items as $item) { - $sort_menu->addAction($item); - } - - $sort_button = id(new PHUIListItemView()) - ->setName(pht('Sort: %s', $active_order)) - ->setIcon('fa-sort-amount-asc') - ->setHref('#') - ->addSigil('boards-dropdown-menu') - ->setMetadata( - array( - 'items' => hsprintf('%s', $sort_menu), - )); - - return $sort_button; - } - private function buildFilterMenu( - PhabricatorUser $viewer, - $custom_query, - PhabricatorApplicationSearchEngine $engine, - $query_key) { - - $named = array( - 'open' => pht('Open Tasks'), - 'all' => pht('All Tasks'), - ); - - if ($viewer->isLoggedIn()) { - $named['assigned'] = pht('Assigned to Me'); - } - - if ($custom_query) { - $named[$custom_query->getQueryKey()] = pht('Custom Filter'); - } - - $items = array(); - foreach ($named as $key => $name) { - $is_selected = ($key == $query_key); - if ($is_selected) { - $active_filter = $name; - } - - $is_custom = false; - if ($custom_query) { - $is_custom = ($key == $custom_query->getQueryKey()); - } - - $item = id(new PhabricatorActionView()) - ->setIcon('fa-search') - ->setSelected($is_selected) - ->setName($name); - - if ($is_custom) { - $uri = $this->getApplicationURI( - 'board/'.$this->id.'/filter/query/'.$key.'/'); - $item->setWorkflow(true); - } else { - $uri = $engine->getQueryResultsPageURI($key); - } - - $uri = $this->getURIWithState($uri); - $item->setHref($uri); - - $items[] = $item; - } - - $items[] = id(new PhabricatorActionView()) - ->setIcon('fa-cog') - ->setHref($this->getApplicationURI('board/'.$this->id.'/filter/')) - ->setWorkflow(true) - ->setName(pht('Advanced Filter...')); - - $filter_menu = id(new PhabricatorActionListView()) - ->setUser($viewer); - foreach ($items as $item) { - $filter_menu->addAction($item); - } - - $filter_button = id(new PHUIListItemView()) - ->setName(pht('Filter: %s', $active_filter)) - ->setIcon('fa-search') - ->setHref('#') - ->addSigil('boards-dropdown-menu') - ->setMetadata( - array( - 'items' => hsprintf('%s', $filter_menu), - )); - - return $filter_button; - } - - private function buildManageMenu( - PhabricatorProject $project, - $show_hidden) { - - $request = $this->getRequest(); - $viewer = $request->getUser(); - - $can_edit = PhabricatorPolicyFilter::hasCapability( - $viewer, - $project, - PhabricatorPolicyCapability::CAN_EDIT); - - $manage_items = array(); - - $manage_items[] = id(new PhabricatorActionView()) - ->setIcon('fa-plus') - ->setName(pht('Add Column')) - ->setHref($this->getApplicationURI('board/'.$this->id.'/edit/')) - ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit); - - $manage_items[] = id(new PhabricatorActionView()) - ->setIcon('fa-exchange') - ->setName(pht('Reorder Columns')) - ->setHref($this->getApplicationURI('board/'.$this->id.'/reorder/')) - ->setDisabled(!$can_edit) - ->setWorkflow(true); - - if ($show_hidden) { - $hidden_uri = $this->getURIWithState() - ->setQueryParam('hidden', null); - $hidden_icon = 'fa-eye-slash'; - $hidden_text = pht('Hide Hidden Columns'); - } else { - $hidden_uri = $this->getURIWithState() - ->setQueryParam('hidden', 'true'); - $hidden_icon = 'fa-eye'; - $hidden_text = pht('Show Hidden Columns'); - } - - $manage_items[] = id(new PhabricatorActionView()) - ->setIcon($hidden_icon) - ->setName($hidden_text) - ->setHref($hidden_uri); - - $batch_edit_uri = $request->getRequestURI(); - $batch_edit_uri->setQueryParam('batch', self::BATCH_EDIT_ALL); - $can_batch_edit = PhabricatorPolicyFilter::hasCapability( - $viewer, - PhabricatorApplication::getByClass('PhabricatorManiphestApplication'), - ManiphestBulkEditCapability::CAPABILITY); - - $manage_items[] = id(new PhabricatorActionView()) - ->setIcon('fa-list-ul') - ->setName(pht('Batch Edit Visible Tasks...')) - ->setHref($batch_edit_uri) - ->setDisabled(!$can_batch_edit); - - $manage_menu = id(new PhabricatorActionListView()) - ->setUser($viewer); - foreach ($manage_items as $item) { - $manage_menu->addAction($item); - } - - $manage_button = id(new PHUIListItemView()) - ->setName(pht('Manage Board')) - ->setIcon('fa-cog') - ->setHref('#') - ->addSigil('boards-dropdown-menu') - ->setMetadata( - array( - 'items' => hsprintf('%s', $manage_menu), - )); - - return $manage_button; - } - - private function buildColumnMenu( - PhabricatorProject $project, - PhabricatorProjectColumn $column) { - - $request = $this->getRequest(); - $viewer = $request->getUser(); - - $can_edit = PhabricatorPolicyFilter::hasCapability( - $viewer, - $project, - PhabricatorPolicyCapability::CAN_EDIT); - - $column_items = array(); - - if ($column->getProxyPHID()) { - $default_phid = $column->getProxyPHID(); - } else { - $default_phid = $column->getProjectPHID(); - } - - $column_items[] = id(new PhabricatorActionView()) - ->setIcon('fa-plus') - ->setName(pht('Create Task...')) - ->setHref($this->getCreateURI()) - ->addSigil('column-add-task') - ->setMetadata( - array( - 'columnPHID' => $column->getPHID(), - 'projectPHID' => $default_phid, - )); - - $batch_edit_uri = $request->getRequestURI(); - $batch_edit_uri->setQueryParam('batch', $column->getID()); - $can_batch_edit = PhabricatorPolicyFilter::hasCapability( - $viewer, - PhabricatorApplication::getByClass('PhabricatorManiphestApplication'), - ManiphestBulkEditCapability::CAPABILITY); - - $column_items[] = id(new PhabricatorActionView()) - ->setIcon('fa-list-ul') - ->setName(pht('Batch Edit Tasks...')) - ->setHref($batch_edit_uri) - ->setDisabled(!$can_batch_edit); - - $detail_uri = $this->getApplicationURI( - 'board/'.$this->id.'/column/'.$column->getID().'/'); - - $column_items[] = id(new PhabricatorActionView()) - ->setIcon('fa-columns') - ->setName(pht('Column Details')) - ->setHref($detail_uri); - - $can_hide = ($can_edit && !$column->isDefaultColumn()); - $hide_uri = 'board/'.$this->id.'/hide/'.$column->getID().'/'; - $hide_uri = $this->getApplicationURI($hide_uri); - $hide_uri = $this->getURIWithState($hide_uri); - - if (!$column->isHidden()) { - $column_items[] = id(new PhabricatorActionView()) - ->setName(pht('Hide Column')) - ->setIcon('fa-eye-slash') - ->setHref($hide_uri) - ->setDisabled(!$can_hide) - ->setWorkflow(true); - } else { - $column_items[] = id(new PhabricatorActionView()) - ->setName(pht('Show Column')) - ->setIcon('fa-eye') - ->setHref($hide_uri) - ->setDisabled(!$can_hide) - ->setWorkflow(true); - } - - $column_menu = id(new PhabricatorActionListView()) - ->setUser($viewer); - foreach ($column_items as $item) { - $column_menu->addAction($item); - } - - $column_button = id(new PHUIIconView()) - ->setIcon('fa-caret-down') - ->setHref('#') - ->addSigil('boards-dropdown-menu') - ->setMetadata( - array( - 'items' => hsprintf('%s', $column_menu), - )); - - return $column_button; - } - - - /** - * Add current state parameters (like order and the visibility of hidden - * columns) to a URI. - * - * This allows actions which toggle or adjust one piece of state to keep - * the rest of the board state persistent. If no URI is provided, this method - * starts with the request URI. - * - * @param string|null URI to add state parameters to. - * @return PhutilURI URI with state parameters. - */ - private function getURIWithState($base = null) { - if ($base === null) { - $base = $this->getRequest()->getRequestURI(); - } - - $base = new PhutilURI($base); - - if ($this->sortKey != PhabricatorProjectColumn::DEFAULT_ORDER) { - $base->setQueryParam('order', $this->sortKey); - } else { - $base->setQueryParam('order', null); - } - - $base->setQueryParam('hidden', $this->showHidden ? 'true' : null); - - return $base; - } - - public function initSprintBehavior($name, $config = array()) { - Javelin::initBehavior( - $name, - $config, - 'sprint'); - } - - private function getCreateURI() { - $viewer = $this->getViewer(); - - // TODO: This should be cleaned up, but maybe we're going to make options - // for each column or board? - $edit_config = id(new ManiphestEditEngine()) - ->setViewer($viewer) - ->loadDefaultEditConfiguration(); - if ($edit_config) { - $form_key = $edit_config->getIdentifier(); - $create_uri = "/maniphest/task/edit/form/{$form_key}/"; - } else { - $create_uri = '/maniphest/task/edit/'; - } - - return $create_uri; - } - - - private function buildInitializeContent(PhabricatorProject $project) { - $request = $this->getRequest(); - $viewer = $this->getViewer(); - - $type = $request->getStr('initialize-type'); - - $id = $project->getID(); - - $profile_uri = $this->getApplicationURI("profile/{$id}/"); - $board_uri = $this->getApplicationURI("board/{$id}/"); - $import_uri = $this->getApplicationURI("board/{$id}/import/"); - - $set_default = $request->getBool('default'); - if ($set_default) { - $this - ->getProfilePanelEngine() - ->adjustDefault(PhabricatorProject::PANEL_WORKBOARD); - } - - if ($request->isFormPost()) { - if ($type == 'backlog-only') { - $column = PhabricatorProjectColumn::initializeNewColumn($viewer) - ->setSequence(0) - ->setProperty('isDefault', true) - ->setProjectPHID($project->getPHID()) - ->save(); - - $project->setHasWorkboard(1)->save(); - - return id(new AphrontRedirectResponse()) - ->setURI($board_uri); - } else { - return id(new AphrontRedirectResponse()) - ->setURI($import_uri); - } - } - - $new_selector = id(new AphrontFormRadioButtonControl()) - ->setLabel(pht('Columns')) - ->setName('initialize-type') - ->setValue('backlog-only') - ->addButton( - 'backlog-only', - pht('New Empty Board'), - pht('Create a new board with just a backlog column.')) - ->addButton( - 'import', - pht('Import Columns'), - pht('Import board columns from another project.')); - - $default_checkbox = id(new AphrontFormCheckboxControl()) - ->setLabel(pht('Make Default')) - ->addCheckbox( - 'default', - 1, - pht('Make the workboard the default view for this project.'), - true); - - $form = id(new AphrontFormView()) - ->setUser($viewer) - ->addHiddenInput('initialize', 1) - ->appendRemarkupInstructions( - pht('The workboard for this project has not been created yet.')) - ->appendControl($new_selector) - ->appendControl($default_checkbox) - ->appendControl( - id(new AphrontFormSubmitControl()) - ->addCancelButton($profile_uri) - ->setValue(pht('Create Workboard'))); - - $box = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Create Workboard')) - ->setForm($form); - - return $box; - } - - private function buildNoAccessContent(PhabricatorProject $project) { - $viewer = $this->getViewer(); - - $id = $project->getID(); - - $profile_uri = $this->getApplicationURI("profile/{$id}/"); - - return $this->newDialog() - ->setTitle(pht('Unable to Create Workboard')) - ->appendParagraph( - pht( - 'The workboard for this project has not been created yet, '. - 'but you do not have permission to create it. Only users '. - 'who can edit this project can create a workboard for it.')) - ->addCancelButton($profile_uri); - } - -} diff --git a/src/controller/board/SprintManiphestEditEngine.php b/src/controller/board/SprintManiphestEditEngine.php deleted file mode 100644 index 2b348cb722b99aac08a71d78c694f1101b97325b..0000000000000000000000000000000000000000 --- a/src/controller/board/SprintManiphestEditEngine.php +++ /dev/null @@ -1,400 +0,0 @@ -<?php - -final class SprintManiphestEditEngine - extends PhabricatorEditEngine { - - const ENGINECONST = 'sprint.maniphest.task'; - - public function getEngineName() { - return pht('Maniphest Tasks'); - } - - public function getSummaryHeader() { - return pht('Configure Maniphest Task Forms'); - } - - public function getSummaryText() { - return pht('Configure how users create and edit tasks.'); - } - - public function getEngineApplicationClass() { - return 'PhabricatorManiphestApplication'; - } - - protected function newEditableObject() { - return ManiphestTask::initializeNewTask($this->getViewer()); - } - - protected function newObjectQuery() { - return id(new ManiphestTaskQuery()); - } - - protected function getObjectCreateTitleText($object) { - return pht('Create New Task'); - } - - protected function getObjectEditTitleText($object) { - return pht('Edit %s %s', $object->getMonogram(), $object->getTitle()); - } - - protected function getObjectEditShortText($object) { - return $object->getMonogram(); - } - - protected function getObjectCreateShortText() { - return pht('Create Task'); - } - - protected function getEditorURI() { - return $this->getApplication()->getApplicationURI('task/edit/'); - } - - protected function getCommentViewHeaderText($object) { - return pht('Weigh In'); - } - - protected function getCommentViewButtonText($object) { - return pht('Set Sail for Adventure'); - } - - protected function getObjectViewURI($object) { - return '/'.$object->getMonogram(); - } - - protected function buildCustomEditFields($object) { - $status_map = $this->getTaskStatusMap($object); - $priority_map = $this->getTaskPriorityMap($object); - - if ($object->isClosed()) { - $default_status = ManiphestTaskStatus::getDefaultStatus(); - } else { - $default_status = ManiphestTaskStatus::getDefaultClosedStatus(); - } - - if ($object->getOwnerPHID()) { - $owner_value = array($object->getOwnerPHID()); - } else { - $owner_value = array($this->getViewer()->getPHID()); - } - - return array( - id(new PhabricatorHandlesEditField()) - ->setKey('parent') - ->setLabel(pht('Parent Task')) - ->setDescription(pht('Task to make this a subtask of.')) - ->setConduitDescription(pht('Create as a subtask of another task.')) - ->setConduitTypeDescription(pht('PHID of the parent task.')) - ->setAliases(array('parentPHID')) - ->setTransactionType(ManiphestTransaction::TYPE_PARENT) - ->setHandleParameterType(new ManiphestTaskListHTTPParameterType()) - ->setSingleValue(null) - ->setIsReorderable(false) - ->setIsDefaultable(false) - ->setIsLockable(false), - id(new PhabricatorHandlesEditField()) - ->setKey('column') - ->setLabel(pht('Column')) - ->setDescription(pht('Workboard column to create this task into.')) - ->setConduitDescription(pht('Create into a workboard column.')) - ->setConduitTypeDescription(pht('PHID of workboard column.')) - ->setAliases(array('columnPHID')) - ->setTransactionType(ManiphestTransaction::TYPE_COLUMN) - ->setSingleValue(null) - ->setIsInvisible(true) - ->setIsReorderable(false) - ->setIsDefaultable(false) - ->setIsLockable(false), - id(new PhabricatorTextEditField()) - ->setKey('title') - ->setLabel(pht('Title')) - ->setDescription(pht('Name of the task.')) - ->setConduitDescription(pht('Rename the task.')) - ->setConduitTypeDescription(pht('New task name.')) - ->setTransactionType(ManiphestTransaction::TYPE_TITLE) - ->setIsRequired(true) - ->setValue($object->getTitle()), - id(new PhabricatorUsersEditField()) - ->setKey('owner') - ->setAliases(array('ownerPHID', 'assign', 'assigned')) - ->setLabel(pht('Assigned To')) - ->setDescription(pht('User who is responsible for the task.')) - ->setConduitDescription(pht('Reassign the task.')) - ->setConduitTypeDescription( - pht('New task owner, or `null` to unassign.')) - ->setTransactionType(ManiphestTransaction::TYPE_OWNER) - ->setIsCopyable(true) - ->setSingleValue($object->getOwnerPHID()) - ->setCommentActionLabel(pht('Assign / Claim')) - ->setCommentActionValue($owner_value), - id(new PhabricatorSelectEditField()) - ->setKey('status') - ->setLabel(pht('Status')) - ->setDescription(pht('Status of the task.')) - ->setConduitDescription(pht('Change the task status.')) - ->setConduitTypeDescription(pht('New task status constant.')) - ->setTransactionType(ManiphestTransaction::TYPE_STATUS) - ->setIsCopyable(true) - ->setValue($object->getStatus()) - ->setOptions($status_map) - ->setCommentActionLabel(pht('Change Status')) - ->setCommentActionValue($default_status), - id(new PhabricatorSelectEditField()) - ->setKey('priority') - ->setLabel(pht('Priority')) - ->setDescription(pht('Priority of the task.')) - ->setConduitDescription(pht('Change the priority of the task.')) - ->setConduitTypeDescription(pht('New task priority constant.')) - ->setTransactionType(ManiphestTransaction::TYPE_PRIORITY) - ->setIsCopyable(true) - ->setValue($object->getPriority()) - ->setOptions($priority_map) - ->setCommentActionLabel(pht('Change Priority')), - id(new PhabricatorRemarkupEditField()) - ->setKey('description') - ->setLabel(pht('Description')) - ->setDescription(pht('Task description.')) - ->setConduitDescription(pht('Update the task description.')) - ->setConduitTypeDescription(pht('New task description.')) - ->setTransactionType(ManiphestTransaction::TYPE_DESCRIPTION) - ->setValue($object->getDescription()) - ->setPreviewPanel( - id(new PHUIRemarkupPreviewPanel()) - ->setHeader(pht('Description Preview'))), - ); - } - - private function getTaskStatusMap(ManiphestTask $task) { - $status_map = ManiphestTaskStatus::getTaskStatusMap(); - - $current_status = $task->getStatus(); - - // If the current status is something we don't recognize (maybe an older - // status which was deleted), put a dummy entry in the status map so that - // saving the form doesn't destroy any data by accident. - if (idx($status_map, $current_status) === null) { - $status_map[$current_status] = pht('<Unknown: %s>', $current_status); - } - - $dup_status = ManiphestTaskStatus::getDuplicateStatus(); - foreach ($status_map as $status => $status_name) { - // Always keep the task's current status. - if ($status == $current_status) { - continue; - } - - // Don't allow tasks to be changed directly into "Closed, Duplicate" - // status. Instead, you have to merge them. See T4819. - if ($status == $dup_status) { - unset($status_map[$status]); - continue; - } - - // Don't let new or existing tasks be moved into a disabled status. - if (ManiphestTaskStatus::isDisabledStatus($status)) { - unset($status_map[$status]); - continue; - } - } - - return $status_map; - } - - private function getTaskPriorityMap(ManiphestTask $task) { - $priority_map = ManiphestTaskPriority::getTaskPriorityMap(); - $current_priority = $task->getPriority(); - - // If the current value isn't a legitimate one, put it in the dropdown - // anyway so saving the form doesn't cause a side effects. - if (idx($priority_map, $current_priority) === null) { - $priority_map[$current_priority] = pht( - '<Unknown: %s>', - $current_priority); - } - - foreach ($priority_map as $priority => $priority_name) { - // Always keep the current priority. - if ($priority == $current_priority) { - continue; - } - - if (ManiphestTaskPriority::isDisabledPriority($priority)) { - unset($priority_map[$priority]); - continue; - } - } - - return $priority_map; - } - - protected function newEditResponse( - AphrontRequest $request, - $object, - array $xactions) { - - if ($request->isAjax()) { - // Reload the task to make sure we pick up the final task state. - $viewer = $this->getViewer(); - $task = id(new ManiphestTaskQuery()) - ->setViewer($viewer) - ->withIDs(array($object->getID())) - ->needSubscriberPHIDs(true) - ->needProjectPHIDs(true) - ->executeOne(); - - switch ($request->getStr('responseType')) { - case 'card': - return $this->buildCardResponse($task); - default: - return $this->buildListResponse($task); - } - - } - - return parent::newEditResponse($request, $object, $xactions); - } - - private function buildListResponse(ManiphestTask $task) { - $controller = $this->getController(); - - $payload = array( - 'tasks' => $controller->renderSingleTask($task), - 'data' => array(), - ); - - return id(new AphrontAjaxResponse())->setContent($payload); - } - - private function buildCardResponse(ManiphestTask $task) { - $controller = $this->getController(); - $request = $controller->getRequest(); - $viewer = $request->getViewer(); - - $column_phid = $request->getStr('columnPHID'); - $order = $request->getStr('order'); - - $column = id(new PhabricatorProjectColumnQuery()) - ->setViewer($viewer) - ->withPHIDs(array($column_phid)) - ->executeOne(); - if (!$column) { - return new Aphront404Response(); - } - - // If the workboard's project and all descendant projects have been removed - // from the card's project list, we are going to remove it from the board - // completely. - - // TODO: If the user did something sneaky and changed a subproject, we'll - // currently leave the card where it was but should really move it to the - // proper new column. - - $descendant_projects = id(new PhabricatorProjectQuery()) - ->setViewer($viewer) - ->withAncestorProjectPHIDs(array($column->getProjectPHID())) - ->execute(); - $board_phids = mpull($descendant_projects, 'getPHID', 'getPHID'); - $board_phids[$column->getProjectPHID()] = $column->getProjectPHID(); - - $project_map = array_fuse($task->getProjectPHIDs()); - $remove_card = !array_intersect_key($board_phids, $project_map); - - $positions = id(new PhabricatorProjectColumnPositionQuery()) - ->setViewer($viewer) - ->withBoardPHIDs(array($column->getProjectPHID())) - ->withColumnPHIDs(array($column->getPHID())) - ->execute(); - $task_phids = mpull($positions, 'getObjectPHID'); - - $column_tasks = id(new ManiphestTaskQuery()) - ->setViewer($viewer) - ->withPHIDs($task_phids) - ->needProjectPHIDs(true) - ->execute(); - - if ($order == PhabricatorProjectColumn::ORDER_NATURAL) { - // TODO: This is a little bit awkward, because PHP and JS use - // slightly different sort order parameters to achieve the same - // effect. It would be good to unify this a bit at some point. - $sort_map = array(); - foreach ($positions as $position) { - $sort_map[$position->getObjectPHID()] = array( - -$position->getSequence(), - $position->getID(), - ); - } - } else { - $sort_map = mpull( - $column_tasks, - 'getPrioritySortVector', - 'getPHID'); - } - - $data = array( - 'removeFromBoard' => $remove_card, - 'sortMap' => $sort_map, - ); - - // TODO: This should just use HandlePool once we get through the EditEngine - // transition. - $owner = null; - if ($task->getOwnerPHID()) { - $owner = id(new PhabricatorHandleQuery()) - ->setViewer($viewer) - ->withPHIDs(array($task->getOwnerPHID())) - ->executeOne(); - } - - $handle_phids = $task->getProjectPHIDs(); - $handle_phids = array_fuse($handle_phids); - $handle_phids = array_diff_key($handle_phids, $board_phids); - - $project_handles = $viewer->loadHandles($handle_phids); - $project_handles = iterator_to_array($project_handles); - - $projects = $request->getArr('projectPHIDs'); - $project = $this->getSprintProjectforTask($viewer, $projects); - - $tasks = id(new SprintBoardTaskCard()) - ->setViewer($viewer) - ->setProject($project) - ->setProjectHandles($project_handles) - ->setTask($task) - ->setOwner($owner) - ->setCanEdit(true) - ->getItem(); - - $tasks->addClass('phui-workcard'); - - $payload = array( - 'tasks' => $tasks, - 'data' => $data, - ); - - return id(new AphrontAjaxResponse())->setContent($payload); - } - - private function getSprintProjectforTask($viewer, $projects) { - $project = null; - - if ($projects) { - $query = id(new PhabricatorProjectQuery()) - ->setViewer($viewer) - ->withPHIDs($projects); - } else { - return null; - } - - $projects = $query->execute(); - - foreach ($projects as $project) { - $sprintquery = id(new SprintQuery()) - ->setPHID($project->getPHID()); - if ($sprintquery->getIsSprint()) { - return $project; - } - } - - } - - -} diff --git a/src/customfield/SprintBeginDateField.php b/src/customfield/SprintBeginDateField.php index 0822e883553308e995d86c5d08baf4562bff1ad8..dcfe98786a588ddb8501db33ead539fdddb5e36b 100644 --- a/src/customfield/SprintBeginDateField.php +++ b/src/customfield/SprintBeginDateField.php @@ -1,4 +1,5 @@ <?php + /** * @author Michael Peters * @author Christopher Johnson diff --git a/src/customfield/SprintEndDateField.php b/src/customfield/SprintEndDateField.php index dd17dbfcd90dc74b1b238b99e6bf61c52b56ef7c..49bffeacbf3c94f74f4dc502ff9b391bfbf41597 100644 --- a/src/customfield/SprintEndDateField.php +++ b/src/customfield/SprintEndDateField.php @@ -1,4 +1,5 @@ <?php + /** * @author Michael Peters * @author Christopher Johnson diff --git a/src/customfield/SprintProjectCustomField.php b/src/customfield/SprintProjectCustomField.php index 5bed886e7c7d531c316b846c4ffff0ba1e2c52b5..94b201f775d59f02cda2905e6741c650cd8f903d 100644 --- a/src/customfield/SprintProjectCustomField.php +++ b/src/customfield/SprintProjectCustomField.php @@ -1,4 +1,5 @@ <?php + /** * @author Michael Peters * @author Christopher Johnson diff --git a/src/customfield/SprintTaskStoryPointsField.php b/src/customfield/SprintTaskStoryPointsField.php index 9425eb515050b29d6bafd2b1f5c8854beb5b2780..1078a94feb6b910410299183b7f9df5c6b0be643 100644 --- a/src/customfield/SprintTaskStoryPointsField.php +++ b/src/customfield/SprintTaskStoryPointsField.php @@ -1,4 +1,5 @@ <?php + /** * @author Michael Peters * @author Christopher Johnson @@ -14,7 +15,7 @@ final class SprintTaskStoryPointsField extends ManiphestCustomField public function __construct() { $this->obj = clone $this; - $this->textproxy = id(new PhabricatorStandardCustomFieldText()) + $this->textproxy = id(new PhabricatorStandardCustomFieldInt()) ->setFieldKey($this->getFieldKey()) ->setApplicationField($this->obj) ->setFieldConfig(array( diff --git a/src/engine/SprintProjectProfilePanelEngine.php b/src/engine/SprintProjectProfilePanelEngine.php index ad305c280ffef0dffc31b8974ae6b5a66c9a8b2a..ecc6e9f88cc2eaeeb766c989e4b93e353758035e 100644 --- a/src/engine/SprintProjectProfilePanelEngine.php +++ b/src/engine/SprintProjectProfilePanelEngine.php @@ -20,6 +20,10 @@ final class SprintProjectProfilePanelEngine ->setBuiltinKey(PhabricatorProject::PANEL_PROFILE) ->setPanelKey(PhabricatorProjectDetailsProfilePanel::PANELKEY); + $panels[] = $this->newPanel() + ->setBuiltinKey(PhabricatorProject::PANEL_POINTS) + ->setPanelKey(PhabricatorProjectPointsProfilePanel::PANELKEY); + $panels[] = $this->newPanel() ->setBuiltinKey(PhabricatorProject::PANEL_WORKBOARD) ->setPanelKey(PhabricatorProjectWorkboardProfilePanel::PANELKEY); @@ -28,11 +32,22 @@ final class SprintProjectProfilePanelEngine ->setBuiltinKey(PhabricatorProject::PANEL_MEMBERS) ->setPanelKey(PhabricatorProjectMembersProfilePanel::PANELKEY); + $panels[] = $this->newPanel() + ->setBuiltinKey(PhabricatorProject::PANEL_SUBPROJECTS) + ->setPanelKey(PhabricatorProjectSubprojectsProfilePanel::PANELKEY); + $panels[] = $this->newPanel() ->setBuiltinKey(PhabricatorProject::PANEL_MANAGE) ->setPanelKey(PhabricatorProjectManageProfilePanel::PANELKEY); + $panels[] = $this->newPanel() + ->setBuiltinKey(SprintConstants::PANEL_BURNDOWN) + ->setPanelKey(SprintProjectProfilePanel::PANELKEY); + + $panels[] = $this->newPanel() + ->setBuiltinKey(SprintConstants::PANEL_PHRAGILE) + ->setPanelKey(PhragileProfilePanel::PANELKEY); + return $panels; } - } diff --git a/src/events/BurndownActionMenuEventListener.php b/src/events/BurndownActionMenuEventListener.php deleted file mode 100644 index 42ba3c404f9230f8e162b00bda2c54c5479ce61e..0000000000000000000000000000000000000000 --- a/src/events/BurndownActionMenuEventListener.php +++ /dev/null @@ -1,97 +0,0 @@ -<?php -/** - * @author Michael Peters - * @author Christopher Johnson - * @license GPL version 3 - */ - -final class BurndownActionMenuEventListener extends PhabricatorEventListener { - - public function register() { - $this->listen(PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS); - } - - public function handleEvent(PhutilEvent $event) { - switch ($event->getType()) { - case PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS: - $this->handleActionsEvent($event); - break; - } - } - - private function handleActionsEvent(PhutilEvent $event) { - $object = $event->getValue('object'); - $enable_phragile = PhabricatorEnv::getEnvConfig('sprint.enable-phragile'); - $actions = null; - if ($object instanceof PhabricatorProject && - $this->isSprint($object) !== false && $enable_phragile === false) { - $actions = $this->renderUserItems($event); - } else if ($object instanceof PhabricatorProject && - $this->isSprint($object) !== false && $enable_phragile !== false) { - $actions = $this->renderOptionItems($event); - } - - $this->addActionMenuItems($event, $actions); - } - - protected function isSprint($object) { - $validator = new SprintValidator(); - $issprint = call_user_func(array($validator, 'checkForSprint'), - array($validator, 'isSprint'), $object->getPHID()); - return $issprint; - } - - private function renderUserItems(PhutilEvent $event) { - if (!$this->canUseApplication($event->getUser())) { - return null; - } - - $project = $event->getValue('object'); - $projectid = $project->getId(); - - $view_uri = '/project/sprint/view/'.$projectid; - $board_uri = '/project/sprint/board/'.$projectid; - - $burndown = id(new PhabricatorActionView()) - ->setIcon('fa-bar-chart-o') - ->setName(pht('View Burndown')) - ->setHref($view_uri); - - $board = id(new PhabricatorActionView()) - ->setIcon('fa-columns') - ->setName(pht('View Sprint Board')) - ->setHref($board_uri); - - return array ($burndown, $board); - } - - private function renderOptionItems(PhutilEvent $event) { - if (!$this->canUseApplication($event->getUser())) { - return null; - } - - $project = $event->getValue('object'); - $projectid = $project->getId(); - $phragile_base_uri = PhabricatorEnv::getEnvConfig('sprint.phragile-uri'); - $phragile_uri = $phragile_base_uri.$projectid; - $view_uri = '/project/sprint/view/'.$projectid; - $board_uri = '/project/sprint/board/'.$projectid; - - $burndown = id(new PhabricatorActionView()) - ->setIcon('fa-bar-chart-o') - ->setName(pht('View Burndown')) - ->setHref($view_uri); - - $board = id(new PhabricatorActionView()) - ->setIcon('fa-columns') - ->setName(pht('View Sprint Board')) - ->setHref($board_uri); - - $phragile = id(new PhabricatorActionView()) - ->setIcon('fa-pie-chart') - ->setName(pht('View in Phragile')) - ->setHref($phragile_uri); - - return array ($burndown, $board, $phragile); - } -} diff --git a/src/profilepanel/SprintProjectWorkboardProfilePanel.php b/src/profilepanel/PhragileProfilePanel.php similarity index 59% rename from src/profilepanel/SprintProjectWorkboardProfilePanel.php rename to src/profilepanel/PhragileProfilePanel.php index 370be21f2bc4667a7c7abc45d7a1d6122a3d0224..f256926d352ecbc70b2723282b607b8047ae2553 100644 --- a/src/profilepanel/SprintProjectWorkboardProfilePanel.php +++ b/src/profilepanel/PhragileProfilePanel.php @@ -1,17 +1,25 @@ <?php -final class SprintProjectWorkboardProfilePanel +final class PhragileProfilePanel extends PhabricatorProfilePanel { - const PANEL_WORKBOARD = 'project.workboard'; - const PANELKEY = 'sprint.workboard'; + const PANELKEY = 'project.phragile'; public function getPanelTypeName() { - return pht('Project Workboard'); + return pht('Phragile'); } private function getDefaultName() { - return pht('Workboard'); + return pht('Phragile'); + } + + public function shouldEnableForObject($object) { + $enable_phragile = PhabricatorEnv::getEnvConfig('sprint.enable-phragile'); + + if ($enable_phragile) { + return true; + } + return false; } public function getDisplayName( @@ -38,33 +46,23 @@ final class SprintProjectWorkboardProfilePanel protected function newNavigationMenuItems( PhabricatorProfilePanelConfiguration $config) { - $viewer = $this->getViewer(); - - // Workboards are only available if Maniphest is installed. - $class = 'PhabricatorManiphestApplication'; - if (!PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) { - return array(); - } $project = $config->getProfileObject(); - $columns = id(new PhabricatorProjectColumnQuery()) - ->setViewer($viewer) - ->withProjectPHIDs(array($project->getPHID())) - ->execute(); - if ($columns) { - $icon = 'fa-columns'; - } else { - $icon = 'fa-columns grey'; - } + $has_children = ($project->getHasSubprojects()) || + ($project->getHasMilestones()); $id = $project->getID(); - $href = "/project/sprint/board/{$id}/"; + $name = $this->getDisplayName($config); + $icon = 'fa-link'; + $phragile_base_uri = PhabricatorEnv::getEnvConfig('sprint.phragile-uri'); + $href = $phragile_base_uri.$id; $item = $this->newItem() ->setHref($href) ->setName($name) + ->setDisabled(!$has_children) ->setIcon($icon); return array( diff --git a/src/profilepanel/SprintProjectDetailsProfilePanel.php b/src/profilepanel/SprintProjectProfilePanel.php similarity index 67% rename from src/profilepanel/SprintProjectDetailsProfilePanel.php rename to src/profilepanel/SprintProjectProfilePanel.php index 2684a4b6f4018e2d00abe9cd5b3fa45a4a28572e..de2fa29f56e8d1dc9a6275703a1598ddc5ed0b74 100644 --- a/src/profilepanel/SprintProjectDetailsProfilePanel.php +++ b/src/profilepanel/SprintProjectProfilePanel.php @@ -1,17 +1,20 @@ <?php -final class SprintProjectDetailsProfilePanel +final class SprintProjectProfilePanel extends PhabricatorProfilePanel { - const PANEL_PROFILE = 'sprint.profile'; - const PANELKEY = 'sprint.details'; + const PANELKEY = 'project.sprint'; public function getPanelTypeName() { - return pht('Sprint Details'); + return pht('Project Burndown'); } private function getDefaultName() { - return pht('Sprint Details'); + return pht('Burndown'); + } + + public function shouldEnableForObject($object) { + return true; } public function getDisplayName( @@ -41,16 +44,20 @@ final class SprintProjectDetailsProfilePanel $project = $config->getProfileObject(); + $has_children = ($project->getHasSubprojects()) || + ($project->getHasMilestones()); + $id = $project->getID(); - $picture = $project->getProfileImageURI(); - $name = $project->getName(); - $href = "/project/sprint/profile/{$id}/"; + $name = $this->getDisplayName($config); + $icon = 'fa-calendar'; + $href = "/project/sprint/view/{$id}/"; $item = $this->newItem() ->setHref($href) ->setName($name) - ->setProfileImage($picture); + ->setDisabled(!$has_children) + ->setIcon($icon); return array( $item, diff --git a/src/query/SprintQuery.php b/src/query/SprintQuery.php index bb94457cf525504104a42d046dc63d521792ab25..b1463f021e9fcea788742d077f5a225584e225a6 100644 --- a/src/query/SprintQuery.php +++ b/src/query/SprintQuery.php @@ -6,17 +6,17 @@ final class SprintQuery extends SprintDAO { private $project; private $projectPHID; - public function setProject ($project) { + public function setProject($project) { $this->project = $project; return $this; } - public function setViewer ($viewer) { + public function setViewer($viewer) { $this->viewer = $viewer; return $this; } - public function setPHID ($project_phid) { + public function setPHID($project_phid) { $this->projectPHID = $project_phid; return $this; } @@ -178,22 +178,22 @@ final class SprintQuery extends SprintDAO { return $xactions; } - public function getXActionObj () { + public function getXActionObj() { $table = new ManiphestTransaction(); return $table; } - public function getXActionConn () { + public function getXActionConn() { $conn = $this->getXActionObj()->establishConnection('r'); return $conn; } - public function getCustomFieldObj () { + public function getCustomFieldObj() { $table = new ManiphestCustomFieldStorage(); return $table; } - public function getCustomFieldConn () { + public function getCustomFieldConn() { $conn = $this->getCustomFieldObj()->establishConnection('r'); return $conn; } @@ -256,11 +256,12 @@ final class SprintQuery extends SprintDAO { return $task_data; } - public function getEdges ($tasks) { + public function getEdges($tasks) { // Load all edges of depends and depended on tasks $edges = id(new PhabricatorEdgeQuery()) ->withSourcePHIDs(array_keys($tasks)) - ->withEdgeTypes(array( ManiphestTaskDependsOnTaskEdgeType::EDGECONST, + ->withEdgeTypes(array( + ManiphestTaskDependsOnTaskEdgeType::EDGECONST, ManiphestTaskDependedOnByTaskEdgeType::EDGECONST, )) ->execute(); @@ -313,7 +314,7 @@ final class SprintQuery extends SprintDAO { return $positions; } - public function getProjectNamefromPHID ($phid) { + public function getProjectNamefromPHID($phid) { $project = id(new PhabricatorProjectQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) ->withPHIDs(array($phid)) @@ -322,7 +323,7 @@ final class SprintQuery extends SprintDAO { return $name; } - public function getTaskNamefromPHID ($phid) { + public function getTaskNamefromPHID($phid) { $task = id(new ManiphestTaskQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) ->withPHIDs(array($phid)) diff --git a/src/storage/BoardDataProvider.php b/src/storage/BoardDataProvider.php index 2088e3c039049b125981a43e8e680cb58d48eced..3a3729e7f84617019edb8dd2b45319069f58ebb2 100644 --- a/src/storage/BoardDataProvider.php +++ b/src/storage/BoardDataProvider.php @@ -9,7 +9,6 @@ final class BoardDataProvider { private $viewer; private $request; private $tasks; - private $taskpoints; private $query; private $stats; private $timezone; @@ -17,81 +16,72 @@ final class BoardDataProvider { private $chartdata; private $coldata; - public function setStart ($start) { + public function setStart($start) { $this->start = $start; return $this; } - public function setEnd ($end) { + public function setEnd($end) { $this->end = $end; return $this; } - public function setProject ($project) { + public function setProject($project) { $this->project = $project; return $this; } - public function getProject () { + public function getProject() { return $this->project; } - public function getColumnData () { + public function getColumnData() { return $this->coldata; } - public function getChartData () { + public function getChartData() { return $this->chartdata; } - public function setViewer ($viewer) { + public function setViewer($viewer) { $this->viewer = $viewer; return $this; } - public function setRequest ($request) { + public function setRequest($request) { $this->request = $request; return $this; } - public function setTimezone ($timezone) { + public function setTimezone($timezone) { $this->timezone = $timezone; return $this; } - public function setTimeSeries ($timeseries) { + public function setTimeSeries($timeseries) { $this->timeseries = $timeseries; return $this; } - public function getTimeSeries () { + public function getTimeSeries() { return $this->timeseries; } - public function setTasks ($tasks) { + public function setTasks($tasks) { $this->tasks = $tasks; return $this; } - public function getTasks () { + public function getTasks() { return $this->tasks; } - public function setTaskPoints ($taskpoints) { - $this->taskpoints = $taskpoints; - return $this; - } - - public function getTaskPoints() { - return $this->taskpoints; - } - - public function setStats ($stats) { + public function setStats($stats) { $this->stats = $stats; return $this; } - public function setQuery ($query) { + public function setQuery($query) { $this->query = $query; return $this; } @@ -134,7 +124,9 @@ final class BoardDataProvider { $task_count = count($tasks); $task_points_total = $this->getTaskPointsSum($tasks); $coldata[] = array( - $colname, $task_count, $task_points_total, + $colname, + $task_count, + $task_points_total, ); } return $coldata; @@ -157,17 +149,17 @@ final class BoardDataProvider { private function getTaskPointsSum($tasks) { $points_sum = null; - $taskpoints = mpull($this->taskpoints, null, 'getObjectPHID'); - $column_points = array_intersect_key($taskpoints, $tasks); - if (!empty($column_points)) { - foreach ($column_points as $key => $value) { - $points = $value->getfieldValue(); + // $taskpoints = mpull($this->taskpoints, null, 'getObjectPHID'); + // $column_points = array_intersect_key($taskpoints, $tasks); + // if (!empty($column_points)) { + foreach ($tasks as $task) { + $points = $task->getPoints(); $points_sum += $points; } if (!isset($points_sum)) { $points_sum = '0'; } - } +// } return $points_sum; } @@ -201,13 +193,13 @@ final class BoardDataProvider { $sprint_xaction = id(new SprintColumnTransaction()) ->setViewer($this->viewer) - ->setTaskPoints($this->taskpoints) + ->setTasks($this->tasks) ->setQuery($this->query) ->setProject($this->project) ->setEvents($xactions); $dates = $sprint_xaction->parseEvents($date_array, $xaction_map); - $this->stats->setTaskPoints($this->taskpoints); + $this->stats->setTasks($this->tasks); $sprint_data = $this->stats->setSprintData($dates); $data = $this->stats->buildDataSet($sprint_data); $this->chartdata = $this->stats->transposeArray($data); diff --git a/src/storage/SprintColumnTransaction.php b/src/storage/SprintColumnTransaction.php index a3470360acdae266f61c742d83f396a343f7eeb6..cfbfa0943f96a617093248d7981b691767dc4f3e 100644 --- a/src/storage/SprintColumnTransaction.php +++ b/src/storage/SprintColumnTransaction.php @@ -5,27 +5,27 @@ final class SprintColumnTransaction { private $viewer; private $project; private $query; - private $taskpoints; + private $tasks; private $events; private $xquery; - public function setViewer ($viewer) { + public function setViewer($viewer) { $this->viewer = $viewer; return $this; } - public function setProject ($project) { + public function setProject($project) { $this->project = $project; return $this; } - public function setQuery ($query) { + public function setQuery($query) { $this->query = $query; return $this; } - public function setTaskPoints ($taskpoints) { - $this->taskpoints = $taskpoints; + public function setTasks($tasks) { + $this->tasks = $tasks; return $this; } @@ -44,13 +44,14 @@ final class SprintColumnTransaction { public function parseEvents($dates) { $sprintpoints = id(new SprintPoints()) - ->setTaskPoints($this->taskpoints); + ->setTasks($this->tasks) + ->setViewer($this->viewer); foreach ($this->events as $event) { $modify_date = $event['modified']; $task_phid = $event['objectPHID']; - $points = $sprintpoints->getTaskPoints($task_phid); + $points = $sprintpoints->getTaskPointsbyPHID($task_phid); $date = phabricator_format_local_time($modify_date, $this->viewer, 'D M j'); @@ -89,7 +90,7 @@ final class SprintColumnTransaction { return $dates; } - private function setXActionEventType ($old_col_name, $new_col_name) { + private function setXActionEventType($old_col_name, $new_col_name) { $old_is_closed = ($old_col_name === null) || SprintConstants::TYPE_CLOSED_STATUS_COLUMN == $old_col_name; diff --git a/src/storage/SprintHistoryDataProvider.php b/src/storage/SprintHistoryDataProvider.php index 6539363b70cb96e42ea9ef02349871b9fddc15ee..2931c5dfa6eecd86fa8ee368322bf9c43d6200c8 100644 --- a/src/storage/SprintHistoryDataProvider.php +++ b/src/storage/SprintHistoryDataProvider.php @@ -7,21 +7,21 @@ final class SprintHistoryDataProvider { private $history; private $project; - public function setViewer ($viewer) { + public function setViewer($viewer) { $this->viewer = $viewer; return $this; } - public function setRequest ($request) { + public function setRequest($request) { $this->request = $request; return $this; } - public function getRequest () { + public function getRequest() { return $this->request; } - public function getRows () { + public function getRows() { return $this->rows; } @@ -55,13 +55,13 @@ final class SprintHistoryDataProvider { $rows[] = $row; } - $this->rows = array_map(function($a) { return $a['0']; }, $rows); + $this->rows = array_map(function ($a) { return $a['0']; }, $rows); return $this; } private function buildRowSet($remove_action, $add_action, $projectname, $taskname, $createdEpoch, $created) { $rows = array(); - $rows[] = array ( + $rows[] = array( $remove_action, $add_action, $projectname, diff --git a/src/storage/SprintListDataProvider.php b/src/storage/SprintListDataProvider.php index 89e2072a8e42537c2e1d2a9a5c00a32378d00f4c..36b99c9a2403c8477497265d2928b2ec0e3043d2 100644 --- a/src/storage/SprintListDataProvider.php +++ b/src/storage/SprintListDataProvider.php @@ -7,21 +7,21 @@ final class SprintListDataProvider { private $sprints; private $rows; - public function setViewer ($viewer) { + public function setViewer($viewer) { $this->viewer = $viewer; return $this; } - public function setRequest ($request) { + public function setRequest($request) { $this->request = $request; return $this; } - public function getRequest () { + public function getRequest() { return $this->request; } - public function getRows () { + public function getRows() { return $this->rows; } @@ -59,13 +59,13 @@ final class SprintListDataProvider { $rows[] = $row; } - $this->rows = array_map(function($a) { return $a['0']; }, $rows); + $this->rows = array_map(function ($a) { return $a['0']; }, $rows); return $this; } private function buildRowSet($project_id, $project_name, $start, $end) { $rows = array(); - $rows[] = array ( + $rows[] = array( phutil_tag( 'a', array( diff --git a/src/storage/SprintStats.php b/src/storage/SprintStats.php index 8e017621def83f6aec3df076ce8a5d480c0416f7..d2dece99a777ee19b05ddebf61ffaa8da8354754 100644 --- a/src/storage/SprintStats.php +++ b/src/storage/SprintStats.php @@ -2,9 +2,9 @@ final class SprintStats { private $timezone; - private $taskpoints; + private $tasks; - public function setTimezone ($viewer) { + public function setTimezone($viewer) { $this->timezone = new DateTimeZone($viewer->getTimezoneIdentifier()); return $this->timezone; } @@ -15,8 +15,8 @@ final class SprintStats { return $dates; } - public function setTaskPoints ($taskpoints) { - $this->taskpoints = $taskpoints; + public function setTasks($tasks) { + $this->tasks = $tasks; return $this; } @@ -42,14 +42,14 @@ final class SprintStats { public function buildTimeSeries($start, $end) { $timezone = $this->timezone; - $timeseries = array_keys($this->buildDateArray ($start, $end, $timezone)); + $timeseries = array_keys($this->buildDateArray($start, $end, $timezone)); return $timeseries; } /** * @param string $date */ - public function getBurndownDate ($date) { + public function getBurndownDate($date) { $sprint_date = id(new BurndownDataDate($date)); return $sprint_date; } @@ -63,7 +63,7 @@ final class SprintStats { public function sumTotalPoints($dates) { $sprintpoints = id(new SprintPoints()) - ->setTaskPoints($this->taskpoints); + ->setTasks($this->tasks); $points_total = $sprintpoints->sumTotalTaskPoints(); foreach ($dates as $date) { $date->setPointsTotal($points_total); @@ -73,7 +73,7 @@ final class SprintStats { public function sumTotalTasks($dates) { $sprintpoints = id(new SprintPoints()) - ->setTaskPoints($this->taskpoints); + ->setTaskPoints($this->tasks); $points_total = $sprintpoints->sumTotalTasks(); foreach ($dates as $date) { $date->setTasksTotal($points_total); @@ -85,7 +85,7 @@ final class SprintStats { $first = true; $previous = new BurndownDataDate($date = null); $sprintpoints = id(new SprintPoints()) - ->setTaskPoints($this->taskpoints); + ->setTasks($this->tasks); $points_total = $sprintpoints->sumTotalTaskPoints(); foreach ($dates as $date) { @@ -113,7 +113,7 @@ final class SprintStats { $first = true; $previous = new BurndownDataDate($date = null); $sprintpoints = id(new SprintPoints()) - ->setTaskPoints($this->taskpoints); + ->setTasks($this->tasks); $tasks_total = $sprintpoints->sumTotalTasks(); foreach ($dates as $date) { $tasks_closed_today = $date->getTasksClosedToday(); @@ -151,14 +151,15 @@ final class SprintStats { $elapsed_business_days++; } - $date->setPointsIdealRemaining (round($date->getPointsTotal() * + $date->setPointsIdealRemaining(round($date->getPointsTotal() * (1 - ($elapsed_business_days / $total_business_days)), 1)); } return $dates; } - public function buildDataSet ($dates) { - $data = array(array( + public function buildDataSet($dates) { + $data = array( + array( pht('Start Points'), pht('Remaining Points'), pht('Ideal Points'), diff --git a/src/storage/TaskTableDataProvider.php b/src/storage/TaskTableDataProvider.php index df2b232ea9e2b433eae5d85ef597f7a38b58f2ea..6179b58441ede4a8d8d4f7ee2b675421e16f3326 100644 --- a/src/storage/TaskTableDataProvider.php +++ b/src/storage/TaskTableDataProvider.php @@ -6,7 +6,6 @@ final class TaskTableDataProvider { private $viewer; private $request; private $tasks; - private $taskpoints; private $query; private $rows; private $blocked; @@ -16,41 +15,36 @@ final class TaskTableDataProvider { private $handles; - public function setProject ($project) { + public function setProject($project) { $this->project = $project; return $this; } - public function setViewer ($viewer) { + public function setViewer($viewer) { $this->viewer = $viewer; return $this; } - public function setRequest ($request) { + public function setRequest($request) { $this->request = $request; return $this; } - public function setTasks ($tasks) { + public function setTasks($tasks) { $this->tasks = $tasks; return $this; } - public function setTaskPoints ($taskpoints) { - $this->taskpoints = $taskpoints; - return $this; - } - - public function setQuery ($query) { + public function setQuery($query) { $this->query = $query; return $this; } - public function getRows () { + public function getRows() { return $this->rows; } - public function getRequest () { + public function getRequest() { return $this->request; } @@ -85,7 +79,7 @@ final class TaskTableDataProvider { $ptasks = array_merge($ptasks, $ptask); } } - return array ($blocker, $ptasks); + return array($blocker, $ptasks); } @@ -93,26 +87,26 @@ final class TaskTableDataProvider { $edges = $this->query->getEdges($this->tasks); $map = $this->buildTaskMap($edges, $this->tasks); $sprintpoints = id(new SprintPoints()) - ->setTaskPoints($this->taskpoints); + ->setTasks($this->tasks); $this->handles = $this->getHandles(); $rows = array(); foreach ($this->tasks as $task) { $this->blocked = $this->checkForBlocked($task, $map); - list ($this->blocker, $this->ptasks) = $this->checkForBlocker($task, + list($this->blocker, $this->ptasks) = $this->checkForBlocker($task, $map); - $this->points = $sprintpoints->getTaskPoints($task->getPHID()); + $this->points = $sprintpoints->getTaskPoints($task); $row = $this->addTaskToTree($task); $rows[] = $row; } - $this->rows = array_map(function($a) { return $a['0']; }, $rows); + $this->rows = array_map(function ($a) { return $a['0']; }, $rows); return $this; } - private function buildTaskMap ($edges, $tasks) { + private function buildTaskMap($edges, $tasks) { $map = array(); foreach ($tasks as $task) { $phid = $task->getPHID(); @@ -209,7 +203,9 @@ final class TaskTableDataProvider { ? 'phui-tag-core-closed' : '', ), - array ($this->buildTaskLink($task), $blockericon, + array( + $this->buildTaskLink($task), + $blockericon, $blockedicon, ))), $cdate, diff --git a/src/tests/SprintApplicationTest.php b/src/tests/SprintApplicationTest.php index 61716f8376005402347cf0dc7d7972de29c4d499..20551696479c49ee40b7c63fe8454cd13720f9ef 100644 --- a/src/tests/SprintApplicationTest.php +++ b/src/tests/SprintApplicationTest.php @@ -1,13 +1,14 @@ <?php + final class SprintApplicationTest extends SprintTestCase { - public function testGetName () { + public function testGetName() { $burndown_application = new SprintApplication(); $name = $burndown_application->getName(); $this->assertEquals('Sprint', $name); } - public function testBaseURI () { + public function testBaseURI() { $burndown_application = new SprintApplication(); $baseuri = $burndown_application->getBaseURI(); $this->assertEquals('/project/sprint/', $baseuri); diff --git a/src/tests/SprintControllerTest.php b/src/tests/SprintControllerTest.php index 62aa372fa7eed6e4b0bd560bbedb7e7affbae321..b9103c7170f8b6ca94bf27da55abf18c391e3065 100644 --- a/src/tests/SprintControllerTest.php +++ b/src/tests/SprintControllerTest.php @@ -1,4 +1,5 @@ <?php + final class SprintControllerTest extends SprintTestCase { public function testshouldAllowPublic() { diff --git a/src/tests/SprintCustomFieldTest.php b/src/tests/SprintCustomFieldTest.php index 2364f93ec7a50b63b9a665eceed9d560d2d88d60..ebe91c8b1f9d6546c8c45649a3cb0b718c60b6bf 100644 --- a/src/tests/SprintCustomFieldTest.php +++ b/src/tests/SprintCustomFieldTest.php @@ -1,4 +1,5 @@ <?php + final class SprintCustomFieldTest extends SprintTestCase { public function testgetBeginFieldName() { diff --git a/src/tests/SprintQueryTest.php b/src/tests/SprintQueryTest.php index 821f0df4d10abe5cf0a01af2473ad055fe421dd6..77a78106124b540e25b08bfb13fdbb3e34906d56 100644 --- a/src/tests/SprintQueryTest.php +++ b/src/tests/SprintQueryTest.php @@ -1,4 +1,5 @@ <?php + final class SprintQueryTest extends SprintTestCase { public function getRequestObject() { diff --git a/src/tests/SprintStatsTest.php b/src/tests/SprintStatsTest.php index 115fc690db343432a9f0332df76fe4f81247eaab..ede4d14366ece863611a5d484dcda4fbf92fc06e 100644 --- a/src/tests/SprintStatsTest.php +++ b/src/tests/SprintStatsTest.php @@ -1,4 +1,5 @@ <?php + final class SprintStatsTest extends SprintTestCase { diff --git a/src/tests/SprintTestCase.php b/src/tests/SprintTestCase.php index 0e4137dbd0c0c5b6a3245c44d9b1d3add759fb03..4beeb5b23bb32656ea47cc3a340faac19388e446 100644 --- a/src/tests/SprintTestCase.php +++ b/src/tests/SprintTestCase.php @@ -1,4 +1,5 @@ <?php + // require_once '/srv/phab/webroot-static/Sprint/scripts/__init_script__.php'; abstract class SprintTestCase extends PHPUnit_Framework_TestCase { diff --git a/src/util/BurndownDataDate.php b/src/util/BurndownDataDate.php index 2d6eb7c0da5f51a2989de9adbd3074c90975ec18..4d95cc68fd48d4b84bc532fb0879a32f8c803399 100644 --- a/src/util/BurndownDataDate.php +++ b/src/util/BurndownDataDate.php @@ -1,4 +1,5 @@ <?php + /** * @author Michael Peters * @author Christopher Johnson @@ -28,27 +29,27 @@ final class BurndownDataDate extends Phobject { $this->date = $date; } - public function setTasksAddedToday () { + public function setTasksAddedToday() { return $this->tasks_added_today = $this->tasks_added_today + 1; } - public function getTasksAddedToday () { + public function getTasksAddedToday() { return $this->tasks_added_today; } - public function setTasksClosedToday () { + public function setTasksClosedToday() { return $this->tasks_closed_today = $this->tasks_closed_today + 1; } - public function getTasksClosedToday () { + public function getTasksClosedToday() { return $this->tasks_closed_today; } - public function setTasksReopenedToday () { + public function setTasksReopenedToday() { return $this->tasks_reopened_today = $this->tasks_reopened_today + 1; } - public function getTasksReopenedToday () { + public function getTasksReopenedToday() { return $this->tasks_reopened_today; } @@ -76,27 +77,27 @@ final class BurndownDataDate extends Phobject { return $this->tasks_remaining; } - public function setPointsAddedToday ($points) { + public function setPointsAddedToday($points) { $this->points_added_today = $this->points_added_today + $points; } - public function getPointsAddedToday () { + public function getPointsAddedToday() { return $this->points_added_today; } - public function setPointsClosedToday ($points) { + public function setPointsClosedToday($points) { $this->points_closed_today = $this->points_closed_today + $points; } - public function getPointsClosedToday () { + public function getPointsClosedToday() { return $this->points_closed_today; } - public function setPointsReopenedToday ($points) { + public function setPointsReopenedToday($points) { $this->points_reopened_today = $this->points_reopened_today + $points; } - public function getPointsReopenedToday () { + public function getPointsReopenedToday() { return $this->points_reopened_today; } diff --git a/src/util/SprintBoardCardToken.php b/src/util/SprintBoardCardToken.php deleted file mode 100644 index ea3e67749bb8d8c7c279f72da544500b24555237..0000000000000000000000000000000000000000 --- a/src/util/SprintBoardCardToken.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php - -final class SprintBoardCardToken extends Phobject { - private $viewer; - - public function setViewer ($viewer) { - $this->viewer = $viewer; - return $this; - } - - public function getTokensForTask($task) { - $tokens_given = id(new PhabricatorTokenGivenQuery()) - ->setViewer($this->viewer) - ->withObjectPHIDs(array($task->getPHID())) - ->execute(); - - if (!$tokens_given) { - return null; - } - - $tokens = id(new PhabricatorTokenQuery()) - ->setViewer($this->viewer) - ->withPHIDs(mpull($tokens_given, 'getTokenPHID')) - ->execute(); - $tokens = mpull($tokens, null, 'getPHID'); - - $author_phids = mpull($tokens_given, 'getAuthorPHID'); - $handles = id(new PhabricatorHandleQuery()) - ->setViewer($this->viewer) - ->withPHIDs($author_phids) - ->execute(); - - Javelin::initBehavior('phabricator-tooltips'); - - $list = array(); - foreach ($tokens_given as $token_given) { - if (!idx($tokens, $token_given->getTokenPHID())) { - continue; - } - - $token = $tokens[$token_given->getTokenPHID()]; - $aural = javelin_tag( - 'span', - array( - 'aural' => true, - ), - pht( - '"%s" token, awarded by %s.', - $token->getName(), - $handles[$token_given->getAuthorPHID()]->getName())); - - $tokenslabel = 'Tokens:'; - $tokensvalue = phutil_tag( - 'dd', - array( - 'class' => 'phui-card-list-value', - ), - array($token->renderIcon(), ' ')); - - $tokenskey = phutil_tag( - 'dt', - array( - 'class' => 'phui-card-list-key', - ), - array($tokenslabel, ' ')); - - $list[] = javelin_tag( - 'dl', - array( - 'sigil' => 'has-tooltip', - 'class' => 'token-icon', - 'meta' => array( - 'tip' => $handles[$token_given->getAuthorPHID()]->getName(), - ), - ), - array( - $aural, - $tokenskey, - $tokensvalue, - )); - } - return $list; - } -} diff --git a/src/util/SprintPoints.php b/src/util/SprintPoints.php index ea3c7a386c9ef8301fe4df903216e801598b990a..03bd351c4f8c5a1d0956fad902f53794793f42e1 100644 --- a/src/util/SprintPoints.php +++ b/src/util/SprintPoints.php @@ -2,31 +2,26 @@ final class SprintPoints extends Phobject { -private $taskpoints; private $task_open_status_sum; private $task_closed_status_sum; private $tasks; private $taskPrioritySum = array(); +private $viewer; - public function setTaskPoints ($taskpoints) { - $this->taskpoints = $taskpoints; + public function setTasks($tasks) { + $this->tasks = $tasks; return $this; } - public function setTasks ($tasks) { - $this->tasks = $tasks; + public function setViewer($viewer) { + $this->viewer = $viewer; return $this; } - public function getTaskPoints($task_phid) { + public function getTaskPoints($task) { $points = null; - $taskpoints = mpull($this->taskpoints, null, 'getObjectPHID'); - if (!empty($taskpoints)) { - foreach ($taskpoints as $key => $value) { - if ($key == $task_phid) { - $points = $value->getfieldValue(); - } - } + if (!empty($task)) { + $points = $task->getPoints(); if (!isset($points)) { $points = '0'; } @@ -34,12 +29,25 @@ private $taskPrioritySum = array(); return $points; } + public function getTaskPointsbyPHID($task_phid) { + $task = $this->getTaskforPHID($task_phid); + $points = $this->getTaskPoints($task); + return $points; + } + + public function getTaskforPHID($phid) { + $task = id(new ManiphestTaskQuery()) + ->setViewer($this->viewer) + ->withPHIDs(array($phid)) + ->executeOne(); + return $task; + } + public function sumTotalTaskPoints() { $points = null; - if (!empty($this->taskpoints)) { - $taskpoints = mpull($this->taskpoints, null, 'getObjectPHID'); - foreach ($taskpoints as $key => $value) { - $points += $value->getfieldValue(); + if (!empty($this->tasks)) { + foreach ($this->tasks as $task) { + $points += $task->getPoints(); } } if (!isset($points)) { @@ -50,8 +58,8 @@ private $taskPrioritySum = array(); public function sumTotalTasks() { $total_tasks = null; - if (!empty($this->taskpoints)) { - $total_tasks += count($this->taskpoints); + if (!empty($this->tasks)) { + $total_tasks += count($this->tasks); } return $total_tasks; } @@ -66,10 +74,10 @@ private $taskPrioritySum = array(); return $priority_name->getTaskPriorityName($task->getPriority()); } - private function sumPointsbyStatus ($task) { + private function sumPointsbyStatus($task) { $status = $this->getTaskStatus($task); - $points = $this->getTaskPoints($task->getPHID()); + $points = $this->getTaskPoints($task); if ($status == 'open') { $this->task_open_status_sum = @@ -81,9 +89,9 @@ private $taskPrioritySum = array(); return; } - private function sumPointsbyPriority ($task) { + private function sumPointsbyPriority($task) { $priority_name = $this->getPriorityName($task); - $points = $this->getTaskPoints($task->getPHID()); + $points = $this->getTaskPoints($task); if ($priority_name) { $this->taskPrioritySum = $this->setTaskPrioritySum($this->taskPrioritySum, $priority_name, @@ -92,7 +100,7 @@ private $taskPrioritySum = array(); return; } - private function setTaskPrioritySum ($task_priority_sum, $priority_name, + private function setTaskPrioritySum($task_priority_sum, $priority_name, $points) { if (empty($task_priority_sum)) { $task_priority_sum[$priority_name] = $points; @@ -106,24 +114,24 @@ private $taskPrioritySum = array(); return $task_priority_sum; } - private function setTaskOpenStatusSum ($task_open_status_sum, $points) { + private function setTaskOpenStatusSum($task_open_status_sum, $points) { $task_open_status_sum += $points; return $task_open_status_sum; } - private function setTaskClosedStatusSum ($task_closed_status_sum, $points) { + private function setTaskClosedStatusSum($task_closed_status_sum, $points) { $task_closed_status_sum += $points; return $task_closed_status_sum; } - private function setStatusPoints () { + private function setStatusPoints() { foreach ($this->tasks as $task) { $this->sumPointsbyStatus($task); } return $this; } - private function setPriorityPoints () { + private function setPriorityPoints() { foreach ($this->tasks as $task) { $this->sumPointsbyPriority($task); } @@ -134,7 +142,7 @@ private $taskPrioritySum = array(); $this->setStatusPoints(); $opensum = $this->getOpenStatusSum(); $closedsum = $this->getClosedStatusSum(); - return array ($opensum, $closedsum); + return array($opensum, $closedsum); } private function getOpenStatusSum() { diff --git a/src/view/SprintBoardTaskCard.php b/src/view/SprintBoardTaskCard.php deleted file mode 100644 index b64ff7e38dfc9db3fec4dfa1b5553c01da82df72..0000000000000000000000000000000000000000 --- a/src/view/SprintBoardTaskCard.php +++ /dev/null @@ -1,151 +0,0 @@ -<?php - -final class SprintBoardTaskCard extends Phobject { - - private $project; - private $viewer; - private $projectHandles; - private $task; - private $owner; - private $canEdit; - private $task_node_id; - private $points; - - public function setViewer(PhabricatorUser $viewer) { - $this->viewer = $viewer; - return $this; - } - - public function setProject ($project) { - $this->project = $project; - return $this; - } - - public function getProject() { - return $this->project; - } - - public function getViewer() { - return $this->viewer; - } - - public function setProjectHandles(array $handles) { - $this->projectHandles = $handles; - return $this; - } - - public function getProjectHandles() { - return $this->projectHandles; - } - - public function setTask(ManiphestTask $task) { - $this->task = $task; - return $this; - } - - public function setNode($task_node_id) { - $this->task_node_id = $task_node_id; - return $this; - } - - public function getTask() { - return $this->task; - } - - public function setOwner(PhabricatorObjectHandle $owner = null) { - $this->owner = $owner; - return $this; - } - public function getOwner() { - return $this->owner; - } - - public function setCanEdit($can_edit) { - $this->canEdit = $can_edit; - return $this; - } - - public function getCanEdit() { - return $this->canEdit; - } - - private function getCardAttributes() { - $pointslabel = 'Points:'; - $pointsvalue = phutil_tag( - 'dd', - array( - 'class' => 'phui-card-list-value', - ), - array($this->points, ' ')); - - $pointskey = phutil_tag( - 'dt', - array( - 'class' => 'phui-card-list-key', - ), - array($pointslabel, ' ')); - return phutil_tag( - 'dl', - array( - 'class' => 'phui-property-list-container', - ), - array( - $pointskey, - $pointsvalue, - )); - } - - public function getItem() { - - $query = id(new SprintQuery()) - ->setProject($this->project) - ->setViewer($this->viewer); - $task = $this->getTask(); - $owner = $this->getOwner(); - $task_phid = $task->getPHID(); - $can_edit = $this->getCanEdit(); - $viewer = $this->getViewer(); - $this->points = $query->getStoryPointsForTask($task_phid); - - $color_map = ManiphestTaskPriority::getColorMap(); - $bar_color = idx($color_map, $task->getPriority(), 'grey'); - - $card = id(new PHUIObjectItemView()) - ->setObject($task) - ->setUser($viewer) - ->setObjectName('T'.$task->getID()) - ->setHeader($task->getTitle()) - ->setGrippable($can_edit) - ->setHref('/T'.$task->getID()) - ->addSigil('project-card') - ->setDisabled($task->isClosed()) - ->setMetadata( - array( - 'objectPHID' => $task_phid, - 'taskNodeID' => $this->task_node_id, - 'points' => $this->points, - )) - ->addAction( - id(new PHUIListItemView()) - ->setName(pht('Edit')) - ->setIcon('fa-pencil') - ->addSigil('edit-project-card') - ->setHref('/project/sprint/board/task/edit/'.$task->getID() - .'/')) - ->setBarColor($bar_color); - - if ($owner) { - $card->addHandleIcon($owner, $owner->getName()); - } - $card->addAttribute($this->getCardAttributes()); - - $project_handles = $this->getProjectHandles(); - if ($project_handles) { - $tag_list = id(new PHUIHandleTagListView()) - ->setSlim(true) - ->setHandles($project_handles); - $card->addAttribute($tag_list); - } - return $card; - } -} diff --git a/src/view/SprintListTableView.php b/src/view/SprintListTableView.php index b3e250b5a8af057984999e23149d57c971b3489a..535abbc88ba42800a130d9dbb39c9f14d1e62820 100644 --- a/src/view/SprintListTableView.php +++ b/src/view/SprintListTableView.php @@ -4,12 +4,12 @@ final class SprintListTableView extends Phobject { private $tableData; - public function setTableData ($table_data) { + public function setTableData($table_data) { $this->tableData = $table_data; return $this; } - public function buildProjectsTable () { + public function buildProjectsTable() { $id = 'list-table'; Javelin::initBehavior('sprint-table', array( 'hardpoint' => $id, diff --git a/src/view/SprintTableView.php b/src/view/SprintTableView.php index e0733eccdc3c6b49ded3c05aeaf794083fcd67c8..45bb6f3fa56d93d9d142519ff44a7d61540c8cbd 100644 --- a/src/view/SprintTableView.php +++ b/src/view/SprintTableView.php @@ -239,7 +239,8 @@ final class SprintTableView extends AphrontView { $table_id = celerity_generate_unique_node_id(); } - $html = phutil_tag('table', array('class' => $table_class, + $html = phutil_tag('table', array( + 'class' => $table_class, 'id' => $table_id, ), $table); return phutil_tag_div('aphront-table-wrap', $html); diff --git a/src/view/SprintView.php b/src/view/SprintView.php index de20e5ae84c0efbb28d0355233680478f9a5361c..8f200e010182667c7ab6d87369ad85558cb806b3 100644 --- a/src/view/SprintView.php +++ b/src/view/SprintView.php @@ -68,7 +68,7 @@ abstract class SprintView extends AphrontView { $project_phid = $request->getStr('project'); if ($project_phid) { $phids = array($project_phid); - $handle = $this->getProjectHandle ($phids, $project_phid, $request); + $handle = $this->getProjectHandle($phids, $project_phid, $request); } $tokens = array(); if ($handle) { diff --git a/src/view/burndown/BoardDataPieView.php b/src/view/burndown/BoardDataPieView.php index a360057ebab0f72685dc82333651d853fa3cca3b..0da806306bf7554f2064dba07e9c620986dd00e5 100644 --- a/src/view/burndown/BoardDataPieView.php +++ b/src/view/burndown/BoardDataPieView.php @@ -1,10 +1,10 @@ <?php -final class BoardDataPieView extends Phobject{ +final class BoardDataPieView extends Phobject { private $boardData; - public function setBoardData ($board_data) { + public function setBoardData($board_data) { $this->boardData = $board_data; return $this; } @@ -86,7 +86,6 @@ final class BoardDataPieView extends Phobject{ private function initTaskStatusPie() { $sprintpoints = id(new SprintPoints()) - ->setTaskPoints($this->boardData->getTaskPoints()) ->setTasks($this->boardData->getTasks()); list($task_open_status_sum, $task_closed_status_sum) = $sprintpoints @@ -106,7 +105,6 @@ final class BoardDataPieView extends Phobject{ private function initTaskPriorityPie() { $sprintpoints = id(new SprintPoints()) - ->setTaskPoints($this->boardData->getTaskPoints()) ->setTasks($this->boardData->getTasks()); $task_priority_sum = $sprintpoints diff --git a/src/view/burndown/BoardDataTableView.php b/src/view/burndown/BoardDataTableView.php index b185f2c230054a575d1c17e5e2ea2f752d4eb2f8..d305691f734134c21717b9aba44dea340302ee15 100644 --- a/src/view/burndown/BoardDataTableView.php +++ b/src/view/burndown/BoardDataTableView.php @@ -1,10 +1,10 @@ <?php -final class BoardDataTableView extends Phobject{ +final class BoardDataTableView extends Phobject { private $boardData; - public function setBoardData ($board_data) { + public function setBoardData($board_data) { $this->boardData = $board_data; return $this; } diff --git a/src/view/burndown/BurndownChartView.php b/src/view/burndown/BurndownChartView.php index 9d4583ef0fc3e1cecbf9efa6992d7e9c89c82ed2..b9a22f3bd060b962e469082137a6c3698134023c 100644 --- a/src/view/burndown/BurndownChartView.php +++ b/src/view/burndown/BurndownChartView.php @@ -1,6 +1,6 @@ <?php -final class BurndownChartView extends Phobject{ +final class BurndownChartView extends Phobject { private $data; public function setChartData($chart_data) { diff --git a/src/view/burndown/EventTableView.php b/src/view/burndown/EventTableView.php index 2c036c0742572cfba8069b71af76d57406675c8d..620943de31b00cea5887468b1577770f25c50a48 100644 --- a/src/view/burndown/EventTableView.php +++ b/src/view/burndown/EventTableView.php @@ -1,33 +1,33 @@ <?php -final class EventTableView extends Phobject{ +final class EventTableView extends Phobject { private $project; private $viewer; private $request; private $events; private $tasks; - public function setProject ($project) { + public function setProject($project) { $this->project = $project; return $this; } - public function setViewer ($viewer) { + public function setViewer($viewer) { $this->viewer = $viewer; return $this; } - public function setEvents ($events) { + public function setEvents($events) { $this->events = $events; return $this; } - public function setTasks ($tasks) { + public function setTasks($tasks) { $this->tasks = $tasks; return $this; } - public function setRequest ($request) { + public function setRequest($request) { $this->request = $request; return $this; } @@ -71,7 +71,7 @@ final class EventTableView extends Phobject{ return $box; } - private function buildEventsTree ($start, $end) { + private function buildEventsTree($start, $end) { $rows = array(); foreach ($this->events as $event) { diff --git a/src/view/burndown/SprintDataView.php b/src/view/burndown/SprintDataView.php index a297babd893481a0b9b5e48448afb33669df3044..4b4b06d0d2b41dd26f7970ec62aab48532e3a94d 100644 --- a/src/view/burndown/SprintDataView.php +++ b/src/view/burndown/SprintDataView.php @@ -57,7 +57,6 @@ final class SprintDataView extends SprintView { ->setRequest($this->request) ->setTasks($this->tasks) ->setTimezone($this->timezone) - ->setTaskPoints($this->taskpoints) ->setStats($stats) ->setQuery($query) ->setTimeSeries($this->timeseries) @@ -97,7 +96,6 @@ final class SprintDataView extends SprintView { ->setViewer($this->viewer) ->setRequest($this->request) ->setTasks($this->tasks) - ->setTaskPoints($this->taskpoints) ->setQuery($query) ->execute(); $tasks_table_view = id(new TasksTableView()) @@ -122,7 +120,11 @@ final class SprintDataView extends SprintView { $event_table = null; } - return array($board_chart, $board_table, $pies, $tasks_table, + return array( + $board_chart, + $board_table, + $pies, + $tasks_table, $event_table, ); } diff --git a/src/view/burndown/TasksTableView.php b/src/view/burndown/TasksTableView.php index ba35d7a76b7593db8a77557b51892d776d973d05..3057ce762dd1754b16fa92de89086a08cea566d1 100644 --- a/src/view/burndown/TasksTableView.php +++ b/src/view/burndown/TasksTableView.php @@ -1,11 +1,11 @@ <?php -final class TasksTableView extends Phobject{ +final class TasksTableView extends Phobject { private $tableData; - public function setTableData ($table_data) { + public function setTableData($table_data) { $this->tableData = $table_data; return $this; } diff --git a/src/view/reports/ProjectOpenTasksView.php b/src/view/reports/ProjectOpenTasksView.php index fcd6a245161418741d4661fde5d994792c2473a3..02fd2d0024185a848123917d476e5f37fafe2748 100644 --- a/src/view/reports/ProjectOpenTasksView.php +++ b/src/view/reports/ProjectOpenTasksView.php @@ -1,4 +1,5 @@ <?php + final class ProjectOpenTasksView extends OpenTasksView { /** @@ -36,8 +37,15 @@ final class ProjectOpenTasksView extends OpenTasksView { $col_header = pht('Project'); $header = pht('Open Tasks by Project and Priority (%s)', $date); - return array ($leftover, $base_link, $leftover_name, $col_header, $header, - $result_closed, $leftover_closed, $result, + return array( + $leftover, + $base_link, + $leftover_name, + $col_header, + $header, + $result_closed, + $leftover_closed, + $result, ); } diff --git a/src/view/reports/SprintHistoryTableView.php b/src/view/reports/SprintHistoryTableView.php index 06908873d931119386e760a07714e13cf079a229..a8565dd5c3c635cf8410eca3fde6af2fa50366b7 100644 --- a/src/view/reports/SprintHistoryTableView.php +++ b/src/view/reports/SprintHistoryTableView.php @@ -6,12 +6,12 @@ final class SprintHistoryTableView extends SprintView { private $tableData; protected $viewer; - public function setViewer (PhabricatorUser $viewer) { + public function setViewer(PhabricatorUser $viewer) { $this->user = $viewer; return $this; } - public function setRequest ($request) { + public function setRequest($request) { $this->request = $request; return $this; } @@ -28,12 +28,12 @@ final class SprintHistoryTableView extends SprintView { return array($filter, $table); } - public function setTableData ($table_data) { + public function setTableData($table_data) { $this->tableData = $table_data; return $this; } - public function buildProjectsTable () { + public function buildProjectsTable() { if ($this->tableData) { $id = 'history-table'; Javelin::initBehavior('sprint-history-table', array( diff --git a/src/view/reports/SprintReportBurnUpView.php b/src/view/reports/SprintReportBurnUpView.php index 2dd511d40042362d134074056f0514371b719b30..56f464af8fc0e2974349cfebaa8ce82675d5b8ca 100644 --- a/src/view/reports/SprintReportBurnUpView.php +++ b/src/view/reports/SprintReportBurnUpView.php @@ -4,12 +4,12 @@ final class SprintReportBurnUpView extends SprintView { private $request; - public function setUser (PhabricatorUser $viewer) { + public function setUser(PhabricatorUser $viewer) { $this->user = $viewer; return $this; } - public function setRequest ($request) { + public function setRequest($request) { $this->request = $request; return $this; } @@ -35,7 +35,7 @@ final class SprintReportBurnUpView extends SprintView { return $data; } - private function addTaskStatustoData ($data) { + private function addTaskStatustoData($data) { foreach ($data as $key => $row) { // NOTE: Hack to avoid json_decode(). @@ -65,9 +65,9 @@ final class SprintReportBurnUpView extends SprintView { return $data; } - private function buildStatsfromEvents ($data) { + private function buildStatsfromEvents($data) { $stats = array(); - $data = $this->addTaskStatustoData ($data); + $data = $this->addTaskStatustoData($data); foreach ($data as $key => $row) { @@ -88,7 +88,7 @@ final class SprintReportBurnUpView extends SprintView { return $stats; } - private function buildDayBucketsfromEvents ($data) { + private function buildDayBucketsfromEvents($data) { $day_buckets = array(); foreach ($data as $key => $row) { @@ -113,7 +113,7 @@ final class SprintReportBurnUpView extends SprintView { } - private function formatBucketRows ($stats, $day_buckets) { + private function formatBucketRows($stats, $day_buckets) { $template = array( 'open' => 0, 'close' => 0, @@ -172,10 +172,10 @@ final class SprintReportBurnUpView extends SprintView { $period['open'] += $info['open']; $period['close'] += $info['close']; } - return array ($rows, $rowc, $week, $month, $period); + return array($rows, $rowc, $week, $month, $period); } - private function renderCaption ($handle) { + private function renderCaption($handle) { $inst = pht( 'NOTE: This table reflects tasks currently in '. 'the project. If a task was opened in the past but added to '. @@ -185,7 +185,7 @@ final class SprintReportBurnUpView extends SprintView { 'counted at all.'); $header = pht('Task Burn Rate for Project %s', $handle->renderLink()); $caption = phutil_tag('p', array(), $inst); - return array ($caption, $header); + return array($caption, $header); } private function formatStatsTableHeaders($week, $month, $period, $rows, @@ -211,7 +211,7 @@ final class SprintReportBurnUpView extends SprintView { $rows = array_reverse($rows); $rowc = array_reverse($rowc); - return array ($rows, $rowc); + return array($rows, $rowc); } private function buildStatsTable() { @@ -220,7 +220,7 @@ final class SprintReportBurnUpView extends SprintView { if ($project_phid) { $phids = array($project_phid); - $handle = $this->getProjectHandle ($phids, $project_phid, $this->request); + $handle = $this->getProjectHandle($phids, $project_phid, $this->request); } $data = $this->getXactionData($project_phid); @@ -228,15 +228,15 @@ final class SprintReportBurnUpView extends SprintView { $stats = $this->buildStatsfromEvents($data); $day_buckets = $this->buildDayBucketsfromEvents($data); - list ($rows, $rowc, $week, $month, $period) = + list($rows, $rowc, $week, $month, $period) = $this->formatBucketRows($stats, $day_buckets); - list ($rows, $rowc) = $this->formatStatsTableHeaders($week, $month, $period, + list($rows, $rowc) = $this->formatStatsTableHeaders($week, $month, $period, $rows, $rowc); $table = $this->statsTableView($rows, $rowc); if ($handle) { - list ($caption, $header) = $this->renderCaption ($handle); + list($caption, $header) = $this->renderCaption($handle); $caption = id(new PHUIInfoView()) ->appendChild($caption) ->setSeverity(PHUIInfoView::SEVERITY_NOTICE); @@ -311,11 +311,12 @@ final class SprintReportBurnUpView extends SprintView { } private function buildSeries(array $data) { - $output = array(array( + $output = array( + array( pht('Dates'), pht('Tasks'), ),); - $tdata = $this->addTaskStatustoData ($data); + $tdata = $this->addTaskStatustoData($data); $counter = 0; foreach ($tdata as $key => $row) { $t = (int)$row['dateCreated'] * 1000; @@ -325,7 +326,8 @@ final class SprintReportBurnUpView extends SprintView { ++$counter; } $output[] = array( - $t, $counter, + $t, + $counter, ); } diff --git a/src/view/reports/SprintReportOpenTasksView.php b/src/view/reports/SprintReportOpenTasksView.php index 6524203775d76d6d9cd3e3b889bda28b7f44d80a..421a35e50d684dded18ecd504872644c1e205424 100644 --- a/src/view/reports/SprintReportOpenTasksView.php +++ b/src/view/reports/SprintReportOpenTasksView.php @@ -6,17 +6,17 @@ final class SprintReportOpenTasksView extends SprintView { private $request; private $view; - public function setUser (PhabricatorUser $viewer) { + public function setUser(PhabricatorUser $viewer) { $this->user = $viewer; return $this; } - public function setRequest ($request) { + public function setRequest($request) { $this->request = $request; return $this; } - public function setView ($view) { + public function setView($view) { $this->view = $view; return $this; } @@ -57,11 +57,11 @@ final class SprintReportOpenTasksView extends SprintView { if (($this->view) == 'user') { list($leftover, $leftover_closed, $base_link, $leftover_name, - $col_header, $header, $result_closed, $result ) = + $col_header, $header, $result_closed, $result) = ($viewer_task_view->execute($tasks, $recently_closed, $date)); } else if (($this->view) == 'project') { list($leftover, $base_link, $leftover_name, $col_header, $header, - $result_closed, $leftover_closed, $result ) = + $result_closed, $leftover_closed, $result) = ($project_task_view->execute($tasks, $recently_closed, $date)); } else { $result = array(); @@ -84,7 +84,7 @@ final class SprintReportOpenTasksView extends SprintView { $base_link, $leftover, $leftover_name, $leftover_closed, $order, $reverse); - list ($cname, $cclass) = $this->buildTableColumns($col_header); + list($cname, $cclass) = $this->buildTableColumns($col_header); $table = $this->buildOpenTasksTable($rows, $cname, $cclass, $order, $reverse); $panel = new PHUIObjectBoxView(); @@ -104,7 +104,7 @@ final class SprintReportOpenTasksView extends SprintView { /** * @param integer $total */ - private function setSortOrder ($row, $order, $total, $oldest_all, $oldest_pri, + private function setSortOrder($row, $order, $total, $oldest_all, $oldest_pri, $closed, $handle) { switch ($order) { case 'total': @@ -133,7 +133,7 @@ final class SprintReportOpenTasksView extends SprintView { * @param string $order * @param integer $reverse */ - private function buildRowsfromResult ($project_handle, $result, + private function buildRowsfromResult($project_handle, $result, $result_closed, $base_link, $leftover, $leftover_name, $leftover_closed, $order, $reverse) { @@ -144,15 +144,15 @@ final class SprintReportOpenTasksView extends SprintView { $rows = array(); foreach ($handles as $handle) { - list ($tasks, $name, $closed) = $this->setTaskArrays($handle, + list($tasks, $name, $closed) = $this->setTaskArrays($handle, $project_handle, $result, $result_closed, $base_link, $leftover, $leftover_name, $leftover_closed); $taskv = $tasks; $tasks = mgroup($tasks, 'getPriority'); - list ($row, $total) = $this->getPriorityMap($name, $tasks); - list ($row, $oldest_all, $oldest_pri ) = $this->renderTaskLinks($taskv, + list($row, $total) = $this->getPriorityMap($name, $tasks); + list($row, $oldest_all, $oldest_pri) = $this->renderTaskLinks($taskv, $closed, $row); $row['sort'] = $this->setSortOrder($row, $order, $total, $oldest_all, @@ -172,7 +172,7 @@ final class SprintReportOpenTasksView extends SprintView { return $rows; } - private function renderTaskLinks ($taskv, $closed, $row) { + private function renderTaskLinks($taskv, $closed, $row) { list($link, $oldest_all) = $this->renderOldest($taskv); $row[] = $link; @@ -201,10 +201,10 @@ final class SprintReportOpenTasksView extends SprintView { } else { $row[] = '-'; } - return array ($row, $oldest_all, $oldest_pri); + return array($row, $oldest_all, $oldest_pri); } - private function getPriorityMap ($name, $tasks) { + private function getPriorityMap($name, $tasks) { $row = array(); $row[] = $name; $total = 0; @@ -218,7 +218,7 @@ final class SprintReportOpenTasksView extends SprintView { $total += $n; } $row[] = number_format($total); - return array ($row, $total); + return array($row, $total); } private function setTaskArrays($handle, $project_handle, $result, @@ -246,7 +246,7 @@ final class SprintReportOpenTasksView extends SprintView { $name = $leftover_name; $closed = $leftover_closed; } - return array ($tasks, $name, $closed); + return array($tasks, $name, $closed); } /** @@ -299,7 +299,7 @@ final class SprintReportOpenTasksView extends SprintView { ), pht('Recently Closed')); $cclass[] = 'center narrow'; - return array ($cname, $cclass); + return array($cname, $cclass); } /** diff --git a/src/view/reports/UserOpenTasksView.php b/src/view/reports/UserOpenTasksView.php index b065d5c1460fb040695e76bdcfd3c305863eeba9..f1fdac11a69e79d3b124512db33bbc096a8327eb 100644 --- a/src/view/reports/UserOpenTasksView.php +++ b/src/view/reports/UserOpenTasksView.php @@ -1,4 +1,5 @@ <?php + final class UserOpenTasksView extends OpenTasksView { /** @@ -17,6 +18,6 @@ final class UserOpenTasksView extends OpenTasksView { $leftover_name = phutil_tag('em', array(), pht('(Up For Grabs)')); $col_header = pht('User'); $header = pht('Open Tasks by User and Priority (%s)', $date); - return array ( $leftover, $leftover_closed, $base_link, $leftover_name, $col_header, $header, $result_closed, $result ); + return array($leftover, $leftover_closed, $base_link, $leftover_name, $col_header, $header, $result_closed, $result); } }