lato 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 +95 -0
- data/Rakefile +8 -0
- data/app/assets/config/lato_manifest.js +5 -0
- data/app/assets/images/lato/user-150x150.jpg +0 -0
- data/app/assets/images/lato/user-300x300.jpg +0 -0
- data/app/assets/images/lato/user-600x600.jpg +0 -0
- data/app/assets/images/lato/user-900x900.jpg +0 -0
- data/app/assets/javascripts/lato/application.js +6 -0
- data/app/assets/javascripts/lato/controllers/application.js +9 -0
- data/app/assets/javascripts/lato/controllers/index.js +11 -0
- data/app/assets/javascripts/lato/controllers/lato_action_controller.js +92 -0
- data/app/assets/javascripts/lato/controllers/lato_aside_opener_controller.js +21 -0
- data/app/assets/javascripts/lato/controllers/lato_feedback_controller.js +13 -0
- data/app/assets/javascripts/lato/controllers/lato_form_controller.js +60 -0
- data/app/assets/javascripts/lato/controllers/lato_hello_controller.js +12 -0
- data/app/assets/javascripts/lato/controllers/lato_operation_controller.js +24 -0
- data/app/assets/stylesheets/lato/application.scss +73 -0
- data/app/controllers/concerns/lato/componentable.rb +52 -0
- data/app/controllers/concerns/lato/layoutable.rb +27 -0
- data/app/controllers/concerns/lato/sessionable.rb +45 -0
- data/app/controllers/lato/account_controller.rb +82 -0
- data/app/controllers/lato/application_controller.rb +21 -0
- data/app/controllers/lato/authentication_controller.rb +121 -0
- data/app/controllers/lato/operations_controller.rb +23 -0
- data/app/helpers/lato/application_helper.rb +5 -0
- data/app/helpers/lato/components_helper.rb +183 -0
- data/app/jobs/lato/application_job.rb +59 -0
- data/app/mailers/lato/application_mailer.rb +6 -0
- data/app/mailers/lato/user_mailer.rb +23 -0
- data/app/models/lato/application_record.rb +5 -0
- data/app/models/lato/operation.rb +96 -0
- data/app/models/lato/session.rb +36 -0
- data/app/models/lato/user.rb +164 -0
- data/app/views/lato/account/_alert-accepted-privacy-policy-version.html.erb +20 -0
- data/app/views/lato/account/_alert-accepted-terms-and-conditions-version.html.erb +20 -0
- data/app/views/lato/account/_form-destroy.html.erb +21 -0
- data/app/views/lato/account/_form-password.html.erb +28 -0
- data/app/views/lato/account/_form-user.html.erb +40 -0
- data/app/views/lato/account/index.html.erb +65 -0
- data/app/views/lato/authentication/_form-recover-password.html.erb +20 -0
- data/app/views/lato/authentication/_form-signin.html.erb +31 -0
- data/app/views/lato/authentication/_form-signup.html.erb +47 -0
- data/app/views/lato/authentication/_form-update-password.html.erb +30 -0
- data/app/views/lato/authentication/_form-verify-email.html.erb +22 -0
- data/app/views/lato/authentication/recover_password.html.erb +13 -0
- data/app/views/lato/authentication/signin.html.erb +13 -0
- data/app/views/lato/authentication/signout.html.erb +11 -0
- data/app/views/lato/authentication/signup.html.erb +13 -0
- data/app/views/lato/authentication/update_password.html.erb +13 -0
- data/app/views/lato/authentication/verify_email.html.erb +7 -0
- data/app/views/lato/components/_index.html.erb +89 -0
- data/app/views/lato/components/_navbar_nav_item.html.erb +5 -0
- data/app/views/lato/components/_operation.html.erb +68 -0
- data/app/views/lato/components/_page_head.html.erb +15 -0
- data/app/views/lato/components/_sidebar_nav_item.html.erb +5 -0
- data/app/views/lato/mailer/user/email_verification_mail.html.erb +9 -0
- data/app/views/lato/mailer/user/password_update_mail.html.erb +9 -0
- data/app/views/lato/operations/show.html.erb +3 -0
- data/app/views/layouts/lato/_action.html.erb +17 -0
- data/app/views/layouts/lato/_aside-opener.html.erb +7 -0
- data/app/views/layouts/lato/_content.html.erb +5 -0
- data/app/views/layouts/lato/_feedbacks.html.erb +16 -0
- data/app/views/layouts/lato/_footer.html.erb +11 -0
- data/app/views/layouts/lato/_mailer-foot_content.html.erb +2 -0
- data/app/views/layouts/lato/_mailer-head_content.html.erb +2 -0
- data/app/views/layouts/lato/_navbar-brand_content.html.erb +1 -0
- data/app/views/layouts/lato/_navbar-nav_content.html.erb +15 -0
- data/app/views/layouts/lato/_navbar.html.erb +16 -0
- data/app/views/layouts/lato/_sidebar-nav_content.html.erb +3 -0
- data/app/views/layouts/lato/_sidebar.html.erb +5 -0
- data/app/views/layouts/lato/application.html.erb +44 -0
- data/app/views/layouts/lato/mailer.html.erb +3 -0
- data/config/importmap.rb +8 -0
- data/config/locales/it.yml +235 -0
- data/config/routes.rb +35 -0
- data/db/migrate/20221022205744_create_lato_users.rb +14 -0
- data/db/migrate/20221118072130_create_lato_operations.rb +14 -0
- data/lib/lato/btstrap.rb +36 -0
- data/lib/lato/config.rb +39 -0
- data/lib/lato/engine.rb +13 -0
- data/lib/lato/version.rb +3 -0
- data/lib/lato.rb +27 -0
- data/lib/tasks/lato_tasks.rake +28 -0
- metadata +199 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0d0fcbdd5ba0523af03858edd0646045fabe36a832f39c3420c60745d4794ef6
|
4
|
+
data.tar.gz: 6debf36698efb7f3e2a64963b22679725c0db5f0561bf79c0f39aa1b017e8705
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ad25978acd813be6f01c18d48e5c4baeb6976770d99206175c0ba2ea4244a8e1b50a6f2943bc405a29921f64b24c3cfbee4068970b0ce9e8cd9bc681336d6adc
|
7
|
+
data.tar.gz: '0735888ffc4bbfcd489729f684e558affa2b2843e10cdb2aeebb8f442c7a0f3159b0f7319f8180a3dc9255a588a1fed406adc38063f1f9de4b9b419899d8276a'
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2022 Gregorio Galante
|
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,95 @@
|
|
1
|
+
# Lato
|
2
|
+
Basic engine for all Lato projects.
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
Add required dependencies to your application's Gemfile:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
# Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]
|
9
|
+
gem "importmap-rails" # NOTE: Probably already installed in default rails 7 project
|
10
|
+
|
11
|
+
# Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]
|
12
|
+
gem "turbo-rails" # NOTE: Probably already installed in default rails 7 project
|
13
|
+
|
14
|
+
# Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]
|
15
|
+
gem "stimulus-rails" # NOTE: Probably already installed in default rails 7 project
|
16
|
+
|
17
|
+
# Use Kredis as Redis interface [https://github.com/rails/kredis]
|
18
|
+
# NOTE: Installation -> https://github.com/rails/kredis#installation
|
19
|
+
gem "kredis"
|
20
|
+
|
21
|
+
# Use Sass to process CSS
|
22
|
+
gem "sassc-rails"
|
23
|
+
|
24
|
+
# Use lato as application panel
|
25
|
+
gem "lato"
|
26
|
+
```
|
27
|
+
|
28
|
+
Install gem and run required tasks:
|
29
|
+
|
30
|
+
```bash
|
31
|
+
$ bundle
|
32
|
+
$ rails active_storage:install
|
33
|
+
$ rails lato:install:application
|
34
|
+
$ rails lato:install:migrations
|
35
|
+
$ rails db:migrate
|
36
|
+
```
|
37
|
+
|
38
|
+
Mount lato routes on the **config/routes.rb** file:
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
Rails.application.routes.draw do
|
42
|
+
mount Lato::Engine => "/lato"
|
43
|
+
|
44
|
+
# ....
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
Import Lato Scss on **app/assets/stylesheets/application.scss** file:
|
49
|
+
```scss
|
50
|
+
@import 'lato/application';
|
51
|
+
|
52
|
+
// ....
|
53
|
+
```
|
54
|
+
|
55
|
+
Import Lato Js on **app/javascript/application.js** file:
|
56
|
+
```js
|
57
|
+
import "lato/application";
|
58
|
+
|
59
|
+
// ....
|
60
|
+
```
|
61
|
+
|
62
|
+
Setup italian locale to the application (currently Lato works with IT locale) on the **config/application.rb** file:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
module MyApplication
|
66
|
+
class Application < Rails::Application
|
67
|
+
config.i18n.available_locales = [:it]
|
68
|
+
config.i18n.default_locale = :it
|
69
|
+
|
70
|
+
# ...
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
```
|
75
|
+
|
76
|
+
## Development
|
77
|
+
|
78
|
+
Be sure to have Redis locally installed and running.
|
79
|
+
|
80
|
+
Clone repository, install dependencies, run migrations and start:
|
81
|
+
|
82
|
+
```shell
|
83
|
+
$ git clone https://github.com/Lato-GAM/lato
|
84
|
+
$ cd lato
|
85
|
+
$ bundle
|
86
|
+
$ rails db:migrate
|
87
|
+
$ foreman start -f Procfile.dev
|
88
|
+
```
|
89
|
+
|
90
|
+
## License
|
91
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
92
|
+
|
93
|
+
## To do
|
94
|
+
- Gestione abbonamenti e acquisti singoli con integrazione Stripe
|
95
|
+
- Gestione input file operazione
|
data/Rakefile
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,11 @@
|
|
1
|
+
// Import and register all your controllers from the importmap under controllers/*
|
2
|
+
|
3
|
+
import { application } from "controllers/application"
|
4
|
+
|
5
|
+
// Eager load all controllers defined in the import map under controllers/**/*_controller
|
6
|
+
// import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading"
|
7
|
+
// eagerLoadControllersFrom("controllers", application)
|
8
|
+
|
9
|
+
// Lazy load controllers as they appear in the DOM (remember not to preload controllers in import map!)
|
10
|
+
import { lazyLoadControllersFrom } from "@hotwired/stimulus-loading"
|
11
|
+
lazyLoadControllersFrom("controllers", application)
|
@@ -0,0 +1,92 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
static targets = [
|
5
|
+
'trigger',
|
6
|
+
'modal',
|
7
|
+
'modalBody',
|
8
|
+
'modalTitle',
|
9
|
+
'modalDialog'
|
10
|
+
]
|
11
|
+
|
12
|
+
/**
|
13
|
+
* Stimulus
|
14
|
+
*/
|
15
|
+
|
16
|
+
connect() {
|
17
|
+
this.bsModals = []
|
18
|
+
this.usedModals = []
|
19
|
+
|
20
|
+
this.modalTargets.forEach((modalTarget, index) => {
|
21
|
+
this.bsModals.push(new bootstrap.Modal(modalTarget))
|
22
|
+
|
23
|
+
modalTarget.addEventListener('show.bs.modal', () => {
|
24
|
+
this.usedModals.push(index)
|
25
|
+
})
|
26
|
+
modalTarget.addEventListener('hide.bs.modal', () => {
|
27
|
+
this.usedModals = this.usedModals.filter((i) => i != index)
|
28
|
+
this.modalBodyTargets[index].innerHTML = ''
|
29
|
+
})
|
30
|
+
})
|
31
|
+
}
|
32
|
+
|
33
|
+
disconnect() {
|
34
|
+
this.bsModals.forEach((bsModal) => {
|
35
|
+
bsModal.dispose()
|
36
|
+
})
|
37
|
+
}
|
38
|
+
|
39
|
+
triggerTargetConnected(element) {
|
40
|
+
element.addEventListener('click', (e) => this.openAction(this.loadOptionsFromTriggerElement(element)))
|
41
|
+
}
|
42
|
+
|
43
|
+
/**
|
44
|
+
* Functions
|
45
|
+
*/
|
46
|
+
|
47
|
+
openAction(options) {
|
48
|
+
const index = this.getFreeModalIndex()
|
49
|
+
|
50
|
+
if (options.turboFrame && options.turboFrame != '_top') {
|
51
|
+
this.modalBodyTargets[index].innerHTML = `<turbo-frame id="${options.turboFrame}"></turbo-frame>`
|
52
|
+
|
53
|
+
if (options.actionTitle) {
|
54
|
+
this.modalTitleTargets[index].innerHTML = options.actionTitle
|
55
|
+
} else {
|
56
|
+
this.modalTitleTargets[index].innerHTML = ''
|
57
|
+
}
|
58
|
+
|
59
|
+
if (options.actionSize) {
|
60
|
+
this.modalDialogTargets[index].classList.add(`modal-${options.actionSize}`)
|
61
|
+
} else {
|
62
|
+
this.modalDialogTargets[index].classList.remove('modal-lg')
|
63
|
+
this.modalDialogTargets[index].classList.remove('modal-xl')
|
64
|
+
this.modalDialogTargets[index].classList.remove('modal-sm')
|
65
|
+
}
|
66
|
+
|
67
|
+
this.bsModals[index].show()
|
68
|
+
}
|
69
|
+
}
|
70
|
+
|
71
|
+
loadOptionsFromTriggerElement(element) {
|
72
|
+
const options = {}
|
73
|
+
options.turboFrame = element.getAttribute('data-turbo-frame')
|
74
|
+
options.actionTitle = element.getAttribute('data-action-title')
|
75
|
+
options.actionSize = element.getAttribute('data-action-size')
|
76
|
+
return options
|
77
|
+
}
|
78
|
+
|
79
|
+
getFreeModalIndex() {
|
80
|
+
for (let i = 0; i < this.modalTargets.length; i++) {
|
81
|
+
if (!this.usedModals.includes(i)) return i
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
/**
|
86
|
+
* Actions
|
87
|
+
*/
|
88
|
+
|
89
|
+
onTriggerClick(e) {
|
90
|
+
this.openAction(this.loadOptionsFromTriggerElement(e.currentTarget))
|
91
|
+
}
|
92
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
|
5
|
+
/**
|
6
|
+
* Functions
|
7
|
+
*/
|
8
|
+
|
9
|
+
toggle() {
|
10
|
+
document.body.classList.toggle('aside-open')
|
11
|
+
}
|
12
|
+
|
13
|
+
/**
|
14
|
+
* Actions
|
15
|
+
*/
|
16
|
+
|
17
|
+
onClickToggle(e) {
|
18
|
+
e.preventDefault()
|
19
|
+
document.body.classList.toggle('aside-open')
|
20
|
+
}
|
21
|
+
}
|
@@ -0,0 +1,60 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
static targets = [
|
5
|
+
'submit',
|
6
|
+
'input'
|
7
|
+
]
|
8
|
+
|
9
|
+
/**
|
10
|
+
* Stimulus
|
11
|
+
*/
|
12
|
+
|
13
|
+
connect() {
|
14
|
+
this.originalFormData = this.loadFormData()
|
15
|
+
this.disableSubmit()
|
16
|
+
}
|
17
|
+
|
18
|
+
/**
|
19
|
+
* Functions
|
20
|
+
*/
|
21
|
+
|
22
|
+
disableSubmit() {
|
23
|
+
if (!this.hasSubmitTarget) return
|
24
|
+
this.submitTarget.setAttribute('disabled', true)
|
25
|
+
}
|
26
|
+
|
27
|
+
enableSubmit() {
|
28
|
+
if (!this.hasSubmitTarget) return
|
29
|
+
this.submitTarget.removeAttribute('disabled')
|
30
|
+
}
|
31
|
+
|
32
|
+
loadFormData() {
|
33
|
+
const formData = {}
|
34
|
+
|
35
|
+
this.inputTargets.forEach((input) => {
|
36
|
+
if (input.type == 'checkbox') {
|
37
|
+
formData[input.name] = input.checked
|
38
|
+
} else {
|
39
|
+
formData[input.name] = input.value
|
40
|
+
}
|
41
|
+
})
|
42
|
+
|
43
|
+
return formData
|
44
|
+
}
|
45
|
+
|
46
|
+
/**
|
47
|
+
* Actions
|
48
|
+
*/
|
49
|
+
|
50
|
+
onInputChange(e) {
|
51
|
+
e.target.classList.remove('is-invalid')
|
52
|
+
|
53
|
+
const formData = this.loadFormData()
|
54
|
+
if (JSON.stringify(formData) != JSON.stringify(this.originalFormData)) {
|
55
|
+
this.enableSubmit()
|
56
|
+
} else {
|
57
|
+
this.disableSubmit()
|
58
|
+
}
|
59
|
+
}
|
60
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
static targets = [
|
5
|
+
'update',
|
6
|
+
'outputFile'
|
7
|
+
]
|
8
|
+
|
9
|
+
/**
|
10
|
+
* Stimulus
|
11
|
+
*/
|
12
|
+
|
13
|
+
connect() {
|
14
|
+
if (this.hasUpdateTarget) {
|
15
|
+
setTimeout(() => {
|
16
|
+
this.updateTarget.click()
|
17
|
+
}, 2000)
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
outputFileTargetConnected(element) {
|
22
|
+
element.click()
|
23
|
+
}
|
24
|
+
}
|
@@ -0,0 +1,73 @@
|
|
1
|
+
/** Import dependencies */
|
2
|
+
|
3
|
+
@import url("https://cdn.jsdelivr.net/npm/bootstrap-icons@1.9.1/font/bootstrap-icons.css");
|
4
|
+
@import "bootstrap";
|
5
|
+
|
6
|
+
/** Turbo loading **/
|
7
|
+
|
8
|
+
.turbo-progress-bar {
|
9
|
+
background-color: $primary;
|
10
|
+
}
|
11
|
+
|
12
|
+
/** Pagination (minimal style for gem kaminari) */
|
13
|
+
|
14
|
+
.pagination {}
|
15
|
+
|
16
|
+
.pagination > span {
|
17
|
+
display: inline-block;
|
18
|
+
margin: 0 4px;
|
19
|
+
}
|
20
|
+
|
21
|
+
.pagination .current {
|
22
|
+
font-weight: bold;
|
23
|
+
}
|
24
|
+
|
25
|
+
/** Custom style */
|
26
|
+
|
27
|
+
main {
|
28
|
+
width: 100%;
|
29
|
+
}
|
30
|
+
|
31
|
+
main, aside {
|
32
|
+
margin-top: 54px;
|
33
|
+
min-height: calc(100vh - 54px);
|
34
|
+
}
|
35
|
+
|
36
|
+
.aside-opener {
|
37
|
+
display: none;
|
38
|
+
}
|
39
|
+
|
40
|
+
@media screen and (max-width: 768px) {
|
41
|
+
aside {
|
42
|
+
position: fixed;
|
43
|
+
bottom: 0;
|
44
|
+
left: 0;
|
45
|
+
width: 100%;
|
46
|
+
height: calc(100% - 54px);
|
47
|
+
z-index: 99;
|
48
|
+
transform: translateX(-100%);
|
49
|
+
transition: transform 0.35s ease-in-out;
|
50
|
+
|
51
|
+
.aside-open & {
|
52
|
+
transform: translateX(0);
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
.aside-opener {
|
57
|
+
display: flex;
|
58
|
+
position: fixed;
|
59
|
+
bottom: 15px;
|
60
|
+
right: 15px;
|
61
|
+
z-index: 100;
|
62
|
+
background-color: $primary;
|
63
|
+
color: $white;
|
64
|
+
border: none;
|
65
|
+
padding: 0;
|
66
|
+
width: 60px;
|
67
|
+
height: 60px;
|
68
|
+
font-size: 20px;
|
69
|
+
justify-content: center;
|
70
|
+
align-items: center;
|
71
|
+
border-radius: 50%;
|
72
|
+
}
|
73
|
+
}
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Lato
|
2
|
+
module Componentable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
def lato_index_collection(collection, options = {})
|
6
|
+
# load options
|
7
|
+
# NOTE: instance variables are for options used by "lato_index" component helper
|
8
|
+
key = options[:key] || 'default'
|
9
|
+
pagination = options[:pagination] || false
|
10
|
+
@_lato_index ||= {}
|
11
|
+
@_lato_index[key] = {
|
12
|
+
columns: options[:columns] || collection.column_names || [],
|
13
|
+
sortable_columns: options[:sortable_columns] || [],
|
14
|
+
searchable_columns: options[:searchable_columns] || []
|
15
|
+
}
|
16
|
+
|
17
|
+
# manage sort by parameter
|
18
|
+
unless params[:sort_by].blank?
|
19
|
+
sort_by_splitted = params[:sort_by].split('|')
|
20
|
+
sort_by_column = sort_by_splitted.first
|
21
|
+
sort_by_order = sort_by_splitted.last
|
22
|
+
|
23
|
+
if collection.respond_to?(:lato_index_order)
|
24
|
+
collection = collection.lato_index_order(sort_by_column.to_sym, sort_by_order.to_sym)
|
25
|
+
else
|
26
|
+
collection = collection.order("#{sort_by_column} #{sort_by_order}")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# manage search by parameter
|
31
|
+
unless params[:search].blank?
|
32
|
+
search = params[:search].to_s
|
33
|
+
if collection.respond_to?(:lato_index_search)
|
34
|
+
collection = collection.lato_index_search(search)
|
35
|
+
else
|
36
|
+
query = @_lato_index[key][:searchable_columns].map { |k| "lower(#{k}) LIKE :search" }
|
37
|
+
collection = collection.where(query.join(' OR '), search: "%#{search.downcase.strip}%")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# manage pagination
|
42
|
+
if pagination || params[:page] || params[:per_page]
|
43
|
+
page = params[:page]&.to_i || 1
|
44
|
+
per_page = params[:per_page]&.to_i || 25
|
45
|
+
per_page = 100 if per_page > 100
|
46
|
+
collection = collection.page(page).per(per_page)
|
47
|
+
end
|
48
|
+
|
49
|
+
collection
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Lato
|
2
|
+
module Layoutable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
before_action do
|
7
|
+
show_sidebar
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def show_sidebar
|
12
|
+
@layout_sidebar = true
|
13
|
+
end
|
14
|
+
|
15
|
+
def hide_sidebar
|
16
|
+
@layout_sidebar = false
|
17
|
+
end
|
18
|
+
|
19
|
+
def active_sidebar(key)
|
20
|
+
@sidebar_key = key
|
21
|
+
end
|
22
|
+
|
23
|
+
def active_navbar(key)
|
24
|
+
@navbar_key = key
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Lato
|
2
|
+
module Sessionable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
before_action do
|
7
|
+
@session = Lato::Session.new(cookies.encrypted[:lato_session])
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def authenticate_session
|
12
|
+
return true if @session.valid?
|
13
|
+
|
14
|
+
respond_to do |format|
|
15
|
+
format.html { redirect_to lato.root_path }
|
16
|
+
format.json { render plain: '', status: :unauthorized }
|
17
|
+
end
|
18
|
+
|
19
|
+
false
|
20
|
+
end
|
21
|
+
|
22
|
+
def not_authenticate_session
|
23
|
+
return true unless @session.valid?
|
24
|
+
|
25
|
+
respond_to do |format|
|
26
|
+
format.html { redirect_to lato.root_path }
|
27
|
+
format.json { render plain: '', status: :unauthorized }
|
28
|
+
end
|
29
|
+
|
30
|
+
false
|
31
|
+
end
|
32
|
+
|
33
|
+
def session_create(user_id)
|
34
|
+
cookies.encrypted[:lato_session] = { value: Lato::Session.generate_session_per_user(user_id), expires: Lato.config.session_lifetime.from_now }
|
35
|
+
|
36
|
+
true
|
37
|
+
end
|
38
|
+
|
39
|
+
def session_destroy
|
40
|
+
cookies.encrypted[:lato_session] = nil
|
41
|
+
|
42
|
+
true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Lato
|
2
|
+
class AccountController < ApplicationController
|
3
|
+
before_action :authenticate_session
|
4
|
+
before_action { active_navbar(:account) }
|
5
|
+
|
6
|
+
def index; end
|
7
|
+
|
8
|
+
def update_user_action
|
9
|
+
respond_to do |format|
|
10
|
+
if @session.user.update(params.require(:user).permit(:first_name, :last_name, :email))
|
11
|
+
format.html { redirect_to lato.account_path, notice: 'Informazioni account aggiornate correttamente' }
|
12
|
+
format.json { render json: @session.user }
|
13
|
+
else
|
14
|
+
format.html { render :index, status: :unprocessable_entity }
|
15
|
+
format.json { render json: @session.user.errors, status: :unprocessable_entity }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def request_verify_email_action
|
21
|
+
respond_to do |format|
|
22
|
+
if @session.user.request_verify_email
|
23
|
+
format.html { redirect_to lato.account_path, notice: 'Ti abbiamo inviato una email con i passaggi da seguire per completare la procedura' }
|
24
|
+
format.json { render json: @session.user }
|
25
|
+
else
|
26
|
+
format.html { render :index, status: :unprocessable_entity }
|
27
|
+
format.json { render json: @session.user.errors, status: :unprocessable_entity }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def update_password_action
|
33
|
+
respond_to do |format|
|
34
|
+
if @session.user.update(params.require(:user).permit(:password, :password_confirmation))
|
35
|
+
format.html { redirect_to lato.account_path, notice: 'Password aggiornate correttamente' }
|
36
|
+
format.json { render json: @session.user }
|
37
|
+
else
|
38
|
+
format.html { render :index, status: :unprocessable_entity }
|
39
|
+
format.json { render json: @session.user.errors, status: :unprocessable_entity }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def destroy_action
|
45
|
+
respond_to do |format|
|
46
|
+
if @session.user.destroy_with_confirmation(params.require(:user).permit(:email_confirmation))
|
47
|
+
session_destroy
|
48
|
+
|
49
|
+
format.html { redirect_to lato.root_path }
|
50
|
+
format.json { render json: {} }
|
51
|
+
else
|
52
|
+
format.html { render :index, status: :unprocessable_entity }
|
53
|
+
format.json { render json: @session.user.errors, status: :unprocessable_entity }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def update_accepted_privacy_policy_version_action
|
59
|
+
respond_to do |format|
|
60
|
+
if @session.user.update(params.require(:user).permit(:accepted_privacy_policy_version))
|
61
|
+
format.html { redirect_to lato.account_path }
|
62
|
+
format.json { render json: @session.user }
|
63
|
+
else
|
64
|
+
format.html { render :index, status: :unprocessable_entity }
|
65
|
+
format.json { render json: @session.user.errors, status: :unprocessable_entity }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def update_accepted_terms_and_conditions_version_action
|
71
|
+
respond_to do |format|
|
72
|
+
if @session.user.update(params.require(:user).permit(:accepted_terms_and_conditions_version))
|
73
|
+
format.html { redirect_to lato.account_path }
|
74
|
+
format.json { render json: @session.user }
|
75
|
+
else
|
76
|
+
format.html { render :index, status: :unprocessable_entity }
|
77
|
+
format.json { render json: @session.user.errors, status: :unprocessable_entity }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|