Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create tokens for groups #15

Merged
merged 30 commits into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
ba2857a
add controller
microstudi Apr 16, 2024
2d4bf64
add back button
microstudi Apr 16, 2024
aeedea3
Update config/locales/en.yml
microstudi Apr 17, 2024
322cdb7
Update app/views/decidim/anonymous_codes/admin/codes/index.html.erb
microstudi Apr 17, 2024
82d0ef3
add new method to codes_controller
ElviaBth Apr 17, 2024
b537bd7
add command createtokens and destroy method
ElviaBth Apr 17, 2024
8e8e927
Merge branch 'main' into feat/generate_tokens
microstudi Apr 17, 2024
88fcd8f
fix merge
microstudi Apr 17, 2024
3c6b7db
table headers
microstudi Apr 17, 2024
b0bebce
fix index page
microstudi Apr 17, 2024
d7f52d3
add warning when inactive gorup
microstudi Apr 17, 2024
abb2904
fix index empty status
microstudi Apr 17, 2024
f69c99c
add system token_codes_spec
ElviaBth Apr 17, 2024
0aa7c2d
relocate exporters
microstudi Apr 17, 2024
575bfe1
Merge branch 'feat/generate_tokens' of github.com:openpoke/decidim-mo…
microstudi Apr 17, 2024
1e7041f
resolve review comments
ElviaBth Apr 17, 2024
8eb8435
use custom find_exporter
microstudi Apr 17, 2024
11aa043
Merge branch 'feat/generate_tokens' of github.com:openpoke/decidim-mo…
microstudi Apr 17, 2024
f28aa51
add create_tokens_spec
ElviaBth Apr 17, 2024
ef5de82
add tokens_form_spec
ElviaBth Apr 17, 2024
7c28397
add codes_controller_spec
ElviaBth Apr 17, 2024
3de8de9
add checks to controller spec
ElviaBth Apr 18, 2024
0bf963d
fix codes_controller_spec get index check
ElviaBth Apr 18, 2024
7fbad3d
allow to create tokens from the group creation
microstudi Apr 18, 2024
583ce62
fix controller spec
ElviaBth Apr 18, 2024
0d4a30f
add test case for GET #new controller method
ElviaBth Apr 18, 2024
4bf3f87
add destroy method spec check
ElviaBth Apr 18, 2024
8142c30
add create controller method spec
ElviaBth Apr 18, 2024
fbec024
add create_tokens_job spec
ElviaBth Apr 19, 2024
768798a
resolve PR specs review comments
ElviaBth Apr 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ def call

transaction do
create_code_group!
CreateTokensJob.perform_later(code_group, form.num_tokens) if form.num_tokens.present?
end

broadcast(:ok)
Expand Down
26 changes: 26 additions & 0 deletions app/commands/decidim/anonymous_codes/admin/create_tokens.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true

module Decidim
module AnonymousCodes
module Admin
class CreateTokens < Decidim::Command
def initialize(form, code_group)
@form = form
@code_group = code_group
end

def call
return broadcast(:invalid) if form.invalid?

CreateTokensJob.perform_later(code_group, form.num_tokens)

broadcast(:ok)
end

private

attr_reader :form, :code_group
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module SurveysControllerOverride
next unless current_settings.allow_answers? && survey.open?
next if visitor_already_answered?

if token_groups.any?
if token_groups.active.any?
next if current_token&.available?

if current_token.blank?
Expand All @@ -22,6 +22,10 @@ module SurveysControllerOverride
end
render "decidim/anonymous_codes/surveys/code_required"
end

if token_groups.inactive.any? && current_user&.admin?
flash.now[:alert] = I18n.t("decidim.anonymous_codes.inactive_group", path: decidim_admin_anonymous_codes.edit_code_group_path(token_groups.inactive.first)).html_safe
end
end

after_action only: :answer do
Expand All @@ -35,11 +39,11 @@ module SurveysControllerOverride
private

def token_groups
@token_groups ||= Decidim::AnonymousCodes::Group.where(resource: survey, active: true)
@token_groups ||= Decidim::AnonymousCodes::Group.where(resource: survey)
end

