Skip to content

Commit fa1ba67

Browse files
committed
Work in Progress: Content Editing in Admin Section
1 parent bd0e98a commit fa1ba67

39 files changed

Lines changed: 653 additions & 64 deletions
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
This controller is used for editing site content
3+
4+
@class AdminSiteContentEditController
5+
@extends Ember.ObjectController
6+
@namespace Discourse
7+
@module Discourse
8+
**/
9+
Discourse.AdminSiteContentEditController = Discourse.ObjectController.extend({
10+
11+
saveDisabled: function() {
12+
if (this.get('saving')) return true;
13+
if (this.blank('content.content')) return true;
14+
return false;
15+
}.property('saving', 'content.content'),
16+
17+
saveChanges: function() {
18+
var controller = this;
19+
controller.setProperties({saving: true, saved: false});
20+
this.get('content').save().then(function () {
21+
controller.setProperties({saving: false, saved: true});
22+
});
23+
}
24+
25+
});
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
Our data model for interacting with custom site content
3+
4+
@class SiteContent
5+
@extends Discourse.Model
6+
@namespace Discourse
7+
@module Discourse
8+
**/
9+
Discourse.SiteContent = Discourse.Model.extend({
10+
11+
markdown: Ember.computed.equal('format', 'markdown'),
12+
plainText: Ember.computed.equal('format', 'plain'),
13+
html: Ember.computed.equal('format', 'html'),
14+
css: Ember.computed.equal('format', 'css'),
15+
16+
/**
17+
Save the content
18+
19+
@method save
20+
@return {jqXHR} a jQuery Promise object
21+
**/
22+
save: function() {
23+
return Discourse.ajax(Discourse.getURL("/admin/site_contents/" + this.get('content_type')), {
24+
type: 'PUT',
25+
data: {content: this.get('content')}
26+
});
27+
}
28+
29+
});
30+
31+
Discourse.SiteContent.reopenClass({
32+
33+
find: function(type) {
34+
return Discourse.ajax(Discourse.getURL("/admin/site_contents/" + type)).then(function (data) {
35+
return Discourse.SiteContent.create(data.site_content);
36+
});
37+
}
38+
39+
});
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
Our data model that represents types of editing site content
3+
4+
@class SiteContentType
5+
@extends Discourse.Model
6+
@namespace Discourse
7+
@module Discourse
8+
**/
9+
Discourse.SiteContentType = Discourse.Model.extend({});
10+
11+
Discourse.SiteContentType.reopenClass({
12+
findAll: function() {
13+
var contentTypes = Em.A();
14+
Discourse.ajax(Discourse.getURL("/admin/site_content_types")).then(function(data) {
15+
data.forEach(function (ct) {
16+
contentTypes.pushObject(Discourse.SiteContentType.create(ct));
17+
});
18+
});
19+
return contentTypes;
20+
}
21+
});

