mobile_workflow 0.1.0 → 0.2.0
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 +86 -0
- data/config/routes.rb +1 -0
- data/db/migrate/20200823174210_create_users.rb +11 -0
- data/lib/generators/mobile_workflow/controller_generator.rb +5 -1
- data/lib/generators/mobile_workflow/install/install_generator.rb +41 -7
- data/lib/generators/mobile_workflow/install/templates/api_controller.rb.erb +14 -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/user.rb.erb +4 -0
- data/lib/generators/mobile_workflow/templates/controller.rb.erb +1 -0
- data/lib/mobile_workflow/version.rb +1 -1
- data/lib/templates/active_record/model/model.rb.erb +3 -35
- metadata +40 -7
- data/app/models/mobile_workflow/application_record.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 256261333d1969340beeb74ed09a0578f550e44f8be36e0dc78353c8dc9ba9d6
|
4
|
+
data.tar.gz: 895641f2f4ccffd872e944e516a97917c412390c5eb505192284ba1dc0b56eca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3b4dd40132e7ac6dd1e3314bc958cd9b1e2ee8b0aa0e9adcbb7e35e57ec933b57f18cb79927acebc8ae2d155895a958885c897c05d54b8b9460b22fc25bc85a
|
7
|
+
data.tar.gz: 37f3c7fce459451c57b9fc8eb2b1f1331c0ab840372ce651fe768abfbf4a2dc3f1f0de389f73add39b13b9d0d3e591edec008dcc39a7dc64326580ecd821ee7b
|
@@ -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,86 @@
|
|
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: 300, width: 600), url: attachment_url(attachment)}
|
21
|
+
end
|
22
|
+
|
23
|
+
def mw_display_video(attachment)
|
24
|
+
{type: :video, previewURL: preview_url(attachment, height: 300, width: 600), url: attachment_url(attachment)}
|
25
|
+
end
|
26
|
+
|
27
|
+
def mw_display_button(label:, style: :primary, on_success: :forward)
|
28
|
+
validate_on_success!(on_success)
|
29
|
+
validate_button_style!(style)
|
30
|
+
|
31
|
+
{type: :button, label: label, style: style, onSuccess: on_success}
|
32
|
+
end
|
33
|
+
|
34
|
+
def mw_display_delete_button(url:, label: "Delete", method: :delete, style: :danger, on_success: :backward)
|
35
|
+
validate_on_success!(on_success)
|
36
|
+
validate_button_style!(style)
|
37
|
+
|
38
|
+
{type: :button, label: label, url: url, method: method, style: style, onSuccess: on_success}
|
39
|
+
end
|
40
|
+
|
41
|
+
def mw_display_button_for_url(label:, url:, method: :put, style: :primary, on_success: :reload)
|
42
|
+
validate_on_success!(on_success)
|
43
|
+
validate_button_style!(style)
|
44
|
+
|
45
|
+
{type: :button, label: label, url: url, method: method, style: style, onSuccess: on_success}
|
46
|
+
end
|
47
|
+
|
48
|
+
def mw_display_button_for_modal_workflow(label:, modal_workflow:, style: :primary, on_success: :none)
|
49
|
+
validate_on_success!(on_success)
|
50
|
+
validate_button_style!(style)
|
51
|
+
|
52
|
+
{type: :button, label: label, modalWorkflow: modal_workflow, style: style, onSuccess: on_success}
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
def validate_on_success!(on_success)
|
57
|
+
raise 'Unknown on_success action' unless ON_SUCCESS_OPTIONS.include?(on_success)
|
58
|
+
end
|
59
|
+
|
60
|
+
def validate_button_style!(style)
|
61
|
+
raise 'Unknown style' unless BUTTON_STYLES.include?(style)
|
62
|
+
end
|
63
|
+
|
64
|
+
def preview_url(attachment, height:, width:, options: { resize_to_fill: [height, width]} )
|
65
|
+
return nil unless attachment.attached?
|
66
|
+
|
67
|
+
if attachment.image?
|
68
|
+
Rails.application.routes.url_helpers.rails_representation_url(attachment.variant(combine_options: options), host: attachment_host)
|
69
|
+
elsif attachment.previewable?
|
70
|
+
Rails.application.routes.url_helpers.rails_representation_url(attachment.preview(options), host: attachment_host)
|
71
|
+
else
|
72
|
+
return nil
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def attachment_url(attachment)
|
77
|
+
return nil unless attachment.attached?
|
78
|
+
|
79
|
+
Rails.application.routes.url_helpers.rails_blob_url(attachment, host: attachment_host)
|
80
|
+
end
|
81
|
+
|
82
|
+
def attachment_host
|
83
|
+
"https://#{ENV['HEROKU_APP_NAME']}.herokuapp.com"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/config/routes.rb
CHANGED
@@ -25,7 +25,11 @@ module MobileWorkflow
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def rewrite_params
|
28
|
-
attributes_names
|
28
|
+
if attributes_names
|
29
|
+
init_params = "\n\t\tparams[:#{singular_table_name}] = {}\n"
|
30
|
+
rewrite_params = attributes_names.map {|name| "params[:#{singular_table_name}][:#{name}] = params.dig(:payload, :#{name}, :answer)" }.join("\n\t\t")
|
31
|
+
init_params + rewrite_params
|
32
|
+
end
|
29
33
|
end
|
30
34
|
end
|
31
35
|
end
|
@@ -3,22 +3,41 @@ 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 = ["answer", "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
|
9
14
|
|
10
15
|
def create_api_controller
|
11
|
-
template(
|
12
|
-
|
13
|
-
|
14
|
-
|
16
|
+
template("api_controller.rb.erb", "app/controllers/api_controller.rb")
|
17
|
+
end
|
18
|
+
|
19
|
+
def mount_engine
|
20
|
+
route "mount MobileWorkflow::Engine => '/'"
|
21
|
+
end
|
22
|
+
|
23
|
+
def generate_doorkeeper
|
24
|
+
return unless options[:doorkeeper_oauth]
|
25
|
+
say "Generating Doorkeeper OAuth"
|
26
|
+
|
27
|
+
generate 'doorkeeper:install'
|
28
|
+
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))'
|
29
|
+
generate 'doorkeeper:migration'
|
30
|
+
generate 'doorkeeper:pkce'
|
31
|
+
template("user.rb.erb", "app/models/user.rb")
|
32
|
+
template("sessions_controller.rb.erb", "app/controllers/sessions_controller.rb")
|
33
|
+
route "resources :sessions, only: [:new, :create]"
|
15
34
|
end
|
16
35
|
|
17
36
|
def generate_models
|
18
37
|
say "Generating models"
|
19
38
|
@model_properties = {}
|
20
39
|
open_api_spec[:components][:schemas].each_pair do |model_name, schema|
|
21
|
-
next if
|
40
|
+
next if SKIP_SCHEMAS.include? model_name # Don't generate schemas for MW schemas
|
22
41
|
|
23
42
|
model_name = model_name.underscore
|
24
43
|
model_properties = model_properties(model_name, schema)
|
@@ -40,6 +59,10 @@ module MobileWorkflow
|
|
40
59
|
route "resources :#{plural_controller_name}, only: [:index, :show, :create]"
|
41
60
|
end
|
42
61
|
end
|
62
|
+
|
63
|
+
def generate_seeds
|
64
|
+
template("seeds.rb.erb", "db/seeds.rb")
|
65
|
+
end
|
43
66
|
|
44
67
|
private
|
45
68
|
def open_api_spec
|
@@ -48,7 +71,7 @@ module MobileWorkflow
|
|
48
71
|
|
49
72
|
def read_openapi_spec
|
50
73
|
say "Loading OpenAPI Spec: #{open_api_spec_path}"
|
51
|
-
return JSON.parse(File.read(open_api_spec_path)).with_indifferent_access
|
74
|
+
return JSON.parse(File.read(File.join(Rails.root, open_api_spec_path))).with_indifferent_access
|
52
75
|
end
|
53
76
|
|
54
77
|
def open_api_spec_path
|
@@ -56,13 +79,24 @@ module MobileWorkflow
|
|
56
79
|
end
|
57
80
|
|
58
81
|
def model_properties(name, schema)
|
59
|
-
generated_properties_args = schema["properties"].keys.collect{|key| "#{key}
|
82
|
+
generated_properties_args = schema["properties"].keys.collect{|key| "#{key}:#{model_property_type(schema["properties"][key])}" }.join(" ")
|
60
83
|
if yes?("Use generated schema #{name}(#{generated_properties_args})[yn]?")
|
61
84
|
generated_properties_args
|
62
85
|
else
|
63
86
|
ask "Specify schema for #{name}: (e.g. text:string image:attachment region:reference)"
|
64
87
|
end
|
65
88
|
end
|
89
|
+
|
90
|
+
def model_property_type(property)
|
91
|
+
case property['$ref']
|
92
|
+
when "#/components/schemas/answer"
|
93
|
+
'string'
|
94
|
+
when "#/components/schemas/attachment"
|
95
|
+
'attachment'
|
96
|
+
else
|
97
|
+
'string'
|
98
|
+
end
|
99
|
+
end
|
66
100
|
end
|
67
101
|
end
|
68
102
|
end
|
@@ -1,5 +1,19 @@
|
|
1
1
|
class ApiController < ActionController::API
|
2
|
+
<% if options[:doorkeeper_oauth] %>
|
3
|
+
before_action :doorkeeper_authorize!, unless: :anonymous_action?
|
4
|
+
|
5
|
+
def current_resource_owner
|
6
|
+
User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
|
7
|
+
end
|
8
|
+
alias_method :current_user, :current_resource_owner
|
9
|
+
|
10
|
+
protected
|
11
|
+
def anonymous_action?
|
12
|
+
false
|
13
|
+
end
|
14
|
+
<% else %>
|
2
15
|
def current_user
|
3
16
|
nil
|
4
17
|
end
|
18
|
+
<% end %>
|
5
19
|
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
|
@@ -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,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mobile_workflow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
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-11-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -58,7 +58,35 @@ dependencies:
|
|
58
58
|
- - ">="
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '0'
|
61
|
-
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: generator_spec
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: byebug
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
description:
|
62
90
|
email:
|
63
91
|
- matt@futureworkshops.com
|
64
92
|
executables: []
|
@@ -70,17 +98,22 @@ files:
|
|
70
98
|
- Rakefile
|
71
99
|
- app/assets/config/mobile_workflow_manifest.js
|
72
100
|
- app/assets/stylesheets/mobile_workflow/application.css
|
101
|
+
- app/controllers/concerns/mobile_workflow/param_parser.rb
|
73
102
|
- app/controllers/concerns/mobile_workflow/s3_storable.rb
|
74
103
|
- app/controllers/mobile_workflow/sns_notifications_controller.rb
|
75
104
|
- app/helpers/mobile_workflow/application_helper.rb
|
76
105
|
- app/jobs/mobile_workflow/application_job.rb
|
77
106
|
- app/mailers/mobile_workflow/application_mailer.rb
|
78
|
-
- app/models/mobile_workflow/
|
107
|
+
- app/models/concerns/mobile_workflow/displayable.rb
|
79
108
|
- app/views/layouts/mobile_workflow/application.html.erb
|
80
109
|
- config/routes.rb
|
110
|
+
- db/migrate/20200823174210_create_users.rb
|
81
111
|
- lib/generators/mobile_workflow/controller_generator.rb
|
82
112
|
- lib/generators/mobile_workflow/install/install_generator.rb
|
83
113
|
- lib/generators/mobile_workflow/install/templates/api_controller.rb.erb
|
114
|
+
- lib/generators/mobile_workflow/install/templates/seeds.rb.erb
|
115
|
+
- lib/generators/mobile_workflow/install/templates/sessions_controller.rb.erb
|
116
|
+
- lib/generators/mobile_workflow/install/templates/user.rb.erb
|
84
117
|
- lib/generators/mobile_workflow/templates/controller.rb.erb
|
85
118
|
- lib/generators/mobile_workflow/templates/controller_spec.rb.erb
|
86
119
|
- lib/mobile_workflow.rb
|
@@ -92,7 +125,7 @@ homepage: https://github.com/futureworkshops/mobile_workflow
|
|
92
125
|
licenses:
|
93
126
|
- MIT
|
94
127
|
metadata: {}
|
95
|
-
post_install_message:
|
128
|
+
post_install_message:
|
96
129
|
rdoc_options: []
|
97
130
|
require_paths:
|
98
131
|
- lib
|
@@ -108,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
108
141
|
version: '0'
|
109
142
|
requirements: []
|
110
143
|
rubygems_version: 3.0.8
|
111
|
-
signing_key:
|
144
|
+
signing_key:
|
112
145
|
specification_version: 4
|
113
146
|
summary: A Rails engine to provide API support for Mobile Workflow Apps.
|
114
147
|
test_files: []
|