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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '068f070743f72d5743182cd41021c33b89579ecef7182a5747c799393a1d4208'
4
- data.tar.gz: 41aef887eb318cf98736112ce4aad51835af98f1d20e0d75f7810c9014f4c5e4
3
+ metadata.gz: 256261333d1969340beeb74ed09a0578f550e44f8be36e0dc78353c8dc9ba9d6
4
+ data.tar.gz: 895641f2f4ccffd872e944e516a97917c412390c5eb505192284ba1dc0b56eca
5
5
  SHA512:
6
- metadata.gz: 90ad8d639c45ff2c757a933199022a1fad59d649c815211425366c45d72a9596e516fe382835b7ffca76f1dc7bdbc85b14d35b65b723dcd751750ff10195803d
7
- data.tar.gz: 8adcf9c22591e5644b484c0216a9f8d157222078f8ed37cebcdc9333560c30294f018e06cdfc26c8d3a27bfe9f7016346658ff4fe83a215d162f2a0946dbcaa6
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
- property = binary["identifier"].split('/')[0] # i.e. image/jpg --> image, video/mp4 --> video
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}/#{property}"),
14
+ "url" => presigned_url("#{object.class.name.underscore}/#{object.id}/#{binary["identifier"]}.#{extension}"),
15
15
  "method" => "PUT"
16
16
  }
17
17
  end
@@ -46,6 +46,10 @@ module MobileWorkflow
46
46
  end
47
47
 
48
48
  def attribute_name
49
+ file_name.split(".")[0] # remove the extension
50
+ end
51
+
52
+ def file_name
49
53
  key_identifiers[2]
50
54
  end
51
55
 
@@ -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
@@ -1,2 +1,3 @@
1
1
  MobileWorkflow::Engine.routes.draw do
2
+ resources :sns_notifications, only: :create
2
3
  end
@@ -0,0 +1,11 @@
1
+ class CreateUsers < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :users do |t|
4
+ t.string :email
5
+ t.string :password_digest
6
+
7
+ t.timestamps
8
+ end
9
+ add_index :users, :email
10
+ end
11
+ end
@@ -25,7 +25,11 @@ module MobileWorkflow
25
25
  end
26
26
 
27
27
  def rewrite_params
28
- attributes_names.map {|name| "params[:#{singular_table_name}][:#{name}] = params[:payload][:#{name}][:answer]" }.join("\n\t\t")
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
- "api_controller.rb.erb",
13
- "app/controllers/api_controller.rb",
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 ["answer", "attachment"].include? model_name # Don't generate schemas for MW schemas
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}:string" }.join(" ")
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,3 @@
1
+ <%- if options[:doorkeeper_oauth] %>
2
+ Doorkeeper::Application.create! name: 'Main App', redirect_uri: 'mww://callback', scopes: 'public'
3
+ <%- 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,4 @@
1
+ class User < ApplicationRecord
2
+ has_secure_password
3
+ validates :email, presence: true
4
+ end
@@ -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
@@ -1,3 +1,3 @@
1
1
  module MobileWorkflow
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -1,7 +1,6 @@
1
1
  <% module_namespacing do -%>
2
2
  class <%= class_name %> < <%= parent_class_name.classify %>
3
- # Enable if you need to generate attachment URLs
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.1.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-06-30 00:00:00.000000000 Z
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
- description:
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/application_record.rb
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: []
@@ -1,5 +0,0 @@
1
- module MobileWorkflow
2
- class ApplicationRecord < ActiveRecord::Base
3
- self.abstract_class = true
4
- end
5
- end