doc_contract 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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