Commits vergleichen
Keine gemeinsamen Commits. „main“ und „remove_subs_and_notices“ haben vollständig unterschiedliche Historien.
main
...
remove_sub
437 geänderte Dateien mit 11871 neuen und 18344 gelöschten Zeilen
|
@ -1,3 +1,2 @@
|
||||||
3.1.999: 1f35b80f85e5fd1efb7f4851f0845700432febdc
|
|
||||||
2.7.99: e07a57e398b6b1676ab42a7e34467556fca5416b
|
2.7.99: e07a57e398b6b1676ab42a7e34467556fca5416b
|
||||||
2.5.1: bb85b3a0d2c0ab6b59bcb405731c39089ec6731c
|
2.5.1: bb85b3a0d2c0ab6b59bcb405731c39089ec6731c
|
||||||
|
|
13
.github/workflows/discourse-plugin.yml
gevendort
13
.github/workflows/discourse-plugin.yml
gevendort
|
@ -1,13 +0,0 @@
|
||||||
name: Discourse Plugin
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
pull_request:
|
|
||||||
schedule:
|
|
||||||
- cron: "0 0 * * *"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ci:
|
|
||||||
uses: discourse/.github/.github/workflows/discourse-plugin.yml@v1
|
|
56
.github/workflows/plugin-linting.yml
gevendort
Normale Datei
56
.github/workflows/plugin-linting.yml
gevendort
Normale Datei
|
@ -0,0 +1,56 @@
|
||||||
|
name: Linting
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- main
|
||||||
|
- stable
|
||||||
|
pull_request:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Set up Node.js
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 14
|
||||||
|
|
||||||
|
- name: Set up ruby
|
||||||
|
uses: ruby/setup-ruby@v1
|
||||||
|
with:
|
||||||
|
ruby-version: 2.7
|
||||||
|
|
||||||
|
- name: Setup bundler
|
||||||
|
run: gem install bundler -v 2.1.4 --no-doc
|
||||||
|
|
||||||
|
- name: Setup gems
|
||||||
|
run: bundle install --jobs 4
|
||||||
|
|
||||||
|
- name: Yarn install
|
||||||
|
run: yarn install --dev
|
||||||
|
|
||||||
|
- name: ESLint
|
||||||
|
run: yarn eslint --ext .js,.js.es6 --no-error-on-unmatched-pattern {test,assets}/javascripts
|
||||||
|
|
||||||
|
- name: Prettier
|
||||||
|
run: |
|
||||||
|
yarn prettier -v
|
||||||
|
if [ -d "assets" ]; then \
|
||||||
|
yarn prettier --list-different "assets/**/*.{scss,js,es6}" ; \
|
||||||
|
fi
|
||||||
|
if [ -d "test" ]; then \
|
||||||
|
yarn prettier --list-different "test/**/*.{js,es6}" ; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Ember template lint
|
||||||
|
run: yarn ember-template-lint assets/javascripts
|
||||||
|
|
||||||
|
- name: Rubocop
|
||||||
|
run: bundle exec rubocop .
|
143
.github/workflows/plugin-tests.yml
gevendort
Normale Datei
143
.github/workflows/plugin-tests.yml
gevendort
Normale Datei
|
@ -0,0 +1,143 @@
|
||||||
|
name: Plugin Tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- stable
|
||||||
|
- master
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 */12 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: ${{ matrix.build_type }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 60
|
||||||
|
|
||||||
|
env:
|
||||||
|
DISCOURSE_HOSTNAME: www.example.com
|
||||||
|
RUBY_GLOBAL_METHOD_CACHE_SIZE: 131072
|
||||||
|
RAILS_ENV: test
|
||||||
|
PGHOST: localhost
|
||||||
|
PGUSER: discourse
|
||||||
|
PGPASSWORD: discourse
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
build_type: ["backend", "frontend"]
|
||||||
|
ruby: ["2.7"]
|
||||||
|
postgres: ["12"]
|
||||||
|
redis: ["6.x"]
|
||||||
|
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:${{ matrix.postgres }}
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
|
env:
|
||||||
|
POSTGRES_USER: discourse
|
||||||
|
POSTGRES_PASSWORD: discourse
|
||||||
|
options: >-
|
||||||
|
--mount type=tmpfs,destination=/var/lib/postgresql/data
|
||||||
|
--health-cmd pg_isready
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 5
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: haya14busa/action-cond@v1
|
||||||
|
id: discourse_branch
|
||||||
|
with:
|
||||||
|
cond: ${{ github.base_ref == 'stable' }}
|
||||||
|
if_true: "stable"
|
||||||
|
if_false: "tests-passed"
|
||||||
|
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
repository: discourse/discourse
|
||||||
|
ref: ${{ steps.discourse_branch.outputs.value }}
|
||||||
|
fetch-depth: 1
|
||||||
|
|
||||||
|
- name: Fetch Repo Name
|
||||||
|
id: repo-name
|
||||||
|
run: echo "::set-output name=value::$(echo '${{ github.repository }}' | awk -F '/' '{print $2}')"
|
||||||
|
|
||||||
|
- name: Install plugin
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
path: plugins/${{ steps.repo-name.outputs.value }}
|
||||||
|
ref: "${{ github.base_ref }}"
|
||||||
|
fetch-depth: 1
|
||||||
|
|
||||||
|
- name: Setup Git
|
||||||
|
run: |
|
||||||
|
git config --global user.email "ci@ci.invalid"
|
||||||
|
git config --global user.name "Discourse CI"
|
||||||
|
|
||||||
|
- name: Setup packages
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get -yqq install postgresql-client libpq-dev gifsicle jpegoptim optipng jhead
|
||||||
|
wget -qO- https://raw.githubusercontent.com/discourse/discourse_docker/master/image/base/install-pngquant | sudo sh
|
||||||
|
|
||||||
|
- name: Update imagemagick
|
||||||
|
if: matrix.build_type == 'backend'
|
||||||
|
run: |
|
||||||
|
wget https://raw.githubusercontent.com/discourse/discourse_docker/master/image/base/install-imagemagick
|
||||||
|
chmod +x install-imagemagick
|
||||||
|
sudo ./install-imagemagick
|
||||||
|
|
||||||
|
- name: Setup redis
|
||||||
|
uses: shogo82148/actions-setup-redis@v1
|
||||||
|
with:
|
||||||
|
redis-version: ${{ matrix.redis }}
|
||||||
|
|
||||||
|
- name: Setup ruby
|
||||||
|
uses: ruby/setup-ruby@v1
|
||||||
|
with:
|
||||||
|
ruby-version: ${{ matrix.ruby }}
|
||||||
|
bundler-cache: true
|
||||||
|
|
||||||
|
- name: Lint English locale
|
||||||
|
if: matrix.build_type == 'backend'
|
||||||
|
run: bundle exec ruby script/i18n_lint.rb "plugins/${{ steps.repo-name.outputs.value }}/locales/{client,server}.en.yml"
|
||||||
|
|
||||||
|
- name: Get yarn cache directory
|
||||||
|
id: yarn-cache-dir
|
||||||
|
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||||
|
|
||||||
|
- name: Yarn cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
id: yarn-cache
|
||||||
|
with:
|
||||||
|
path: ${{ steps.yarn-cache-dir.outputs.dir }}
|
||||||
|
key: ${{ runner.os }}-${{ matrix.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-${{ matrix.os }}-yarn-
|
||||||
|
|
||||||
|
- name: Yarn install
|
||||||
|
run: yarn install --dev
|
||||||
|
|
||||||
|
- name: Migrate database
|
||||||
|
run: |
|
||||||
|
bin/rake db:create
|
||||||
|
bin/rake db:migrate
|
||||||
|
|
||||||
|
- name: Plugin RSpec with Coverage
|
||||||
|
if: matrix.build_type == 'backend'
|
||||||
|
run: |
|
||||||
|
if [ -e plugins/${{ steps.repo-name.outputs.value }}/.simplecov ]
|
||||||
|
then
|
||||||
|
cp plugins/${{ steps.repo-name.outputs.value }}/.simplecov .simplecov
|
||||||
|
export COVERAGE=1
|
||||||
|
fi
|
||||||
|
bin/rake plugin:spec[${{ steps.repo-name.outputs.value }}]
|
||||||
|
|
||||||
|
- name: Plugin QUnit
|
||||||
|
if: matrix.build_type == 'frontend'
|
||||||
|
run: QUNIT_SKIP_CORE=1 LOAD_PLUGINS=1 QUNIT_EMBER_CLI=0 bin/rake "qunit:test['600000','/w/qunit']"
|
||||||
|
timeout-minutes: 30
|
3
.gitignore
gevendort
3
.gitignore
gevendort
|
@ -1,8 +1,7 @@
|
||||||
coverage/*
|
coverage/*
|
||||||
!coverage/.last_run.json
|
!coverage/.last_run.json
|
||||||
gems/*
|
gems/
|
||||||
.bundle/
|
.bundle/
|
||||||
auto_generated
|
auto_generated
|
||||||
.DS_Store
|
.DS_Store
|
||||||
node_modules/
|
node_modules/
|
||||||
vendor/*
|
|
||||||
|
|
|
@ -1,8 +1,2 @@
|
||||||
inherit_gem:
|
inherit_gem:
|
||||||
rubocop-discourse: default.yml
|
rubocop-discourse: default.yml
|
||||||
|
|
||||||
RSpec/ContextWording:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
RSpec/DescribeClass:
|
|
||||||
Enabled: false
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
All code in this repository is Copyright 2023 by Angus McLeod.
|
All code in this repository is Copyright 2018 by Angus McLeod.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
31
Gemfile.lock
31
Gemfile.lock
|
@ -2,32 +2,31 @@ GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
ast (2.4.2)
|
ast (2.4.2)
|
||||||
json (2.6.2)
|
parallel (1.20.1)
|
||||||
parallel (1.22.1)
|
parser (3.0.1.0)
|
||||||
parser (3.1.2.1)
|
|
||||||
ast (~> 2.4.1)
|
ast (~> 2.4.1)
|
||||||
rainbow (3.1.1)
|
rainbow (3.0.0)
|
||||||
regexp_parser (2.6.0)
|
regexp_parser (2.1.1)
|
||||||
rexml (3.2.5)
|
rexml (3.2.5)
|
||||||
rubocop (1.36.0)
|
rubocop (1.12.1)
|
||||||
json (~> 2.3)
|
|
||||||
parallel (~> 1.10)
|
parallel (~> 1.10)
|
||||||
parser (>= 3.1.2.1)
|
parser (>= 3.0.0.0)
|
||||||
rainbow (>= 2.2.2, < 4.0)
|
rainbow (>= 2.2.2, < 4.0)
|
||||||
regexp_parser (>= 1.8, < 3.0)
|
regexp_parser (>= 1.8, < 3.0)
|
||||||
rexml (>= 3.2.5, < 4.0)
|
rexml
|
||||||
rubocop-ast (>= 1.20.1, < 2.0)
|
rubocop-ast (>= 1.2.0, < 2.0)
|
||||||
ruby-progressbar (~> 1.7)
|
ruby-progressbar (~> 1.7)
|
||||||
unicode-display_width (>= 1.4.0, < 3.0)
|
unicode-display_width (>= 1.4.0, < 3.0)
|
||||||
rubocop-ast (1.22.0)
|
rubocop-ast (1.4.1)
|
||||||
parser (>= 3.1.1.0)
|
parser (>= 2.7.1.5)
|
||||||
rubocop-discourse (3.0)
|
rubocop-discourse (2.4.1)
|
||||||
rubocop (>= 1.1.0)
|
rubocop (>= 1.1.0)
|
||||||
rubocop-rspec (>= 2.0.0)
|
rubocop-rspec (>= 2.0.0)
|
||||||
rubocop-rspec (2.13.2)
|
rubocop-rspec (2.2.0)
|
||||||
rubocop (~> 1.33)
|
rubocop (~> 1.0)
|
||||||
|
rubocop-ast (>= 1.1.0)
|
||||||
ruby-progressbar (1.11.0)
|
ruby-progressbar (1.11.0)
|
||||||
unicode-display_width (2.3.0)
|
unicode-display_width (2.0.0)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
|
28
README.md
28
README.md
|
@ -1,27 +1,3 @@
|
||||||
# Discourse Custom Wizard Plugin
|
# discourse-custom-wizard
|
||||||
|
|
||||||
The Custom Wizard Plugin lets you make forms for your Discourse forum. Better user onboarding, structured posting, data enrichment, automated actions and much more for your community.
|
See further: https://thepavilion.io/c/knowledge/discourse/custom-wizard/118
|
||||||
|
|
||||||
<img src="https://camo.githubusercontent.com/593432f1fc9658ffca104065668cc88fa21dffcd3002cb78ffd50c71f33a2523/68747470733a2f2f706176696c696f6e2d6173736574732e6e7963332e63646e2e6469676974616c6f6365616e7370616365732e636f6d2f706c7567696e732f77697a6172642d7265706f7369746f72792d62616e6e65722e706e67" alt="" data-canonical-src="https://pavilion-assets.nyc3.cdn.digitaloceanspaces.com/plugins/wizard-repository-banner.png" style="max-width: 100%;" width="400">
|
|
||||||
|
|
||||||
👋 Looking to report an issue? We're managing issues for this plugin using our [bug report wizard](https://coop.pavilion.tech/w/bug-report).
|
|
||||||
|
|
||||||
## Install
|
|
||||||
|
|
||||||
If you're not sure how to install a plugin in Discourse, please follow the [plugin installation guide](https://meta.discourse.org/t/install-a-plugin/19157) or contact your Discourse hosting provider.
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
|
|
||||||
[Read the full documentation here](https://coop.pavilion.tech/c/82), or go directly to the relevant section
|
|
||||||
|
|
||||||
- [Wizard Administration](https://coop.pavilion.tech/t/1602)
|
|
||||||
- [Wizard Settings](https://coop.pavilion.tech/t/1614)
|
|
||||||
- [Step Settings](https://coop.pavilion.tech/t/1735)
|
|
||||||
- [Field Settings](https://coop.pavilion.tech/t/1580)
|
|
||||||
- [Conditional Settings](https://coop.pavilion.tech/t/1673)
|
|
||||||
- [Field Interpolation](https://coop.pavilion.tech/t/1557)
|
|
||||||
- [Handling Dates and Times](https://coop.pavilion.tech/t/1708)
|
|
||||||
|
|
||||||
## Support
|
|
||||||
|
|
||||||
- [Report an issue](https://coop.pavilion.tech/w/bug-report)
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
# Security Policy
|
|
||||||
|
|
||||||
The security of Discourse plugins are premised on the security of [Discourse](https://github.com/discourse/discourse). Please first consider whether a security issue is best reported and handled by the Discourse team. You can view the Discourse security policy [here](https://github.com/discourse/discourse/security/policy).
|
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
|
||||||
|
|
||||||
If you find a security vulnerability that is specific to this plugin, please report it to development@pavilion.tech. Security issues always take precedence over all other work. All commits specific to security are prefixed with SECURITY.
|
|
|
@ -8,7 +8,7 @@ class CustomWizard::AdminController < ::Admin::AdminController
|
||||||
subscribed: subcription.subscribed?,
|
subscribed: subcription.subscribed?,
|
||||||
subscription_type: subcription.type,
|
subscription_type: subcription.type,
|
||||||
subscription_attributes: CustomWizard::Subscription.attributes,
|
subscription_attributes: CustomWizard::Subscription.attributes,
|
||||||
subscription_client_installed: CustomWizard::Subscription.client_installed?
|
subscription_client_installed: subcription.client_installed?
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,6 @@ class CustomWizard::AdminApiController < CustomWizard::AdminController
|
||||||
raise Discourse::InvalidParameters, "An API with that name already exists: '#{current.title || current.name}'"
|
raise Discourse::InvalidParameters, "An API with that name already exists: '#{current.title || current.name}'"
|
||||||
end
|
end
|
||||||
|
|
||||||
unless subscription.includes?(:api, :all)
|
|
||||||
raise Discourse::InvalidParameters, "Your subscription doesn't include API features."
|
|
||||||
end
|
|
||||||
|
|
||||||
PluginStoreRow.transaction do
|
PluginStoreRow.transaction do
|
||||||
CustomWizard::Api.set(api_params[:name], title: api_params[:title])
|
CustomWizard::Api.set(api_params[:name], title: api_params[:title])
|
||||||
|
|
||||||
|
@ -134,8 +130,4 @@ class CustomWizard::AdminApiController < CustomWizard::AdminController
|
||||||
|
|
||||||
@auth_data ||= auth_data
|
@auth_data ||= auth_data
|
||||||
end
|
end
|
||||||
|
|
||||||
def subscription
|
|
||||||
@subscription ||= CustomWizard::Subscription.new
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -22,12 +22,7 @@ class CustomWizard::AdminSubmissionsController < CustomWizard::AdminController
|
||||||
end
|
end
|
||||||
|
|
||||||
def download
|
def download
|
||||||
content = ActiveModel::ArraySerializer.new(
|
send_data submission_list.submissions.to_json,
|
||||||
CustomWizard::Submission.list(@wizard).submissions,
|
|
||||||
each_serializer: CustomWizard::SubmissionSerializer
|
|
||||||
)
|
|
||||||
|
|
||||||
send_data content.to_json,
|
|
||||||
filename: "#{Discourse.current_hostname}-wizard-submissions-#{@wizard.name}.json",
|
filename: "#{Discourse.current_hostname}-wizard-submissions-#{@wizard.name}.json",
|
||||||
content_type: "application/json",
|
content_type: "application/json",
|
||||||
disposition: "attachment"
|
disposition: "attachment"
|
||||||
|
|
|
@ -88,7 +88,6 @@ class CustomWizard::AdminWizardController < CustomWizard::AdminController
|
||||||
:title,
|
:title,
|
||||||
:key,
|
:key,
|
||||||
:banner,
|
:banner,
|
||||||
:banner_upload_id,
|
|
||||||
:raw_description,
|
:raw_description,
|
||||||
:required_data_message,
|
:required_data_message,
|
||||||
:force_final,
|
:force_final,
|
||||||
|
@ -100,7 +99,6 @@ class CustomWizard::AdminWizardController < CustomWizard::AdminController
|
||||||
:index,
|
:index,
|
||||||
:label,
|
:label,
|
||||||
:image,
|
:image,
|
||||||
:image_upload_id,
|
|
||||||
:description,
|
:description,
|
||||||
:required,
|
:required,
|
||||||
:key,
|
:key,
|
||||||
|
@ -114,7 +112,6 @@ class CustomWizard::AdminWizardController < CustomWizard::AdminController
|
||||||
:property,
|
:property,
|
||||||
:preview_template,
|
:preview_template,
|
||||||
:placeholder,
|
:placeholder,
|
||||||
:can_create_tag,
|
|
||||||
prefill: mapped_params,
|
prefill: mapped_params,
|
||||||
content: mapped_params,
|
content: mapped_params,
|
||||||
condition: mapped_params,
|
condition: mapped_params,
|
||||||
|
@ -164,9 +161,7 @@ class CustomWizard::AdminWizardController < CustomWizard::AdminController
|
||||||
mentionable_level: mapped_params,
|
mentionable_level: mapped_params,
|
||||||
messageable_level: mapped_params,
|
messageable_level: mapped_params,
|
||||||
visibility_level: mapped_params,
|
visibility_level: mapped_params,
|
||||||
members_visibility_level: mapped_params,
|
members_visibility_level: mapped_params
|
||||||
add_event: mapped_params,
|
|
||||||
add_location: mapped_params
|
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
class CustomWizard::StepsController < ::CustomWizard::WizardClientController
|
class CustomWizard::StepsController < ::ApplicationController
|
||||||
|
before_action :ensure_logged_in
|
||||||
before_action :ensure_can_update
|
before_action :ensure_can_update
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
@ -21,7 +22,7 @@ class CustomWizard::StepsController < ::CustomWizard::WizardClientController
|
||||||
|
|
||||||
if updater.success?
|
if updater.success?
|
||||||
wizard_id = update_params[:wizard_id]
|
wizard_id = update_params[:wizard_id]
|
||||||
builder = CustomWizard::Builder.new(wizard_id, current_user, guest_id)
|
builder = CustomWizard::Builder.new(wizard_id, current_user)
|
||||||
@wizard = builder.build(force: true)
|
@wizard = builder.build(force: true)
|
||||||
|
|
||||||
current_step = @wizard.find_step(update[:step_id])
|
current_step = @wizard.find_step(update[:step_id])
|
||||||
|
@ -84,6 +85,7 @@ class CustomWizard::StepsController < ::CustomWizard::WizardClientController
|
||||||
private
|
private
|
||||||
|
|
||||||
def ensure_can_update
|
def ensure_can_update
|
||||||
|
@builder = CustomWizard::Builder.new(update_params[:wizard_id], current_user)
|
||||||
raise Discourse::InvalidParameters.new(:wizard_id) if @builder.template.nil?
|
raise Discourse::InvalidParameters.new(:wizard_id) if @builder.template.nil?
|
||||||
raise Discourse::InvalidAccess.new if !@builder.wizard || !@builder.wizard.can_access?
|
raise Discourse::InvalidAccess.new if !@builder.wizard || !@builder.wizard.can_access?
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,41 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
class CustomWizard::WizardController < ::CustomWizard::WizardClientController
|
class CustomWizard::WizardController < ::ActionController::Base
|
||||||
def show
|
helper ApplicationHelper
|
||||||
|
|
||||||
|
include CurrentUser
|
||||||
|
include CanonicalURL::ControllerExtensions
|
||||||
|
include GlobalPath
|
||||||
|
|
||||||
|
prepend_view_path(Rails.root.join('plugins', 'discourse-custom-wizard', 'app', 'views'))
|
||||||
|
layout :set_wizard_layout
|
||||||
|
|
||||||
|
before_action :preload_wizard_json
|
||||||
|
before_action :ensure_plugin_enabled
|
||||||
|
before_action :ensure_logged_in, only: [:skip]
|
||||||
|
|
||||||
|
helper_method :wizard_page_title
|
||||||
|
helper_method :wizard_theme_id
|
||||||
|
helper_method :wizard_theme_lookup
|
||||||
|
helper_method :wizard_theme_translations_lookup
|
||||||
|
|
||||||
|
def set_wizard_layout
|
||||||
|
action_name === 'qunit' ? 'qunit' : 'wizard'
|
||||||
|
end
|
||||||
|
|
||||||
|
def index
|
||||||
|
respond_to do |format|
|
||||||
|
format.json do
|
||||||
if wizard.present?
|
if wizard.present?
|
||||||
render json: CustomWizard::WizardSerializer.new(wizard, scope: guardian, root: false).as_json, status: 200
|
render json: CustomWizard::WizardSerializer.new(wizard, scope: guardian, root: false).as_json, status: 200
|
||||||
else
|
else
|
||||||
render json: { error: I18n.t('wizard.none') }
|
render json: { error: I18n.t('wizard.none') }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
format.html do
|
||||||
|
render "default/empty"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def skip
|
def skip
|
||||||
params.require(:wizard_id)
|
params.require(:wizard_id)
|
||||||
|
@ -28,12 +57,69 @@ class CustomWizard::WizardController < ::CustomWizard::WizardClientController
|
||||||
render json: result
|
render json: result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def qunit
|
||||||
|
raise Discourse::InvalidAccess.new if Rails.env.production?
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html do
|
||||||
|
render "default/empty"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
|
def ensure_logged_in
|
||||||
|
raise Discourse::NotLoggedIn.new unless current_user.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def guardian
|
||||||
|
@guardian ||= Guardian.new(current_user, request)
|
||||||
|
end
|
||||||
|
|
||||||
def wizard
|
def wizard
|
||||||
@wizard ||= begin
|
@wizard ||= begin
|
||||||
return nil unless @builder.present?
|
builder = CustomWizard::Builder.new(params[:wizard_id].underscore, current_user)
|
||||||
@builder.build({ reset: params[:reset] }, params)
|
return nil unless builder.present?
|
||||||
|
opts = {}
|
||||||
|
opts[:reset] = params[:reset]
|
||||||
|
builder.build(opts, params)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def wizard_page_title
|
||||||
|
wizard ? (wizard.name || wizard.id) : I18n.t('wizard.custom_title')
|
||||||
|
end
|
||||||
|
|
||||||
|
def wizard_theme_id
|
||||||
|
wizard ? wizard.theme_id : nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def wizard_theme_lookup(name)
|
||||||
|
Theme.lookup_field(wizard_theme_id, view_context.mobile_view? ? :mobile : :desktop, name)
|
||||||
|
end
|
||||||
|
|
||||||
|
def wizard_theme_translations_lookup
|
||||||
|
Theme.lookup_field(wizard_theme_id, :translations, I18n.locale)
|
||||||
|
end
|
||||||
|
|
||||||
|
def preload_wizard_json
|
||||||
|
return if request.xhr? || request.format.json?
|
||||||
|
return if request.method != "GET"
|
||||||
|
|
||||||
|
store_preloaded("siteSettings", SiteSetting.client_settings_json)
|
||||||
|
end
|
||||||
|
|
||||||
|
def store_preloaded(key, json)
|
||||||
|
@preloaded ||= {}
|
||||||
|
@preloaded[key] = json.gsub("</", "<\\/")
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def ensure_plugin_enabled
|
||||||
|
unless SiteSetting.custom_wizard_enabled
|
||||||
|
redirect_to path("/")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
class CustomWizard::WizardClientController < ::ApplicationController
|
|
||||||
before_action :ensure_plugin_enabled
|
|
||||||
before_action :set_builder
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def ensure_plugin_enabled
|
|
||||||
unless SiteSetting.custom_wizard_enabled
|
|
||||||
redirect_to path("/")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def guest_id
|
|
||||||
return nil if current_user.present?
|
|
||||||
cookies[:custom_wizard_guest_id] ||= CustomWizard::Wizard.generate_guest_id
|
|
||||||
cookies[:custom_wizard_guest_id]
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_builder
|
|
||||||
@builder = CustomWizard::Builder.new(params[:wizard_id].underscore, current_user, guest_id)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -2,15 +2,12 @@
|
||||||
class CustomWizard::SubmissionSerializer < ApplicationSerializer
|
class CustomWizard::SubmissionSerializer < ApplicationSerializer
|
||||||
attributes :id,
|
attributes :id,
|
||||||
:fields,
|
:fields,
|
||||||
:submitted_at,
|
:submitted_at
|
||||||
:user
|
|
||||||
|
has_one :user, serializer: ::BasicUserSerializer, embed: :objects
|
||||||
|
|
||||||
def include_user?
|
def include_user?
|
||||||
object.wizard.user.present?
|
object.user.present?
|
||||||
end
|
|
||||||
|
|
||||||
def user
|
|
||||||
::BasicUserSerializer.new(object.wizard.user, root: false).as_json
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def fields
|
def fields
|
||||||
|
|
|
@ -17,7 +17,6 @@ class CustomWizard::FieldSerializer < ::ApplicationSerializer
|
||||||
:property,
|
:property,
|
||||||
:content,
|
:content,
|
||||||
:tag_groups,
|
:tag_groups,
|
||||||
:can_create_tag,
|
|
||||||
:validations,
|
:validations,
|
||||||
:max_length,
|
:max_length,
|
||||||
:char_counter,
|
:char_counter,
|
||||||
|
@ -99,10 +98,6 @@ class CustomWizard::FieldSerializer < ::ApplicationSerializer
|
||||||
object.tag_groups
|
object.tag_groups
|
||||||
end
|
end
|
||||||
|
|
||||||
def can_create_tag
|
|
||||||
object.can_create_tag
|
|
||||||
end
|
|
||||||
|
|
||||||
def validations
|
def validations
|
||||||
validations = {}
|
validations = {}
|
||||||
object.validations&.each do |type, props|
|
object.validations&.each do |type, props|
|
||||||
|
|
|
@ -9,10 +9,14 @@ class CustomWizard::WizardSerializer < CustomWizard::BasicWizardSerializer
|
||||||
:completed,
|
:completed,
|
||||||
:required,
|
:required,
|
||||||
:permitted,
|
:permitted,
|
||||||
|
:uncategorized_category_id,
|
||||||
|
:categories,
|
||||||
|
:subscribed,
|
||||||
:resume_on_revisit
|
:resume_on_revisit
|
||||||
|
|
||||||
has_many :steps, serializer: ::CustomWizard::StepSerializer, embed: :objects
|
has_many :steps, serializer: ::CustomWizard::StepSerializer, embed: :objects
|
||||||
has_one :user, serializer: ::BasicUserSerializer, embed: :objects
|
has_one :user, serializer: ::BasicUserSerializer, embed: :objects
|
||||||
|
has_many :groups, serializer: ::BasicGroupSerializer, embed: :objects
|
||||||
|
|
||||||
def completed
|
def completed
|
||||||
object.completed?
|
object.completed?
|
||||||
|
@ -43,4 +47,28 @@ class CustomWizard::WizardSerializer < CustomWizard::BasicWizardSerializer
|
||||||
def include_steps?
|
def include_steps?
|
||||||
!include_completed?
|
!include_completed?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def include_categories?
|
||||||
|
object.needs_categories
|
||||||
|
end
|
||||||
|
|
||||||
|
def include_groups?
|
||||||
|
object.needs_groups
|
||||||
|
end
|
||||||
|
|
||||||
|
def uncategorized_category_id
|
||||||
|
SiteSetting.uncategorized_category_id
|
||||||
|
end
|
||||||
|
|
||||||
|
def include_uncategorized_category_id?
|
||||||
|
object.needs_categories
|
||||||
|
end
|
||||||
|
|
||||||
|
def categories
|
||||||
|
object.categories.map { |c| c.to_h }
|
||||||
|
end
|
||||||
|
|
||||||
|
def subscribed
|
||||||
|
CustomWizard::Subscription.subscribed?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
62
app/views/layouts/wizard.html.erb
Normale Datei
62
app/views/layouts/wizard.html.erb
Normale Datei
|
@ -0,0 +1,62 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<%= discourse_color_scheme_stylesheets %>
|
||||||
|
|
||||||
|
<%= discourse_stylesheet_link_tag :wizard, theme_id: nil %>
|
||||||
|
<%= discourse_stylesheet_link_tag :wizard_custom %>
|
||||||
|
<%- if wizard_theme_id.present? %>
|
||||||
|
<%= discourse_stylesheet_link_tag (mobile_view? ? :mobile_theme : :desktop_theme), theme_id: wizard_theme_id %>
|
||||||
|
<%- end %>
|
||||||
|
|
||||||
|
<%= preload_script "locales/#{I18n.locale}" %>
|
||||||
|
<%= preload_script "ember_jquery" %>
|
||||||
|
<%= preload_script "wizard-vendor" %>
|
||||||
|
<%= preload_script "wizard-custom" %>
|
||||||
|
<%= preload_script "wizard-raw-templates" %>
|
||||||
|
<%= preload_script "wizard-plugin" %>
|
||||||
|
<%= preload_script "pretty-text-bundle" %>
|
||||||
|
<script src="<%= ExtraLocalesController.url("wizard") %>"></script>
|
||||||
|
<%= csrf_meta_tags %>
|
||||||
|
|
||||||
|
<%- unless customization_disabled? %>
|
||||||
|
<%= wizard_theme_translations_lookup %>
|
||||||
|
<%= raw wizard_theme_lookup("head_tag") %>
|
||||||
|
<%- end %>
|
||||||
|
|
||||||
|
<%= server_plugin_outlet "custom_wizard" %>
|
||||||
|
|
||||||
|
<%= tag.meta id: 'data-discourse-setup', data: client_side_setup_data %>
|
||||||
|
|
||||||
|
<meta name="discourse_theme_id" content="<%= wizard_theme_id %>">
|
||||||
|
<meta name="discourse-base-uri" content="<%= Discourse.base_path %>">
|
||||||
|
|
||||||
|
<%= render partial: "layouts/head" %>
|
||||||
|
<title><%= wizard_page_title %></title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class='custom-wizard'>
|
||||||
|
<%- unless customization_disabled? %>
|
||||||
|
<%= raw wizard_theme_lookup("header") %>
|
||||||
|
<%- end %>
|
||||||
|
|
||||||
|
<div id='custom-wizard-main'></div>
|
||||||
|
|
||||||
|
<%- unless customization_disabled? %>
|
||||||
|
<%= raw wizard_theme_lookup("body_tag") %>
|
||||||
|
<%- end %>
|
||||||
|
|
||||||
|
<%- if current_user %>
|
||||||
|
<%= preload_script 'wizard-custom-start' %>
|
||||||
|
<%- else %>
|
||||||
|
<%= preload_script 'wizard-custom-guest' %>
|
||||||
|
<%- end %>
|
||||||
|
|
||||||
|
<div id="svg-sprites" style="display:none;">
|
||||||
|
<div class="fontawesome">
|
||||||
|
<%= raw SvgSprite.bundle %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="hidden" id="data-preloaded-wizard" data-preloaded-wizard="<%= preloaded_json %>"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,3 +0,0 @@
|
||||||
import Component from "@ember/component";
|
|
||||||
|
|
||||||
export default Component.extend({});
|
|
|
@ -1,3 +0,0 @@
|
||||||
import Component from "@ember/component";
|
|
||||||
|
|
||||||
export default Component.extend({});
|
|
|
@ -1,3 +0,0 @@
|
||||||
import Component from "@ember/component";
|
|
||||||
|
|
||||||
export default Component.extend({});
|
|
|
@ -1,3 +0,0 @@
|
||||||
import Component from "@ember/component";
|
|
||||||
|
|
||||||
export default Component.extend({});
|
|
|
@ -1,3 +0,0 @@
|
||||||
import Component from "@ember/component";
|
|
||||||
|
|
||||||
export default Component.extend({});
|
|
|
@ -1,3 +0,0 @@
|
||||||
import TimeInput from "discourse/components/time-input";
|
|
||||||
|
|
||||||
export default TimeInput.extend({});
|
|
|
@ -1,34 +0,0 @@
|
||||||
<DModal @closeModal={{@closeModal}} @title={{this.title}}>
|
|
||||||
{{#if loading}}
|
|
||||||
<LoadingSpinner size="large" />
|
|
||||||
{{else}}
|
|
||||||
<div class="edit-directory-columns-container">
|
|
||||||
{{#each @model.columns as |column|}}
|
|
||||||
<div class="edit-directory-column">
|
|
||||||
<div class="left-content">
|
|
||||||
<label class="column-name">
|
|
||||||
<Input @type="checkbox" @checked={{column.enabled}} />
|
|
||||||
{{directory-table-header-title
|
|
||||||
field=column.label
|
|
||||||
translated=true
|
|
||||||
}}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
<div class="modal-footer">
|
|
||||||
<DButton
|
|
||||||
class="btn-primary"
|
|
||||||
@label="directory.edit_columns.save"
|
|
||||||
@action={{action "save"}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<DButton
|
|
||||||
class="btn-secondary reset-to-default"
|
|
||||||
@label="directory.edit_columns.reset_to_default"
|
|
||||||
@action={{action "resetToDefault"}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</DModal>
|
|
|
@ -1,15 +0,0 @@
|
||||||
import Component from "@glimmer/component";
|
|
||||||
import { action } from "@ember/object";
|
|
||||||
import I18n from "I18n";
|
|
||||||
|
|
||||||
export default class AdminWizardsColumnComponent extends Component {
|
|
||||||
title = I18n.t("admin.wizard.edit_columns");
|
|
||||||
|
|
||||||
@action save() {
|
|
||||||
this.args.closeModal();
|
|
||||||
}
|
|
||||||
|
|
||||||
@action resetToDefault() {
|
|
||||||
this.args.model.reset();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
<DModal
|
|
||||||
@closeModal={{@closeModal}}
|
|
||||||
class="next-session-time-modal"
|
|
||||||
@title={{this.title}}
|
|
||||||
>
|
|
||||||
<DateTimeInput
|
|
||||||
@date={{this.bufferedDateTime}}
|
|
||||||
@onChange={{action "dateTimeChanged"}}
|
|
||||||
@showTime="true"
|
|
||||||
@clearable="true"
|
|
||||||
/>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<DButton
|
|
||||||
@action={{action "submit"}}
|
|
||||||
class="btn-primary"
|
|
||||||
@label="admin.wizard.after_time_modal.done"
|
|
||||||
@disabled={{this.submitDisabled}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</DModal>
|
|
|
@ -1,30 +0,0 @@
|
||||||
import Component from "@glimmer/component";
|
|
||||||
import { tracked } from "@glimmer/tracking";
|
|
||||||
import { action } from "@ember/object";
|
|
||||||
import I18n from "I18n";
|
|
||||||
|
|
||||||
export default class NextSessionScheduledComponent extends Component {
|
|
||||||
@tracked bufferedDateTime;
|
|
||||||
title = I18n.t("admin.wizard.after_time_modal.title");
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super(...arguments);
|
|
||||||
this.bufferedDateTime = this.args.model.dateTime
|
|
||||||
? moment(this.args.model.dateTime)
|
|
||||||
: moment(Date.now());
|
|
||||||
}
|
|
||||||
|
|
||||||
get submitDisabled() {
|
|
||||||
return moment().isAfter(this.bufferedDateTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
@action submit() {
|
|
||||||
const dateTime = this.bufferedDateTime;
|
|
||||||
this.args.model.update(moment(dateTime).utc().toISOString());
|
|
||||||
this.args.closeModal();
|
|
||||||
}
|
|
||||||
|
|
||||||
@action dateTimeChanged(dateTime) {
|
|
||||||
this.bufferedDateTime = dateTime;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { default as discourseComputed } from "discourse-common/utils/decorators";
|
import { default as discourseComputed } from "discourse-common/utils/decorators";
|
||||||
|
import { subscriptionSelectKitContent } from "discourse/plugins/discourse-custom-wizard/discourse/lib/wizard-subscription";
|
||||||
import { empty, equal, or } from "@ember/object/computed";
|
import { empty, equal, or } from "@ember/object/computed";
|
||||||
import { notificationLevels, selectKitContent } from "../lib/wizard";
|
import { notificationLevels, selectKitContent } from "../lib/wizard";
|
||||||
import { computed } from "@ember/object";
|
import { computed } from "@ember/object";
|
||||||
|
@ -15,7 +16,6 @@ export default Component.extend(UndoChanges, {
|
||||||
createTopic: equal("action.type", "create_topic"),
|
createTopic: equal("action.type", "create_topic"),
|
||||||
updateProfile: equal("action.type", "update_profile"),
|
updateProfile: equal("action.type", "update_profile"),
|
||||||
watchCategories: equal("action.type", "watch_categories"),
|
watchCategories: equal("action.type", "watch_categories"),
|
||||||
watchTags: equal("action.type", "watch_tags"),
|
|
||||||
sendMessage: equal("action.type", "send_message"),
|
sendMessage: equal("action.type", "send_message"),
|
||||||
openComposer: equal("action.type", "open_composer"),
|
openComposer: equal("action.type", "open_composer"),
|
||||||
sendToApi: equal("action.type", "send_to_api"),
|
sendToApi: equal("action.type", "send_to_api"),
|
||||||
|
@ -37,11 +37,13 @@ export default Component.extend(UndoChanges, {
|
||||||
availableNotificationLevels: notificationLevels.map((type) => {
|
availableNotificationLevels: notificationLevels.map((type) => {
|
||||||
return {
|
return {
|
||||||
id: type,
|
id: type,
|
||||||
name: I18n.t(`admin.wizard.action.watch_x.notification_level.${type}`),
|
name: I18n.t(
|
||||||
|
`admin.wizard.action.watch_categories.notification_level.${type}`
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
|
||||||
messageUrl: "https://discourse.pluginmanager.org/t/action-settings",
|
messageUrl: "https://thepavilion.io/t/2810",
|
||||||
|
|
||||||
@discourseComputed("action.type")
|
@discourseComputed("action.type")
|
||||||
messageKey(type) {
|
messageKey(type) {
|
||||||
|
@ -92,13 +94,8 @@ export default Component.extend(UndoChanges, {
|
||||||
return apis.find((a) => a.name === api).endpoints;
|
return apis.find((a) => a.name === api).endpoints;
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed("fieldTypes")
|
@discourseComputed
|
||||||
hasEventField(fieldTypes) {
|
actionTypes() {
|
||||||
return fieldTypes.map((ft) => ft.id).includes("event");
|
return subscriptionSelectKitContent("action", "types");
|
||||||
},
|
|
||||||
|
|
||||||
@discourseComputed("fieldTypes")
|
|
||||||
hasLocationField(fieldTypes) {
|
|
||||||
return fieldTypes.map((ft) => ft.id).includes("location");
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -27,7 +27,7 @@ export default Component.extend(UndoChanges, {
|
||||||
isTextType: or("isText", "isTextarea", "isComposer"),
|
isTextType: or("isText", "isTextarea", "isComposer"),
|
||||||
isComposerPreview: equal("field.type", "composer_preview"),
|
isComposerPreview: equal("field.type", "composer_preview"),
|
||||||
categoryPropertyTypes: selectKitContent(["id", "slug"]),
|
categoryPropertyTypes: selectKitContent(["id", "slug"]),
|
||||||
messageUrl: "https://discourse.pluginmanager.org/t/field-settings",
|
messageUrl: "https://thepavilion.io/t/2809",
|
||||||
|
|
||||||
@discourseComputed("field.type")
|
@discourseComputed("field.type")
|
||||||
validations(type) {
|
validations(type) {
|
||||||
|
@ -143,17 +143,11 @@ export default Component.extend(UndoChanges, {
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
imageUploadDone(upload) {
|
imageUploadDone(upload) {
|
||||||
this.setProperties({
|
this.set("field.image", upload.url);
|
||||||
"field.image": upload.url,
|
|
||||||
"field.image_upload_id": upload.id,
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
imageUploadDeleted() {
|
imageUploadDeleted() {
|
||||||
this.setProperties({
|
this.set("field.image", null);
|
||||||
"field.image": null,
|
|
||||||
"field.image_upload_id": null,
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -24,17 +24,11 @@ export default Component.extend({
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
bannerUploadDone(upload) {
|
bannerUploadDone(upload) {
|
||||||
this.setProperties({
|
this.set("step.banner", upload.url);
|
||||||
"step.banner": upload.url,
|
|
||||||
"step.banner_upload_id": upload.id,
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
bannerUploadDeleted() {
|
bannerUploadDeleted() {
|
||||||
this.setProperties({
|
this.set("step.banner", null);
|
||||||
"step.banner": null,
|
|
||||||
"step.banner_upload_id": null,
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -71,17 +71,6 @@ export default Component.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getNextIndex() {
|
|
||||||
const items = this.items;
|
|
||||||
if (!items || items.length === 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
const numbers = items
|
|
||||||
.map((i) => Number(i.id.split("_").pop()))
|
|
||||||
.sort((a, b) => a - b);
|
|
||||||
return numbers[numbers.length - 1];
|
|
||||||
},
|
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
add() {
|
add() {
|
||||||
const items = this.get("items");
|
const items = this.get("items");
|
||||||
|
@ -89,9 +78,16 @@ export default Component.extend({
|
||||||
let params = setWizardDefaults({}, itemType);
|
let params = setWizardDefaults({}, itemType);
|
||||||
|
|
||||||
params.isNew = true;
|
params.isNew = true;
|
||||||
params.index = this.getNextIndex();
|
|
||||||
|
|
||||||
let id = `${itemType}_${params.index + 1}`;
|
let index = 0;
|
||||||
|
if (items.length) {
|
||||||
|
let last_item = items[items.length - 1];
|
||||||
|
index = Number(last_item.id.split("_").pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
params.index = index;
|
||||||
|
|
||||||
|
let id = `${itemType}_${index + 1}`;
|
||||||
if (itemType === "field") {
|
if (itemType === "field") {
|
||||||
id = `${this.parentId}_${id}`;
|
id = `${this.parentId}_${id}`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@ import {
|
||||||
import Component from "@ember/component";
|
import Component from "@ember/component";
|
||||||
import { bind, later } from "@ember/runloop";
|
import { bind, later } from "@ember/runloop";
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
import Subscription from "../mixins/subscription";
|
|
||||||
|
|
||||||
const customFieldActionMap = {
|
const customFieldActionMap = {
|
||||||
topic: ["create_topic", "send_message"],
|
topic: ["create_topic", "send_message"],
|
||||||
|
@ -27,7 +26,7 @@ const customFieldActionMap = {
|
||||||
|
|
||||||
const values = ["present", "true", "false"];
|
const values = ["present", "true", "false"];
|
||||||
|
|
||||||
export default Component.extend(Subscription, {
|
export default Component.extend({
|
||||||
classNameBindings: [":mapper-selector", "activeType"],
|
classNameBindings: [":mapper-selector", "activeType"],
|
||||||
|
|
||||||
showText: computed("activeType", function () {
|
showText: computed("activeType", function () {
|
||||||
|
@ -117,9 +116,6 @@ export default Component.extend(Subscription, {
|
||||||
groupEnabled: computed("options.groupSelection", "inputType", function () {
|
groupEnabled: computed("options.groupSelection", "inputType", function () {
|
||||||
return this.optionEnabled("groupSelection");
|
return this.optionEnabled("groupSelection");
|
||||||
}),
|
}),
|
||||||
guestGroup: computed("options.guestGroup", "inputType", function () {
|
|
||||||
return this.optionEnabled("guestGroup");
|
|
||||||
}),
|
|
||||||
userEnabled: computed("options.userSelection", "inputType", function () {
|
userEnabled: computed("options.userSelection", "inputType", function () {
|
||||||
return this.optionEnabled("userSelection");
|
return this.optionEnabled("userSelection");
|
||||||
}),
|
}),
|
||||||
|
@ -130,29 +126,7 @@ export default Component.extend(Subscription, {
|
||||||
return this.connector === "is";
|
return this.connector === "is";
|
||||||
}),
|
}),
|
||||||
|
|
||||||
@discourseComputed("site.groups", "guestGroup", "subscriptionType")
|
groups: alias("site.groups"),
|
||||||
groups(groups, guestGroup, subscriptionType) {
|
|
||||||
let result = groups;
|
|
||||||
if (!guestGroup) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (["standard", "business"].includes(subscriptionType)) {
|
|
||||||
let guestIndex;
|
|
||||||
result.forEach((r, index) => {
|
|
||||||
if (r.id === 0) {
|
|
||||||
r.name = I18n.t("admin.wizard.selector.label.users");
|
|
||||||
guestIndex = index;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
result.splice(guestIndex, 0, {
|
|
||||||
id: -1,
|
|
||||||
name: I18n.t("admin.wizard.selector.label.guests"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
categories: alias("site.categories"),
|
categories: alias("site.categories"),
|
||||||
showComboBox: or(
|
showComboBox: or(
|
||||||
"showWizardField",
|
"showWizardField",
|
||||||
|
@ -403,7 +377,7 @@ export default Component.extend(Subscription, {
|
||||||
this.changeValue(event.target.value);
|
this.changeValue(event.target.value);
|
||||||
},
|
},
|
||||||
|
|
||||||
changeUserValue(value) {
|
changeUserValue(previousValue, value) {
|
||||||
this.changeValue(value);
|
this.changeValue(value);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -32,7 +32,6 @@ export default Component.extend({
|
||||||
pairConnector: options.pairConnector || null,
|
pairConnector: options.pairConnector || null,
|
||||||
outputConnector: options.outputConnector || null,
|
outputConnector: options.outputConnector || null,
|
||||||
context: options.context || null,
|
context: options.context || null,
|
||||||
guestGroup: options.guestGroup || false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let inputTypes = ["key", "value", "output"];
|
let inputTypes = ["key", "value", "output"];
|
||||||
|
|
|
@ -11,7 +11,7 @@ export default Component.extend(Subscription, {
|
||||||
|
|
||||||
@discourseComputed("subscriptionType")
|
@discourseComputed("subscriptionType")
|
||||||
i18nKey(type) {
|
i18nKey(type) {
|
||||||
return `admin.wizard.subscription.type.${type ? type : "none"}`;
|
return `admin.wizard.subscription_container.type.${type ? type : "none"}`;
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed("i18nKey")
|
@discourseComputed("i18nKey")
|
||||||
|
|
|
@ -7,19 +7,19 @@ export default Component.extend(Subscription, {
|
||||||
|
|
||||||
@discourseComputed("subscribed")
|
@discourseComputed("subscribed")
|
||||||
subscribedIcon(subscribed) {
|
subscribedIcon(subscribed) {
|
||||||
return subscribed ? "check" : "times";
|
return subscribed ? "check" : "dash";
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed("subscribed")
|
@discourseComputed("subscribed")
|
||||||
subscribedLabel(subscribed) {
|
subscribedLabel(subscribed) {
|
||||||
return `admin.wizard.subscription.${
|
return `admin.wizard.subscription_container.${
|
||||||
subscribed ? "subscribed" : "not_subscribed"
|
subscribed ? "subscribed" : "not_subscribed"
|
||||||
}.label`;
|
}.label`;
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed("subscribed")
|
@discourseComputed("subscribed")
|
||||||
subscribedTitle(subscribed) {
|
subscribedTitle(subscribed) {
|
||||||
return `admin.wizard.subscription.${
|
return `admin.wizard.subscription_container.${
|
||||||
subscribed ? "subscribed" : "not_subscribed"
|
subscribed ? "subscribed" : "not_subscribed"
|
||||||
}.title`;
|
}.title`;
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
import Component from "@ember/component";
|
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
|
||||||
import Subscription from "../mixins/subscription";
|
|
||||||
import I18n from "I18n";
|
|
||||||
|
|
||||||
export default Component.extend(Subscription, {
|
|
||||||
tagName: "a",
|
|
||||||
classNameBindings: [":btn", ":btn-pavilion-support", "subscriptionType"],
|
|
||||||
attributeBindings: ["title"],
|
|
||||||
|
|
||||||
@discourseComputed("subscribed")
|
|
||||||
i18nKey(subscribed) {
|
|
||||||
return `admin.wizard.subscription.cta.${
|
|
||||||
subscribed ? "subscribed" : "none"
|
|
||||||
}`;
|
|
||||||
},
|
|
||||||
|
|
||||||
@discourseComputed("subscribed")
|
|
||||||
icon(subscribed) {
|
|
||||||
return subscribed ? "far-life-ring" : "external-link-alt";
|
|
||||||
},
|
|
||||||
|
|
||||||
@discourseComputed("i18nKey")
|
|
||||||
title(i18nKey) {
|
|
||||||
return I18n.t(`${i18nKey}.title`);
|
|
||||||
},
|
|
||||||
|
|
||||||
@discourseComputed("i18nKey")
|
|
||||||
label(i18nKey) {
|
|
||||||
return I18n.t(`${i18nKey}.label`);
|
|
||||||
},
|
|
||||||
|
|
||||||
click() {
|
|
||||||
window.open(this.subscriptionCtaLink, "_blank").focus();
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,6 +1,10 @@
|
||||||
import SingleSelectComponent from "select-kit/components/single-select";
|
import SingleSelectComponent from "select-kit/components/single-select";
|
||||||
import Subscription from "../mixins/subscription";
|
import Subscription from "../mixins/subscription";
|
||||||
import { filterValues } from "discourse/plugins/discourse-custom-wizard/discourse/lib/wizard-schema";
|
import wizardSchema from "discourse/plugins/discourse-custom-wizard/discourse/lib/wizard-schema";
|
||||||
|
import {
|
||||||
|
subscriptionTypeSufficient,
|
||||||
|
subscriptionTypes,
|
||||||
|
} from "discourse/plugins/discourse-custom-wizard/discourse/lib/wizard-subscription";
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
|
|
||||||
|
@ -25,68 +29,44 @@ export default SingleSelectComponent.extend(Subscription, {
|
||||||
caretDownIcon: "caret-down",
|
caretDownIcon: "caret-down",
|
||||||
},
|
},
|
||||||
|
|
||||||
allowedSubscriptionTypes(feature, attribute, value) {
|
requiredSubscriptionType(feature, attribute, value) {
|
||||||
let attributes = this.subscriptionAttributes[feature];
|
let attributes = this.subscriptionAttributes[feature];
|
||||||
if (!attributes || !attributes[attribute]) {
|
if (!attributes || !attributes[attribute]) {
|
||||||
return ["none"];
|
return null;
|
||||||
}
|
}
|
||||||
let allowedTypes = [];
|
|
||||||
Object.keys(attributes[attribute]).forEach((subscriptionType) => {
|
let requiredType = null;
|
||||||
|
Object.keys(attributes[attribute]).some((subscriptionType) => {
|
||||||
let values = attributes[attribute][subscriptionType];
|
let values = attributes[attribute][subscriptionType];
|
||||||
if (values[0] === "*" || values.includes(value)) {
|
if (values[0] === "*" || values.includes(value)) {
|
||||||
allowedTypes.push(subscriptionType);
|
if (subscriptionTypes.includes(subscriptionType)) {
|
||||||
|
requiredType = subscriptionType;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
return allowedTypes;
|
|
||||||
|
return requiredType;
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed("feature", "attribute", "wizard.allowGuests")
|
@discourseComputed("feature", "attribute")
|
||||||
content(feature, attribute) {
|
content(feature, attribute) {
|
||||||
return filterValues(this.wizard, feature, attribute)
|
return wizardSchema[feature][attribute].map((value) => {
|
||||||
.map((value) => {
|
let requiredSubscriptionType = this.requiredSubscriptionType(
|
||||||
let allowedSubscriptionTypes = this.allowedSubscriptionTypes(
|
|
||||||
feature,
|
feature,
|
||||||
attribute,
|
attribute,
|
||||||
value
|
value
|
||||||
);
|
);
|
||||||
|
return {
|
||||||
let subscriptionRequired =
|
|
||||||
allowedSubscriptionTypes.length &&
|
|
||||||
!allowedSubscriptionTypes.includes("none");
|
|
||||||
|
|
||||||
let attrs = {
|
|
||||||
id: value,
|
id: value,
|
||||||
name: I18n.t(nameKey(feature, attribute, value)),
|
name: I18n.t(nameKey(feature, attribute, value)),
|
||||||
subscriptionRequired,
|
subscriptionType: requiredSubscriptionType,
|
||||||
|
disabled: !subscriptionTypeSufficient(
|
||||||
|
this.subscriptionType,
|
||||||
|
requiredSubscriptionType
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (subscriptionRequired) {
|
|
||||||
let subscribed = allowedSubscriptionTypes.includes(
|
|
||||||
this.subscriptionType
|
|
||||||
);
|
|
||||||
let selectorKey = subscribed ? "subscribed" : "not_subscribed";
|
|
||||||
let selectorLabel = `admin.wizard.subscription.${selectorKey}.selector`;
|
|
||||||
|
|
||||||
attrs.disabled = !subscribed;
|
|
||||||
attrs.selectorLabel = selectorLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
return attrs;
|
|
||||||
})
|
|
||||||
.sort(function (a, b) {
|
|
||||||
if (a.subscriptionType && !b.subscriptionType) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (!a.subscriptionType && b.subscriptionType) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (a.subscriptionType === b.subscriptionType) {
|
|
||||||
return a.subscriptionType
|
|
||||||
? a.subscriptionType.localeCompare(b.subscriptionType)
|
|
||||||
: 0;
|
|
||||||
} else {
|
|
||||||
return a.subscriptionType === "standard" ? -1 : 0;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -25,9 +25,9 @@ export default Component.extend({
|
||||||
textState: "text-collapsed",
|
textState: "text-collapsed",
|
||||||
toggleText: I18n.t("admin.wizard.expand_text"),
|
toggleText: I18n.t("admin.wizard.expand_text"),
|
||||||
|
|
||||||
@discourseComputed("value", "isUser", "isSubmittedAt")
|
@discourseComputed("value", "isUser")
|
||||||
hasValue(value, isUser, isSubmittedAt) {
|
hasValue(value, isUser) {
|
||||||
if (isUser || isSubmittedAt) {
|
if (isUser) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
return value && value.value;
|
return value && value.value;
|
||||||
|
|
|
@ -5,7 +5,11 @@ import { scheduleOnce } from "@ember/runloop";
|
||||||
import Component from "@ember/component";
|
import Component from "@ember/component";
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
|
|
||||||
const excludedUserProperties = ["profile_background", "card_background"];
|
const excludedUserProperties = [
|
||||||
|
"avatar",
|
||||||
|
"profile_background",
|
||||||
|
"card_background",
|
||||||
|
];
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
classNames: "wizard-text-editor",
|
classNames: "wizard-text-editor",
|
||||||
|
@ -48,12 +52,12 @@ export default Component.extend({
|
||||||
|
|
||||||
@discourseComputed("wizardFields")
|
@discourseComputed("wizardFields")
|
||||||
wizardFieldList(wizardFields) {
|
wizardFieldList(wizardFields) {
|
||||||
return (wizardFields || []).map((f) => ` w{${f.id}}`);
|
return wizardFields.map((f) => ` w{${f.id}}`);
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed("wizardActions")
|
@discourseComputed("wizardActions")
|
||||||
wizardActionList(wizardActions) {
|
wizardActionList(wizardActions) {
|
||||||
return (wizardActions || []).map((a) => ` w{${a.id}}`);
|
return wizardActions.map((a) => ` w{${a.id}}`);
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
value=wizardListVal
|
value=wizardListVal
|
||||||
content=wizardList
|
content=wizardList
|
||||||
onChange=(action "changeWizard")
|
onChange=(action "changeWizard")
|
||||||
options=(hash none="admin.wizard.select")
|
options=(hash
|
||||||
}}
|
none="admin.wizard.select"
|
||||||
|
)}}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
|
@ -1,9 +1,9 @@
|
||||||
import CustomWizardAdmin from "../../models/custom-wizard-admin";
|
import CustomWizard from "../../models/custom-wizard";
|
||||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
setupComponent(attrs, component) {
|
setupComponent(attrs, component) {
|
||||||
CustomWizardAdmin.all()
|
CustomWizard.all()
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
component.set("wizardList", result);
|
component.set("wizardList", result);
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
{{#each site.complete_custom_wizard as |wizard|}}
|
{{#each site.complete_custom_wizard as |wizard|}}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="alert alert-info alert-wizard">
|
<div class="alert alert-info alert-wizard">
|
||||||
<a href={{wizard.url}}>{{i18n
|
<a href={{wizard.url}}>{{i18n "wizard.complete_custom" name=wizard.name}}</a>
|
||||||
"wizard.complete_custom"
|
|
||||||
name=wizard.name
|
|
||||||
}}</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
|
@ -4,14 +4,10 @@ import CustomWizardApi from "../models/custom-wizard-api";
|
||||||
import { default as discourseComputed } from "discourse-common/utils/decorators";
|
import { default as discourseComputed } from "discourse-common/utils/decorators";
|
||||||
import { and, equal, not } from "@ember/object/computed";
|
import { and, equal, not } from "@ember/object/computed";
|
||||||
import { selectKitContent } from "../lib/wizard";
|
import { selectKitContent } from "../lib/wizard";
|
||||||
import { underscore } from "@ember/string";
|
|
||||||
import Controller from "@ember/controller";
|
import Controller from "@ember/controller";
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
import { inject as service } from "@ember/service";
|
|
||||||
|
|
||||||
export default Controller.extend({
|
export default Controller.extend({
|
||||||
router: service(),
|
|
||||||
|
|
||||||
queryParams: ["refresh_list"],
|
queryParams: ["refresh_list"],
|
||||||
loadingSubscriptions: false,
|
loadingSubscriptions: false,
|
||||||
notAuthorized: not("api.authorized"),
|
notAuthorized: not("api.authorized"),
|
||||||
|
@ -24,8 +20,29 @@ export default Controller.extend({
|
||||||
"application/x-www-form-urlencoded",
|
"application/x-www-form-urlencoded",
|
||||||
]),
|
]),
|
||||||
successCodes: selectKitContent([
|
successCodes: selectKitContent([
|
||||||
100, 101, 102, 200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 300, 301,
|
100,
|
||||||
302, 303, 303, 304, 305, 306, 307, 308,
|
101,
|
||||||
|
102,
|
||||||
|
200,
|
||||||
|
201,
|
||||||
|
202,
|
||||||
|
203,
|
||||||
|
204,
|
||||||
|
205,
|
||||||
|
206,
|
||||||
|
207,
|
||||||
|
208,
|
||||||
|
226,
|
||||||
|
300,
|
||||||
|
301,
|
||||||
|
302,
|
||||||
|
303,
|
||||||
|
303,
|
||||||
|
304,
|
||||||
|
305,
|
||||||
|
306,
|
||||||
|
307,
|
||||||
|
308,
|
||||||
]),
|
]),
|
||||||
|
|
||||||
@discourseComputed(
|
@discourseComputed(
|
||||||
|
@ -71,11 +88,6 @@ export default Controller.extend({
|
||||||
twoLeggedOauth: equal("api.authType", "oauth_2"),
|
twoLeggedOauth: equal("api.authType", "oauth_2"),
|
||||||
threeLeggedOauth: equal("api.authType", "oauth_3"),
|
threeLeggedOauth: equal("api.authType", "oauth_3"),
|
||||||
|
|
||||||
@discourseComputed("api.isNew")
|
|
||||||
nameClass(isNew) {
|
|
||||||
return isNew ? "new" : "saved";
|
|
||||||
},
|
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
addParam() {
|
addParam() {
|
||||||
this.get("api.authParams").pushObject({});
|
this.get("api.authParams").pushObject({});
|
||||||
|
@ -101,7 +113,7 @@ export default Controller.extend({
|
||||||
|
|
||||||
if (authType === "oauth_2") {
|
if (authType === "oauth_2") {
|
||||||
this.set("authorizing", true);
|
this.set("authorizing", true);
|
||||||
ajax(`/admin/wizards/apis/${underscore(name)}/authorize`)
|
ajax(`/admin/wizards/apis/${name.underscore()}/authorize`)
|
||||||
.catch(popupAjaxError)
|
.catch(popupAjaxError)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
|
@ -137,6 +149,7 @@ export default Controller.extend({
|
||||||
const api = this.get("api");
|
const api = this.get("api");
|
||||||
const name = api.name;
|
const name = api.name;
|
||||||
const authType = api.authType;
|
const authType = api.authType;
|
||||||
|
let refreshList = false; // eslint-disable-line
|
||||||
let error;
|
let error;
|
||||||
|
|
||||||
if (!name || !authType) {
|
if (!name || !authType) {
|
||||||
|
@ -151,6 +164,11 @@ export default Controller.extend({
|
||||||
data["title"] = api.title;
|
data["title"] = api.title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const originalTitle = this.get("api.originalTitle");
|
||||||
|
if (api.get("isNew") || (originalTitle && api.title !== originalTitle)) {
|
||||||
|
refreshList = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (api.get("isNew")) {
|
if (api.get("isNew")) {
|
||||||
data["new"] = true;
|
data["new"] = true;
|
||||||
}
|
}
|
||||||
|
@ -170,11 +188,11 @@ export default Controller.extend({
|
||||||
if (!api[rp]) {
|
if (!api[rp]) {
|
||||||
let key = rp.replace("auth", "");
|
let key = rp.replace("auth", "");
|
||||||
error = `${I18n.t(
|
error = `${I18n.t(
|
||||||
`admin.wizard.api.auth.${underscore(key)}`
|
`admin.wizard.api.auth.${key.underscore()}`
|
||||||
)} is required for ${authType}`;
|
)} is required for ${authType}`;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
data[underscore(rp)] = api[rp];
|
data[rp.underscore()] = api[rp];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,7 +222,7 @@ export default Controller.extend({
|
||||||
|
|
||||||
this.set("updating", true);
|
this.set("updating", true);
|
||||||
|
|
||||||
ajax(`/admin/wizards/api/${underscore(name)}`, {
|
ajax(`/admin/wizards/api/${name.underscore()}`, {
|
||||||
type: "PUT",
|
type: "PUT",
|
||||||
data,
|
data,
|
||||||
})
|
})
|
||||||
|
@ -227,7 +245,7 @@ export default Controller.extend({
|
||||||
|
|
||||||
this.set("updating", true);
|
this.set("updating", true);
|
||||||
|
|
||||||
ajax(`/admin/wizards/api/${underscore(name)}`, {
|
ajax(`/admin/wizards/api/${name.underscore()}`, {
|
||||||
type: "DELETE",
|
type: "DELETE",
|
||||||
})
|
})
|
||||||
.catch(popupAjaxError)
|
.catch(popupAjaxError)
|
||||||
|
@ -245,13 +263,13 @@ export default Controller.extend({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ajax(`/admin/wizards/api/${underscore(name)}/logs`, {
|
ajax(`/admin/wizards/api/${name.underscore()}/logs`, {
|
||||||
type: "DELETE",
|
type: "DELETE",
|
||||||
})
|
})
|
||||||
.catch(popupAjaxError)
|
.catch(popupAjaxError)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
this.router.transitionTo("adminWizardsApis").then(() => {
|
this.transitionToRoute("adminWizardsApis").then(() => {
|
||||||
this.send("refreshModel");
|
this.send("refreshModel");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
import Controller from "@ember/controller";
|
||||||
|
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||||
|
|
||||||
|
export default Controller.extend(ModalFunctionality, {
|
||||||
|
actions: {
|
||||||
|
save() {
|
||||||
|
this.send("closeModal");
|
||||||
|
},
|
||||||
|
|
||||||
|
resetToDefault() {
|
||||||
|
this.get("model.reset")();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
|
@ -4,7 +4,7 @@ import CustomWizardCustomField from "../models/custom-wizard-custom-field";
|
||||||
export default Controller.extend({
|
export default Controller.extend({
|
||||||
messageKey: "create",
|
messageKey: "create",
|
||||||
fieldKeys: ["klass", "type", "name", "serializers"],
|
fieldKeys: ["klass", "type", "name", "serializers"],
|
||||||
documentationUrl: "https://discourse.pluginmanager.org/t/custom-fields",
|
documentationUrl: "https://thepavilion.io/t/3572",
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
addField() {
|
addField() {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import I18n from "I18n";
|
||||||
import { underscore } from "@ember/string";
|
import { underscore } from "@ember/string";
|
||||||
|
|
||||||
export default Controller.extend({
|
export default Controller.extend({
|
||||||
messageUrl: "https://discourse.pluginmanager.org/t/wizard-manager",
|
messageUrl: "https://thepavilion.io/t/3652",
|
||||||
messageKey: "info",
|
messageKey: "info",
|
||||||
messageIcon: "info-circle",
|
messageIcon: "info-circle",
|
||||||
messageClass: "info",
|
messageClass: "info",
|
||||||
|
@ -68,7 +68,7 @@ export default Controller.extend({
|
||||||
file: null,
|
file: null,
|
||||||
filename: null,
|
filename: null,
|
||||||
});
|
});
|
||||||
document.getElementById("custom-wizard-file-upload").value = "";
|
$("#file-upload").val("");
|
||||||
},
|
},
|
||||||
|
|
||||||
@observes("importing", "destroying")
|
@observes("importing", "destroying")
|
||||||
|
@ -83,7 +83,7 @@ export default Controller.extend({
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
upload() {
|
upload() {
|
||||||
document.getElementById("custom-wizard-file-upload").click();
|
$("#file-upload").click();
|
||||||
},
|
},
|
||||||
|
|
||||||
clearFile() {
|
clearFile() {
|
||||||
|
@ -102,7 +102,7 @@ export default Controller.extend({
|
||||||
if (maxFileSize < file.size) {
|
if (maxFileSize < file.size) {
|
||||||
this.setMessage("error", "file_size_error");
|
this.setMessage("error", "file_size_error");
|
||||||
this.set("file", null);
|
this.set("file", null);
|
||||||
document.getElementById("custom-wizard-file-upload").value = "";
|
$("#file-upload").val("");
|
||||||
} else {
|
} else {
|
||||||
this.setProperties({
|
this.setProperties({
|
||||||
file,
|
file,
|
||||||
|
|
|
@ -2,13 +2,10 @@ import Controller from "@ember/controller";
|
||||||
import { empty } from "@ember/object/computed";
|
import { empty } from "@ember/object/computed";
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
import { fmt } from "discourse/lib/computed";
|
import { fmt } from "discourse/lib/computed";
|
||||||
import { inject as service } from "@ember/service";
|
import showModal from "discourse/lib/show-modal";
|
||||||
import AdminWizardsColumnsModal from "../components/modal/admin-wizards-columns";
|
import CustomWizard from "../models/custom-wizard";
|
||||||
import CustomWizardAdmin from "../models/custom-wizard-admin";
|
|
||||||
import { formatModel } from "../lib/wizard-submission";
|
|
||||||
|
|
||||||
export default Controller.extend({
|
export default Controller.extend({
|
||||||
modal: service(),
|
|
||||||
downloadUrl: fmt("wizard.id", "/admin/wizards/submissions/%@/download"),
|
downloadUrl: fmt("wizard.id", "/admin/wizards/submissions/%@/download"),
|
||||||
noResults: empty("submissions"),
|
noResults: empty("submissions"),
|
||||||
page: 0,
|
page: 0,
|
||||||
|
@ -19,12 +16,10 @@ export default Controller.extend({
|
||||||
const wizardId = this.get("wizard.id");
|
const wizardId = this.get("wizard.id");
|
||||||
|
|
||||||
this.set("loadingMore", true);
|
this.set("loadingMore", true);
|
||||||
CustomWizardAdmin.submissions(wizardId, page)
|
CustomWizard.submissions(wizardId, page)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
if (result.submissions) {
|
if (result.submissions) {
|
||||||
const { submissions } = formatModel(result);
|
this.get("submissions").pushObjects(result.submissions);
|
||||||
|
|
||||||
this.get("submissions").pushObjects(submissions);
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
|
@ -32,7 +27,7 @@ export default Controller.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed("submissions.[]", "fields.@each.enabled")
|
@discourseComputed("submissions", "fields.@each.enabled")
|
||||||
displaySubmissions(submissions, fields) {
|
displaySubmissions(submissions, fields) {
|
||||||
let result = [];
|
let result = [];
|
||||||
|
|
||||||
|
@ -59,7 +54,7 @@ export default Controller.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
showEditColumnsModal() {
|
showEditColumnsModal() {
|
||||||
return this.modal.show(AdminWizardsColumnsModal, {
|
return showModal("admin-wizards-columns", {
|
||||||
model: {
|
model: {
|
||||||
columns: this.get("fields"),
|
columns: this.get("fields"),
|
||||||
reset: () => {
|
reset: () => {
|
||||||
|
|
|
@ -3,18 +3,15 @@ import {
|
||||||
observes,
|
observes,
|
||||||
} from "discourse-common/utils/decorators";
|
} from "discourse-common/utils/decorators";
|
||||||
import { notEmpty } from "@ember/object/computed";
|
import { notEmpty } from "@ember/object/computed";
|
||||||
import { inject as service } from "@ember/service";
|
import showModal from "discourse/lib/show-modal";
|
||||||
import NextSessionScheduledModal from "../components/modal/next-session-scheduled";
|
|
||||||
import { generateId, wizardFieldList } from "../lib/wizard";
|
import { generateId, wizardFieldList } from "../lib/wizard";
|
||||||
import { dasherize } from "@ember/string";
|
import { dasherize } from "@ember/string";
|
||||||
import { later, scheduleOnce } from "@ember/runloop";
|
import { later, scheduleOnce } from "@ember/runloop";
|
||||||
import Controller from "@ember/controller";
|
import Controller from "@ember/controller";
|
||||||
import copyText from "discourse/lib/copy-text";
|
import copyText from "discourse/lib/copy-text";
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
import { filterValues } from "discourse/plugins/discourse-custom-wizard/discourse/lib/wizard-schema";
|
|
||||||
|
|
||||||
export default Controller.extend({
|
export default Controller.extend({
|
||||||
modal: service(),
|
|
||||||
hasName: notEmpty("wizard.name"),
|
hasName: notEmpty("wizard.name"),
|
||||||
|
|
||||||
@observes("currentStep")
|
@observes("currentStep")
|
||||||
|
@ -39,8 +36,7 @@ export default Controller.extend({
|
||||||
|
|
||||||
@discourseComputed("wizard.id")
|
@discourseComputed("wizard.id")
|
||||||
wizardUrl(wizardId) {
|
wizardUrl(wizardId) {
|
||||||
let baseUrl = window.location.href.split("/admin");
|
return window.location.origin + "/w/" + dasherize(wizardId);
|
||||||
return baseUrl[0] + "/w/" + dasherize(wizardId);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed("wizard.after_time_scheduled")
|
@discourseComputed("wizard.after_time_scheduled")
|
||||||
|
@ -62,19 +58,6 @@ export default Controller.extend({
|
||||||
}
|
}
|
||||||
return wizardFieldList(steps);
|
return wizardFieldList(steps);
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed("fieldTypes", "wizard.allowGuests")
|
|
||||||
filteredFieldTypes(fieldTypes) {
|
|
||||||
const fieldTypeIds = fieldTypes.map((f) => f.id);
|
|
||||||
const allowedTypeIds = filterValues(
|
|
||||||
this.wizard,
|
|
||||||
"field",
|
|
||||||
"type",
|
|
||||||
fieldTypeIds
|
|
||||||
);
|
|
||||||
return fieldTypes.filter((f) => allowedTypeIds.includes(f.id));
|
|
||||||
},
|
|
||||||
|
|
||||||
getErrorMessage(result) {
|
getErrorMessage(result) {
|
||||||
if (result.backend_validation_error) {
|
if (result.backend_validation_error) {
|
||||||
return result.backend_validation_error;
|
return result.backend_validation_error;
|
||||||
|
@ -128,13 +111,15 @@ export default Controller.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
setNextSessionScheduled() {
|
setNextSessionScheduled() {
|
||||||
this.modal.show(NextSessionScheduledModal, {
|
let controller = showModal("next-session-scheduled", {
|
||||||
model: {
|
model: {
|
||||||
dateTime: this.wizard.after_time_scheduled,
|
dateTime: this.wizard.after_time_scheduled,
|
||||||
update: (dateTime) =>
|
update: (dateTime) =>
|
||||||
this.set("wizard.after_time_scheduled", dateTime),
|
this.set("wizard.after_time_scheduled", dateTime),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
controller.setup();
|
||||||
},
|
},
|
||||||
|
|
||||||
copyUrl() {
|
copyUrl() {
|
||||||
|
|
|
@ -21,6 +21,5 @@ export default Controller.extend({
|
||||||
return key;
|
return key;
|
||||||
},
|
},
|
||||||
|
|
||||||
messageUrl:
|
messageUrl: "https://thepavilion.io/c/knowledge/discourse/custom-wizard",
|
||||||
"https://discourse.pluginmanager.org/c/discourse-custom-wizard/documentation",
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import Controller from "@ember/controller";
|
import Controller from "@ember/controller";
|
||||||
import { equal, or } from "@ember/object/computed";
|
import { equal } from "@ember/object/computed";
|
||||||
|
|
||||||
export default Controller.extend({
|
export default Controller.extend({
|
||||||
businessSubscription: equal("subscriptionType", "business"),
|
businessSubscription: equal("subscriptionType", "business"),
|
||||||
communitySubscription: equal("subscriptionType", "community"),
|
|
||||||
standardSubscription: equal("subscriptionType", "standard"),
|
standardSubscription: equal("subscriptionType", "standard"),
|
||||||
showApi: or("businessSubscription", "communitySubscription"),
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { default as discourseComputed } from "discourse-common/utils/decorators";
|
||||||
|
import Controller from "@ember/controller";
|
||||||
|
|
||||||
|
export default Controller.extend({
|
||||||
|
title: "admin.wizard.after_time_modal.title",
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
this.set("bufferedDateTime", moment(this.model.dateTime));
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("bufferedDateTime")
|
||||||
|
submitDisabled(dateTime) {
|
||||||
|
return moment().isAfter(dateTime);
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
submit() {
|
||||||
|
const dateTime = this.get("bufferedDateTime");
|
||||||
|
this.get("model.update")(moment(dateTime).utc().toISOString());
|
||||||
|
this.send("closeModal");
|
||||||
|
},
|
||||||
|
|
||||||
|
dateTimeChanged(dateTime) {
|
||||||
|
this.set("bufferedDateTime", dateTime);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
|
@ -1,12 +0,0 @@
|
||||||
export default function () {
|
|
||||||
this.route(
|
|
||||||
"customWizard",
|
|
||||||
{ path: "/w/:wizard_id", resetNamespace: true },
|
|
||||||
function () {
|
|
||||||
this.route("customWizardStep", {
|
|
||||||
path: "/steps/:step_id",
|
|
||||||
resetNamespace: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
6
assets/javascripts/discourse/helpers/custom-wizard.js.es6
Normale Datei
6
assets/javascripts/discourse/helpers/custom-wizard.js.es6
Normale Datei
|
@ -0,0 +1,6 @@
|
||||||
|
import { registerUnbound } from "discourse-common/lib/helpers";
|
||||||
|
import { dasherize } from "@ember/string";
|
||||||
|
|
||||||
|
registerUnbound("dasherize", function (string) {
|
||||||
|
return dasherize(string);
|
||||||
|
});
|
|
@ -1,25 +0,0 @@
|
||||||
import { registerUnbound } from "discourse-common/lib/helpers";
|
|
||||||
import I18n from "I18n";
|
|
||||||
import Handlebars from "handlebars";
|
|
||||||
|
|
||||||
export default registerUnbound(
|
|
||||||
"wizard-char-counter",
|
|
||||||
function (body, maxLength) {
|
|
||||||
let bodyLength = body ? body.length : 0;
|
|
||||||
let finalString;
|
|
||||||
|
|
||||||
if (maxLength) {
|
|
||||||
let isOverMax = bodyLength > maxLength ? "true" : "false";
|
|
||||||
finalString = `<div class="body-length" data-length=${bodyLength} data-over-max=${isOverMax}>${bodyLength} / ${I18n.t(
|
|
||||||
"wizard.x_characters",
|
|
||||||
{ count: parseInt(maxLength, 10) }
|
|
||||||
)}</div>`;
|
|
||||||
} else {
|
|
||||||
finalString = `<div class="body-length">${I18n.t("wizard.x_characters", {
|
|
||||||
count: parseInt(bodyLength, 10),
|
|
||||||
})}</div>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Handlebars.SafeString(finalString);
|
|
||||||
}
|
|
||||||
);
|
|
|
@ -1,12 +1,11 @@
|
||||||
import DiscourseURL from "discourse/lib/url";
|
import DiscourseURL from "discourse/lib/url";
|
||||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||||
import getUrl from "discourse-common/lib/get-url";
|
import getUrl from "discourse-common/lib/get-url";
|
||||||
import { observes } from "discourse-common/utils/decorators";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "custom-wizard-edits",
|
name: "custom-wizard-edits",
|
||||||
initialize(container) {
|
initialize(container) {
|
||||||
const siteSettings = container.lookup("service:site-settings");
|
const siteSettings = container.lookup("site-settings:main");
|
||||||
|
|
||||||
if (!siteSettings.custom_wizard_enabled) {
|
if (!siteSettings.custom_wizard_enabled) {
|
||||||
return;
|
return;
|
||||||
|
@ -36,63 +35,6 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
api.modifyClass("component:uppy-image-uploader", {
|
|
||||||
pluginId: "custom-wizard",
|
|
||||||
// Needed to ensure appEvents get registered when navigating between steps
|
|
||||||
@observes("id")
|
|
||||||
initOnStepChange() {
|
|
||||||
if (/wizard-field|wizard-step/.test(this.id)) {
|
|
||||||
this._initialize();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
api.modifyClass("component:d-editor", {
|
|
||||||
pluginId: "custom-wizard",
|
|
||||||
|
|
||||||
didInsertElement() {
|
|
||||||
this._super(...arguments);
|
|
||||||
|
|
||||||
if (this.wizardComposer) {
|
|
||||||
this.appEvents.on(
|
|
||||||
`wizard-editor:insert-text`,
|
|
||||||
this,
|
|
||||||
"_wizardInsertText"
|
|
||||||
);
|
|
||||||
this.appEvents.on(
|
|
||||||
"wizard-editor:replace-text",
|
|
||||||
this,
|
|
||||||
"_wizardReplaceText"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_wizardInsertText(text, options) {
|
|
||||||
if (
|
|
||||||
this.session.wizardEventFieldId === this.fieldId &&
|
|
||||||
this.element
|
|
||||||
) {
|
|
||||||
this.insertText(text, options);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_wizardReplaceText(oldVal, newVal, opts = {}) {
|
|
||||||
if (this.session.wizardEventFieldId === this.fieldId) {
|
|
||||||
this.replaceText(oldVal, newVal, opts);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
api.modifyClass("component:category-chooser", {
|
|
||||||
categoriesByScope(options = {}) {
|
|
||||||
let categories = this._super(options);
|
|
||||||
|
|
||||||
return categories.filter((category) => {
|
|
||||||
return !category.custom_fields?.create_topic_wizard;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
import DiscourseURL from "discourse/lib/url";
|
import ApplicationRoute from "discourse/routes/application";
|
||||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
|
||||||
import { dasherize } from "@ember/string";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "custom-wizard-redirect",
|
name: "custom-wizard-redirect",
|
||||||
after: "message-bus",
|
after: "message-bus",
|
||||||
|
|
||||||
initialize(container) {
|
initialize: function (container) {
|
||||||
const messageBus = container.lookup("service:message-bus");
|
const messageBus = container.lookup("message-bus:main");
|
||||||
const siteSettings = container.lookup("service:site-settings");
|
const siteSettings = container.lookup("site-settings:main");
|
||||||
|
|
||||||
if (!siteSettings.custom_wizard_enabled) {
|
if (!siteSettings.custom_wizard_enabled || !messageBus) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,27 +17,28 @@ export default {
|
||||||
window.location.href = wizardUrl;
|
window.location.href = wizardUrl;
|
||||||
});
|
});
|
||||||
|
|
||||||
withPluginApi("0.8.36", (api) => {
|
ApplicationRoute.reopen({
|
||||||
api.onAppEvent("page:changed", (data) => {
|
actions: {
|
||||||
const currentUser = api.getCurrentUser();
|
willTransition(transition) {
|
||||||
|
const redirectToWizard = this.get("currentUser.redirect_to_wizard");
|
||||||
if (currentUser) {
|
const excludedPaths = this.siteSettings.wizard_redirect_exclude_paths
|
||||||
const redirectToWizard = currentUser.redirect_to_wizard;
|
|
||||||
const excludedPaths = siteSettings.wizard_redirect_exclude_paths
|
|
||||||
.split("|")
|
.split("|")
|
||||||
.concat(["loading"]);
|
.concat(["loading"]);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
redirectToWizard &&
|
redirectToWizard &&
|
||||||
!data.url.includes("ignore_redirect") &&
|
(!transition.intent.name ||
|
||||||
data.currentRouteName !== "customWizardStep" &&
|
|
||||||
!excludedPaths.find((p) => {
|
!excludedPaths.find((p) => {
|
||||||
return data.currentRouteName.indexOf(p) > -1;
|
return transition.intent.name.indexOf(p) > -1;
|
||||||
})
|
}))
|
||||||
) {
|
) {
|
||||||
DiscourseURL.routeTo(`/w/${dasherize(redirectToWizard)}`);
|
transition.abort();
|
||||||
|
window.location = "/w/" + redirectToWizard.dasherize();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
return this._super(transition);
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,7 +35,6 @@ function inputTypesContent(options = {}) {
|
||||||
const connectors = {
|
const connectors = {
|
||||||
pair: [
|
pair: [
|
||||||
"equal",
|
"equal",
|
||||||
"not_equal",
|
|
||||||
"greater",
|
"greater",
|
||||||
"less",
|
"less",
|
||||||
"greater_or_equal",
|
"greater_or_equal",
|
||||||
|
|
|
@ -41,7 +41,6 @@ const step = {
|
||||||
index: null,
|
index: null,
|
||||||
title: null,
|
title: null,
|
||||||
banner: null,
|
banner: null,
|
||||||
banner_upload_id: null,
|
|
||||||
raw_description: null,
|
raw_description: null,
|
||||||
required_data: null,
|
required_data: null,
|
||||||
required_data_message: null,
|
required_data_message: null,
|
||||||
|
@ -66,13 +65,11 @@ const field = {
|
||||||
index: null,
|
index: null,
|
||||||
label: null,
|
label: null,
|
||||||
image: null,
|
image: null,
|
||||||
image_upload_id: null,
|
|
||||||
description: null,
|
description: null,
|
||||||
property: null,
|
property: null,
|
||||||
required: null,
|
required: null,
|
||||||
type: null,
|
type: null,
|
||||||
condition: null,
|
condition: null,
|
||||||
tag_groups: null,
|
|
||||||
},
|
},
|
||||||
types: {},
|
types: {},
|
||||||
mapped: ["prefill", "content", "condition", "index"],
|
mapped: ["prefill", "content", "condition", "index"],
|
||||||
|
@ -99,8 +96,6 @@ const action = {
|
||||||
custom_fields: null,
|
custom_fields: null,
|
||||||
skip_redirect: null,
|
skip_redirect: null,
|
||||||
suppress_notifications: null,
|
suppress_notifications: null,
|
||||||
add_event: null,
|
|
||||||
add_location: null,
|
|
||||||
},
|
},
|
||||||
send_message: {
|
send_message: {
|
||||||
title: null,
|
title: null,
|
||||||
|
@ -133,12 +128,6 @@ const action = {
|
||||||
wizard_user: true,
|
wizard_user: true,
|
||||||
usernames: null,
|
usernames: null,
|
||||||
},
|
},
|
||||||
watch_tags: {
|
|
||||||
tags: null,
|
|
||||||
notification_level: null,
|
|
||||||
wizard_user: true,
|
|
||||||
usernames: null,
|
|
||||||
},
|
|
||||||
send_to_api: {
|
send_to_api: {
|
||||||
api: null,
|
api: null,
|
||||||
api_endpoint: null,
|
api_endpoint: null,
|
||||||
|
@ -203,50 +192,17 @@ const action = {
|
||||||
"messageable_level",
|
"messageable_level",
|
||||||
"visibility_level",
|
"visibility_level",
|
||||||
"members_visibility_level",
|
"members_visibility_level",
|
||||||
"add_event",
|
|
||||||
"add_location",
|
|
||||||
],
|
],
|
||||||
required: ["id", "type"],
|
required: ["id", "type"],
|
||||||
dependent: {},
|
dependent: {},
|
||||||
objectArrays: {},
|
objectArrays: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const filters = {
|
|
||||||
allow_guests: {
|
|
||||||
field: {
|
|
||||||
type: [
|
|
||||||
"text",
|
|
||||||
"textarea",
|
|
||||||
"text_only",
|
|
||||||
"date",
|
|
||||||
"time",
|
|
||||||
"date_time",
|
|
||||||
"number",
|
|
||||||
"checkbox",
|
|
||||||
"url",
|
|
||||||
"dropdown",
|
|
||||||
"tag",
|
|
||||||
"category",
|
|
||||||
"group",
|
|
||||||
"user_selector",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
action: {
|
|
||||||
type: ["route_to", "send_message"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const custom_field = {
|
const custom_field = {
|
||||||
klass: ["topic", "post", "group", "category"],
|
klass: ["topic", "post", "group", "category"],
|
||||||
type: ["string", "boolean", "integer", "json"],
|
type: ["string", "boolean", "integer", "json"],
|
||||||
};
|
};
|
||||||
|
|
||||||
export function buildFieldTypes(types) {
|
|
||||||
wizardSchema.field.types = types;
|
|
||||||
wizardSchema.field.type = Object.keys(types);
|
|
||||||
}
|
|
||||||
|
|
||||||
field.type = Object.keys(field.types);
|
field.type = Object.keys(field.types);
|
||||||
action.type = Object.keys(action.types);
|
action.type = Object.keys(action.types);
|
||||||
|
|
||||||
|
@ -256,30 +212,17 @@ const wizardSchema = {
|
||||||
field,
|
field,
|
||||||
custom_field,
|
custom_field,
|
||||||
action,
|
action,
|
||||||
filters,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function buildFieldTypes(types) {
|
||||||
|
wizardSchema.field.types = types;
|
||||||
|
}
|
||||||
|
|
||||||
export function buildFieldValidations(validations) {
|
export function buildFieldValidations(validations) {
|
||||||
wizardSchema.field.validations = validations;
|
wizardSchema.field.validations = validations;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function filterValues(currentWizard, feature, attribute, values = null) {
|
const siteSettings = getOwner(this).lookup("site-settings:main");
|
||||||
values = values || wizardSchema[feature][attribute];
|
|
||||||
|
|
||||||
if (currentWizard && currentWizard.allowGuests) {
|
|
||||||
const filteredFeature = wizardSchema.filters.allow_guests[feature];
|
|
||||||
if (filteredFeature) {
|
|
||||||
const filtered = filteredFeature[attribute];
|
|
||||||
if (filtered) {
|
|
||||||
values = values.filter((v) => filtered.includes(v));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
|
|
||||||
const siteSettings = getOwner(this).lookup("service:site-settings");
|
|
||||||
if (siteSettings.wizard_apis_enabled) {
|
if (siteSettings.wizard_apis_enabled) {
|
||||||
wizardSchema.action.types.send_to_api = {
|
wizardSchema.action.types.send_to_api = {
|
||||||
api: null,
|
api: null,
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
import EmberObject from "@ember/object";
|
|
||||||
|
|
||||||
function formatModel(model) {
|
|
||||||
let fields = [
|
|
||||||
EmberObject.create({
|
|
||||||
id: "submitted_at",
|
|
||||||
label: "Submitted At",
|
|
||||||
enabled: true,
|
|
||||||
}),
|
|
||||||
EmberObject.create({ id: "username", label: "User", enabled: true }),
|
|
||||||
];
|
|
||||||
let submissions = [];
|
|
||||||
|
|
||||||
model.submissions.forEach((s) => {
|
|
||||||
let submission = {
|
|
||||||
submitted_at: s.submitted_at,
|
|
||||||
username: s.user,
|
|
||||||
};
|
|
||||||
|
|
||||||
Object.keys(s.fields).forEach((fieldId) => {
|
|
||||||
if (!fields.some((field) => field.id === fieldId)) {
|
|
||||||
fields.push(
|
|
||||||
EmberObject.create({
|
|
||||||
id: fieldId,
|
|
||||||
label: s.fields[fieldId].label,
|
|
||||||
enabled: true,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
submission[fieldId] = s.fields[fieldId];
|
|
||||||
});
|
|
||||||
|
|
||||||
submissions.push(EmberObject.create(submission));
|
|
||||||
});
|
|
||||||
|
|
||||||
return { fields, submissions };
|
|
||||||
}
|
|
||||||
|
|
||||||
export { formatModel };
|
|
22
assets/javascripts/discourse/lib/wizard-subscription.js.es6
Normale Datei
22
assets/javascripts/discourse/lib/wizard-subscription.js.es6
Normale Datei
|
@ -0,0 +1,22 @@
|
||||||
|
const subscriptionTypes = ["standard", "business"];
|
||||||
|
|
||||||
|
function subscriptionTypeSufficient(subscriptionType, requiredType) {
|
||||||
|
if (requiredType && !subscriptionType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (requiredType === "none" || requiredType === null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
requiredType === "standard" &&
|
||||||
|
subscriptionTypes.includes(subscriptionType)
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (requiredType === "business" && subscriptionType === "business") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { subscriptionTypeSufficient, subscriptionTypes };
|
|
@ -1,6 +1,5 @@
|
||||||
import EmberObject from "@ember/object";
|
import EmberObject from "@ember/object";
|
||||||
import wizardSchema from "./wizard-schema";
|
import wizardSchema from "./wizard-schema";
|
||||||
import I18n from "I18n";
|
|
||||||
|
|
||||||
function selectKitContent(content) {
|
function selectKitContent(content) {
|
||||||
return content.map((i) => ({ id: i, name: i }));
|
return content.map((i) => ({ id: i, name: i }));
|
||||||
|
@ -34,10 +33,6 @@ function camelCase(string) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function translationOrText(i18nKey, text) {
|
|
||||||
return I18n.findTranslation(i18nKey) ? I18n.t(i18nKey) : text;
|
|
||||||
}
|
|
||||||
|
|
||||||
const userProperties = [
|
const userProperties = [
|
||||||
"name",
|
"name",
|
||||||
"username",
|
"username",
|
||||||
|
@ -126,5 +121,4 @@ export {
|
||||||
notificationLevels,
|
notificationLevels,
|
||||||
wizardFieldList,
|
wizardFieldList,
|
||||||
sentenceCase,
|
sentenceCase,
|
||||||
translationOrText,
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,14 +3,8 @@ import { getOwner } from "discourse-common/lib/get-owner";
|
||||||
import { readOnly } from "@ember/object/computed";
|
import { readOnly } from "@ember/object/computed";
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
|
|
||||||
const PRODUCT_PAGE = "https://custom-wizard.pavilion.tech";
|
|
||||||
const SUPPORT_MESSAGE =
|
|
||||||
"https://coop.pavilion.tech/new-message?username=support&title=Custom%20Wizard%20Support";
|
|
||||||
const MANAGER_CATEGORY =
|
|
||||||
"https://discourse.pluginmanager.org/c/discourse-custom-wizard";
|
|
||||||
|
|
||||||
export default Mixin.create({
|
export default Mixin.create({
|
||||||
subscriptionLandingUrl: PRODUCT_PAGE,
|
subscriptionLandingUrl: "https://custom-wizard.pavilion.tech",
|
||||||
subscriptionClientUrl: "/admin/plugins/subscription-client",
|
subscriptionClientUrl: "/admin/plugins/subscription-client",
|
||||||
|
|
||||||
@discourseComputed
|
@discourseComputed
|
||||||
|
@ -21,7 +15,6 @@ export default Mixin.create({
|
||||||
subscribed: readOnly("adminWizards.subscribed"),
|
subscribed: readOnly("adminWizards.subscribed"),
|
||||||
subscriptionType: readOnly("adminWizards.subscriptionType"),
|
subscriptionType: readOnly("adminWizards.subscriptionType"),
|
||||||
businessSubscription: readOnly("adminWizards.businessSubscription"),
|
businessSubscription: readOnly("adminWizards.businessSubscription"),
|
||||||
communitySubscription: readOnly("adminWizards.communitySubscription"),
|
|
||||||
standardSubscription: readOnly("adminWizards.standardSubscription"),
|
standardSubscription: readOnly("adminWizards.standardSubscription"),
|
||||||
subscriptionAttributes: readOnly("adminWizards.subscriptionAttributes"),
|
subscriptionAttributes: readOnly("adminWizards.subscriptionAttributes"),
|
||||||
subscriptionClientInstalled: readOnly(
|
subscriptionClientInstalled: readOnly(
|
||||||
|
@ -34,20 +27,4 @@ export default Mixin.create({
|
||||||
? this.subscriptionClientUrl
|
? this.subscriptionClientUrl
|
||||||
: this.subscriptionLandingUrl;
|
: this.subscriptionLandingUrl;
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed("subscriptionType")
|
|
||||||
subscriptionCtaLink(subscriptionType) {
|
|
||||||
switch (subscriptionType) {
|
|
||||||
case "none":
|
|
||||||
return PRODUCT_PAGE;
|
|
||||||
case "standard":
|
|
||||||
return SUPPORT_MESSAGE;
|
|
||||||
case "business":
|
|
||||||
return SUPPORT_MESSAGE;
|
|
||||||
case "community":
|
|
||||||
return MANAGER_CATEGORY;
|
|
||||||
default:
|
|
||||||
return PRODUCT_PAGE;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,8 +4,6 @@ import { get, set } from "@ember/object";
|
||||||
import Mixin from "@ember/object/mixin";
|
import Mixin from "@ember/object/mixin";
|
||||||
import { deepEqual } from "discourse-common/lib/object";
|
import { deepEqual } from "discourse-common/lib/object";
|
||||||
|
|
||||||
const observedCache = [];
|
|
||||||
|
|
||||||
export default Mixin.create({
|
export default Mixin.create({
|
||||||
didInsertElement() {
|
didInsertElement() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
|
@ -34,13 +32,7 @@ export default Mixin.create({
|
||||||
};
|
};
|
||||||
|
|
||||||
listProperties(componentType, opts).forEach((property) => {
|
listProperties(componentType, opts).forEach((property) => {
|
||||||
if (observedCache.includes(property)) {
|
|
||||||
obj.removeObserver(property, this, this.toggleUndo);
|
obj.removeObserver(property, this, this.toggleUndo);
|
||||||
let index = observedCache.indexOf(property);
|
|
||||||
if (index !== -1) {
|
|
||||||
observedCache.splice(index, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -53,9 +45,6 @@ export default Mixin.create({
|
||||||
};
|
};
|
||||||
|
|
||||||
listProperties(componentType, opts).forEach((property) => {
|
listProperties(componentType, opts).forEach((property) => {
|
||||||
if (observedCache.indexOf(property) === -1) {
|
|
||||||
observedCache.push(property);
|
|
||||||
}
|
|
||||||
obj.addObserver(property, this, this.toggleUndo);
|
obj.addObserver(property, this, this.toggleUndo);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
|
||||||
|
|
||||||
export const States = {
|
|
||||||
UNCHECKED: 0,
|
|
||||||
INVALID: 1,
|
|
||||||
VALID: 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default {
|
|
||||||
_validState: null,
|
|
||||||
errorDescription: null,
|
|
||||||
|
|
||||||
init() {
|
|
||||||
this._super(...arguments);
|
|
||||||
this.set("_validState", States.UNCHECKED);
|
|
||||||
},
|
|
||||||
|
|
||||||
@discourseComputed("_validState")
|
|
||||||
valid: (state) => state === States.VALID,
|
|
||||||
|
|
||||||
@discourseComputed("_validState")
|
|
||||||
invalid: (state) => state === States.INVALID,
|
|
||||||
|
|
||||||
@discourseComputed("_validState")
|
|
||||||
unchecked: (state) => state === States.UNCHECKED,
|
|
||||||
|
|
||||||
setValid(valid, description) {
|
|
||||||
this.set("_validState", valid ? States.VALID : States.INVALID);
|
|
||||||
|
|
||||||
if (!valid && description && description.length) {
|
|
||||||
this.set("errorDescription", description);
|
|
||||||
} else {
|
|
||||||
this.set("errorDescription", null);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -1,242 +0,0 @@
|
||||||
import EmberObject from "@ember/object";
|
|
||||||
import { buildProperties, mapped, present } from "../lib/wizard-json";
|
|
||||||
import { listProperties, snakeCase } from "../lib/wizard";
|
|
||||||
import wizardSchema from "../lib/wizard-schema";
|
|
||||||
import { Promise } from "rsvp";
|
|
||||||
import { ajax } from "discourse/lib/ajax";
|
|
||||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
|
||||||
|
|
||||||
const GUEST_GROUP_ID = -1;
|
|
||||||
|
|
||||||
const CustomWizardAdmin = EmberObject.extend({
|
|
||||||
@discourseComputed("permitted.@each.output")
|
|
||||||
allowGuests(permitted) {
|
|
||||||
return (
|
|
||||||
permitted &&
|
|
||||||
permitted.filter((p) => p.output && p.output.includes(GUEST_GROUP_ID))
|
|
||||||
.length
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
save(opts) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
let wizard = this.buildJson(this, "wizard");
|
|
||||||
|
|
||||||
if (wizard.error) {
|
|
||||||
reject(wizard);
|
|
||||||
}
|
|
||||||
|
|
||||||
let data = {
|
|
||||||
wizard,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (opts.create) {
|
|
||||||
data.create = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ajax(`/admin/wizards/wizard/${wizard.id}`, {
|
|
||||||
type: "PUT",
|
|
||||||
contentType: "application/json",
|
|
||||||
data: JSON.stringify(data),
|
|
||||||
}).then((result) => {
|
|
||||||
if (result.backend_validation_error) {
|
|
||||||
reject(result);
|
|
||||||
} else {
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
buildJson(object, type, result = {}) {
|
|
||||||
let objectType = object.type || null;
|
|
||||||
|
|
||||||
if (wizardSchema[type].types) {
|
|
||||||
if (!objectType) {
|
|
||||||
result.error = {
|
|
||||||
type: "required",
|
|
||||||
params: { type, property: "type" },
|
|
||||||
};
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let property of listProperties(type, { objectType })) {
|
|
||||||
let value = object.get(property);
|
|
||||||
|
|
||||||
result = this.validateValue(property, value, object, type, result);
|
|
||||||
|
|
||||||
if (result.error) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mapped(property, type)) {
|
|
||||||
value = this.buildMappedJson(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value !== undefined && value !== null) {
|
|
||||||
result[property] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!result.error) {
|
|
||||||
for (let arrayObjectType of Object.keys(
|
|
||||||
wizardSchema[type].objectArrays
|
|
||||||
)) {
|
|
||||||
let arraySchema = wizardSchema[type].objectArrays[arrayObjectType];
|
|
||||||
let objectArray = object.get(arraySchema.property);
|
|
||||||
|
|
||||||
if (arraySchema.required && !present(objectArray)) {
|
|
||||||
result.error = {
|
|
||||||
type: "required",
|
|
||||||
params: { type, property: arraySchema.property },
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
result[arraySchema.property] = [];
|
|
||||||
|
|
||||||
for (let item of objectArray) {
|
|
||||||
let itemProps = this.buildJson(item, arrayObjectType);
|
|
||||||
|
|
||||||
if (itemProps.error) {
|
|
||||||
result.error = itemProps.error;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
result[arraySchema.property].push(itemProps);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
|
|
||||||
validateValue(property, value, object, type, result) {
|
|
||||||
if (wizardSchema[type].required.indexOf(property) > -1 && !value) {
|
|
||||||
result.error = {
|
|
||||||
type: "required",
|
|
||||||
params: { type, property },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let dependent = wizardSchema[type].dependent[property];
|
|
||||||
if (dependent && value && !object[dependent]) {
|
|
||||||
result.error = {
|
|
||||||
type: "dependent",
|
|
||||||
params: { property, dependent },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (property === "api_body") {
|
|
||||||
try {
|
|
||||||
value = JSON.parse(value);
|
|
||||||
} catch (e) {
|
|
||||||
result.error = {
|
|
||||||
type: "invalid",
|
|
||||||
params: { type, property },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
|
|
||||||
buildMappedJson(value) {
|
|
||||||
if (typeof value === "string" || Number.isInteger(value)) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
if (!value || !value.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let inputs = value;
|
|
||||||
let result = [];
|
|
||||||
|
|
||||||
inputs.forEach((inpt) => {
|
|
||||||
let input = {
|
|
||||||
type: inpt.type,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (inpt.connector) {
|
|
||||||
input.connector = inpt.connector;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (present(inpt.output)) {
|
|
||||||
input.output = inpt.output;
|
|
||||||
input.output_type = snakeCase(inpt.output_type);
|
|
||||||
input.output_connector = inpt.output_connector;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (present(inpt.pairs)) {
|
|
||||||
input.pairs = [];
|
|
||||||
|
|
||||||
inpt.pairs.forEach((pr) => {
|
|
||||||
if (present(pr.key) && present(pr.value)) {
|
|
||||||
let pairParams = {
|
|
||||||
index: pr.index,
|
|
||||||
key: pr.key,
|
|
||||||
key_type: snakeCase(pr.key_type),
|
|
||||||
value: pr.value,
|
|
||||||
value_type: snakeCase(pr.value_type),
|
|
||||||
connector: pr.connector,
|
|
||||||
};
|
|
||||||
|
|
||||||
input.pairs.push(pairParams);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
(input.type === "assignment" && present(input.output)) ||
|
|
||||||
present(input.pairs)
|
|
||||||
) {
|
|
||||||
result.push(input);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!result.length) {
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
|
|
||||||
remove() {
|
|
||||||
return ajax(`/admin/wizards/wizard/${this.id}`, {
|
|
||||||
type: "DELETE",
|
|
||||||
})
|
|
||||||
.then(() => this.destroy())
|
|
||||||
.catch(popupAjaxError);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
CustomWizardAdmin.reopenClass({
|
|
||||||
all() {
|
|
||||||
return ajax("/admin/wizards/wizard", {
|
|
||||||
type: "GET",
|
|
||||||
})
|
|
||||||
.then((result) => {
|
|
||||||
return result.wizard_list;
|
|
||||||
})
|
|
||||||
.catch(popupAjaxError);
|
|
||||||
},
|
|
||||||
|
|
||||||
submissions(wizardId, page = 0) {
|
|
||||||
return ajax(`/admin/wizards/submissions/${wizardId}`, {
|
|
||||||
type: "GET",
|
|
||||||
data: {
|
|
||||||
page,
|
|
||||||
},
|
|
||||||
}).catch(popupAjaxError);
|
|
||||||
},
|
|
||||||
|
|
||||||
create(wizardJson = {}) {
|
|
||||||
const wizard = this._super.apply(this);
|
|
||||||
wizard.setProperties(buildProperties(wizardJson));
|
|
||||||
return wizard;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export default CustomWizardAdmin;
|
|
|
@ -1,127 +1,272 @@
|
||||||
import EmberObject from "@ember/object";
|
import EmberObject from "@ember/object";
|
||||||
import { ajax } from "discourse/lib/ajax";
|
import { ajax } from "discourse/lib/ajax";
|
||||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import { Promise } from "rsvp";
|
||||||
import getUrl from "discourse-common/lib/get-url";
|
import { listProperties, snakeCase } from "../lib/wizard";
|
||||||
import CustomWizardField from "./custom-wizard-field";
|
import { buildProperties, mapped, present } from "../lib/wizard-json";
|
||||||
import CustomWizardStep from "./custom-wizard-step";
|
import wizardSchema from "../lib/wizard-schema";
|
||||||
|
|
||||||
const CustomWizard = EmberObject.extend({
|
const CustomWizard = EmberObject.extend({
|
||||||
@discourseComputed("steps.length")
|
save(opts) {
|
||||||
totalSteps: (length) => length,
|
return new Promise((resolve, reject) => {
|
||||||
|
let wizard = this.buildJson(this, "wizard");
|
||||||
|
|
||||||
skip() {
|
if (wizard.error) {
|
||||||
if (this.required && !this.completed && this.permitted) {
|
reject(wizard);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
CustomWizard.skip(this.id);
|
|
||||||
|
let data = {
|
||||||
|
wizard,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (opts.create) {
|
||||||
|
data.create = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ajax(`/admin/wizards/wizard/${wizard.id}`, {
|
||||||
|
type: "PUT",
|
||||||
|
contentType: "application/json",
|
||||||
|
data: JSON.stringify(data),
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.backend_validation_error) {
|
||||||
|
reject(result);
|
||||||
|
} else {
|
||||||
|
resolve(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
restart() {
|
buildJson(object, type, result = {}) {
|
||||||
CustomWizard.restart(this.id);
|
let objectType = object.type || null;
|
||||||
|
|
||||||
|
if (wizardSchema[type].types) {
|
||||||
|
if (!objectType) {
|
||||||
|
result.error = {
|
||||||
|
type: "required",
|
||||||
|
params: { type, property: "type" },
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let property of listProperties(type, { objectType })) {
|
||||||
|
let value = object.get(property);
|
||||||
|
|
||||||
|
result = this.validateValue(property, value, object, type, result);
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mapped(property, type)) {
|
||||||
|
value = this.buildMappedJson(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value !== undefined && value !== null) {
|
||||||
|
result[property] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result.error) {
|
||||||
|
for (let arrayObjectType of Object.keys(
|
||||||
|
wizardSchema[type].objectArrays
|
||||||
|
)) {
|
||||||
|
let arraySchema = wizardSchema[type].objectArrays[arrayObjectType];
|
||||||
|
let objectArray = object.get(arraySchema.property);
|
||||||
|
|
||||||
|
if (arraySchema.required && !present(objectArray)) {
|
||||||
|
result.error = {
|
||||||
|
type: "required",
|
||||||
|
params: { type, property: arraySchema.property },
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result[arraySchema.property] = [];
|
||||||
|
|
||||||
|
for (let item of objectArray) {
|
||||||
|
let itemProps = this.buildJson(item, arrayObjectType);
|
||||||
|
|
||||||
|
if (itemProps.error) {
|
||||||
|
result.error = itemProps.error;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
result[arraySchema.property].push(itemProps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
validateValue(property, value, object, type, result) {
|
||||||
|
if (wizardSchema[type].required.indexOf(property) > -1 && !value) {
|
||||||
|
result.error = {
|
||||||
|
type: "required",
|
||||||
|
params: { type, property },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let dependent = wizardSchema[type].dependent[property];
|
||||||
|
if (dependent && value && !object[dependent]) {
|
||||||
|
result.error = {
|
||||||
|
type: "dependent",
|
||||||
|
params: { property, dependent },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property === "api_body") {
|
||||||
|
try {
|
||||||
|
value = JSON.parse(value);
|
||||||
|
} catch (e) {
|
||||||
|
result.error = {
|
||||||
|
type: "invalid",
|
||||||
|
params: { type, property },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
buildMappedJson(value) {
|
||||||
|
if (typeof value === "string" || Number.isInteger(value)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
if (!value || !value.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let inputs = value;
|
||||||
|
let result = [];
|
||||||
|
|
||||||
|
inputs.forEach((inpt) => {
|
||||||
|
let input = {
|
||||||
|
type: inpt.type,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (inpt.connector) {
|
||||||
|
input.connector = inpt.connector;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (present(inpt.output)) {
|
||||||
|
input.output = inpt.output;
|
||||||
|
input.output_type = snakeCase(inpt.output_type);
|
||||||
|
input.output_connector = inpt.output_connector;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (present(inpt.pairs)) {
|
||||||
|
input.pairs = [];
|
||||||
|
|
||||||
|
inpt.pairs.forEach((pr) => {
|
||||||
|
if (present(pr.key) && present(pr.value)) {
|
||||||
|
let pairParams = {
|
||||||
|
index: pr.index,
|
||||||
|
key: pr.key,
|
||||||
|
key_type: snakeCase(pr.key_type),
|
||||||
|
value: pr.value,
|
||||||
|
value_type: snakeCase(pr.value_type),
|
||||||
|
connector: pr.connector,
|
||||||
|
};
|
||||||
|
|
||||||
|
input.pairs.push(pairParams);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
(input.type === "assignment" && present(input.output)) ||
|
||||||
|
present(input.pairs)
|
||||||
|
) {
|
||||||
|
result.push(input);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!result.length) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
remove() {
|
||||||
|
return ajax(`/admin/wizards/wizard/${this.id}`, {
|
||||||
|
type: "DELETE",
|
||||||
|
})
|
||||||
|
.then(() => this.destroy())
|
||||||
|
.catch(popupAjaxError);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
CustomWizard.reopenClass({
|
CustomWizard.reopenClass({
|
||||||
skip(wizardId) {
|
all() {
|
||||||
ajax({ url: `/w/${wizardId}/skip`, type: "PUT" })
|
return ajax("/admin/wizards/wizard", {
|
||||||
|
type: "GET",
|
||||||
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
CustomWizard.finished(result);
|
return result.wizard_list;
|
||||||
})
|
})
|
||||||
.catch(popupAjaxError);
|
.catch(popupAjaxError);
|
||||||
},
|
},
|
||||||
|
|
||||||
restart(wizardId) {
|
submissions(wizardId, page = null) {
|
||||||
ajax({ url: `/w/${wizardId}/skip`, type: "PUT" })
|
let data = {};
|
||||||
.then(() => {
|
|
||||||
window.location.href = `/w/${wizardId}`;
|
if (page) {
|
||||||
|
data.page = page;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ajax(`/admin/wizards/submissions/${wizardId}`, {
|
||||||
|
type: "GET",
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
.then((result) => {
|
||||||
|
if (result.wizard) {
|
||||||
|
let fields = [{ id: "username", label: "User" }];
|
||||||
|
let submissions = [];
|
||||||
|
let wizard = result.wizard;
|
||||||
|
let total = result.total;
|
||||||
|
|
||||||
|
result.submissions.forEach((s) => {
|
||||||
|
let submission = {
|
||||||
|
username: s.user,
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.keys(s.fields).forEach((fieldId) => {
|
||||||
|
if (!fields.some((field) => field.id === fieldId)) {
|
||||||
|
fields.push({ id: fieldId, label: s.fields[fieldId].label });
|
||||||
|
}
|
||||||
|
submission[fieldId] = s.fields[fieldId];
|
||||||
|
});
|
||||||
|
submission["submitted_at"] = s.submitted_at;
|
||||||
|
submissions.push(submission);
|
||||||
|
});
|
||||||
|
|
||||||
|
let submittedAt = {
|
||||||
|
id: "submitted_at",
|
||||||
|
label: "Submitted At",
|
||||||
|
};
|
||||||
|
|
||||||
|
fields.push(submittedAt);
|
||||||
|
|
||||||
|
return {
|
||||||
|
wizard,
|
||||||
|
fields,
|
||||||
|
submissions,
|
||||||
|
total,
|
||||||
|
};
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch(popupAjaxError);
|
.catch(popupAjaxError);
|
||||||
},
|
},
|
||||||
|
|
||||||
finished(result) {
|
create(wizardJson = {}) {
|
||||||
let url = "/";
|
const wizard = this._super.apply(this);
|
||||||
if (result.redirect_on_complete) {
|
wizard.setProperties(buildProperties(wizardJson));
|
||||||
url = result.redirect_on_complete;
|
return wizard;
|
||||||
}
|
|
||||||
window.location.href = getUrl(url);
|
|
||||||
},
|
|
||||||
|
|
||||||
build(wizardJson) {
|
|
||||||
if (!wizardJson) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wizardJson.completed && wizardJson.steps) {
|
|
||||||
wizardJson.steps = wizardJson.steps
|
|
||||||
.map((step) => {
|
|
||||||
const stepObj = CustomWizardStep.create(step);
|
|
||||||
stepObj.wizardId = wizardJson.id;
|
|
||||||
|
|
||||||
stepObj.fields.sort((a, b) => {
|
|
||||||
return parseFloat(a.number) - parseFloat(b.number);
|
|
||||||
});
|
|
||||||
|
|
||||||
let tabindex = 1;
|
|
||||||
stepObj.fields.forEach((f) => {
|
|
||||||
f.tabindex = tabindex;
|
|
||||||
|
|
||||||
if (["date_time"].includes(f.type)) {
|
|
||||||
tabindex = tabindex + 2;
|
|
||||||
} else {
|
|
||||||
tabindex++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
stepObj.fields = stepObj.fields.map((f) => {
|
|
||||||
f.wizardId = wizardJson.id;
|
|
||||||
f.stepId = stepObj.id;
|
|
||||||
return CustomWizardField.create(f);
|
|
||||||
});
|
|
||||||
|
|
||||||
return stepObj;
|
|
||||||
})
|
|
||||||
.sort((a, b) => {
|
|
||||||
return parseFloat(a.index) - parseFloat(b.index);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return CustomWizard.create(wizardJson);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export function findCustomWizard(wizardId, params = {}) {
|
|
||||||
let url = `/w/${wizardId}.json`;
|
|
||||||
|
|
||||||
let paramKeys = Object.keys(params).filter((k) => {
|
|
||||||
if (k === "wizard_id") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !!params[k];
|
|
||||||
});
|
|
||||||
|
|
||||||
if (paramKeys.length) {
|
|
||||||
url += "?";
|
|
||||||
paramKeys.forEach((k, i) => {
|
|
||||||
if (i > 0) {
|
|
||||||
url += "&";
|
|
||||||
}
|
|
||||||
url += `${k}=${params[k]}`;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return ajax(url).then((result) => {
|
|
||||||
return CustomWizard.build(result);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let _wizard_store;
|
|
||||||
|
|
||||||
export function updateCachedWizard(wizard) {
|
|
||||||
_wizard_store = wizard;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getCachedWizard() {
|
|
||||||
return _wizard_store;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default CustomWizard;
|
export default CustomWizard;
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
import CustomWizardApi from "../models/custom-wizard-api";
|
import CustomWizardApi from "../models/custom-wizard-api";
|
||||||
import DiscourseRoute from "discourse/routes/discourse";
|
import DiscourseRoute from "discourse/routes/discourse";
|
||||||
import { inject as service } from "@ember/service";
|
|
||||||
|
|
||||||
export default DiscourseRoute.extend({
|
export default DiscourseRoute.extend({
|
||||||
router: service(),
|
|
||||||
|
|
||||||
model(params) {
|
model(params) {
|
||||||
if (params.name === "create") {
|
if (params.name === "create") {
|
||||||
return CustomWizardApi.create({ isNew: true });
|
return CustomWizardApi.create({ isNew: true });
|
||||||
|
@ -13,12 +10,6 @@ export default DiscourseRoute.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
afterModel(model) {
|
|
||||||
if (model === null) {
|
|
||||||
return this.router.transitionTo("adminWizardsApi");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
setupController(controller, model) {
|
setupController(controller, model) {
|
||||||
controller.set("api", model);
|
controller.set("api", model);
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
import DiscourseRoute from "discourse/routes/discourse";
|
import DiscourseRoute from "discourse/routes/discourse";
|
||||||
import CustomWizardApi from "../models/custom-wizard-api";
|
import CustomWizardApi from "../models/custom-wizard-api";
|
||||||
import { inject as service } from "@ember/service";
|
|
||||||
|
|
||||||
export default DiscourseRoute.extend({
|
export default DiscourseRoute.extend({
|
||||||
router: service(),
|
|
||||||
|
|
||||||
model() {
|
model() {
|
||||||
return CustomWizardApi.list();
|
return CustomWizardApi.list();
|
||||||
},
|
},
|
||||||
|
@ -28,11 +25,11 @@ export default DiscourseRoute.extend({
|
||||||
actions: {
|
actions: {
|
||||||
changeApi(apiName) {
|
changeApi(apiName) {
|
||||||
this.controllerFor("adminWizardsApi").set("apiName", apiName);
|
this.controllerFor("adminWizardsApi").set("apiName", apiName);
|
||||||
this.router.transitionTo("adminWizardsApiShow", apiName);
|
this.transitionTo("adminWizardsApiShow", apiName);
|
||||||
},
|
},
|
||||||
|
|
||||||
afterDestroy() {
|
afterDestroy() {
|
||||||
this.router.transitionTo("adminWizardsApi").then(() => this.refresh());
|
this.transitionTo("adminWizardsApi").then(() => this.refresh());
|
||||||
},
|
},
|
||||||
|
|
||||||
afterSave(apiName) {
|
afterSave(apiName) {
|
||||||
|
@ -41,7 +38,7 @@ export default DiscourseRoute.extend({
|
||||||
|
|
||||||
createApi() {
|
createApi() {
|
||||||
this.controllerFor("adminWizardsApi").set("apiName", "create");
|
this.controllerFor("adminWizardsApi").set("apiName", "create");
|
||||||
this.router.transitionTo("adminWizardsApiShow", "create");
|
this.transitionTo("adminWizardsApiShow", "create");
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,21 +1,12 @@
|
||||||
import CustomWizardLogs from "../models/custom-wizard-logs";
|
import CustomWizardLogs from "../models/custom-wizard-logs";
|
||||||
import DiscourseRoute from "discourse/routes/discourse";
|
import DiscourseRoute from "discourse/routes/discourse";
|
||||||
import { A } from "@ember/array";
|
import { A } from "@ember/array";
|
||||||
import { inject as service } from "@ember/service";
|
|
||||||
|
|
||||||
export default DiscourseRoute.extend({
|
export default DiscourseRoute.extend({
|
||||||
router: service(),
|
|
||||||
|
|
||||||
model(params) {
|
model(params) {
|
||||||
return CustomWizardLogs.list(params.wizardId);
|
return CustomWizardLogs.list(params.wizardId);
|
||||||
},
|
},
|
||||||
|
|
||||||
afterModel(model) {
|
|
||||||
if (model === null) {
|
|
||||||
return this.router.transitionTo("adminWizardsLogs");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
setupController(controller, model) {
|
setupController(controller, model) {
|
||||||
controller.setProperties({
|
controller.setProperties({
|
||||||
wizard: model.wizard,
|
wizard: model.wizard,
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
import DiscourseRoute from "discourse/routes/discourse";
|
import DiscourseRoute from "discourse/routes/discourse";
|
||||||
import { ajax } from "discourse/lib/ajax";
|
import { ajax } from "discourse/lib/ajax";
|
||||||
import { inject as service } from "@ember/service";
|
|
||||||
|
|
||||||
export default DiscourseRoute.extend({
|
export default DiscourseRoute.extend({
|
||||||
router: service(),
|
|
||||||
|
|
||||||
model() {
|
model() {
|
||||||
return ajax(`/admin/wizards/wizard`);
|
return ajax(`/admin/wizards/wizard`);
|
||||||
},
|
},
|
||||||
|
@ -21,7 +18,7 @@ export default DiscourseRoute.extend({
|
||||||
actions: {
|
actions: {
|
||||||
changeWizard(wizardId) {
|
changeWizard(wizardId) {
|
||||||
this.controllerFor("adminWizardsLogs").set("wizardId", wizardId);
|
this.controllerFor("adminWizardsLogs").set("wizardId", wizardId);
|
||||||
this.router.transitionTo("adminWizardsLogsShow", wizardId);
|
this.transitionTo("adminWizardsLogsShow", wizardId);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import CustomWizardAdmin from "../models/custom-wizard-admin";
|
import CustomWizard from "../models/custom-wizard";
|
||||||
import DiscourseRoute from "discourse/routes/discourse";
|
import DiscourseRoute from "discourse/routes/discourse";
|
||||||
|
|
||||||
export default DiscourseRoute.extend({
|
export default DiscourseRoute.extend({
|
||||||
model() {
|
model() {
|
||||||
return CustomWizardAdmin.all();
|
return CustomWizard.all();
|
||||||
},
|
},
|
||||||
|
|
||||||
setupController(controller, model) {
|
setupController(controller, model) {
|
||||||
|
|
|
@ -1,29 +1,23 @@
|
||||||
import { A } from "@ember/array";
|
import { A } from "@ember/array";
|
||||||
import CustomWizardAdmin from "../models/custom-wizard-admin";
|
import EmberObject from "@ember/object";
|
||||||
import DiscourseRoute from "discourse/routes/discourse";
|
import DiscourseRoute from "discourse/routes/discourse";
|
||||||
import { formatModel } from "../lib/wizard-submission";
|
import CustomWizard from "../models/custom-wizard";
|
||||||
import { inject as service } from "@ember/service";
|
|
||||||
|
|
||||||
export default DiscourseRoute.extend({
|
export default DiscourseRoute.extend({
|
||||||
router: service(),
|
|
||||||
|
|
||||||
model(params) {
|
model(params) {
|
||||||
return CustomWizardAdmin.submissions(params.wizardId);
|
return CustomWizard.submissions(params.wizardId);
|
||||||
},
|
|
||||||
|
|
||||||
afterModel(model) {
|
|
||||||
if (model === null) {
|
|
||||||
return this.router.transitionTo("adminWizardsSubmissions");
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
setupController(controller, model) {
|
setupController(controller, model) {
|
||||||
const { fields, submissions } = formatModel(model);
|
const fields = model.fields.map((f) => {
|
||||||
|
const fieldsObject = EmberObject.create(f);
|
||||||
|
fieldsObject.enabled = true;
|
||||||
|
return fieldsObject;
|
||||||
|
});
|
||||||
controller.setProperties({
|
controller.setProperties({
|
||||||
wizard: model.wizard,
|
wizard: model.wizard,
|
||||||
fields: A(fields),
|
fields: A(fields),
|
||||||
submissions: A(submissions),
|
submissions: A(model.submissions),
|
||||||
total: model.total,
|
total: model.total,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
import DiscourseRoute from "discourse/routes/discourse";
|
import DiscourseRoute from "discourse/routes/discourse";
|
||||||
import { ajax } from "discourse/lib/ajax";
|
import { ajax } from "discourse/lib/ajax";
|
||||||
import { inject as service } from "@ember/service";
|
|
||||||
|
|
||||||
export default DiscourseRoute.extend({
|
export default DiscourseRoute.extend({
|
||||||
router: service(),
|
|
||||||
|
|
||||||
model() {
|
model() {
|
||||||
return ajax(`/admin/wizards/wizard`);
|
return ajax(`/admin/wizards/wizard`);
|
||||||
},
|
},
|
||||||
|
@ -21,7 +18,7 @@ export default DiscourseRoute.extend({
|
||||||
actions: {
|
actions: {
|
||||||
changeWizard(wizardId) {
|
changeWizard(wizardId) {
|
||||||
this.controllerFor("adminWizardsSubmissions").set("wizardId", wizardId);
|
this.controllerFor("adminWizardsSubmissions").set("wizardId", wizardId);
|
||||||
this.router.transitionTo("adminWizardsSubmissionsShow", wizardId);
|
this.transitionTo("adminWizardsSubmissionsShow", wizardId);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
import CustomWizardAdmin from "../models/custom-wizard-admin";
|
import CustomWizard from "../models/custom-wizard";
|
||||||
import { ajax } from "discourse/lib/ajax";
|
import { ajax } from "discourse/lib/ajax";
|
||||||
import DiscourseRoute from "discourse/routes/discourse";
|
import DiscourseRoute from "discourse/routes/discourse";
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
import { inject as service } from "@ember/service";
|
|
||||||
|
|
||||||
export default DiscourseRoute.extend({
|
export default DiscourseRoute.extend({
|
||||||
router: service(),
|
|
||||||
|
|
||||||
model(params) {
|
model(params) {
|
||||||
if (params.wizardId === "create") {
|
if (params.wizardId === "create") {
|
||||||
return { create: true };
|
return { create: true };
|
||||||
|
@ -17,15 +14,13 @@ export default DiscourseRoute.extend({
|
||||||
|
|
||||||
afterModel(model) {
|
afterModel(model) {
|
||||||
if (model.none) {
|
if (model.none) {
|
||||||
return this.router.transitionTo("adminWizardsWizard");
|
return this.transitionTo("adminWizardsWizard");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
setupController(controller, model) {
|
setupController(controller, model) {
|
||||||
const parentModel = this.modelFor("adminWizardsWizard");
|
const parentModel = this.modelFor("adminWizardsWizard");
|
||||||
const wizard = CustomWizardAdmin.create(
|
const wizard = CustomWizard.create(!model || model.create ? {} : model);
|
||||||
!model || model.create ? {} : model
|
|
||||||
);
|
|
||||||
const fieldTypes = Object.keys(parentModel.field_types).map((type) => {
|
const fieldTypes = Object.keys(parentModel.field_types).map((type) => {
|
||||||
return {
|
return {
|
||||||
id: type,
|
id: type,
|
||||||
|
|
|
@ -4,11 +4,8 @@ import EmberObject, { set } from "@ember/object";
|
||||||
import { A } from "@ember/array";
|
import { A } from "@ember/array";
|
||||||
import { all } from "rsvp";
|
import { all } from "rsvp";
|
||||||
import { ajax } from "discourse/lib/ajax";
|
import { ajax } from "discourse/lib/ajax";
|
||||||
import { inject as service } from "@ember/service";
|
|
||||||
|
|
||||||
export default DiscourseRoute.extend({
|
export default DiscourseRoute.extend({
|
||||||
router: service(),
|
|
||||||
|
|
||||||
model() {
|
model() {
|
||||||
return ajax("/admin/wizards/wizard");
|
return ajax("/admin/wizards/wizard");
|
||||||
},
|
},
|
||||||
|
@ -83,14 +80,14 @@ export default DiscourseRoute.extend({
|
||||||
this.controllerFor("adminWizardsWizard").set("wizardId", wizardId);
|
this.controllerFor("adminWizardsWizard").set("wizardId", wizardId);
|
||||||
|
|
||||||
if (wizardId) {
|
if (wizardId) {
|
||||||
this.router.transitionTo("adminWizardsWizardShow", wizardId);
|
this.transitionTo("adminWizardsWizardShow", wizardId);
|
||||||
} else {
|
} else {
|
||||||
this.router.transitionTo("adminWizardsWizard");
|
this.transitionTo("adminWizardsWizard");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
afterDestroy() {
|
afterDestroy() {
|
||||||
this.router.transitionTo("adminWizardsWizard").then(() => this.refresh());
|
this.transitionTo("adminWizardsWizard").then(() => this.refresh());
|
||||||
},
|
},
|
||||||
|
|
||||||
afterSave(wizardId) {
|
afterSave(wizardId) {
|
||||||
|
@ -99,7 +96,7 @@ export default DiscourseRoute.extend({
|
||||||
|
|
||||||
createWizard() {
|
createWizard() {
|
||||||
this.controllerFor("adminWizardsWizard").set("wizardId", "create");
|
this.controllerFor("adminWizardsWizard").set("wizardId", "create");
|
||||||
this.router.transitionTo("adminWizardsWizardShow", "create");
|
this.transitionTo("adminWizardsWizardShow", "create");
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
import DiscourseRoute from "discourse/routes/discourse";
|
import DiscourseRoute from "discourse/routes/discourse";
|
||||||
import { ajax } from "discourse/lib/ajax";
|
import { ajax } from "discourse/lib/ajax";
|
||||||
import { inject as service } from "@ember/service";
|
|
||||||
|
|
||||||
export default DiscourseRoute.extend({
|
export default DiscourseRoute.extend({
|
||||||
router: service(),
|
|
||||||
|
|
||||||
model() {
|
model() {
|
||||||
return ajax("/admin/wizards");
|
return ajax("/admin/wizards");
|
||||||
},
|
},
|
||||||
|
@ -20,7 +17,7 @@ export default DiscourseRoute.extend({
|
||||||
|
|
||||||
afterModel(model, transition) {
|
afterModel(model, transition) {
|
||||||
if (transition.targetName === "adminWizards.index") {
|
if (transition.targetName === "adminWizards.index") {
|
||||||
this.router.transitionTo("adminWizardsWizard");
|
this.transitionTo("adminWizardsWizard");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,12 +8,7 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{d-button
|
{{d-button label="admin.wizard.api.save" action=(action "save") class="btn-primary" disabled=saveDisabled}}
|
||||||
label="admin.wizard.api.save"
|
|
||||||
action=(action "save")
|
|
||||||
class="btn-primary"
|
|
||||||
disabled=saveDisabled
|
|
||||||
}}
|
|
||||||
|
|
||||||
{{#if showRemove}}
|
{{#if showRemove}}
|
||||||
{{d-button action=(action "remove") label="admin.wizard.api.remove"}}
|
{{d-button action=(action "remove") label="admin.wizard.api.remove"}}
|
||||||
|
@ -26,32 +21,26 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="wizard-header large">
|
<div class="wizard-header">
|
||||||
{{#if api.isNew}}
|
{{#if api.isNew}}
|
||||||
{{i18n "admin.wizard.api.new"}}
|
{{i18n "admin.wizard.api.new"}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<span>{{api.title}}</span>
|
{{api.title}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="metadata">
|
<div class="metadata">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<label>{{i18n "admin.wizard.api.title"}}</label>
|
<label>{{i18n "admin.wizard.api.title"}}</label>
|
||||||
<Input
|
{{input value=api.title placeholder=(i18n "admin.wizard.api.title_placeholder")}}
|
||||||
@value={{this.api.title}}
|
|
||||||
placeholder={{i18n "admin.wizard.api.title_placeholder"}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="name {{nameClass}}">
|
<div class="name">
|
||||||
<label>{{i18n "admin.wizard.api.name"}}</label>
|
<label>{{i18n "admin.wizard.api.name"}}</label>
|
||||||
{{#if api.isNew}}
|
{{#if api.isNew}}
|
||||||
<Input
|
{{input value=api.name placeholder=(i18n "admin.wizard.api.name_placeholder")}}
|
||||||
@value={{this.api.name}}
|
|
||||||
placeholder={{i18n "admin.wizard.api.name_placeholder"}}
|
|
||||||
/>
|
|
||||||
{{else}}
|
{{else}}
|
||||||
<span>{{api.name}}</span>
|
{{api.name}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -67,16 +56,14 @@
|
||||||
<span>{{authErrorMessage}}</span>
|
<span>{{authErrorMessage}}</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{d-button
|
{{d-button label="admin.wizard.api.auth.btn"
|
||||||
label="admin.wizard.api.auth.btn"
|
|
||||||
action=(action "authorize")
|
action=(action "authorize")
|
||||||
disabled=authDisabled
|
disabled=authDisabled
|
||||||
class="btn-primary"
|
class="btn-primary"}}
|
||||||
}}
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="wizard-header medium">
|
<div class="wizard-header">
|
||||||
{{i18n "admin.wizard.api.auth.label"}}
|
{{i18n "admin.wizard.api.auth.label"}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -84,7 +71,7 @@
|
||||||
<div class="wizard-api-authentication">
|
<div class="wizard-api-authentication">
|
||||||
<div class="settings">
|
<div class="settings">
|
||||||
|
|
||||||
<div class="wizard-header small">
|
<div class="wizard-header medium">
|
||||||
{{i18n "admin.wizard.api.auth.settings"}}
|
{{i18n "admin.wizard.api.auth.settings"}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -106,8 +93,9 @@
|
||||||
value=api.authType
|
value=api.authType
|
||||||
content=authorizationTypes
|
content=authorizationTypes
|
||||||
onChange=(action (mut api.authType))
|
onChange=(action (mut api.authType))
|
||||||
options=(hash none="admin.wizard.api.auth.type_none")
|
options=(hash
|
||||||
}}
|
none="admin.wizard.api.auth.type_none"
|
||||||
|
)}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -116,7 +104,7 @@
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>{{i18n "admin.wizard.api.auth.url"}}</label>
|
<label>{{i18n "admin.wizard.api.auth.url"}}</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<Input @value={{this.api.authUrl}} />
|
{{input value=api.authUrl}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -124,21 +112,21 @@
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>{{i18n "admin.wizard.api.auth.token_url"}}</label>
|
<label>{{i18n "admin.wizard.api.auth.token_url"}}</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<Input @value={{this.api.tokenUrl}} />
|
{{input value=api.tokenUrl}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>{{i18n "admin.wizard.api.auth.client_id"}}</label>
|
<label>{{i18n "admin.wizard.api.auth.client_id"}}</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<Input @value={{this.api.clientId}} />
|
{{input value=api.clientId}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>{{i18n "admin.wizard.api.auth.client_secret"}}</label>
|
<label>{{i18n "admin.wizard.api.auth.client_secret"}}</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<Input @value={{this.api.clientSecret}} />
|
{{input value=api.clientSecret}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -147,26 +135,12 @@
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{#each api.authParams as |param|}}
|
{{#each api.authParams as |param|}}
|
||||||
<div class="param">
|
<div class="param">
|
||||||
<Input
|
{{input value=param.key placeholder=(i18n "admin.wizard.key")}}
|
||||||
@value={{this.param.key}}
|
{{input value=param.value placeholder=(i18n "admin.wizard.value")}}
|
||||||
placeholder={{i18n "admin.wizard.key"}}
|
{{d-button action=(action "removeParam") actionParam=param icon="times"}}
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
@value={{this.param.value}}
|
|
||||||
placeholder={{i18n "admin.wizard.value"}}
|
|
||||||
/>
|
|
||||||
{{d-button
|
|
||||||
action=(action "removeParam")
|
|
||||||
actionParam=param
|
|
||||||
icon="times"
|
|
||||||
}}
|
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{d-button
|
{{d-button label="admin.wizard.api.auth.params.new" icon="plus" action=(action "addParam")}}
|
||||||
label="admin.wizard.api.auth.params.new"
|
|
||||||
icon="plus"
|
|
||||||
action=(action "addParam")
|
|
||||||
}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -175,14 +149,14 @@
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>{{i18n "admin.wizard.api.auth.username"}}</label>
|
<label>{{i18n "admin.wizard.api.auth.username"}}</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<Input @value={{this.api.username}} />
|
{{input value=api.username}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>{{i18n "admin.wizard.api.auth.password"}}</label>
|
<label>{{i18n "admin.wizard.api.auth.password"}}</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<Input @value={{this.api.password}} />
|
{{input value=api.password}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -200,7 +174,7 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="wizard-header small">
|
<div class="wizard-header medium">
|
||||||
{{i18n "admin.wizard.api.status.label"}}
|
{{i18n "admin.wizard.api.status.label"}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -246,16 +220,12 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="wizard-header medium">
|
<div class="wizard-header">
|
||||||
{{i18n "admin.wizard.api.endpoint.label"}}
|
{{i18n "admin.wizard.api.endpoint.label"}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="wizard-api-endpoints">
|
<div class="wizard-api-endpoints">
|
||||||
{{d-button
|
{{d-button action=(action "addEndpoint") label="admin.wizard.api.endpoint.add" icon="plus"}}
|
||||||
action=(action "addEndpoint")
|
|
||||||
label="admin.wizard.api.endpoint.add"
|
|
||||||
icon="plus"
|
|
||||||
}}
|
|
||||||
|
|
||||||
{{#if api.endpoints}}
|
{{#if api.endpoints}}
|
||||||
<div class="endpoint-list">
|
<div class="endpoint-list">
|
||||||
|
@ -265,43 +235,38 @@
|
||||||
<div class="endpoint">
|
<div class="endpoint">
|
||||||
<div class="endpoint-">
|
<div class="endpoint-">
|
||||||
<div class="top">
|
<div class="top">
|
||||||
<Input
|
{{input value=endpoint.name
|
||||||
@value={{endpoint.name}}
|
placeholder=(i18n "admin.wizard.api.endpoint.name")}}
|
||||||
placeholder={{i18n "admin.wizard.api.endpoint.name"}}
|
{{input value=endpoint.url
|
||||||
/>
|
placeholder=(i18n "admin.wizard.api.endpoint.url")
|
||||||
<Input
|
class="endpoint-url"}}
|
||||||
@value={{endpoint.url}}
|
{{d-button action=(action "removeEndpoint")
|
||||||
placeholder={{i18n "admin.wizard.api.endpoint.url"}}
|
|
||||||
class="endpoint-url"
|
|
||||||
/>
|
|
||||||
{{d-button
|
|
||||||
action=(action "removeEndpoint")
|
|
||||||
actionParam=endpoint
|
actionParam=endpoint
|
||||||
icon="times"
|
icon="times"
|
||||||
class="remove-endpoint"
|
class="remove-endpoint"}}
|
||||||
}}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="bottom">
|
<div class="bottom">
|
||||||
{{combo-box
|
{{combo-box
|
||||||
content=endpointMethods
|
content=endpointMethods
|
||||||
value=endpoint.method
|
value=endpoint.method
|
||||||
onChange=(action (mut endpoint.method))
|
onChange=(action (mut endpoint.method))
|
||||||
options=(hash none="admin.wizard.api.endpoint.method")
|
options=(hash
|
||||||
}}
|
none="admin.wizard.api.endpoint.method"
|
||||||
|
)}}
|
||||||
{{combo-box
|
{{combo-box
|
||||||
content=contentTypes
|
content=contentTypes
|
||||||
value=endpoint.content_type
|
value=endpoint.content_type
|
||||||
onChange=(action (mut endpoint.content_type))
|
onChange=(action (mut endpoint.content_type))
|
||||||
options=(hash none="admin.wizard.api.endpoint.content_type")
|
options=(hash
|
||||||
}}
|
none="admin.wizard.api.endpoint.content_type"
|
||||||
|
)}}
|
||||||
{{multi-select
|
{{multi-select
|
||||||
value=endpoint.success_codes
|
value=endpoint.success_codes
|
||||||
content=successCodes
|
content=successCodes
|
||||||
onChange=(action (mut endpoint.success_codes))
|
onChange=(action (mut endpoint.success_codes))
|
||||||
options=(hash
|
options=(hash
|
||||||
none="admin.wizard.api.endpoint.success_codes"
|
none="admin.wizard.api.endpoint.success_codes"
|
||||||
)
|
)}}
|
||||||
}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -312,16 +277,11 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="wizard-header medium">
|
<div class="wizard-header">
|
||||||
{{i18n "admin.wizard.api.log.label"}}
|
{{i18n "admin.wizard.api.log.label"}}
|
||||||
|
{{d-button action=(action "clearLogs")
|
||||||
<div class="controls">
|
icon="trash-alt"
|
||||||
{{d-button
|
class="clear-logs"}}
|
||||||
action=(action "clearLogs")
|
|
||||||
class="clear-logs"
|
|
||||||
label="admin.wizard.api.log.clear"
|
|
||||||
}}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="wizard-api-log">
|
<div class="wizard-api-log">
|
||||||
|
@ -340,10 +300,7 @@
|
||||||
<td>{{logentry.time}}</td>
|
<td>{{logentry.time}}</td>
|
||||||
<td class="user-image">
|
<td class="user-image">
|
||||||
<div class="user-image-inner">
|
<div class="user-image-inner">
|
||||||
<a
|
<a href={{logentry.userpath}} data-user-card={{logentry.username}}>{{avatar logentry imageSize="large"}}</a>
|
||||||
href={{logentry.userpath}}
|
|
||||||
data-user-card={{logentry.username}}
|
|
||||||
>{{avatar logentry imageSize="medium"}}</a>
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>{{logentry.status}}</td>
|
<td>{{logentry.status}}</td>
|
||||||
|
|
|
@ -3,14 +3,14 @@
|
||||||
value=apiName
|
value=apiName
|
||||||
content=apiList
|
content=apiList
|
||||||
onChange=(route-action "changeApi")
|
onChange=(route-action "changeApi")
|
||||||
options=(hash none="admin.wizard.api.select")
|
options=(hash
|
||||||
}}
|
none="admin.wizard.api.select"
|
||||||
|
)}}
|
||||||
|
|
||||||
{{d-button
|
{{d-button
|
||||||
action=(route-action "createApi")
|
action="createApi"
|
||||||
label="admin.wizard.api.create"
|
label="admin.wizard.api.create"
|
||||||
icon="plus"
|
icon="plus"}}
|
||||||
}}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="admin-wizard-container">
|
<div class="admin-wizard-container">
|
||||||
|
|
|
@ -5,8 +5,7 @@
|
||||||
{{d-button
|
{{d-button
|
||||||
label="admin.wizard.custom_field.add"
|
label="admin.wizard.custom_field.add"
|
||||||
icon="plus"
|
icon="plus"
|
||||||
action=(action "addField")
|
action="addField"}}
|
||||||
}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -15,8 +14,7 @@
|
||||||
opts=messageOpts
|
opts=messageOpts
|
||||||
type=messageType
|
type=messageType
|
||||||
url=documentationUrl
|
url=documentationUrl
|
||||||
component="custom_fields"
|
component="custom_fields"}}
|
||||||
}}
|
|
||||||
|
|
||||||
<div class="admin-wizard-container">
|
<div class="admin-wizard-container">
|
||||||
{{#if customFields}}
|
{{#if customFields}}
|
||||||
|
@ -34,8 +32,7 @@
|
||||||
{{custom-field-input
|
{{custom-field-input
|
||||||
field=field
|
field=field
|
||||||
removeField=(action "removeField")
|
removeField=(action "removeField")
|
||||||
saveField=(action "saveField")
|
saveField=(action "saveField")}}
|
||||||
}}
|
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -8,9 +8,8 @@
|
||||||
{{d-button
|
{{d-button
|
||||||
label="refresh"
|
label="refresh"
|
||||||
icon="sync"
|
icon="sync"
|
||||||
action=(action "refresh")
|
action="refresh"
|
||||||
class="refresh"
|
class="refresh"}}
|
||||||
}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -32,10 +31,7 @@
|
||||||
{{#each logs as |log|}}
|
{{#each logs as |log|}}
|
||||||
<tr>
|
<tr>
|
||||||
{{#each-in log as |field value|}}
|
{{#each-in log as |field value|}}
|
||||||
<td class="small">{{wizard-table-field
|
<td class="small">{{wizard-table-field field=field value=value}}</td>
|
||||||
field=field
|
|
||||||
value=value
|
|
||||||
}}</td>
|
|
||||||
{{/each-in}}
|
{{/each-in}}
|
||||||
</tr>
|
</tr>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
|
@ -3,16 +3,16 @@
|
||||||
value=wizardId
|
value=wizardId
|
||||||
content=wizardList
|
content=wizardList
|
||||||
onChange=(route-action "changeWizard")
|
onChange=(route-action "changeWizard")
|
||||||
options=(hash none="admin.wizard.select")
|
options=(hash
|
||||||
}}
|
none="admin.wizard.select"
|
||||||
|
)}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{wizard-message
|
{{wizard-message
|
||||||
key=messageKey
|
key=messageKey
|
||||||
opts=messageOpts
|
opts=messageOpts
|
||||||
url=documentationUrl
|
url=documentationUrl
|
||||||
component="logs"
|
component="logs"}}
|
||||||
}}
|
|
||||||
|
|
||||||
<div class="admin-wizard-container">
|
<div class="admin-wizard-container">
|
||||||
{{outlet}}
|
{{outlet}}
|
||||||
|
|
|
@ -11,35 +11,30 @@
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<Input
|
{{input
|
||||||
id="custom-wizard-file-upload"
|
id="file-upload"
|
||||||
@type="file"
|
type="file"
|
||||||
accept="application/json"
|
accept="application/json"
|
||||||
{{on "input" (action "setFile")}}
|
change=(action "setFile")}}
|
||||||
/>
|
|
||||||
{{d-button
|
{{d-button
|
||||||
id="upload-button"
|
id="upload-button"
|
||||||
label="admin.wizard.manager.upload"
|
label="admin.wizard.manager.upload"
|
||||||
action=(action "upload")
|
action=(action "upload")}}
|
||||||
}}
|
|
||||||
{{d-button
|
{{d-button
|
||||||
id="import-button"
|
id="import-button"
|
||||||
label="admin.wizard.manager.import"
|
label="admin.wizard.manager.import"
|
||||||
action=(action "import")
|
action=(action "import")
|
||||||
disabled=importDisabled
|
disabled=importDisabled}}
|
||||||
}}
|
|
||||||
{{d-button
|
{{d-button
|
||||||
id="export-button"
|
id="export-button"
|
||||||
label="admin.wizard.manager.export"
|
label="admin.wizard.manager.export"
|
||||||
action=(action "export")
|
action=(action "export")
|
||||||
disabled=exportDisabled
|
disabled=exportDisabled}}
|
||||||
}}
|
|
||||||
{{d-button
|
{{d-button
|
||||||
id="destroy-button"
|
id="destroy-button"
|
||||||
label="admin.wizard.manager.destroy"
|
label="admin.wizard.manager.destroy"
|
||||||
action=(action "destroy")
|
action=(action "destroy")
|
||||||
disabled=destoryDisabled
|
disabled=destoryDisabled}}
|
||||||
}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -50,8 +45,7 @@
|
||||||
opts=messageOpts
|
opts=messageOpts
|
||||||
items=messageItems
|
items=messageItems
|
||||||
loading=loading
|
loading=loading
|
||||||
component="manager"
|
component="manager"}}
|
||||||
}}
|
|
||||||
|
|
||||||
<div class="admin-wizard-container">
|
<div class="admin-wizard-container">
|
||||||
<table class="table grid">
|
<table class="table grid">
|
||||||
|
@ -71,18 +65,16 @@
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
</td>
|
</td>
|
||||||
<td class="control-column">
|
<td class="control-column">
|
||||||
<Input
|
{{input
|
||||||
@type="checkbox"
|
type="checkbox"
|
||||||
class="export"
|
class="export"
|
||||||
{{on "change" (action "selectWizard")}}
|
change=(action "selectWizard")}}
|
||||||
/>
|
|
||||||
</td>
|
</td>
|
||||||
<td class="control-column">
|
<td class="control-column">
|
||||||
<Input
|
{{input
|
||||||
@type="checkbox"
|
type="checkbox"
|
||||||
class="destroy"
|
class="destroy"
|
||||||
{{on "change" (action "selectWizard")}}
|
change=(action "selectWizard")}}
|
||||||
/>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
|
@ -3,16 +3,16 @@
|
||||||
value=wizardId
|
value=wizardId
|
||||||
content=wizardList
|
content=wizardList
|
||||||
onChange=(route-action "changeWizard")
|
onChange=(route-action "changeWizard")
|
||||||
options=(hash none="admin.wizard.select")
|
options=(hash
|
||||||
}}
|
none="admin.wizard.select"
|
||||||
|
)}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{wizard-message
|
{{wizard-message
|
||||||
key=messageKey
|
key=messageKey
|
||||||
opts=messageOpts
|
opts=messageOpts
|
||||||
url=documentationUrl
|
url=documentationUrl
|
||||||
component="submissions"
|
component="submissions"}}
|
||||||
}}
|
|
||||||
|
|
||||||
<div class="admin-wizard-container">
|
<div class="admin-wizard-container">
|
||||||
{{outlet}}
|
{{outlet}}
|
||||||
|
|
|
@ -1,31 +1,18 @@
|
||||||
{{#if wizard}}
|
{{#if wizard}}
|
||||||
<div class="wizard-header large">
|
<div class="wizard-header large">
|
||||||
<Input
|
{{input
|
||||||
@value={{this.wizard.name}}
|
|
||||||
name="name"
|
name="name"
|
||||||
placeholder={{i18n "admin.wizard.name_placeholder"}}
|
value=wizard.name
|
||||||
/>
|
placeholderKey="admin.wizard.name_placeholder"}}
|
||||||
|
|
||||||
<div class="wizard-url">
|
<div class="wizard-url">
|
||||||
{{#if wizard.name}}
|
{{#if wizard.name}}
|
||||||
{{#if copiedUrl}}
|
{{#if copiedUrl}}
|
||||||
{{d-button
|
{{d-button class="btn-hover pull-right" icon="copy" label="ip_lookup.copied"}}
|
||||||
class="btn-hover pull-right"
|
|
||||||
icon="copy"
|
|
||||||
label="ip_lookup.copied"
|
|
||||||
}}
|
|
||||||
{{else}}
|
{{else}}
|
||||||
{{d-button
|
{{d-button action=(action "copyUrl") class="pull-right no-text" icon="copy"}}
|
||||||
action=(action "copyUrl")
|
|
||||||
class="pull-right no-text"
|
|
||||||
icon="copy"
|
|
||||||
}}
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<a
|
<a href={{wizardUrl}} target="_blank" rel="noopener noreferrer">{{wizardUrl}}</a>
|
||||||
href={{wizardUrl}}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>{{wizardUrl}}</a>
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -36,12 +23,11 @@
|
||||||
<label>{{i18n "admin.wizard.background"}}</label>
|
<label>{{i18n "admin.wizard.background"}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
<Input
|
{{input
|
||||||
@value={{this.wizard.background}}
|
|
||||||
name="background"
|
name="background"
|
||||||
placeholder={{i18n "admin.wizard.background_placeholder"}}
|
value=wizard.background
|
||||||
class="small"
|
placeholderKey="admin.wizard.background_placeholder"
|
||||||
/>
|
class="small"}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -55,8 +41,9 @@
|
||||||
valueProperty="id"
|
valueProperty="id"
|
||||||
value=wizard.theme_id
|
value=wizard.theme_id
|
||||||
onChange=(action (mut wizard.theme_id))
|
onChange=(action (mut wizard.theme_id))
|
||||||
options=(hash none="admin.wizard.no_theme")
|
options=(hash
|
||||||
}}
|
none="admin.wizard.no_theme"
|
||||||
|
)}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -68,21 +55,11 @@
|
||||||
<div class="wizard-settings">
|
<div class="wizard-settings">
|
||||||
<div class="setting">
|
<div class="setting">
|
||||||
<div class="setting-label">
|
<div class="setting-label">
|
||||||
<label>{{i18n "admin.wizard.save_submissions"}}</label>
|
<label>{{i18n "admin.wizard.required"}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
<Input @type="checkbox" @checked={{this.wizard.save_submissions}} />
|
{{input type="checkbox" checked=wizard.required}}
|
||||||
<span>{{i18n "admin.wizard.save_submissions_label"}}</span>
|
<span>{{i18n "admin.wizard.required_label"}}</span>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting">
|
|
||||||
<div class="setting-label">
|
|
||||||
<label>{{i18n "admin.wizard.multiple_submissions"}}</label>
|
|
||||||
</div>
|
|
||||||
<div class="setting-value">
|
|
||||||
<Input @type="checkbox" @checked={{this.wizard.multiple_submissions}} />
|
|
||||||
<span>{{i18n "admin.wizard.multiple_submissions_label"}}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -91,17 +68,27 @@
|
||||||
<label>{{i18n "admin.wizard.after_signup"}}</label>
|
<label>{{i18n "admin.wizard.after_signup"}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
<Input @type="checkbox" @checked={{this.wizard.after_signup}} />
|
{{input type="checkbox" checked=wizard.after_signup}}
|
||||||
<span>{{i18n "admin.wizard.after_signup_label"}}</span>
|
<span>{{i18n "admin.wizard.after_signup_label"}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="setting">
|
||||||
|
<div class="setting-label">
|
||||||
|
<label>{{i18n "admin.wizard.multiple_submissions"}}</label>
|
||||||
|
</div>
|
||||||
|
<div class="setting-value">
|
||||||
|
{{input type="checkbox" checked=wizard.multiple_submissions}}
|
||||||
|
<span>{{i18n "admin.wizard.multiple_submissions_label"}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="setting">
|
<div class="setting">
|
||||||
<div class="setting-label">
|
<div class="setting-label">
|
||||||
<label>{{i18n "admin.wizard.prompt_completion"}}</label>
|
<label>{{i18n "admin.wizard.prompt_completion"}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
<Input @type="checkbox" @checked={{this.wizard.prompt_completion}} />
|
{{input type="checkbox" checked=wizard.prompt_completion}}
|
||||||
<span>{{i18n "admin.wizard.prompt_completion_label"}}</span>
|
<span>{{i18n "admin.wizard.prompt_completion_label"}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -111,35 +98,13 @@
|
||||||
<label>{{i18n "admin.wizard.after_time"}}</label>
|
<label>{{i18n "admin.wizard.after_time"}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
<Input @type="checkbox" @checked={{this.wizard.after_time}} />
|
{{input type="checkbox" checked=wizard.after_time}}
|
||||||
<span>{{i18n "admin.wizard.after_time_label"}}</span>
|
<span>{{i18n "admin.wizard.after_time_label"}}</span>
|
||||||
{{d-button
|
{{d-button
|
||||||
action=(action "setNextSessionScheduled")
|
action="setNextSessionScheduled"
|
||||||
translatedLabel=nextSessionScheduledLabel
|
translatedLabel=nextSessionScheduledLabel
|
||||||
class="btn-after-time"
|
class="btn-after-time"
|
||||||
icon="far-calendar"
|
icon="far-calendar"}}
|
||||||
}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{#wizard-subscription-container}}
|
|
||||||
<div class="setting">
|
|
||||||
<div class="setting-label">
|
|
||||||
<label>{{i18n "admin.wizard.required"}}</label>
|
|
||||||
</div>
|
|
||||||
<div class="setting-value">
|
|
||||||
<Input @type="checkbox" @checked={{this.wizard.required}} />
|
|
||||||
<span>{{i18n "admin.wizard.required_label"}}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting">
|
|
||||||
<div class="setting-label">
|
|
||||||
<label>{{i18n "admin.wizard.restart_on_revisit"}}</label>
|
|
||||||
</div>
|
|
||||||
<div class="setting-value">
|
|
||||||
<Input @type="checkbox" @checked={{this.wizard.restart_on_revisit}} />
|
|
||||||
<span>{{i18n "admin.wizard.restart_on_revisit_label"}}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -154,18 +119,40 @@
|
||||||
context="wizard"
|
context="wizard"
|
||||||
inputTypes="assignment,validation"
|
inputTypes="assignment,validation"
|
||||||
groupSelection="output"
|
groupSelection="output"
|
||||||
guestGroup=true
|
|
||||||
userFieldSelection="key"
|
userFieldSelection="key"
|
||||||
textSelection="value"
|
textSelection="value"
|
||||||
inputConnector="and"
|
inputConnector="and"
|
||||||
)
|
)}}
|
||||||
}}
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#wizard-subscription-container}}
|
||||||
|
<div class="setting">
|
||||||
|
<div class="setting-label">
|
||||||
|
<label>{{i18n "admin.wizard.save_submissions"}}</label>
|
||||||
|
</div>
|
||||||
|
<div class="setting-value">
|
||||||
|
{{input type="checkbox" checked=wizard.save_submissions}}
|
||||||
|
<span>{{i18n "admin.wizard.save_submissions_label"}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting">
|
||||||
|
<div class="setting-label">
|
||||||
|
<label>{{i18n "admin.wizard.restart_on_revisit"}}</label>
|
||||||
|
</div>
|
||||||
|
<div class="setting-value">
|
||||||
|
{{input type="checkbox" checked=wizard.restart_on_revisit}}
|
||||||
|
<span>{{i18n "admin.wizard.restart_on_revisit_label"}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/wizard-subscription-container}}
|
{{/wizard-subscription-container}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{wizard-links itemType="step" current=currentStep items=wizard.steps}}
|
{{wizard-links
|
||||||
|
itemType="step"
|
||||||
|
current=currentStep
|
||||||
|
items=wizard.steps}}
|
||||||
|
|
||||||
{{#if currentStep}}
|
{{#if currentStep}}
|
||||||
{{wizard-custom-step
|
{{wizard-custom-step
|
||||||
|
@ -173,37 +160,28 @@
|
||||||
wizard=wizard
|
wizard=wizard
|
||||||
currentField=currentField
|
currentField=currentField
|
||||||
wizardFields=wizardFields
|
wizardFields=wizardFields
|
||||||
fieldTypes=filteredFieldTypes
|
fieldTypes=fieldTypes
|
||||||
subscribed=subscribed
|
subscribed=subscribed}}
|
||||||
}}
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{wizard-links
|
{{wizard-links
|
||||||
itemType="action"
|
itemType="action"
|
||||||
current=currentAction
|
current=currentAction
|
||||||
items=wizard.actions
|
items=wizard.actions
|
||||||
generateLabels=true
|
generateLabels=true}}
|
||||||
}}
|
|
||||||
|
|
||||||
{{#each wizard.actions as |wizardAction|}}
|
{{#each wizard.actions as |action|}}
|
||||||
{{wizard-custom-action
|
{{wizard-custom-action
|
||||||
action=wizardAction
|
action=action
|
||||||
currentActionId=currentAction.id
|
currentActionId=currentAction.id
|
||||||
wizard=wizard
|
wizard=wizard
|
||||||
apis=apis
|
apis=apis
|
||||||
removeAction="removeAction"
|
removeAction="removeAction"
|
||||||
wizardFields=wizardFields
|
wizardFields=wizardFields}}
|
||||||
fieldTypes=filteredFieldTypes
|
|
||||||
}}
|
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
||||||
<div class="admin-wizard-buttons">
|
<div class="admin-wizard-buttons">
|
||||||
<button
|
<button {{action "save"}} disabled={{disableSave}} class="btn btn-primary" type="button">
|
||||||
{{action "save"}}
|
|
||||||
disabled={{disableSave}}
|
|
||||||
class="btn btn-primary"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
{{i18n "admin.wizard.save"}}
|
{{i18n "admin.wizard.save"}}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
|
|
@ -3,17 +3,20 @@
|
||||||
value=wizardListVal
|
value=wizardListVal
|
||||||
content=wizardList
|
content=wizardList
|
||||||
onChange=(route-action "changeWizard")
|
onChange=(route-action "changeWizard")
|
||||||
options=(hash none="admin.wizard.select")
|
options=(hash
|
||||||
}}
|
none="admin.wizard.select"
|
||||||
|
)}}
|
||||||
|
|
||||||
{{d-button
|
{{d-button
|
||||||
action=(route-action "createWizard")
|
action="createWizard"
|
||||||
label="admin.wizard.create"
|
label="admin.wizard.create"
|
||||||
icon="plus"
|
icon="plus"}}
|
||||||
}}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{wizard-message key=messageKey url=messageUrl component="wizard"}}
|
{{wizard-message
|
||||||
|
key=messageKey
|
||||||
|
url=messageUrl
|
||||||
|
component="wizard"}}
|
||||||
|
|
||||||
<div class="admin-wizard-container settings">
|
<div class="admin-wizard-container settings">
|
||||||
{{outlet}}
|
{{outlet}}
|
||||||
|
|
|
@ -1,25 +1,18 @@
|
||||||
{{#admin-nav}}
|
{{#admin-nav}}
|
||||||
{{nav-item route="adminWizardsWizard" label="admin.wizard.nav_label"}}
|
{{nav-item route="adminWizardsWizard" label="admin.wizard.nav_label"}}
|
||||||
{{nav-item
|
{{nav-item route="adminWizardsCustomFields" label="admin.wizard.custom_field.nav_label"}}
|
||||||
route="adminWizardsCustomFields"
|
{{nav-item route="adminWizardsSubmissions" label="admin.wizard.submissions.nav_label"}}
|
||||||
label="admin.wizard.custom_field.nav_label"
|
{{#if businessSubscription}}
|
||||||
}}
|
|
||||||
{{nav-item
|
|
||||||
route="adminWizardsSubmissions"
|
|
||||||
label="admin.wizard.submissions.nav_label"
|
|
||||||
}}
|
|
||||||
{{#if showApi}}
|
|
||||||
{{nav-item route="adminWizardsApi" label="admin.wizard.api.nav_label"}}
|
{{nav-item route="adminWizardsApi" label="admin.wizard.api.nav_label"}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{nav-item route="adminWizardsLogs" label="admin.wizard.log.nav_label"}}
|
{{nav-item route="adminWizardsLogs" label="admin.wizard.log.nav_label"}}
|
||||||
{{nav-item
|
{{nav-item route="adminWizardsManager" label="admin.wizard.manager.nav_label"}}
|
||||||
route="adminWizardsManager"
|
|
||||||
label="admin.wizard.manager.nav_label"
|
|
||||||
}}
|
|
||||||
|
|
||||||
<div class="admin-actions">
|
<div class="admin-actions">
|
||||||
{{wizard-subscription-badge}}
|
{{wizard-subscription-badge}}
|
||||||
{{wizard-subscription-cta}}
|
<a target="_blank" class="btn btn-pavilion-support" rel="noreferrer noopener" href="https://thepavilion.io/w/support" title={{i18n "admin.wizard.support_button.title"}}>
|
||||||
|
{{d-icon "far-life-ring"}}{{i18n "admin.wizard.support_button.label"}}
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{{/admin-nav}}
|
{{/admin-nav}}
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,9 @@
|
||||||
feature="custom_field"
|
feature="custom_field"
|
||||||
attribute="klass"
|
attribute="klass"
|
||||||
onChange=(action (mut field.klass))
|
onChange=(action (mut field.klass))
|
||||||
options=(hash none="admin.wizard.custom_field.klass.select")
|
options=(hash
|
||||||
}}
|
none="admin.wizard.custom_field.klass.select"
|
||||||
|
)}}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{wizard-subscription-selector
|
{{wizard-subscription-selector
|
||||||
|
@ -14,22 +15,23 @@
|
||||||
feature="custom_field"
|
feature="custom_field"
|
||||||
attribute="type"
|
attribute="type"
|
||||||
onChange=(action (mut field.type))
|
onChange=(action (mut field.type))
|
||||||
options=(hash none="admin.wizard.custom_field.type.select")
|
options=(hash
|
||||||
}}
|
none="admin.wizard.custom_field.type.select"
|
||||||
|
)}}
|
||||||
</td>
|
</td>
|
||||||
<td class="input">
|
<td class="input">
|
||||||
<Input
|
{{input
|
||||||
@value={{this.field.name}}
|
value=field.name
|
||||||
placeholder={{i18n "admin.wizard.custom_field.name.select"}}
|
placeholder=(i18n "admin.wizard.custom_field.name.select")}}
|
||||||
/>
|
|
||||||
</td>
|
</td>
|
||||||
<td class="multi-select">
|
<td class="multi-select">
|
||||||
{{multi-select
|
{{multi-select
|
||||||
value=field.serializers
|
value=field.serializers
|
||||||
content=serializerContent
|
content=serializerContent
|
||||||
onChange=(action (mut field.serializers))
|
onChange=(action (mut field.serializers))
|
||||||
options=(hash none="admin.wizard.custom_field.serializers.select")
|
options=(hash
|
||||||
}}
|
none="admin.wizard.custom_field.serializers.select"
|
||||||
|
)}}
|
||||||
</td>
|
</td>
|
||||||
<td class="actions">
|
<td class="actions">
|
||||||
{{#if loading}}
|
{{#if loading}}
|
||||||
|
@ -40,18 +42,19 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{d-button
|
{{d-button
|
||||||
action=(action "destroy")
|
action="destroy"
|
||||||
icon="trash-alt"
|
icon="trash-alt"
|
||||||
class="destroy"
|
class="destroy"
|
||||||
disabled=destroyDisabled
|
disabled=destroyDisabled}}
|
||||||
}}
|
|
||||||
{{d-button
|
{{d-button
|
||||||
icon="save"
|
icon="save"
|
||||||
action=(action "save")
|
action="save"
|
||||||
disabled=saveDisabled
|
disabled=saveDisabled
|
||||||
class="save"
|
class="save"}}
|
||||||
}}
|
{{d-button
|
||||||
{{d-button action=(action "close") icon="times" disabled=closeDisabled}}
|
action="close"
|
||||||
|
icon="times"
|
||||||
|
disabled=closeDisabled}}
|
||||||
</td>
|
</td>
|
||||||
{{else}}
|
{{else}}
|
||||||
<td><label>{{field.klass}}</label></td>
|
<td><label>{{field.klass}}</label></td>
|
||||||
|
@ -74,7 +77,7 @@
|
||||||
</td>
|
</td>
|
||||||
{{else}}
|
{{else}}
|
||||||
<td class="actions">
|
<td class="actions">
|
||||||
{{d-button action=(action "edit") icon="pencil-alt"}}
|
{{d-button action="edit" icon="pencil-alt"}}
|
||||||
</td>
|
</td>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
|
@ -1,11 +0,0 @@
|
||||||
<Input
|
|
||||||
@type={{this.inputType}}
|
|
||||||
@value={{readonly this.value}}
|
|
||||||
class="date-picker"
|
|
||||||
placeholder={{this.placeholder}}
|
|
||||||
tabindex={{this.tabindex}}
|
|
||||||
{{on "input" (action "onChangeDate")}}
|
|
||||||
autocomplete="off"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div class="picker-container"></div>
|
|
|
@ -1,8 +0,0 @@
|
||||||
{{custom-wizard-category-selector
|
|
||||||
categories=categories
|
|
||||||
class=fieldClass
|
|
||||||
whitelist=field.content
|
|
||||||
onChange=(action (mut categories))
|
|
||||||
tabindex=field.tabindex
|
|
||||||
options=(hash maximum=field.limit)
|
|
||||||
}}
|
|
|
@ -1,7 +0,0 @@
|
||||||
<Input
|
|
||||||
id={{this.field.id}}
|
|
||||||
@type="checkbox"
|
|
||||||
@checked={{this.field.value}}
|
|
||||||
tabindex={{this.field.tabindex}}
|
|
||||||
class={{this.fieldClass}}
|
|
||||||
/>
|
|
|
@ -1,25 +0,0 @@
|
||||||
{{custom-wizard-composer-editor
|
|
||||||
field=field
|
|
||||||
composer=composer
|
|
||||||
wizard=wizard
|
|
||||||
fieldClass=fieldClass
|
|
||||||
groupsMentioned=(action "groupsMentioned")
|
|
||||||
cannotSeeMention=(action "cannotSeeMention")
|
|
||||||
importQuote=(action "importQuote")
|
|
||||||
togglePreview=(action "togglePreview")
|
|
||||||
afterRefresh=(action "afterRefresh")
|
|
||||||
}}
|
|
||||||
|
|
||||||
<div class="bottom-bar">
|
|
||||||
<button
|
|
||||||
class="wizard-btn toggle-preview"
|
|
||||||
{{action "togglePreview"}}
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<span class="d-button-label">{{i18n togglePreviewLabel}}</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{{#if field.char_counter}}
|
|
||||||
{{wizard-char-counter field.value field.max_length}}
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
|
@ -1,10 +0,0 @@
|
||||||
{{custom-wizard-group-selector
|
|
||||||
groups=site.groups
|
|
||||||
class=fieldClass
|
|
||||||
field=field
|
|
||||||
whitelist=field.content
|
|
||||||
value=field.value
|
|
||||||
tabindex=field.tabindex
|
|
||||||
onChange=(action (mut field.value))
|
|
||||||
options=(hash none="select_kit.default_header_text")
|
|
||||||
}}
|
|
|
@ -1,8 +0,0 @@
|
||||||
<Input
|
|
||||||
id={{this.field.id}}
|
|
||||||
step="0.01"
|
|
||||||
@type="number"
|
|
||||||
@value={{this.field.value}}
|
|
||||||
tabindex={{this.field.tabindex}}
|
|
||||||
class={{this.fieldClass}}
|
|
||||||
/>
|
|
|
@ -1,8 +0,0 @@
|
||||||
{{custom-wizard-tag-chooser
|
|
||||||
tags=field.value
|
|
||||||
class=fieldClass
|
|
||||||
tabindex=field.tabindex
|
|
||||||
tagGroups=field.tag_groups
|
|
||||||
everyTag=true
|
|
||||||
options=(hash maximum=field.limit allowAny=field.can_create_tag)
|
|
||||||
}}
|
|
|
@ -1,8 +0,0 @@
|
||||||
<Input
|
|
||||||
id={{this.field.id}}
|
|
||||||
@value={{this.field.value}}
|
|
||||||
tabindex={{this.field.tabindex}}
|
|
||||||
class={{this.fieldClass}}
|
|
||||||
placeholder={{this.field.translatedPlaceholder}}
|
|
||||||
autocomplete={{this.autocomplete}}
|
|
||||||
/>
|
|
|
@ -1,7 +0,0 @@
|
||||||
<Textarea
|
|
||||||
id={{this.field.id}}
|
|
||||||
@value={{this.field.value}}
|
|
||||||
tabindex={{this.field.tabindex}}
|
|
||||||
class={{this.fieldClass}}
|
|
||||||
placeholder={{this.field.translatedPlaceholder}}
|
|
||||||
/>
|
|
Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen
Laden …
Tabelle hinzufügen
In neuem Issue referenzieren