diff --git a/.eslintrc.yml b/.eslintrc.yml new file mode 100644 index 0000000000000000000000000000000000000000..bf16d5a4312e8115ec5a6c46ef82372eec529b4b --- /dev/null +++ b/.eslintrc.yml @@ -0,0 +1,180 @@ +env: + browser: true +extends: "eslint:recommended" +rules: + # key: 0 = allow, 1 = warn, 2 = error + + # Possible Errors + no-await-in-loop: 1 + no-console: 1 + no-extra-parens: [1, 'all'] + no-template-curly-in-string: 0 + + # Best Practices + accessor-pairs: 0 + array-callback-return: 0 + block-scoped-var: 1 + class-methods-use-this: 0 + complexity: 0 + consistent-return: 0 + curly: [1, 'all'] + default-case: 1 + dot-location: [1, 'property'] + dot-notation: 0 + eqeqeq: 1 + guard-for-in: 0 + max-classes-per-file: 0 + no-alert: 1 + no-caller: 1 + no-div-regex: 1 + no-else-return: 0 + no-empty-function: 1 + no-eq-null: 1 + no-eval: 0 + no-extend-native: 0 + no-extra-bind: 0 + no-extra-label: 1 + no-floating-decimal: 1 + no-implicit-coercion: 1 + no-implied-eval: 1 + no-invalid-this: 0 + no-iterator: 1 + no-labels: 0 + no-lone-blocks: 1 + no-loop-func: 1 + no-magic-numbers: 0 + no-multi-spaces: 1 + no-multi-str: 1 + no-new: 0 + no-new-func: 1 + no-new-wrappers: 1 + no-octal-escape: 1 + no-param-reassign: 1 + no-proto: 1 + no-restricted-globals: 1 + no-restricted-properties: 0 + no-return-assign: 1 + no-return-await: 1 + no-script-url: 1 + no-self-compare: 1 + no-sequences: 1 + no-throw-literal: 1 + no-unmodified-loop-condition: 1 + no-unused-expressions: 1 + no-useless-call: 1 + no-useless-concat: 1 + no-useless-return: 1 + no-void: 1 + no-warning-comments: 0 + prefer-named-capture-group: 0 + prefer-promise-reject-errors: 1 + radix: 1 + require-await: 1 + require-unicode-regexp: 0 + vars-on-top: 1 + wrap-iife: 1 + yoda: 1 + + # Strict Mode + strict: [1, 'safe'] + + # Variables + init-declarations: 0 + no-label-var: 1 + no-implicit-globals: 0 + no-shadow: 1 + no-undef-init: 1 + no-undefined: 1 + no-use-before-define: 1 + + # Stylistic Issues + array-bracket-newline: 0 + array-bracket-spacing: [1, 'never'] + array-element-newline: 0 + block-spacing: [1, 'always'] + brace-style: [1, '1tbs'] + camelcase: 1 + capitalized-comments: 0 + comma-dangle: [1, 'never'] + comma-spacing: [1, { "before": false, "after": true }] + comma-style: 1 + computed-property-spacing: [1, 'never'] + consistent-this: [1, 'that'] + eol-last: 1 + func-call-spacing: [1, 'never'] + func-name-matching: [1, 'always'] + func-names: 0 + func-style: [1, 'expression'] + function-paren-newline: [1, 'never'] + id-blacklist: 0 + id-length: 0 + id-match: 0 + implicit-arrow-linebreak: 0 + indent: [1, 4] + jsx-quotes: 0 + key-spacing: 1 + keyword-spacing: 1 + line-comment-position: [1, 'above'] + linebreak-style: [1, 'unix'] + lines-around-comment: 0 + lines-between-class-members: [1, 'always', { exceptAfterSingleLine: true }] + max-depth: [1, 4] + max-len: 0 + max-lines: 0 + max-lines-per-function: 0 + max-nested-callbacks: 0 + max-params: [1, 4] + max-statements: 0 + max-statements-per-line: [1, { max: 1 }] + multiline-comment-style: 0 + multiline-ternary: 0 + new-cap: 1 + new-parens: 1 + newline-per-chained-call: 1 + no-array-constructor: 0 + no-bitwise: 0 + no-continue: 0 + no-inline-comments: 0 + no-lonely-if: 1 + no-mixed-operators: 0 + no-multi-assign: 1 + no-multiple-empty-lines: 1 + no-negated-condition: 0 + no-nested-ternary: 1 + no-new-object: 0 + no-plusplus: 1 + no-restricted-syntax: 0 + no-tabs: 1 + no-ternary: 0 + no-trailing-spaces: 1 + no-underscore-dangle: 1 + no-unneeded-ternary: 1 + no-whitespace-before-property: 1 + nonblock-statement-body-position: 1 + object-curly-newline: 0 + object-curly-spacing: [1, 'always'] + object-property-newline: 0 + one-var: [1, 'consecutive'] + one-var-declaration-per-line: [1, 'always'] + operator-assignment: [1, 'always'] + operator-linebreak: 0 + padded-blocks: [1, 'never'] + padding-line-between-statements: 0 + prefer-object-spread: 0 + quote-props: 0 + quotes: [1, 'single'] + semi: [1, 'always'] + semi-spacing: [1, { before: false, after: true }] + semi-style: [1, 'last'] + sort-keys: 0 + sort-vars: 0 + space-before-blocks: [1, 'always'] + space-before-function-paren: [1, 'always'] + space-in-parens: [1, 'never'] + space-infix-ops: 0 + space-unary-ops: [1, { words: true, nonwords: false }] + spaced-comment: [1, 'always', { markers: ["global", "="] }] + switch-colon-spacing: [1, { after: true, before: false }] + template-tag-spacing: [1, 'always'] + unicode-bom: [1, 'never'] + wrap-regex: 1 diff --git a/.sass-lint.yml b/.sass-lint.yml new file mode 100644 index 0000000000000000000000000000000000000000..ceb2b87e752e710ef30840bee196fb813dd22f93 --- /dev/null +++ b/.sass-lint.yml @@ -0,0 +1,55 @@ +# Linter Options +options: + # Don't merge default rules + merge-default-rules: false + # Set the formatter to 'html' + formatter: html + # Output file instead of logging results + output-file: 'linters/sass-lint.html' + # Raise an error if more than 50 warnings are generated + max-warnings: 50 +# File Options +files: + include: + - 'app/assets/stylesheets/**/*.s+(a|c)ss' + - 'docs/themes/**/*.s+(a|c)ss' + ignore: + - 'vendor/**/*.*' +# Rule Configuration +rules: + class-name-format: 0 + extends-before-mixins: 2 + extends-before-declarations: 2 + mixins-before-declarations: + - 2 + - + exclude: + - breakpoint + - breakpoint-next + - breakpoint-min + - breakpoint-max + - breakpoint-infix + - media-breakpoint-up + - media-breakpoint-down + - media-breakpoint-between + - media-breakpoint-only + - mq + no-warn: 1 + no-debug: 1 + hex-length: + - 2 + - + style: long + hex-notation: + - 2 + - + style: uppercase + indentation: + - 4 + - + size: 4 + property-sort-order: + - 1 + - + order: alphabetical + ignore-custom-properties: false diff --git a/app/assets/stylesheets/application.sass b/app/assets/stylesheets/application.sass index d5b57dee4e5a818ccd0fcc9f51e1ecd835196811..27474b5d81f82f89fc5c67af09b5b7241062c228 100644 --- a/app/assets/stylesheets/application.sass +++ b/app/assets/stylesheets/application.sass @@ -1,2 +1,4 @@ -@import "bootstrap" +@import 'bootstrap' +@import 'appstack/light' +@import 'simple_form_password_with_hints' @import 'application/*' diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb index db3f81f6a1f0c04e0035b8f34a9b589d50af909a..4620a2382b6ee35724c3ecf3e259c21a2f1a8f47 100644 --- a/app/views/devise/sessions/new.html.erb +++ b/app/views/devise/sessions/new.html.erb @@ -1,20 +1,32 @@ -<h2><%= t(".sign_in") %></h2> +<h2 class="text-center"><%= t('login.not_registered_yet') %></h2> +<div class="form-actions text-center mt-3"> + <%= link_to t("devise.registrations.new.sign_up"), new_registration_path(resource_name), class: 'btn btn btn-lg btn-primary' %><br /> +</div> +<hr class="mt-4 mb-4"> + +<h2 class="text-center"><%= t('login.already_registered') %></h2> <%= simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %> <div class="form-inputs"> <%= f.input :email, required: false, autofocus: true, input_html: { autocomplete: "email" } %> - <%= f.input :password, - as: :password_with_hints, - allow_password_uncloaking: true, - required: false, - input_html: { autocomplete: "current-password" } %> + <div class="mb-3 password optional user_password"> + <%= f.input :password, + as: :password_with_hints, + allow_password_uncloaking: true, + required: false, + wrapper: false, + input_html: { autocomplete: "current-password" } %> + <small> + <%= link_to t("devise.passwords.new.forgot_your_password"), new_password_path(resource_name) %> + </small> + </div> <%= f.input :remember_me, as: :boolean if devise_mapping.rememberable? %> </div> - <div class="form-actions"> + <div class="form-actions text-center mt-3"> <%= f.button :submit, t(".sign_in"), class: 'btn btn-lg btn-primary' %> </div> <% end %> diff --git a/app/views/devise/shared/_links.html.erb b/app/views/devise/shared/_links.html.erb index d11c0611c870c0746348378fa6beedcde1025938..05579cd5c218fad2ef7dd3e8e59733b2e0283b5f 100644 --- a/app/views/devise/shared/_links.html.erb +++ b/app/views/devise/shared/_links.html.erb @@ -1,25 +1,19 @@ -<%- if controller_name != 'sessions' %> - <%= link_to t(".sign_in"), new_session_path(resource_name) %><br /> -<% end %> - -<%- if devise_mapping.registerable? && controller_name != 'registrations' %> - <%= link_to t(".sign_up"), new_registration_path(resource_name) %><br /> -<% end %> - -<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %> - <%= link_to t(".forgot_your_password"), new_password_path(resource_name) %><br /> -<% end %> +<div class="text-center mt-2"> + <%- if controller_name != 'sessions' %> + <%= link_to t(".sign_in"), new_session_path(resource_name) %><br /> + <% end %> -<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %> - <%= link_to t('.didn_t_receive_confirmation_instructions'), new_confirmation_path(resource_name) %><br /> -<% end %> + <%- if devise_mapping.confirmable? && controller_name != 'confirmations' %> + <%= link_to t('.didn_t_receive_confirmation_instructions'), new_confirmation_path(resource_name) %><br /> + <% end %> -<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %> - <%= link_to t('.didn_t_receive_unlock_instructions'), new_unlock_path(resource_name) %><br /> -<% end %> + <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %> + <%= link_to t('.didn_t_receive_unlock_instructions'), new_unlock_path(resource_name) %><br /> + <% end %> -<%- if devise_mapping.omniauthable? %> - <%- resource_class.omniauth_providers.each do |provider| %> - <%= link_to t('.sign_in_with_provider', provider: OmniAuth::Utils.camelize(provider)), omniauth_authorize_path(resource_name, provider), method: :post %><br /> + <%- if devise_mapping.omniauthable? %> + <%- resource_class.omniauth_providers.each do |provider| %> + <%= link_to t('.sign_in_with_provider', provider: OmniAuth::Utils.camelize(provider)), omniauth_authorize_path(resource_name, provider), method: :post %><br /> + <% end %> <% end %> -<% end %> +</div> diff --git a/app/views/layouts/devise.html.erb b/app/views/layouts/devise.html.erb index bf0769f907de1d36782224e0efe78ae5031eb4c6..834a33ea7f010d50a6eb4ccbcc65f8bc84ccb782 100644 --- a/app/views/layouts/devise.html.erb +++ b/app/views/layouts/devise.html.erb @@ -6,8 +6,8 @@ <title><%= yield :title %></title> <%= csrf_meta_tags %> <%= csp_meta_tag %> - <%= stylesheet_link_tag 'admin', media: 'all' %> - <%= javascript_include_tag 'admin' %> + <%= stylesheet_link_tag 'application', media: 'all' %> + <%= javascript_include_tag 'application' %> <%= favicon_link_tag 'favicon.png' %> </head> <body data-theme="default" data-layout="fluid"> @@ -17,7 +17,12 @@ <div class="row h-100"> <div class="col-sm-10 col-md-8 col-lg-6 mx-auto d-table h-100"> <div class="d-table-cell align-middle"> - <h1 class="mb-5 text-center"><%= current_university %></h1> + <div class="text-center mt-4"> + <h1 class="h2"><%= current_university %></h1> + <p class="lead"> + <%= t('login.subtitle') %> + </p> + </div> <div class="card"> <div class="card-body text-start"> <div class="m-sm-4"> diff --git a/config/locales/en.yml b/config/locales/en.yml index 1d3a8099e197f91a9526300a883a1ec7599c36c6..941e35100b4bbe64ac48699ccabe25db28b5e005 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,63 +1,66 @@ en: - true: Yes - false: No - home: Home - dashboard: Dashboard - show: Show - create: Create - edit: Edit - delete: Delete - please-confirm: Are you sure? - validate: Validate activerecord: models: university: + language: + one: Language + other: Languages + user: + attributes: + university: + address: Address + city: City + country: Country + name: Name + private: Private + public: Public + public_or_private: Public/private + zipcode: Zipcode + user: + email: Email + first_name: First name + language: Favourite language + last_name: Last name + mobile_phone: Mobile phone + researcher: Researcher profile + role: Role + one: User + other: Users one: University other: Universities - language: - one: Language - other: Languages - user: - one: User - other: Users - attributes: - university: - name: Name - address: Address - zipcode: Zipcode - city: City - country: Country - private: Private - public_or_private: Public/private - public: Public - private: Private - user: - email: Email - first_name: First name - last_name: Last name - mobile_phone: Mobile phone - role: Role - researcher: Researcher profile - language: Favourite language + create: Create + dashboard: Dashboard + delete: Delete devise: mailer: two_factor_authentication: subject: "Two-factor authentication code" + shared: + links: + sign_out: "Sign out" + two_factor_authentication: + attempt_failed: "Invalid Code" + code_has_been_sent: "Your authentication code has been sent." + enter_code_direct_otp: "Enter the code that was sent to you" + enter_code_totp: "Enter the code from your authentication application" + max_login_attempts_reached: "You're account has been locked for security reasons.<br />Please contact an administrator." + resend_code: "Resend Code" + send_code_instead: "Send me a code instead" + send_email_code: 'Send me a code via email' + success: "" text_html: "Your two-factor authentication code for %{university} is %{code}<br>It will expire in 5 minutes." - shared: - links: - sign_out: "Sign out" - two_factor_authentication: - attempt_failed: "Invalid Code" - code_has_been_sent: "Your authentication code has been sent." - enter_code_direct_otp: "Enter the code that was sent to you" - enter_code_totp: "Enter the code from your authentication application" - max_login_attempts_reached: "You're account has been locked for security reasons.<br />Please contact an administrator." - resend_code: "Resend Code" - send_code_instead: "Send me a code instead" - send_email_code: 'Send me a code via email' - success: "" + edit: Edit + false: No + home: Home + login: + already_registered: Already registered? + not_registered_yet: Not registered yet? + subtitle: Sign in to your account to continue + please-confirm: Are you sure? simple_form: hints: user: - mobile_phone: "International format (+XX)" \ No newline at end of file + mobile_phone: "International format (+XX)" + show: Show + true: Yes + validate: Validate diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 6c9359b576911889f88980fe9d1382908985edbd..0758a3567f8e9fc8c8fc6649a3f2c56c7542c568 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -1,63 +1,66 @@ fr: - true: Oui - false: Non - home: Accueil - dashboard: Tableau de bord - show: Voir - create: Créer - edit: Modifier - delete: Supprimer - please-confirm: Est-ce que vous confirmez ? - validate: Valider activerecord: models: university: + language: + one: Langue + other: Langues + user: + attributes: + university: + address: Adresse + city: Ville + country: Pays + name: Nom + private: Etablissement privé + public: Public + public_or_private: Public/privé + user: + email: Email + first_name: Prénom + language: Langue préférée + last_name: Nom + mobile_phone: Téléphone portable + researcher: Profil de chercheur + role: Rôle + zipcode: Code postal + one: Utilisateur + other: Utilisateurs one: Université other: Universités - language: - one: Langue - other: Langues - user: - one: Utilisateur - other: Utilisateurs - attributes: - university: - name: Nom - address: Adresse - zipcode: Code postal - city: Ville - country: Pays - private: Etablissement privé - public_or_private: Public/privé - public: Public - private: Privé - user: - email: Email - first_name: Prénom - last_name: Nom - mobile_phone: Téléphone portable - role: Rôle - researcher: Profil de chercheur - language: Langue préférée + create: Créer + dashboard: Tableau de bord + delete: Supprimer devise: mailer: two_factor_authentication_code: subject: "Code d'authentification à deux facteurs" + shared: + links: + sign_out: "Se déconnecter" + two_factor_authentication: + attempt_failed: "Code invalide" + code_has_been_sent: "Un code d'authentification vient de vous être envoyé." + enter_code_direct_otp: "Entrez le code qui vous a été envoyé" + enter_code_totp: "Entrez le code de votre application d'authentification" + max_login_attempts_reached: "Votre compte a été bloqué pour des raisons de sécurité.<br />Veuillez contacter un administrateur." + resend_code: "Renvoyer le code" + send_code_instead: "Envoyez-moi plutôt un code" + send_email_code: 'Envoyer le code par email' + success: "" text_html: "Votre code d'authentification pour %{university} est %{code}<br>Il expirera dans 5 minutes." - shared: - links: - sign_out: "Se déconnecter" - two_factor_authentication: - attempt_failed: "Code invalide" - code_has_been_sent: "Un code d'authentification vient de vous être envoyé." - enter_code_direct_otp: "Entrez le code qui vous a été envoyé" - enter_code_totp: "Entrez le code de votre application d'authentification" - max_login_attempts_reached: "Votre compte a été bloqué pour des raisons de sécurité.<br />Veuillez contacter un administrateur." - resend_code: "Renvoyer le code" - send_code_instead: "Envoyez-moi plutôt un code" - send_email_code: 'Envoyer le code par email' - success: "" + edit: Modifier + false: Non + home: Accueil + login: + already_registered: Déjà inscrit ? + not_registered_yet: Pas encore inscrit ? + subtitle: Vous devez être authentifié pour continuer + please-confirm: Est-ce que vous confirmez ? simple_form: hints: user: - mobile_phone: "Format international (+XX)" \ No newline at end of file + mobile_phone: "Format international (+XX)" + show: Voir + true: Oui + validate: Valider