doc_contract 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +191 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/config/doc_contract_manifest.js +3 -0
  6. data/app/assets/javascripts/doc_contract/application.coffee +68 -0
  7. data/app/assets/stylesheets/doc_contract/application.sass +52 -0
  8. data/app/assets/stylesheets/doc_contract/pandoc.css +15 -0
  9. data/app/controllers/concerns/doc_contract/shared_template_and_instance_methods.rb +71 -0
  10. data/app/controllers/doc_contract/application_controller.rb +20 -0
  11. data/app/controllers/doc_contract/contract_instances_controller.rb +56 -0
  12. data/app/controllers/doc_contract/contract_templates_controller.rb +69 -0
  13. data/app/helpers/doc_contract/application_helper.rb +178 -0
  14. data/app/models/concerns/yaml_validator.rb +9 -0
  15. data/app/models/doc_contract/contract_instance.rb +39 -0
  16. data/app/models/doc_contract/contract_template.rb +37 -0
  17. data/app/views/doc_contract/application/_button-destroy-record.html.slim +1 -0
  18. data/app/views/doc_contract/application/_button-edit-record.html.slim +1 -0
  19. data/app/views/doc_contract/application/_button-new-record.html.slim +1 -0
  20. data/app/views/doc_contract/application/_button-preview-html.html.slim +9 -0
  21. data/app/views/doc_contract/application/_button-preview-markdown.html.slim +9 -0
  22. data/app/views/doc_contract/application/_button-preview-pdf.html.slim +1 -0
  23. data/app/views/doc_contract/application/_definition_table_attribute_errors.html.slim +7 -0
  24. data/app/views/doc_contract/application/_messages.html.slim +4 -0
  25. data/app/views/doc_contract/application/_navigation.html.slim +18 -0
  26. data/app/views/doc_contract/application/main.html.slim +6 -0
  27. data/app/views/doc_contract/contract_instances/_form.html.slim +25 -0
  28. data/app/views/doc_contract/contract_instances/edit.html.slim +3 -0
  29. data/app/views/doc_contract/contract_instances/index.html.slim +34 -0
  30. data/app/views/doc_contract/contract_instances/new.html.slim +3 -0
  31. data/app/views/doc_contract/contract_instances/show.html.slim +25 -0
  32. data/app/views/doc_contract/contract_templates/_form.html.slim +34 -0
  33. data/app/views/doc_contract/contract_templates/edit.html.slim +3 -0
  34. data/app/views/doc_contract/contract_templates/index.html.slim +31 -0
  35. data/app/views/doc_contract/contract_templates/new.html.slim +3 -0
  36. data/app/views/doc_contract/contract_templates/show.html.slim +28 -0
  37. data/app/views/doc_contract/kaminari/_first_page.html.slim +2 -0
  38. data/app/views/doc_contract/kaminari/_gap.html.slim +2 -0
  39. data/app/views/doc_contract/kaminari/_last_page.html.slim +2 -0
  40. data/app/views/doc_contract/kaminari/_next_page.html.slim +2 -0
  41. data/app/views/doc_contract/kaminari/_page.html.slim +6 -0
  42. data/app/views/doc_contract/kaminari/_paginator.html.slim +11 -0
  43. data/app/views/doc_contract/kaminari/_prev_page.html.slim +2 -0
  44. data/app/views/layouts/doc_contract/application.html.slim +23 -0
  45. data/config/initializers/human_plural.rb +16 -0
  46. data/config/locales/en.yml +30 -0
  47. data/config/routes.rb +17 -0
  48. data/db/migrate/20220118150923_create_doc_contract_contract_templates.rb +10 -0
  49. data/db/migrate/20220121160034_add_markdown_to_doc_contract_contract_templates.rb +5 -0
  50. data/db/migrate/20220121165825_add_config_yml_to_doc_contract_contract_templates.rb +5 -0
  51. data/db/migrate/20220122151402_create_doc_contract_contract_instances.rb +11 -0
  52. data/db/migrate/20220125183437_add_titlepage_background_to_contract_templates.rb +5 -0
  53. data/lib/doc_contract/engine.rb +24 -0
  54. data/lib/doc_contract/handlebars.rb +99 -0
  55. data/lib/doc_contract/version.rb +3 -0
  56. data/lib/doc_contract.rb +9 -0
  57. data/lib/tasks/doc_contract_tasks.rake +4 -0
  58. metadata +254 -0