def current_token
@current_token ||= Decidim::AnonymousCodes::Token.where(group: token_groups).find_by(token: token_param)
@current_token ||= Decidim::AnonymousCodes::Token.where(group: token_groups.active).find_by(token: token_param)
end

def token_param
Expand Down
22 changes: 19 additions & 3 deletions app/controllers/decidim/anonymous_codes/admin/codes_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,34 @@ def index
def new
enforce_permission_to :create, :anonymous_code_token

# todo
@form = form(TokensForm).instance
end

def create
enforce_permission_to :create, :anonymous_code_token

# todo
@form = form(TokensForm).from_params(params)

CreateTokens.call(@form, code_group) do
on(:ok) do
flash[:notice] = I18n.t("codes.create.success", scope: "decidim.anonymous_codes.admin")
redirect_to code_group_codes_path
end

on(:invalid) do
flash.now[:alert] = I18n.t("codes.create.invalid", scope: "decidim.anonymous_codes.admin")
render action: "new"
end
end
end

def destroy
enforce_permission_to :destroy, :anonymous_code_token, token: token
# todo
token.destroy!

flash[:notice] = I18n.t("codes.destroy.success", scope: "decidim.anonymous_codes.admin")

redirect_to code_group_codes_path
end

def export
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# frozen_string_literal: true

require "wicked_pdf"

module Decidim
module AnonymousCodes
module Exporters
# Inherits from abstract PDF exporter. This class is used to set
# the parameters used to create a PDF when exporting Survey Answers.
#
class AnonymousTokensPdf < Decidim::Exporters::PDF
def controller
@controller ||= AnonymousTokensPdfControllerHelper.new
end

def template
"decidim/anonymous_codes/admin/export/tokens_pdf"
end

def layout
"decidim/anonymous_codes/admin/export/pdf"
end

def locals
{
code_group: collection&.first&.group,
collection: collection.map { |token| Decidim::AnonymousCodes::TokenSerializer.new(token).serialize }
}
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

module Decidim
module AnonymousCodes
module Exporters
# rubocop: disable Rails/ApplicationController
# A dummy controller to render views while exporting questionnaires
class AnonymousTokensPdfControllerHelper < ActionController::Base
# rubocop: enable Rails/ApplicationController
helper Decidim::TranslationsHelper
end
end
end
end
2 changes: 2 additions & 0 deletions app/forms/decidim/anonymous_codes/admin/code_group_form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ class CodeGroupForm < Decidim::Form
attribute :active, Boolean, default: true
attribute :max_reuses, Integer, default: 1
attribute :resource_id, Integer
attribute :num_tokens, Integer

validates :title, translatable_presence: true
validates :expires_at, date: { after: Time.current }, if: ->(form) { form.expires_at.present? && form.active }
validates :max_reuses, presence: true, numericality: { only_integer: true, greater_than: 0 }
validates :num_tokens, numericality: { only_integer: true, greater_than: 0 }, if: ->(form) { form.num_tokens.present? }

def resource
@resource ||= Decidim::Surveys::Survey.find_by(id: resource_id)
Expand Down
13 changes: 13 additions & 0 deletions app/forms/decidim/anonymous_codes/admin/tokens_form.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

module Decidim
module AnonymousCodes
module Admin
class TokensForm < Decidim::Form
attribute :num_tokens, Integer, default: 1

validates :num_tokens, presence: true, numericality: { only_integer: true, greater_than: 0 }
end
end
end
end
31 changes: 31 additions & 0 deletions app/jobs/decidim/anonymous_codes/create_tokens_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

module Decidim
module AnonymousCodes
class CreateTokensJob < ApplicationJob
def perform(code_group, num_tokens)
@code_group = code_group
num_tokens.times do
create_token!
end
end

private

attr_reader :code_group

def create_token!
token = new_token while token.blank?
token.save!
end

def new_token
token = Decidim::AnonymousCodes::Token.new(
token: Decidim::AnonymousCodes.token_generator,
group: code_group
)
token if token.valid?
end
end
end
end
10 changes: 9 additions & 1 deletion app/jobs/decidim/anonymous_codes/export_group_tokens_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,15 @@ class ExportGroupTokensJob < ApplicationJob
queue_as :exports

