doc_contract 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
![Scheme](/spec/dummy/public/DocContract-scheme.png)
|
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
|
+
![Edit template scnreenshot](/spec/dummy/public/DocContract-template-edit.png)
|
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
|