Skip to content

Commit

Permalink
Merge pull request #7 from gtt-project/next
Browse files Browse the repository at this point in the history
Next
  • Loading branch information
dkastl authored Jul 1, 2024
2 parents c2fc7e9 + 10a3348 commit 78b5305
Show file tree
Hide file tree
Showing 42 changed files with 1,517 additions and 1,133 deletions.
147 changes: 94 additions & 53 deletions app/controllers/print_templates_controller.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
class PrintTemplatesController < ApplicationController
layout ->{ @project ? 'base' : 'admin' }
layout -> { @project ? 'base' : 'admin' }

self.main_menu = false

before_action :set_trackers, only: [:new, :create, :edit, :update]
before_action :find_print_template, only: [:edit, :update, :destroy]
before_action :find_print_template, only: [:edit, :update, :destroy, :show]
before_action :require_admin, except: [:show, :fields_for_tracker]

# TODO: make this work with Rails.ajax
# before_action :authorize_view_print_templates, only: [:show, :fields_for_tracker]

def index
@print_templates = PrintTemplate.includes(:tracker).all
@print_templates = PrintTemplate.includes(:tracker).all.order(name: :asc)
end

def new
Expand All @@ -28,7 +25,6 @@ def create
end

def edit
# @print_template is set by before_action
end

def update
Expand All @@ -48,71 +44,116 @@ def destroy
end

def show
@print_template = PrintTemplate.find(params[:id])
# Define the keys that need to be parsed as JSON
json_keys = ['schemas']

# Parse specified JSON strings to nested JSON
parsed_json = @print_template.attributes.each_with_object({}) do |(key, value), hash|
hash[key] = if json_keys.include?(key) && value.is_a?(String)
begin
JSON.parse(value)
rescue JSON::ParserError
value
end
else
value
end
end

fields_data = generate_fields_data(@print_template.tracker)

# Merge fields data into parsed_json
merged_json = parsed_json.merge(fields_data)

respond_to do |format|
format.json { render json: @print_template }
format.js
format.json { render json: merged_json }
end
end

def fields_for_tracker
@tracker = Tracker.find(params[:tracker_id])

