Skip to content

Commit e6629aa

Browse files
committed
合并官方更新 & 升级到 0.5.7
2 parents da09e76 + 1c452a6 commit e6629aa

68 files changed

Lines changed: 1083 additions & 478 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎CONTRIBUTING.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,11 @@ reported. Especially, why do you consider this to be a bug? What do you expect t
9494
9595
### Technical details:
9696
97-
* Ghost Version: master (latest commit: 590ba48988b51b9c5e8d99afbb84c997436d7f21)
98-
* Client OS: Mac OS X 10.8.4
97+
* Ghost Version: master (latest commit: a761de2079dca4df49567b1bddac492f25033985)
98+
* Client OS: Mac OS X 10.10.1
9999
* Server OS: CentOS 6.4
100100
* Node Version: 0.10.16
101-
* Browser: Chrome 29.0.1547.57
101+
* Browser: Chrome 39.0.2171.71
102102
* Database: SQLite / MySQL / postgres
103103
```
104104

‎core/client/assets/lib/uploader.js‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,10 @@ UploadUi = function ($dropzone, settings) {
151151

152152
$dropzone.find('img.js-upload-target').css({'display': 'none'});
153153

154+
// This is the start point if no image exists
155+
$dropzone.find('img.js-upload-target').css({display: 'none'});
156+
$dropzone.find('div.description').show();
157+
154158
$dropzone.removeClass('pre-image-uploader image-uploader-url').addClass('image-uploader');
155159
this.removeExtras();
156160
this.buildExtras();
@@ -177,6 +181,7 @@ UploadUi = function ($dropzone, settings) {
177181
$dropzone.find('.js-cancel').on('click', function () {
178182
$dropzone.find('.js-url').remove();
179183
$dropzone.find('.js-fileupload').removeClass('right');
184+
$dropzone.trigger('imagecleared');
180185
self.removeExtras();
181186
self.initWithDropzone();
182187
});
@@ -222,11 +227,14 @@ UploadUi = function ($dropzone, settings) {
222227

223228
// This is the start point if an image already exists
224229
$dropzone.removeClass('image-uploader image-uploader-url').addClass('pre-image-uploader');
225-
//$dropzone.find('div.description').hide();
230+
231+
$dropzone.find('div.description').hide();
232+
$dropzone.find('img.js-upload-target').show();
226233
$dropzone.append($cancel);
227234
$dropzone.find('.js-cancel').on('click', function () {
228235
$dropzone.find('img.js-upload-target').attr({src: ''});
229236
$dropzone.find('div.description').show();
237+
$dropzone.trigger('imagecleared');
230238
$dropzone.delay(2500).animate({opacity: 100}, 1000, function () {
231239
self.init();
232240
});

‎core/client/assets/sass/components/modals.scss‎

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@
124124

125125
.modal-header {
126126
position: relative;
127+
margin-bottom: 18px;
127128

128129
h1 {
129130
display: inline-block;
@@ -136,6 +137,10 @@
136137
.modal-body {
137138
position: relative;
138139
overflow-y: auto;
140+
141+
.red {
142+
color: $red;
143+
}
139144
}
140145

141146
.modal-footer {
@@ -160,4 +165,39 @@
160165

161166
.modal-style-centered {
162167
text-align: center;
163-
}
168+
}
169+
170+
// Modal login styles
171+
.modal-body .login-form {
172+
display: block; // Override inherited `display: table-cell;`
173+
174+
.password-wrap {
175+
input {
176+
width: 100%;
177+
}
178+
}
179+
180+
@media (max-width: 900px) {
181+
margin: 0 auto;
182+
max-width: 264px;
183+
184+
.password-wrap {
185+
width: 100%;
186+
margin: 0 auto 1em;
187+
}
188+
189+
.btn {
190+
margin: 0;
191+
width: 100%;
192+
margin-bottom: 1em;
193+
}
194+
}
195+
196+
@media (min-width: 901px) {
197+
display: flex;
198+
199+
.password-wrap {
200+
flex: 1;
201+
}
202+
}
203+
}
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
var ActivatingListItem = Ember.Component.extend({
22
tagName: 'li',
33
classNameBindings: ['active'],
4-
active: false
4+
active: false,
5+
6+
unfocusLink: function () {
7+
this.$('a').blur();
8+
}.on('click')
59
});
610

711
export default ActivatingListItem;

‎core/client/components/gh-uploader.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ var PostImageUploader = Ember.Component.extend({
1818
}
1919
});
2020

21-
$this.find('.js-cancel').on('click', function () {
21+
$this.on('imagecleared', function () {
2222
self.sendAction('canceled');
2323
});
2424
}.on('didInsertElement'),

‎core/client/controllers/modals/delete-all.js‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ var DeleteAllController = Ember.Controller.extend({
77
type: 'DELETE'
88
}).then(function () {
99
self.notifications.showSuccess('All content deleted from database.');
10+
self.store.unloadAll('post');
11+
self.store.unloadAll('tag');
1012
}).catch(function (response) {
1113
self.notifications.showErrors(response);
1214
});

‎core/client/controllers/modals/delete-user.js‎

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,24 @@
1-
var DeleteUserController = Ember.Controller.extend({
1+
var DeleteUserController = Ember.ObjectController.extend({
2+
userPostCount: Ember.computed('id', function () {
3+
var promise,
4+
query = {
5+
author: this.get('slug'),
6+
status: 'all'
7+
};
8+
9+
promise = this.store.find('post', query).then(function (results) {
10+
return results.meta.pagination.total;
11+
});
12+
13+
return Ember.Object.extend(Ember.PromiseProxyMixin, {
14+
count: Ember.computed.alias('content'),
15+
16+
inflection: Ember.computed('count', function () {
17+
return this.get('count') > 1 ? 'posts' : 'post';
18+
})
19+
}).create({promise: promise});
20+
}),
21+
222
actions: {
323
confirmAccept: function () {
424
var self = this,
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import SigninController from 'ghost/controllers/signin';
2+
3+
export default SigninController.extend({
4+
needs: 'application',
5+
6+
identification: Ember.computed('session.user.email', function () {
7+
return this.get('session.user.email');
8+
}),
9+
10+
actions: {
11+
authenticate: function () {
12+
var appController = this.get('controllers.application'),
13+
self = this;
14+
15+
appController.set('skipAuthSuccessHandler', true);
16+
17+
this._super().then(function () {
18+
self.send('closeModal');
19+
self.notifications.showSuccess('Login successful.');
20+
self.set('password', '');
21+
}).finally(function () {
22+
appController.set('skipAuthSuccessHandler', undefined);
23+
});
24+
},
25+
26+
confirmAccept: function () {
27+
this.send('validateAndAuthenticate');
28+
}
29+
}
30+
});

‎core/client/controllers/settings/labs.js‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ var LabsController = Ember.Controller.extend(Ember.Evented, {
88
formData = new FormData();
99

1010
this.set('uploadButtonText', '导入');
11+
this.set('importErrors', '');
1112
this.notifications.closePassive();
1213

1314
formData.append('importfile', file);

‎core/client/controllers/settings/tags.js‎

Lines changed: 106 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,105 @@ import boundOneWay from 'ghost/utils/bound-one-way';
44
var TagsController = Ember.ArrayController.extend(PaginationMixin, {
55
tags: Ember.computed.alias('model'),
66

7+
needs: 'application',
8+
79
activeTag: null,
810
activeTagNameScratch: boundOneWay('activeTag.name'),
911
activeTagSlugScratch: boundOneWay('activeTag.slug'),
1012
activeTagDescriptionScratch: boundOneWay('activeTag.description'),
13+
activeTagMetaTitleScratch: boundOneWay('activeTag.meta_title'),
14+
activeTagMetaDescriptionScratch: boundOneWay('activeTag.meta_description'),
1115

1216
init: function (options) {
1317
options = options || {};
1418
options.modelType = 'tag';
1519
this._super(options);
1620
},
1721

18-
saveActiveTag: function () {
22+
isViewingSubview: Ember.computed('controllers.application.showSettingsMenu', function (key, value) {
23+
// Not viewing a subview if we can't even see the PSM
24+
if (!this.get('controllers.application.showSettingsMenu')) {
25+
return false;
26+
}
27+
if (arguments.length > 1) {
28+
return value;
29+
}
30+
31+
return false;
32+
}),
33+
34+
showErrors: function (errors) {
35+
errors = Ember.isArray(errors) ? errors : [errors];
36+
this.notifications.showErrors(errors);
37+
},
38+
39+
saveActiveTagProperty: function (propKey, newValue) {
1940
var activeTag = this.get('activeTag'),
20-
name = activeTag.get('name'),
41+
currentValue = activeTag.get(propKey),
2142
self = this;
2243

23-
activeTag.save().then(function () {
24-
self.notifications.showSuccess('Saved ' + name);
25-
}).catch(function (error) {
26-
self.notifications.showAPIError(error);
44+
newValue = newValue.trim();
45+
46+
// Quit if there was no change
47+
if (newValue === currentValue) {
48+
return;
49+
}
50+
51+
activeTag.set(propKey, newValue);
52+
53+
this.notifications.closePassive();
54+
55+
activeTag.save().catch(function (errors) {
56+
self.showErrors(errors);
2757
});
2858
},
2959

60+
seoTitle: Ember.computed('scratch', 'activeTagNameScratch', 'activeTagMetaTitleScratch', function () {
61+
var metaTitle = this.get('activeTagMetaTitleScratch') || '';
62+
63+
metaTitle = metaTitle.length > 0 ? metaTitle : this.get('activeTagNameScratch');
64+
65+
if (metaTitle && metaTitle.length > 70) {
66+
metaTitle = metaTitle.substring(0, 70).trim();
67+
metaTitle = Ember.Handlebars.Utils.escapeExpression(metaTitle);
68+
metaTitle = new Ember.Handlebars.SafeString(metaTitle + '…');
69+
}
70+
71+
return metaTitle;
72+
}),
73+
74+
seoURL: Ember.computed('activeTagSlugScratch', function () {
75+
var blogUrl = this.get('config').blogUrl,
76+
seoSlug = this.get('activeTagSlugScratch') ? this.get('activeTagSlugScratch') : '',
77+
seoURL = blogUrl + '/tag/' + seoSlug;
78+
79+
// only append a slash to the URL if the slug exists
80+
if (seoSlug) {
81+
seoURL += '/';
82+
}
83+
84+
if (seoURL.length > 70) {
85+
seoURL = seoURL.substring(0, 70).trim();
86+
seoURL = new Ember.Handlebars.SafeString(seoURL + '…');
87+
}
88+
89+
return seoURL;
90+
}),
91+
92+
seoDescription: Ember.computed('scratch', 'activeTagDescriptionScratch', 'activeTagMetaDescriptionScratch', function () {
93+
var metaDescription = this.get('activeTagMetaDescriptionScratch') || '';
94+
95+
metaDescription = metaDescription.length > 0 ? metaDescription : this.get('activeTagDescriptionScratch');
96+
97+
if (metaDescription && metaDescription.length > 156) {
98+
metaDescription = metaDescription.substring(0, 156).trim();
99+
metaDescription = Ember.Handlebars.Utils.escapeExpression(metaDescription);
100+
metaDescription = new Ember.Handlebars.SafeString(metaDescription + '…');
101+
}
102+
103+
return metaDescription;
104+
}),
105+
30106
actions: {
31107
newTag: function () {
32108
this.set('activeTag', this.store.createRecord('tag'));
@@ -52,47 +128,39 @@ var TagsController = Ember.ArrayController.extend(PaginationMixin, {
52128
},
53129

54130
saveActiveTagName: function (name) {
55-
var activeTag = this.get('activeTag'),
56-
currentName = activeTag.get('name');
57-
58-
name = name.trim();
59-
if (!name || name === currentName) {
60-
return;
61-
}
62-
63-
// setting all of the properties as they are not saved until name is present
64-
activeTag.setProperties({
65-
name: name,
66-
slug: this.get('activeTagSlugScratch').trim(),
67-
description: this.get('activeTagDescriptionScratch').trim()
68-
});
69-
this.saveActiveTag();
131+
this.saveActiveTagProperty('name', name);
70132
},
71133

72134
saveActiveTagSlug: function (slug) {
73-
var name = this.get('activeTag.name'),
74-
currentSlug = this.get('activeTag.slug') || '';
135+
this.saveActiveTagProperty('slug', slug);
136+
},
75137

76-
slug = slug.trim();
77-
if (!name || !slug || slug === currentSlug) {
78-
return;
79-
}
138+
saveActiveTagDescription: function (description) {
139+
this.saveActiveTagProperty('description', description);
140+
},
80141

81-
this.set('activeTag.slug', slug);
82-
this.saveActiveTag();
142+
saveActiveTagMetaTitle: function (metaTitle) {
143+
this.saveActiveTagProperty('meta_title', metaTitle);
83144
},
84145

85-
saveActiveTagDescription: function (description) {
86-
var name = this.get('activeTag.name'),
87-
currentDescription = this.get('activeTag.description') || '';
146+
saveActiveTagMetaDescription: function (metaDescription) {
147+
this.saveActiveTagProperty('meta_description', metaDescription);
148+
},
88149

89-
description = description.trim();
90-
if (!name || description === currentDescription) {
91-
return;
92-
}
150+
showSubview: function () {
151+
this.set('isViewingSubview', true);
152+
},
153+
154+
closeSubview: function () {
155+
this.set('isViewingSubview', false);
156+
},
157+
158+
setCoverImage: function (image) {
159+
this.saveActiveTagProperty('image', image);
160+
},
93161

94-
this.set('activeTag.description', description);
95-
this.saveActiveTag();
162+
clearCoverImage: function () {
163+
this.saveActiveTagProperty('image', '');
96164
}
97165
}
98166
});

0 commit comments

Comments
 (0)