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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5eb3ce664185e17d8c932c25bce2b271961673dbf91cc8bdc468c362f821981a
|
4
|
+
data.tar.gz: 9bb96322248d535055d6b5f7ad257388b6d2ef3ce41dd0057600fcc49545e5ee
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1be23ad090e9720299542b7fd16242c1aa2b3c4965535773ac166bd5de9fa65d97a2bd717df25667e6c7f185b50cb1d369b690721bce3e3ef91a4236a56a6441
|
7
|
+
data.tar.gz: d61685f08d14746fc7125932de2fe348e1e8403cc30a8705daf4916ee4dedab49c1bb074ba4fef586f4217b494697de91e4d87938b9ed77a0e63d39261b86ba7
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2022 Benjamin ter Kuile
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
# DocContract
|
2
|
+
DocContract is a `rails` `engine` that is an application wrapper around the https://pandoc.org/
|
3
|
+
pdf creation library.
|
4
|
+
|
5
|
+
The objective is to create and maintain contracts for customers as easy as possible
|
6
|
+
and thereby removing redundancy, which gives reason to errors and to create for
|
7
|
+
example a maintenance contract for a new year by just setting the `yaml` configuration to:
|
8
|
+
```yaml
|
9
|
+
year: 2022
|
10
|
+
```
|
11
|
+
|
12
|
+

