Page MenuHomestyx hydra

No OneTemporary

diff --git a/resources/sql/autopatches/20161212.dashboardpanel.01.author.sql b/resources/sql/autopatches/20161212.dashboardpanel.01.author.sql
new file mode 100644
index 0000000000..00c52d19cb
--- /dev/null
+++ b/resources/sql/autopatches/20161212.dashboardpanel.01.author.sql
@@ -0,0 +1,2 @@
+ALTER TABLE {$NAMESPACE}_dashboard.dashboard_panel
+ ADD authorPHID VARBINARY(64) NOT NULL;
diff --git a/resources/sql/autopatches/20161212.dashboardpanel.02.author.php b/resources/sql/autopatches/20161212.dashboardpanel.02.author.php
new file mode 100644
index 0000000000..bc87aef91c
--- /dev/null
+++ b/resources/sql/autopatches/20161212.dashboardpanel.02.author.php
@@ -0,0 +1,39 @@
+<?php
+
+// Set authorPHID on Dashboard Panels
+//
+$table = new PhabricatorDashboardPanel();
+$conn_w = $table->establishConnection('w');
+
+$txn_table = new PhabricatorDashboardPanelTransaction();
+$txn_conn = $table->establishConnection('r');
+
+echo pht("Building Dashboard Panel authorPHIDs...\n");
+
+foreach (new LiskMigrationIterator($table) as $panel) {
+
+ if ($panel->getAuthorPHID()) {
+ continue;
+ }
+
+ $panel_row = queryfx_one(
+ $txn_conn,
+ 'SELECT authorPHID FROM %T WHERE objectPHID = %s ORDER BY id ASC LIMIT 1',
+ $txn_table->getTableName(),
+ $panel->getPHID());
+
+ if (!$panel_row) {
+ $author_phid = id(new PhabricatorDashboardApplication())->getPHID();
+ } else {
+ $author_phid = $panel_row['authorPHID'];
+ }
+
+ queryfx(
+ $conn_w,
+ 'UPDATE %T SET authorPHID = %s WHERE id = %d',
+ $table->getTableName(),
+ $author_phid,
+ $panel->getID());
+}
+
+echo pht("Done\n");
diff --git a/src/applications/dashboard/controller/PhabricatorDashboardPanelEditController.php b/src/applications/dashboard/controller/PhabricatorDashboardPanelEditController.php
index b85498c13c..787d1c63ee 100644
--- a/src/applications/dashboard/controller/PhabricatorDashboardPanelEditController.php
+++ b/src/applications/dashboard/controller/PhabricatorDashboardPanelEditController.php
@@ -1,443 +1,443 @@
<?php
final class PhabricatorDashboardPanelEditController
extends PhabricatorDashboardController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
// If the user is trying to create a panel directly on a dashboard, make
// sure they have permission to see and edit the dashboard.
$dashboard_id = $request->getInt('dashboardID');
$dashboard = null;
if ($dashboard_id) {
$dashboard = id(new PhabricatorDashboardQuery())
->setViewer($viewer)
->withIDs(array($dashboard_id))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$dashboard) {
return new Aphront404Response();
}
$manage_uri = $this->getApplicationURI('manage/'.$dashboard_id.'/');
}
if ($id) {
$is_create = false;
if ($dashboard) {
$capabilities = array(
PhabricatorPolicyCapability::CAN_VIEW,
);
} else {
$capabilities = array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
$panel = id(new PhabricatorDashboardPanelQuery())
->setViewer($viewer)
->withIDs(array($id))
->requireCapabilities($capabilities)
->executeOne();
if (!$panel) {
return new Aphront404Response();
}
if ($dashboard) {
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$panel,
PhabricatorPolicyCapability::CAN_EDIT);
if (!$can_edit) {
if ($request->isFormPost() && $request->getBool('copy')) {
$panel = $this->copyPanel(
$request,
$dashboard,
$panel);
} else {
return $this->processPanelCloneRequest(
$request,
$dashboard,
$panel);
}
}
}
} else {
$is_create = true;
$panel = PhabricatorDashboardPanel::initializeNewPanel($viewer);
$types = PhabricatorDashboardPanelType::getAllPanelTypes();
$type = $request->getStr('type');
if (empty($types[$type])) {
return $this->processPanelTypeRequest($request);
}
$panel->setPanelType($type);
}
if ($is_create) {
$title = pht('Create New Panel');
$button = pht('Create Panel');
$header_icon = 'fa-plus-square';
if ($dashboard) {
$cancel_uri = $manage_uri;
} else {
$cancel_uri = $this->getApplicationURI('panel/');
}
} else {
$title = pht('Edit Panel: %s', $panel->getName());
$button = pht('Save Panel');
$header_icon = 'fa-pencil';
if ($dashboard) {
$cancel_uri = $manage_uri;
} else {
$cancel_uri = '/'.$panel->getMonogram();
}
}
$v_name = $panel->getName();
$e_name = true;
$field_list = PhabricatorCustomField::getObjectFields(
$panel,
PhabricatorCustomField::ROLE_EDIT);
$field_list
->setViewer($viewer)
->readFieldsFromStorage($panel);
if ($is_create && !$request->isFormPost()) {
$panel->requireImplementation()->initializeFieldsFromRequest(
$panel,
$field_list,
$request);
}
$validation_exception = null;
// NOTE: We require 'edit' to distinguish between the "Choose a Type"
// and "Create a Panel" dialogs.
if ($request->isFormPost() && $request->getBool('edit')) {
$v_name = $request->getStr('name');
$v_view_policy = $request->getStr('viewPolicy');
$v_edit_policy = $request->getStr('editPolicy');
$type_name = PhabricatorDashboardPanelTransaction::TYPE_NAME;
$type_view_policy = PhabricatorTransactions::TYPE_VIEW_POLICY;
$type_edit_policy = PhabricatorTransactions::TYPE_EDIT_POLICY;
$xactions = array();
$xactions[] = id(new PhabricatorDashboardPanelTransaction())
->setTransactionType($type_name)
->setNewValue($v_name);
$xactions[] = id(new PhabricatorDashboardPanelTransaction())
->setTransactionType($type_view_policy)
->setNewValue($v_view_policy);
$xactions[] = id(new PhabricatorDashboardPanelTransaction())
->setTransactionType($type_edit_policy)
->setNewValue($v_edit_policy);
$field_xactions = $field_list->buildFieldTransactionsFromRequest(
new PhabricatorDashboardPanelTransaction(),
$request);
$xactions = array_merge($xactions, $field_xactions);
try {
$editor = id(new PhabricatorDashboardPanelTransactionEditor())
->setActor($viewer)
->setContinueOnNoEffect(true)
->setContentSourceFromRequest($request)
->applyTransactions($panel, $xactions);
// If we're creating a panel directly on a dashboard, add it now.
if ($dashboard) {
PhabricatorDashboardTransactionEditor::addPanelToDashboard(
$viewer,
PhabricatorContentSource::newFromRequest($request),
$panel,
$dashboard,
$request->getInt('column', 0));
}
if ($dashboard) {
$done_uri = $manage_uri;
} else {
$done_uri = '/'.$panel->getMonogram();
}
return id(new AphrontRedirectResponse())->setURI($done_uri);
} catch (PhabricatorApplicationTransactionValidationException $ex) {
$validation_exception = $ex;
$e_name = $validation_exception->getShortMessage($type_name);
$panel->setViewPolicy($v_view_policy);
$panel->setEditPolicy($v_edit_policy);
}
}
// NOTE: We're setting the submit URI explicitly because we need to edit
// a different panel if we just cloned the original panel.
if ($is_create) {
$submit_uri = $this->getApplicationURI('panel/edit/');
} else {
$submit_uri = $this->getApplicationURI('panel/edit/'.$panel->getID().'/');
}
$policies = id(new PhabricatorPolicyQuery())
->setViewer($viewer)
->setObject($panel)
->execute();
$form = id(new AphrontFormView())
->setUser($viewer)
->setAction($submit_uri)
->addHiddenInput('edit', true)
->addHiddenInput('dashboardID', $request->getInt('dashboardID'))
->addHiddenInput('column', $request->getInt('column'))
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Name'))
->setName('name')
->setValue($v_name)
->setError($e_name))
->appendChild(
id(new AphrontFormPolicyControl())
->setName('viewPolicy')
->setPolicyObject($panel)
->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
->setPolicies($policies))
->appendChild(
id(new AphrontFormPolicyControl())
->setName('editPolicy')
->setPolicyObject($panel)
->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
->setPolicies($policies));
$field_list->appendFieldsToForm($form);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(
pht('Panels'),
$this->getApplicationURI('panel/'));
if ($is_create) {
$crumbs->addTextCrumb(pht('New Panel'));
$form->addHiddenInput('type', $panel->getPanelType());
} else {
$crumbs->addTextCrumb(
$panel->getMonogram(),
'/'.$panel->getMonogram());
$crumbs->addTextCrumb(pht('Edit'));
}
$crumbs->setBorder(true);
if ($request->isAjax()) {
return $this->newDialog()
->setTitle($title)
->setSubmitURI($submit_uri)
->setWidth(AphrontDialogView::WIDTH_FORM)
->setValidationException($validation_exception)
->appendChild($form->buildLayoutView())
->addCancelButton($cancel_uri)
->addSubmitButton($button);
} else {
$form
->appendChild(
id(new AphrontFormSubmitControl())
->setValue($button)
->addCancelButton($cancel_uri));
}
$box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Panel'))
->setValidationException($validation_exception)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setForm($form);
$header = id(new PHUIHeaderView())
->setHeader($title)
->setHeaderIcon($header_icon);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setFooter($box);
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
}
private function processPanelTypeRequest(AphrontRequest $request) {
$viewer = $request->getUser();
$types = PhabricatorDashboardPanelType::getAllPanelTypes();
$v_type = null;
$errors = array();
if ($request->isFormPost()) {
$v_type = $request->getStr('type');
if (!isset($types[$v_type])) {
$errors[] = pht('You must select a type of panel to create.');
}
}
$cancel_uri = $this->getApplicationURI('panel/');
if (!$v_type) {
$v_type = key($types);
}
$panel_types = id(new AphrontFormRadioButtonControl())
->setName('type')
->setValue($v_type);
foreach ($types as $key => $type) {
$panel_types->addButton(
$key,
$type->getPanelTypeName(),
$type->getPanelTypeDescription());
}
$form = id(new AphrontFormView())
->setUser($viewer)
->addHiddenInput('dashboardID', $request->getInt('dashboardID'))
->addHiddenInput('column', $request->getInt('column'))
->appendRemarkupInstructions(
pht(
'Choose the type of dashboard panel to create:'))
->appendChild($panel_types);
if ($request->isAjax()) {
return $this->newDialog()
->setTitle(pht('Add New Panel'))
->setWidth(AphrontDialogView::WIDTH_FORM)
->setErrors($errors)
->appendChild($form->buildLayoutView())
->addCancelbutton($cancel_uri)
->addSubmitButton(pht('Continue'));
} else {
$form->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Continue'))
->addCancelButton($cancel_uri));
}
$title = pht('Create Dashboard Panel');
$header_icon = 'fa-plus-square';
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(
pht('Panels'),
$this->getApplicationURI('panel/'));
$crumbs->addTextCrumb(pht('New Panel'));
$crumbs->setBorder(true);
$box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Panel'))
->setFormErrors($errors)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setForm($form);
$header = id(new PHUIHeaderView())
->setHeader($title)
->setHeaderIcon($header_icon);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setFooter($box);
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
}
private function processPanelCloneRequest(
AphrontRequest $request,
PhabricatorDashboard $dashboard,
PhabricatorDashboardPanel $panel) {
$viewer = $request->getUser();
$manage_uri = $this->getApplicationURI('manage/'.$dashboard->getID().'/');
return $this->newDialog()
->setTitle(pht('Copy Panel?'))
->addHiddenInput('copy', true)
->addHiddenInput('dashboardID', $request->getInt('dashboardID'))
->addHiddenInput('column', $request->getInt('column'))
->appendParagraph(
pht(
'You do not have permission to edit this dashboard panel, but you '.
'can make a copy and edit that instead. If you choose to copy the '.
'panel, the original will be replaced with the new copy on this '.
'dashboard.'))
->appendParagraph(
pht(
'Do you want to make a copy of this panel?'))
->addCancelButton($manage_uri)
->addSubmitButton(pht('Copy Panel'));
}
private function copyPanel(
AphrontRequest $request,
PhabricatorDashboard $dashboard,
PhabricatorDashboardPanel $panel) {
$viewer = $request->getUser();
$copy = PhabricatorDashboardPanel::initializeNewPanel($viewer);
- $copy = PhabricatorDashboardPanel::copyPanel($copy, $panel);
+ $copy = PhabricatorDashboardPanel::copyPanel($copy, $panel, $viewer);
$copy->openTransaction();
$copy->save();
// TODO: This should record a transaction on the panel copy, too.
$xactions = array();
$xactions[] = id(new PhabricatorDashboardTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue(
'edge:type',
PhabricatorDashboardDashboardHasPanelEdgeType::EDGECONST)
->setNewValue(
array(
'+' => array(
$copy->getPHID() => $copy->getPHID(),
),
'-' => array(
$panel->getPHID() => $panel->getPHID(),
),
));
$layout_config = $dashboard->getLayoutConfigObject();
$layout_config->replacePanel($panel->getPHID(), $copy->getPHID());
$dashboard->setLayoutConfigFromObject($layout_config);
$dashboard->save();
$editor = id(new PhabricatorDashboardTransactionEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnMissingFields(true)
->setContinueOnNoEffect(true)
->applyTransactions($dashboard, $xactions);
$copy->saveTransaction();
return $copy;
}
}
diff --git a/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php b/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php
index 3a6589a32c..6fbdb3d99c 100644
--- a/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php
+++ b/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php
@@ -1,85 +1,98 @@
<?php
final class PhabricatorDashboardPanelQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $archived;
private $panelTypes;
+ private $authorPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withArchived($archived) {
$this->archived = $archived;
return $this;
}
public function withPanelTypes(array $types) {
$this->panelTypes = $types;
return $this;
}
+ public function withAuthorPHIDs(array $authors) {
+ $this->authorPHIDs = $authors;
+ return $this;
+ }
+
protected function loadPage() {
return $this->loadStandardPage($this->newResultObject());
}
public function newResultObject() {
// TODO: If we don't do this, SearchEngine explodes when trying to
// enumerate custom fields. For now, just give the panel a default panel
// type so custom fields work. In the long run, we may want to find a
// cleaner or more general approach for this.
$text_type = id(new PhabricatorDashboardTextPanelType())
->getPanelTypeKey();
return id(new PhabricatorDashboardPanel())
->setPanelType($text_type);
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'phid IN (%Ls)',
$this->phids);
}
if ($this->archived !== null) {
$where[] = qsprintf(
$conn,
'isArchived = %d',
(int)$this->archived);
}
if ($this->panelTypes !== null) {
$where[] = qsprintf(
$conn,
'panelType IN (%Ls)',
$this->panelTypes);
}
+ if ($this->authorPHIDs !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'authorPHID IN (%Ls)',
+ $this->authorPHIDs);
+ }
+
return $where;
}
public function getQueryApplicationClass() {
return 'PhabricatorDashboardApplication';
}
}
diff --git a/src/applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php b/src/applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php
index 113ed8ff94..d9fe25ab02 100644
--- a/src/applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php
+++ b/src/applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php
@@ -1,125 +1,146 @@
<?php
final class PhabricatorDashboardPanelSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Dashboard Panels');
}
public function getApplicationClassName() {
return 'PhabricatorDashboardApplication';
}
public function newQuery() {
return new PhabricatorDashboardPanelQuery();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['status']) {
switch ($map['status']) {
case 'active':
$query->withArchived(false);
break;
case 'archived':
$query->withArchived(true);
break;
default:
break;
}
}
if ($map['paneltype']) {
$query->withPanelTypes(array($map['paneltype']));
}
+ if ($map['authorPHIDs']) {
+ $query->withAuthorPHIDs($map['authorPHIDs']);
+ }
+
return $query;
}
protected function buildCustomSearchFields() {
return array(
+ id(new PhabricatorSearchDatasourceField())
+ ->setLabel(pht('Authored By'))
+ ->setKey('authorPHIDs')
+ ->setDatasource(new PhabricatorPeopleUserFunctionDatasource()),
id(new PhabricatorSearchSelectField())
->setKey('status')
->setLabel(pht('Status'))
->setOptions(
id(new PhabricatorDashboardPanel())
->getStatuses()),
id(new PhabricatorSearchSelectField())
->setKey('paneltype')
->setLabel(pht('Panel Type'))
->setOptions(
id(new PhabricatorDashboardPanel())
->getPanelTypes()),
);
}
protected function getURI($path) {
return '/dashboard/panel/'.$path;
}
protected function getBuiltinQueryNames() {
- return array(
- 'active' => pht('Active Panels'),
- 'all' => pht('All Panels'),
- );
+ $names = array();
+
+ if ($this->requireViewer()->isLoggedIn()) {
+ $names['authored'] = pht('Authored');
+ }
+
+ $names['active'] = pht('Active Panels');
+ $names['all'] = pht('All Panels');
+
+ return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
+ $viewer = $this->requireViewer();
switch ($query_key) {
case 'active':
return $query->setParameter('status', 'active');
+ case 'authored':
+ return $query->setParameter(
+ 'authorPHIDs',
+ array(
+ $viewer->getPHID(),
+ ));
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $panels,
PhabricatorSavedQuery $query,
array $handles) {
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
foreach ($panels as $panel) {
$item = id(new PHUIObjectItemView())
->setObjectName($panel->getMonogram())
->setHeader($panel->getName())
->setHref('/'.$panel->getMonogram())
->setObject($panel);
$impl = $panel->getImplementation();
if ($impl) {
$type_text = $impl->getPanelTypeName();
} else {
$type_text = nonempty($panel->getPanelType(), pht('Unknown Type'));
}
$item->addAttribute($type_text);
$properties = $panel->getProperties();
$class = idx($properties, 'class');
$item->addAttribute($class);
if ($panel->getIsArchived()) {
$item->setDisabled(true);
}
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No panels found.'));
return $result;
}
}
diff --git a/src/applications/dashboard/query/PhabricatorDashboardSearchEngine.php b/src/applications/dashboard/query/PhabricatorDashboardSearchEngine.php
index 70325de3bb..389bbb6bdc 100644
--- a/src/applications/dashboard/query/PhabricatorDashboardSearchEngine.php
+++ b/src/applications/dashboard/query/PhabricatorDashboardSearchEngine.php
@@ -1,218 +1,218 @@
<?php
final class PhabricatorDashboardSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Dashboards');
}
public function getApplicationClassName() {
return 'PhabricatorDashboardApplication';
}
public function newQuery() {
return id(new PhabricatorDashboardQuery())
->needProjects(true);
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Authored By'))
->setKey('authorPHIDs')
->setDatasource(new PhabricatorPeopleUserFunctionDatasource()),
id(new PhabricatorSearchCheckboxesField())
->setKey('statuses')
->setLabel(pht('Status'))
->setOptions(PhabricatorDashboard::getStatusNameMap()),
);
}
protected function getURI($path) {
return '/dashboard/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
if ($this->requireViewer()->isLoggedIn()) {
$names['authored'] = pht('Authored');
}
$names['open'] = pht('Active Dashboards');
$names['all'] = pht('All Dashboards');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
$viewer = $this->requireViewer();
switch ($query_key) {
case 'all':
return $query;
case 'authored':
return $query->setParameter(
- 'authored',
+ 'authorPHIDs',
array(
$viewer->getPHID(),
));
case 'open':
return $query->setParameter(
'statuses',
array(
PhabricatorDashboard::STATUS_ACTIVE,
));
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['statuses']) {
$query->withStatuses($map['statuses']);
}
if ($map['authorPHIDs']) {
$query->withAuthorPHIDs($map['authorPHIDs']);
}
return $query;
}
protected function renderResultList(
array $dashboards,
PhabricatorSavedQuery $query,
array $handles) {
$dashboards = mpull($dashboards, null, 'getPHID');
$viewer = $this->requireViewer();
if ($dashboards) {
$installs = id(new PhabricatorDashboardInstall())
->loadAllWhere(
'objectPHID IN (%Ls) AND dashboardPHID IN (%Ls)',
array(
PhabricatorHomeApplication::DASHBOARD_DEFAULT,
$viewer->getPHID(),
),
array_keys($dashboards));
$installs = mpull($installs, null, 'getDashboardPHID');
} else {
$installs = array();
}
$proj_phids = array();
foreach ($dashboards as $dashboard) {
foreach ($dashboard->getProjectPHIDs() as $project_phid) {
$proj_phids[] = $project_phid;
}
}
$proj_handles = id(new PhabricatorHandleQuery())
->setViewer($viewer)
->withPHIDs($proj_phids)
->execute();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
$list->initBehavior('phabricator-tooltips', array());
$list->requireResource('aphront-tooltip-css');
foreach ($dashboards as $dashboard_phid => $dashboard) {
$id = $dashboard->getID();
$item = id(new PHUIObjectItemView())
->setObjectName(pht('Dashboard %d', $id))
->setHeader($dashboard->getName())
->setHref($this->getApplicationURI("view/{$id}/"))
->setObject($dashboard);
if (isset($installs[$dashboard_phid])) {
$install = $installs[$dashboard_phid];
if ($install->getObjectPHID() == $viewer->getPHID()) {
$attrs = array(
'tip' => pht(
'This dashboard is installed to your personal homepage.'),
);
$item->addIcon('fa-user', pht('Installed'), $attrs);
} else {
$attrs = array(
'tip' => pht(
'This dashboard is the default homepage for all users.'),
);
$item->addIcon('fa-globe', pht('Installed'), $attrs);
}
}
$project_handles = array_select_keys(
$proj_handles,
$dashboard->getProjectPHIDs());
$item->addAttribute(
id(new PHUIHandleTagListView())
->setLimit(4)
->setNoDataString(pht('No Projects'))
->setSlim(true)
->setHandles($project_handles));
if ($dashboard->isArchived()) {
$item->setDisabled(true);
}
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$dashboard,
PhabricatorPolicyCapability::CAN_EDIT);
$href_view = $this->getApplicationURI("manage/{$id}/");
$item->addAction(
id(new PHUIListItemView())
->setName(pht('Manage'))
->setIcon('fa-th')
->setHref($href_view));
$href_edit = $this->getApplicationURI("edit/{$id}/");
$item->addAction(
id(new PHUIListItemView())
->setName(pht('Edit'))
->setIcon('fa-pencil')
->setHref($href_edit)
->setDisabled(!$can_edit));
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No dashboards found.'));
return $result;
}
protected function getNewUserBody() {
$create_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Create a Dashboard'))
->setHref('/dashboard/create/')
->setColor(PHUIButtonView::GREEN);
$icon = $this->getApplication()->getIcon();
$app_name = $this->getApplication()->getName();
$view = id(new PHUIBigInfoView())
->setIcon($icon)
->setTitle(pht('Welcome to %s', $app_name))
->setDescription(
pht('Customize your homepage with different panels and '.
'search queries.'))
->addAction($create_button);
return $view;
}
}
diff --git a/src/applications/dashboard/storage/PhabricatorDashboardPanel.php b/src/applications/dashboard/storage/PhabricatorDashboardPanel.php
index 64e6ea5b87..6067abf79f 100644
--- a/src/applications/dashboard/storage/PhabricatorDashboardPanel.php
+++ b/src/applications/dashboard/storage/PhabricatorDashboardPanel.php
@@ -1,195 +1,200 @@
<?php
/**
* An individual dashboard panel.
*/
final class PhabricatorDashboardPanel
extends PhabricatorDashboardDAO
implements
PhabricatorApplicationTransactionInterface,
PhabricatorPolicyInterface,
PhabricatorCustomFieldInterface,
PhabricatorFlaggableInterface,
PhabricatorDestructibleInterface {
protected $name;
protected $panelType;
protected $viewPolicy;
protected $editPolicy;
+ protected $authorPHID;
protected $isArchived = 0;
protected $properties = array();
private $customFields = self::ATTACHABLE;
public static function initializeNewPanel(PhabricatorUser $actor) {
return id(new PhabricatorDashboardPanel())
->setName('')
+ ->setAuthorPHID($actor->getPHID())
->setViewPolicy(PhabricatorPolicies::POLICY_USER)
->setEditPolicy($actor->getPHID());
}
public static function copyPanel(
PhabricatorDashboardPanel $dst,
- PhabricatorDashboardPanel $src) {
+ PhabricatorDashboardPanel $src,
+ PhabricatorUser $user) {
$dst->name = $src->name;
$dst->panelType = $src->panelType;
$dst->properties = $src->properties;
+ $dst->authorPHID = $user->getPHID();
return $dst;
}
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'properties' => self::SERIALIZATION_JSON,
),
self::CONFIG_COLUMN_SCHEMA => array(
'name' => 'text255',
'panelType' => 'text64',
+ 'authorPHID' => 'phid',
'isArchived' => 'bool',
),
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhabricatorDashboardPanelPHIDType::TYPECONST);
}
public function getProperty($key, $default = null) {
return idx($this->properties, $key, $default);
}
public function setProperty($key, $value) {
$this->properties[$key] = $value;
return $this;
}
public function getMonogram() {
return 'W'.$this->getID();
}
public function getURI() {
return '/'.$this->getMonogram();
}
public function getPanelTypes() {
$panel_types = PhabricatorDashboardPanelType::getAllPanelTypes();
$panel_types = mpull($panel_types, 'getPanelTypeName', 'getPanelTypeKey');
asort($panel_types);
$panel_types = (array('' => pht('(All Types)')) + $panel_types);
return $panel_types;
}
public function getStatuses() {
$statuses =
array(
'' => pht('(All Panels)'),
'active' => pht('Active Panels'),
'archived' => pht('Archived Panels'),
);
return $statuses;
}
public function getImplementation() {
return idx(
PhabricatorDashboardPanelType::getAllPanelTypes(),
$this->getPanelType());
}
public function requireImplementation() {
$impl = $this->getImplementation();
if (!$impl) {
throw new Exception(
pht(
'Attempting to use a panel in a way that requires an '.
'implementation, but the panel implementation ("%s") is unknown to '.
'Phabricator.',
$this->getPanelType()));
}
return $impl;
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
public function getApplicationTransactionEditor() {
return new PhabricatorDashboardPanelTransactionEditor();
}
public function getApplicationTransactionObject() {
return $this;
}
public function getApplicationTransactionTemplate() {
return new PhabricatorDashboardPanelTransaction();
}
public function willRenderTimeline(
PhabricatorApplicationTransactionView $timeline,
AphrontRequest $request) {
return $timeline;
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return $this->getViewPolicy();
case PhabricatorPolicyCapability::CAN_EDIT:
return $this->getEditPolicy();
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return false;
}
/* -( PhabricatorCustomFieldInterface )------------------------------------ */
public function getCustomFieldSpecificationForRole($role) {
return array();
}
public function getCustomFieldBaseClass() {
return 'PhabricatorDashboardPanelCustomField';
}
public function getCustomFields() {
return $this->assertAttached($this->customFields);
}
public function attachCustomFields(PhabricatorCustomFieldAttachment $fields) {
$this->customFields = $fields;
return $this;
}
/* -( PhabricatorDestructibleInterface )----------------------------------- */
public function destroyObjectPermanently(
PhabricatorDestructionEngine $engine) {
$this->openTransaction();
$this->delete();
$this->saveTransaction();
}
}

File Metadata

Mime Type
text/x-diff
Expires
Wed, Nov 5, 3:20 PM (3 h, 52 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
321010
Default Alt Text
(34 KB)

Event Timeline