Spiegel von
https://github.com/paviliondev/discourse-custom-wizard.git
synchronisiert 2024-11-22 17:30:29 +01:00
made the changes discussed with Angus, some UI improvements and some edge-case validations
Dieser Commit ist enthalten in:
Ursprung
98d8eeffca
Commit
bf9ceb6dd3
7 geänderte Dateien mit 143 neuen und 118 gelöschten Zeilen
|
@ -2,97 +2,84 @@ import {ajax} from 'discourse/lib/ajax';
|
||||||
|
|
||||||
export default Ember.Controller.extend({
|
export default Ember.Controller.extend({
|
||||||
init() {
|
init() {
|
||||||
|
|
||||||
this._super();
|
this._super();
|
||||||
this.set('selected', new Set());
|
this.set('selected', Ember.A());
|
||||||
this.set('filePath', []);
|
this.set('filePath', Ember.A());
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
|
||||||
checkChanged(event) {
|
checkChanged(event) {
|
||||||
|
|
||||||
let selected = this.get('selected');
|
let selected = this.get('selected');
|
||||||
|
|
||||||
|
|
||||||
if (event.target.checked) {
|
if (event.target.checked) {
|
||||||
|
selected.addObject(event.target.id)
|
||||||
|
|
||||||
selected.add(event.target.id)
|
|
||||||
|
|
||||||
} else if (!event.target.checked) {
|
} else if (!event.target.checked) {
|
||||||
selected.delete(event.target.id)
|
selected.removeObject(event.target.id)
|
||||||
}
|
}
|
||||||
console.log(selected);
|
console.log(selected);
|
||||||
this.set('selected', selected)
|
this.set('selected', selected)
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
export() {
|
export() {
|
||||||
let wizards = this.get('selected');
|
let wizards = this.get('selected');
|
||||||
let url = Discourse.BaseUrl;
|
let url = Discourse.BaseUrl;
|
||||||
let route = '/admin/wizards/transfer/export';
|
let route = '/admin/wizards/transfer/export';
|
||||||
url += route + '?';
|
url += route + '?';
|
||||||
|
if (!wizards.length) {
|
||||||
|
this.set('noneSelected', "Please select atleast one wizard")
|
||||||
|
} else {
|
||||||
|
this.set('noneSelected', '')
|
||||||
wizards.forEach((wizard) => {
|
wizards.forEach((wizard) => {
|
||||||
let step = 'wizards[]=' + wizard;
|
let step = 'wizards[]=' + wizard;
|
||||||
step += '&';
|
step += '&';
|
||||||
url += step
|
url += step
|
||||||
});
|
});
|
||||||
|
|
||||||
location.href = url;
|
location.href = url;
|
||||||
|
}
|
||||||
console.log(url)
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
setFilePath(event) {
|
setFilePath(event) {
|
||||||
console.log(event.target.files[0]);
|
|
||||||
|
|
||||||
// 512 kb is the max file size
|
// 512 kb is the max file size
|
||||||
let maxFileSize = 512 * 1024;
|
let maxFileSize = 512 * 1024;
|
||||||
|
if (event.target.files[0] === undefined) {
|
||||||
|
this.get('filePath').length = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
if (maxFileSize < event.target.files[0].size) {
|
if (maxFileSize < event.target.files[0].size) {
|
||||||
this.set('fileError', 'The file size is too big')
|
this.set('fileError', 'The file size is too big')
|
||||||
} else {
|
} else {
|
||||||
|
// emptying the array as we allow only one file upload at a time
|
||||||
this.set('filePath', event.target.files[0])
|
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() {
|
import() {
|
||||||
|
|
||||||
let $formData = new FormData();
|
let $formData = new FormData();
|
||||||
$formData.append('file', this.get('filePath'));
|
console.log(this.get('filePath'))
|
||||||
|
if (this.get('filePath').length) {
|
||||||
|
this.set('noFile', '')
|
||||||
|
$formData.append('file', this.get('filePath')[0]);
|
||||||
console.log($formData);
|
console.log($formData);
|
||||||
|
|
||||||
ajax('/admin/wizards/transfer/import', {
|
ajax('/admin/wizards/transfer/import', {
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
data: $formData,
|
data: $formData,
|
||||||
processData: false,
|
processData: false,
|
||||||
contentType: false,
|
contentType: false,
|
||||||
|
|
||||||
}).then(result => {
|
}).then(result => {
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
alert(result.error)
|
this.set('error', result.error)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
alert(result.success)
|
this.set('success_ids', result.success)
|
||||||
|
this.set('failure_ids', result.failed)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
this.set('noFile', 'Please choose a file to export')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,8 +12,7 @@ export default {
|
||||||
this.route('adminWizardsApi', { path: '/:name', resetNamespace: true });
|
this.route('adminWizardsApi', { path: '/:name', resetNamespace: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
this.route('adminWizardsTransfer',{path:'/transfer', resetNamespace:true});
|
this.route('adminWizardsTransfer', { path: '/transfer', resetNamespace: true });
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
import CustomWizard from '../models/custom-wizard';
|
import CustomWizard from '../models/custom-wizard';
|
||||||
export default Discourse.Route.extend({
|
|
||||||
|
|
||||||
model(){
|
export default Discourse.Route.extend({
|
||||||
|
model() {
|
||||||
return CustomWizard.all()
|
return CustomWizard.all()
|
||||||
},
|
},
|
||||||
isEmberized: true
|
|
||||||
// isEmberized(){
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
<h3>Select Wizards to export</h3>
|
<h2>Export</h2>
|
||||||
{{log this}}
|
|
||||||
|
|
||||||
<form {{action 'export' wizards on="submit"}} class="form">
|
<ul class="wizard-list-select">
|
||||||
<ul>
|
|
||||||
{{#each model as |w|}}
|
{{#each model as |w|}}
|
||||||
|
|
||||||
<li style="list-style-type: none;">
|
<li style="list-style-type: none;">
|
||||||
|
@ -12,23 +10,46 @@
|
||||||
</li>
|
</li>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
{{!-- <button type='submit' class='btn btn-primary'>--}}
|
|
||||||
{{!-- {{ i18n 'admin.wizard.transfer.export' }}--}}
|
{{d-button id="export-button" class="btn btn-primary side" label="admin.wizard.transfer.export"
|
||||||
{{!-- </button>--}}
|
action=(action "export")}}
|
||||||
{{d-button label="admin.wizard.transfer.export" action=(action "export")}}
|
|
||||||
|
|
||||||
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
<h2>Import</h2>
|
||||||
{{input id='file_url' type="file" change=(action "setFilePath")}}
|
{{input id='file_url' type="file" change=(action "setFilePath")}}
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
{{d-button label="admin.wizard.transfer.import" action=(action "import")}}
|
|
||||||
|
|
||||||
{{!--{{resumable-upload--}}
|
|
||||||
{{!-- target="transfer/import"--}}
|
|
||||||
{{!-- success=(action "jsonSuccess")--}}
|
{{d-button id="import-button" class="btn btn-primary side" label="admin.wizard.transfer.import"
|
||||||
{{!-- error=(action "jsonError")--}}
|
action=(action "import")}}
|
||||||
{{!-- uploadText="Import"--}}
|
|
||||||
|
{{#if this.noneSelected}}
|
||||||
|
<p>{{this.noneSelected}}</p>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if this.noFile}}
|
||||||
|
<p>{{this.noFile}}</p>
|
||||||
|
{{/if}}
|
||||||
|
{{#if this.fileError}}
|
||||||
|
<p>{{this.fileError}}</p>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if this.error}}
|
||||||
|
<p>{{this.error}}</p>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if this.success_ids}}
|
||||||
|
{{#each this.success_ids as |id|}}
|
||||||
|
<p>Wizard: {{id}} saved successfully</p>
|
||||||
|
{{/each}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if this.failure_ids}}
|
||||||
|
{{#each this.failure_ids as |id|}}
|
||||||
|
<p>Wizard: {{id}} could not be saved</p>
|
||||||
|
{{/each}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
|
||||||
|
|
19
assets/stylesheets/wizard/wizard_transfer.scss
Normale Datei
19
assets/stylesheets/wizard/wizard_transfer.scss
Normale Datei
|
@ -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;
|
||||||
|
}
|
|
@ -1,27 +1,23 @@
|
||||||
class CustomWizard::TransferController < ::ApplicationController
|
class CustomWizard::TransferController < ::ApplicationController
|
||||||
before_action :ensure_logged_in
|
before_action :ensure_logged_in
|
||||||
before_action :ensure_admin
|
before_action :ensure_admin
|
||||||
|
|
||||||
skip_before_action :check_xhr, :only => [:export]
|
skip_before_action :check_xhr, :only => [:export]
|
||||||
|
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def export
|
def export
|
||||||
|
|
||||||
wizards = params['wizards']
|
wizards = params['wizards']
|
||||||
wizard_objects = []
|
wizard_objects = []
|
||||||
wizards.each do
|
if wizards.nil?
|
||||||
|w|
|
render json: {error: 'Please select atleast one wizard'}
|
||||||
# p w
|
return
|
||||||
|
|
||||||
wizard_objects.push(PluginStore.get('custom_wizard', w.tr('-', '_')))
|
|
||||||
|
|
||||||
end
|
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'
|
send_data wizard_objects.to_json, type: "application/json", disposition: 'attachment', filename: 'wizards.json'
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -36,6 +32,10 @@ class CustomWizard::TransferController < ::ApplicationController
|
||||||
|
|
||||||
def import
|
def import
|
||||||
file = File.read(params['file'].tempfile)
|
file = File.read(params['file'].tempfile)
|
||||||
|
if file.nil?
|
||||||
|
render json: {error: "No file selected"}
|
||||||
|
return
|
||||||
|
end
|
||||||
fileSize = file.size
|
fileSize = file.size
|
||||||
maxFileSize = 512 * 1024
|
maxFileSize = 512 * 1024
|
||||||
if maxFileSize < fileSize
|
if maxFileSize < fileSize
|
||||||
|
@ -49,25 +49,26 @@ class CustomWizard::TransferController < ::ApplicationController
|
||||||
jsonObject = JSON.parse file
|
jsonObject = JSON.parse file
|
||||||
|
|
||||||
countValid = 0
|
countValid = 0
|
||||||
|
success_ids = []
|
||||||
|
failed_ids = []
|
||||||
jsonObject.each do |o|
|
jsonObject.each do |o|
|
||||||
# validate whether the given json is a valid "wizard"
|
# validate whether the given json is a valid "wizard"
|
||||||
next unless CustomWizard::Template.new(o)
|
next unless CustomWizard::Template.new(o)
|
||||||
countValid += 1
|
countValid += 1
|
||||||
|
|
||||||
|
|
||||||
puts 'json entity'
|
|
||||||
pluginStoreEntry = PluginStore.new 'custom_wizard'
|
pluginStoreEntry = PluginStore.new 'custom_wizard'
|
||||||
#plugin store detects the json object type and sets proper `type_name` for the entry
|
#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
|
end
|
||||||
|
|
||||||
if countValid == 0
|
if countValid == 0
|
||||||
render json: {error: "File doesn't contain any valid wizards"}
|
render json: {error: "File doesn't contain any valid wizards"}
|
||||||
else
|
else
|
||||||
render json: {success: "Wizards imported successfully"}
|
render json: {success: success_ids, failed: failed_ids}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# admin/wizards/transfer/import
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
12
plugin.rb
12
plugin.rb
|
@ -5,6 +5,7 @@
|
||||||
# url: https://github.com/angusmcleod/discourse-custom-wizard
|
# url: https://github.com/angusmcleod/discourse-custom-wizard
|
||||||
|
|
||||||
register_asset 'stylesheets/wizard_custom_admin.scss'
|
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.min.js'
|
||||||
register_asset 'lib/jquery.timepicker.scss'
|
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', 'javascripts')
|
||||||
config.assets.paths << Rails.root.join('plugins', 'discourse-custom-wizard', 'assets', 'stylesheets', 'wizard')
|
config.assets.paths << Rails.root.join('plugins', 'discourse-custom-wizard', 'assets', 'stylesheets', 'wizard')
|
||||||
|
|
||||||
|
|
||||||
if Rails.env.production?
|
if Rails.env.production?
|
||||||
config.assets.precompile += %w{
|
config.assets.precompile += %w{
|
||||||
wizard-custom-lib.js
|
wizard-custom-lib.js
|
||||||
|
@ -76,7 +78,7 @@ after_initialize do
|
||||||
get 'admin/wizards/apis/:name/redirect' => 'api#redirect'
|
get 'admin/wizards/apis/:name/redirect' => 'api#redirect'
|
||||||
get 'admin/wizards/apis/:name/authorize' => 'api#authorize'
|
get 'admin/wizards/apis/:name/authorize' => 'api#authorize'
|
||||||
#transfer code
|
#transfer code
|
||||||
get 'admin/wizards/transfer' =>'transfer#index'
|
get 'admin/wizards/transfer' => 'transfer#index'
|
||||||
get 'admin/wizards/transfer/export' => 'transfer#export'
|
get 'admin/wizards/transfer/export' => 'transfer#export'
|
||||||
post 'admin/wizards/transfer/import' => 'transfer#import'
|
post 'admin/wizards/transfer/import' => 'transfer#import'
|
||||||
end
|
end
|
||||||
|
@ -94,7 +96,7 @@ after_initialize do
|
||||||
load File.expand_path('../controllers/steps.rb', __FILE__)
|
load File.expand_path('../controllers/steps.rb', __FILE__)
|
||||||
load File.expand_path('../controllers/admin.rb', __FILE__)
|
load File.expand_path('../controllers/admin.rb', __FILE__)
|
||||||
#transfer code
|
#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('../jobs/refresh_api_access_token.rb', __FILE__)
|
||||||
load File.expand_path('../lib/api/api.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/']
|
@excluded_routes ||= SiteSetting.wizard_redirect_exclude_paths.split('|') + ['/w/']
|
||||||
url = request.referer || request.original_url
|
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\//
|
if request.referer !~ /\/w\// && request.referer !~ /\/invites\//
|
||||||
CustomWizard::Wizard.set_submission_redirect(current_user, wizard_id, request.referer)
|
CustomWizard::Wizard.set_submission_redirect(current_user, wizard_id, request.referer)
|
||||||
end
|
end
|
||||||
|
@ -163,7 +165,7 @@ after_initialize do
|
||||||
end
|
end
|
||||||
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
|
## TODO limit this to the first admin
|
||||||
SiteSerializer.class_eval do
|
SiteSerializer.class_eval do
|
||||||
|
@ -175,7 +177,7 @@ after_initialize do
|
||||||
|
|
||||||
def complete_custom_wizard
|
def complete_custom_wizard
|
||||||
if scope.user && requires_completion = CustomWizard::Wizard.prompt_completion(scope.user)
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Laden …
In neuem Issue referenzieren