|
13
|
+
|
14
|
+
The structure of contract maintenance is that you create a contract template for a customer,
|
15
|
+
for example a maintenance contract by creating a configuration (`yaml`) and a `markdown`
|
16
|
+
formatted contract. The markdown is then [handlebars](https://handlebarsjs.com/guide/expressions.html)
|
17
|
+
processed to prevent search/replace, summation and redundancy errors.
|
18
|
+
|
19
|
+
Then the [LaTeX](https://www.latex-project.org/) based [pandoc](https://pandoc.org/) system using the [eisvogel](https://github.com/Wandmalfarbe/pandoc-latex-template)
|
20
|
+
template is further used to convert the readable `markdown` to a nicely formatted PDF contract.
|
21
|
+
|
22
|
+
This `engine` is inpired by the [walle/gimli](https://github.com/walle/gimli)
|
23
|
+
gem but was no longer viable due to lack of maintenance and apparently a better renderer
|
24
|
+
that is [pandoc](https://pandoc.org/)
|
25
|
+
|
26
|
+
## Usage
|
27
|
+
Create a contract template consisting of a configuration `yaml` and a `markdown` formatted
|
28
|
+
contract. The `yaml` might look like:
|
29
|
+
|
30
|
+
```yaml
|
31
|
+
titlepage: true
|
32
|
+
title: Maintenance contract {{customer}} {{year}}
|
33
|
+
subtitle: To the future and beyond!
|
34
|
+
date: 2022-01-24
|
35
|
+
year: 2021
|
36
|
+
full_customer_name: E-corp located in Gotham City
|
37
|
+
customer: E-corp
|
38
|
+
contractor: Path-E-Tech Management
|
39
|
+
full_contractor_name: Path-E-Tech Management L.L.C. located in Gotham City
|
40
|
+
production_url: https://contracts.path-e-tech.com
|
41
|
+
staging_url: https://contracts-staging.path-e-tech.com
|
42
|
+
support_email: support@path-e-tech.com
|
43
|
+
author: Dullbert
|
44
|
+
header-left: "{{title}}"
|
45
|
+
header-right: "{{contractor}}"
|
46
|
+
footer-left: "{{customer}} | {{today}}"
|
47
|
+
toc: true
|
48
|
+
toc-own-page: true
|
49
|
+
numbersections: true
|
50
|
+
footer-right: '\thepage\ of \pageref{LastPage}'
|
51
|
+
geometry: margin=2.5cm
|
52
|
+
urlcolor: blue
|
53
|
+
header-includes: '\usepackage{lastpage}'
|
54
|
+
offer_items:
|
55
|
+
- label: Maintenance of the platform infrastructure
|
56
|
+
amount: 2_000
|
57
|
+
- label: Maintenance of the application API
|
58
|
+
amount: 2_000
|
59
|
+
- label: Do migrations for the Infrastructure adapter
|
60
|
+
amount: 2_500
|
61
|
+
```
|
62
|
+
|
63
|
+
And a basic markdown:
|
64
|
+
|
65
|
+
```markdown
|
66
|
+
# Introduction
|
67
|
+
|
68
|
+
## Client
|
69
|
+
|
70
|
+
This maintenance contract is requested by:
|
71
|
+
{{full_customer_name}}, hereafter {{customer}},
|
72
|
+
|
73
|
+
And created by:
|
74
|
+
{{full_contractor_name}}, hereafter {{contractor}}.
|
75
|
+
|
76
|
+
|
77
|
+
## Behest
|
78
|
+
contract stuff
|
79
|
+
|
80
|
+
\newpage
|
81
|
+
# Quote breakdown
|
82
|
+
|
83
|
+
## Fixed costs
|
84
|
+
|
85
|
+
Subject | Cost/y
|
86
|
+
--- | ---:
|
87
|
+
{{#each offer_items}}{{this.label}} | {{euro this.amount}}
|
88
|
+
{{/each}}**Total** | **{{euro offer_items_total}}**
|
89
|
+
|
90
|
+
The total costs for {{year}} for {{to_sentence (map offer_items 'label')}} will thereby be {{to_words offer_items_total}} ({{euro offer_items_total}}). All the amounts include
|
91
|
+
a VAT of 21%.
|
92
|
+
|
93
|
+
## Variable costs
|
94
|
+
And more contract stuff
|
95
|
+
```
|
96
|
+
|
97
|
+
## Installation
|
98
|
+
|
99
|
+
### Install the system dependencies
|
100
|
+
The largest dependency is the [LaTeX](https://www.latex-project.org/) installation:
|
101
|
+
```bash
|
102
|
+
$ sudo apt-get install texlive-full
|
103
|
+
$ sudo apt-get install pandoc
|
104
|
+
```
|
105
|
+
*NOTE*: For trimmed down version of `texlive-full` do trial and error or check docs
|
106
|
+
|
107
|
+
Or for mac:
|
108
|
+
```bash
|
109
|
+
$ brew install mactex
|
110
|
+
$ brew install pandoc
|
111
|
+
```
|
112
|
+
|
113
|
+
And to be able to use the `pandoc-latex-environment`
|
114
|
+
also install that one:
|
115
|
+
```bash
|
116
|
+
$ pip install pandoc-latex-environment
|
117
|
+
```
|
118
|
+
|
119
|
+
### Add the engine to your `rails` app
|
120
|
+
Add this line to your application's Gemfile:
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
gem "doc_contract"
|
124
|
+
```
|
125
|
+
|
126
|
+
And then execute:
|
127
|
+
```bash
|
128
|
+
$ bundle
|
129
|
+
$ bundle exec rails db:migrate
|
130
|
+
```
|
131
|
+
|
132
|
+
### Mount the engine to your routes
|
133
|
+
In your `config/routes.rb` file add:
|
134
|
+
```ruby
|
135
|
+
mount DocContract::Engine => '/doc-contract'
|
136
|
+
```
|
137
|
+
|
138
|
+
### Add the authorizations
|
139
|
+
In your `app/models/ability.rb` file add the authorizations.
|
140
|
+
This is a custom operation that you have to adjust to your needs.
|
141
|
+
To allow all users full controll to the contracts add:
|
142
|
+
```ruby
|
143
|
+
can :manage, DocContract::ContractTemplate
|
144
|
+
can :manage, DocContract::ContractInstance
|
145
|
+
```
|
146
|
+
|
147
|
+
If the `Ability` file does not yet exist, generate it using:
|
148
|
+
```bash
|
149
|
+
rails generate cancan:ability
|
150
|
+
```
|
151
|
+
|
152
|
+
### Other languages (i18n)
|
153
|
+
To use for a lets say Spanish based website add [rails-i18n](https://github.com/svenfuchs/rails-i18n) to your `Gemfile`
|
154
|
+
|
155
|
+
```ruby
|
156
|
+
gem 'rails-i18n'
|
157
|
+
```
|
158
|
+
|
159
|
+
And configure your application in `config/application.rb` to handle the languages:
|
160
|
+
|
161
|
+
```ruby
|
162
|
+
config.i18n.available_locales = %i[en es]
|
163
|
+
config.i18n.default_locale = :en
|
164
|
+
```
|
165
|
+
|
166
|
+
## Customization
|
167
|
+
|
168
|
+
### The main page
|
169
|
+
The main page of this engine is a bit of a placeholder page. The contents of this page can be found in [app/views/doc\_contract/application/main.html.slim](app/views/doc\_contract/application/main.html.slim).
|
170
|
+
To put your own version of this page create a view having this path in the main application. To only deactivate the README content there
|
171
|
+
put the following in your `config/application.rb` file:
|
172
|
+
|
173
|
+
```ruby
|
174
|
+
config.doc_contract.show_readme_on_main_page = false
|
175
|
+
```
|
176
|
+
|
177
|
+
### The link home content
|
178
|
+
The default value for `config/application.rb` is:
|
179
|
+
|
180
|
+
```ruby
|
181
|
+
config.doc_contract.link_home_content = '<i class="arrow left icon"></i> Back'
|
182
|
+
```
|
183
|
+
To change for example the icon, see the options at the [fomantic-ui](https://fomantic-ui.com/elements/icon.html) site.
|
184
|
+
|
185
|
+
### Screenshot
|
186
|
+

|
187
|
+
## Contributing
|
188
|
+
Contribution directions go here.
|
189
|
+
|
190
|
+
## License
|
191
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
#= require jquery
|
2
|
+
#= require jquery_ujs
|
3
|
+
#= require semantic-ui
|
4
|
+
#= require ace-rails-ap
|
5
|
+
|
6
|
+
latex_template_infos =
|
7
|
+
eisvogel: '
|
8
|
+
Look at:
|
9
|
+
<a href="https://github.com/Wandmalfarbe/pandoc-latex-template" target="_blank">
|
10
|
+
https://github.com/Wandmalfarbe/pandoc-latex-template
|
11
|
+
</a>'
|
12
|
+
$ ->
|
13
|
+
$('.ui.dropdown').dropdown() # assume fomantic that has the clearable class option, a lot better than the below custom code
|
14
|
+
|
15
|
+
$('.preview-markdown').click ->
|
16
|
+
markdown = $('#contract_template_markdown').val()
|
17
|
+
target = $(@).data('target')
|
18
|
+
modal = $('#markdown-preview-modal')
|
19
|
+
modal.modal 'show'
|
20
|
+
$.post target, {markdown: markdown}, (response) ->
|
21
|
+
content = modal.find('.content')
|
22
|
+
content.html response.markdown
|
23
|
+
false
|
24
|
+
$('.preview-html').click ->
|
25
|
+
markdown = $('#contract_template_markdown').val()
|
26
|
+
target = $(@).data('target')
|
27
|
+
modal = $('#html-preview-modal')
|
28
|
+
modal.modal 'show'
|
29
|
+
$.post target, {markdown: markdown}, (response) ->
|
30
|
+
content = modal.find('.content')
|
31
|
+
content.html response.html
|
32
|
+
false
|
33
|
+
|
34
|
+
latex_template = $('select#contract_template_latex_template')
|
35
|
+
latex_template.change ->
|
36
|
+
el = $(@)
|
37
|
+
$('.contract_template_latex_template_info').remove()
|
38
|
+
if info_html = latex_template_infos[el.val()]
|
39
|
+
info = $('<button><i class="info icon"></button>').addClass('contract_template_latex_template_info circular ui olive icon button')
|
40
|
+
info.popup
|
41
|
+
html: info_html
|
42
|
+
hoverable: true
|
43
|
+
el.after info
|
44
|
+
latex_template.change() if latex_template.length
|
45
|
+
|
46
|
+
contract_config_yml = $('#contract_template_config_yml,#contract_instance_config_yml')
|
47
|
+
if contract_config_yml.length
|
48
|
+
config_yml_editor = ace.edit 'contract_config_yml_editor',
|
49
|
+
mode: 'ace/mode/yaml'
|
50
|
+
theme: 'ace/theme/monokai'
|
51
|
+
value: contract_config_yml.val()
|
52
|
+
tabSize: 2
|
53
|
+
useSoftTabs: true
|
54
|
+
config_yml_editor.getSession().on 'change', (something, session) ->
|
55
|
+
contract_config_yml.val session.getValue()
|
56
|
+
false
|
57
|
+
contract_config_yml.hide()
|
58
|
+
|
59
|
+
contract_markdown = $('#contract_template_markdown')
|
60
|
+
if contract_markdown.length
|
61
|
+
markdown_editor = ace.edit 'contract_template_markdown_editor',
|
62
|
+
mode: 'ace/mode/markdown'
|
63
|
+
theme: 'ace/theme/monokai'
|
64
|
+
value: contract_markdown.val()
|
65
|
+
markdown_editor.getSession().on 'change', (something, session) ->
|
66
|
+
contract_markdown.val session.getValue()
|
67
|
+
false
|
68
|
+
contract_markdown.hide()
|
@@ -0,0 +1,52 @@
|
|
1
|
+
@import "semantic-ui"
|
2
|
+
main
|
3
|
+
min-height: calc(100% - 57px - 1rem) // 34px for footer inclusion
|
4
|
+
padding-top: 40px
|
5
|
+
> .page-title
|
6
|
+
padding-top: 12px
|
7
|
+
> .container .page-title
|
8
|
+
padding-top: 12px
|
9
|
+
|
10
|
+
#contract_template_markdown_editor, #contract_config_yml_editor
|
11
|
+
//position: absolute
|
12
|
+
width: 100%
|
13
|
+
height: 600px
|
14
|
+
|
15
|
+
#readme_container
|
16
|
+
pre
|
17
|
+
max-height: 500px
|
18
|
+
overflow: auto
|
19
|
+
margin: 10px
|
20
|
+
border: 1px solid #777
|
21
|
+
.contract-markdown-show-container
|
22
|
+
@import "./pandoc"
|
23
|
+
.contract-markdown-show-container
|
24
|
+
max-height: 600px
|
25
|
+
overflow-y: scroll
|
26
|
+
|
27
|
+
pre.scrolling.content
|
28
|
+
margin: 0
|
29
|
+
|
30
|
+
/* tables */
|
31
|
+
table.ui.table
|
32
|
+
.actions
|
33
|
+
text-align: right
|
34
|
+
thead
|
35
|
+
tr.search
|
36
|
+
th, td
|
37
|
+
padding-top: 2px
|
38
|
+
padding-bottom: 2px
|
39
|
+
.clear-filters-button
|
40
|
+
display: none
|
41
|
+
&.conditions-present
|
42
|
+
th, td
|
43
|
+
background-color: #d2e1ec
|
44
|
+
.clear-filters-button
|
45
|
+
display: inline-block
|
46
|
+
.column-filter.actions
|
47
|
+
min-width: 85px
|
48
|
+
padding-right: 3px
|
49
|
+
tbody
|
50
|
+
td.actions
|
51
|
+
min-width: 112px
|
52
|
+
padding-right: 3px
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module DocContract
|
2
|
+
module SharedTemplateAndInstanceMethods
|
3
|
+
# POST /doc-contract/contract_templates/:id/processed_markdown?markdown=...
|
4
|
+
def processed_markdown
|
5
|
+
@record = record_class.find params[:id]
|
6
|
+
authorize! :show, @record
|
7
|
+
# Allow preview using the markdown parameter. Fallback to actual saved
|
8
|
+
# version when param is not given
|
9
|
+
@record.markdown = params[:markdown] if params[:markdown].present?
|
10
|
+
render json: {markdown: @record.processed_markdown}
|
11
|
+
end
|
12
|
+
|
13
|
+
def processed_html
|
14
|
+
@record = record_class.find params[:id]
|
15
|
+
authorize! :show, @record
|
16
|
+
# Allow preview using the markdown parameter. Fallback to actual saved
|
17
|
+
# version when param is not given
|
18
|
+
@record.markdown = params[:markdown] if params[:markdown].present?
|
19
|
+
render json: {html: @record.processed_html}
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_pdf
|
23
|
+
@record = record_class.find params[:id]
|
24
|
+
authorize! :show, @record
|
25
|
+
# Allow preview using the markdown parameter. Fallback to actual saved
|
26
|
+
# version when param is not given
|
27
|
+
@record.markdown = params[:markdown] if params[:markdown].present?
|
28
|
+
@tempfile_markdown = Tempfile.new(['pandoc-markdown', '.md'])
|
29
|
+
config_addittions = {}
|
30
|
+
if nbackground = @record.try(:titlepage_background) || @record.contract_template.titlepage_background.presence
|
31
|
+
config_addittions['titlepage-background'] = "vendor/assets/doc-contract/titlepage-backgrounds/background#{nbackground}.pdf"
|
32
|
+
end
|
33
|
+
template_markdown = @record.template_markdown(config_addittions)
|
34
|
+
@tempfile_markdown.write template_markdown
|
35
|
+
#@tempfile_markdown.rewind
|
36
|
+
@tempfile_markdown.close
|
37
|
+
@tempfile_pdf = Tempfile.create(['pandoc-pdf-', '.pdf'])
|
38
|
+
@tempfile_pdf.close
|
39
|
+
command = %( pandoc --template=vendor/assets/doc-contract/pandoc-templates/eisvogel.tex --css=app/assets/stylesheets/doc_contract/pandoc.css #{@tempfile_markdown.path} -o #{@tempfile_pdf.path} )
|
40
|
+
command << " --variable top-level-division=chapter" if @record.config['book']
|
41
|
+
#command << " --variable titlepage=true" if false # done through YAML config
|
42
|
+
command << " --listings" # if some conditions TODO: make this a database boolean
|
43
|
+
command << " --filter pandoc-latex-environment" if template_markdown['pandoc-latex-environment:']
|
44
|
+
|
45
|
+
stdout, stderr, status = nil
|
46
|
+
Dir.chdir DocContract::Engine.root do
|
47
|
+
stdout, stderr, status = Open3.capture3(command)
|
48
|
+
end
|
49
|
+
if status.success?
|
50
|
+
send_file @tempfile_pdf.path
|
51
|
+
else
|
52
|
+
redirect_back fallback_location: record_class, flash: {error: stderr}
|
53
|
+
end
|
54
|
+
ensure
|
55
|
+
@tempfile_markdown.unlink rescue nil
|
56
|
+
@tempfile_pdf.unlink rescue nil
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def record_class
|
62
|
+
result = controller_path.classify.safe_constantize
|
63
|
+
raise "Cannot determine record_class from controller_path: #{controller_path}" unless result
|
64
|
+
result
|
65
|
+
end
|
66
|
+
|
67
|
+
def record_params
|
68
|
+
params.require(record_class.name.demodulize.underscore).permit!
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module DocContract
|
2
|
+
class ApplicationController < ApplicationController
|
3
|
+
helper_method :query, :readme_html
|
4
|
+
def main
|
5
|
+
end
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def query
|
10
|
+
params[:q]
|
11
|
+
end
|
12
|
+
|
13
|
+
def readme_html
|
14
|
+
result = DocContract::Engine.root.join('README.md').read
|
15
|
+
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, tables: true, fenced_code_blocks: true)
|
16
|
+
markdown.render result
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module DocContract
|
2
|
+
class ContractInstancesController < ApplicationController
|
3
|
+
include SharedTemplateAndInstanceMethods
|
4
|
+
helper_method :record_class
|
5
|
+
respond_to :html
|
6
|
+
|
7
|
+
def index
|
8
|
+
authorize! :index, record_class
|
9
|
+
@q = record_class.search query
|
10
|
+
@q.sorts = "created_at desc" if @q.sorts.empty?
|
11
|
+
@records = @q.result.includes(:contract_template).page(params[:page]).per(100)
|
12
|
+
respond_with(@records)
|
13
|
+
end
|
14
|
+
|
15
|
+
def new
|
16
|
+
@record = record_class.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def edit
|
20
|
+
@record = record_class.find(params[:id])
|
21
|
+
authorize! :edit, @record
|
22
|
+
end
|
23
|
+
|
24
|
+
def create
|
25
|
+
authorize! :create, record_class
|
26
|
+
@record = record_class.new record_params
|
27
|
+
if @record.save
|
28
|
+
redirect_to @record
|
29
|
+
else
|
30
|
+
render :new, status: :unprocessable_entity
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def update
|
35
|
+
@record = record_class.find params[:id]
|
36
|
+
authorize! :update, @record
|
37
|
+
if @record.update record_params
|
38
|
+
redirect_to @record
|
39
|
+
else
|
40
|
+
render :edit, status: :unprocessable_entity
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def show
|
45
|
+
@record = record_class.find params[:id]
|
46
|
+
authorize! :show, @record
|
47
|
+
end
|
48
|
+
|
49
|
+
def destroy
|
50
|
+
@record = record_class.find params[:id]
|
51
|
+
authorize! :destroy, @record
|
52
|
+
@record.destroy
|
53
|
+
redirect_to record_class
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module DocContract
|
2
|
+
class ContractTemplatesController < ApplicationController
|
3
|
+
include SharedTemplateAndInstanceMethods
|
4
|
+
helper_method :record_class
|
5
|
+
respond_to :html
|
6
|
+
|
7
|
+
def index
|
8
|
+
authorize! :index, record_class
|
9
|
+
@q = record_class.search query
|
10
|
+
@q.sorts = 'created_at desc' if @q.sorts.empty?
|
11
|
+
@records = @q.result.page(params[:page]).per(100)
|
12
|
+
respond_with(@records)
|
13
|
+
end
|
14
|
+
|
15
|
+
def new
|
16
|
+
@record = record_class.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def edit
|
20
|
+
@record = record_class.find(params[:id])
|
21
|
+
authorize! :edit, @record
|
22
|
+
end
|
23
|
+
|
24
|
+
def create
|
25
|
+
authorize! :create, record_class
|
26
|
+
@record = record_class.new record_params
|
27
|
+
if @record.save
|
28
|
+
redirect_to @record, status: :see_other
|
29
|
+
else
|
30
|
+
render action: 'new'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def update
|
35
|
+
@record = record_class.find params[:id]
|
36
|
+
authorize! :update, @record
|
37
|
+
if @record.update record_params
|
38
|
+
redirect_to @record, status: :see_other
|
39
|
+
else
|
40
|
+
render action: 'edit'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def show
|
45
|
+
@record = record_class.find params[:id]
|
46
|
+
authorize! :show, @record
|
47
|
+
end
|
48
|
+
|
49
|
+
def destroy
|
50
|
+
@record = record_class.find params[:id]
|
51
|
+
authorize! :destroy, @record
|
52
|
+
@record.destroy
|
53
|
+
redirect_to record_class, status: :see_other
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def record_class
|
59
|
+
result = controller_path.classify.safe_constantize
|
60
|
+
raise "Cannot determine record_class from controller_path: #{controller_path}" unless result
|
61
|
+
|
62
|
+
result
|
63
|
+
end
|
64
|
+
|
65
|
+
def record_params
|
66
|
+
params.require(record_class.name.demodulize.underscore).permit!
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|