From 1a63938b334c902e10cf9602a379f99959077454 Mon Sep 17 00:00:00 2001
From: epriestley
Date: Tue, 16 Oct 2012 09:44:43 -0700
Subject: [PATCH] Further improve various Phame UI things
Summary:
- Better icons and action order.
- "Move Post" action.
- (Bugfix) Allow multiple blogs to be set to not having custom domains.
- Make "Write Post" skip the "select a blog" step when coming from a blog view.
- Sort blog list on "Write Post".
- Show messages when a post is a draft or not on a blog.
Test Plan: Created posts, blogs, moved posts, preview/live'd posts, etc.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T1373
Differential Revision: https://secure.phabricator.com/D3708
---
scripts/celerity/generate_sprites.php | 5 +-
.../PhabricatorApplicationPhame.php | 1 +
.../blog/PhameBlogEditController.php | 2 +-
.../blog/PhameBlogViewController.php | 2 +-
.../post/PhamePostNewController.php | 81 ++++++++++++--
.../post/PhamePostNotLiveController.php | 4 +-
.../post/PhamePostViewController.php | 103 +++++++++---------
src/view/form/AphrontErrorView.php | 21 ++--
webroot/rsrc/css/aphront/error-view.css | 1 +
webroot/rsrc/css/autosprite.css | 30 +++--
.../layout/phabricator-action-list-view.css | 2 +-
.../layout/phabricator-property-list-view.css | 24 ++++
webroot/rsrc/image/autosprite.png | Bin 145081 -> 146324 bytes
13 files changed, 192 insertions(+), 84 deletions(-)
diff --git a/scripts/celerity/generate_sprites.php b/scripts/celerity/generate_sprites.php
index a6f2b109b5..b44e61f1e3 100755
--- a/scripts/celerity/generate_sprites.php
+++ b/scripts/celerity/generate_sprites.php
@@ -220,7 +220,10 @@ $action_map = array(
'subscribe-delete' => 'icon/unsubscribe.png',
'new' => 'icon/page_white_put.png',
'world' => 'icon/world.png',
- 'delete' => 'icon/delete.png',
+ 'delete' => 'icon/page_delete.png',
+ 'move' => 'icon/page_go.png',
+ 'preview' => 'icon/page_world.png',
+ 'unpublish' => 'icon/page_error.png',
);
foreach ($action_map as $icon => $source) {
diff --git a/src/applications/phame/application/PhabricatorApplicationPhame.php b/src/applications/phame/application/PhabricatorApplicationPhame.php
index 5867f9d194..84ca525a9c 100644
--- a/src/applications/phame/application/PhabricatorApplicationPhame.php
+++ b/src/applications/phame/application/PhabricatorApplicationPhame.php
@@ -59,6 +59,7 @@ final class PhabricatorApplicationPhame extends PhabricatorApplication {
'preview/' => 'PhamePostPreviewController',
'framed/(?P\d+)/' => 'PhamePostFramedController',
'new/' => 'PhamePostNewController',
+ 'move/(?P\d+)/' => 'PhamePostNewController'
),
'blog/' => array(
'(?:(?Puser|all)/)?' => 'PhameBlogListController',
diff --git a/src/applications/phame/controller/blog/PhameBlogEditController.php b/src/applications/phame/controller/blog/PhameBlogEditController.php
index 35cddc9b52..4b953d2bd0 100644
--- a/src/applications/phame/controller/blog/PhameBlogEditController.php
+++ b/src/applications/phame/controller/blog/PhameBlogEditController.php
@@ -80,7 +80,7 @@ final class PhameBlogEditController
$blog->setName($name);
$blog->setDescription($description);
- $blog->setDomain($custom_domain);
+ $blog->setDomain(nonempty($custom_domain, null));
$blog->setSkin($skin);
if (!empty($custom_domain)) {
diff --git a/src/applications/phame/controller/blog/PhameBlogViewController.php b/src/applications/phame/controller/blog/PhameBlogViewController.php
index 7533d0b86b..8475cee454 100644
--- a/src/applications/phame/controller/blog/PhameBlogViewController.php
+++ b/src/applications/phame/controller/blog/PhameBlogViewController.php
@@ -139,7 +139,7 @@ final class PhameBlogViewController extends PhameController {
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('new')
- ->setHref($this->getApplicationURI('post/new/?blog='.$blog->getID()))
+ ->setHref($this->getApplicationURI('post/edit/?blog='.$blog->getID()))
->setName(pht('Write Post'))
->setDisabled(!$can_join)
->setWorkflow(!$can_join));
diff --git a/src/applications/phame/controller/post/PhamePostNewController.php b/src/applications/phame/controller/post/PhamePostNewController.php
index 6393c2d9b0..60b7056e67 100644
--- a/src/applications/phame/controller/post/PhamePostNewController.php
+++ b/src/applications/phame/controller/post/PhamePostNewController.php
@@ -21,10 +21,57 @@
*/
final class PhamePostNewController extends PhameController {
+ private $id;
+
+ public function willProcessRequest(array $data) {
+ $this->id = idx($data, 'id');
+ }
+
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
+ $post = null;
+ $view_uri = null;
+ if ($this->id) {
+ $post = id(new PhamePostQuery())
+ ->setViewer($user)
+ ->withIDs(array($this->id))
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->executeOne();
+ if (!$post) {
+ return new Aphront404Response();
+ }
+
+ $view_uri = '/post/view/'.$post->getID().'/';
+ $view_uri = $this->getApplicationURI($view_uri);
+
+ if ($request->isFormPost()) {
+ $blog = id(new PhameBlogQuery())
+ ->setViewer($user)
+ ->withIDs(array($request->getInt('blog')))
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_JOIN,
+ ))
+ ->executeOne();
+
+ if ($blog) {
+ $post->setBlogPHID($blog->getPHID());
+ $post->save();
+
+ return id(new AphrontRedirectResponse())->setURI($view_uri);
+ }
+ }
+
+ $title = pht('Move Post');
+ } else {
+ $title = pht('Create Post');
+ }
+
$blogs = id(new PhameBlogQuery())
->setViewer($user)
->requireCapabilities(
@@ -36,8 +83,7 @@ final class PhamePostNewController extends PhameController {
$nav = $this->renderSideNavFilterView();
$nav->selectFilter('post/new');
$nav->appendChild(
- id(new PhabricatorHeaderView())->setHeader(
- pht('Create Post')));
+ id(new PhabricatorHeaderView())->setHeader($title));
if (!$blogs) {
$notification = id(new AphrontErrorView())
@@ -49,20 +95,37 @@ final class PhamePostNewController extends PhameController {
$nav->appendChild($notification);
} else {
$options = mpull($blogs, 'getName', 'getID');
+ asort($options);
+
+ $selected_value = null;
+ if ($post && $post->getBlog()) {
+ $selected_value = $post->getBlog()->getID();
+ }
$form = id(new AphrontFormView())
->setUser($user)
- ->setMethod('GET')
->setFlexible(true)
- ->setAction($this->getApplicationURI('post/edit/'))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel('Blog')
->setName('blog')
- ->setOptions($options))
- ->appendChild(
- id(new AphrontFormSubmitControl())
- ->setValue('Continue'));
+ ->setOptions($options)
+ ->setValue($selected_value));
+
+ if ($post) {
+ $form
+ ->appendChild(
+ id(new AphrontFormSubmitControl())
+ ->setValue(pht('Move Post'))
+ ->addCancelButton($view_uri));
+ } else {
+ $form
+ ->setAction($this->getApplicationURI('post/edit/'))
+ ->setMethod('GET')
+ ->appendChild(
+ id(new AphrontFormSubmitControl())
+ ->setValue(pht('Continue')));
+ }
$nav->appendChild($form);
}
@@ -70,7 +133,7 @@ final class PhamePostNewController extends PhameController {
return $this->buildApplicationPage(
$nav,
array(
- 'title' => 'Create Post',
+ 'title' => $title,
'device' => true,
));
}
diff --git a/src/applications/phame/controller/post/PhamePostNotLiveController.php b/src/applications/phame/controller/post/PhamePostNotLiveController.php
index 9676a11ad8..8d5cb3715b 100644
--- a/src/applications/phame/controller/post/PhamePostNotLiveController.php
+++ b/src/applications/phame/controller/post/PhamePostNotLiveController.php
@@ -43,8 +43,8 @@ final class PhamePostNotLiveController extends PhameController {
if (!$post->getBlog()) {
$reasons[] =
''.pht('You can not view the live version of this post because it '.
- 'is not associated with a blog. Edit the post and choose a blog to '.
- 'publish it to.').'
';
+ 'is not associated with a blog. Move the post to a blog in order to '.
+ 'view it live.').'
';
}
if ($post->isDraft()) {
diff --git a/src/applications/phame/controller/post/PhamePostViewController.php b/src/applications/phame/controller/post/PhamePostViewController.php
index affbfbda81..626a1704c4 100644
--- a/src/applications/phame/controller/post/PhamePostViewController.php
+++ b/src/applications/phame/controller/post/PhamePostViewController.php
@@ -40,28 +40,30 @@ final class PhamePostViewController extends PhameController {
return new Aphront404Response();
}
+ $nav = $this->renderSideNavFilterView();
+
+ $nav->appendChild(
+ id(new PhabricatorHeaderView())
+ ->setHeader($post->getTitle()));
+
if ($post->isDraft()) {
- $notice = array(
- 'title' => 'You are previewing a draft.',
- 'body' => 'Only you can see this draft until you publish it. '.
- 'If you chose a comment widget it will show up when '.
- 'you publish.'
- );
- } else if ($request->getExists('saved')) {
- $new_link = phutil_render_tag(
- 'a',
- array(
- 'href' => '/phame/post/new/',
- 'class' => 'button green',
- ),
- 'write another blog post'
- );
- $notice = array(
- 'title' => 'Saved post successfully.',
- 'body' => 'Seek even more phame and '.$new_link.'.'
- );
- } else {
- $notice = array();
+ $nav->appendChild(
+ id(new AphrontErrorView())
+ ->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
+ ->setTitle(pht('Draft Post'))
+ ->appendChild(
+ pht('Only you can see this draft until you publish it. '.
+ 'Use "Preview / Publish" to publish this post.')));
+ }
+
+ if (!$post->getBlog()) {
+ $nav->appendChild(
+ id(new AphrontErrorView())
+ ->setSeverity(AphrontErrorView::SEVERITY_WARNING)
+ ->setTitle(pht('Not On A Blog'))
+ ->appendChild(
+ pht('This post is not associated with a blog (the blog may have '.
+ 'been deleted). Use "Move Post" to move it to a new blog.')));
}
$this->loadHandles(
@@ -70,16 +72,11 @@ final class PhamePostViewController extends PhameController {
$post->getBloggerPHID(),
));
- $nav = $this->renderSideNavFilterView(null);
-
- $header = id(new PhabricatorHeaderView())->setHeader($post->getTitle());
-
$actions = $this->renderActions($post, $user);
$properties = $this->renderProperties($post, $user);
$nav->appendChild(
array(
- $header,
$actions,
$properties,
));
@@ -115,6 +112,37 @@ final class PhamePostViewController extends PhameController {
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
+ $actions->addAction(
+ id(new PhabricatorActionView())
+ ->setIcon('move')
+ ->setHref($this->getApplicationURI('post/move/'.$id.'/'))
+ ->setName('Move Post')
+ ->setDisabled(!$can_edit)
+ ->setWorkflow(!$can_edit));
+
+ if ($post->isDraft()) {
+ $actions->addAction(
+ id(new PhabricatorActionView())
+ ->setIcon('preview')
+ ->setHref($this->getApplicationURI('post/publish/'.$id.'/'))
+ ->setName(pht('Preview / Publish')));
+ } else {
+ $actions->addAction(
+ id(new PhabricatorActionView())
+ ->setIcon('unpublish')
+ ->setHref($this->getApplicationURI('post/unpublish/'.$id.'/'))
+ ->setName(pht('Unpublish'))
+ ->setWorkflow(true));
+ }
+
+ $actions->addAction(
+ id(new PhabricatorActionView())
+ ->setIcon('delete')
+ ->setHref($this->getApplicationURI('post/delete/'.$id.'/'))
+ ->setName('Delete Post')
+ ->setDisabled(!$can_edit)
+ ->setWorkflow(true));
+
$blog = $post->getBlog();
$can_view_live = $blog && !$post->isDraft();
@@ -133,29 +161,6 @@ final class PhamePostViewController extends PhameController {
->setDisabled(!$can_view_live)
->setWorkflow(!$can_view_live));
- if ($post->isDraft()) {
- $actions->addAction(
- id(new PhabricatorActionView())
- ->setIcon('world')
- ->setHref($this->getApplicationURI('post/publish/'.$id.'/'))
- ->setName(pht('Preview / Publish')));
- } else {
- $actions->addAction(
- id(new PhabricatorActionView())
- ->setIcon('delete')
- ->setHref($this->getApplicationURI('post/unpublish/'.$id.'/'))
- ->setName(pht('Unpublish'))
- ->setWorkflow(true));
- }
-
- $actions->addAction(
- id(new PhabricatorActionView())
- ->setIcon('delete')
- ->setHref($this->getApplicationURI('post/delete/'.$id.'/'))
- ->setName('Delete Post')
- ->setDisabled(!$can_edit)
- ->setWorkflow(true));
-
return $actions;
}
diff --git a/src/view/form/AphrontErrorView.php b/src/view/form/AphrontErrorView.php
index f68dc129cd..dce3e9a974 100644
--- a/src/view/form/AphrontErrorView.php
+++ b/src/view/form/AphrontErrorView.php
@@ -89,20 +89,19 @@ final class AphrontErrorView extends AphrontView {
$more_classes[] = 'aphront-error-severity-'.$this->severity;
$more_classes = implode(' ', $more_classes);
- return
+ return phutil_render_tag(
+ 'div',
+ array(
+ 'id' => $this->id,
+ 'class' => 'aphront-error-view '.$more_classes,
+ ),
+ $title.
phutil_render_tag(
'div',
array(
- 'id' => $this->id,
- 'class' => 'aphront-error-view '.$more_classes,
+ 'class' => 'aphront-error-view-body',
),
- $title.
- phutil_render_tag(
- 'div',
- array(
- 'class' => 'aphront-error-view-body',
- ),
- $this->renderChildren().
- $list));
+ $this->renderChildren().
+ $list));
}
}
diff --git a/webroot/rsrc/css/aphront/error-view.css b/webroot/rsrc/css/aphront/error-view.css
index 02056f45cf..21f6e36156 100644
--- a/webroot/rsrc/css/aphront/error-view.css
+++ b/webroot/rsrc/css/aphront/error-view.css
@@ -66,3 +66,4 @@
.aphront-error-severity-nodata .aphront-error-view-head {
background: #e3e3e3;
}
+
diff --git a/webroot/rsrc/css/autosprite.css b/webroot/rsrc/css/autosprite.css
index e26de1e87e..5b93e88883 100644
--- a/webroot/rsrc/css/autosprite.css
+++ b/webroot/rsrc/css/autosprite.css
@@ -760,38 +760,50 @@
background-position: 0px -7359px;
}
-.remarkup-assist-b {
+.action-move {
background-position: 0px -7376px;
}
+.action-preview {
+ background-position: 0px -7393px;
+}
+
+.action-unpublish {
+ background-position: 0px -7410px;
+}
+
+.remarkup-assist-b {
+ background-position: 0px -7427px;
+}
+
.remarkup-assist-code {
- background-position: 0px -7391px;
+ background-position: 0px -7442px;
}
.remarkup-assist-i {
- background-position: 0px -7406px;
+ background-position: 0px -7457px;
}
.remarkup-assist-image {
- background-position: 0px -7421px;
+ background-position: 0px -7472px;
}
.remarkup-assist-ol {
- background-position: 0px -7436px;
+ background-position: 0px -7487px;
}
.remarkup-assist-tag {
- background-position: 0px -7451px;
+ background-position: 0px -7502px;
}
.remarkup-assist-tt {
- background-position: 0px -7466px;
+ background-position: 0px -7517px;
}
.remarkup-assist-ul {
- background-position: 0px -7481px;
+ background-position: 0px -7532px;
}
.remarkup-assist-help {
- background-position: 0px -7496px;
+ background-position: 0px -7547px;
}
diff --git a/webroot/rsrc/css/layout/phabricator-action-list-view.css b/webroot/rsrc/css/layout/phabricator-action-list-view.css
index 80083e448a..a8d7ce03d2 100644
--- a/webroot/rsrc/css/layout/phabricator-action-list-view.css
+++ b/webroot/rsrc/css/layout/phabricator-action-list-view.css
@@ -11,7 +11,7 @@
padding: .5em 0;
float: right;
- margin-top: -30px;
+ margin-top: 0px;
margin-right: 1%;
width: 20%;
border-radius: 2px;
diff --git a/webroot/rsrc/css/layout/phabricator-property-list-view.css b/webroot/rsrc/css/layout/phabricator-property-list-view.css
index 22f3affe7a..dec6656600 100644
--- a/webroot/rsrc/css/layout/phabricator-property-list-view.css
+++ b/webroot/rsrc/css/layout/phabricator-property-list-view.css
@@ -66,3 +66,27 @@
.phabricator-property-list-text-content {
padding: 12px 18px;
}
+
+/* When we follow an action list view on the Desktop, move down 30px so the
+ action list can start slightly above the property list. This is an unusual
+ case where we have something between the header and the action/property
+ lists and we want to give it space. */
+.device-desktop .phabricator-action-list-view +
+ .phabricator-property-list-view {
+ clear: left;
+ margin-top: 30px;
+}
+
+
+/* In the common case where we immediately follow a header, move back up 30px
+ so we snuggle next to the header. */
+.device-desktop .phabricator-header-view
+ + .phabricator-action-list-view {
+ margin-top: -30px;
+}
+
+.device-desktop .phabricator-header-view
+ + .phabricator-action-list-view
+ + .phabricator-property-list-view {
+ margin-top: 0px;
+}
diff --git a/webroot/rsrc/image/autosprite.png b/webroot/rsrc/image/autosprite.png
index 35b9978462331503b68147e952b1cc66fd37e7e6..89a7ff31adbcbdc2ddf30e17890916d5d8d90c0b 100644
GIT binary patch
delta 6255
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
Z@_%8FNdd3y%w7Nh002ovPDHLkV1mjb7xw@F
delta 5002
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
Ug+S0)z5oCK07*qoM6N<$f^zb~sQ>@~