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 +4 -4
- data/README.md +33 -18
- data/app/controllers/concerns/decidim/friendly_signup/needs_header_snippets.rb +2 -5
- data/app/controllers/decidim/friendly_signup/application_controller.rb +8 -0
- data/app/controllers/decidim/friendly_signup/validator_controller.rb +18 -0
- data/app/packs/entrypoints/decidim_friendly_signup.js +2 -1
- data/app/packs/src/decidim/friendly_signup/lib/instant_validator.js +95 -0
- data/app/packs/src/decidim/friendly_signup/{password_toggler.js → lib/password_toggler.js} +0 -0
- data/app/packs/src/decidim/friendly_signup/{password_helper.js → setup_password.js} +1 -1
- data/app/packs/src/decidim/friendly_signup/setup_validations.js +7 -0
- data/app/views/decidim/devise/registrations/new.html.erb +5 -5
- data/app/views/decidim/friendly_signup/shared/_password_fields.html.erb +1 -1
- data/lib/decidim/friendly_signup/engine.rb +4 -0
- data/lib/decidim/friendly_signup/user_attribute_validator.rb +49 -0
- data/lib/decidim/friendly_signup/version.rb +1 -1
- data/lib/decidim/friendly_signup.rb +15 -0
- data/package-lock.json +2 -2
- data/package.json +1 -1
- metadata +9 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c631ec440674f278ea3a0f3369435831014443e36f2f4247d1a87d914e7e66c8
|
4
|
+
data.tar.gz: cf5ca968cfe4459a63471e02ff36dd38f28cfb042c3146e175c3766dab4a6571
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
- [
|
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
|
-
|
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
|
-
$
|
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?(
|
27
|
-
|
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,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
|
@@ -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
|
+
}
|
File without changes
|
@@ -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
|
|
@@ -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
|
@@ -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.
|
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.
|
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
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.
|
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-
|
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/
|
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
|