about summary refs log tree commit diff
path: root/app/views
diff options
context:
space:
mode:
authorEugen Rochko <eugen@zeonfederated.com>2017-11-27 16:07:59 +0100
committerGitHub <noreply@github.com>2017-11-27 16:07:59 +0100
commit740f8a95a905e949b6a74bc69dcaf638d2d46248 (patch)
tree8e09ff52b47c0cd303a9681014b34e68b5e28c51 /app/views
parent0ea4478b68e60e442e5b254c2d2bc511e27fea83 (diff)
Add consumable invites (#5814)
* Add consumable invites

* Add UI for generating invite codes

* Add tests

* Display max uses and expiration in invites table, delete invite

* Remove unused column and redundant validator

- Default follows not used, probably bad idea
- InviteCodeValidator is redundant because RegistrationsController
  checks invite code validity

* Add admin setting to disable invites

* Add admin UI for invites, configurable role for invite creation

- Admin UI that lists everyone's invites, always available
- Admin setting min_invite_role to control who can invite people
- Non-admin invite UI only visible if users are allowed to

* Do not remove invites from database, expire them instantly
Diffstat (limited to 'app/views')
-rw-r--r--app/views/admin/action_logs/_action_log.html.haml2
-rw-r--r--app/views/admin/invites/_invite.html.haml15
-rw-r--r--app/views/admin/invites/index.html.haml22
-rw-r--r--app/views/admin/settings/edit.html.haml5
-rw-r--r--app/views/auth/registrations/new.html.haml1
-rw-r--r--app/views/invites/_form.html.haml9
-rw-r--r--app/views/invites/_invite.html.haml11
-rw-r--r--app/views/invites/index.html.haml19
8 files changed, 83 insertions, 1 deletions
diff --git a/app/views/admin/action_logs/_action_log.html.haml b/app/views/admin/action_logs/_action_log.html.haml
index 72816d731..ec90961cb 100644
--- a/app/views/admin/action_logs/_action_log.html.haml
+++ b/app/views/admin/action_logs/_action_log.html.haml
@@ -1,7 +1,7 @@
 %li.log-entry
   .log-entry__header
     .log-entry__avatar
-      = image_tag action_log.account.avatar.url(:original), alt: '', width: 48, height: 48, class: 'avatar'
+      = image_tag action_log.account.avatar.url(:original), alt: '', width: 40, height: 40, class: 'avatar'
     .log-entry__content
       .log-entry__title
         = t("admin.action_logs.actions.#{action_log.action}_#{action_log.target_type.underscore}", name: content_tag(:span, action_log.account.username, class: 'username'), target: content_tag(:span, log_target(action_log), class: 'target')).html_safe
diff --git a/app/views/admin/invites/_invite.html.haml b/app/views/admin/invites/_invite.html.haml
new file mode 100644
index 000000000..81edfd912
--- /dev/null
+++ b/app/views/admin/invites/_invite.html.haml
@@ -0,0 +1,15 @@
+%tr
+  %td
+    .name-tag
+      = image_tag invite.user.account.avatar.url(:original), alt: '', width: 16, height: 16, class: 'avatar'
+      %span.username= invite.user.account.username
+  %td
+    = invite.uses
+    = " / #{invite.max_uses}" unless invite.max_uses.nil?
+  %td
+    - if invite.expires_at.nil?
+      ∞
+    - else
+      = l invite.expires_at
+  %td= table_link_to 'link', public_invite_url(invite_code: invite.code), public_invite_url(invite_code: invite.code)
+  %td= table_link_to 'times', t('invites.delete'), invite_path(invite), method: :delete if policy(invite).destroy?
diff --git a/app/views/admin/invites/index.html.haml b/app/views/admin/invites/index.html.haml
new file mode 100644
index 000000000..52a748fe0
--- /dev/null
+++ b/app/views/admin/invites/index.html.haml
@@ -0,0 +1,22 @@
+- content_for :page_title do
+  = t('admin.invites.title')
+
+- if policy(:invite).create?
+  %p= t('invites.prompt')
+
+  = render 'invites/form'
+
+  %hr/
+
+%table.table
+  %thead
+    %tr
+      %th
+      %th= t('invites.table.uses')
+      %th= t('invites.table.expires_at')
+      %th
+      %th
+  %tbody
+    = render @invites
+
+= paginate @invites
diff --git a/app/views/admin/settings/edit.html.haml b/app/views/admin/settings/edit.html.haml
index b07718315..c7c25f528 100644
--- a/app/views/admin/settings/edit.html.haml
+++ b/app/views/admin/settings/edit.html.haml
@@ -33,6 +33,11 @@
   %hr/
 
   .fields-group
+    = f.input :min_invite_role, wrapper: :with_label, collection: %i(disabled user moderator admin), label: t('admin.settings.registrations.min_invite_role.title'), label_method: lambda { |role| role == :disabled ? t('admin.settings.registrations.min_invite_role.disabled') : t("admin.accounts.roles.#{role}") }, as: :radio_buttons, include_blank: false, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li'
+
+  %hr/
+
+  .fields-group
     = f.input :site_extended_description, wrapper: :with_block_label, as: :text, label: t('admin.settings.site_description_extended.title'), hint: t('admin.settings.site_description_extended.desc_html'), input_html: { rows: 8 }
     = f.input :site_terms, wrapper: :with_block_label, as: :text, label: t('admin.settings.site_terms.title'), hint: t('admin.settings.site_terms.desc_html'), input_html: { rows: 8 }
 
diff --git a/app/views/auth/registrations/new.html.haml b/app/views/auth/registrations/new.html.haml
index f71675df0..2d4c0f5ac 100644
--- a/app/views/auth/registrations/new.html.haml
+++ b/app/views/auth/registrations/new.html.haml
@@ -16,6 +16,7 @@
   = f.input :email, placeholder: t('simple_form.labels.defaults.email'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.email'), :autocomplete => 'off' }
   = f.input :password, placeholder: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'off' }
   = f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_password'), :autocomplete => 'off' }
+  = f.input :invite_code, as: :hidden
 
   .actions
     = f.button :button, t('auth.register'), type: :submit
diff --git a/app/views/invites/_form.html.haml b/app/views/invites/_form.html.haml
new file mode 100644
index 000000000..99647f597
--- /dev/null
+++ b/app/views/invites/_form.html.haml
@@ -0,0 +1,9 @@
+= simple_form_for(@invite) do |f|
+  = render 'shared/error_messages', object: @invite
+
+  .fields-group
+    = f.input :max_uses, wrapper: :with_label, collection: [1, 5, 10, 25, 50, 100], label_method: lambda { |num| I18n.t('invites.max_uses', count: num) }, prompt: I18n.t('invites.max_uses_prompt')
+    = f.input :expires_in, wrapper: :with_label, collection: [30.minutes, 1.hour, 6.hours, 12.hours, 1.day].map(&:to_i), label_method: lambda { |i| I18n.t("invites.expires_in.#{i}") }, prompt: I18n.t('invites.expires_in_prompt')
+
+  .actions
+    = f.button :button, t('invites.generate'), type: :submit
diff --git a/app/views/invites/_invite.html.haml b/app/views/invites/_invite.html.haml
new file mode 100644
index 000000000..d794d72e4
--- /dev/null
+++ b/app/views/invites/_invite.html.haml
@@ -0,0 +1,11 @@
+%tr
+  %td
+    = invite.uses
+    = " / #{invite.max_uses}" unless invite.max_uses.nil?
+  %td
+    - if invite.expires_at.nil?
+      ∞
+    - else
+      = l invite.expires_at
+  %td= table_link_to 'link', public_invite_url(invite_code: invite.code), public_invite_url(invite_code: invite.code)
+  %td= table_link_to 'times', t('invites.delete'), invite_path(invite), method: :delete if policy(invite).destroy?
diff --git a/app/views/invites/index.html.haml b/app/views/invites/index.html.haml
new file mode 100644
index 000000000..f4c5047fa
--- /dev/null
+++ b/app/views/invites/index.html.haml
@@ -0,0 +1,19 @@
+- content_for :page_title do
+  = t('invites.title')
+
+- if policy(:invite).create?
+  %p= t('invites.prompt')
+
+  = render 'form'
+
+  %hr/
+
+%table.table
+  %thead
+    %tr
+      %th= t('invites.table.uses')
+      %th= t('invites.table.expires_at')
+      %th
+      %th
+  %tbody
+    = render @invites