1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-21 04:50:55 +01:00

Paste - kill tabs

Summary:
merge paste create and paste list into a single controller.  Add a "filter list"
to the left hand side and have new "create w/ recent", "my" and "all" views.  UI
wrinkle -- "create w/ recent" does not paginate the recent pastes and instead
upsells the user to the new "all" view.

Also includes a business logic clean up or two for simplicity of code.

Test Plan:
- created a paste from the UI
- tried to create a paste with title and no body
- tried to create a paste with no title and no body
- viewed the paste list on "create" view
- viewed the paste list on "author" view
- viewed the paste list on "all" view
- viewed page 2 of the paste list for "author" and "all" views
- "forked" a given paste through completion

Reviewers: epriestley

Reviewed By: epriestley

CC: aran, epriestley, btrahan

Maniphest Tasks: T631

Differential Revision: 1198
This commit is contained in:
Bob Trahan 2011-12-13 09:48:17 -08:00
parent 4edfd35503
commit 6f1dfbb658
6 changed files with 352 additions and 211 deletions

View file

@ -315,10 +315,9 @@ class AphrontDefaultApplicationConfiguration
'/status/$' => 'PhabricatorStatusController', '/status/$' => 'PhabricatorStatusController',
'/paste/' => array( '/paste/' => array(
'$' => 'PhabricatorPasteCreateController', '$' => 'PhabricatorPasteListController',
'list/' => 'PhabricatorPasteListController', 'filter/(?P<filter>\w+)/$' => 'PhabricatorPasteListController',
), ),
'/P(?P<id>\d+)$' => 'PhabricatorPasteViewController', '/P(?P<id>\d+)$' => 'PhabricatorPasteViewController',
'/help/' => array( '/help/' => array(

View file

@ -26,15 +26,6 @@ abstract class PhabricatorPasteController extends PhabricatorController {
$page->setBaseURI('/paste/'); $page->setBaseURI('/paste/');
$page->setTitle(idx($data, 'title')); $page->setTitle(idx($data, 'title'));
$page->setGlyph("\xE2\x9C\x8E"); $page->setGlyph("\xE2\x9C\x8E");
$page->setTabs(
array(
'list' => array(
'href' => '/paste/list/',
'name' => 'Paste List',
),
),
idx($data, 'tab'));
$page->appendChild($view); $page->appendChild($view);
$response = new AphrontWebpageResponse(); $response = new AphrontWebpageResponse();

View file

@ -1,156 +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 PhabricatorPasteCreateController extends PhabricatorPasteController {
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$paste = new PhabricatorPaste();
$error_view = null;
$e_text = true;
$fork = $request->getInt('fork');
$paste_text = null;
$paste_parent = null;
if ($request->isFormPost()) {
$errors = array();
$title = $request->getStr('title');
$paste_language = $request->getStr('language');
$text = $request->getStr('text');
if (!strlen($text)) {
$e_text = 'Required';
$errors[] = 'The paste may not be blank.';
} else {
$e_text = null;
}
$parent = id(new PhabricatorPaste())->loadOneWhere(
'phid = %s',
$request->getStr('parent'));
if ($parent) {
$paste->setParentPHID($parent->getPHID());
}
$paste->setTitle($title);
if (!$errors) {
if ($paste_language == 'infer') {
// If it's infer, store an empty string. Otherwise, store the
// language name. We do this so we can refer to 'infer' elsewhere
// in the code (such as default value) while retaining backwards
// compatibility with old posts with no language stored.
$paste_language = '';
}
$paste->setLanguage($paste_language);
$paste_file = PhabricatorFile::newFromFileData(
$text,
array(
'name' => $title,
'mime-type' => 'text/plain; charset=utf-8',
'authorPHID' => $user->getPHID(),
));
$paste->setFilePHID($paste_file->getPHID());
$paste->setAuthorPHID($user->getPHID());
$paste->save();
return id(new AphrontRedirectResponse())
->setURI('/P'.$paste->getID());
} else {
$error_view = new AphrontErrorView();
$error_view->setErrors($errors);
$error_view->setTitle('A problem has occurred!');
}
} else {
if ($fork) {
$fork_paste = id(new PhabricatorPaste())->load($fork);
if ($fork_paste) {
$paste->setTitle('Fork of '.$fork_paste->getID().': '.
$fork_paste->getTitle());
$fork_file = id(new PhabricatorFile())->loadOneWhere(
'phid = %s',
$fork_paste->getFilePHID());
$paste_text = $fork_file->loadFileData();
$paste_language = nonempty($fork_paste->getLanguage(), 'infer');
$paste_parent = $fork_paste->getPHID();
}
} else {
$paste_language = PhabricatorEnv::getEnvConfig(
'pygments.dropdown-default');
}
}
$form = new AphrontFormView();
$available_languages = PhabricatorEnv::getEnvConfig(
'pygments.dropdown-choices');
asort($available_languages);
$language_select = id(new AphrontFormSelectControl())
->setLabel('Language')
->setName('language')
->setValue($paste_language)
->setOptions($available_languages);
$form
->setUser($user)
->setAction($request->getRequestURI()->getPath())
->addHiddenInput('parent', $paste_parent)
->appendChild(
id(new AphrontFormTextControl())
->setLabel('Title')
->setValue($paste->getTitle())
->setName('title'))
->appendChild($language_select)
->appendChild(
id(new AphrontFormTextAreaControl())
->setLabel('Text')
->setError($e_text)
->setValue($paste_text)
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL)
->setName('text'))
->appendChild(
id(new AphrontFormSubmitControl())
->addCancelButton('/paste/')
->setValue('Create Paste'));
$panel = new AphrontPanelView();
$panel->setWidth(AphrontPanelView::WIDTH_FORM);
$panel->setHeader('Create a Paste');
$panel->appendChild($form);
return $this->buildStandardPageResponse(
array(
$error_view,
$panel,
),
array(
'title' => 'Paste Creation',
'tab' => 'create',
));
}
}

View file

@ -1,25 +0,0 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'aphront/response/redirect');
phutil_require_module('phabricator', 'applications/files/storage/file');
phutil_require_module('phabricator', 'applications/paste/controller/base');
phutil_require_module('phabricator', 'applications/paste/storage/paste');
phutil_require_module('phabricator', 'infrastructure/env');
phutil_require_module('phabricator', 'view/form/base');
phutil_require_module('phabricator', 'view/form/control/select');
phutil_require_module('phabricator', 'view/form/control/submit');
phutil_require_module('phabricator', 'view/form/control/text');
phutil_require_module('phabricator', 'view/form/control/textarea');
phutil_require_module('phabricator', 'view/form/error');
phutil_require_module('phabricator', 'view/layout/panel');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorPasteCreateController.php');

