mobile_workflow 0.1.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/concerns/mobile_workflow/param_parser.rb +17 -0
- data/app/controllers/concerns/mobile_workflow/s3_storable.rb +2 -2
- data/app/controllers/mobile_workflow/sns_notifications_controller.rb +4 -0
- data/app/models/concerns/mobile_workflow/displayable.rb +95 -0
- data/bin/mwf +34 -0
- data/config/routes.rb +1 -0
- data/db/migrate/20200823174210_create_users.rb +11 -0
- data/lib/generators/mobile_workflow/controller_generator.rb +0 -4
- data/lib/generators/mobile_workflow/install/install_generator.rb +51 -10
- data/lib/generators/mobile_workflow/install/templates/Gemfile.erb +50 -0
- data/lib/generators/mobile_workflow/install/templates/Procfile +2 -0
- data/lib/generators/mobile_workflow/install/templates/Procfile.dev +1 -0
- data/lib/generators/mobile_workflow/install/templates/README.md.erb +22 -0
- data/lib/generators/mobile_workflow/install/templates/ability.rb +7 -0
- data/lib/generators/mobile_workflow/install/templates/api_controller.rb.erb +19 -0
- data/lib/generators/mobile_workflow/install/templates/seeds.rb.erb +3 -0
- data/lib/generators/mobile_workflow/install/templates/sessions_controller.rb.erb +20 -0
- data/lib/generators/mobile_workflow/install/templates/storage.s3.yml +14 -0
- data/lib/generators/mobile_workflow/install/templates/user.rb.erb +4 -0
- data/lib/generators/mobile_workflow/templates/controller.rb.erb +5 -7
- data/lib/generators/mobile_workflow/templates/controller_spec.rb.erb +2 -2
- data/lib/mobile_workflow/cli.rb +9 -0
- data/lib/mobile_workflow/cli/app_builder.rb +84 -0
- data/lib/mobile_workflow/cli/app_server_cleaner.rb +24 -0
- data/lib/mobile_workflow/cli/app_server_generator.rb +98 -0
- data/lib/mobile_workflow/cli/aws_backend.rb +80 -0
- data/lib/mobile_workflow/cli/dokku_backend.rb +57 -0
- data/lib/mobile_workflow/cli/heroku_backend.rb +47 -0
- data/lib/mobile_workflow/version.rb +3 -1
- data/lib/templates/active_record/model/model.rb.erb +3 -35
- metadata +59 -18
- data/app/models/mobile_workflow/application_record.rb +0 -5
- data/lib/tasks/mobile_workflow_tasks.rake +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a1d55314927070ee5d1b4498b99b760952214839e146ae0e271bc2ff49a1fce9
|
4
|
+
data.tar.gz: e666ed9c786f10335e1d30505a4f62059636034821d3e4e2d17d532929bfee93
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 80da58aa822183db3273fd34e89b9563040349bc17b60f8817f467f59561e2d7e1684ecaa48b85f88e3993ac7819538fb0515b0aeaddf513727f3f033117b5be
|
7
|
+
data.tar.gz: 6ad8369700ca16b92de687238fabad59f9bd695c9b8941d85beae13edd38d338a658edc5e5085439c3944d63f855f5ae3078ed4cd17467283dd121b7d4b8e848
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module MobileWorkflow
|
2
|
+
module ParamParser
|
3
|
+
def mw_rewrite_payload_properties(model:, properties:)
|
4
|
+
properties.each {|property| mw_rewrite_payload_property(model: model, model_property: property, params_property: property)}
|
5
|
+
end
|
6
|
+
|
7
|
+
def mw_rewrite_payload_property(model:, model_property:, params_property:)
|
8
|
+
params[model][model_property] = params.dig(:payload, params_property, :answer)
|
9
|
+
end
|
10
|
+
|
11
|
+
def mw_rewrite_payload_array(model:, model_property:, params_property:)
|
12
|
+
answer = params.dig(:payload, params_property, :answer)
|
13
|
+
params[model][model_property] = answer[0] if answer
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
@@ -7,11 +7,11 @@ module MobileWorkflow
|
|
7
7
|
return unless params["binaries"]
|
8
8
|
|
9
9
|
params["binaries"].collect do |binary|
|
10
|
-
|
10
|
+
extension = binary["mimetype"].split('/')[1] # i.e. image/jpg --> image, video/mp4 --> video
|
11
11
|
|
12
12
|
{
|
13
13
|
"identifier" => binary["identifier"],
|
14
|
-
"url" => presigned_url("#{object.class.name.underscore}/#{object.id}/#{
|
14
|
+
"url" => presigned_url("#{object.class.name.underscore}/#{object.id}/#{binary["identifier"]}.#{extension}"),
|
15
15
|
"method" => "PUT"
|
16
16
|
}
|
17
17
|
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module MobileWorkflow
|
2
|
+
module Displayable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
include Rails.application.routes.url_helpers
|
5
|
+
|
6
|
+
ON_SUCCESS_OPTIONS = [:none, :reload, :backward, :forward]
|
7
|
+
BUTTON_STYLES = [:primary, :outline, :danger]
|
8
|
+
|
9
|
+
def mw_list_item(id: self.id, text:, detail_text: nil, sf_symbol_name: nil, image_attachment: nil)
|
10
|
+
mw_list_item = {id: id, text: text, detailText: detail_text, sfSymbolName: sf_symbol_name}
|
11
|
+
mw_list_item[:imageURL] = preview_url(image_attachment, height: 100, width: 100) if image_attachment
|
12
|
+
mw_list_item.compact
|
13
|
+
end
|
14
|
+
|
15
|
+
def mw_display_text(text:, label: nil)
|
16
|
+
{type: :text, label: label, text: text.to_s}.compact
|
17
|
+
end
|
18
|
+
|
19
|
+
def mw_display_image(attachment)
|
20
|
+
{type: :image, previewURL: preview_url(attachment, height: 600, width: 1200), url: attachment_url(attachment)}
|
21
|
+
end
|
22
|
+
|
23
|
+
def mw_display_unsplash_image(image_url)
|
24
|
+
if image_url.start_with? "https://unsplash.com/photos"
|
25
|
+
unsplash_id = image_url.split('/').last
|
26
|
+
image_url = "https://source.unsplash.com/#{unsplash_id}/800x600"
|
27
|
+
end
|
28
|
+
|
29
|
+
{type: :image, previewURL: image_url, url: image_url}
|
30
|
+
end
|
31
|
+
|
32
|
+
def mw_display_video(attachment)
|
33
|
+
{type: :video, previewURL: preview_url(attachment, height: 600, width: 1200), url: attachment_url(attachment)}
|
34
|
+
end
|
35
|
+
|
36
|
+
def mw_display_button(label:, style: :primary, on_success: :forward)
|
37
|
+
validate_on_success!(on_success)
|
38
|
+
validate_button_style!(style)
|
39
|
+
|
40
|
+
{type: :button, label: label, style: style, onSuccess: on_success}
|
41
|
+
end
|
42
|
+
|
43
|
+
def mw_display_delete_button(url:, label: "Delete", method: :delete, style: :danger, on_success: :backward)
|
44
|
+
validate_on_success!(on_success)
|
45
|
+
validate_button_style!(style)
|
46
|
+
|
47
|
+
{type: :button, label: label, url: url, method: method, style: style, onSuccess: on_success}
|
48
|
+
end
|
49
|
+
|
50
|
+
def mw_display_button_for_url(label:, url:, method: :put, style: :primary, on_success: :reload)
|
51
|
+
validate_on_success!(on_success)
|
52
|
+
validate_button_style!(style)
|
53
|
+
|
54
|
+
{type: :button, label: label, url: url, method: method, style: style, onSuccess: on_success}
|
55
|
+
end
|
56
|
+
|
57
|
+
def mw_display_button_for_modal_workflow(label:, modal_workflow_name:, style: :primary, on_success: :none)
|
58
|
+
validate_on_success!(on_success)
|
59
|
+
validate_button_style!(style)
|
60
|
+
|
61
|
+
{type: :button, label: label, modalWorkflow: modal_workflow_name, style: style, onSuccess: on_success}
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
def validate_on_success!(on_success)
|
66
|
+
raise 'Unknown on_success action' unless ON_SUCCESS_OPTIONS.include?(on_success)
|
67
|
+
end
|
68
|
+
|
69
|
+
def validate_button_style!(style)
|
70
|
+
raise 'Unknown style' unless BUTTON_STYLES.include?(style)
|
71
|
+
end
|
72
|
+
|
73
|
+
def preview_url(attachment, height:, width:, options: { resize_to_fill: [height, width]} )
|
74
|
+
return nil unless attachment.attached?
|
75
|
+
|
76
|
+
if attachment.image?
|
77
|
+
Rails.application.routes.url_helpers.rails_representation_url(attachment.variant(combine_options: options), host: attachment_host)
|
78
|
+
elsif attachment.previewable?
|
79
|
+
Rails.application.routes.url_helpers.rails_representation_url(attachment.preview(options), host: attachment_host)
|
80
|
+
else
|
81
|
+
return nil
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def attachment_url(attachment)
|
86
|
+
return nil unless attachment.attached?
|
87
|
+
|
88
|
+
Rails.application.routes.url_helpers.rails_blob_url(attachment, host: attachment_host)
|
89
|
+
end
|
90
|
+
|
91
|
+
def attachment_host
|
92
|
+
"https://#{ENV['HEROKU_APP_NAME']}.herokuapp.com"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
data/bin/mwf
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require_relative '../lib/mobile_workflow/cli'
|
3
|
+
|
4
|
+
# Byebug for dev
|
5
|
+
begin
|
6
|
+
require 'byebug'
|
7
|
+
rescue LoadError
|
8
|
+
end
|
9
|
+
|
10
|
+
if ARGV.empty?
|
11
|
+
puts "USAGE: mwf <platform> <command> [options]"
|
12
|
+
puts "Example: mwf rails create:app_server --help"
|
13
|
+
puts "Example: mwf rails destroy:app_server --help"
|
14
|
+
exit 0
|
15
|
+
elsif ['-v', '--version'].include? ARGV[0]
|
16
|
+
puts MobileWorkflow::VERSION
|
17
|
+
exit 0
|
18
|
+
elsif 'rails' == ARGV[0] && 'create:app_server' == ARGV[1]
|
19
|
+
ARGV.shift
|
20
|
+
ARGV.shift
|
21
|
+
|
22
|
+
templates_root = File.expand_path(File.join("..", "lib", "generators", "mobile_workflow", "install", "templates"), File.dirname(__FILE__))
|
23
|
+
MobileWorkflow::Cli::AppServerGenerator.source_root templates_root
|
24
|
+
MobileWorkflow::Cli::AppServerGenerator.source_paths << Rails::Generators::AppGenerator.source_root << templates_root
|
25
|
+
MobileWorkflow::Cli::AppServerGenerator.start
|
26
|
+
elsif 'rails' == ARGV[0] && 'destroy:app_server' == ARGV[1]
|
27
|
+
ARGV.shift
|
28
|
+
ARGV.shift
|
29
|
+
|
30
|
+
ARGV.unshift(MobileWorkflow::Cli::AppServerCleaner.default_task) unless ARGV[0] == '--help'
|
31
|
+
MobileWorkflow::Cli::AppServerCleaner.start(ARGV)
|
32
|
+
end
|
33
|
+
|
34
|
+
|
data/config/routes.rb
CHANGED
@@ -23,10 +23,6 @@ module MobileWorkflow
|
|
23
23
|
params = attributes_names.map{ |name| ":#{name}" }
|
24
24
|
params.join(", ")
|
25
25
|
end
|
26
|
-
|
27
|
-
def rewrite_params
|
28
|
-
attributes_names.map {|name| "params[:#{singular_table_name}][:#{name}] = params[:payload][:#{name}][:answer]" }.join("\n\t\t")
|
29
|
-
end
|
30
26
|
end
|
31
27
|
end
|
32
28
|
end
|
@@ -3,22 +3,42 @@ require "rails/generators/base"
|
|
3
3
|
module MobileWorkflow
|
4
4
|
module Generators
|
5
5
|
class InstallGenerator < Rails::Generators::Base
|
6
|
+
|
7
|
+
# Schemas to avoid generating models for (static items from MW)
|
8
|
+
SKIP_SCHEMAS = ["attachment", "ListItem", "DisplayItem", "DisplayText", "DisplayButton", "DisplayImage", "DisplayVideo"]
|
9
|
+
|
6
10
|
source_root File.expand_path("../templates", __FILE__)
|
7
11
|
|
8
12
|
class_option :open_api_spec_path, type: :string, default: "config/open_api_spec.json"
|
13
|
+
class_option :doorkeeper_oauth, type: :boolean, default: false
|
14
|
+
class_option :interactive, type: :boolean, default: false
|
9
15
|
|
10
16
|
def create_api_controller
|
11
|
-
template(
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
template("api_controller.rb.erb", "app/controllers/api_controller.rb")
|
18
|
+
end
|
19
|
+
|
20
|
+
def mount_engine
|
21
|
+
route "mount MobileWorkflow::Engine => '/'"
|
22
|
+
end
|
23
|
+
|
24
|
+
def generate_doorkeeper
|
25
|
+
return unless options[:doorkeeper_oauth]
|
26
|
+
say "Generating Doorkeeper OAuth"
|
27
|
+
|
28
|
+
generate 'doorkeeper:install'
|
29
|
+
gsub_file 'config/initializers/doorkeeper.rb', 'raise "Please configure doorkeeper resource_owner_authenticator block located in #{__FILE__}"', 'User.find_by_id(session[:user_id]) || redirect_to(new_session_url(return_to: request.fullpath))'
|
30
|
+
generate 'doorkeeper:migration'
|
31
|
+
generate 'doorkeeper:pkce'
|
32
|
+
template("user.rb.erb", "app/models/user.rb")
|
33
|
+
template("sessions_controller.rb.erb", "app/controllers/sessions_controller.rb")
|
34
|
+
route "resources :sessions, only: [:new, :create]"
|
15
35
|
end
|
16
36
|
|
17
37
|
def generate_models
|
18
38
|
say "Generating models"
|
19
39
|
@model_properties = {}
|
20
40
|
open_api_spec[:components][:schemas].each_pair do |model_name, schema|
|
21
|
-
next if
|
41
|
+
next if SKIP_SCHEMAS.include? model_name # Don't generate schemas for MW schemas
|
22
42
|
|
23
43
|
model_name = model_name.underscore
|
24
44
|
model_properties = model_properties(model_name, schema)
|
@@ -29,8 +49,6 @@ module MobileWorkflow
|
|
29
49
|
|
30
50
|
def generate_controllers_and_routes
|
31
51
|
say "Generating controllers"
|
32
|
-
controller_names = open_api_spec[:paths].keys.collect{|url_path| url_path.split('/').last }
|
33
|
-
|
34
52
|
route "root to: 'admin/#{controller_names.first}#index'"
|
35
53
|
|
36
54
|
controller_names.each do |plural_controller_name|
|
@@ -40,29 +58,52 @@ module MobileWorkflow
|
|
40
58
|
route "resources :#{plural_controller_name}, only: [:index, :show, :create]"
|
41
59
|
end
|
42
60
|
end
|
61
|
+
|
62
|
+
def generate_seeds
|
63
|
+
template("seeds.rb.erb", "db/seeds.rb", force: true)
|
64
|
+
end
|
43
65
|
|
44
66
|
private
|
67
|
+
def controller_names
|
68
|
+
@controller_names ||= oai_spec_paths.collect{|url_path| url_path.split('/')[1] }.uniq
|
69
|
+
end
|
70
|
+
|
71
|
+
def oai_spec_paths
|
72
|
+
@oai_spec_paths ||= open_api_spec[:paths].keys
|
73
|
+
end
|
74
|
+
|
45
75
|
def open_api_spec
|
46
76
|
@open_api_spec ||= read_openapi_spec
|
47
77
|
end
|
48
78
|
|
49
79
|
def read_openapi_spec
|
50
80
|
say "Loading OpenAPI Spec: #{open_api_spec_path}"
|
51
|
-
return JSON.parse(File.read(open_api_spec_path)).with_indifferent_access
|
81
|
+
return JSON.parse(File.read(File.join(Rails.root, open_api_spec_path))).with_indifferent_access
|
52
82
|
end
|
53
83
|
|
54
84
|
def open_api_spec_path
|
55
85
|
options[:open_api_spec_path]
|
56
86
|
end
|
57
87
|
|
88
|
+
def interactive?
|
89
|
+
options[:interactive]
|
90
|
+
end
|
91
|
+
|
58
92
|
def model_properties(name, schema)
|
59
|
-
generated_properties_args = schema["properties"].keys.collect{|key| "#{key}
|
60
|
-
if yes?("Use generated schema #{name}(#{generated_properties_args})[yn]?")
|
93
|
+
generated_properties_args = schema["properties"].keys.collect{|key| "#{key}:#{model_property_type(schema["properties"][key])}" }.join(" ")
|
94
|
+
if !interactive? || yes?("Use generated schema #{name}(#{generated_properties_args})[yn]?")
|
61
95
|
generated_properties_args
|
62
96
|
else
|
63
97
|
ask "Specify schema for #{name}: (e.g. text:string image:attachment region:reference)"
|
64
98
|
end
|
65
99
|
end
|
100
|
+
|
101
|
+
def model_property_type(property)
|
102
|
+
return property["type"] unless property["type"].blank?
|
103
|
+
return 'attachment' if property['$ref'] == "#/components/schemas/attachment"
|
104
|
+
|
105
|
+
raise 'Unknown property type'
|
106
|
+
end
|
66
107
|
end
|
67
108
|
end
|
68
109
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
3
|
+
|
4
|
+
ruby '2.6.6'
|
5
|
+
|
6
|
+
# Core Gems
|
7
|
+
gem 'rails', '~> 6.1.0'
|
8
|
+
gem 'puma', '~> 5.0'
|
9
|
+
gem 'sass-rails', '>= 6'
|
10
|
+
gem 'turbolinks', '~> 5'
|
11
|
+
|
12
|
+
# Mobile Workflow
|
13
|
+
#gem 'mobile_workflow', path: '../mobile_workflow'
|
14
|
+
gem 'mobile_workflow', github: 'FutureWorkshops/mobile_workflow'
|
15
|
+
|
16
|
+
# Authorisation / Authentication
|
17
|
+
<%- if options[:doorkeeper_oauth] %>
|
18
|
+
gem 'doorkeeper'
|
19
|
+
gem 'bcrypt-ruby'
|
20
|
+
<%- end %>
|
21
|
+
gem 'cancancan', '~> 3.1'
|
22
|
+
|
23
|
+
# Admin console
|
24
|
+
gem 'administrate', '~> 0.13.0'
|
25
|
+
gem 'administrate-field-active_storage'
|
26
|
+
gem 'administrate-field-enum'
|
27
|
+
|
28
|
+
<%- if options[:s3_storage] %>
|
29
|
+
# Backend storage for S3
|
30
|
+
gem "image_processing"
|
31
|
+
gem 'aws-sdk-s3', '~> 1.60', '>= 1.60.1'
|
32
|
+
gem 'aws-sdk-sns', '~> 1.23'
|
33
|
+
<%- end %>
|
34
|
+
|
35
|
+
group :development do
|
36
|
+
gem 'web-console', '>= 3.3.0'
|
37
|
+
gem 'listen', '>= 3.0.5', '< 3.2'
|
38
|
+
end
|
39
|
+
|
40
|
+
group :development, :test do
|
41
|
+
gem 'sqlite3'
|
42
|
+
gem 'rspec-rails', '~> 4.0.0'
|
43
|
+
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
|
44
|
+
gem 'dotenv-rails'
|
45
|
+
gem 'factory_bot_rails'
|
46
|
+
end
|
47
|
+
|
48
|
+
group :production do
|
49
|
+
gem 'pg', '>= 0.18', '< 2.0'
|
50
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
web: bundle exec rackup config.ru -p $PORT
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# <%= app_name.humanize %>
|
2
|
+
|
3
|
+
## Prereqs
|
4
|
+
* Ruby >= 2.5.5
|
5
|
+
* Rails >= 6.0.0
|
6
|
+
|
7
|
+
Optional
|
8
|
+
* Heroku toolbelt
|
9
|
+
* Heroku account
|
10
|
+
|
11
|
+
## Getting Started
|
12
|
+
|
13
|
+
After you have cloned this repo, run this setup script to set up your machine
|
14
|
+
with the necessary dependencies to run and test this app:
|
15
|
+
|
16
|
+
% ./bin/setup
|
17
|
+
|
18
|
+
After setting up, you can run the application using [Heroku Local]:
|
19
|
+
|
20
|
+
% heroku local
|
21
|
+
|
22
|
+
[Heroku Local]: https://devcenter.heroku.com/articles/heroku-local
|
@@ -1,5 +1,24 @@
|
|
1
1
|
class ApiController < ActionController::API
|
2
|
+
rescue_from CanCan::AccessDenied do |exception|
|
3
|
+
Rails.logger.debug "Access denied on #{exception.action} #{exception.subject.inspect}"
|
4
|
+
head :forbidden
|
5
|
+
end
|
6
|
+
|
7
|
+
<% if options[:doorkeeper_oauth] %>
|
8
|
+
before_action :doorkeeper_authorize!, unless: :anonymous_action?
|
9
|
+
|
10
|
+
def current_resource_owner
|
11
|
+
User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token&.accessible?
|
12
|
+
end
|
13
|
+
alias_method :current_user, :current_resource_owner
|
14
|
+
|
15
|
+
protected
|
16
|
+
def anonymous_action?
|
17
|
+
false
|
18
|
+
end
|
19
|
+
<% else %>
|
2
20
|
def current_user
|
3
21
|
nil
|
4
22
|
end
|
23
|
+
<% end %>
|
5
24
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class SessionsController < ApplicationController
|
2
|
+
def new
|
3
|
+
end
|
4
|
+
|
5
|
+
def create
|
6
|
+
@user = User.find_by(email: params[:email])
|
7
|
+
if @user && @user.authenticate(params[:password])
|
8
|
+
session[:user_id] = @user.id
|
9
|
+
redirect_to params[:return_to] || root_url, notice: "Logged in!"
|
10
|
+
else
|
11
|
+
flash[:warning] = "You have entered incorrect email and/or password."
|
12
|
+
render :new
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def destroy
|
17
|
+
session.delete(:user_id)
|
18
|
+
redirect_to root_path
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
test:
|
2
|
+
service: Disk
|
3
|
+
root: <%= Rails.root.join("tmp/storage") %>
|
4
|
+
|
5
|
+
local:
|
6
|
+
service: Disk
|
7
|
+
root: <%= Rails.root.join("storage") %>
|
8
|
+
|
9
|
+
amazon:
|
10
|
+
service: S3
|
11
|
+
access_key_id: <%= ENV['AWS_ACCESS_ID'] %>
|
12
|
+
secret_access_key: <%= ENV['AWS_SECRET_KEY'] %>
|
13
|
+
region: <%= ENV['AWS_REGION'] %>
|
14
|
+
bucket: <%= ENV['AWS_BUCKET_NAME'] %>
|
@@ -1,5 +1,6 @@
|
|
1
1
|
<% module_namespacing do -%>
|
2
2
|
class <%= controller_class_name %>Controller < ApiController
|
3
|
+
# include MobileWorkflow::S3Storable
|
3
4
|
before_action :rewrite_payload, only: :create
|
4
5
|
|
5
6
|
load_and_authorize_resource
|
@@ -23,19 +24,16 @@ class <%= controller_class_name %>Controller < ApiController
|
|
23
24
|
private
|
24
25
|
def rewrite_payload
|
25
26
|
# Use this method to make any changes to params to make them compatible with ActiveRecord
|
26
|
-
|
27
|
-
# 1. Example to get
|
28
|
-
# params[:payload][:name] = params.dig(:payload, :name, :answer)
|
29
|
-
|
30
|
-
# 2. Example to get selected id from a list
|
27
|
+
|
28
|
+
# 1. Example to get selected id from a list
|
31
29
|
# passport_id = params.dig(:payload, :choose_passport, :selected, :id)
|
32
30
|
|
33
31
|
Rails.logger.debug "Pre-rewrite params: #{params}"
|
34
|
-
|
32
|
+
# Do your rewriting here
|
35
33
|
end
|
36
34
|
|
37
35
|
def <%= singular_table_name.underscore %>_params
|
38
|
-
params.require(
|
36
|
+
params.require(:payload).permit(<%= permitted_params %>)
|
39
37
|
end
|
40
38
|
end
|
41
39
|
<% end %>
|
@@ -8,7 +8,7 @@ RSpec.describe <%= controller_class_name %>Controller do
|
|
8
8
|
let(:json_response) { JSON.parse(response.body, symbolize_names: true) }
|
9
9
|
|
10
10
|
describe 'GET #index' do
|
11
|
-
let!(:<%= controller_class_name.singularize.underscore %>) {
|
11
|
+
let!(:<%= controller_class_name.singularize.underscore %>) { create(:<%= controller_class_name.singularize.underscore %>) }
|
12
12
|
before(:each) { get :index, params: params }
|
13
13
|
|
14
14
|
context 'ok' do
|
@@ -18,7 +18,7 @@ RSpec.describe <%= controller_class_name %>Controller do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
describe 'GET #show' do
|
21
|
-
let(:<%= controller_class_name.singularize.underscore %>) {
|
21
|
+
let(:<%= controller_class_name.singularize.underscore %>) { create(:<%= controller_class_name.singularize.underscore %>) }
|
22
22
|
let(:params) { { id: <%= controller_class_name.singularize.underscore %>.id } }
|
23
23
|
before(:each) { get :show, params: params }
|
24
24
|
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require "mobile_workflow/version"
|
2
|
+
|
3
|
+
require "mobile_workflow/cli/app_server_generator"
|
4
|
+
require "mobile_workflow/cli/app_builder"
|
5
|
+
require "mobile_workflow/cli/app_server_cleaner"
|
6
|
+
|
7
|
+
require "mobile_workflow/cli/aws_backend"
|
8
|
+
require "mobile_workflow/cli/heroku_backend"
|
9
|
+
require "mobile_workflow/cli/dokku_backend"
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module MobileWorkflow::Cli
|
2
|
+
class AppBuilder < Rails::AppBuilder
|
3
|
+
def readme
|
4
|
+
template 'README.md.erb', 'README.md'
|
5
|
+
end
|
6
|
+
|
7
|
+
def gemfile
|
8
|
+
template 'Gemfile.erb', 'Gemfile'
|
9
|
+
end
|
10
|
+
|
11
|
+
def procfiles
|
12
|
+
copy_file 'Procfile', 'Procfile'
|
13
|
+
copy_file 'Procfile.dev', 'Procfile.dev'
|
14
|
+
end
|
15
|
+
|
16
|
+
def rspec_generator
|
17
|
+
generate 'rspec:install'
|
18
|
+
end
|
19
|
+
|
20
|
+
def ability_generator
|
21
|
+
copy_file 'ability.rb', 'app/models/ability.rb'
|
22
|
+
end
|
23
|
+
|
24
|
+
def active_storage
|
25
|
+
rails_command 'active_storage:install'
|
26
|
+
copy_file 'storage.s3.yml', 'config/storage.yml'
|
27
|
+
gsub_file 'config/environments/production.rb', 'config.active_storage.service = :local', 'config.active_storage.service = :amazon'
|
28
|
+
end
|
29
|
+
|
30
|
+
def mobile_workflow_generator(open_api_spec_path)
|
31
|
+
copy_file open_api_spec_path, 'config/open_api_spec.json'
|
32
|
+
gen_opts = ""
|
33
|
+
gen_opts += "--doorkeeper_oauth" if options[:doorkeeper_oauth]
|
34
|
+
generate "mobile_workflow:install #{gen_opts}"
|
35
|
+
|
36
|
+
# Copy user migrations if needed
|
37
|
+
rails_command 'mobile_workflow:install:migrations' if options[:doorkeeper_oauth]
|
38
|
+
end
|
39
|
+
|
40
|
+
def s3_backend(region)
|
41
|
+
@region = region
|
42
|
+
aws_backend.create
|
43
|
+
aws_backend.write_env
|
44
|
+
|
45
|
+
if options[:heroku]
|
46
|
+
heroku_backend.sync_dotenv
|
47
|
+
sleep 10 # Wait for the server to restart
|
48
|
+
aws_backend.create_topic_subscription(heroku_backend.notifications_endpoint)
|
49
|
+
elsif options[:dokku]
|
50
|
+
dokku_backend.sync_dotenv
|
51
|
+
aws_backend.create_topic_subscription(dokku_backend.notifications_endpoint)
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
def heroku
|
57
|
+
heroku_backend.create
|
58
|
+
heroku_backend.configure_activestorage if options[:s3_storage]
|
59
|
+
heroku_backend.deploy
|
60
|
+
heroku_backend.sync_dotenv
|
61
|
+
end
|
62
|
+
|
63
|
+
def dokku(dokku_host)
|
64
|
+
@dokku_host = dokku_host
|
65
|
+
dokku_backend.create
|
66
|
+
dokku_backend.configure_activestorage if options[:s3_storage]
|
67
|
+
dokku_backend.deploy
|
68
|
+
dokku_backend.sync_dotenv
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
def aws_backend
|
73
|
+
@aws_backend ||= AwsBackend.new(app_name: app_name, region: @region)
|
74
|
+
end
|
75
|
+
|
76
|
+
def dokku_backend
|
77
|
+
@dokku_backend ||= DokkuBackend.new(app_name: app_name, dokku_host: @dokku_host)
|
78
|
+
end
|
79
|
+
|
80
|
+
def heroku_backend
|
81
|
+
@heroku_backend ||= HerokuBackend.new(app_name: app_name)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/rails/app/app_generator'
|
3
|
+
require 'json'
|
4
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
5
|
+
|
6
|
+
module MobileWorkflow::Cli
|
7
|
+
class AppServerCleaner < Thor
|
8
|
+
class_option :version, type: :boolean, aliases: "-v", desc: "Show version number and quit"
|
9
|
+
class_option :help, type: :boolean, aliases: '-h', desc: "Show this help message and quit"
|
10
|
+
|
11
|
+
class_option :heroku, type: :boolean, default: false, desc: "Clean Heroku app"
|
12
|
+
class_option :s3_storage, type: :boolean, default: false, desc: "Clean an s3 backend for attachment upload and storage"
|
13
|
+
class_option :aws_region, type: :string, default: 'us-east-1', desc: "Specify a region to create AWS resources in"
|
14
|
+
|
15
|
+
default_task :clean
|
16
|
+
|
17
|
+
desc "rails destroy:app_server APP_NAME", "Destroy App server"
|
18
|
+
def clean(app_name)
|
19
|
+
`rm -rf #{app_name}`
|
20
|
+
AwsBackend.new(app_name: app_name, region: options[:aws_region]).destroy if options[:s3_storage]
|
21
|
+
HerokuBackend.new(app_name: app_name).destroy if options[:heroku]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/rails/app/app_generator'
|
3
|
+
require 'json'
|
4
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
5
|
+
|
6
|
+
module MobileWorkflow::Cli
|
7
|
+
class AppServerGenerator < Rails::Generators::AppGenerator
|
8
|
+
hide!
|
9
|
+
class_option :skip_test, type: :boolean, default: true, desc: "Skip Test Unit"
|
10
|
+
class_option :force, type: :boolean, default: true, desc: "Force overwrite"
|
11
|
+
class_option :skip_webpack_install, type: :boolean, default: true, desc: "Skip webpacker installation"
|
12
|
+
class_option :skip_bootsnap, type: :boolean, default: true, desc: "Skip Bootsnap"
|
13
|
+
|
14
|
+
class_option :version, type: :boolean, aliases: "-v", desc: "Show version number and quit"
|
15
|
+
class_option :help, type: :boolean, aliases: '-h', desc: "Show this help message and quit"
|
16
|
+
|
17
|
+
class_option :heroku, type: :boolean, default: false, desc: "Create Heroku app"
|
18
|
+
|
19
|
+
class_option :dokku, type: :boolean, default: false, desc: "Create Dokku app"
|
20
|
+
class_option :dokku_host, type: :string, desc: "Specify the Dokku host machine e.g. 18.131.127.164"
|
21
|
+
|
22
|
+
class_option :s3_storage, type: :boolean, default: false, desc: "Create an s3 backend for attachment upload and storage"
|
23
|
+
class_option :aws_region, type: :string, default: 'us-east-1', desc: "Specify a region to create AWS resources in"
|
24
|
+
|
25
|
+
class_option :doorkeeper_oauth, type: :boolean, default: false, desc: "Use Doorkeeper gem for OAuth login"
|
26
|
+
|
27
|
+
def self.banner
|
28
|
+
"mwf rails create:app_server <directory> <OpenAPI Spec file path> [options]"
|
29
|
+
end
|
30
|
+
|
31
|
+
def finish_template
|
32
|
+
super
|
33
|
+
after_bundle do
|
34
|
+
build :procfiles
|
35
|
+
build :rspec_generator
|
36
|
+
build :ability_generator
|
37
|
+
build :active_storage if options[:s3_storage]
|
38
|
+
build :mobile_workflow_generator, ARGV[1]
|
39
|
+
setup_db
|
40
|
+
generate_administrate
|
41
|
+
|
42
|
+
generate_dot_env
|
43
|
+
initial_git_commit
|
44
|
+
|
45
|
+
build :heroku if options[:heroku]
|
46
|
+
build :dokku, options[:dokku_host] if options[:dokku]
|
47
|
+
build :s3_backend, options[:aws_region] if options[:s3_storage]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
protected
|
52
|
+
|
53
|
+
def get_builder_class
|
54
|
+
MobileWorkflow::Cli::AppBuilder
|
55
|
+
end
|
56
|
+
|
57
|
+
# Todo: MBS - move these methods to the builder class
|
58
|
+
# Ideally override RailsBuilder methods
|
59
|
+
private
|
60
|
+
def generate_administrate
|
61
|
+
generate 'administrate:install'
|
62
|
+
file 'app/assets/config/manifest.js', <<-CODE
|
63
|
+
//= link administrate/application.css
|
64
|
+
//= link administrate/application.js
|
65
|
+
CODE
|
66
|
+
|
67
|
+
file 'app/controllers/admin/application_controller.rb', <<-CODE
|
68
|
+
module Admin
|
69
|
+
class ApplicationController < Administrate::ApplicationController
|
70
|
+
http_basic_authenticate_with(name: ENV["ADMIN_USER"], password: ENV["ADMIN_PASSWORD"])
|
71
|
+
end
|
72
|
+
end
|
73
|
+
CODE
|
74
|
+
generate 'administrate:routes'
|
75
|
+
end
|
76
|
+
|
77
|
+
def setup_db
|
78
|
+
rails_command "db:drop"
|
79
|
+
rails_command "db:create"
|
80
|
+
rails_command "db:migrate"
|
81
|
+
end
|
82
|
+
|
83
|
+
def initial_git_commit
|
84
|
+
git add: "."
|
85
|
+
git commit: %Q{ -m 'Initial commit' }
|
86
|
+
end
|
87
|
+
|
88
|
+
def generate_dot_env
|
89
|
+
admin_user = 'admin'
|
90
|
+
admin_password = SecureRandom.base64(12)
|
91
|
+
|
92
|
+
file '.env', <<-CODE
|
93
|
+
ADMIN_USER=#{admin_user}
|
94
|
+
ADMIN_PASSWORD=#{admin_password}
|
95
|
+
CODE
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module MobileWorkflow::Cli
|
4
|
+
class AwsBackend
|
5
|
+
|
6
|
+
attr_accessor :access_id, :secret_key, :region, :bucket_name
|
7
|
+
|
8
|
+
def initialize(app_name:, region:)
|
9
|
+
@app_name = app_name
|
10
|
+
@aws_name = @app_name.gsub("_", "-")
|
11
|
+
@region = region
|
12
|
+
end
|
13
|
+
|
14
|
+
def bucket_name
|
15
|
+
@aws_name
|
16
|
+
end
|
17
|
+
|
18
|
+
def create
|
19
|
+
bucket_configuration = ''
|
20
|
+
bucket_configuration += "--create-bucket-configuration LocationConstraint=#{@region}" unless @region.eql? 'us-east-1'
|
21
|
+
aws_command "aws s3api create-bucket --bucket #{@aws_name} --acl private --region #{@region} #{bucket_configuration}"
|
22
|
+
@topic_arn = aws_command("aws sns create-topic --name #{@aws_name} --region #{@region}")["TopicArn"]
|
23
|
+
aws_command "aws iam create-user --user-name #{@aws_name}"
|
24
|
+
aws_command "aws iam put-user-policy --user-name #{@aws_name} --policy-name s3 --policy-document '{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":[\"s3:PutObject\",\"s3:PutObjectAcl\",\"s3:GetObject\", \"s3:DeleteObject\"],\"Resource\":[\"arn:aws:s3:::#{@aws_name}/*\"]}, {\"Effect\": \"Allow\", \"Action\": \"s3:ListBucket\", \"Resource\": \"arn:aws:s3:::#{@aws_name}\"}]}'"
|
25
|
+
aws_command "aws iam put-user-policy --user-name #{@aws_name} --policy-name sns --policy-document '{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":[\"sns:ConfirmSubscription\"],\"Resource\":[\"#{@topic_arn}\"]}]}'"
|
26
|
+
aws_command "aws sns set-topic-attributes --topic-arn #{@topic_arn} --region #{@region} --attribute-name Policy --attribute-value '{\"Version\": \"2012-10-17\", \"Id\": \"s3\", \"Statement\": [{\"Sid\": \"#{@aws_name}-s3-sid\", \"Effect\": \"Allow\", \"Principal\": {\"AWS\": \"*\"}, \"Action\": \"SNS:Publish\", \"Resource\": \"#{@topic_arn}\", \"Condition\": {\"ArnEquals\": {\"aws:SourceArn\": \"arn:aws:s3:::#{@aws_name}\"}}}]}'"
|
27
|
+
aws_command "aws s3api put-bucket-notification-configuration --bucket #{@aws_name} --notification-configuration '{\"TopicConfigurations\": [{\"TopicArn\": \"#{@topic_arn}\", \"Events\": [\"s3:ObjectCreated:*\"]}]}'"
|
28
|
+
aws_credentials_json = aws_command("aws iam create-access-key --user-name #{@aws_name}")["AccessKey"]
|
29
|
+
@access_id, @secret_key = aws_credentials_json["AccessKeyId"], aws_credentials_json["SecretAccessKey"]
|
30
|
+
return @access_id, @secret_key
|
31
|
+
end
|
32
|
+
|
33
|
+
def put_env
|
34
|
+
puts "AWS_ACCESS_ID=#{access_id}"
|
35
|
+
puts "AWS_SECRET_KEY=#{secret_key}"
|
36
|
+
puts "AWS_REGION=#{region}"
|
37
|
+
puts "AWS_BUCKET_NAME=#{bucket_name}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def write_env
|
41
|
+
open('.env', 'a') { |f|
|
42
|
+
f.puts "AWS_ACCESS_ID=#{access_id}"
|
43
|
+
f.puts "AWS_SECRET_KEY=#{secret_key}"
|
44
|
+
f.puts "AWS_REGION=#{region}"
|
45
|
+
f.puts "AWS_BUCKET_NAME=#{bucket_name}"
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def create_topic_subscription(endpoint)
|
50
|
+
aws_command "aws sns subscribe --topic-arn #{@topic_arn} --region #{@region} --protocol https --notification-endpoint #{endpoint}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def destroy
|
54
|
+
aws_command "aws s3api delete-bucket --bucket #{@aws_name} --region #{@region}"
|
55
|
+
|
56
|
+
aws_command("aws sns list-topics")["Topics"].each do |topic|
|
57
|
+
topic_arn = topic["TopicArn"]
|
58
|
+
aws_command "aws sns delete-topic --topic-arn '#{topic_arn}'" if topic_arn.end_with?(@aws_name)
|
59
|
+
end
|
60
|
+
|
61
|
+
aws_command "aws iam delete-user-policy --user-name #{@aws_name} --policy-name s3"
|
62
|
+
aws_command "aws iam delete-user-policy --user-name #{@aws_name} --policy-name sns"
|
63
|
+
aws_command("aws iam list-access-keys --user-name #{@aws_name}")["AccessKeyMetadata"].each do |accessKeyMetadata|
|
64
|
+
aws_command "aws iam delete-access-key --user-name #{@aws_name} --access-key #{accessKeyMetadata["AccessKeyId"]}"
|
65
|
+
end
|
66
|
+
aws_command "aws iam delete-user --user-name #{@aws_name}"
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
def aws_command(command)
|
71
|
+
puts "Running: #{command}"
|
72
|
+
output = `#{command}`
|
73
|
+
return nil if output == nil || output.strip == ""
|
74
|
+
|
75
|
+
puts "Output: #{output}"
|
76
|
+
JSON.parse(output)
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module MobileWorkflow::Cli
|
2
|
+
class DokkuBackend
|
3
|
+
def initialize(dokku_host:, app_name:)
|
4
|
+
@dokku_host = dokku_host
|
5
|
+
@dokku_app_name = app_name.gsub("_", "-")
|
6
|
+
end
|
7
|
+
|
8
|
+
def create
|
9
|
+
remote_command "dokku apps:create #{@dokku_app_name}"
|
10
|
+
remote_command "dokku postgres:create #{@dokku_app_name}"
|
11
|
+
remote_command "dokku postgres:link #{@dokku_app_name} #{@dokku_app_name}"
|
12
|
+
remote_command "dokku domains:enable #{@dokku_app_name}"
|
13
|
+
remote_command "dokku letsencrypt #{@dokku_app_name}"
|
14
|
+
|
15
|
+
local_command "git remote add dokku dokku@#{@dokku_host}:#{@dokku_app_name}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def configure_activestorage
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
def deploy
|
23
|
+
local_command "git push dokku master"
|
24
|
+
end
|
25
|
+
|
26
|
+
def sync_dotenv
|
27
|
+
env = File.read(".env").split.join(" ")
|
28
|
+
puts "Setting env: #{env}"
|
29
|
+
local_command "dokku config:set #{env}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def destroy
|
33
|
+
remote_command "dokku apps:destroy #{@dokku_app_name}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def dokku_app_host
|
37
|
+
remote_command "dokku url #{@dokku_app_name}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def notifications_endpoint
|
41
|
+
"https://#{dokku_app_host}/sns_notifications"
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
def remote_command(command)
|
46
|
+
command = "ssh -t ubuntu@#{@dokku_host} '#{command}'"
|
47
|
+
local_command(command)
|
48
|
+
end
|
49
|
+
|
50
|
+
def local_command(command)
|
51
|
+
puts "Running: #{command}"
|
52
|
+
output = `#{command}`
|
53
|
+
puts "Output: #{output}" unless output.blank?
|
54
|
+
return output
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module MobileWorkflow::Cli
|
2
|
+
class HerokuBackend
|
3
|
+
def initialize(app_name:)
|
4
|
+
@heroku_app_name = app_name.gsub("_", "-")
|
5
|
+
end
|
6
|
+
|
7
|
+
def create
|
8
|
+
heroku_command "heroku create #{@heroku_app_name}"
|
9
|
+
heroku_command "git push --set-upstream heroku master"
|
10
|
+
end
|
11
|
+
|
12
|
+
def configure_activestorage
|
13
|
+
heroku_command "heroku buildpacks:add -i 1 https://github.com/heroku/heroku-buildpack-activestorage-preview --app #{@heroku_app_name}"
|
14
|
+
heroku_command "heroku labs:enable runtime-dyno-metadata --app #{@heroku_app_name}" # Gives access to heroku variables which can be used to construct URLs
|
15
|
+
|
16
|
+
# Force recompile after buildpacks change
|
17
|
+
heroku_command "git commit --allow-empty -m 'empty commit'"
|
18
|
+
deploy
|
19
|
+
end
|
20
|
+
|
21
|
+
def deploy
|
22
|
+
heroku_command "git push"
|
23
|
+
end
|
24
|
+
|
25
|
+
def sync_dotenv
|
26
|
+
env = File.read(".env").split.join(" ")
|
27
|
+
puts "Setting env: #{env}"
|
28
|
+
heroku_command "heroku config:set #{env} --app #{@heroku_app_name}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def destroy
|
32
|
+
heroku_command "heroku destroy #{@heroku_app_name} --confirm #{@heroku_app_name}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def notifications_endpoint
|
36
|
+
"https://#{@heroku_app_name}.herokuapp.com/sns_notifications"
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
def heroku_command(command)
|
41
|
+
puts "Running: #{command}"
|
42
|
+
output = `#{command}`
|
43
|
+
puts "Output: #{output}"
|
44
|
+
return output
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
<% module_namespacing do -%>
|
2
2
|
class <%= class_name %> < <%= parent_class_name.classify %>
|
3
|
-
|
4
|
-
# include Rails.application.routes.url_helpers
|
3
|
+
include MobileWorkflow::Displayable
|
5
4
|
|
6
5
|
<% attributes.select(&:reference?).each do |attribute| -%>
|
7
6
|
belongs_to :<%= attribute.name %><%= ', polymorphic: true' if attribute.polymorphic? %>
|
@@ -14,43 +13,12 @@ class <%= class_name %> < <%= parent_class_name.classify %>
|
|
14
13
|
<% end -%>
|
15
14
|
|
16
15
|
def list_item_as_json
|
17
|
-
|
18
|
-
id: id,
|
19
|
-
text: text,
|
20
|
-
# detailText: nil,
|
21
|
-
# sfSymbolName: nil,
|
22
|
-
# imageURL: preview_url(image, height: 100, width: 100)
|
23
|
-
}
|
16
|
+
mw_list_item(text: text)
|
24
17
|
end
|
25
18
|
|
26
19
|
def display_as_json
|
27
|
-
[
|
28
|
-
{label: "ID", text: text, mimeType: 'text/plain'},
|
29
|
-
{label: "Text", text: text, mimeType: 'text/plain'}
|
30
|
-
]
|
20
|
+
[mw_display_text(label: 'ID', text: id.to_s)]
|
31
21
|
end
|
32
|
-
|
33
|
-
# private
|
34
|
-
# include Rails.application.routes.url_helpers # for attachment URLs
|
35
|
-
# def preview_url(attachment, height:, width:, options: { resize_to_fill: [height, width]} )
|
36
|
-
# return nil unless attachment.attached?
|
37
|
-
#
|
38
|
-
# if attachment.image?
|
39
|
-
# Rails.application.routes.url_helpers.rails_representation_url(attachment.variant(combine_options: options), host: attachment_host)
|
40
|
-
# elsif attachment.previewable?
|
41
|
-
# Rails.application.routes.url_helpers.rails_representation_url(attachment.preview(options), host: attachment_host)
|
42
|
-
# else
|
43
|
-
# return nil
|
44
|
-
# end
|
45
|
-
# end
|
46
|
-
#
|
47
|
-
# def attachment_url(attachment)
|
48
|
-
# Rails.application.routes.url_helpers.rails_blob_url(attachment, host: attachment_host)
|
49
|
-
# end
|
50
|
-
#
|
51
|
-
# def attachment_host
|
52
|
-
# "https://#{ENV['HEROKU_APP_NAME']}.herokuapp.com"
|
53
|
-
# end
|
54
22
|
|
55
23
|
end
|
56
24
|
<% end -%>
|
metadata
CHANGED
@@ -1,35 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mobile_workflow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Brooke-Smith
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-12-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 6.0.3
|
20
17
|
- - ">="
|
21
18
|
- !ruby/object:Gem::Version
|
22
|
-
version: 6.0
|
19
|
+
version: 6.1.0
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
|
-
- - "~>"
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: 6.0.3
|
30
24
|
- - ">="
|
31
25
|
- !ruby/object:Gem::Version
|
32
|
-
version: 6.0
|
26
|
+
version: 6.1.0
|
33
27
|
- !ruby/object:Gem::Dependency
|
34
28
|
name: sqlite3
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,10 +52,39 @@ dependencies:
|
|
58
52
|
- - ">="
|
59
53
|
- !ruby/object:Gem::Version
|
60
54
|
version: '0'
|
61
|
-
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: generator_spec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: byebug
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description:
|
62
84
|
email:
|
63
85
|
- matt@futureworkshops.com
|
64
|
-
executables:
|
86
|
+
executables:
|
87
|
+
- mwf
|
65
88
|
extensions: []
|
66
89
|
extra_rdoc_files: []
|
67
90
|
files:
|
@@ -70,29 +93,47 @@ files:
|
|
70
93
|
- Rakefile
|
71
94
|
- app/assets/config/mobile_workflow_manifest.js
|
72
95
|
- app/assets/stylesheets/mobile_workflow/application.css
|
96
|
+
- app/controllers/concerns/mobile_workflow/param_parser.rb
|
73
97
|
- app/controllers/concerns/mobile_workflow/s3_storable.rb
|
74
98
|
- app/controllers/mobile_workflow/sns_notifications_controller.rb
|
75
99
|
- app/helpers/mobile_workflow/application_helper.rb
|
76
100
|
- app/jobs/mobile_workflow/application_job.rb
|
77
101
|
- app/mailers/mobile_workflow/application_mailer.rb
|
78
|
-
- app/models/mobile_workflow/
|
102
|
+
- app/models/concerns/mobile_workflow/displayable.rb
|
79
103
|
- app/views/layouts/mobile_workflow/application.html.erb
|
104
|
+
- bin/mwf
|
80
105
|
- config/routes.rb
|
106
|
+
- db/migrate/20200823174210_create_users.rb
|
81
107
|
- lib/generators/mobile_workflow/controller_generator.rb
|
82
108
|
- lib/generators/mobile_workflow/install/install_generator.rb
|
109
|
+
- lib/generators/mobile_workflow/install/templates/Gemfile.erb
|
110
|
+
- lib/generators/mobile_workflow/install/templates/Procfile
|
111
|
+
- lib/generators/mobile_workflow/install/templates/Procfile.dev
|
112
|
+
- lib/generators/mobile_workflow/install/templates/README.md.erb
|
113
|
+
- lib/generators/mobile_workflow/install/templates/ability.rb
|
83
114
|
- lib/generators/mobile_workflow/install/templates/api_controller.rb.erb
|
115
|
+
- lib/generators/mobile_workflow/install/templates/seeds.rb.erb
|
116
|
+
- lib/generators/mobile_workflow/install/templates/sessions_controller.rb.erb
|
117
|
+
- lib/generators/mobile_workflow/install/templates/storage.s3.yml
|
118
|
+
- lib/generators/mobile_workflow/install/templates/user.rb.erb
|
84
119
|
- lib/generators/mobile_workflow/templates/controller.rb.erb
|
85
120
|
- lib/generators/mobile_workflow/templates/controller_spec.rb.erb
|
86
121
|
- lib/mobile_workflow.rb
|
122
|
+
- lib/mobile_workflow/cli.rb
|
123
|
+
- lib/mobile_workflow/cli/app_builder.rb
|
124
|
+
- lib/mobile_workflow/cli/app_server_cleaner.rb
|
125
|
+
- lib/mobile_workflow/cli/app_server_generator.rb
|
126
|
+
- lib/mobile_workflow/cli/aws_backend.rb
|
127
|
+
- lib/mobile_workflow/cli/dokku_backend.rb
|
128
|
+
- lib/mobile_workflow/cli/heroku_backend.rb
|
87
129
|
- lib/mobile_workflow/engine.rb
|
88
130
|
- lib/mobile_workflow/version.rb
|
89
|
-
- lib/tasks/mobile_workflow_tasks.rake
|
90
131
|
- lib/templates/active_record/model/model.rb.erb
|
91
132
|
homepage: https://github.com/futureworkshops/mobile_workflow
|
92
133
|
licenses:
|
93
134
|
- MIT
|
94
135
|
metadata: {}
|
95
|
-
post_install_message:
|
136
|
+
post_install_message:
|
96
137
|
rdoc_options: []
|
97
138
|
require_paths:
|
98
139
|
- lib
|
@@ -100,7 +141,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
100
141
|
requirements:
|
101
142
|
- - ">="
|
102
143
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
144
|
+
version: 2.5.5
|
104
145
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
146
|
requirements:
|
106
147
|
- - ">="
|
@@ -108,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
108
149
|
version: '0'
|
109
150
|
requirements: []
|
110
151
|
rubygems_version: 3.0.8
|
111
|
-
signing_key:
|
152
|
+
signing_key:
|
112
153
|
specification_version: 4
|
113
154
|
summary: A Rails engine to provide API support for Mobile Workflow Apps.
|
114
155
|
test_files: []
|