@@ -0,0 +1,178 @@
1
+ module DocContract
2
+ module ApplicationHelper
3
+ # Return active or nil based on the given route spec
4
+ # %li{ class: active_class('users') # true if controller is users, false otherwise
5
+ # %li{ class: active_class('pages#about') # true if controller is pages and action is about
6
+ #NOTE: Taken from the dunlop-core gem. That is the best maintained version
7
+ def active_class(*route_specs)
8
+ options = route_specs.extract_options!
9
+ return nil if Array.wrap(options[:except]).any?{|exception| current_route_spec?(exception) }
10
+ return 'active' if route_specs.any?{|rs| current_route_spec?(rs, options) }
11
+ nil
12
+ end
13
+
14
+ # Check if the current route matches the route given as argument.
15
+ # The syntax is meant to be a bit similar to specifying routes in
16
+ # `config/routes.rb`.
17
+ # current_route_spec?('products') #=> true if controller name is products, false otherwise
18
+ # current_route_spec?('products#show') #=> true if controller_name is products AND action_name is show
19
+ # current_route_spec?('#show') #=> true if action_name is show, false otherwise
20
+ #NOTE: this helper is tested through the active_class helper
21
+ #NOTE: Taken from the dunlop-core gem. That is the best maintained version
22
+ def current_route_spec?(route_spec, options = {})
23
+ return route_spec.match([controller_path, action_name].join('#')) if route_spec.is_a?(Regexp)
24
+ controller, action = route_spec.split('#')
25
+ return action == params[:id] if controller_path == 'high_voltage/pages'
26
+ actual_controller_parts = controller_path.split('/')
27
+ if controller #and controller_path == controller
28
+ tested_controller_parts = controller.split('/')
29
+ return if tested_controller_parts.size > actual_controller_parts.size
30
+ if actual_controller_parts[0...tested_controller_parts.size] == tested_controller_parts
31
+ # controller spec matches
32
+ return true unless action
33
+ action_name == action
34
+ end
35
+ else
36
+ action_name == action
37
+ end
38
+ end
39
+
40
+ #NOTE: Taken from the dunlop-core gem. That is the best maintained version
41
+ def page_title(*args, &blk)
42
+ extra_content = capture(&blk) if blk.present?
43
+ if resource_title?(args)
44
+ @scope_model = args[1].is_a?(ActiveRecord::Base) ? args[1].class : args[1]
45
+ content = page_title_for_resource(args)
46
+ else
47
+ content = page_title_for_string(args)
48
+ end
49
+ content += extra_content if extra_content.present?
50
+ title_tag = content_tag(:h2, content, class: 'page-title ui header')
51
+ content_for :page_title, title_tag
52
+ title_tag
53
+ end
54
+
55
+ def resource_title?(args)
56
+ args.first.is_a?(Symbol) &&
57
+ (args[1].respond_to?(:model_name) || args[1].class.respond_to?(:model_name))
58
+ end
59
+
60
+ def page_title_for_string(args)
61
+ title = html_escape(args.first)
62
+ options = args.last.is_a?(Hash) ? args.last : {}
63
+ if back_options = options[:back]
64
+ url =
65
+ case back_options
66
+ when Array then polymorphic_path(back_options)
67
+ when true then :back
68
+ else back_options
69
+ end
70
+ if url
71
+ back_link = link_to content_tag(:i, nil, class: 'left arrow icon'), url, class: 'title-back-link'
72
+ title = back_link.safe_concat(title)
73
+ end
74
+ end
75
+ title
76
+ end
77
+
78
+ def page_title_for_resource(args)
79
+ options = args.extract_options!
80
+ model = args[1].respond_to?(:model_name) ? args[1] : args[1].class
81
+ if args.first == :index
82
+ title = t('action.index.label', models: model.model_name.human_plural).html_safe
83
+ else
84
+ title = t("action.#{args.first}.label", model: model.model_name.human).html_safe
85
+ end
86
+ if back_options = options[:back]
87
+ url =
88
+ case back_options
89
+ when Array then polymorphic_path(back_options)
90
+ when true then :back
91
+ else back_options
92
+ end
93
+ if url
94
+ back_link = link_to content_tag(:i, nil, class: 'left arrow icon'), url, class: 'title-back-link'
95
+ title = back_link.safe_concat(title)
96
+ end
97
+ end
98
+ title
99
+ end
100
+
101
+ def search_result_info(records)
102
+ from_item = (records.current_page - 1) * records.limit_value + 1
103
+ to_item = [from_item + records.size - 1, records.total_count].min
104
+ from_item = 0 if records.total_count.zero?
105
+ "#{from_item} - #{to_item} / #{records.total_count}"
106
+ end
107
+
108
+ def at(attribute_name, scope_model=nil)
109
+ scope_model ||= @scope_model
110
+ scope_model.human_attribute_name(attribute_name)
111
+ end
112
+
113
+ # Search helpers from dunlop
114
+ def search_row(options = {}, &blk)
115
+ classes = Array.wrap(options[:class])
116
+ classes |= ['search']
117
+ classes << 'conditions-present' if @q.conditions.present?
118
+ content = capture(&blk)
119
+ content_tag(:tr, content, class: classes )
120
+ end
121
+
122
+ # This helper returns the link for showing a record inside a table
123
+ def table_show_link(record, path = nil, options = {})
124
+ if options.has_key?(:authorized)
125
+ return unless options[:authorized]
126
+ else
127
+ return unless can? :show, record
128
+ end
129
+ link_to(content_tag(:i,nil, class: 'folder open icon'), path || record, class: 'table-link show ui mini basic primary icon button')
130
+ end
131
+
132
+ # This helper returns the link for showing a record inside a table
133
+ def table_download_link(record, path = nil, options = {})
134
+ if options.has_key?(:authorized)
135
+ return unless options[:authorized]
136
+ else
137
+ return unless can? :download, record
138
+ end
139
+ link_to(content_tag(:i,nil, class: 'download icon'), path || [:download, record], class: 'table-link download ui mini violet icon button')
140
+ end
141
+
142
+ # This helper returns the link for editing a record inside a table
143
+ def table_edit_link(record, path = nil, options = {})
144
+ if options.has_key?(:authorized)
145
+ return unless options[:authorized]
146
+ else
147
+ return unless can? :update, record
148
+ end
149
+ link_to(content_tag(:i, nil, class: 'write icon'), path || [:edit, record], class: 'table-link edit ui mini basic yellow icon button')
150
+ end
151
+
152
+ def table_destroy_link(record, path = nil, options = {})
153
+ if options.has_key?(:authorized)
154
+ return unless options[:authorized]
155
+ else
156
+ return unless can? :destroy, record
157
+ end
158
+ confirm_text = "Are you sure you want to delete #{record.class.model_name.human}"
159
+ record_name = nil
160
+ record_name = record.presentation_name if record.respond_to?(:presentation_name)
161
+ record_name ||= record.name if record.respond_to?(:name)
162
+ record_name ||= record.title if record.respond_to?(:title)
163
+ confirm_text << " #{record_name}" if record_name.present?
164
+ confirm_text << "?"
165
+ link_to(content_tag(:i, nil, class: 'trash icon'), path || record, method: :delete, data: { confirm: confirm_text }, class: 'table-link destroy ui mini negative icon button')
166
+ end
167
+
168
+ # https://coderwall.com/p/7gqmog/display-flash-messages-with-semantic-ui-in-rails
169
+ def flash_class(level)
170
+ case level.to_sym
171
+ when :success then "ui positive message"
172
+ when :error, :alert then "ui negative message"
173
+ when :notice then "ui info message"
174
+ else "ui #{level} message"
175
+ end
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,9 @@
1
+ class YamlValidator < ActiveModel::EachValidator
2
+ def validate_each(record, attribute, value)
3
+ return if value.blank?
4
+ object = YAML.load(value) rescue nil
5
+ unless object
6
+ record.errors.add attribute, (options[:message] || "is not valid YAML")
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,39 @@
1
+ module DocContract
2
+ class ContractInstance < ApplicationRecord
3
+ validates :name, presence: true
4
+ belongs_to :contract_template
5
+
6
+ def config
7
+ own_config = YAML.load(config_yml.to_s) || {}
8
+ own_config.reverse_merge contract_template.config
9
+ end
10
+
11
+ def markdown
12
+ contract_template.markdown
13
+ end
14
+
15
+ def markdown=(value)
16
+ contract_template.markdown = value
17
+ end
18
+
19
+ def processed_markdown(config_addittions = {})
20
+ config = self.config
21
+ config.merge! config_addittions unless config_addittions.blank?
22
+ DocContract::Handlebars.compile(markdown, config)
23
+ end
24
+
25
+ def template_markdown(config_addittions = {})
26
+ config = self.config
27
+ config.merge! config_addittions unless config_addittions.blank?
28
+ result = DocContract::Handlebars.compile(markdown, config)
29
+ # prefix the markdown with the config (eisvogel pandoc)
30
+ "#{config.to_yaml}...\n\n"+result
31
+ end
32
+
33
+ def processed_html
34
+ result = processed_markdown.sub(/.*\n...\n\n/m, '')
35
+ markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, tables: true)
36
+ markdown.render result
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,37 @@
1
+ module DocContract
2
+ class ContractTemplate < ApplicationRecord
3
+ HANDLEBARS_REGEX = /{{((#)?[a-z\._ ]+)}}/
4
+ has_many :contract_instances, dependent: :delete_all
5
+
6
+ validates :name, presence: true
7
+ validates :config_yml, yaml: true
8
+
9
+ def config
10
+ YAML.load(config_yml.to_s) || {}
11
+ end
12
+
13
+ def processed_markdown(config_addittions = {})
14
+ config = self.config
15
+ config.merge! config_addittions unless config_addittions.blank?
16
+ DocContract::Handlebars.compile(markdown, config)
17
+ end
18
+
19
+ def template_markdown(config_addittions = {})
20
+ config = self.config
21
+ config.merge! config_addittions unless config_addittions.blank?
22
+ result = DocContract::Handlebars.compile(markdown, config)
23
+ # prefix the markdown with the config (eisvogel pandoc)
24
+ "#{config.to_yaml}...\n\n"+result
25
+ end
26
+
27
+ def processed_html
28
+ result = processed_markdown.sub(/.*\n...\n\n/m, '')
29
+ markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, tables: true)
30
+ markdown.render result
31
+ end
32
+
33
+ def present_handlebars_expressions
34
+ markdown.scan(HANDLEBARS_REGEX).map(&:first).uniq
35
+ end
36
+ end
37
+ end
@@ -0,0 +1 @@
1
+ = link_to t('action.destroy.label', model: (record_class).model_name.human), record, class: 'ui red button', method: :delete, data: { confirm: t('general.are_you_sure') }
@@ -0,0 +1 @@
1
+ = link_to t('action.edit.label', model: (record_class).model_name.human), polymorphic_path(record, action: :edit), class: 'ui yellow button'
@@ -0,0 +1 @@
1
+ = link_to t('action.new.label', model: (record_class).model_name.human), polymorphic_path(record_class, action: :new), class: 'ui primary basic button'
@@ -0,0 +1,9 @@
1
+ .ui.pink.button.preview-html data-target=polymorphic_path(record, action: :processed_html) Preview html
2
+ #html-preview-modal.ui.overlay.fullscreen.modal
3
+ .header html preview handlebars interpreted
4
+ pre.scrolling.content
5
+ .ui.active.inline.loader
6
+ .actions
7
+ - unless params[:action] == 'edit'
8
+ = link_to t('Edit'), [record, action: :edit], class: 'ui yellow button'
9
+ .ui.cancel.button Close
@@ -0,0 +1,9 @@
1
+ .ui.pink.button.preview-markdown data-target=polymorphic_path(record, action: :processed_markdown) Preview markdown
2
+ #markdown-preview-modal.ui.overlay.fullscreen.modal
3
+ .header Markdown preview handlebars interpreted
4
+ pre.scrolling.content
5
+ .ui.active.inline.loader
6
+ .actions
7
+ - unless params[:action] == 'edit'
8
+ = link_to t('Edit'), [record, action: :edit], class: 'ui yellow button'
9
+ .ui.cancel.button Close
@@ -0,0 +1 @@
1
+ = link_to 'PDF', polymorphic_path(@record, action: :get_pdf), class: 'ui button'
@@ -0,0 +1,7 @@
1
+ - if errors = @record.errors[attribute].presence
2
+ .ui.visible.negative.message
3
+ .content
4
+ h3.header Errors found
5
+ ul
6
+ - errors.each do |error|
7
+ li= error
@@ -0,0 +1,4 @@
1
+ - flash.each do |key, value|
2
+ .closable.visible class=flash_class(key)
3
+ i.close.icon
4
+ = value
@@ -0,0 +1,18 @@
1
+ .ui.inverted.menu.fixed
2
+ = link_to main_app.root_path, class: 'header item'
3
+ = Rails.application.config.doc_contract.link_home_content.to_s.html_safe
4
+ - if current_user.present?
5
+ = link_to DocContract::ContractTemplate.model_name.human_plural, [DocContract::ContractTemplate], class: ['item', active_class('doc_contract/contract_templates')]
6
+ = link_to DocContract::ContractInstance.model_name.human_plural, [DocContract::ContractInstance], class: ['item', active_class('doc_contract/contract_instances')]
7
+ .right.menu
8
+ - if current_user.present?
9
+ .ui.dropdown.item
10
+ span= current_user.respond_to?(:nickname) ? current_user.nickname : current_user.email
11
+ i.dropdown.icon
12
+ .menu
13
+ = link_to main_app.destroy_user_session_path, method: :delete, class: 'item'
14
+ i.sign.out.icon
15
+ span.text= t 'user.sign_out'
16
+ - else
17
+ = link_to t('devise.sessions.new.sign_in'), main_app.new_user_session_path, class: 'item'
18
+
@@ -0,0 +1,6 @@
1
+ .ui.two.item.menu
2
+ = link_to DocContract::ContractTemplate.model_name.human_plural, [DocContract::ContractTemplate], class: ['item', active_class('doc_contract/contract_templates')]
3
+ = link_to DocContract::ContractInstance.model_name.human_plural, [DocContract::ContractInstance], class: ['item', active_class('doc_contract/contract_instances')]
4
+ - if Rails.application.config.doc_contract.show_readme_on_main_page
5
+ hr
6
+ #readme_container== readme_html
@@ -0,0 +1,25 @@
1
+ /table.ui.attached.compact.definition.table
2
+ = form_with model: @record, class: 'ui form' do |f|
3
+ table.ui.top.attached.compact.definition.table
4
+ tbody
5
+ tr
6
+ td= at :name
7
+ td: .ui.input= f.text_field :name
8
+ tr
9
+ td
10
+ = DocContract::ContractTemplate.model_name.human
11
+ = render 'definition_table_attribute_errors', attribute: :contract_template_id
12
+ td
13
+ = f.collection_select :contract_template_id, DocContract::ContractTemplate.all, :id, :name, class: 'ui input'
14
+ tr
15
+ td
16
+ = at :config_yml
17
+ = render 'definition_table_attribute_errors', attribute: :config_yml
18
+ td
19
+ = f.text_area :config_yml
20
+ #contract_config_yml_editor= raw @record.config_yml
21
+ .ui.bottom.attached.segment
22
+ = f.submit class: 'ui primary button'
23
+ - unless @record.new_record?
24
+ = render 'button-preview-markdown', record: @record
25
+ = render 'button-destroy-record', record: @record
@@ -0,0 +1,3 @@
1
+ .ui.container
2
+ = page_title :edit, @record, back: @record
3
+ = render 'form'
@@ -0,0 +1,34 @@
1
+ .ui.container
2
+ = page_title :index, record_class
3
+ - if @records.any? or @q.conditions.present?
4
+ = search_form_for(@q, html: {class: 'ui form'}) do |f|
5
+ = hidden_field_tag :per_page, params[:per_page], id: 'q_per_page'
6
+ table.ui.compact.top.attached.striped.table
7
+ thead
8
+ tr
9
+ th= at :name
10
+ th= DocContract::ContractTemplate.model_name.human
11
+ th.column-filter.actions
12
+ = search_result_info @records
13
+ = search_row class: 'ui mini form' do
14
+ th= f.text_field :name_cont, placeholder: 'name contains'
15
+ th= f.text_field :contract_template_name_cont, placeholder: 'template contains'
16
+ th.column-filter.actions
17
+ button.ui.mini.primary.icon.button
18
+ i.filter.icon
19
+ = link_to polymorphic_path(record_class, reset_q: true), class: 'clear-filters-button ui mini basic yellow icon button' do
20
+ i.close.icon
21
+ tbody
22
+ - @records.each do |record|
23
+ tr
24
+ td= link_to record.name, record
25
+ td= link_to record.contract_template.name, record.contract_template
26
+ td.actions
27
+ = table_show_link record
28
+ = table_edit_link record
29
+ .ui.bottom.attached.segment
30
+ = render 'button-new-record'
31
+ = paginate @records
32
+ - else
33
+ p= t 'collection.empty', models: record_class.model_name.human_plural
34
+ = render 'button-new-record'
@@ -0,0 +1,3 @@
1
+ .ui.container
2
+ = page_title :new, record_class, back: [record_class]
3
+ = render 'form'
@@ -0,0 +1,25 @@
1
+ .ui.container
2
+ = page_title :show, @record, back: [record_class]
3
+ table.ui.top.attached.compact.definition.table
4
+ tbody
5
+ tr
6
+ td= at :name
7
+ td= @record.name
8
+ tr
9
+ td= DocContract::ContractTemplate.model_name.human
10
+ td= link_to @record.contract_template.name, @record.contract_template
11
+ tr
12
+ td= at :config_yml
13
+ td
14
+ pre=raw @record.config_yml
15
+ tr
16
+ td Markdown tags
17
+ td
18
+ ul
19
+ - @record.contract_template.markdown.scan(/{{{?((#[a-z]+ )?[a-z]+.[a-z]*)}?}}/).uniq.each do |founds|
20
+ li= founds[0]
21
+ .ui.bottom.attached.segment
22
+ = render 'button-preview-markdown', record: @record
23
+ /= render 'button-preview-html', record: @record
24
+ = render 'button-preview-pdf', record: @record
25
+ = render 'button-edit-record', record: @record
@@ -0,0 +1,34 @@
1
+ /table.ui.attached.compact.definition.table
2
+ = form_with model: @record, class: 'ui form' do |f|
3
+ table.ui.top.attached.compact.definition.table
4
+ tbody
5
+ tr
6
+ td.collapsing= at :name
7
+ td: .ui.input= f.text_field :name
8
+ tr
9
+ td.collapsing= at :latex_template
10
+ td: .ui.input= f.select :latex_template, %w[eisvogel]
11
+ tr
12
+ td.collapsing= at :titlepage_background
13
+ td= f.select :titlepage_background, (1..11), include_blank: ' -- '
14
+ tr
15
+ td.collapsing
16
+ = at :config_yml
17
+ = render 'definition_table_attribute_errors', attribute: :config_yml
18
+ td
19
+ = f.text_area :config_yml
20
+ #contract_config_yml_editor= raw @record.config_yml
21
+ tr
22
+ td.collapsing
23
+ = at :markdown
24
+ = render 'definition_table_attribute_errors', attribute: :markdown
25
+ td
26
+ = f.text_area :markdown
27
+ #contract_template_markdown_editor= raw @record.markdown
28
+ /textarea.hidden= @record.markdown
29
+ .ui.bottom.attached.segment
30
+ = f.submit class: 'ui primary button'
31
+ - unless @record.new_record?
32
+ = render 'button-preview-markdown', record: @record
33
+ = render 'button-preview-html', record: @record
34
+ = render 'button-destroy-record', record: @record
@@ -0,0 +1,3 @@
1
+ .ui.container
2
+ = page_title :edit, @record, back: @record
3
+ = render 'form'
@@ -0,0 +1,31 @@
1
+ .ui.container
2
+ = page_title :index, record_class
3
+ - if @records.any? or @q.conditions.present?
4
+ = search_form_for(@q, html: {class: 'ui form'}) do |f|
5
+ = hidden_field_tag :per_page, params[:per_page], id: 'q_per_page'
6
+ table.ui.compact.top.attached.striped.table
7
+ thead
8
+ tr
9
+ th= at :name
10
+ th.column-filter.actions
11
+ = search_result_info @records
12
+ = search_row class: 'ui mini form' do
13
+ th= f.text_field :name_cont, placeholder: 'name contains'
14
+ th.column-filter.actions
15
+ button.ui.mini.primary.icon.button
16
+ i.filter.icon
17
+ = link_to polymorphic_path(record_class, reset_q: true), class: 'clear-filters-button ui mini basic yellow icon button' do
18
+ i.close.icon
19
+ tbody
20
+ - @records.each do |record|
21
+ tr
22
+ td= link_to record.name, record
23
+ td.actions
24
+ = table_show_link record
25
+ = table_edit_link record
26
+ .ui.bottom.attached.segment
27
+ = render 'button-new-record'
28
+ = paginate @records
29
+ - else
30
+ p= t 'collection.empty', models: record_class.model_name.human_plural
31
+ = render 'button-new-record'
@@ -0,0 +1,3 @@
1
+ .ui.container
2
+ = page_title :new, record_class, back: [record_class]
3
+ = render 'form'
@@ -0,0 +1,28 @@
1
+ .ui.container
2
+ = page_title :show, @record, back: [record_class]
3
+ table.ui.top.attached.compact.definition.table
4
+ tbody
5
+ tr
6
+ td= at :name
7
+ td= @record.name
8
+ tr
9
+ td= at :latex_template
10
+ td= @record.latex_template
11
+ tr
12
+ td= at :config_yml
13
+ td
14
+ pre=raw @record.config_yml
15
+ tr
16
+ td Markdown tags
17
+ td
18
+ ul
19
+ - @record.present_handlebars_expressions.each do |expression|
20
+ li= expression
21
+ tr
22
+ td Raw preview
23
+ td: .contract-markdown-show-container=raw @record.processed_html
24
+ .ui.bottom.attached.segment
25
+ = render 'button-preview-markdown', record: @record
26
+ /= render 'button-preview-html', record: @record
27
+ = render 'button-preview-pdf', record: @record
28
+ = render 'button-edit-record', record: @record
@@ -0,0 +1,2 @@
1
+ = link_to url, title: t('views.pagination.first').html_safe, class: 'item', remote: remote do
2
+ i.angle.double.left.icon
@@ -0,0 +1,2 @@
1
+ .item
2
+ = t('views.pagination.truncate').html_safe
@@ -0,0 +1,2 @@
1
+ = link_to url, title: t('views.pagination.last').html_safe, class: 'item', remote: remote do
2
+ i.angle.double.right.icon
@@ -0,0 +1,2 @@
1
+ = link_to url, title: t('views.pagination.next').html_safe, class: 'item', remote: remote do
2
+ i.right.angle.icon
@@ -0,0 +1,6 @@
1
+ - if page.current?
2
+ = link_to url, title: page, class: 'item active', remote: remote do
3
+ = page
4
+ - else
5
+ = link_to url, title: page, class: 'item', remote: remote do
6
+ = page
@@ -0,0 +1,11 @@
1
+ = paginator.render do
2
+ nav.ui.pagination.menu
3
+ == first_page_tag unless current_page.first?
4
+ == prev_page_tag unless current_page.first?
5
+ - each_page do |page|
6
+ - if page.left_outer? || page.right_outer? || page.inside_window?
7
+ == page_tag page
8
+ - elsif !page.was_truncated?
9
+ == gap_tag
10
+ == next_page_tag unless current_page.last?
11
+ == last_page_tag unless current_page.last?
@@ -0,0 +1,2 @@
1
+ = link_to url, title: t('views.pagination.previous').html_safe, class: 'item', remote: remote do
2
+ i.left.angle.icon
@@ -0,0 +1,23 @@
1
+ doctype html
2
+ html lang="en"
3
+ head
4
+ title= content_for?(:title) ? yield(:title) : 'DocContract Engine'
5
+ meta name="description" content="#{content_for?(:description) ? yield(:description) : 'Application'}"
6
+ = csrf_meta_tags
7
+ = csp_meta_tag
8
+
9
+ meta charset="utf-8"
10
+ meta content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0" name="viewport"
11
+
12
+ = stylesheet_link_tag 'doc_contract/application', media: 'all'
13
+ = javascript_include_tag 'doc_contract/application'
14
+ = content_for :head
15
+ body
16
+ header= render 'navigation'
17
+ /.environment-ribbon class=Rails.env
18
+ span= Rails.env
19
+ main role="main"
20
+ = render 'messages'
21
+ = yield
22
+ hr
23
+ p DocContract Engine
@@ -0,0 +1,16 @@
1
+ module ActiveModel
2
+ class Name
3
+ def human_plural
4
+ # Try to find the plural name of a model. If none can be found try to find a non namespaced version and return that one
5
+ default = Proc.new do |path|
6
+ if path.present? and path['/'] # non namespaced model a/b/c => a
7
+ unnamespaced_path = path.sub(/\.(\w+)\/[\w\\]+/, '.\1')
8
+ I18n.t(unnamespaced_path, default: Proc.new{ human.pluralize })
9
+ else
10
+ human.pluralize
11
+ end
12
+ end
13
+ I18n.t("#{@klass.i18n_scope}.models.plural.#{i18n_key}", default: default )
14
+ end
15
+ end
16
+ end