1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-28 16:30:59 +01:00

Simplify Project status field

Summary:
This was a sort of speculative feature added by a contributor some time ago and
just serves as a label; for now, simplify it into "active" and "archived" and
remove "archived" projects from the "active" list.

  - Fix a bug where we'd publish a "renamed from X to X" transaction that had no
effect.
  - Publish stories about status changes.
  - Remove the "edit affiliation" controller, which has no links in the UI
(effectively replaced by join/leave links).
  - Add query/conduit support.

Test Plan: Edited the status of several projects.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran, epriestley

Maniphest Tasks: T681

Differential Revision: https://secure.phabricator.com/D1573
This commit is contained in:
epriestley 2012-02-07 14:59:38 -08:00
parent a5f8846f47
commit 4caa684724
19 changed files with 135 additions and 158 deletions

View file

@ -0,0 +1 @@
UPDATE phabricator_project.project SET status = IF(status = 5, 100, 0);

View file

@ -627,7 +627,6 @@ phutil_register_library_map(array(
'PhabricatorProfileHeaderView' => 'view/layout/profileheader',
'PhabricatorProject' => 'applications/project/storage/project',
'PhabricatorProjectAffiliation' => 'applications/project/storage/affiliation',
'PhabricatorProjectAffiliationEditController' => 'applications/project/controller/editaffiliation',
'PhabricatorProjectConstants' => 'applications/project/constants/base',
'PhabricatorProjectController' => 'applications/project/controller/base',
'PhabricatorProjectCreateController' => 'applications/project/controller/create',
@ -1332,7 +1331,6 @@ phutil_register_library_map(array(
'PhabricatorProfileHeaderView' => 'AphrontView',
'PhabricatorProject' => 'PhabricatorProjectDAO',
'PhabricatorProjectAffiliation' => 'PhabricatorProjectDAO',
'PhabricatorProjectAffiliationEditController' => 'PhabricatorProjectController',
'PhabricatorProjectController' => 'PhabricatorController',
'PhabricatorProjectCreateController' => 'PhabricatorProjectController',
'PhabricatorProjectDAO' => 'PhabricatorLiskDAO',

View file

@ -206,8 +206,6 @@ class AphrontDefaultApplicationConfiguration
'edit/(?P<id>\d+)/$' => 'PhabricatorProjectProfileEditController',
'view/(?P<id>\d+)/(?:(?P<page>\w+)/)?$'
=> 'PhabricatorProjectProfileController',
'affiliation/(?P<id>\d+)/$'
=> 'PhabricatorProjectAffiliationEditController',
'create/$' => 'PhabricatorProjectCreateController',
'update/(?P<id>\d+)/(?P<action>[^/]+)/$'
=> 'PhabricatorProjectUpdateController',

View file

@ -26,9 +26,19 @@ final class ConduitAPI_project_query_Method extends ConduitAPI_project_Method {
}
public function defineParamTypes() {
$statuses = array(
PhabricatorProjectQuery::STATUS_ANY,
PhabricatorProjectQuery::STATUS_OPEN,
PhabricatorProjectQuery::STATUS_CLOSED,
PhabricatorProjectQuery::STATUS_ACTIVE,
PhabricatorProjectQuery::STATUS_ARCHIVED,
);
return array(
'ids' => 'optional list<int>',
'phids' => 'optional list<phid>',
'status' => 'optional enum<'.implode(', ', $statuses).'>',
'members' => 'optional list<phid>',
@ -55,6 +65,11 @@ final class ConduitAPI_project_query_Method extends ConduitAPI_project_Method {
$query->withIDs($ids);
}
$status = $request->getValue('status');
if ($status) {
$query->withStatus($status);
}
$phids = $request->getValue('phids');
if ($phids) {
$query->withPHIDs($phids);

View file

@ -106,6 +106,10 @@ abstract class PhabricatorFeedStory {
phutil_escape_html($handle->getLinkName()));
}
final protected function renderString($str) {
return '<strong>'.phutil_escape_html($str).'</strong>';
}
final protected function renderSummary($text, $len = 128) {
if ($len) {
$text = phutil_utf8_shorten($text, $len);

View file

@ -49,16 +49,29 @@ class PhabricatorFeedStoryProject extends PhabricatorFeedStory {
$action = 'renamed project '.
$this->linkTo($proj_phid).
' from '.
'<strong>'.phutil_escape_html($old).'</strong>'.
$this->renderString($old).
' to '.
'<strong>'.phutil_escape_html($new).'</strong>.';
$this->renderString($new).
'.';
} else {
$action = 'created project '.
$this->linkTo($proj_phid).
' (as '.
'<strong>'.phutil_escape_html($new).'</strong>).';
$this->renderString($new).
').';
}
break;
case PhabricatorProjectTransactionType::TYPE_STATUS:
$action = 'changed project '.
$this->linkTo($proj_phid).
' status from '.
$this->renderString(
PhabricatorProjectStatus::getNameForStatus($old)).
' to '.
$this->renderString(
PhabricatorProjectStatus::getNameForStatus($new)).
'.';
break;
case PhabricatorProjectTransactionType::TYPE_MEMBERS:
$add = array_diff($new, $old);
$rem = array_diff($old, $new);

View file

@ -8,9 +8,9 @@
phutil_require_module('phabricator', 'applications/feed/story/base');
phutil_require_module('phabricator', 'applications/feed/view/story');
phutil_require_module('phabricator', 'applications/project/constants/status');
phutil_require_module('phabricator', 'applications/project/constants/transaction');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils');

View file

@ -1,7 +1,7 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,41 +18,23 @@
final class PhabricatorProjectStatus {
const UNKNOWN = 0;
const NOT_STARTED = 1;
const IN_PROGRESS = 2;
const REVIEW_PROCESS = 3;
const RELEASED = 4;
const COMPLETED = 5;
const DEFERRED = 6;
const ONGOING = 7;
const STATUS_ACTIVE = 0;
const STATUS_ARCHIVED = 100;
public static function getNameForStatus($status) {
static $map = array(
self::UNKNOWN => '',
self::NOT_STARTED => 'Not started',
self::IN_PROGRESS => 'In progress',
self::ONGOING => 'Ongoing',
self::REVIEW_PROCESS => 'Review process',
self::RELEASED => 'Released',
self::COMPLETED => 'Completed',
self::DEFERRED => 'Deferred',
self::STATUS_ACTIVE => 'Active',
self::STATUS_ARCHIVED => 'Archived',
);
return idx($map, coalesce($status, '?'), $map[self::UNKNOWN]);
return idx($map, coalesce($status, '?'), 'Unknown');
}
public static function getStatusMap() {
return array(
self::UNKNOWN => 'Who knows?',
self::NOT_STARTED => 'Not started',
self::IN_PROGRESS => 'In progress',
self::ONGOING => 'Ongoing',
self::REVIEW_PROCESS => 'Review process',
self::RELEASED => 'Released',
self::COMPLETED => 'Completed',
self::DEFERRED => 'Deferred',
self::STATUS_ACTIVE => 'Active',
self::STATUS_ARCHIVED => 'Archived',
);
}
}

View file

@ -21,5 +21,6 @@ final class PhabricatorProjectTransactionType
const TYPE_NAME = 'name';
const TYPE_MEMBERS = 'members';
const TYPE_STATUS = 'status';
}

View file

@ -49,8 +49,6 @@ class PhabricatorProjectCreateController
$errors[] = $ex->getMessage();
}
$project->setStatus(PhabricatorProjectStatus::ONGOING);
$profile->setBlurb($request->getStr('blurb'));
if (!$errors) {

View file

@ -1,95 +0,0 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class PhabricatorProjectAffiliationEditController
extends PhabricatorProjectController {
private $id;
public function willProcessRequest(array $data) {
$this->id = $data['id'];
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$project = id(new PhabricatorProject())->load($this->id);
if (!$project) {
return new Aphront404Response();
}
$affiliation = id(new PhabricatorProjectAffiliation())->loadOneWhere(
'projectPHID = %s AND userPHID = %s',
$project->getPHID(),
$user->getPHID());
if (!$affiliation) {
$affiliation = new PhabricatorProjectAffiliation();
$affiliation->setUserPHID($user->getPHID());
$affiliation->setProjectPHID($project->getPHID());
}
if ($request->isFormPost()) {
$affiliation->setRole($request->getStr('role'));
if (!strlen($affiliation->getRole())) {
if ($affiliation->getID()) {
if ($affiliation->getIsOwner()) {
$affiliation->setRole('Owner');
$affiliation->save();
} else {
$affiliation->delete();
}
}
} else {
$affiliation->save();
}
return id(new AphrontRedirectResponse())
->setURI('/project/view/'.$project->getID().'/');
}
$form = new AphrontFormView();
$form
->setUser($user)
->setAction('/project/affiliation/'.$project->getID().'/')
->appendChild(
id(new AphrontFormTextControl())
->setLabel('Role')
->setName('role')
->setValue($affiliation->getRole()))
->appendChild(
id(new AphrontFormSubmitControl())
->addCancelButton('/project/view/'.$project->getID().'/')
->setValue('Save'));
$panel = new AphrontPanelView();
$panel->setHeader('Edit Project Affiliation');
$panel->setWidth(AphrontPanelView::WIDTH_FORM);
$panel->appendChild($form);
return $this->buildStandardPageResponse(
$panel,
array(
'title' => 'Edit Project Affiliation',
));
}
}

View file

@ -1,22 +0,0 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'aphront/response/404');
phutil_require_module('phabricator', 'aphront/response/redirect');
phutil_require_module('phabricator', 'applications/project/controller/base');
phutil_require_module('phabricator', 'applications/project/storage/affiliation');
phutil_require_module('phabricator', 'applications/project/storage/project');
phutil_require_module('phabricator', 'view/form/base');
phutil_require_module('phabricator', 'view/form/control/submit');
phutil_require_module('phabricator', 'view/form/control/text');
phutil_require_module('phabricator', 'view/layout/panel');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorProjectAffiliationEditController.php');

View file

@ -50,17 +50,22 @@ class PhabricatorProjectListController
$view_phid = $request->getUser()->getPHID();
$status_filter = PhabricatorProjectQuery::STATUS_ANY;
switch ($this->filter) {
case 'active':
$table_header = 'Active Projects';
$query->setMembers(array($view_phid));
$query->withStatus(PhabricatorProjectQuery::STATUS_ACTIVE);
break;
case 'owned':
$table_header = 'Owned Projects';
$query->setOwners(array($view_phid));
$query->withStatus($status_filter);
break;
case 'all':
$table_header = 'All Projects';
$query->withStatus($status_filter);
break;
}
@ -128,6 +133,8 @@ class PhabricatorProjectListController
'href' => '/project/view/'.$project->getID().'/',
),
phutil_escape_html($project->getName())),
phutil_escape_html(
PhabricatorProjectStatus::getNameForStatus($project->getStatus())),
phutil_escape_html($blurb),
phutil_escape_html($population),
phutil_render_tag(
@ -143,6 +150,7 @@ class PhabricatorProjectListController
$table->setHeaders(
array(
'Project',
'Status',
'Description',
'Population',
'Open Tasks',
@ -150,6 +158,7 @@ class PhabricatorProjectListController
$table->setColumnClasses(
array(
'pri',
'',
'wide',
'',
''

View file

@ -7,6 +7,7 @@
phutil_require_module('phabricator', 'applications/maniphest/query');
phutil_require_module('phabricator', 'applications/project/constants/status');
phutil_require_module('phabricator', 'applications/project/controller/base');
phutil_require_module('phabricator', 'applications/project/query/project');
phutil_require_module('phabricator', 'applications/project/storage/affiliation');

View file

@ -65,6 +65,12 @@ class PhabricatorProjectProfileEditController
$xaction->setNewValue($request->getStr('name'));
$xactions[] = $xaction;
$xaction = new PhabricatorProjectTransaction();
$xaction->setTransactionType(
PhabricatorProjectTransactionType::TYPE_STATUS);
$xaction->setNewValue($request->getStr('status'));
$xactions[] = $xaction;
$editor = new PhabricatorProjectEditor($project);
$editor->setUser($user);
$editor->applyTransactions($xactions);
@ -73,7 +79,6 @@ class PhabricatorProjectProfileEditController
$errors[] = $ex->getMessage();
}
$project->setStatus($request->getStr('status'));
$project->setSubprojectPHIDs($request->getArr('set_subprojects'));
$profile->setBlurb($request->getStr('blurb'));

View file

@ -48,12 +48,21 @@ final class PhabricatorProjectEditor {
$project->setAuthorPHID($user->getPHID());
}
foreach ($transactions as $xaction) {
foreach ($transactions as $key => $xaction) {
$type = $xaction->getTransactionType();
$this->setTransactionOldValue($project, $xaction);
$this->applyTransactionEffect($project, $xaction);
if (!$this->transactionHasEffect($xaction)) {
unset($transactions[$key]);
continue;
}
$this->applyTransactionEffect($project, $xaction);
}
if (!$transactions) {
return $this;
}
try {
@ -128,6 +137,9 @@ final class PhabricatorProjectEditor {
case PhabricatorProjectTransactionType::TYPE_NAME:
$xaction->setOldValue($project->getName());
break;
case PhabricatorProjectTransactionType::TYPE_STATUS:
$xaction->setOldValue($project->getStatus());
break;
case PhabricatorProjectTransactionType::TYPE_MEMBERS:
$affils = $project->loadAffiliations();
$project->attachAffiliations($affils);
@ -158,6 +170,9 @@ final class PhabricatorProjectEditor {
$project->setPhrictionSlug($xaction->getNewValue());
$this->validateName($project);
break;
case PhabricatorProjectTransactionType::TYPE_STATUS:
$project->setStatus($xaction->getNewValue());
break;
case PhabricatorProjectTransactionType::TYPE_MEMBERS:
$old = array_fill_keys($xaction->getOldValue(), true);
$new = array_fill_keys($xaction->getNewValue(), true);
@ -213,4 +228,9 @@ final class PhabricatorProjectEditor {
->publish();
}
private function transactionHasEffect(
PhabricatorProjectTransaction $xaction) {
return ($xaction->getOldValue() !== $xaction->getNewValue());
}
}

View file

@ -23,6 +23,13 @@ final class PhabricatorProjectQuery {
private $owners;
private $members;
private $status = 'status-any';
const STATUS_ANY = 'status-any';
const STATUS_OPEN = 'status-open';
const STATUS_CLOSED = 'status-closed';
const STATUS_ACTIVE = 'status-active';
const STATUS_ARCHIVED = 'status-archived';
private $limit;
private $offset;
@ -38,6 +45,11 @@ final class PhabricatorProjectQuery {
return $this;
}
public function withStatus($status) {
$this->status = $status;
return $this;
}
public function setLimit($limit) {
$this->limit = $limit;
return $this;
@ -113,6 +125,42 @@ final class PhabricatorProjectQuery {
private function buildWhereClause($conn_r) {
$where = array();
if ($this->status != self::STATUS_ANY) {
switch ($this->status) {
case self::STATUS_OPEN:
$where[] = qsprintf(
$conn_r,
'status IN (%Ld)',
array(
PhabricatorProjectStatus::STATUS_ACTIVE,
));
break;
case self::STATUS_CLOSED:
$where[] = qsprintf(
$conn_r,
'status IN (%Ld)',
array(
PhabricatorProjectStatus::STATUS_ARCHIVED,
));
break;
case self::STATUS_ACTIVE:
$where[] = qsprintf(
$conn_r,
'status = %d',
PhabricatorProjectStatus::STATUS_ACTIVE);
break;
case self::STATUS_ARCHIVED:
$where[] = qsprintf(
$conn_r,
'status = %d',
PhabricatorProjectStatus::STATUS_ARCHIVED);
break;
default:
throw new Exception(
"Unknown project status '{$this->status}'!");
}
}
if ($this->ids) {
$where[] = qsprintf(
$conn_r,

View file

@ -6,6 +6,7 @@
phutil_require_module('phabricator', 'applications/project/constants/status');
phutil_require_module('phabricator', 'applications/project/storage/affiliation');
phutil_require_module('phabricator', 'applications/project/storage/project');
phutil_require_module('phabricator', 'storage/qsprintf');

View file

@ -20,7 +20,7 @@ class PhabricatorProject extends PhabricatorProjectDAO {
protected $name;
protected $phid;
protected $status = PhabricatorProjectStatus::UNKNOWN;
protected $status = PhabricatorProjectStatus::STATUS_ACTIVE;
protected $authorPHID;
protected $subprojectPHIDs = array();
protected $phrictionSlug;