From bc0b9af576c7a99f4f89be0bf10aa3c9b3697c77 Mon Sep 17 00:00:00 2001
From: Sam
Date: Tue, 9 May 2017 17:20:28 -0400
Subject: [PATCH] FEATURE: support uploads for themes
This allows themes to bundle various assets
---
.../admin-customize-themes-show.js.es6 | 17 ++++++
.../modals/admin-add-upload.js.es6 | 43 +++++++++++++
.../javascripts/admin/models/theme.js.es6 | 60 ++++++++++++++++---
.../admin/templates/customize-themes-show.hbs | 20 ++++++-
.../templates/modal/admin-add-upload.hbs | 12 ++++
.../stylesheets/common/admin/customize.scss | 16 +++++
app/controllers/admin/themes_controller.rb | 26 +++++++-
app/models/remote_theme.rb | 29 ++++++++-
app/models/theme.rb | 11 ++--
app/models/theme_field.rb | 4 +-
app/models/upload.rb | 8 ++-
app/serializers/theme_serializer.rb | 22 ++++++-
config/locales/client.en.yml | 6 ++
config/locales/server.en.yml | 1 +
config/routes.rb | 1 +
config/site_settings.yml | 3 +
lib/git_importer.rb | 15 ++++-
lib/stylesheet/compiler.rb | 1 +
lib/stylesheet/importer.rb | 9 ++-
lib/validators/upload_validator.rb | 27 +++++----
.../admin/themes_controller_spec.rb | 35 +++++++++--
spec/fixtures/woff2/fake.woff2 | 1 +
spec/models/remote_theme_spec.rb | 32 ++++++++--
spec/models/theme_spec.rb | 3 +
.../admin/models/theme-test.js.es6 | 17 ++++++
25 files changed, 368 insertions(+), 51 deletions(-)
create mode 100644 app/assets/javascripts/admin/controllers/modals/admin-add-upload.js.es6
create mode 100644 app/assets/javascripts/admin/templates/modal/admin-add-upload.hbs
create mode 100644 spec/fixtures/woff2/fake.woff2
create mode 100644 test/javascripts/admin/models/theme-test.js.es6
diff --git a/app/assets/javascripts/admin/controllers/admin-customize-themes-show.js.es6 b/app/assets/javascripts/admin/controllers/admin-customize-themes-show.js.es6
index 3b2c2d9683..65f3dbc562 100644
--- a/app/assets/javascripts/admin/controllers/admin-customize-themes-show.js.es6
+++ b/app/assets/javascripts/admin/controllers/admin-customize-themes-show.js.es6
@@ -1,6 +1,9 @@
import { default as computed } from 'ember-addons/ember-computed-decorators';
import { url } from 'discourse/lib/computed';
import { popupAjaxError } from 'discourse/lib/ajax-error';
+import showModal from 'discourse/lib/show-modal';
+
+const THEME_UPLOAD_VAR = 2;
export default Ember.Controller.extend({
@@ -96,6 +99,16 @@ export default Ember.Controller.extend({
});
},
+ addUploadModal() {
+ showModal('admin-add-upload', {admin: true, name: ''});
+ },
+
+ addUpload(info) {
+ let model = this.get("model");
+ model.setField('common', info.name, '', info.upload_id, THEME_UPLOAD_VAR);
+ model.saveChanges('theme_fields').catch(e => popupAjaxError(e));
+ },
+
cancelChangeScheme() {
this.set("colorSchemeId", this.get("model.color_scheme_id"));
},
@@ -154,6 +167,10 @@ export default Ember.Controller.extend({
this.get("model").addChildTheme(theme);
},
+ removeUpload(upload) {
+ this.get("model").removeField(upload);
+ },
+
removeChildTheme(theme) {
this.get("model").removeChildTheme(theme);
},
diff --git a/app/assets/javascripts/admin/controllers/modals/admin-add-upload.js.es6 b/app/assets/javascripts/admin/controllers/modals/admin-add-upload.js.es6
new file mode 100644
index 0000000000..9b29d3b0d5
--- /dev/null
+++ b/app/assets/javascripts/admin/controllers/modals/admin-add-upload.js.es6
@@ -0,0 +1,43 @@
+import ModalFunctionality from 'discourse/mixins/modal-functionality';
+import { ajax } from 'discourse/lib/ajax';
+// import computed from 'ember-addons/ember-computed-decorators';
+import { popupAjaxError } from 'discourse/lib/ajax-error';
+
+export default Ember.Controller.extend(ModalFunctionality, {
+ adminCustomizeThemesShow: Ember.inject.controller(),
+
+ actions: {
+ updateName() {
+ let name = this.get('name');
+ if (Em.isEmpty(name)) {
+ name = $('#file-input')[0].files[0].name;
+ this.set('name', name.split(".")[0]);
+ }
+ },
+ upload() {
+
+ let options = {
+ type: 'POST'
+ };
+
+ options.processData = false;
+ options.contentType = false;
+ options.data = new FormData();
+ let file = $('#file-input')[0].files[0];
+ options.data.append('file', file);
+
+ ajax('/admin/themes/upload_asset', options).then(result=>{
+ let upload = {
+ upload_id: result.upload_id,
+ name: this.get('name'),
+ original_filename: file.name
+ };
+ this.get('adminCustomizeThemesShow').send('addUpload', upload);
+ this.send('closeModal');
+ }).catch(e => {
+ popupAjaxError(e);
+ });
+
+ }
+ }
+});
diff --git a/app/assets/javascripts/admin/models/theme.js.es6 b/app/assets/javascripts/admin/models/theme.js.es6
index 229d7ee0c0..3da681477a 100644
--- a/app/assets/javascripts/admin/models/theme.js.es6
+++ b/app/assets/javascripts/admin/models/theme.js.es6
@@ -1,6 +1,8 @@
import RestModel from 'discourse/models/rest';
import { default as computed } from 'ember-addons/ember-computed-decorators';
+const THEME_UPLOAD_VAR = 2;
+
const Theme = RestModel.extend({
@computed('theme_fields')
@@ -14,12 +16,26 @@ const Theme = RestModel.extend({
let hash = {};
if (fields) {
fields.forEach(field=>{
- hash[field.target + " " + field.name] = field;
+ if (!field.type_id || field.type_id < THEME_UPLOAD_VAR) {
+ hash[this.getKey(field)] = field;
+ }
});
}
return hash;
},
+ @computed('theme_fields', 'theme_fields.@each')
+ uploads(fields) {
+ if (!fields) {
+ return [];
+ }
+ return fields.filter((f)=> f.target === 'common' && f.type_id === THEME_UPLOAD_VAR);
+ },
+
+ getKey(field){
+ return field.target + " " + field.name;
+ },
+
hasEdited(target, name){
if (name) {
return !Em.isEmpty(this.getField(target, name));
@@ -31,30 +47,56 @@ const Theme = RestModel.extend({
getError(target, name) {
let themeFields = this.get("themeFields");
- let key = target + " " + name;
+ let key = this.getKey({target,name});
let field = themeFields[key];
return field ? field.error : "";
},
getField(target, name) {
let themeFields = this.get("themeFields");
- let key = target + " " + name;
+ let key = this.getKey({target, name})
let field = themeFields[key];
return field ? field.value : "";
},
- setField(target, name, value) {
+ removeField(field) {
this.set("changed", true);
+ field.upload_id = null;
+ field.value = null;
+
+ return this.saveChanges("theme_fields");
+ },
+
+ setField(target, name, value, upload_id, type_id) {
+ this.set("changed", true);
let themeFields = this.get("themeFields");
- let key = target + " " + name;
- let field = themeFields[key];
- if (!field) {
- field = {name, target, value};
+ let field = {name, target, value, upload_id, type_id};
+
+ // slow path for uploads and so on
+ if (type_id && type_id > 1) {
+ let fields = this.get("theme_fields");
+ let existing = fields.find((f) =>
+ f.target === target &&
+ f.name === name &&
+ f.type_id === type_id);
+ if (existing) {
+ existing.value = value;
+ existing.upload_id = upload_id;
+ } else {
+ fields.push(field);
+ }
+ return;
+ }
+
+ // fast path
+ let key = this.getKey({target,name});
+ let existingField = themeFields[key];
+ if (!existingField) {
this.theme_fields.push(field);
themeFields[key] = field;
} else {
- field.value = value;
+ existingField.value = value;
}
},
diff --git a/app/assets/javascripts/admin/templates/customize-themes-show.hbs b/app/assets/javascripts/admin/templates/customize-themes-show.hbs
index 55c2c5bb39..b4908d7143 100644
--- a/app/assets/javascripts/admin/templates/customize-themes-show.hbs
+++ b/app/assets/javascripts/admin/templates/customize-themes-show.hbs
@@ -51,7 +51,6 @@
{{i18n "admin.customize.theme.css_html"}}
{{#if hasEditedFields}}
-
{{i18n "admin.customize.theme.custom_sections"}}
{{#each editedDescriptions as |desc|}}
@@ -87,6 +86,21 @@
{{/if}}
+
+ {{i18n "admin.customize.theme.uploads"}}
+ {{#if model.uploads}}
+
+ {{#each model.uploads as |upload|}}
+ - ${{upload.name}}: {{upload.filename}}{{d-button action="removeUpload" actionParam=upload class="second btn-small cancel-edit" icon="times"}}
+ {{/each}}
+
+ {{else}}
+ {{i18n "admin.customize.theme.no_uploads"}}
+ {{/if}}
+
+ {{#d-button action="addUploadModal" icon="plus"}}{{i18n "admin.customize.theme.add"}}{{/d-button}}
+
+
{{#if availableChildThemes}}
{{i18n "admin.customize.theme.theme_components"}}
{{#unless model.childThemes.length}}
@@ -97,9 +111,9 @@
{{else}}
-