def perform(user, group, format)
export_data = Decidim::Exporters.find_exporter(format).new(group.tokens, TokenSerializer).export
exporter = format == "AnonymousTokensPdf" ? Decidim::AnonymousCodes::Exporters::AnonymousTokensPdf : Decidim::Exporters.find_exporter(format)

if exporter
Rails.logger.info "Exporting tokens for group #{group.id} in #{format} format"
else
Rails.logger.error "Cannot export tokens for group #{group.id}: Unknown format: #{format}"
end

export_data = exporter.new(group.tokens, TokenSerializer).export

ExportMailer.export(user, "tokens_for_group_#{group.id}", export_data).deliver_now
end
Expand Down
3 changes: 3 additions & 0 deletions app/models/decidim/anonymous_codes/group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ class Group < ApplicationRecord
has_many :tokens, class_name: "Decidim::AnonymousCodes::Token", dependent: :destroy
belongs_to :resource, polymorphic: true, optional: true

scope :active, -> { where(active: true) }
scope :inactive, -> { where(active: false) }

def self.for(organization)
where(organization: organization)
end
Expand Down
36 changes: 14 additions & 22 deletions app/views/decidim/anonymous_codes/admin/code_groups/_form.html.erb
Original file line number Diff line number Diff line change
@@ -1,27 +1,19 @@
<div class="card">
<div class="card-divider">
<h2 class="card-title"><%= title %></h2>
</div>

<div class="card-section">
<div class="row column">
<%= form.translated :text_field, :title, label: t(".title") %>
</div>
<div class="row column">
<%= form.translated :text_field, :title, label: t(".title") %>
</div>

<div class="row column">
<%= form.datetime_field :expires_at, label: t(".expires_at") %>
</div>
<div class="row column">
<%= form.datetime_field :expires_at, label: t(".expires_at") %>
</div>

<div class="row column">
<%= form.check_box :active, label: t(".active") %>
</div>
<div class="row column">
<%= form.check_box :active, label: t(".active") %>
</div>

<div class="row column">
<%= form.number_field :max_reuses, label: t(".max_reuses") %>
</div>
<div class="row column">
<%= form.number_field :max_reuses, label: t(".max_reuses") %>
</div>

<div class="row column">
<%= form.select :resource_id, surveys, include_blank: true, label: t(".resource") %>
</div>
</div>
<div class="row column">
<%= form.select :resource_id, surveys, include_blank: true, label: t(".resource") %>
</div>
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
<%= decidim_form_for(@form, html: { class: "form edit_code_group" }) do |f| %>
<%= render partial: "form", object: f, locals: { title: t(".title") } %>
<div class="card">
<div class="card-divider">
<h2 class="card-title"><%= t(".title") %>
<a class="button tiny button--title hollow" href="<%= code_groups_path %>"><%= t("codes.index.back", scope: "decidim.anonymous_codes.admin") %></a>
</h2>
</div>

<div class="card-section">
<%= render partial: "form", object: f %>
</div>
</div>