# Define core fields
@core_fields = {
'standard#author.name' => ['text', 'field_author'],
'standard#status.name' => ['text', 'field_status'],
'standard#priority.name' => ['text', 'field_priority'],
'standard#assigned_to.name' => ['text', 'field_assigned_to'],
'standard#category.name' => ['text', 'field_category'],
'standard#fixed_version.name' => ['text', 'field_fixed_version'],
'standard#subject' => ['text', 'field_subject'],
'standard#description' => ['text', 'field_description'],
'standard#start_date' => ['date', 'field_start_date'],
'standard#due_date' => ['date', 'field_due_date'],
'standard#done_ratio' => ['text', 'field_done_ratio'],
'standard#estimated_hours' => ['text', 'field_estimated_hours'],
'standard#total_estimated_hours' => ['text', 'field_total_estimated_hours'],
'standard#spent_hours' => ['text', 'label_spent_time'],
'standard#total_spent_hours' => ['text', 'label_total_spent_time'],
'standard#created_on' => ['date', 'field_created_on'],
'standard#updated_on' => ['date', 'field_updated_on'],
'standard#closed_on' => ['date', 'field_closed_on'],
tracker = Tracker.find(params[:tracker_id])
fields_data = generate_fields_data(tracker)
render json: fields_data
end

private

def generate_fields_data(tracker)
# Define the fields that are available for the print template
core_fields = {
'author.name' => ['string', l(:field_author)],
'status.name' => ['string', l(:field_status)],
'priority.name' => ['string', l(:field_priority)],
'assigned_to.name' => ['string', l(:field_assigned_to)],
'category.name' => ['string', l(:field_category)],
'fixed_version.name' => ['string', l(:field_fixed_version)],
'subject' => ['string', l(:field_subject)],
'description' => ['text', l(:field_description)],
'start_date' => ['date', l(:field_start_date)],
'due_date' => ['date', l(:field_due_date)],
'done_ratio' => ['float', l(:field_done_ratio)],
'estimated_hours' => ['float', l(:field_estimated_hours)],
'total_estimated_hours' => ['float', l(:field_total_estimated_hours)],
'spent_hours' => ['float', l(:label_spent_time)],
'total_spent_hours' => ['float', l(:label_total_spent_time)],
'created_on' => ['date', l(:field_created_on)],
'updated_on' => ['date', l(:field_updated_on)],
'closed_on' => ['date', l(:field_closed_on)],
}.map { |field, attributes| create_field_hash(field, *attributes) }

# Define custom fields with their names directly
@custom_fields = @tracker.custom_fields.map do |cf|
field_identifier = "custom#issue_custom_field_values_#{cf.id}"
# Custom fields
custom_fields = tracker.custom_fields.map do |cf|
field_key = "cf_#{cf.id}"
field_format = cf.field_format
field_name = cf.name
field_label = cf.name

create_field_hash(field_identifier, field_format, field_name)
create_field_hash(field_key, field_format, field_label)
end

# Define special fields with localization keys
@special_fields = {
'special#issue_map' => ['image', 'field_issue_map'],
'special#issue_url' => ['qrcode', 'field_issue_url']
# Special fields
special_fields = {
'issue_map' => ['map', l(:field_issue_map)],
'issue_url' => ['link', l(:field_issue_url)],
}.map { |field, attributes| create_field_hash(field, *attributes) }

# Sorting
@core_fields.sort_by! { |field| field[:name].downcase }
@custom_fields.sort_by! { |field| field[:name].downcase }
@special_fields.sort_by! { |field| field[:name].downcase }
# Field formats
format_list = {
'bool' => ['boolean', 'Boolean'],
'date' => ['date', 'Date'],
# 'attachment' => ['file', 'File'],
'float' => ['float', 'Float'],
'int' => ['integer', 'Integer'],
# 'enumeration' => ['enumeration', 'Key/value list'],
# 'link' => ['link', 'Link'],
# 'list' => ['list', 'List'],
# 'text' => ['text', 'Long text'],
'string' => ['string', 'Text'],
# 'user' => ['user', 'User'],
# 'version' => ['version', 'Version'],
}.map { |field, attributes| create_field_hash(field, *attributes) }

respond_to do |format|
format.js
end
# Return the fields data
{
'fieldKeyOptions': [{
'label': l(:label_core_fields),
'options': core_fields.sort_by! { |field| field[:value].downcase }
}, {
'label': l(:label_custom_fields),
'options': custom_fields.sort_by! { |field| field[:value].downcase }
}, {
'label': l(:label_special_fields),
'options': special_fields.sort_by! { |field| field[:value].downcase }
}],
'fieldFormatOptions': format_list
}
end

private

def create_field_hash(field, format, name_or_key)
name = I18n.exists?(name_or_key) ? I18n.t(name_or_key) : name_or_key

{
name: name,
identifier: field,
label: name,
value: field,
format: format
}
end
Expand All @@ -126,7 +167,7 @@ def find_print_template
end

def print_template_params
params.require(:print_template).permit(:name, :schemas, :inputs, :basepdf, :tracker_id)
params.require(:print_template).permit(:name, :schemas, :basepdf, :tracker_id, :context)
end

def require_admin
Expand Down
9 changes: 1 addition & 8 deletions app/controllers/print_templates_pdfme_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def designer
@csrf_token = form_authenticity_token
end

def form
def viewer
issue_id = params[:issue_id]
api_key = User.current.api_key

Expand Down Expand Up @@ -55,13 +55,6 @@ def form
@csrf_token = form_authenticity_token
end

# Future actions for viewer, generator, etc.
# def viewer
# end

# def generator
# end

private

def authorize_view_print_templates
Expand Down
5 changes: 5 additions & 0 deletions app/models/print_template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,9 @@ class PrintTemplate < ActiveRecord::Base
validates :name, uniqueness: { scope: :tracker_id }

validates :tracker_id, presence: true

# The context of the print template must be one of the following values.
CONTEXT_OPTIONS = %w(issue issues project).freeze

validates :context, presence: true, inclusion: { in: CONTEXT_OPTIONS }
end
39 changes: 22 additions & 17 deletions app/views/print_templates/_form.html.erb
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
<div class="box tabular">
<p><%= f.text_field :name, required: true, size: 50 %></p>

<p>
<%= f.select :context,
options_for_select([
[ l(:label_print_template_context_option_issue), 'issue' ],
[ l(:label_print_template_context_option_issues), 'issues', { disabled: true } ],
[ l(:label_print_template_context_option_project), 'project', { disabled: true } ]
],
@print_template.context || 'issue'),
{ required: true } %>
</p>


<p>
<%= f.select :tracker_id,
options_from_collection_for_select(@trackers, :id, :name, @print_template.tracker_id || @trackers.first.id),
{ required: true },
{ data: { url: url_for(controller: 'print_templates', action: 'fields_for_tracker', format: :js) } } %>
options_from_collection_for_select(@trackers, :id, :name, @print_template.tracker_id || @trackers.first.id),
{ required: true },
{ data: { url: url_for(controller: 'print_templates', action: 'fields_for_tracker', format: :json) } } %>
</p>

<p>
<%= content_tag(:label, l(:label_print_template_basepdf), for: 'pdf-upload') %>
<input type="file" onchange="encodeBasePDF(this)" accept="application/pdf" id="pdf-upload" />
<input type="file" accept="application/pdf" id="pdf-upload" />
<span id="basepdf-ok-icon" class="icon-only icon-ok" style="<%= 'display: none;' unless @print_template.basepdf.present? %>"></span>
<%= link_to l(:link_print_template_basepdf_reset), '#', id: 'use-blank-pdf', style: ('display: none;' unless @print_template.basepdf.present?) %>
</p>
Expand All @@ -24,24 +37,12 @@
<!-- Hidden Fields -->
<%= f.hidden_field :schemas, value: @print_template.schemas, id: 'print_template_schemas' %>
<%= f.hidden_field :basepdf, value: @print_template.basepdf, id: 'print_template_basepdf' %>
<%= f.hidden_field :inputs, value: @print_template.inputs, id: 'print_template_inputs' %>
</div>

<div id="designer-fullscreen" class="pdfme-overlay" style="display:none;">
<div id="designer-button-bar" style="display: flex; align-items: center; justify-content: space-between;">
<div>
<!-- Dropdown for issue fields -->
<%= select_tag :field, options_for_select([]), id: 'tracker-fields', include_blank: true, class: 'btn ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only' %>

<!-- Button to create a new field -->
<%= button_tag type: 'button', id: 'add-field-btn', class: 'btn ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary' do %>
<span class="ui-icon ui-icon-plus"></span>
<%= l(:button_print_template_add_field) %>
<% end %>
</div>

<div style="margin-right:15px;">
<!-- Buttons aligned to the right -->
<!-- Buttons aligned to the left -->
<input type="file" id="template-file-input" style="display: none;" accept="application/json">
<%= button_tag type: 'button', id: 'template_upload-designer-fullscreen-btn', class: 'btn ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary' do %>
<span class="ui-icon ui-icon-arrowthick-1-n"></span>
Expand All @@ -51,6 +52,10 @@
<span class="ui-icon ui-icon-arrowthick-1-s"></span>
<%= l(:button_print_template_designer_template_download) %>
<% end %>
</div>

<div style="margin-right:15px;">
<!-- Buttons aligned to the right -->
<%= button_tag type: 'button', id: 'close-designer-fullscreen-btn', class: 'btn ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary' do %>
<span class="ui-icon ui-icon-closethick"></span>
<%= l(:button_print_template_designer_close) %>
Expand Down
4 changes: 2 additions & 2 deletions app/views/print_templates/_issue_sidebar.html.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<% if @issue && @issue.tracker %>
<h3><%= l(:label_print_templates_plural) %></h3>
<% print_templates = PrintTemplate.where(tracker_id: @issue.tracker_id).order(:name) %>
<% print_templates = PrintTemplate.where(tracker_id: @issue.tracker_id, context: 'issue').order(:name) %>
<% if print_templates.any? %>
<p>
<%= label_tag 'print_template_select', l(:label_select_print_template) %>
Expand Down Expand Up @@ -29,7 +29,7 @@
<% end %>
</div>
</div>
<iframe id="pdfme-form-iframe" src="<%= url_for(controller: 'print_templates_pdfme', action: 'form', issue_id: @issue.id) %>"></iframe>
<iframe id="pdfme-form-iframe" src="<%= url_for(controller: 'print_templates_pdfme', action: 'viewer', issue_id: @issue.id) %>"></iframe>
</div>
<% else %>
<p><%= l(:label_no_print_template_available) %>
Expand Down
1 change: 1 addition & 0 deletions app/views/print_templates/_list.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<tr>
<th><%= l :label_print_template_name %></th>
<th><%= l :label_tracker %></th>
<th><%= l :label_print_template_context %></th>
<th><%= l :label_print_template_basepdf %></th>
<th></th>
</tr>
Expand Down
16 changes: 14 additions & 2 deletions app/views/print_templates/_print_template.html.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
<% def localized_context(context) %>
<% case context %>
<% when 'issue' %>
<%= l(:label_print_template_context_option_issue) %>
<% when 'issues' %>
<%= l(:label_print_template_context_option_issues) %>
<% else %>
<%= context %>
<% end %>
<% end %>

<tr>
<td><%= link_to print_template.name, edit_print_template_path(print_template) %></td>
<td class="text"><%= textilizable print_template.tracker.name %></td>
<td class="text"><%= link_to print_template.name, edit_print_template_path(print_template) %></td>
<td><%= textilizable print_template.tracker.name %></td>
<td><%= textilizable localized_context(print_template.context) %></td>
<td>
<% if print_template.basepdf.present? %>
<span class="icon-only icon-ok"></span>
Expand Down
33 changes: 0 additions & 33 deletions app/views/print_templates/fields_for_tracker.js.erb

This file was deleted.

4 changes: 2 additions & 2 deletions app/views/print_templates_pdfme/designer.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
</head>
<body>
<div id="pdfme-container">
<div id="pdfme-loading">Reload page to start PDFme Designer...</div>
<div id="pdfme-loading"><%= l(:reload_page_for_designer) %></div>
</div>
<%= javascript_include_tag 'pdfme-designer', plugin: :redmine_print_templates %>
<script type="text/javascript">
var embeddedFonts = <%= raw @fonts.to_json %>;
const embeddedFonts = <%= raw @fonts.to_json %>;
</script>
</body>
</html>
Loading

0 comments on commit 78b5305

Please sign in to comment.