From bf9ceb6dd3eb1af46573283e1b88efae881ebcd3 Mon Sep 17 00:00:00 2001 From: Faizaan Gagan Date: Tue, 30 Jul 2019 22:34:18 +0530 Subject: [PATCH] made the changes discussed with Angus, some UI improvements and some edge-case validations --- .../controllers/admin-wizards-transfer.js.es6 | 107 ++++++++---------- .../custom-wizard-admin-route-map.js.es6 | 3 +- .../routes/admin-wizards-transfer.js.es6 | 10 +- .../templates/admin-wizards-transfer.hbs | 71 ++++++++---- .../stylesheets/wizard/wizard_transfer.scss | 19 ++++ controllers/transfer.rb | 39 +++---- plugin.rb | 12 +- 7 files changed, 143 insertions(+), 118 deletions(-) create mode 100644 assets/stylesheets/wizard/wizard_transfer.scss diff --git a/assets/javascripts/discourse/controllers/admin-wizards-transfer.js.es6 b/assets/javascripts/discourse/controllers/admin-wizards-transfer.js.es6 index 2876a24f..5fd428e0 100644 --- a/assets/javascripts/discourse/controllers/admin-wizards-transfer.js.es6 +++ b/assets/javascripts/discourse/controllers/admin-wizards-transfer.js.es6 @@ -2,97 +2,84 @@ import {ajax} from 'discourse/lib/ajax'; export default Ember.Controller.extend({ init() { - this._super(); - this.set('selected', new Set()); - this.set('filePath', []); - - + this.set('selected', Ember.A()); + this.set('filePath', Ember.A()); }, actions: { - checkChanged(event) { - let selected = this.get('selected'); - - if (event.target.checked) { - - - selected.add(event.target.id) - + selected.addObject(event.target.id) } else if (!event.target.checked) { - selected.delete(event.target.id) + selected.removeObject(event.target.id) } console.log(selected); this.set('selected', selected) - - }, - export() { let wizards = this.get('selected'); let url = Discourse.BaseUrl; let route = '/admin/wizards/transfer/export'; url += route + '?'; - - wizards.forEach((wizard) => { - let step = 'wizards[]=' + wizard; - step += '&'; - url += step - }); - - location.href = url; - - console.log(url) - + if (!wizards.length) { + this.set('noneSelected', "Please select atleast one wizard") + } else { + this.set('noneSelected', '') + wizards.forEach((wizard) => { + let step = 'wizards[]=' + wizard; + step += '&'; + url += step + }); + location.href = url; + } }, setFilePath(event) { - console.log(event.target.files[0]); - // 512 kb is the max file size let maxFileSize = 512 * 1024; - + if (event.target.files[0] === undefined) { + this.get('filePath').length = 0 + return + } if (maxFileSize < event.target.files[0].size) { this.set('fileError', 'The file size is too big') } else { - - this.set('filePath', event.target.files[0]) - + // emptying the array as we allow only one file upload at a time + this.get('filePath').length = 0 + // interestingly, this.get gives us the actual reference to the object so modifying it + // actually modifies the actual value + this.get('filePath').addObject(event.target.files[0]) + console.log(this.get('filePath')) } + }, - } - - , import() { - let $formData = new FormData(); - $formData.append('file', this.get('filePath')); - console.log($formData); - - ajax('/admin/wizards/transfer/import', { - type: 'POST', - data: $formData, - processData: false, - contentType: false, - - }).then(result => { - if (result.error) { - alert(result.error) - - } else { - alert(result.success) - } - }) - + console.log(this.get('filePath')) + if (this.get('filePath').length) { + this.set('noFile', '') + $formData.append('file', this.get('filePath')[0]); + console.log($formData); + ajax('/admin/wizards/transfer/import', { + type: 'POST', + data: $formData, + processData: false, + contentType: false, + }).then(result => { + if (result.error) { + this.set('error', result.error) + } else { + this.set('success_ids', result.success) + this.set('failure_ids', result.failed) + } + }) + } else { + this.set('noFile', 'Please choose a file to export') + } } - - } - - }); diff --git a/assets/javascripts/discourse/custom-wizard-admin-route-map.js.es6 b/assets/javascripts/discourse/custom-wizard-admin-route-map.js.es6 index 5fac4221..001569f2 100644 --- a/assets/javascripts/discourse/custom-wizard-admin-route-map.js.es6 +++ b/assets/javascripts/discourse/custom-wizard-admin-route-map.js.es6 @@ -12,8 +12,7 @@ export default { this.route('adminWizardsApi', { path: '/:name', resetNamespace: true }); }); - this.route('adminWizardsTransfer',{path:'/transfer', resetNamespace:true}); - + this.route('adminWizardsTransfer', { path: '/transfer', resetNamespace: true }); }); } diff --git a/assets/javascripts/discourse/routes/admin-wizards-transfer.js.es6 b/assets/javascripts/discourse/routes/admin-wizards-transfer.js.es6 index 92a9f5a2..ead2d991 100644 --- a/assets/javascripts/discourse/routes/admin-wizards-transfer.js.es6 +++ b/assets/javascripts/discourse/routes/admin-wizards-transfer.js.es6 @@ -1,11 +1,7 @@ import CustomWizard from '../models/custom-wizard'; -export default Discourse.Route.extend({ - model(){ - return CustomWizard.all() +export default Discourse.Route.extend({ + model() { + return CustomWizard.all() }, - isEmberized: true - // isEmberized(){ - // return true; - // } }) diff --git a/assets/javascripts/discourse/templates/admin-wizards-transfer.hbs b/assets/javascripts/discourse/templates/admin-wizards-transfer.hbs index 4b8f8e0f..de856753 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-transfer.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-transfer.hbs @@ -1,34 +1,55 @@ -

Select Wizards to export

-{{log this}} +

Export

-
- + +{{d-button id="export-button" class="btn btn-primary side" label="admin.wizard.transfer.export" + action=(action "export")}} -
-{{input id='file_url' type="file" change=(action "setFilePath")}} -
-
-{{d-button label="admin.wizard.transfer.import" action=(action "import")}} +

Import

+{{input id='file_url' type="file" change=(action "setFilePath")}} + + + +{{d-button id="import-button" class="btn btn-primary side" label="admin.wizard.transfer.import" + action=(action "import")}} + +{{#if this.noneSelected}} +

{{this.noneSelected}}

+{{/if}} + +{{#if this.noFile}} +

{{this.noFile}}

+{{/if}} +{{#if this.fileError}} +

{{this.fileError}}

+{{/if}} + +{{#if this.error}} +

{{this.error}}

+{{/if}} + +{{#if this.success_ids}} + {{#each this.success_ids as |id|}} +

Wizard: {{id}} saved successfully

+ {{/each}} +{{/if}} + +{{#if this.failure_ids}} + {{#each this.failure_ids as |id|}} +

Wizard: {{id}} could not be saved

+ {{/each}} +{{/if}} -{{!--{{resumable-upload--}} -{{!-- target="transfer/import"--}} -{{!-- success=(action "jsonSuccess")--}} -{{!-- error=(action "jsonError")--}} -{{!-- uploadText="Import"--}} diff --git a/assets/stylesheets/wizard/wizard_transfer.scss b/assets/stylesheets/wizard/wizard_transfer.scss new file mode 100644 index 00000000..61c15b61 --- /dev/null +++ b/assets/stylesheets/wizard/wizard_transfer.scss @@ -0,0 +1,19 @@ +#export-button{ + margin-left: 30px; +} +#import-button{ + margin-left: 15px; +} +#file_url { + display: inline; +} + +.wizard-list-select { + display: inline-block; + +} + +.wizard-action-buttons{ + display: inline-flex; + flex-direction: column; +} diff --git a/controllers/transfer.rb b/controllers/transfer.rb index c1a631a0..999811b2 100644 --- a/controllers/transfer.rb +++ b/controllers/transfer.rb @@ -1,27 +1,23 @@ class CustomWizard::TransferController < ::ApplicationController before_action :ensure_logged_in before_action :ensure_admin - skip_before_action :check_xhr, :only => [:export] - def index - end def export - wizards = params['wizards'] wizard_objects = [] - wizards.each do - |w| - # p w - - wizard_objects.push(PluginStore.get('custom_wizard', w.tr('-', '_'))) - + if wizards.nil? + render json: {error: 'Please select atleast one wizard'} + return end - puts 'wizard_objects' - p wizard_objects + + wizards.each do |w| + wizard_objects.push(PluginStore.get('custom_wizard', w.tr('-', '_'))) + end + send_data wizard_objects.to_json, type: "application/json", disposition: 'attachment', filename: 'wizards.json' end @@ -36,6 +32,10 @@ class CustomWizard::TransferController < ::ApplicationController def import file = File.read(params['file'].tempfile) + if file.nil? + render json: {error: "No file selected"} + return + end fileSize = file.size maxFileSize = 512 * 1024 if maxFileSize < fileSize @@ -49,25 +49,26 @@ class CustomWizard::TransferController < ::ApplicationController jsonObject = JSON.parse file countValid = 0 + success_ids = [] + failed_ids = [] jsonObject.each do |o| # validate whether the given json is a valid "wizard" next unless CustomWizard::Template.new(o) countValid += 1 - - - puts 'json entity' pluginStoreEntry = PluginStore.new 'custom_wizard' #plugin store detects the json object type and sets proper `type_name` for the entry - pluginStoreEntry.set(o['id'], o) - + # this condition helps us avoid updating an existing wizard instead of adding a new one + saved = pluginStoreEntry.set(o['id'], o) unless pluginStoreEntry.get(o['id']) + success_ids.push o['id'] if !!saved + failed_ids.push o['id'] if !saved end if countValid == 0 render json: {error: "File doesn't contain any valid wizards"} else - render json: {success: "Wizards imported successfully"} + render json: {success: success_ids, failed: failed_ids} end end - # admin/wizards/transfer/import + end diff --git a/plugin.rb b/plugin.rb index b02f615f..20260e32 100644 --- a/plugin.rb +++ b/plugin.rb @@ -5,6 +5,7 @@ # url: https://github.com/angusmcleod/discourse-custom-wizard register_asset 'stylesheets/wizard_custom_admin.scss' +register_asset 'stylesheets/wizard/wizard_transfer.scss' register_asset 'lib/jquery.timepicker.min.js' register_asset 'lib/jquery.timepicker.scss' @@ -12,6 +13,7 @@ config = Rails.application.config config.assets.paths << Rails.root.join('plugins', 'discourse-custom-wizard', 'assets', 'javascripts') config.assets.paths << Rails.root.join('plugins', 'discourse-custom-wizard', 'assets', 'stylesheets', 'wizard') + if Rails.env.production? config.assets.precompile += %w{ wizard-custom-lib.js @@ -76,7 +78,7 @@ after_initialize do get 'admin/wizards/apis/:name/redirect' => 'api#redirect' get 'admin/wizards/apis/:name/authorize' => 'api#authorize' #transfer code - get 'admin/wizards/transfer' =>'transfer#index' + get 'admin/wizards/transfer' => 'transfer#index' get 'admin/wizards/transfer/export' => 'transfer#export' post 'admin/wizards/transfer/import' => 'transfer#import' end @@ -94,7 +96,7 @@ after_initialize do load File.expand_path('../controllers/steps.rb', __FILE__) load File.expand_path('../controllers/admin.rb', __FILE__) #transfer code - load File.expand_path('../controllers/transfer.rb',__FILE__) + load File.expand_path('../controllers/transfer.rb', __FILE__) load File.expand_path('../jobs/refresh_api_access_token.rb', __FILE__) load File.expand_path('../lib/api/api.rb', __FILE__) @@ -151,7 +153,7 @@ after_initialize do @excluded_routes ||= SiteSetting.wizard_redirect_exclude_paths.split('|') + ['/w/'] url = request.referer || request.original_url - if request.format === 'text/html' && !@excluded_routes.any? { |str| /#{str}/ =~ url } && wizard_id + if request.format === 'text/html' && !@excluded_routes.any? {|str| /#{str}/ =~ url} && wizard_id if request.referer !~ /\/w\// && request.referer !~ /\/invites\// CustomWizard::Wizard.set_submission_redirect(current_user, wizard_id, request.referer) end @@ -163,7 +165,7 @@ after_initialize do end end - add_to_serializer(:current_user, :redirect_to_wizard) { object.custom_fields['redirect_to_wizard'] } + add_to_serializer(:current_user, :redirect_to_wizard) {object.custom_fields['redirect_to_wizard']} ## TODO limit this to the first admin SiteSerializer.class_eval do @@ -175,7 +177,7 @@ after_initialize do def complete_custom_wizard if scope.user && requires_completion = CustomWizard::Wizard.prompt_completion(scope.user) - requires_completion.map { |w| { name: w[:name], url: "/w/#{w[:id]}" } } + requires_completion.map {|w| {name: w[:name], url: "/w/#{w[:id]}"}} end end