diff --git a/app/assets/javascripts/admin/controllers/admin-customize-css-html.js.es6 b/app/assets/javascripts/admin/controllers/admin-customize-css-html.js.es6
index 266f06c3e8d..be6834333d9 100644
--- a/app/assets/javascripts/admin/controllers/admin-customize-css-html.js.es6
+++ b/app/assets/javascripts/admin/controllers/admin-customize-css-html.js.es6
@@ -1,3 +1,5 @@
+import showModal from 'discourse/lib/show-modal';
+
/**
This controller supports interface for creating custom CSS skins in Discourse.
@@ -21,6 +23,10 @@ export default Ember.ArrayController.extend({
this.set('selectedItem', item);
},
+ importModal: function() {
+ showModal('upload-customization');
+ },
+
/**
Select a given style
diff --git a/app/assets/javascripts/admin/models/site_customization.js b/app/assets/javascripts/admin/models/site_customization.js
index 4d9ca8c7bf6..f7b6346a958 100644
--- a/app/assets/javascripts/admin/models/site_customization.js
+++ b/app/assets/javascripts/admin/models/site_customization.js
@@ -78,6 +78,7 @@ Discourse.SiteCustomization = Discourse.Model.extend({
siteCustomization.set('savingStatus', I18n.t('saved'));
siteCustomization.set('saving',false);
siteCustomization.startTrackingChanges();
+ return siteCustomization;
});
},
diff --git a/app/assets/javascripts/admin/templates/customize_css_html.hbs b/app/assets/javascripts/admin/templates/customize_css_html.hbs
index 8b9fff5fcf0..e2cc7951a01 100644
--- a/app/assets/javascripts/admin/templates/customize_css_html.hbs
+++ b/app/assets/javascripts/admin/templates/customize_css_html.hbs
@@ -8,6 +8,7 @@
+ {{d-button action="importModal" icon="upload" label="admin.customize.import"}}
{{#if selectedItem}}
diff --git a/app/assets/javascripts/discourse/components/json-file-uploader.js.es6 b/app/assets/javascripts/discourse/components/json-file-uploader.js.es6
new file mode 100644
index 00000000000..954d5f8d2ae
--- /dev/null
+++ b/app/assets/javascripts/discourse/components/json-file-uploader.js.es6
@@ -0,0 +1,76 @@
+
+export default Em.Component.extend({
+ fileInput: null,
+ loading: false,
+ expectedRootObjectName: null,
+
+ classNames: ['json-uploader'],
+
+ _initialize: function() {
+ const $this = this.$();
+ const self = this;
+
+ const $fileInput = $this.find('#js-file-input');
+ this.set('fileInput', $fileInput[0]);
+
+ $fileInput.on('change', function() {
+ self.fileSelected(this.files);
+ });
+
+ const $fileSelect = $this.find('.fileSelect');
+
+ $fileSelect.on('dragover dragenter', function(e) {
+ if (e.preventDefault) e.preventDefault();
+ return false;
+ });
+ $fileSelect.on('drop', function(e) {
+ if (e.preventDefault) e.preventDefault();
+
+ self.fileSelected(e.dataTransfer.files);
+ return false;
+ });
+
+ }.on('didInsertElement'),
+
+ setReady: function() {
+ let parsed;
+ try {
+ parsed = JSON.parse(this.get('value'));
+ } catch (e) {
+ this.set('ready', false);
+ return;
+ }
+
+ const rootObject = parsed[this.get('expectedRootObjectName')];
+
+ if (rootObject !== null && rootObject !== undefined) {
+ this.set('ready', true);
+ } else {
+ this.set('ready', false);
+ }
+ }.observes('destination', 'expectedRootObjectName'),
+
+ actions: {
+ selectFile: function() {
+ const $fileInput = $(this.get('fileInput'));
+ $fileInput.click();
+ }
+ },
+
+ fileSelected(fileList) {
+ const self = this;
+ const numFiles = fileList.length;
+ const firstFile = fileList[0];
+
+ this.set('loading', true);
+
+ let reader = new FileReader();
+ reader.onload = function(evt) {
+ self.set('value', evt.target.result);
+ self.set('loading', false);
+ };
+
+ reader.readAsText(firstFile);
+ }
+
+});
diff --git a/app/assets/javascripts/discourse/controllers/upload-customization.js.es6 b/app/assets/javascripts/discourse/controllers/upload-customization.js.es6
new file mode 100644
index 00000000000..09158f53752
--- /dev/null
+++ b/app/assets/javascripts/discourse/controllers/upload-customization.js.es6
@@ -0,0 +1,52 @@
+import ModalFunctionality from 'discourse/mixins/modal-functionality';
+
+export default Ember.Controller.extend(ModalFunctionality, {
+ notReady: Em.computed.not('ready'),
+
+ needs: ['admin-customize-css-html'],
+
+ title: "hi",
+
+ ready: function() {
+ let parsed;
+ try {
+ parsed = JSON.parse(this.get('customizationFile'));
+ } catch (e) {
+ return false;
+ }
+
+ return !!parsed["site_customization"];
+ }.property('customizationFile'),
+
+ actions: {
+ createCustomization: function() {
+ const self = this;
+ const object = JSON.parse(this.get('customizationFile')).site_customization;
+
+ // Slight fixup before creating object
+ object.enabled = false;
+ delete object.id;
+ delete object.key;
+
+ const customization = Discourse.SiteCustomization.create(object);
+
+ this.set('loading', true);
+ customization.save().then(function(customization) {
+ self.send('closeModal');
+ self.set('loading', false);
+
+ const parentController = self.get('controllers.admin-customize-css-html');
+ parentController.pushObject(customization);
+ parentController.set('selectedItem', customization);
+ }).catch(function(xhr) {
+ self.set('loading', false);
+ if (xhr.responseJSON) {
+ bootbox.alert(xhr.responseJSON.errors.join("
"));
+ } else {
+ bootbox.alert(I18n.t('generic_error'));
+ }
+ });
+ }
+ }
+
+});
diff --git a/app/assets/javascripts/discourse/templates/components/json-file-uploader.hbs b/app/assets/javascripts/discourse/templates/components/json-file-uploader.hbs
new file mode 100644
index 00000000000..655e3f7340d
--- /dev/null
+++ b/app/assets/javascripts/discourse/templates/components/json-file-uploader.hbs
@@ -0,0 +1,10 @@
+