aasm_progressable 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b02c82b67010f9ab734beab0cec83dc3e2aaf0fc
4
+ data.tar.gz: 3b159e1d8fc17986bf5593759dec67a072965a02
5
+ SHA512:
6
+ metadata.gz: 0319067fe12b531167669eaa3ca4f6850e55b5f2bfb40f23debd0c9481e7d518dab2ab0babbbac44ed5760b93cf35f196a39d2c2c2a65622993082c684f2a9df
7
+ data.tar.gz: e47d7ae2467fea32e275f73881433f64a03742deb5b07023d9e8e6879009564873ef836dc4150552d9c63c9fb7f8a4b5488e7d0d7be7f7f0ed3c3a3f8d3c06ce
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ aasm_progressable
2
+ =================
3
+
4
+ Rails helper to render the progress indicators for simple linear [AASM](https://github.com/aasm/aasm) workflows. It allows users to see steps in a workflow they have completed, which step is in progress, and which steps have not been completed. See the following image for an example.
5
+
6
+ ![Example Screenshot](https://raw.github.com/WorkflowsOnRails/aasm_progressable/master/docs/sample-screenshot.png)
7
+
8
+
9
+ Using aasm_progressable
10
+ -----------------------
11
+
12
+ Add `aasm_progressable` to your Gemfile, and run bundler to install it. For each model with an appropriate workflow, include `AasmProgressable::ModelMixin`, and add a call to `aasm_state_order` with an array of symbols corresponding to
13
+ the expected order in which the states will be traversed. For example, if we have an `Order` class that starts from the `new` state, proceeds to `processing`, and then `shipping`, we might have
14
+
15
+ ```rb
16
+ class Order < ActiveRecord::Base
17
+ include AASM
18
+ aasm do
19
+ state :new, initial: true
20
+ state :processing
21
+ state :shipping
22
+
23
+ event :confirm do
24
+ transitions from: :new, to: :processing
25
+ end
26
+ event :dispatch do
27
+ transitions from: :processing, to: :shipping
28
+ end
29
+ end
30
+
31
+ aasm_state_order [:new, :processing, :shipping]
32
+ end
33
+ ```
34
+
35
+ In order to render the progress indicator, we need to add `helper AasmProgressable::Helper` to your ApplicationController. Then, in any detailed views for the order (such as orders#show), we can add `<%= render_state_indicator the_model_instance %>` to render an indicator for the state of the specified instance of the model. By default, this will render an ordered list (`ol`) with one element per state, with the elements corresponding to complete, current, and incomplete states being classed with `complete`, `active`, and `incomplete` respectively. You can add a ` *= require aasm_progressable` line to your application stylesheet to include some default styling for the indicator.
36
+
37
+
38
+ Customizing and Localizing aasm_progressable
39
+ --------------------------------------------
40
+
41
+ aasm_progressable uses `AASM::Localizer#human_state_name` to convert AASM states to output text. By default, this method will replace underscores with spaces, and capitalize the first letter of the state name. However, it can also fetch state names from a locale key of the form `activerecord.attributes.<model-table-name>.<aasm-column-name>/<state-symbol>`. By default, `<aasm-column-name>` will be "aasm_state".
42
+
43
+ As an example, if we wanted to display "Unconfirmed" as English name for the `:new` order state in the previous example, we could add the following to config/locales/en.yml:
44
+
45
+ ```yaml
46
+ en:
47
+ activerecord:
48
+ attributes:
49
+ order:
50
+ aasm_state/new: "Unconfirmed"
51
+ ```
52
+
53
+
54
+ Limitations
55
+ ------------
56
+
57
+ Models that use aasm_progressable should have a strictly linear workflow, ie. there should be no branches in the state machine. Loops and skipped states are permitted, but there may not be alternative states. If a model instance is in a state that does not appear in the model's `aasm_state_order` declaration, then the helper will not be able to infer the state transition history of the instance and all states will be rendered as if they were completed.
@@ -0,0 +1,32 @@
1
+ .state-indicator {
2
+ display: table;
3
+ table-layout: fixed;
4
+ width: 100%;
5
+ border-collapse: separate;
6
+ font-size: 16px;
7
+
8
+ ol {
9
+ display: table-row;
10
+ }
11
+ li {
12
+ display: table-cell;
13
+ padding: 6px 16px;
14
+ border-right: 4px solid #fff;
15
+
16
+ &:last-child {
17
+ border-right: none;
18
+ }
19
+ }
20
+ .complete {
21
+ background: #6aa3d5;
22
+ color: #fff;
23
+ }
24
+ .active {
25
+ background: #357ebd;
26
+ color: #fff;
27
+ }
28
+ .incomplete {
29
+ background: #eae8ec;
30
+ color: #999;
31
+ }
32
+ }
@@ -0,0 +1,62 @@
1
+ # The ActionView helper. This should be made accessible to appropriate
2
+ # controllers by adding a `helper AasmProgressable::Helper` declaration
3
+ # to them.
4
+ #
5
+ # @author Brendan MacDonell
6
+ module AasmProgressable
7
+ # Internal class to manage display attribute associated with each
8
+ # model state, such as the name to display, and if the state has
9
+ # been completed yet or not.
10
+ class State
11
+ attr_reader :id # the internal ID for the state (as a string)
12
+ attr_reader :name # name displayed to the user
13
+
14
+ def initialize(id, name, status_classes)
15
+ @id = id.to_s
16
+ @name = name
17
+ @status_classes = status_classes
18
+ end
19
+
20
+ # html_class may contain complete, previous, active, next, or incomplete.
21
+ def html_class
22
+ @status_classes.join(' ')
23
+ end
24
+
25
+ def is?(status_class)
26
+ @status_classes.include? status_class
27
+ end
28
+
29
+ # Returns an Array of State instances corresponding to the states
30
+ # of a model instance. The State instances are returned in the order
31
+ # given by the `aasm_state_order` declaration in the model.
32
+ def self.create_all(object)
33
+ localizer = AASM::Localizer.new
34
+ state_order = object.aasm_state_order
35
+ current_state = object.aasm.current_state
36
+
37
+ current_state_index = state_order.index(current_state)
38
+
39
+ object.aasm_state_order.each_with_index.map do |state, index|
40
+ status_classes = []
41
+ status_classes << :complete if index < current_state_index
42
+ status_classes << :previous if index == current_state_index - 1
43
+ status_classes << :active if index == current_state_index
44
+ status_classes << :next if index == current_state_index + 1
45
+ status_classes << :incomplete if index > current_state_index
46
+
47
+ name = localizer.human_state_name(object.class, state)
48
+ State.new(state, name, status_classes)
49
+ end
50
+ end
51
+ end
52
+
53
+ module Helper
54
+ # Renders a state indicator for a specified model instance.
55
+ def render_state_indicator(object, locals: {})
56
+ states = State.create_all(object)
57
+ locals = {states: states}.merge(locals)
58
+ rendered = render partial: 'aasm_progressable/states/list', locals: locals
59
+ rendered.html_safe
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,9 @@
1
+ <div class="state-indicator">
2
+ <ol>
3
+ <% states.each_with_index do |state, index| %>
4
+ <li class="<%= state.html_class %>">
5
+ <%= index + 1 %>. <%= state.name %>
6
+ </li>
7
+ <% end %>
8
+ </ol>
9
+ </div>
@@ -0,0 +1,5 @@
1
+ require "aasm_progressable/engine"
2
+ require "aasm_progressable/model_mixin"
3
+
4
+ module AasmProgressable
5
+ end
@@ -0,0 +1,5 @@
1
+ module AasmProgressable
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace AasmProgressable
4
+ end
5
+ end
@@ -0,0 +1,53 @@
1
+ # Mixin for models with linear AASM-defined workflows.
2
+ #
3
+ # This mixin provides the aasm_state_order class settor, as well as
4
+ # a similarly-named instance gettor.
5
+ #
6
+ # @author Brendan MacDonell
7
+ module AasmProgressable
8
+ module ModelMixin
9
+ extend ActiveSupport::Concern
10
+
11
+ # Instance gettor to return the state order for the model
12
+ def aasm_state_order
13
+ self.class.get_aasm_state_order
14
+ end
15
+
16
+ def have_completed?(state)
17
+ current_index, target_index = state_index(self.aasm.current_state, state)
18
+ current_index > target_index
19
+ end
20
+
21
+ def have_not_completed?(state)
22
+ not have_completed?(state)
23
+ end
24
+
25
+ def have_started?(state)
26
+ current_index, target_index = state_index(self.aasm.current_state, state)
27
+ current_index >= target_index
28
+ end
29
+
30
+ def have_not_started?(state)
31
+ not have_started?(state)
32
+ end
33
+
34
+ # Class gettors and settors for the state order
35
+ module ClassMethods
36
+ def aasm_state_order order
37
+ @state_order = order
38
+ end
39
+
40
+ def get_aasm_state_order
41
+ @state_order
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ # Returns an array of zero-index state indices, where each index indicates
48
+ # the state's position in the ordered state collection.
49
+ def state_index(*states)
50
+ states.map { |state| self.aasm_state_order.index(state) }
51
+ end
52
+ end
53
+ end
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aasm_progressable
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Brendan MacDonell
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-12-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: aasm
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sass-rails
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '4.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '4.0'
55
+ description: Progress indicators for linear AASM workflows
56
+ email: brendan@macdonell.net
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - README.md
62
+ - app/assets/stylesheets/aasm_progressable.css.scss
63
+ - app/helpers/aasm_progressable/helper.rb
64
+ - app/views/aasm_progressable/states/_list.html.erb
65
+ - lib/aasm_progressable.rb
66
+ - lib/aasm_progressable/engine.rb
67
+ - lib/aasm_progressable/model_mixin.rb
68
+ homepage: http://rubygems.org/gems/aasm_progressable
69
+ licenses:
70
+ - MIT
71
+ metadata: {}
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 2.2.2
89
+ signing_key:
90
+ specification_version: 4
91
+ summary: AASM Progressable
92
+ test_files: []
93
+ has_rdoc: