maquina 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 +28 -0
- data/Rakefile +8 -0
- data/app/assets/images/maquina/maquina.svg +18 -0
- data/app/assets/javascripts/maquina/application.js +4 -0
- data/app/assets/javascripts/maquina/controllers/alert_controller.js +29 -0
- data/app/assets/javascripts/maquina/controllers/application.js +9 -0
- data/app/assets/javascripts/maquina/controllers/file_controller.js +60 -0
- data/app/assets/javascripts/maquina/controllers/index.js +11 -0
- data/app/assets/javascripts/maquina/controllers/mobile_menu_controller.js +31 -0
- data/app/assets/javascripts/maquina/controllers/modal_controller.js +39 -0
- data/app/assets/javascripts/maquina/controllers/modal_open_controller.js +15 -0
- data/app/assets/javascripts/maquina/controllers/popup_menu_controller.js +17 -0
- data/app/assets/javascripts/maquina/controllers/submit_form_controller.js +11 -0
- data/app/assets/stylesheets/maquina/application.css +15 -0
- data/app/assets/stylesheets/maquina/application.tailwind.css +102 -0
- data/app/controllers/concerns/maquina/authenticate.rb +41 -0
- data/app/controllers/concerns/maquina/create.rb +27 -0
- data/app/controllers/concerns/maquina/destroy.rb +28 -0
- data/app/controllers/concerns/maquina/edit.rb +29 -0
- data/app/controllers/concerns/maquina/index.rb +33 -0
- data/app/controllers/concerns/maquina/new.rb +22 -0
- data/app/controllers/concerns/maquina/resourceful.rb +180 -0
- data/app/controllers/concerns/maquina/show.rb +27 -0
- data/app/controllers/concerns/maquina/update.rb +31 -0
- data/app/controllers/maquina/accept_invitations_controller.rb +28 -0
- data/app/controllers/maquina/application_controller.rb +19 -0
- data/app/controllers/maquina/dashboard_controller.rb +16 -0
- data/app/controllers/maquina/invitations_controller.rb +51 -0
- data/app/controllers/maquina/plans_controller.rb +56 -0
- data/app/controllers/maquina/sessions_controller.rb +56 -0
- data/app/controllers/maquina/unauthorized_controller.rb +9 -0
- data/app/controllers/maquina/users_controller.rb +24 -0
- data/app/helpers/maquina/application_helper.rb +19 -0
- data/app/helpers/maquina/navbar_menu_helper.rb +29 -0
- data/app/helpers/maquina/views_helper.rb +9 -0
- data/app/jobs/maquina/application_job.rb +4 -0
- data/app/mailers/maquina/application_mailer.rb +8 -0
- data/app/mailers/maquina/user_notifications_mailer.rb +16 -0
- data/app/models/concerns/maquina/authenticate_by.rb +33 -0
- data/app/models/concerns/maquina/blockeable.rb +28 -0
- data/app/models/concerns/maquina/multifactor.rb +80 -0
- data/app/models/concerns/maquina/retain_passwords.rb +32 -0
- data/app/models/concerns/maquina/searchable.rb +24 -0
- data/app/models/maquina/active_session.rb +33 -0
- data/app/models/maquina/application_record.rb +11 -0
- data/app/models/maquina/current.rb +21 -0
- data/app/models/maquina/invitation.rb +15 -0
- data/app/models/maquina/plan.rb +38 -0
- data/app/models/maquina/used_password.rb +17 -0
- data/app/models/maquina/user.rb +33 -0
- data/app/policies/maquina/application_policy.rb +50 -0
- data/app/policies/maquina/invitation_policy.rb +13 -0
- data/app/policies/maquina/navigation_policy.rb +13 -0
- data/app/policies/maquina/plan_policy.rb +49 -0
- data/app/policies/maquina/user_policy.rb +27 -0
- data/app/views/layouts/maquina/application.html.erb +26 -0
- data/app/views/layouts/maquina/mailer.html.erb +377 -0
- data/app/views/layouts/maquina/mailer.text.erb +12 -0
- data/app/views/layouts/maquina/sessions.html.erb +24 -0
- data/app/views/maquina/accept_invitations/new.html.erb +9 -0
- data/app/views/maquina/accept_invitations/new_view.rb +41 -0
- data/app/views/maquina/application/_navbar.html.erb +21 -0
- data/app/views/maquina/application/alert.rb +104 -0
- data/app/views/maquina/application/components/action_text_component.rb +20 -0
- data/app/views/maquina/application/components/checkbox_component.rb +21 -0
- data/app/views/maquina/application/components/component_base.rb +60 -0
- data/app/views/maquina/application/components/file_component.rb +59 -0
- data/app/views/maquina/application/components/input_component.rb +20 -0
- data/app/views/maquina/application/components/select_component.rb +44 -0
- data/app/views/maquina/application/create.turbo_stream.erb +11 -0
- data/app/views/maquina/application/edit.html.erb +9 -0
- data/app/views/maquina/application/edit.rb +17 -0
- data/app/views/maquina/application/form.rb +77 -0
- data/app/views/maquina/application/index.html.erb +10 -0
- data/app/views/maquina/application/index_header.rb +46 -0
- data/app/views/maquina/application/index_modal.rb +43 -0
- data/app/views/maquina/application/index_table.rb +121 -0
- data/app/views/maquina/application/new.html.erb +9 -0
- data/app/views/maquina/application/new.rb +18 -0
- data/app/views/maquina/application/sessions_header.rb +31 -0
- data/app/views/maquina/application/show.html.erb +1 -0
- data/app/views/maquina/application/update.turbo_stream.erb +11 -0
- data/app/views/maquina/application_view.rb +46 -0
- data/app/views/maquina/dashboard/index.html.erb +0 -0
- data/app/views/maquina/invitations/create.turbo_stream.erb +13 -0
- data/app/views/maquina/invitations/new.html.erb +3 -0
- data/app/views/maquina/navbar/menu.rb +62 -0
- data/app/views/maquina/navbar/menu_item_link.rb +34 -0
- data/app/views/maquina/navbar/mobile_button.rb +29 -0
- data/app/views/maquina/navbar/mobile_menu.rb +47 -0
- data/app/views/maquina/navbar/notification.rb +37 -0
- data/app/views/maquina/navbar/profile.rb +16 -0
- data/app/views/maquina/navbar/profile_button.rb +24 -0
- data/app/views/maquina/navbar/profile_menu.rb +108 -0
- data/app/views/maquina/navbar/profile_menu_item_link.rb +41 -0
- data/app/views/maquina/navbar/search.rb +40 -0
- data/app/views/maquina/navbar/title.rb +22 -0
- data/app/views/maquina/sessions/create.turbo_stream.erb +11 -0
- data/app/views/maquina/sessions/form.rb +56 -0
- data/app/views/maquina/sessions/new.html.erb +9 -0
- data/app/views/maquina/unauthorized/401.html.erb +1 -0
- data/app/views/maquina/user_notifications_mailer/invitation_email.html.erb +40 -0
- data/app/views/maquina/user_notifications_mailer/invitation_email.text.erb +12 -0
- data/config/definitions.rb +1 -0
- data/config/initializers/importmap.rb +17 -0
- data/config/initializers/money.rb +116 -0
- data/config/initializers/pagy.rb +235 -0
- data/config/locales/flash.en.yml +44 -0
- data/config/locales/forms.en.yml +58 -0
- data/config/locales/mailers.en.yml +35 -0
- data/config/locales/models.en.yml +34 -0
- data/config/locales/routes.en.yml +7 -0
- data/config/locales/views.en.yml +45 -0
- data/config/routes.rb +17 -0
- data/db/migrate/20221109010726_create_maquina_plans.rb +13 -0
- data/db/migrate/20221113000409_create_maquina_users.rb +19 -0
- data/db/migrate/20221113020108_create_maquina_used_passwords.rb +10 -0
- data/db/migrate/20221115223414_create_maquina_active_sessions.rb +15 -0
- data/db/migrate/20230201203922_create_maquina_invitations.rb +12 -0
- data/db/schema.rb +1 -0
- data/lib/generators/maquina/install_generator.rb +32 -0
- data/lib/generators/maquina/install_templates/install_templates_generator.rb +31 -0
- data/lib/generators/maquina/tailwind_config/tailwind_config_generator.rb +11 -0
- data/lib/generators/maquina/tailwind_config/templates/app/assets/config/maquina/tailwind.config.js.tt +68 -0
- data/lib/generators/maquina/templates/config/initializers/maquina.rb +3 -0
- data/lib/maquina/engine.rb +17 -0
- data/lib/maquina/version.rb +3 -0
- data/lib/maquina.rb +48 -0
- data/lib/tasks/install.rake +19 -0
- data/lib/tasks/maquina_tasks.rake +4 -0
- data/lib/tasks/tailwind.rake +25 -0
- metadata +456 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e5dffb067d8cdaf6d56c9777275907b321ec48188950945521a44d4d48fd92a2
|
4
|
+
data.tar.gz: 28a3e313221bd3f2e465ba565e5e493ba3ccc419512c7f5f59d80353a0d45168
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2b4517a5605cd8245948afec893c75b60fdc522d56982d76928726fdcf797e2552a026321f2e24d2ab8a7387e8de01158a10065300d4914f5d07cf4b1df0c3d7
|
7
|
+
data.tar.gz: cb442f6712c58691771d8b01f99d22038c9491b92c5cf324860d5e250b692d749c67254184194de8d2b0132fb9339d32f17ebe6976c9eacd30a903a87bf098a7
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2022 Mario Alberto Chávez
|
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,28 @@
|
|
1
|
+
# Maquina
|
2
|
+
Short description and motivation.
|
3
|
+
|
4
|
+
## Usage
|
5
|
+
How to use my plugin.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem "maquina"
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
```bash
|
16
|
+
$ bundle
|
17
|
+
```
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
```bash
|
21
|
+
$ gem install maquina
|
22
|
+
```
|
23
|
+
|
24
|
+
## Contributing
|
25
|
+
Contribution directions go here.
|
26
|
+
|
27
|
+
## License
|
28
|
+
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,18 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<svg version="1.1" viewBox="0 0 486 486" xmlns="http://www.w3.org/2000/svg">
|
3
|
+
<title>Maquina</title>
|
4
|
+
<defs>
|
5
|
+
<linearGradient id="a" x1="21.152%" y1="21.848%" y2="93.468%">
|
6
|
+
<stop stop-color="#50B1FD" stop-opacity=".96" offset="0"/>
|
7
|
+
<stop stop-color="#DE77DE" stop-opacity=".96" offset="1"/>
|
8
|
+
</linearGradient>
|
9
|
+
</defs>
|
10
|
+
<g fill="none" fill-rule="evenodd">
|
11
|
+
<g transform="translate(-13 -13)">
|
12
|
+
<g transform="translate(13 13)">
|
13
|
+
<circle cx="243" cy="243" r="243" fill="url(#a)"/>
|
14
|
+
<path d="m238.9 47.002 3.4301 0.016598v30.431c-108.78 8.7223-163.18 71.895-163.18 189.52l54.567-31.709c3.7144-56.281 50.542-100.78 107.76-100.78 10.162 0 19.996 1.4034 29.319 4.0271 0.78425-57.904 1.3072-88.259 1.5685-91.068 161.58 36.443 197.13 192.94 138.54 291.1-4.3817-2.5298-13.063-7.5417-26.354-15.216 46.838-98.57 19.325-177.26-82.539-236.07l0.18734 65.903c28.537 19.437 47.276 52.193 47.276 89.325 0 30.25-12.436 57.595-32.475 77.201 49.541 28.346 75.468 43.309 77.781 44.887-110.21 123.65-264.32 78.878-321.77-19.957 4.3369-2.6059 12.929-7.7686 26.085-15.673 63.504 88.753 145.67 102.84 246.49 42.26l-57.118-31.449c-14.207 6.876-30.149 10.731-46.991 10.731-50.271 0-92.52-34.347-104.56-80.855-49.09 27.458-74.899 41.768-77.424 42.929-48.243-154.99 63.879-262.81 175.97-265.5l3.4312-0.04945zm3.0839 149.47c-25.681 0-46.5 20.819-46.5 46.5s20.819 46.5 46.5 46.5c25.681 0 46.5-20.819 46.5-46.5s-20.819-46.5-46.5-46.5z" fill="#fff"/>
|
15
|
+
</g>
|
16
|
+
</g>
|
17
|
+
</g>
|
18
|
+
</svg>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
import { useTransition } from "stimulus-use"
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Alert Controller
|
6
|
+
*
|
7
|
+
* Cuando hay información en el objeto Flash de Rails se muestra con una animación
|
8
|
+
* el mensaje y desaparece solo después de 10 segundos o cerrándolo con la X.
|
9
|
+
*/
|
10
|
+
|
11
|
+
export default class extends Controller {
|
12
|
+
static targets = ["alert"];
|
13
|
+
|
14
|
+
connect() {
|
15
|
+
let element = this.element;
|
16
|
+
if (this.hasAlertTarget) {
|
17
|
+
element = this.alertTarget
|
18
|
+
}
|
19
|
+
useTransition(this, { element: element })
|
20
|
+
|
21
|
+
this.enter()
|
22
|
+
|
23
|
+
setTimeout(this.close.bind(this), 10000)
|
24
|
+
}
|
25
|
+
|
26
|
+
close() {
|
27
|
+
this.leave()
|
28
|
+
}
|
29
|
+
}
|
@@ -0,0 +1,60 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
static targets = ["fileInput", "container", "preview", "placeholder"]
|
5
|
+
static values = { maxSize: Number, image: String, validationMessage: String }
|
6
|
+
|
7
|
+
connect() {
|
8
|
+
if (this.hasFileInputTarget) {
|
9
|
+
this.fileInputTarget.addEventListener("change", this.fileSelected.bind(this))
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
disconnect() {
|
14
|
+
if (this.hasFileInputTarget) {
|
15
|
+
this.fileInputTarget.removeEventListener("change", this.fileSelected.bind(this))
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
select(event) {
|
20
|
+
event.preventDefault();
|
21
|
+
this.fileInputTarget.click();
|
22
|
+
}
|
23
|
+
|
24
|
+
fileSelected(event) {
|
25
|
+
if (event.target.files.length > 0) {
|
26
|
+
this.containerTarget.querySelectorAll(".help-error").forEach(error => error.remove())
|
27
|
+
this.validateFile(event.target.files[0])
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
validateFile(file) {
|
32
|
+
if (file.size > this.maxSizeValue) {
|
33
|
+
this.fileInputTarget.value = ""
|
34
|
+
this.addError()
|
35
|
+
this.clearPreview()
|
36
|
+
} else {
|
37
|
+
this.loadPreview(file)
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
addError() {
|
42
|
+
const messageNode = document.createElement("p");
|
43
|
+
messageNode.classList.add("help", "help-error");
|
44
|
+
messageNode.innerText = this.validationMessageValue;
|
45
|
+
|
46
|
+
this.containerTarget.appendChild(messageNode)
|
47
|
+
}
|
48
|
+
|
49
|
+
clearPreview() {
|
50
|
+
this.previewTarget.classList.add("hidden")
|
51
|
+
this.placeholderTarget.classList.remove("hidden")
|
52
|
+
this.previewTarget.setAttribute("src", "")
|
53
|
+
}
|
54
|
+
|
55
|
+
loadPreview(file) {
|
56
|
+
this.previewTarget.setAttribute("src", URL.createObjectURL(file))
|
57
|
+
this.previewTarget.classList.remove("hidden")
|
58
|
+
this.placeholderTarget.classList.add("hidden")
|
59
|
+
}
|
60
|
+
}
|
@@ -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,31 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
import { useClickOutside, useTransition } from "stimulus-use"
|
3
|
+
|
4
|
+
export default class extends Controller {
|
5
|
+
static targets = ["menu", "open", "close"]
|
6
|
+
|
7
|
+
connect() {
|
8
|
+
useClickOutside(this);
|
9
|
+
useTransition(this, { element: this.menuTarget })
|
10
|
+
}
|
11
|
+
|
12
|
+
toggle() {
|
13
|
+
this.toggleTransition();
|
14
|
+
}
|
15
|
+
|
16
|
+
clickOutside() {
|
17
|
+
if (!this.menuTarget.classList.contains("hidden")) {
|
18
|
+
this.toggleTransition();
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
enter() {
|
23
|
+
this.openTarget.classList.toggle("hidden")
|
24
|
+
this.closeTarget.classList.toggle("hidden")
|
25
|
+
}
|
26
|
+
|
27
|
+
leave() {
|
28
|
+
this.openTarget.classList.toggle("hidden")
|
29
|
+
this.closeTarget.classList.toggle("hidden")
|
30
|
+
}
|
31
|
+
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
import { useTransition } from "stimulus-use"
|
3
|
+
|
4
|
+
export default class extends Controller {
|
5
|
+
static targets = ["content", "container", "frame"]
|
6
|
+
|
7
|
+
connect() {
|
8
|
+
useTransition(this, { element: this.contentTarget })
|
9
|
+
|
10
|
+
this.resultCallback = this.modalResult.bind(this)
|
11
|
+
addEventListener("turbo:submit-end", this.resultCallback)
|
12
|
+
}
|
13
|
+
|
14
|
+
disconnect() {
|
15
|
+
removeEventListener("turbo:submit-end", this.resultCallback)
|
16
|
+
}
|
17
|
+
|
18
|
+
modalResult(event) {
|
19
|
+
if (event.detail.fetchResponse.response.status == 202) {
|
20
|
+
this.toggleModal(event)
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
toggleModal(event) {
|
25
|
+
event.preventDefault()
|
26
|
+
|
27
|
+
if (this.hasFrameTarget && this.contentTarget.classList.contains("hidden")) {
|
28
|
+
let url = event["detail"]["src"] || this.element.dataset["frameSrc"]
|
29
|
+
this.frameTarget.setAttribute("src", url)
|
30
|
+
} else if (!this.contentTarget.classList.contains("hidden")) {
|
31
|
+
this.frameTarget.setAttribute("src", "")
|
32
|
+
this.frameTarget.innerText = ""
|
33
|
+
}
|
34
|
+
|
35
|
+
document.documentElement.classList.toggle("overflow-hidden")
|
36
|
+
this.containerTarget.classList.toggle("hidden")
|
37
|
+
this.toggleTransition()
|
38
|
+
}
|
39
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus";
|
2
|
+
import { useDispatch } from "stimulus-use";
|
3
|
+
|
4
|
+
export default class extends Controller {
|
5
|
+
static targets = [];
|
6
|
+
|
7
|
+
connect() {
|
8
|
+
useDispatch(this)
|
9
|
+
}
|
10
|
+
|
11
|
+
open(event) {
|
12
|
+
event.preventDefault();
|
13
|
+
this.dispatch("toggle", {src: event.target.getAttribute("href")});
|
14
|
+
}
|
15
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus";
|
2
|
+
import { useClickOutside, useTransition } from "stimulus-use"
|
3
|
+
|
4
|
+
export default class extends Controller {
|
5
|
+
static targets = ["menu"];
|
6
|
+
|
7
|
+
connect() {
|
8
|
+
useClickOutside(this);
|
9
|
+
useTransition(this, { element: this.menuTarget })
|
10
|
+
}
|
11
|
+
|
12
|
+
clickOutside() {
|
13
|
+
if (!this.menuTarget.classList.contains("hidden")) {
|
14
|
+
this.toggleTransition();
|
15
|
+
}
|
16
|
+
}
|
17
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,102 @@
|
|
1
|
+
@tailwind base;
|
2
|
+
@tailwind components;
|
3
|
+
@tailwind utilities;
|
4
|
+
|
5
|
+
/* @layer base { */
|
6
|
+
:root {
|
7
|
+
--color-base: 31 27 54;
|
8
|
+
--color-accented: 37 99 235;
|
9
|
+
--color-inverted: 255 255 255;
|
10
|
+
--color-accented-hover: 59 130 246;
|
11
|
+
--color-muted: 55 65 81;
|
12
|
+
--color-dimmed: 75 85 99;
|
13
|
+
--color-error: 220 38 38;
|
14
|
+
|
15
|
+
--color-border-base: 209 213 219;
|
16
|
+
--color-border-accented: 37 99 235;
|
17
|
+
}
|
18
|
+
|
19
|
+
.label {
|
20
|
+
@apply text-sm font-medium text-skin-muted;
|
21
|
+
}
|
22
|
+
|
23
|
+
.input {
|
24
|
+
@apply appearance-none rounded-md border border-skin-base px-3 py-2 placeholder-gray-400 shadow-sm focus:border-skin-accented focus:outline-none focus:ring-skin-accented sm:text-sm;
|
25
|
+
}
|
26
|
+
|
27
|
+
.link {
|
28
|
+
@apply font-medium text-skin-accented hover:text-skin-accented-hover;
|
29
|
+
}
|
30
|
+
|
31
|
+
.check {
|
32
|
+
@apply border-skin-base h-4 w-4 text-skin-accented focus:ring-skin-accented rounded;
|
33
|
+
}
|
34
|
+
|
35
|
+
.button {
|
36
|
+
@apply inline-flex justify-center py-2 px-4 border border-skin-base rounded-md shadow-sm text-sm font-medium text-skin-muted bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-skin-accented;
|
37
|
+
}
|
38
|
+
|
39
|
+
.control-error .label {
|
40
|
+
@apply text-skin-error;
|
41
|
+
}
|
42
|
+
|
43
|
+
.control-error .input {
|
44
|
+
@apply border-skin-error focus:border-skin-error focus:ring-skin-error;
|
45
|
+
}
|
46
|
+
|
47
|
+
.help {
|
48
|
+
@apply mt-2 text-sm text-skin-dimmed;
|
49
|
+
}
|
50
|
+
|
51
|
+
.help-error {
|
52
|
+
@apply text-skin-error;
|
53
|
+
}
|
54
|
+
|
55
|
+
.button[disabled] {
|
56
|
+
@apply bg-gray-50 text-skin-dimmed cursor-default;
|
57
|
+
}
|
58
|
+
|
59
|
+
.button-accented {
|
60
|
+
@apply rounded-md border border-transparent bg-skin-accented py-2 px-4 text-sm font-medium text-skin-inverted shadow-sm hover:bg-skin-accented-hover focus:outline-none focus:ring-2 focus:ring-skin-accented focus:ring-offset-2;
|
61
|
+
}
|
62
|
+
|
63
|
+
input[type="search"] {
|
64
|
+
@apply block w-full rounded-md border border-skin-base pl-10 leading-5 placeholder-gray-400 focus:placeholder-gray-300 focus:outline-none focus:ring-1 focus:ring-skin-accented focus:border-skin-accented sm:text-sm;
|
65
|
+
}
|
66
|
+
|
67
|
+
.desktop-menu {
|
68
|
+
@apply hidden lg:ml-6 lg:flex lg:space-x-8;
|
69
|
+
}
|
70
|
+
|
71
|
+
.desktop-menu-item {
|
72
|
+
@apply font-sans uppercase border-transparent text-skin-dimmed underline-offset-4 decoration-2 hover:underline hover:decoration-skin-accented hover:text-skin-muted inline-flex items-center px-1 pt-1 text-sm font-medium;
|
73
|
+
}
|
74
|
+
|
75
|
+
.desktop-menu-item__active {
|
76
|
+
@apply decoration-skin-accented underline text-skin-base;
|
77
|
+
}
|
78
|
+
|
79
|
+
.mobile-menu {
|
80
|
+
@apply pt-2 pb-3 space-y-1;
|
81
|
+
}
|
82
|
+
|
83
|
+
.mobile-menu-item {
|
84
|
+
@apply font-sans border-transparent text-skin-dimmed hover:bg-gray-200 hover:border-gray-300 hover:text-skin-muted block pl-3 pr-4 py-2 border-l-4 text-base font-medium;
|
85
|
+
}
|
86
|
+
|
87
|
+
.mobile-menu-item__active {
|
88
|
+
@apply bg-skin-accented-hover border-skin-accented text-skin-accented hover:text-skin-accented hover:bg-skin-accented-hover hover:border-skin-accented;
|
89
|
+
}
|
90
|
+
|
91
|
+
.desktop-profile-menu-item {
|
92
|
+
@apply block w-full text-left font-sans px-4 py-2 text-sm text-skin-dimmed hover:bg-gray-200 hover:text-skin-muted;
|
93
|
+
}
|
94
|
+
|
95
|
+
.mobile-profile-menu-item {
|
96
|
+
@apply block font-sans px-4 py-2 text-base font-medium text-skin-dimmed hover:text-skin-muted hover:bg-gray-200;
|
97
|
+
}
|
98
|
+
|
99
|
+
.mobile-button {
|
100
|
+
@apply inline-flex items-center justify-center p-2 rounded-md text-skin-dimmed hover:text-skin-muted hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-skin-accented;
|
101
|
+
}
|
102
|
+
/* } */
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Maquina
|
4
|
+
module Authenticate
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
helper_method :signed_in?, :current_user
|
9
|
+
end
|
10
|
+
|
11
|
+
def authenticate!
|
12
|
+
load_session
|
13
|
+
|
14
|
+
redirect_to maquina.new_sessions_path if !signed_in?
|
15
|
+
end
|
16
|
+
|
17
|
+
def signed_in?
|
18
|
+
load_session if Maquina::Current.active_session.blank?
|
19
|
+
|
20
|
+
Maquina::Current.signed_in?
|
21
|
+
end
|
22
|
+
|
23
|
+
def current_user
|
24
|
+
load_session if Maquina::Current.active_session.blank?
|
25
|
+
|
26
|
+
Maquina::Current.user
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def load_session
|
32
|
+
active_session_id = session["--active_session"]
|
33
|
+
return if active_session_id.blank?
|
34
|
+
|
35
|
+
active_session = ActiveSession.eager_load(:user).find_by(id: active_session_id)
|
36
|
+
return if active_session.blank?
|
37
|
+
|
38
|
+
Maquina::Current.active_session = active_session
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Maquina
|
4
|
+
module Create
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
def create(&block)
|
9
|
+
authorize! with: policy_class if policy_class.present?
|
10
|
+
|
11
|
+
@resource ||= begin
|
12
|
+
resource = resource_class.new(resource_secure_params)
|
13
|
+
resource.save
|
14
|
+
|
15
|
+
resource
|
16
|
+
end
|
17
|
+
|
18
|
+
@status = @resource.errors.empty? ? :created : :unprocessable_entity
|
19
|
+
response.status = @status
|
20
|
+
set_flash_message(@status)
|
21
|
+
|
22
|
+
dual_action_response(@resource, &block)
|
23
|
+
end
|
24
|
+
alias_method :create!, :create
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Maquina
|
4
|
+
module Destroy
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
def destroy(&block)
|
9
|
+
@resource ||= begin
|
10
|
+
scope = resource_class
|
11
|
+
# TODO: Implement policy authorization (ActionPolicy)
|
12
|
+
# scope = scope.where(organization)
|
13
|
+
# TODO: Implement filtering by organization
|
14
|
+
scope.find_by!(find_by_param => params[:id])
|
15
|
+
end
|
16
|
+
|
17
|
+
@resource.destroy
|
18
|
+
|
19
|
+
status = :no_content
|
20
|
+
response.status = status
|
21
|
+
set_flash_message(status)
|
22
|
+
|
23
|
+
dual_action_response(@resource, &block)
|
24
|
+
end
|
25
|
+
alias_method :destroy!, :destroy
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Maquina
|
4
|
+
module Edit
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
def edit(&block)
|
9
|
+
@resource ||= begin
|
10
|
+
scope = resource_class
|
11
|
+
# TODO: Implement filtering by organization
|
12
|
+
# scope = scope.where(organization)
|
13
|
+
scope = yield(scope) if block.present?
|
14
|
+
|
15
|
+
resource = scope.find_by!(find_by_param => params[:id])
|
16
|
+
|
17
|
+
authorize! resource, with: policy_class if policy_class.present?
|
18
|
+
|
19
|
+
resource
|
20
|
+
end
|
21
|
+
|
22
|
+
respond_to do |format|
|
23
|
+
format.html
|
24
|
+
end
|
25
|
+
end
|
26
|
+
alias_method :edit!, :edit
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Maquina
|
4
|
+
module Index
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
include Pagy::Backend
|
7
|
+
|
8
|
+
included do
|
9
|
+
def index(&block)
|
10
|
+
authorize! with: policy_class if policy_class.present?
|
11
|
+
|
12
|
+
@collection ||= begin
|
13
|
+
scope = resource_class.order(updated_at: :desc)
|
14
|
+
scope = authorized_scope(scope) if policy_class.present?
|
15
|
+
|
16
|
+
search_value = params[:q]&.strip
|
17
|
+
scope = scope.search_full(search_value) if search_value.present?
|
18
|
+
|
19
|
+
scope = yield(scope) if block.present?
|
20
|
+
|
21
|
+
@pagination, record = pagy(scope)
|
22
|
+
record
|
23
|
+
end
|
24
|
+
|
25
|
+
respond_to do |format|
|
26
|
+
format.html { render :index }
|
27
|
+
format.json { render json: collection }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
alias_method :index!, :index
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Maquina
|
4
|
+
module New
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
def new(&block)
|
9
|
+
authorize! with: policy_class if policy_class.present?
|
10
|
+
|
11
|
+
# TODO: Implement filtering by organization
|
12
|
+
@resource = resource_class.new
|
13
|
+
@resource = yield(@resource) if block.present?
|
14
|
+
|
15
|
+
respond_to do |format|
|
16
|
+
format.html
|
17
|
+
end
|
18
|
+
end
|
19
|
+
alias_method :new!, :new
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|