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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +191 -0
- data/Rakefile +8 -0
- data/app/assets/config/doc_contract_manifest.js +3 -0
- data/app/assets/javascripts/doc_contract/application.coffee +68 -0
- data/app/assets/stylesheets/doc_contract/application.sass +52 -0
- data/app/assets/stylesheets/doc_contract/pandoc.css +15 -0
- data/app/controllers/concerns/doc_contract/shared_template_and_instance_methods.rb +71 -0
- data/app/controllers/doc_contract/application_controller.rb +20 -0
- data/app/controllers/doc_contract/contract_instances_controller.rb +56 -0
- data/app/controllers/doc_contract/contract_templates_controller.rb +69 -0
- data/app/helpers/doc_contract/application_helper.rb +178 -0
- data/app/models/concerns/yaml_validator.rb +9 -0
- data/app/models/doc_contract/contract_instance.rb +39 -0
- data/app/models/doc_contract/contract_template.rb +37 -0
- data/app/views/doc_contract/application/_button-destroy-record.html.slim +1 -0
- data/app/views/doc_contract/application/_button-edit-record.html.slim +1 -0
- data/app/views/doc_contract/application/_button-new-record.html.slim +1 -0
- data/app/views/doc_contract/application/_button-preview-html.html.slim +9 -0
- data/app/views/doc_contract/application/_button-preview-markdown.html.slim +9 -0
- data/app/views/doc_contract/application/_button-preview-pdf.html.slim +1 -0
- data/app/views/doc_contract/application/_definition_table_attribute_errors.html.slim +7 -0
- data/app/views/doc_contract/application/_messages.html.slim +4 -0
- data/app/views/doc_contract/application/_navigation.html.slim +18 -0
- data/app/views/doc_contract/application/main.html.slim +6 -0
- data/app/views/doc_contract/contract_instances/_form.html.slim +25 -0
- data/app/views/doc_contract/contract_instances/edit.html.slim +3 -0
- data/app/views/doc_contract/contract_instances/index.html.slim +34 -0
- data/app/views/doc_contract/contract_instances/new.html.slim +3 -0
- data/app/views/doc_contract/contract_instances/show.html.slim +25 -0
- data/app/views/doc_contract/contract_templates/_form.html.slim +34 -0
- data/app/views/doc_contract/contract_templates/edit.html.slim +3 -0
- data/app/views/doc_contract/contract_templates/index.html.slim +31 -0
- data/app/views/doc_contract/contract_templates/new.html.slim +3 -0
- data/app/views/doc_contract/contract_templates/show.html.slim +28 -0
- data/app/views/doc_contract/kaminari/_first_page.html.slim +2 -0
- data/app/views/doc_contract/kaminari/_gap.html.slim +2 -0
- data/app/views/doc_contract/kaminari/_last_page.html.slim +2 -0
- data/app/views/doc_contract/kaminari/_next_page.html.slim +2 -0
- data/app/views/doc_contract/kaminari/_page.html.slim +6 -0
- data/app/views/doc_contract/kaminari/_paginator.html.slim +11 -0
- data/app/views/doc_contract/kaminari/_prev_page.html.slim +2 -0
- data/app/views/layouts/doc_contract/application.html.slim +23 -0
- data/config/initializers/human_plural.rb +16 -0
- data/config/locales/en.yml +30 -0
- data/config/routes.rb +17 -0
- data/db/migrate/20220118150923_create_doc_contract_contract_templates.rb +10 -0
- data/db/migrate/20220121160034_add_markdown_to_doc_contract_contract_templates.rb +5 -0
- data/db/migrate/20220121165825_add_config_yml_to_doc_contract_contract_templates.rb +5 -0
- data/db/migrate/20220122151402_create_doc_contract_contract_instances.rb +11 -0
- data/db/migrate/20220125183437_add_titlepage_background_to_contract_templates.rb +5 -0
- data/lib/doc_contract/engine.rb +24 -0
- data/lib/doc_contract/handlebars.rb +99 -0
- data/lib/doc_contract/version.rb +3 -0
- data/lib/doc_contract.rb +9 -0
- data/lib/tasks/doc_contract_tasks.rake +4 -0
- 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,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,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,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,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,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,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,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
|