0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-24 23:48:13 -05:00

Merge pull request #4858 from PaulAdamDavis/nav-drag-order

Drag & Drop Navigation Reordering
This commit is contained in:
Matt Enlow 2015-02-13 11:26:34 -07:00
commit 920c80e908
8 changed files with 89 additions and 10 deletions

View file

@ -394,18 +394,33 @@
display: flex; display: flex;
@media (max-width: 600px) { @media (max-width: 600px) {
position: relative;
margin-bottom: 20px; margin-bottom: 20px;
} }
@media (min-width: 601px) { @media (min-width: 601px) {
margin-bottom: 10px; margin-bottom: 10px;
} }
// &.last-navigation-item {
&:last-child {
padding-left: 27px; // .navigation-item-drag-handle width + horizontal padding
}
} }
.navigation-item-drag-handle { .navigation-item-drag-handle {
padding-left: 10px; padding: 6px 17px 0 10px;
padding-right: 17px;
width: 27px; width: 27px;
cursor: move; cursor: move;
@media (max-width: 600px) {
&:before {
position: absolute;
top: 50%;
left: 4px;
margin-top: -9px;
z-index: 20;
}
}
} }
.navigation-inputs { .navigation-inputs {
@ -449,6 +464,7 @@
padding-left: 10px; padding-left: 10px;
width: 40px; width: 40px;
position: relative; position: relative;
z-index: 10;
button { button {
width: 30px; width: 30px;

View file

@ -187,6 +187,7 @@ select {
width: 100%; width: 100%;
border: 1px solid #E0DFD7; border: 1px solid #E0DFD7;
border-radius: $border-radius; border-radius: $border-radius;
-webkit-appearance: none;
font-size: 1.4rem; font-size: 1.4rem;
font-weight: normal; font-weight: normal;

View file

@ -1,6 +1,9 @@
var NavItemComponent = Ember.Component.extend({ var NavItemComponent = Ember.Component.extend({
classNames: 'navigation-item', classNames: 'navigation-item',
attributeBindings: ['order:data-order'],
order: Ember.computed.readOnly('navItem.order'),
keyPress: function (event) { keyPress: function (event) {
// enter key // enter key
if (event.keyCode === 13) { if (event.keyCode === 13) {

View file

@ -4,6 +4,7 @@ var NavigationController,
NavItem = Ember.Object.extend({ NavItem = Ember.Object.extend({
label: '', label: '',
url: '', url: '',
order: '',
isComplete: Ember.computed('label', 'url', function () { isComplete: Ember.computed('label', 'url', function () {
return !(Ember.isBlank(this.get('label')) || Ember.isBlank(this.get('url'))); return !(Ember.isBlank(this.get('label')) || Ember.isBlank(this.get('url')));
@ -31,6 +32,8 @@ NavigationController = Ember.Controller.extend({
return NavItem.create(item); return NavItem.create(item);
}); });
navItems.sortBy('order');
lastItem = navItems.get('lastObject'); lastItem = navItems.get('lastObject');
if (!lastItem || lastItem.get('isComplete')) { if (!lastItem || lastItem.get('isComplete')) {
navItems.addObject(NavItem.create()); navItems.addObject(NavItem.create());
@ -51,13 +54,24 @@ NavigationController = Ember.Controller.extend({
}); });
}), }),
updateOrder: function (indexes) {
var navItems = this.get('navigationItems'),
order = 0;
indexes.forEach(function (index) {
navItems[index].set('order', order);
order = order + 1; // Increment order order by one
});
},
actions: { actions: {
addItem: function () { addItem: function () {
var navItems = this.get('navigationItems'), var navItems = this.get('navigationItems'),
lastItem = navItems.get('lastObject'); lastItem = navItems.get('lastObject');
if (lastItem && lastItem.get('isComplete')) { if (lastItem && lastItem.get('isComplete')) {
navItems.addObject(NavItem.create()); lastItem.set('order', (navItems.length - 1)); // -1 because order is 0-index, length is 1-index
navItems.addObject(NavItem.create()); // Adds new blank navItem
} }
}, },
@ -67,6 +81,14 @@ NavigationController = Ember.Controller.extend({
} }
this.get('navigationItems').removeObject(item); this.get('navigationItems').removeObject(item);
var navItems = this.get('navigationItems'),
order = 0;
navItems.forEach(function (item) {
item.set('order', order);
order = order + 1; // Increment order order by one
});
}, },
updateUrl: function (url, navItem) { updateUrl: function (url, navItem) {
@ -92,7 +114,8 @@ NavigationController = Ember.Controller.extend({
navSetting = this.get('navigationItems').map(function (item) { navSetting = this.get('navigationItems').map(function (item) {
var label, var label,
url; url,
order;
if (!item || !item.get('isComplete')) { if (!item || !item.get('isComplete')) {
return; return;
@ -100,6 +123,7 @@ NavigationController = Ember.Controller.extend({
label = item.get('label').trim(); label = item.get('label').trim();
url = item.get('url').trim(); url = item.get('url').trim();
order = item.get('order');
match = url.match(blogUrlRegex); match = url.match(blogUrlRegex);
@ -118,9 +142,14 @@ NavigationController = Ember.Controller.extend({
return; return;
} }
return {label: label, url: url}; return {label: label, url: url, order: order};
}).compact(); }).compact();
// Sort JSON so nav items are stored in the correct order order
navSetting.sort(function (a, b) {
return a.order - b.order;
});
this.set('model.navigation', JSON.stringify(navSetting)); this.set('model.navigation', JSON.stringify(navSetting));
// trigger change event because even if the final JSON is unchanged // trigger change event because even if the final JSON is unchanged

View file

@ -1,10 +1,13 @@
import AuthenticatedRoute from 'ghost/routes/authenticated'; import AuthenticatedRoute from 'ghost/routes/authenticated';
import CurrentUserSettings from 'ghost/mixins/current-user-settings'; import CurrentUserSettings from 'ghost/mixins/current-user-settings';
import styleBody from 'ghost/mixins/style-body';
var NavigationRoute = AuthenticatedRoute.extend(CurrentUserSettings, { var NavigationRoute = AuthenticatedRoute.extend(styleBody, CurrentUserSettings, {
titleToken: 'Navigation', titleToken: 'Navigation',
classNames: ['settings-view-navigation'],
beforeModel: function () { beforeModel: function () {
if (!this.get('config.navigationUI')) { if (!this.get('config.navigationUI')) {
return this.transitionTo('settings.general'); return this.transitionTo('settings.general');

View file

@ -1,6 +1,8 @@
<button type="button" class="navigation-item-drag-handle icon-grab"> {{#unless navItem.last}}
<span class="navigation-item-drag-handle icon-grab">
<span class="hidden">Reorder</span> <span class="hidden">Reorder</span>
</button> </span>
{{/unless}}
<div class="navigation-inputs"> <div class="navigation-inputs">
<span class="navigation-item-label"> <span class="navigation-item-label">
{{gh-trim-focus-input focus=navItem.last placeholder="Label" value=navItem.label}} {{gh-trim-focus-input focus=navItem.last placeholder="Label" value=navItem.label}}

View file

@ -7,7 +7,7 @@
</header> </header>
<section class="content settings-navigation"> <section class="content settings-navigation">
<form id="settings-navigation" novalidate="novalidate"> <form id="settings-navigation" class="js-settings-navigation" novalidate="novalidate">
{{#each navItem in navigationItems}} {{#each navItem in navigationItems}}
{{gh-navitem navItem=navItem baseUrl=blogUrl addItem="addItem" deleteItem="deleteItem" updateUrl="updateUrl"}} {{gh-navitem navItem=navItem baseUrl=blogUrl addItem="addItem" deleteItem="deleteItem" updateUrl="updateUrl"}}
{{/each}} {{/each}}

View file

@ -1,6 +1,31 @@
import BaseView from 'ghost/views/settings/content-base'; import BaseView from 'ghost/views/settings/content-base';
var SettingsNavigationView = BaseView.extend({ var SettingsNavigationView = BaseView.extend({
didInsertElement: function () {
var controller = this.get('controller'),
navContainer = Ember.$('.js-settings-navigation'),
navElements = '.navigation-item:not(.navigation-item:last-child)';
navContainer.sortable({
handle: '.navigation-item-drag-handle',
items: navElements,
update: function () {
var indexes = [];
navContainer.find(navElements).each(function () {
var order = Ember.$(this).data('order');
indexes.push(order);
});
controller.updateOrder(indexes);
}
});
},
willDestroyElement: function () {
Ember.$('.js-settings-navigation').sortable('destroy');
}
}); });
export default SettingsNavigationView; export default SettingsNavigationView;