decidim-friendly_signup 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
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