decidim-friendly_signup 0.1 → 0.2

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: 8f2ae2b38da8d5bfc15a20685f71f03c57874127d6017924d475a142f60d02cf
4
- data.tar.gz: 929035be31dd91ac0e725b849f83385164966b2be0f47ed103a8d3b5c3cbc149
3
+ metadata.gz: c631ec440674f278ea3a0f3369435831014443e36f2f4247d1a87d914e7e66c8
4
+ data.tar.gz: cf5ca968cfe4459a63471e02ff36dd38f28cfb042c3146e175c3766dab4a6571
5
5
  SHA512:
6
- metadata.gz: ed74b6aaba9d5bf1bd4187f9199e1caba5c7ee2684be73eb271274734bced92119ead384a77a9434d6de9b65126e84b6799789e8d9286b0e25b4f573721ff4b3
7
- data.tar.gz: 28a1e3a53faf886766638d2765533fd3d395401c291f60d7b25066386682be00fcd581585e925c007dd0ad404d0db94794b73c188d24fe00e79e3934767c28d7
6
+ metadata.gz: cdd1a58fad3b2b40cb5f73497c3ca408a621afce743073b40c9fee720a4e9050e0d5a8f3b495e5024b6e807ce7fe8c61859e264259fd3ccec30424d025114bb3
7
+ data.tar.gz: b0437d886f9018aaed1a3f405f52032d77c8c01ec7f1f40bb8a61b708138f1eeedbacb424ab394d26048c7bb643d14b3579ddce4954cd5c2af521fea6ffc8f38
data/README.md CHANGED
@@ -1,21 +1,25 @@
1
1
  # Decidim::FriendlySignup
2
2
 
