mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-22 14:52:41 +01:00
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
This commit is contained in:
parent
9b15aa195e
commit
1a63938b33
13 changed files with 192 additions and 84 deletions
|
@ -220,7 +220,10 @@ $action_map = array(
|
||||||
'subscribe-delete' => 'icon/unsubscribe.png',
|
'subscribe-delete' => 'icon/unsubscribe.png',
|
||||||
'new' => 'icon/page_white_put.png',
|
'new' => 'icon/page_white_put.png',
|
||||||
'world' => 'icon/world.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) {
|
foreach ($action_map as $icon => $source) {
|
||||||
|
|
|
@ -59,6 +59,7 @@ final class PhabricatorApplicationPhame extends PhabricatorApplication {
|
||||||
'preview/' => 'PhamePostPreviewController',
|
'preview/' => 'PhamePostPreviewController',
|
||||||
'framed/(?P<id>\d+)/' => 'PhamePostFramedController',
|
'framed/(?P<id>\d+)/' => 'PhamePostFramedController',
|
||||||
'new/' => 'PhamePostNewController',
|
'new/' => 'PhamePostNewController',
|
||||||
|
'move/(?P<id>\d+)/' => 'PhamePostNewController'
|
||||||
),
|
),
|
||||||
'blog/' => array(
|
'blog/' => array(
|
||||||
'(?:(?P<filter>user|all)/)?' => 'PhameBlogListController',
|
'(?:(?P<filter>user|all)/)?' => 'PhameBlogListController',
|
||||||
|
|
|
@ -80,7 +80,7 @@ final class PhameBlogEditController
|
||||||
|
|
||||||
$blog->setName($name);
|
$blog->setName($name);
|
||||||
$blog->setDescription($description);
|
$blog->setDescription($description);
|
||||||
$blog->setDomain($custom_domain);
|
$blog->setDomain(nonempty($custom_domain, null));
|
||||||
$blog->setSkin($skin);
|
$blog->setSkin($skin);
|
||||||
|
|
||||||
if (!empty($custom_domain)) {
|
if (!empty($custom_domain)) {
|
||||||
|
|
|
@ -139,7 +139,7 @@ final class PhameBlogViewController extends PhameController {
|
||||||
$actions->addAction(
|
$actions->addAction(
|
||||||
id(new PhabricatorActionView())
|
id(new PhabricatorActionView())
|
||||||
->setIcon('new')
|
->setIcon('new')
|
||||||
->setHref($this->getApplicationURI('post/new/?blog='.$blog->getID()))
|
->setHref($this->getApplicationURI('post/edit/?blog='.$blog->getID()))
|
||||||
->setName(pht('Write Post'))
|
->setName(pht('Write Post'))
|
||||||
->setDisabled(!$can_join)
|
->setDisabled(!$can_join)
|
||||||
->setWorkflow(!$can_join));
|
->setWorkflow(!$can_join));
|
||||||
|
|
|
@ -21,10 +21,57 @@
|
||||||
*/
|
*/
|
||||||
final class PhamePostNewController extends PhameController {
|
final class PhamePostNewController extends PhameController {
|
||||||
|
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
public function willProcessRequest(array $data) {
|
||||||
|
$this->id = idx($data, 'id');
|
||||||
|
}
|
||||||
|
|
||||||
public function processRequest() {
|
public function processRequest() {
|
||||||
$request = $this->getRequest();
|
$request = $this->getRequest();
|
||||||
$user = $request->getUser();
|
$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())
|
$blogs = id(new PhameBlogQuery())
|
||||||
->setViewer($user)
|
->setViewer($user)
|
||||||
->requireCapabilities(
|
->requireCapabilities(
|
||||||
|
@ -36,8 +83,7 @@ final class PhamePostNewController extends PhameController {
|
||||||
$nav = $this->renderSideNavFilterView();
|
$nav = $this->renderSideNavFilterView();
|
||||||
$nav->selectFilter('post/new');
|
$nav->selectFilter('post/new');
|
||||||
$nav->appendChild(
|
$nav->appendChild(
|
||||||
id(new PhabricatorHeaderView())->setHeader(
|
id(new PhabricatorHeaderView())->setHeader($title));
|
||||||
pht('Create Post')));
|
|
||||||
|
|
||||||
if (!$blogs) {
|
if (!$blogs) {
|
||||||
$notification = id(new AphrontErrorView())
|
$notification = id(new AphrontErrorView())
|
||||||
|
@ -49,20 +95,37 @@ final class PhamePostNewController extends PhameController {
|
||||||
$nav->appendChild($notification);
|
$nav->appendChild($notification);
|
||||||
} else {
|
} else {
|
||||||
$options = mpull($blogs, 'getName', 'getID');
|
$options = mpull($blogs, 'getName', 'getID');
|
||||||
|
asort($options);
|
||||||
|
|
||||||
|
$selected_value = null;
|
||||||
|
if ($post && $post->getBlog()) {
|
||||||
|
$selected_value = $post->getBlog()->getID();
|
||||||
|
}
|
||||||
|
|
||||||
$form = id(new AphrontFormView())
|
$form = id(new AphrontFormView())
|
||||||
->setUser($user)
|
->setUser($user)
|
||||||
->setMethod('GET')
|
|
||||||
->setFlexible(true)
|
->setFlexible(true)
|
||||||
->setAction($this->getApplicationURI('post/edit/'))
|
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormSelectControl())
|
id(new AphrontFormSelectControl())
|
||||||
->setLabel('Blog')
|
->setLabel('Blog')
|
||||||
->setName('blog')
|
->setName('blog')
|
||||||
->setOptions($options))
|
->setOptions($options)
|
||||||
->appendChild(
|
->setValue($selected_value));
|
||||||
id(new AphrontFormSubmitControl())
|
|
||||||
->setValue('Continue'));
|
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);
|
$nav->appendChild($form);
|
||||||
}
|
}
|
||||||
|
@ -70,7 +133,7 @@ final class PhamePostNewController extends PhameController {
|
||||||
return $this->buildApplicationPage(
|
return $this->buildApplicationPage(
|
||||||
$nav,
|
$nav,
|
||||||
array(
|
array(
|
||||||
'title' => 'Create Post',
|
'title' => $title,
|
||||||
'device' => true,
|
'device' => true,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,8 +43,8 @@ final class PhamePostNotLiveController extends PhameController {
|
||||||
if (!$post->getBlog()) {
|
if (!$post->getBlog()) {
|
||||||
$reasons[] =
|
$reasons[] =
|
||||||
'<p>'.pht('You can not view the live version of this post because it '.
|
'<p>'.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 '.
|
'is not associated with a blog. Move the post to a blog in order to '.
|
||||||
'publish it to.').'</p>';
|
'view it live.').'</p>';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($post->isDraft()) {
|
if ($post->isDraft()) {
|
||||||
|
|
|
@ -40,28 +40,30 @@ final class PhamePostViewController extends PhameController {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$nav = $this->renderSideNavFilterView();
|
||||||
|
|
||||||
|
$nav->appendChild(
|
||||||
|
id(new PhabricatorHeaderView())
|
||||||
|
->setHeader($post->getTitle()));
|
||||||
|
|
||||||
if ($post->isDraft()) {
|
if ($post->isDraft()) {
|
||||||
$notice = array(
|
$nav->appendChild(
|
||||||
'title' => 'You are previewing a draft.',
|
id(new AphrontErrorView())
|
||||||
'body' => 'Only you can see this draft until you publish it. '.
|
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
|
||||||
'If you chose a comment widget it will show up when '.
|
->setTitle(pht('Draft Post'))
|
||||||
'you publish.'
|
->appendChild(
|
||||||
);
|
pht('Only you can see this draft until you publish it. '.
|
||||||
} else if ($request->getExists('saved')) {
|
'Use "Preview / Publish" to publish this post.')));
|
||||||
$new_link = phutil_render_tag(
|
}
|
||||||
'a',
|
|
||||||
array(
|
if (!$post->getBlog()) {
|
||||||
'href' => '/phame/post/new/',
|
$nav->appendChild(
|
||||||
'class' => 'button green',
|
id(new AphrontErrorView())
|
||||||
),
|
->setSeverity(AphrontErrorView::SEVERITY_WARNING)
|
||||||
'write another blog post'
|
->setTitle(pht('Not On A Blog'))
|
||||||
);
|
->appendChild(
|
||||||
$notice = array(
|
pht('This post is not associated with a blog (the blog may have '.
|
||||||
'title' => 'Saved post successfully.',
|
'been deleted). Use "Move Post" to move it to a new blog.')));
|
||||||
'body' => 'Seek even more phame and '.$new_link.'.'
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$notice = array();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->loadHandles(
|
$this->loadHandles(
|
||||||
|
@ -70,16 +72,11 @@ final class PhamePostViewController extends PhameController {
|
||||||
$post->getBloggerPHID(),
|
$post->getBloggerPHID(),
|
||||||
));
|
));
|
||||||
|
|
||||||
$nav = $this->renderSideNavFilterView(null);
|
|
||||||
|
|
||||||
$header = id(new PhabricatorHeaderView())->setHeader($post->getTitle());
|
|
||||||
|
|
||||||
$actions = $this->renderActions($post, $user);
|
$actions = $this->renderActions($post, $user);
|
||||||
$properties = $this->renderProperties($post, $user);
|
$properties = $this->renderProperties($post, $user);
|
||||||
|
|
||||||
$nav->appendChild(
|
$nav->appendChild(
|
||||||
array(
|
array(
|
||||||
$header,
|
|
||||||
$actions,
|
$actions,
|
||||||
$properties,
|
$properties,
|
||||||
));
|
));
|
||||||
|
@ -115,6 +112,37 @@ final class PhamePostViewController extends PhameController {
|
||||||
->setDisabled(!$can_edit)
|
->setDisabled(!$can_edit)
|
||||||
->setWorkflow(!$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();
|
$blog = $post->getBlog();
|
||||||
$can_view_live = $blog && !$post->isDraft();
|
$can_view_live = $blog && !$post->isDraft();
|
||||||
|
|
||||||
|
@ -133,29 +161,6 @@ final class PhamePostViewController extends PhameController {
|
||||||
->setDisabled(!$can_view_live)
|
->setDisabled(!$can_view_live)
|
||||||
->setWorkflow(!$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;
|
return $actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,20 +89,19 @@ final class AphrontErrorView extends AphrontView {
|
||||||
$more_classes[] = 'aphront-error-severity-'.$this->severity;
|
$more_classes[] = 'aphront-error-severity-'.$this->severity;
|
||||||
$more_classes = implode(' ', $more_classes);
|
$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(
|
phutil_render_tag(
|
||||||
'div',
|
'div',
|
||||||
array(
|
array(
|
||||||
'id' => $this->id,
|
'class' => 'aphront-error-view-body',
|
||||||
'class' => 'aphront-error-view '.$more_classes,
|
|
||||||
),
|
),
|
||||||
$title.
|
$this->renderChildren().
|
||||||
phutil_render_tag(
|
$list));
|
||||||
'div',
|
|
||||||
array(
|
|
||||||
'class' => 'aphront-error-view-body',
|
|
||||||
),
|
|
||||||
$this->renderChildren().
|
|
||||||
$list));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,3 +66,4 @@
|
||||||
.aphront-error-severity-nodata .aphront-error-view-head {
|
.aphront-error-severity-nodata .aphront-error-view-head {
|
||||||
background: #e3e3e3;
|
background: #e3e3e3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -760,38 +760,50 @@
|
||||||
background-position: 0px -7359px;
|
background-position: 0px -7359px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.remarkup-assist-b {
|
.action-move {
|
||||||
background-position: 0px -7376px;
|
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 {
|
.remarkup-assist-code {
|
||||||
background-position: 0px -7391px;
|
background-position: 0px -7442px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.remarkup-assist-i {
|
.remarkup-assist-i {
|
||||||
background-position: 0px -7406px;
|
background-position: 0px -7457px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.remarkup-assist-image {
|
.remarkup-assist-image {
|
||||||
background-position: 0px -7421px;
|
background-position: 0px -7472px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.remarkup-assist-ol {
|
.remarkup-assist-ol {
|
||||||
background-position: 0px -7436px;
|
background-position: 0px -7487px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.remarkup-assist-tag {
|
.remarkup-assist-tag {
|
||||||
background-position: 0px -7451px;
|
background-position: 0px -7502px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.remarkup-assist-tt {
|
.remarkup-assist-tt {
|
||||||
background-position: 0px -7466px;
|
background-position: 0px -7517px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.remarkup-assist-ul {
|
.remarkup-assist-ul {
|
||||||
background-position: 0px -7481px;
|
background-position: 0px -7532px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.remarkup-assist-help {
|
.remarkup-assist-help {
|
||||||
background-position: 0px -7496px;
|
background-position: 0px -7547px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
padding: .5em 0;
|
padding: .5em 0;
|
||||||
|
|
||||||
float: right;
|
float: right;
|
||||||
margin-top: -30px;
|
margin-top: 0px;
|
||||||
margin-right: 1%;
|
margin-right: 1%;
|
||||||
width: 20%;
|
width: 20%;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
|
|
|
@ -66,3 +66,27 @@
|
||||||
.phabricator-property-list-text-content {
|
.phabricator-property-list-text-content {
|
||||||
padding: 12px 18px;
|
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;
|
||||||
|
}
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 143 KiB |
Loading…
Reference in a new issue