app/assets/javascripts/admin/models/site_customization.js

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,17 @@ Discourse.SiteCustomization = Discourse.Model.extend({
1414
return this.startTrackingChanges();
1515
},
1616

17-
description: (function() {
17+
description: function() {
1818
return "" + this.name + (this.enabled ? ' (*)' : '');
19-
}).property('selected', 'name'),
19+
}.property('selected', 'name'),
2020

21-
changed: (function() {
21+
changed: function() {
2222
var _this = this;
23-
if (!this.originals) {
24-
return false;
25-
}
23+
if (!this.originals) return false;
2624
return this.trackedProperties.any(function(p) {
2725
return _this.originals[p] !== _this.get(p);
2826
});
29-
}).property('override_default_style', 'enabled', 'name', 'stylesheet', 'header', 'originals'),
27+
}.property('override_default_style', 'enabled', 'name', 'stylesheet', 'header', 'originals'),
3028

3129
startTrackingChanges: function() {
3230
var _this = this;
@@ -37,18 +35,17 @@ Discourse.SiteCustomization = Discourse.Model.extend({
3735
});
3836
},
3937

40-
previewUrl: (function() {
38+
previewUrl: function() {
4139
return "/?preview-style=" + (this.get('key'));
42-
}).property('key'),
40+
}.property('key'),
4341

44-
disableSave: (function() {
42+
disableSave: function() {
4543
return !this.get('changed');
46-
}).property('changed'),
44+
}.property('changed'),
4745

4846
save: function() {
49-
var data;
5047
this.startTrackingChanges();
51-
data = {
48+
var data = {
5249
name: this.name,
5350
enabled: this.enabled,
5451
stylesheet: this.stylesheet,
@@ -66,7 +63,6 @@ Discourse.SiteCustomization = Discourse.Model.extend({
6663

6764
destroy: function() {
6865
if (!this.id) return;
69-
7066
return Discourse.ajax({
7167
url: Discourse.getURL("/admin/site_customizations/") + this.id,
7268
type: 'DELETE'
@@ -76,13 +72,12 @@ Discourse.SiteCustomization = Discourse.Model.extend({
7672
});
7773

7874
var SiteCustomizations = Ember.ArrayProxy.extend({
79-
selectedItemChanged: (function() {
80-
var selected;
81-
selected = this.get('selectedItem');
75+
selectedItemChanged: function() {
76+
var selected = this.get('selectedItem');
8277
return this.get('content').each(function(i) {
8378
return i.set('selected', selected === i);
8479
});
85-
}).observes('selectedItem')
80+
}.observes('selectedItem')
8681
});
8782

8883
Discourse.SiteCustomization.reopenClass({

app/assets/javascripts/admin/routes/admin_routes.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ Discourse.Route.buildRoutes(function() {
88
this.resource('admin', { path: '/admin' }, function() {
99
this.route('dashboard', { path: '/' });
1010
this.route('site_settings', { path: '/site_settings' });
11+
12+
13+
this.resource('adminSiteContents', { path: '/site_contents' }, function() {
14+
this.resource('adminSiteContentEdit', {path: '/:content_type'});
15+
});
16+
1117
this.route('email_logs', { path: '/email_logs' });
1218
this.route('customize', { path: '/customize' });
1319
this.route('api', {path: '/api'});
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
Allows users to customize site content
3+
4+
@class AdminSiteContentEditRoute
5+
@extends Discourse.Route
6+
@namespace Discourse
7+
@module Discourse
8+
**/
9+
Discourse.AdminSiteContentEditRoute = Discourse.Route.extend({
10+
11+
serialize: function(model) {
12+
return {content_type: model.get('content_type')};
13+
},
14+
15+
model: function(params) {
16+
return {content_type: params.content_type};
17+
},
18+
19+
renderTemplate: function() {
20+
this.render('admin/templates/site_content_edit', {into: 'admin/templates/site_contents'});
21+
},
22+
23+
exit: function() {
24+
this._super();
25+
this.render('admin/templates/site_contents_empty', {into: 'admin/templates/site_contents'});
26+
},
27+
28+
setupController: function(controller, model) {
29+
controller.set('loaded', false);
30+
controller.setProperties({saving: false, saved: false});
31+
32+
Discourse.SiteContent.find(Em.get(model, 'content_type')).then(function (sc) {
33+
controller.set('content', sc);
34+
controller.set('loaded', true);
35+
})
36+
}
37+
38+
39+
});
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
Allows users to customize site content
3+
4+
@class AdminSiteContentsRoute
5+
@extends Discourse.Route
6+
@namespace Discourse
7+
@module Discourse
8+
**/
9+
Discourse.AdminSiteContentsRoute = Discourse.Route.extend({
10+
11+
model: function() {
12+
return Discourse.SiteContentType.findAll();
13+
},
14+
15+
renderTemplate: function() {
16+
this.render('admin/templates/site_contents', {into: 'admin/templates/admin'});
17+
this.render('admin/templates/site_contents_empty', {into: 'admin/templates/site_contents'});
18+
}
19+
});
20+

app/assets/javascripts/admin/templates/admin.js.handlebars

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
<div class="container">
22
<div class="row">
3-
<div class="full-width">
4-
3+
<div class="full-width">
4+
55
<ul class="nav nav-pills">
66
<li>{{#linkTo 'admin.dashboard'}}{{i18n admin.dashboard.title}}{{/linkTo}}</li>
77
<li>{{#linkTo 'admin.site_settings'}}{{i18n admin.site_settings.title}}{{/linkTo}}</li>
8+
<li>{{#linkTo 'adminSiteContents'}}{{i18n admin.site_content.title}}{{/linkTo}}</li>
89
<li>{{#linkTo 'adminUsersList.active'}}{{i18n admin.users.title}}{{/linkTo}}</li>
910
<li>{{#linkTo 'admin.email_logs'}}{{i18n admin.email_logs.title}}{{/linkTo}}</li>
1011
<li>{{#linkTo 'adminFlags.active'}}{{i18n admin.flags.title}}{{/linkTo}}</li>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{{#if loaded}}
2+
<h3>{{title}}</h3>
3+
<p class='description'>{{description}}</p>
4+
5+
{{#if markdown}}
6+
{{view Discourse.PagedownEditor valueBinding="content.content"}}
7+
{{/if}}
8+
9+
{{#if plainText}}
10+
{{view Ember.TextArea valueBinding="content.content" class="plain"}}
11+
{{/if}}
12+
13+
{{#if html}}
14+
{{view Discourse.AceEditorView contentBinding="content.content" mode="html"}}
15+
{{/if}}
16+
17+
{{#if css}}
18+
{{view Discourse.AceEditorView contentBinding="content.content" mode="css"}}
19+
{{/if}}
20+
21+
22+
23+
<div class='controls'>
24+
<button class='btn' {{action saveChanges}} {{bindAttr disabled="saveDisabled"}}>
25+
{{#if saving}}
26+
{{i18n saving}}
27+
{{else}}
28+
{{i18n save}}
29+
{{/if}}
30+
</button>
31+
{{#if saved}}{{i18n saved}}{{/if}}
32+
</div>
33+
34+
{{else}}
35+
<div class='spinner'>{{i18n loading}}</div>
36+
{{/if}}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<div class='row'>
2+
<div class='content-list span6'>
3+
<h3>{{i18n admin.site_content.edit}}</h3>
4+
<ul>
5+
{{#each type in content}}
6+
<li>
7+
{{#linkTo 'adminSiteContentEdit' type}}{{type.title}}{{/linkTo}}
8+
</li>
9+
{{/each}}
10+
</ul>
11+
</div>
12+
13+
<div class='content-editor span15'>
14+
{{outlet}}
15+
</div>
16+
</div>

0 commit comments

Comments
 (0)