From 1e53c179a3c910f733a35cbd4f85fb3ceaa78bfa Mon Sep 17 00:00:00 2001 From: riking <rikingcoding@gmail.com> Date: Sat, 16 May 2015 18:15:42 -0700 Subject: [PATCH 1/6] FEATURE: Export customizations as JSON files --- .../admin/models/site_customization.js | 6 ++++- .../admin/templates/customize_css_html.hbs | 1 + .../stylesheets/common/admin/admin_base.scss | 3 +++ .../admin/site_customizations_controller.rb | 22 +++++++++++++++++++ .../site_customization_serializer.rb | 7 ++++++ config/locales/client.en.yml | 2 ++ 6 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 app/serializers/site_customization_serializer.rb diff --git a/app/assets/javascripts/admin/models/site_customization.js b/app/assets/javascripts/admin/models/site_customization.js index 27b6ddbdd..4d9ca8c7b 100644 --- a/app/assets/javascripts/admin/models/site_customization.js +++ b/app/assets/javascripts/admin/models/site_customization.js @@ -84,7 +84,11 @@ Discourse.SiteCustomization = Discourse.Model.extend({ destroy: function() { if (!this.id) return; return Discourse.ajax("/admin/site_customizations/" + this.id, { type: 'DELETE' }); - } + }, + + download_url: function() { + return Discourse.getURL('/admin/site_customizations/' + this.id); + }.property('id') }); var SiteCustomizations = Ember.ArrayProxy.extend({ diff --git a/app/assets/javascripts/admin/templates/customize_css_html.hbs b/app/assets/javascripts/admin/templates/customize_css_html.hbs index 004318e1e..8b9fff5fc 100644 --- a/app/assets/javascripts/admin/templates/customize_css_html.hbs +++ b/app/assets/javascripts/admin/templates/customize_css_html.hbs @@ -14,6 +14,7 @@ <div {{bind-attr class=":current-style view.maximized:maximized"}}> <div class='wrapper'> {{text-field class="style-name" value=selectedItem.name}} + <a class="btn export" download target="_blank" href={{selectedItem.download_url}}>{{fa-icon "download"}} {{i18n 'admin.export_json.button_text'}}</a> <div class='admin-controls'> <ul class="nav nav-pills"> diff --git a/app/assets/stylesheets/common/admin/admin_base.scss b/app/assets/stylesheets/common/admin/admin_base.scss index 6659f61a7..fc240b294 100644 --- a/app/assets/stylesheets/common/admin/admin_base.scss +++ b/app/assets/stylesheets/common/admin/admin_base.scss @@ -545,6 +545,9 @@ section.details { .preview-link { margin-left: 15px; } + .export { + float: right; + } padding-left: 10px; width: 70%; .style-name { diff --git a/app/controllers/admin/site_customizations_controller.rb b/app/controllers/admin/site_customizations_controller.rb index dc104fd74..30929fe4e 100644 --- a/app/controllers/admin/site_customizations_controller.rb +++ b/app/controllers/admin/site_customizations_controller.rb @@ -2,6 +2,8 @@ class Admin::SiteCustomizationsController < Admin::AdminController before_filter :enable_customization + skip_before_filter :check_xhr, only: [:show] + def index @site_customizations = SiteCustomization.order(:name) @@ -48,6 +50,26 @@ class Admin::SiteCustomizationsController < Admin::AdminController end end + def show + @site_customization = SiteCustomization.find(params[:id]) + + respond_to do |format| + format.json do + check_xhr + render json: SiteCustomizationSerializer.new(@site_customization) + end + + format.any(:html, :text) do + raise RenderEmpty.new if request.xhr? + + response.headers['Content-Disposition'] = "attachment; filename=#{@site_customization.name.parameterize}.dcstyle.json" + response.sending_file = true + render json: SiteCustomizationSerializer.new(@site_customization) + end + end + + end + private def site_customization_params diff --git a/app/serializers/site_customization_serializer.rb b/app/serializers/site_customization_serializer.rb new file mode 100644 index 000000000..7d5242355 --- /dev/null +++ b/app/serializers/site_customization_serializer.rb @@ -0,0 +1,7 @@ +class SiteCustomizationSerializer < ApplicationSerializer + + attributes :name, :enabled, :created_at, :updated_at, + :stylesheet, :header, :footer, :top, + :mobile_stylesheet, :mobile_header, :mobile_footer, :mobile_top, + :head_tag, :body_tag +end diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 7300d658b..9286504b2 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -1863,6 +1863,8 @@ en: screened_email: "Export full screened email list in CSV format." screened_ip: "Export full screened IP list in CSV format." screened_url: "Export full screened URL list in CSV format." + export_json: + button_text: "Export" invite: button_text: "Send Invites" From 291d9fc65e73ba8cf4c2e6ec0e5203fbcaa1c656 Mon Sep 17 00:00:00 2001 From: riking <rikingcoding@gmail.com> Date: Sat, 16 May 2015 19:56:19 -0700 Subject: [PATCH 2/6] FEATURE: Import customizations from a JSON file --- .../admin-customize-css-html.js.es6 | 6 ++ .../admin/models/site_customization.js | 1 + .../admin/templates/customize_css_html.hbs | 1 + .../components/json-file-uploader.js.es6 | 76 +++++++++++++++++++ .../controllers/upload-customization.js.es6 | 52 +++++++++++++ .../components/json-file-uploader.hbs | 10 +++ .../templates/modal/upload-customization.hbs | 8 ++ .../views/upload-customization.js.es6 | 6 ++ app/assets/stylesheets/common/base/modal.scss | 23 ++++++ .../site_customization_serializer.rb | 2 +- config/locales/client.en.yml | 4 + 11 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 app/assets/javascripts/discourse/components/json-file-uploader.js.es6 create mode 100644 app/assets/javascripts/discourse/controllers/upload-customization.js.es6 create mode 100644 app/assets/javascripts/discourse/templates/components/json-file-uploader.hbs create mode 100644 app/assets/javascripts/discourse/templates/modal/upload-customization.hbs create mode 100644 app/assets/javascripts/discourse/views/upload-customization.js.es6 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 266f06c3e..be6834333 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 4d9ca8c7b..f7b6346a9 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 8b9fff5fc..e2cc7951a 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 @@ <button {{action "newCustomization"}} class='btn'> {{fa-icon "plus"}}{{i18n 'admin.customize.new'}} </button> + {{d-button action="importModal" icon="upload" label="admin.customize.import"}} </div> {{#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 000000000..954d5f8d2 --- /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 000000000..09158f537 --- /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("<br>")); + } 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 000000000..655e3f734 --- /dev/null +++ b/app/assets/javascripts/discourse/templates/components/json-file-uploader.hbs @@ -0,0 +1,10 @@ +<div class="jsfu-file"> + <input id="js-file-input" type="file" style="display:none;" accept=".json,application/json"> + {{d-button class="fileSelect" action="selectFile" class="" icon="upload" label="upload_selector.select_file"}} + {{conditional-loading-spinner condition=loading size="small"}} +</div> +<div class="jsfu-separator">{{i18n "alternation"}}</div> +<div class="jsfu-paste"> + {{textarea value=value}} +</div> + diff --git a/app/assets/javascripts/discourse/templates/modal/upload-customization.hbs b/app/assets/javascripts/discourse/templates/modal/upload-customization.hbs new file mode 100644 index 000000000..8cc7851b3 --- /dev/null +++ b/app/assets/javascripts/discourse/templates/modal/upload-customization.hbs @@ -0,0 +1,8 @@ +<form {{action "dummy" on="submit"}}> + <div class='modal-body'> + {{json-file-uploader value=customizationFile}} + </div> + <div class="modal-footer"> + {{d-button class='btn-primary' action='createCustomization' type='submit' disabled=notReady icon="plus" label='admin.customize.import'}} + </div> +</form> diff --git a/app/assets/javascripts/discourse/views/upload-customization.js.es6 b/app/assets/javascripts/discourse/views/upload-customization.js.es6 new file mode 100644 index 000000000..c6e336157 --- /dev/null +++ b/app/assets/javascripts/discourse/views/upload-customization.js.es6 @@ -0,0 +1,6 @@ +import ModalBodyView from "discourse/views/modal-body"; + +export default ModalBodyView.extend({ + templateName: 'modal/upload-customization', + title: I18n.t('admin.customize.import_title') +}); diff --git a/app/assets/stylesheets/common/base/modal.scss b/app/assets/stylesheets/common/base/modal.scss index d5aa63a9b..1115a89ac 100644 --- a/app/assets/stylesheets/common/base/modal.scss +++ b/app/assets/stylesheets/common/base/modal.scss @@ -138,6 +138,29 @@ .raw-email-textarea { height: 300px; } + .json-uploader { + display: table-row; + .jsfu-file { + display: table-cell; + vertical-align: middle; + min-width: 120px; + } + .jsfu-separator { + vertical-align: middle; + display: table-cell; + font-size: 36px; + padding-left: 10px; + padding-right: 10px; + } + .jsfu-paste { + display: table-cell; + width: 100%; + textarea { + margin-bottom: 0; + margin-top: 4px; + } + } + } } .password-confirmation { display: none; diff --git a/app/serializers/site_customization_serializer.rb b/app/serializers/site_customization_serializer.rb index 7d5242355..1c8ff8f9d 100644 --- a/app/serializers/site_customization_serializer.rb +++ b/app/serializers/site_customization_serializer.rb @@ -1,6 +1,6 @@ class SiteCustomizationSerializer < ApplicationSerializer - attributes :name, :enabled, :created_at, :updated_at, + attributes :id, :name, :key, :enabled, :created_at, :updated_at, :stylesheet, :header, :footer, :top, :mobile_stylesheet, :mobile_header, :mobile_footer, :mobile_top, :head_tag, :body_tag diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 9286504b2..064a928f6 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -143,6 +143,7 @@ en: every_two_weeks: "every two weeks" every_three_days: "every three days" max_of_count: "max of {{count}}" + alternation: "or" character_count: one: "{{count}} character" other: "{{count}} characters" @@ -849,6 +850,7 @@ en: hint: "(you can also drag & drop into the editor to upload them)" hint_for_supported_browsers: "(you can also drag and drop or paste images into the editor to upload them)" uploading: "Uploading" + select_file: "Select File" image_link: "link your image will point to" search: @@ -1894,6 +1896,8 @@ en: save: "Save" new: "New" new_style: "New Style" + import: "Import" + import_title: "Select a file or paste text" delete: "Delete" delete_confirm: "Delete this customization?" about: "Modify CSS stylesheets and HTML headers on the site. Add a customization to start." From fbc06d044ff40774620d15460e518434db847e70 Mon Sep 17 00:00:00 2001 From: riking <rikingcoding@gmail.com> Date: Sat, 16 May 2015 20:33:31 -0700 Subject: [PATCH 3/6] Use .dcstylejson instead of .dcstyle.json --- .../discourse/components/json-file-uploader.js.es6 | 4 ++++ .../discourse/templates/components/json-file-uploader.hbs | 2 +- .../discourse/templates/modal/upload-customization.hbs | 2 +- app/controllers/admin/site_customizations_controller.rb | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/discourse/components/json-file-uploader.js.es6 b/app/assets/javascripts/discourse/components/json-file-uploader.js.es6 index 954d5f8d2..250260dc4 100644 --- a/app/assets/javascripts/discourse/components/json-file-uploader.js.es6 +++ b/app/assets/javascripts/discourse/components/json-file-uploader.js.es6 @@ -32,6 +32,10 @@ export default Em.Component.extend({ }.on('didInsertElement'), + accept: function() { + return ".json,application/json" + (this.get('extension') ? "," + this.get('extension') : ""); + }.property('extension'), + setReady: function() { let parsed; try { diff --git a/app/assets/javascripts/discourse/templates/components/json-file-uploader.hbs b/app/assets/javascripts/discourse/templates/components/json-file-uploader.hbs index 655e3f734..fba3461c5 100644 --- a/app/assets/javascripts/discourse/templates/components/json-file-uploader.hbs +++ b/app/assets/javascripts/discourse/templates/components/json-file-uploader.hbs @@ -1,5 +1,5 @@ <div class="jsfu-file"> - <input id="js-file-input" type="file" style="display:none;" accept=".json,application/json"> + <input id="js-file-input" type="file" style="display:none;" accept={{accept}}> {{d-button class="fileSelect" action="selectFile" class="" icon="upload" label="upload_selector.select_file"}} {{conditional-loading-spinner condition=loading size="small"}} </div> diff --git a/app/assets/javascripts/discourse/templates/modal/upload-customization.hbs b/app/assets/javascripts/discourse/templates/modal/upload-customization.hbs index 8cc7851b3..3e49a755e 100644 --- a/app/assets/javascripts/discourse/templates/modal/upload-customization.hbs +++ b/app/assets/javascripts/discourse/templates/modal/upload-customization.hbs @@ -1,6 +1,6 @@ <form {{action "dummy" on="submit"}}> <div class='modal-body'> - {{json-file-uploader value=customizationFile}} + {{json-file-uploader value=customizationFile extension=".dcstylejson"}} </div> <div class="modal-footer"> {{d-button class='btn-primary' action='createCustomization' type='submit' disabled=notReady icon="plus" label='admin.customize.import'}} diff --git a/app/controllers/admin/site_customizations_controller.rb b/app/controllers/admin/site_customizations_controller.rb index 30929fe4e..0eedc538c 100644 --- a/app/controllers/admin/site_customizations_controller.rb +++ b/app/controllers/admin/site_customizations_controller.rb @@ -62,7 +62,7 @@ class Admin::SiteCustomizationsController < Admin::AdminController format.any(:html, :text) do raise RenderEmpty.new if request.xhr? - response.headers['Content-Disposition'] = "attachment; filename=#{@site_customization.name.parameterize}.dcstyle.json" + response.headers['Content-Disposition'] = "attachment; filename=#{@site_customization.name.parameterize}.dcstylejson" response.sending_file = true render json: SiteCustomizationSerializer.new(@site_customization) end From 30abc91a5c1ebe613d7aaf45acc5fc4463950409 Mon Sep 17 00:00:00 2001 From: riking <rikingcoding@gmail.com> Date: Sat, 16 May 2015 21:04:57 -0700 Subject: [PATCH 4/6] this just in: drag events are very broken --- .../components/json-file-uploader.js.es6 | 21 ++++++++++++-- .../components/json-file-uploader.hbs | 20 +++++++------ app/assets/stylesheets/common/base/modal.scss | 28 ++++++++++++++++++- 3 files changed, 56 insertions(+), 13 deletions(-) diff --git a/app/assets/javascripts/discourse/components/json-file-uploader.js.es6 b/app/assets/javascripts/discourse/components/json-file-uploader.js.es6 index 250260dc4..b1fd33c38 100644 --- a/app/assets/javascripts/discourse/components/json-file-uploader.js.es6 +++ b/app/assets/javascripts/discourse/components/json-file-uploader.js.es6 @@ -3,6 +3,7 @@ export default Em.Component.extend({ fileInput: null, loading: false, expectedRootObjectName: null, + hover: 0, classNames: ['json-uploader'], @@ -17,15 +18,29 @@ export default Em.Component.extend({ self.fileSelected(this.files); }); - const $fileSelect = $this.find('.fileSelect'); + const $dragContainer = $this.find('.jsfu-shade-container'); - $fileSelect.on('dragover dragenter', function(e) { + $this.on('dragover', function(e) { if (e.preventDefault) e.preventDefault(); + //self.set('hover', true); return false; }); - $fileSelect.on('drop', function(e) { + $this.on('dragenter', function(e) { + if (e.preventDefault) e.preventDefault(); + console.log('dragenter'); + self.set('hover', self.get('hover') + 1); + return false; + }); + $this.on('dragleave', function(e) { + if (e.preventDefault) e.preventDefault(); + console.log('dragleave'); + self.set('hover', self.get('hover') - 1); + return false; + }); + $this.on('drop', function(e) { if (e.preventDefault) e.preventDefault(); + self.set('hover', 0); self.fileSelected(e.dataTransfer.files); return false; }); diff --git a/app/assets/javascripts/discourse/templates/components/json-file-uploader.hbs b/app/assets/javascripts/discourse/templates/components/json-file-uploader.hbs index fba3461c5..b34f6c4b9 100644 --- a/app/assets/javascripts/discourse/templates/components/json-file-uploader.hbs +++ b/app/assets/javascripts/discourse/templates/components/json-file-uploader.hbs @@ -1,10 +1,12 @@ -<div class="jsfu-file"> - <input id="js-file-input" type="file" style="display:none;" accept={{accept}}> - {{d-button class="fileSelect" action="selectFile" class="" icon="upload" label="upload_selector.select_file"}} - {{conditional-loading-spinner condition=loading size="small"}} +<div class="jsfu-shade-container"> + <div class="jsfu-file"> + <input id="js-file-input" type="file" style="display:none;" accept={{accept}}> + {{d-button class="fileSelect" action="selectFile" class="" icon="upload" label="upload_selector.select_file"}} + {{conditional-loading-spinner condition=loading size="small"}} + </div> + <div class="jsfu-separator">{{i18n "alternation"}}</div> + <div class="jsfu-paste"> + {{textarea value=value}} + </div> + <div class="jsfu-shade {{if hover '' 'hidden'}}"><span class="text">{{fa-icon "upload"}}</span></div> </div> -<div class="jsfu-separator">{{i18n "alternation"}}</div> -<div class="jsfu-paste"> - {{textarea value=value}} -</div> - diff --git a/app/assets/stylesheets/common/base/modal.scss b/app/assets/stylesheets/common/base/modal.scss index 1115a89ac..43b94b2c9 100644 --- a/app/assets/stylesheets/common/base/modal.scss +++ b/app/assets/stylesheets/common/base/modal.scss @@ -139,7 +139,33 @@ height: 300px; } .json-uploader { - display: table-row; + .jsfu-shade-container { + display: table-row; + width: 100%; + height: 100%; + position: relative; + } + .jsfu-shade { + z-index: 1; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + .text { + color: rgb(255,255,255); + position: absolute; + top: 40%; + font-size: 36px; + text-align: center; + line-height: 38px; + margin-left: auto; + margin-right: auto; + left: 0; + right: 0; + } + } .jsfu-file { display: table-cell; vertical-align: middle; From d0b61ed23e95b9d51c25c8e0db64e9123b4ac82c Mon Sep 17 00:00:00 2001 From: riking <rikingcoding@gmail.com> Date: Sat, 16 May 2015 21:18:07 -0700 Subject: [PATCH 5/6] Filter files to only plain-text --- .../components/json-file-uploader.js.es6 | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/discourse/components/json-file-uploader.js.es6 b/app/assets/javascripts/discourse/components/json-file-uploader.js.es6 index b1fd33c38..fc0bf7bd6 100644 --- a/app/assets/javascripts/discourse/components/json-file-uploader.js.es6 +++ b/app/assets/javascripts/discourse/components/json-file-uploader.js.es6 @@ -22,18 +22,15 @@ export default Em.Component.extend({ $this.on('dragover', function(e) { if (e.preventDefault) e.preventDefault(); - //self.set('hover', true); return false; }); $this.on('dragenter', function(e) { if (e.preventDefault) e.preventDefault(); - console.log('dragenter'); self.set('hover', self.get('hover') + 1); return false; }); $this.on('dragleave', function(e) { if (e.preventDefault) e.preventDefault(); - console.log('dragleave'); self.set('hover', self.get('hover') - 1); return false; }); @@ -78,7 +75,20 @@ export default Em.Component.extend({ fileSelected(fileList) { const self = this; - const numFiles = fileList.length; + let files = []; + for (let i = 0; i < fileList.length; i++) { + files[i] = fileList[i]; + } + const fileNameRegex = /\.(json|txt)$/; + files = files.filter(function(file) { + if (fileNameRegex.test(file.name)) { + return true; + } + if (file.type === "text/plain") { + return true; + } + return false; + }); const firstFile = fileList[0]; this.set('loading', true); From d112f39031fb0460f94e456362fe55ea36763308 Mon Sep 17 00:00:00 2001 From: riking <rikingcoding@gmail.com> Date: Tue, 19 May 2015 18:35:16 -0700 Subject: [PATCH 6/6] Change extension back to .dcstyle.json --- .../javascripts/discourse/components/json-file-uploader.js.es6 | 2 +- .../discourse/templates/modal/upload-customization.hbs | 2 +- app/controllers/admin/site_customizations_controller.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/discourse/components/json-file-uploader.js.es6 b/app/assets/javascripts/discourse/components/json-file-uploader.js.es6 index fc0bf7bd6..c86784ca2 100644 --- a/app/assets/javascripts/discourse/components/json-file-uploader.js.es6 +++ b/app/assets/javascripts/discourse/components/json-file-uploader.js.es6 @@ -45,7 +45,7 @@ export default Em.Component.extend({ }.on('didInsertElement'), accept: function() { - return ".json,application/json" + (this.get('extension') ? "," + this.get('extension') : ""); + return ".json,application/json,application/x-javascript,text/json" + (this.get('extension') ? "," + this.get('extension') : ""); }.property('extension'), setReady: function() { diff --git a/app/assets/javascripts/discourse/templates/modal/upload-customization.hbs b/app/assets/javascripts/discourse/templates/modal/upload-customization.hbs index 3e49a755e..6d5d53e5b 100644 --- a/app/assets/javascripts/discourse/templates/modal/upload-customization.hbs +++ b/app/assets/javascripts/discourse/templates/modal/upload-customization.hbs @@ -1,6 +1,6 @@ <form {{action "dummy" on="submit"}}> <div class='modal-body'> - {{json-file-uploader value=customizationFile extension=".dcstylejson"}} + {{json-file-uploader value=customizationFile extension=".dcstyle.json"}} </div> <div class="modal-footer"> {{d-button class='btn-primary' action='createCustomization' type='submit' disabled=notReady icon="plus" label='admin.customize.import'}} diff --git a/app/controllers/admin/site_customizations_controller.rb b/app/controllers/admin/site_customizations_controller.rb index 0eedc538c..30929fe4e 100644 --- a/app/controllers/admin/site_customizations_controller.rb +++ b/app/controllers/admin/site_customizations_controller.rb @@ -62,7 +62,7 @@ class Admin::SiteCustomizationsController < Admin::AdminController format.any(:html, :text) do raise RenderEmpty.new if request.xhr? - response.headers['Content-Disposition'] = "attachment; filename=#{@site_customization.name.parameterize}.dcstylejson" + response.headers['Content-Disposition'] = "attachment; filename=#{@site_customization.name.parameterize}.dcstyle.json" response.sending_file = true render json: SiteCustomizationSerializer.new(@site_customization) end