View file

@ -17,18 +17,292 @@
*/ */
class PhabricatorPasteListController extends PhabricatorPasteController { class PhabricatorPasteListController extends PhabricatorPasteController {
private $filter;
private $errorView;
private $errorText;
private $paste;
private $pasteText;
private $offset;
private $pageSize;
private $author;
private function setFilter($filter) {
$this->filter = $filter;
return $this;
}
private function getFilter() {
return $this->filter;
}
private function setErrorView($error_view) {
$this->errorView = $error_view;
return $this;
}
private function getErrorView() {
return $this->errorView;
}
private function setErrorText($error_text) {
$this->errorText = $error_text;
return $this;
}
private function getErrorText() {
return $this->errorText;
}
private function setPaste(PhabricatorPaste $paste) {
$this->paste = $paste;
return $this;
}
private function getPaste() {
return $this->paste;
}
private function setPasteText($paste_text) {
$this->pasteText = $paste_text;
return $this;
}
private function getPasteText() {
return $this->pasteText;
}
private function setOffset($offset) {
$this->offset = $offset;
return $this;
}
private function getOffset() {
return $this->offset;
}
private function setPageSize($page_size) {
$this->pageSize = $page_size;
return $this;
}
private function getPageSize() {
return $this->pageSize;
}
private function setAuthor($author) {
$this->author = $author;
return $this;
}
private function getAuthor() {
return $this->author;
}
public function willProcessRequest(array $data) {
$this->setFilter(idx($data, 'filter', 'create'));
}
public function processRequest() { public function processRequest() {
$request = $this->getRequest(); $request = $this->getRequest();
$user = $request->getUser();
$paste_list = array();
$pager = null;
switch ($this->getFilter()) {
case 'create':
default:
// if we successfully create a paste, we redirect to view it
$created_paste_redirect = $this->processCreateRequest();
if ($created_paste_redirect) {
return $created_paste_redirect;
}
// if we didn't succeed or we weren't trying, load just a few
// recent pastes with NO pagination
$this->setOffset(0);
$this->setPageSize(10);
list($paste_list, $pager) = $this->loadPasteList();
break;
case 'my':
$this->setAuthor($user->getPHID());
$this->setOffset($request->getInt('page', 0));
list($paste_list, $pager) = $this->loadPasteList();
break;
case 'all':
$this->setOffset($request->getInt('page', 0));
list($paste_list, $pager) = $this->loadPasteList();
break;
}
$filters = array(
'create' => array(
'name' => 'Create Paste',
),
'my' => array(
'name' => 'My Pastes',
),
'all' => array(
'name' => 'All Pastes',
),
);
$side_nav = new AphrontSideNavView();
foreach ($filters as $filter_key => $filter) {
$selected = $filter_key == $this->getFilter();
$side_nav->addNavItem(
phutil_render_tag(
'a',
array(
'href' => '/paste/filter/'.$filter_key.'/',
'class' => $selected ? 'aphront-side-nav-selected': null,
),
$filter['name'])
);
}
if ($this->getErrorView()) {
$side_nav->appendChild($this->getErrorView());
}
switch ($this->getFilter()) {
case 'create':
default:
$side_nav->appendChild($this->renderCreatePaste());
$see_all = phutil_render_tag(
'a',
array(
'href' => '/paste/filter/all',
),
'See all Pastes');
$header = "Recent Pastes &middot; {$see_all}";
$side_nav->appendChild($this->renderPasteList($paste_list,
$header,
$pager = null));
break;
case 'my':
$header = 'Your Pastes';
$side_nav->appendChild($this->renderPasteList($paste_list,
$header,
$pager));
break;
case 'all':
$header = 'All Pastes';
$side_nav->appendChild($this->renderPasteList($paste_list,
$header,
$pager));
break;
}
return $this->buildStandardPageResponse(
$side_nav,
array(
'title' => 'Paste',
)
);
}
private function processCreateRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$fork = $request->getInt('fork');
$error_view = null;
$e_text = true;
$new_paste = new PhabricatorPaste();
$new_paste_text = null;
$new_paste_language = PhabricatorEnv::getEnvConfig(
'pygments.dropdown-default');
if ($request->isFormPost()) {
$errors = array();
$text = $request->getStr('text');
if (!strlen($text)) {
$e_text = 'Required';
$errors[] = 'The paste may not be blank.';
} else {
$e_text = null;
}
$parent_phid = $request->getStr('parent');
if ($parent_phid) {
$parent = id(new PhabricatorPaste())->loadOneWhere('phid = %s',
$parent_phid);
if ($parent) {
$new_paste->setParentPHID($parent->getPHID());
}
}
$title = $request->getStr('title');
$new_paste->setTitle($title);
$new_paste_language = $request->getStr('language');
if (!$errors) {
if ($new_paste_language == 'infer') {
// If it's infer, store an empty string. Otherwise, store the
// language name. We do this so we can refer to 'infer' elsewhere
// in the code (such as default value) while retaining backwards
// compatibility with old posts with no language stored.
$new_paste_language = '';
}
$new_paste->setLanguage($new_paste_language);
$new_paste_file = PhabricatorFile::newFromFileData(
$text,
array(
'name' => $title,
'mime-type' => 'text/plain; charset=utf-8',
'authorPHID' => $user->getPHID(),
));
$new_paste->setFilePHID($new_paste_file->getPHID());
$new_paste->setAuthorPHID($user->getPHID());
$new_paste->save();
return id(new AphrontRedirectResponse())
->setURI('/P'.$new_paste->getID());
} else {
$error_view = new AphrontErrorView();
$error_view->setErrors($errors);
$error_view->setTitle('A problem has occurred!');
}
} else if ($fork) {
$fork_paste = id(new PhabricatorPaste())->load($fork);
if ($fork_paste) {
$new_paste->setTitle('Fork of '.$fork_paste->getID().': '.
$fork_paste->getTitle());
$fork_file = id(new PhabricatorFile())->loadOneWhere(
'phid = %s',
$fork_paste->getFilePHID());
$new_paste_text = $fork_file->loadFileData();
$new_paste_language = nonempty($fork_paste->getLanguage(), 'infer');
$new_paste->setParentPHID($fork_paste->getPHID());
}
}
$this->setErrorView($error_view);
$this->setErrorText($e_text);
$this->setPasteText($new_paste_text);
$new_paste->setLanguage($new_paste_language);
$this->setPaste($new_paste);
}
private function loadPasteList() {
$request = $this->getRequest();
$pager = new AphrontPagerView(); $pager = new AphrontPagerView();
$pager->setOffset($request->getInt('page')); $pager->setOffset($this->getOffset());
if ($this->getPageSize()) {
$pager->setPageSize($this->getPageSize());
}
if ($this->getAuthor()) {
$pastes = id(new PhabricatorPaste())->loadAllWhere(
'authorPHID = %s ORDER BY id DESC LIMIT %d, %d',
$this->getAuthor(),
$pager->getOffset(),
$pager->getPageSize() + 1);
} else {
$pastes = id(new PhabricatorPaste())->loadAllWhere( $pastes = id(new PhabricatorPaste())->loadAllWhere(
'1 = 1 ORDER BY id DESC LIMIT %d, %d', '1 = 1 ORDER BY id DESC LIMIT %d, %d',
$pager->getOffset(), $pager->getOffset(),
$pager->getPageSize() + 1); $pager->getPageSize() + 1);
}
$pastes = $pager->sliceResults($pastes); $pastes = $pager->sliceResults($pastes);
$pager->setURI($request->getRequestURI(), 'page'); $pager->setURI($request->getRequestURI(), 'page');
@ -39,12 +313,12 @@ class PhabricatorPasteListController extends PhabricatorPasteController {
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles(); $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
} }
$rows = array(); $paste_list_rows = array();
foreach ($pastes as $paste) { foreach ($pastes as $paste) {
$handle = $handles[$paste->getAuthorPHID()]; $handle = $handles[$paste->getAuthorPHID()];
$rows[] = array( $paste_list_rows[] = array(
phutil_escape_html('P'.$paste->getID()), phutil_escape_html('P'.$paste->getID()),
// TODO: Make this filter by user instead of going to their profile. // TODO: Make this filter by user instead of going to their profile.
@ -77,7 +351,60 @@ class PhabricatorPasteListController extends PhabricatorPasteController {
); );
} }
$table = new AphrontTableView($rows); return array($paste_list_rows, $pager);
}
private function renderCreatePaste() {
$request = $this->getRequest();
$user = $request->getUser();
$new_paste = $this->getPaste();
$form = new AphrontFormView();
$available_languages = PhabricatorEnv::getEnvConfig(
'pygments.dropdown-choices');
asort($available_languages);
$language_select = id(new AphrontFormSelectControl())
->setLabel('Language')
->setName('language')
->setValue($new_paste->getLanguage())
->setOptions($available_languages);
$form
->setUser($user)
->setAction($request->getRequestURI()->getPath())
->addHiddenInput('parent', $new_paste->getParentPHID())
->appendChild(
id(new AphrontFormTextControl())
->setLabel('Title')
->setValue($new_paste->getTitle())
->setName('title'))
->appendChild($language_select)
->appendChild(
id(new AphrontFormTextAreaControl())
->setLabel('Text')
->setError($this->getErrorText())
->setValue($this->getPasteText())
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL)
->setName('text'))
->appendChild(
id(new AphrontFormSubmitControl())
->addCancelButton('/paste/')
->setValue('Create Paste'));
$create_panel = new AphrontPanelView();
$create_panel->setWidth(AphrontPanelView::WIDTH_FULL);
$create_panel->setHeader('Create a Paste');
$create_panel->appendChild($form);
return $create_panel;
}
private function renderPasteList($paste_list_rows,
$header,
$pager = null) {
$table = new AphrontTableView($paste_list_rows);
$table->setHeaders( $table->setHeaders(
array( array(
'Paste ID', 'Paste ID',
@ -98,17 +425,12 @@ class PhabricatorPasteListController extends PhabricatorPasteController {
$panel = new AphrontPanelView(); $panel = new AphrontPanelView();
$panel->setWidth(AphrontPanelView::WIDTH_FULL); $panel->setWidth(AphrontPanelView::WIDTH_FULL);
$panel->setHeader("Paste"); $panel->setHeader($header);
$panel->setCreateButton('Paste Something', '/paste/');
$panel->appendChild($table); $panel->appendChild($table);
if ($pager) {
$panel->appendChild($pager); $panel->appendChild($pager);
}
return $this->buildStandardPageResponse( return $panel;
$panel,
array(
'title' => 'Paste List',
'tab' => 'list',
)
);
} }
} }

View file

@ -6,13 +6,23 @@
phutil_require_module('phabricator', 'aphront/response/redirect');
phutil_require_module('phabricator', 'applications/files/storage/file');
phutil_require_module('phabricator', 'applications/files/uri'); phutil_require_module('phabricator', 'applications/files/uri');
phutil_require_module('phabricator', 'applications/paste/controller/base'); phutil_require_module('phabricator', 'applications/paste/controller/base');
phutil_require_module('phabricator', 'applications/paste/storage/paste'); phutil_require_module('phabricator', 'applications/paste/storage/paste');
phutil_require_module('phabricator', 'applications/phid/handle/data'); phutil_require_module('phabricator', 'applications/phid/handle/data');
phutil_require_module('phabricator', 'infrastructure/env');
phutil_require_module('phabricator', 'view/control/pager'); phutil_require_module('phabricator', 'view/control/pager');
phutil_require_module('phabricator', 'view/control/table'); phutil_require_module('phabricator', 'view/control/table');
phutil_require_module('phabricator', 'view/form/base');
phutil_require_module('phabricator', 'view/form/control/select');
phutil_require_module('phabricator', 'view/form/control/submit');
phutil_require_module('phabricator', 'view/form/control/text');
phutil_require_module('phabricator', 'view/form/control/textarea');
phutil_require_module('phabricator', 'view/form/error');
phutil_require_module('phabricator', 'view/layout/panel'); phutil_require_module('phabricator', 'view/layout/panel');
phutil_require_module('phabricator', 'view/layout/sidenav');
phutil_require_module('phutil', 'markup'); phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils'); phutil_require_module('phutil', 'utils');