3
+ [![[CI] Lint](https://github.com/OpenSourcePolitics/decidim-module-friendly_signup/actions/workflows/lint.yml/badge.svg)](https://github.com/OpenSourcePolitics/decidim-module-friendly_signup/actions/workflows/lint.yml)
3
4
  [![[CI] Test](https://github.com/OpenSourcePolitics/decidim-module-friendly_signup/actions/workflows/test.yml/badge.svg)](https://github.com/OpenSourcePolitics/decidim-module-friendly_signup/actions/workflows/test.yml)
4
5
  [![Maintainability](https://api.codeclimate.com/v1/badges/46c261f70f7f49a8f385/maintainability)](https://codeclimate.com/github/OpenSourcePolitics/decidim-module-friendly_signup/maintainability)
5
6
  [![Test Coverage](https://codecov.io/gh/OpenSourcePolitics/decidim-module-friendly_signup/branch/main/graph/badge.svg?token=1lrOiLdy9P)](https://codecov.io/gh/OpenSourcePolitics/decidim-module-friendly_signup)
7
+ [![Gem Version](https://badge.fury.io/rb/decidim-friendly_signup.svg)](https://badge.fury.io/rb/decidim-friendly_signup)
8
+
6
9
  ---
7
- A more user friendly approach for the user registration process.
10
+
11
+ A more user friendly approach for the user registration process in [Decidim](https://github.com/decidim/decidim).
8
12
 
9
13
  ## Usage
10
14
 
11
15
  This module simply substitutes some pages to ease up the registration process in Decidim.
12
16
 
13
- Features:
17
+ ### Features:
14
18
 
15
19
  - [x] Simplify the password field and add a button with a "show password". ![Show/hide password](examples/passwords.png)
16
20
 
17
21
  - [ ] Remove the nickname field from the registration process and automatically create one on registering
18
- - [ ] Instant validate parameters when registering without having to send it for backend validation
22
+ - [x] Instant validate parameters when registering without having to send it for backend validation. ![Instant validation](examples/instant_validation.png)
19
23
  - [ ] Use checkout codes to validate the email instead of a link
20
24
 
21
25
  ## Installation
@@ -38,9 +42,21 @@ And then execute:
38
42
  bundle
39
43
  ```
40
44
 
45
+ **Note:**
46
+
47
+ The correct version of FriendlySignup should resolved automatically by the Bundler.
48
+ However you can force some specific version using `gem "decidim-friendly_signup", "~> 0.1.0"` in the Gemfile.
49
+
50
+ Depending on your Decidim version, choose the corresponding FriendlySignup version to ensure compatibility:
51
+
52
+ | FriendlySignup version | Compatible Decidim versions |
53
+ |---|---|
54
+ | 0.2.x | 0.26.x |
55
+ | 0.1.x | 0.26.x |
56
+
41
57
  ## Configuration
42
58
 
43
- Customize your integration by creating an initializer (ie: `config/initializes/friendly_signup.rb`) and set some of the variables:
59
+ Customize your integration by creating an initializer (ie: `config/initializes/friendly_signup.rb`) and set some of the variables (you don't need to do this if you want all features enabled):
44
60
 
45
61
  ```ruby
46
62
  # config/initializers/friendly_signup.rb
@@ -48,14 +64,23 @@ Customize your integration by creating an initializer (ie: `config/initializes/f
48
64
  Decidim::FriendlySignup.configure do |config|
49
65
  # Override password views or leave the originals (default is true):
50
66
  config.override_passwords = false
51
- end
52
67
 
68
+ # Automatically validate user inputs in the register form (default is true):
69
+ config.use_instant_validation = false
70
+ end
53
71
  ```
54
72
 
55
73
  ## Contributing
56
74
 
57
75
  Bug reports and pull requests are welcome on GitHub at https://github.com/OpenSourcePolitics/decidim-module-friendly_signup.
58
76
 
77
+ ### Localization
78
+
79
+ If you would like to see this module in your own language, you can help with its
80
+ translation at Crowdin:
81
+
82
+ https://crowdin.com/project/decidim-friendly-signup
83
+
59
84
  ### Developing
60
85
 
61
86
  To start contributing to this project, first:
@@ -133,23 +158,13 @@ commands shown above.
133
158
 
134
159
  ### Test code coverage
135
160
 
136
- If you want to generate the code coverage report for the tests, you can use
137
- the `SIMPLECOV=1` environment variable in the rspec command as follows:
161
+ Test coverage should be generated automatically in the folder "coverage" once any test is run:
138
162
 
139
163
  ```bash
140
- $ SIMPLECOV=1 bundle exec rspec
164
+ $ bundle exec rspec
165
+ $ firefox coverage/index.html
141
166
  ```
142
167
 
143
- This will generate a folder named `coverage` in the project root which contains
144
- the code coverage report.
145
-
146
- ### Localization
147
-
148
- If you would like to see this module in your own language, you can help with its
149
- translation at Crowdin:
150
-
151
- https://crowdin.com/project/decidim-friendly-signup
152
-
153
168
  ## License
154
169
 
155
170
  See [LICENSE-AGPLv3.txt](LICENSE-AGPLv3.txt).
@@ -23,11 +23,8 @@ module Decidim
23
23
  @snippets
24
24
  end
25
25
 
26
- def friendly_override_activated?(type)
27
- case type
28
- when :override_passwords
29
- Decidim::FriendlySignup.override_passwords.present?
30
- end
26
+ def friendly_override_activated?(feat)
27
+ Decidim::FriendlySignup.send(feat.to_s).present?
31
28
  end
32
29
  end
33
30
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module FriendlySignup
5
+ class ApplicationController < Decidim::ApplicationController
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module FriendlySignup
5
+ class ValidatorController < ApplicationController
6
+ include Decidim::FormFactory
7
+
8
+ def validate
9
+ @form = form(Decidim::RegistrationForm).from_params(params)
10
+ validator = UserAttributeValidator.new(form: @form, attribute: params[:attribute])
11
+ render json: {
12
+ valid: validator.valid?,
13
+ error: validator.error
14
+ }
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,4 +1,5 @@
1
- import "src/decidim/friendly_signup/password_helper"
1
+ import "src/decidim/friendly_signup/setup_password"
2
+ import "src/decidim/friendly_signup/setup_validations"
2
3
 
3
4
  // CSS
4
5
  import "entrypoints/decidim_friendly_signup.scss";
@@ -0,0 +1,95 @@
1
+ /* eslint-disable line-comment-position, no-ternary, no-inline-comments */
2
+
3
+ // Instant, server-side validation
4
+ // compatible with abide classes https://get.foundation/sites/docs/abide.html
5
+ export default class InstantValidator {
6
+ // ms before xhr check
7
+ static get TIMEOUT() {
8
+ return 150;
9
+ }
10
+
11
+ constructor($form) {
12
+ this.$form = $form;
13
+ this.$inputs = $form.find("[data-instant-attribute]");
14
+ this.url = this.$form.data("validationUrl");
15
+ }
16
+
17
+ init() {
18
+ // this final validation prevents abide from resetting the field when user loses focus
19
+ this.$inputs.on("blur", (evt) => {
20
+ this.validate($(evt.currentTarget));
21
+ });
22
+ this.$inputs.on("keyup", (evt) => {
23
+ let $input = $(evt.currentTarget);
24
+ let checkTimeout = $input.data("checkTimeout");
25
+ // Trigger live validation with a delay to avoid throttling
26
+ if (checkTimeout) {
27
+ clearTimeout(checkTimeout);
28
+ }
29
+ $input.data("checkTimeout", setTimeout(() => {
30
+ this.validate($input);
31
+ }, this.TIMEOUT)
32
+ );
33
+ });
34
+ }
35
+
36
+ value($input) {
37
+ return $input.val().trim();
38
+ }
39
+
40
+ attribute($input) {
41
+ return $input.data("instantAttribute");
42
+ }
43
+
44
+ target($input) {
45
+ const $target = this.$form.find($input.data("instantTarget"));
46
+ return $target.length
47
+ ? $target
48
+ : $input;
49
+ }
50
+
51
+ validate($input) {
52
+ this.tamper($input);
53
+ this.post($input).done((response) => {
54
+ this.setFeedback(response, $input);
55
+ });
56
+ }
57
+
58
+ setFeedback(data, $input) {
59
+ if (data.valid) {
60
+ this.clearErrors($input);
61
+ } else {
62
+ this.addErrors(this.target($input), data.error);
63
+ }
64
+ }
65
+
66
+ tamper($dest) {
67
+ $dest.data("tampered", $dest.val().trim() !== "");
68
+ }
69
+
70
+ isTampered($dest) {
71
+ return $dest.data("tampered");
72
+ }
73
+
74
+ addErrors($dest, msg) {
75
+ if ($dest.closest("label").find(".form-error").length > 1) {
76
+ // Decidim may add and additional error class that does not play well with abide
77
+ $dest.closest("label").find(".form-error:last").remove();
78
+ }
79
+ this.$form.foundation("addErrorClasses", $dest);
80
+ if (msg) {
81
+ $dest.closest("label").find(".form-error").text(msg);
82
+ }
83
+ }
84
+
85
+ clearErrors($dest) {
86
+ this.$form.foundation("removeErrorClasses", $dest);
87
+ }
88
+
89
+ post($input) {
90
+ return $.ajax(this.url, {
91
+ method: "POST",
92
+ data: `${this.$form.serialize()}&attribute=${this.attribute($input)}`
93
+ });
94
+ }
95
+ }
@@ -1,4 +1,4 @@
1
- import PasswordToggler from "src/decidim/friendly_signup/password_toggler";
1
+ import PasswordToggler from "src/decidim/friendly_signup/lib/password_toggler";
2
2
 
3
3
  $(() => {
4
4
  window.Decidim = window.Decidim || {};
@@ -0,0 +1,7 @@
1
+ import InstantValidator from "src/decidim/friendly_signup/lib/instant_validator";
2
+
3
+ $(() => {
4
+ window.Decidim = window.Decidim || {};
5
+ window.Decidim.instantValidator = new InstantValidator($("form.instant-validation"));
6
+ window.Decidim.instantValidator.init();
7
+ });
@@ -26,7 +26,7 @@
26
26
  <div class="row">
27
27
  <div class="columns large-6 medium-10 medium-centered">
28
28
 
29
- <%= decidim_form_for(@form, namespace: "registration", as: resource_name, url: registration_path(resource_name), html: { class: "register-form new_user", id: "register-form" }) do |f| %>
29
+ <%= decidim_form_for(@form, namespace: "registration", as: resource_name, url: registration_path(resource_name), html: { class: "register-form new_user#{friendly_override_activated?(:use_instant_validation) && ' instant-validation'}", id: "register-form" }, data: { "validation-url": decidim_friendly_signup.validate_path }) do |f| %>
30
30
  <%= invisible_captcha %>
31
31
  <div class="card">
32
32
  <div class="card__content">
@@ -34,21 +34,21 @@
34
34
 
35
35
  <div class="user-person">
36
36
  <div class="field">
37
- <%= f.text_field :name, help_text: t(".username_help") %>
37
+ <%= f.text_field :name, help_text: t(".username_help"), autocomplete: "off" %>
38
38
  </div>
39
39
  </div>
40
40
 
41
41
  <div class="user-nickname">
42
42
  <div class="field">
43
- <%= f.text_field :nickname, help_text: t(".nickname_help", organization: current_organization.name), prefix: { value: "@", small: 1, large: 1 } %>
43
+ <%= f.text_field :nickname, help_text: t(".nickname_help", organization: current_organization.name), prefix: { value: "@", small: 1, large: 1 }, autocomplete: "off" %>
44
44
  </div>
45
45
  </div>
46
46
 
47
47
  <div class="field">
48
- <%= f.email_field :email %>
48
+ <%= f.email_field :email, autocomplete: "email", data: { "instant-attribute": "email" } %>
49
49
  </div>
50
50
 
51
- <%= render("decidim/friendly_signup/shared/password_fields", form: f, options: { help_text: t(".password_help", minimun_characters: ::PasswordValidator::MINIMUM_LENGTH), autocomplete: "off" }) %>
51
+ <%= render("decidim/friendly_signup/shared/password_fields", form: f, options: { required: true, help_text: t(".password_help", minimun_characters: ::PasswordValidator::MINIMUM_LENGTH), autocomplete: "off", data: { "instant-attribute": "password" } }) %>
52
52
  </div>
53
53
  </div>
54
54
 
@@ -11,7 +11,7 @@
11
11
 
12
12
  <div class="user-password-confirmation">
13
13
  <div class="field">
14
- <%= form.password_field :password_confirmation, options.except(:help_text, :autocomplete) %>
14
+ <%= form.password_field :password_confirmation %>
15
15
  </div>
16
16
  </div>
17
17
  <% else %>
@@ -9,6 +9,10 @@ module Decidim
9
9
  class Engine < ::Rails::Engine
10
10
  isolate_namespace Decidim::FriendlySignup
11
11
 
12
+ routes do
13
+ post :validate, to: "validator#validate"
14
+ end
15
+
12
16
  # Prepare a zone to create overrides
13
17
  # https://edgeguides.rubyonrails.org/engines.html#overriding-models-and-controllers
14
18
  # overrides
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module FriendlySignup
5
+ class UserAttributeValidator
6
+ def initialize(attribute:, form:)
7
+ @attribute = attribute
8
+ @form = form
9
+ end
10
+
11
+ delegate :current_organization, to: :form
12
+ attr_reader :attribute, :form
13
+
14
+ def valid?
15
+ @valid ||= begin
16
+ form.validate
17
+ # we don't validate the form but the attribute alone
18
+ errors.blank?
19
+ end
20
+ end
21
+
22
+ def input
23
+ @input ||= form.public_send(attribute).to_s.dup if valid_attribute?
24
+ end
25
+
26
+ def errors
27
+ @errors ||= valid_attribute? ? form.errors[attribute] : ["Invalid attribute"]
28
+ end
29
+
30
+ def error
31
+ errors.flatten.map(&:upcase_first).join(". ") unless valid?
32
+ end
33
+
34
+ private
35
+
36
+ def valid_attribute?
37
+ %w(nickname email name password).include? attribute.to_s
38
+ end
39
+
40
+ def valid_suggestor?
41
+ ["nickname"].include? attribute.to_s
42
+ end
43
+
44
+ def valid_users
45
+ Decidim::UserBaseEntity.where(invitation_token: nil, organization: current_organization)
46
+ end
47
+ end
48
+ end
49
+ end
@@ -5,6 +5,6 @@ module Decidim
5
5
  module FriendlySignup
6
6
  DECIDIM_VERSION = "0.26.2"
7
7
  COMPAT_DECIDIM_VERSION = "~> 0.26.0"
8
- VERSION = "0.1"
8
+ VERSION = "0.2"
9
9
  end
10
10
  end
@@ -1,14 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "decidim/friendly_signup/version"
3
4
  require "decidim/friendly_signup/engine"
4
5
 
5
6
  module Decidim
6
7
  module FriendlySignup
7
8
  include ActiveSupport::Configurable
8
9
 
10
+ autoload :UserAttributeValidator, "decidim/friendly_signup/user_attribute_validator"
11
+
9
12
  # Whether to override passwords boxes or not
10
13
  config_accessor :override_passwords do
11
14
  true
12
15
  end
16
+
17
+ # Whether to use instant validation or not
18
+ config_accessor :use_instant_validation do
19
+ true
20
+ end
13
21
  end
14
22
  end
23
+
24
+ # Engines to handle logic unrelated to participatory spaces or components
25
+ Decidim.register_global_engine(
26
+ :decidim_friendly_signup, # this is the name of the global method to access engine routes
27
+ ::Decidim::FriendlySignup::Engine,
28
+ at: "/friendly_signup"
29
+ )
data/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "decidim-module-friendly_signup",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "decidim-module-friendly_signup",
9
- "version": "0.1.0",
9
+ "version": "0.2.0",
10
10
  "license": "AGPL-3.0-or-later",
11
11
  "devDependencies": {
12
12
  "eslint": "^7.25.0",
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "decidim-module-friendly_signup",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "A better signup process for Decidim",
5
5
  "main": "index.js",
6
6
  "directories": {
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: decidim-friendly_signup
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.1'
4
+ version: '0.2'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Vergés
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-07-12 00:00:00.000000000 Z
11
+ date: 2022-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: decidim-core
@@ -49,11 +49,15 @@ files:
49
49
  - README.md
50
50
  - Rakefile
51
51
  - app/controllers/concerns/decidim/friendly_signup/needs_header_snippets.rb
52
+ - app/controllers/decidim/friendly_signup/application_controller.rb
53
+ - app/controllers/decidim/friendly_signup/validator_controller.rb
52
54
  - app/packs/entrypoints/decidim_friendly_signup.js
53
55
  - app/packs/entrypoints/decidim_friendly_signup.scss
54
56
  - app/packs/images/decidim/friendly_signup/icon.svg
55
- - app/packs/src/decidim/friendly_signup/password_helper.js
56
- - app/packs/src/decidim/friendly_signup/password_toggler.js
57
+ - app/packs/src/decidim/friendly_signup/lib/instant_validator.js
58
+ - app/packs/src/decidim/friendly_signup/lib/password_toggler.js
59
+ - app/packs/src/decidim/friendly_signup/setup_password.js
60
+ - app/packs/src/decidim/friendly_signup/setup_validations.js
57
61
  - app/packs/stylesheets/decidim/friendly_signup/_input-groups.scss
58
62
  - app/views/decidim/account/_password_fields.html.erb
59
63
  - app/views/decidim/devise/invitations/edit.html.erb
@@ -65,6 +69,7 @@ files:
65
69
  - config/locales/en.yml
66
70
  - lib/decidim/friendly_signup.rb
67
71
  - lib/decidim/friendly_signup/engine.rb
72
+ - lib/decidim/friendly_signup/user_attribute_validator.rb
68
73
  - lib/decidim/friendly_signup/version.rb
69
74
  - package-lock.json
70
75
  - package.json