<div class="button--double form-general-submit">
<%= f.submit "update" %>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@
<% groups.each do |group| %>
<tr>
<td><%= translated_attribute(group.title) %></td>
<td><%= t("booleans.#{group.active}") %></td>
<td><%= group.expires_at.present? ? ("<span class=\"text-#{ group.expired? ? "warning" : ""}\">#{l(group.expires_at, format: :decidim_short)}</span>".html_safe) : t(".never") %></td>
<td><strong class="<%= group.active? ? "text-success" : "text-alert" %>"><%= t("booleans.#{group.active}") %></strong></td>
<td><%= group.expires_at.present? ? ("<span class=\"text-#{ group.expired? ? "warning" : ""}\">#{l(group.expires_at, format: :decidim_short)}</span>".html_safe) : content_tag(:em, t(".never")) %></td>
<td><%= "#{group.tokens.used.count} / #{group.tokens_count}" %></td>
<td><%= group.max_reuses %></td>
<td class="table-list__actions">
<%= icon_link_to "eye", resource_path(group), t("actions.preview", scope: "decidim.anonymous_codes.admin"), class: "action-icon--preview#{group&.resource ? '':' invisible'}", target: :_blank %>
<%= icon_link_to "list", code_group_codes_path(group), t("actions.list_tokens", scope: "decidim.anonymous_codes.admin"), class: "action-icon--preview#{group&.resource ? '':' invisible'}" %>
<%= icon_link_to "pencil", edit_code_group_path(group.id), t("actions.edit", scope: "decidim.anonymous_codes.admin"), class: "action-icon--edit#{allowed_to?(:update, :anonymous_code_group, code_group: group) ? '' : ' invisible'}" %>
<%= icon_link_to "circle-x", code_group_path(group.id), t("actions.destroy", scope: "decidim.anonymous_codes.admin"), method: :delete, class: "action-icon--remove#{allowed_to?(:destroy, :anonymous_code_group, code_group: group) ? '' : ' invisible'}", data: { confirm: t("actions.confirm_destroy", scope: "decidim.anonymous_codes.admin") } %>
<%= icon_link_to "list", code_group_codes_path(group), t("actions.list_tokens", scope: "decidim.anonymous_codes.admin"), class: "action-icon--preview#{allowed_to?(:view, :anonymous_code_token) ? '':' invisible'}" %>
<%= icon_link_to "pencil", edit_code_group_path(group), t("actions.edit", scope: "decidim.anonymous_codes.admin"), class: "action-icon--edit#{allowed_to?(:update, :anonymous_code_group, code_group: group) ? '' : ' invisible'}" %>
<%= icon_link_to "circle-x", code_group_path(group), t("actions.destroy", scope: "decidim.anonymous_codes.admin"), method: :delete, class: "action-icon--remove#{allowed_to?(:destroy, :anonymous_code_group, code_group: group) ? '' : ' invisible'}", data: { confirm: t("actions.confirm_destroy", scope: "decidim.anonymous_codes.admin") } %>
</td>
</tr>
<% end %>
Expand All @@ -44,7 +44,7 @@
<% else %>
<div>
<%= t("code_groups.index.no_access_code_groups_records", scope: "decidim.anonymous_codes.admin") %>
<p><%= t("code_groups.index.start_by", scope: "decidim.anonymous_codes.admin", button: link_to(t("code_groups.index.new_access_code_group_button", scope: "decidim.anonymous_codes.admin"), new_code_group_path)) %></p>
<p><%= link_to t("code_groups.index.start_by", scope: "decidim.anonymous_codes.admin"), new_code_group_path %></p>
</div>
<% end %>
</div>
Expand Down
16 changes: 15 additions & 1 deletion app/views/decidim/anonymous_codes/admin/code_groups/new.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
<%= decidim_form_for(@form, url: code_groups_path, html: { class: "form new_code_group" }) do |f| %>
<%= render partial: "form", object: f, locals: { title: t(".title") } %>
<div class="card">
<div class="card-divider">
<h2 class="card-title"><%= t(".title") %>
<a class="button tiny button--title hollow" href="<%= code_groups_path %>"><%= t("codes.index.back", scope: "decidim.anonymous_codes.admin") %></a>
</h2>
</div>

<div class="card-section">
<%= render partial: "form", object: f %>

<div class="row column">
<%= f.number_field :num_tokens, label: t(".num_tokens") %>
</div>
</div>
</div>

<div class="button--double form-general-submit">
<%= f.submit "create" %>
Expand Down
14 changes: 14 additions & 0 deletions app/views/decidim/anonymous_codes/admin/codes/_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<div class="card">
<div class="card-divider">
<h2 class="card-title"><%= title %>

<a class="button tiny button--title hollow" href="<%= code_group_codes_path(code_group) %>"><%= t("codes.index.back_to_codes", scope: "decidim.anonymous_codes.admin") %></a>
</h2>
</div>

<div class="card-section">
<div class="row column">
<%= form.number_field :num_tokens, label: t(".number_of_tokens_to_generate") %>
</div>
</div>
</div>
Loading
Loading