satis 2.1.46 → 2.1.47
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/satis/application.css +1 -0
- data/app/components/satis/attachments/component.css +136 -0
- data/app/components/satis/attachments/component.html.slim +26 -0
- data/app/components/satis/attachments/component.rb +34 -0
- data/app/components/satis/attachments/create.json.jbuilder +5 -0
- data/app/components/satis/card/component.css +2 -2
- data/app/components/satis/card/component.html.slim +1 -1
- data/app/components/satis/dropdown/component_controller.js +2 -5
- data/app/components/satis/editor/component.css +1 -1
- data/app/components/satis/sidebar_menu_item/component.css +4 -0
- data/app/components/satis/tabs/component.html.slim +1 -1
- data/app/controllers/satis/attachments_controller.rb +35 -0
- data/app/helpers/satis/application_helper.rb +0 -8
- data/app/javascript/satis/controllers/attachment_delete_controller.js +49 -0
- data/app/javascript/satis/controllers/attachment_upload_controller.js +109 -0
- data/app/javascript/satis/controllers/index.js +7 -0
- data/config/routes.rb +2 -0
- data/lib/satis/helpers/container.rb +1 -0
- data/lib/satis/version.rb +1 -1
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b4aa4a7fdd94865ec844e8389cee2d3d19009f817a48d48bdb5e44b1ab7d12f
|
4
|
+
data.tar.gz: 6b6eaa2df3376c21b24bd32ef981963c1a6c6a564f6a7ccb2f8ffa8fe51d699f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3bf96d40e2775fb1042a21be50b0796db96d424a8bd2414934e246675ac60bb8cdadd55b27cb82b232f9f6d0e1bd961e154cf9e44902f14732dbd747fd23cff
|
7
|
+
data.tar.gz: 8ebb4d890726d4e1e3d76b65650091bbafa273e7756c01835f30aec4157e1c488539cd04e971158e96aa7b7651f1c50264ac64cf0ed4daa0c638c8a16bd41d03
|
@@ -1,4 +1,5 @@
|
|
1
1
|
@import '../../../components/satis/appearance_switcher/component.css';
|
2
|
+
@import '../../../components/satis/attachments/component.css';
|
2
3
|
@import '../../../components/satis/breadcrumbs/component.css';
|
3
4
|
@import '../../../components/satis/card/component.css';
|
4
5
|
@import '../../../components/satis/call_to_action/component.css';
|
@@ -0,0 +1,136 @@
|
|
1
|
+
.attachments__group {
|
2
|
+
@apply grid gap-6 mt-10 justify-start;
|
3
|
+
grid-template-columns: repeat(auto-fill, 200px);
|
4
|
+
}
|
5
|
+
|
6
|
+
.attachments__attachment {
|
7
|
+
@apply relative w-[200px] h-[200px] bg-cover bg-center bg-no-repeat rounded-lg shadow-md overflow-hidden;
|
8
|
+
@apply dark:bg-gray-900;
|
9
|
+
}
|
10
|
+
|
11
|
+
.attachments__attachment:hover {
|
12
|
+
@apply opacity-90;
|
13
|
+
}
|
14
|
+
|
15
|
+
.attachments__attachment .attachments__button {
|
16
|
+
@apply hidden absolute top-2.5 bg-white bg-opacity-80 p-1.5 rounded-full;
|
17
|
+
@apply dark:bg-gray-700 dark:text-white;
|
18
|
+
}
|
19
|
+
|
20
|
+
.attachments__attachment .attachments__button:first-of-type {
|
21
|
+
@apply left-2.5;
|
22
|
+
}
|
23
|
+
|
24
|
+
.attachments__attachment .attachments__button:last-of-type {
|
25
|
+
@apply right-2.5;
|
26
|
+
}
|
27
|
+
|
28
|
+
.attachments__attachment:hover .attachments__button {
|
29
|
+
@apply block;
|
30
|
+
}
|
31
|
+
|
32
|
+
.attachments__attachment .attachments__filename {
|
33
|
+
@apply hidden absolute bottom-0 left-0 right-0 bg-black bg-opacity-70 text-white p-1.5 text-center text-xs;
|
34
|
+
@apply dark:bg-gray-900 dark:bg-opacity-90;
|
35
|
+
}
|
36
|
+
|
37
|
+
.attachments__attachment:hover .attachments__filename {
|
38
|
+
@apply block;
|
39
|
+
}
|
40
|
+
|
41
|
+
.preview-text {
|
42
|
+
@apply absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-white bg-opacity-70 p-2.5 rounded text-sm text-gray-800;
|
43
|
+
@apply dark:bg-gray-800 dark:bg-opacity-70 dark:text-gray-200;
|
44
|
+
}
|
45
|
+
|
46
|
+
@media (max-width: 640px) {
|
47
|
+
.attachments__group {
|
48
|
+
grid-template-columns: repeat(auto-fill, 150px);
|
49
|
+
}
|
50
|
+
|
51
|
+
.attachments__attachment {
|
52
|
+
@apply w-[150px] h-[150px];
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
.icon.uploading {
|
57
|
+
display: none; /* Ensure this is hidden by default */
|
58
|
+
}
|
59
|
+
|
60
|
+
.uploading .icon.uploading {
|
61
|
+
display: inline-block; /* Show only when uploading */
|
62
|
+
}
|
63
|
+
|
64
|
+
.icon.upload {
|
65
|
+
display: inline-block; /* Ensure the upload icon is visible */
|
66
|
+
}
|
67
|
+
|
68
|
+
.uploading .icon.upload {
|
69
|
+
display: none; /* Hide the upload icon during upload */
|
70
|
+
}
|
71
|
+
|
72
|
+
.attachment-upload-button {
|
73
|
+
display: inline-block;
|
74
|
+
}
|
75
|
+
|
76
|
+
.upload-btn {
|
77
|
+
@apply dark:bg-gray-900 dark:text-white;
|
78
|
+
align-items: center;
|
79
|
+
padding: 10px 15px;
|
80
|
+
background-color: #f0f0f0;
|
81
|
+
border: 2px dashed #ccc;
|
82
|
+
border-radius: 5px;
|
83
|
+
cursor: pointer;
|
84
|
+
transition: all 0.3s ease;
|
85
|
+
font-family: Arial, sans-serif;
|
86
|
+
color: #333;
|
87
|
+
}
|
88
|
+
|
89
|
+
.upload-btn:hover {
|
90
|
+
@apply dark:bg-gray-900 dark:text-white dark:border-gray-700;
|
91
|
+
background-color: #e0e0e0;
|
92
|
+
border-color: #999;
|
93
|
+
}
|
94
|
+
|
95
|
+
.upload-btn:focus {
|
96
|
+
outline: none;
|
97
|
+
box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.5);
|
98
|
+
}
|
99
|
+
|
100
|
+
.upload-btn .icon {
|
101
|
+
margin-right: 10px;
|
102
|
+
font-size: 18px;
|
103
|
+
}
|
104
|
+
|
105
|
+
.upload-btn .icon.upload {
|
106
|
+
color: #4a90e2;
|
107
|
+
}
|
108
|
+
|
109
|
+
.upload-btn .icon.uploading {
|
110
|
+
display: none;
|
111
|
+
color: #f39c12;
|
112
|
+
}
|
113
|
+
|
114
|
+
.uploading .upload-btn .icon.upload {
|
115
|
+
display: none;
|
116
|
+
}
|
117
|
+
|
118
|
+
.uploading .upload-btn .icon.uploading {
|
119
|
+
display: inline-block;
|
120
|
+
}
|
121
|
+
|
122
|
+
.upload-btn .button-text {
|
123
|
+
font-size: 14px;
|
124
|
+
}
|
125
|
+
|
126
|
+
.dragging .upload-btn {
|
127
|
+
background-color: #e8f0fe;
|
128
|
+
border-color: #4285f4;
|
129
|
+
}
|
130
|
+
|
131
|
+
.uploading .upload-btn {
|
132
|
+
@apply dark:bg-gray-800 dark:border-gray-600 dark:text-white;
|
133
|
+
background-color: #fcf8e3;
|
134
|
+
border-color: #f39c12;
|
135
|
+
cursor: not-allowed;
|
136
|
+
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
div.attachment-upload.upload-btn data-controller="attachment-upload" data-attachment-upload-url="#{Satis::Engine.routes.url_helpers.attachments_path(sgid: model_sgid, attribute: attribute)}" data-attachment-upload-param-name="attachments[]"data-attachment-upload-extra-data='{}' data-turbo="true" turbo-method="post"
|
2
|
+
span.icon.upload
|
3
|
+
i.fas.fa-upload
|
4
|
+
span.icon.uploading
|
5
|
+
i.fal.fa-circle-notch.fa-spin
|
6
|
+
span.button-text Drag or click to attach files
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
div.attachments__group
|
11
|
+
- attachments = model_has_images ? model.images : model.attachments
|
12
|
+
- attachments.each do |attachment|
|
13
|
+
div.attachments__attachment(style= attachment_style(attachment))
|
14
|
+
- unless attachment.representable?
|
15
|
+
div.preview-text
|
16
|
+
i.fas.fa-file(aria-hidden="true")
|
17
|
+
|
18
|
+
= link_to Satis::Engine.routes.url_helpers.attachment_path(attachment, sgid: model_sgid, attribute: attribute), data: {turbo_method: :delete, turbo_confirm: "Are you sure you want to delete this attachment?"}, class: 'attachments__button' do
|
19
|
+
i.fas.fa-xmark
|
20
|
+
|
21
|
+
|
22
|
+
= link_to Rails.application.routes.url_helpers.rails_blob_url(attachment, host: request.host + ":#{request.port}"), data: { turbo: true, turbolinks: false }, class: 'attachments__button', download: true do
|
23
|
+
i.fas.fa-download
|
24
|
+
|
25
|
+
span.attachments__filename
|
26
|
+
= attachment.filename
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Satis
|
2
|
+
module Attachments
|
3
|
+
class Component < Satis::ApplicationComponent
|
4
|
+
include Rails.application.routes.url_helpers
|
5
|
+
|
6
|
+
attr_reader :model, :attribute, :attachments_options
|
7
|
+
|
8
|
+
def initialize(model, attribute, **options)
|
9
|
+
super()
|
10
|
+
@model = model
|
11
|
+
@attribute = attribute
|
12
|
+
@attachments_options = options
|
13
|
+
end
|
14
|
+
|
15
|
+
def model_has_images
|
16
|
+
model.respond_to?(:images)
|
17
|
+
end
|
18
|
+
|
19
|
+
def attachment_style(attachment)
|
20
|
+
if attachment.representable?
|
21
|
+
url = attachment.representation(resize_to_limit: [200, 200]).processed.url
|
22
|
+
"background-image: url(#{url})"
|
23
|
+
else
|
24
|
+
"background-color: f0f0f0"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def model_sgid
|
30
|
+
@model.to_sgid(expires_in: nil, for: 'satis_attachments')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -2,11 +2,11 @@
|
|
2
2
|
@apply bg-white h-full sm:rounded-lg sm:shadow dark:bg-gray-800 overflow-hidden;
|
3
3
|
|
4
4
|
&__header {
|
5
|
-
@apply px-4 py-5 sm:px-6 dark:bg-gray-900 dark:border-gray-700 dark:text-gray-300;
|
5
|
+
@apply px-4 py-5 sm:px-6 dark:bg-gray-900 bg-white dark:border-gray-700 dark:text-gray-300;
|
6
6
|
}
|
7
7
|
|
8
8
|
&__tabs {
|
9
|
-
@apply bg-white px-4 border-b border-gray-200 sm:px-5 dark:bg-gray-900 dark:border-gray-700 dark:text-gray-300;
|
9
|
+
@apply bg-white px-4 border-b border-gray-200 sm:px-5 bg-white dark:bg-gray-900 dark:border-gray-700 dark:text-gray-300;
|
10
10
|
|
11
11
|
a:first {
|
12
12
|
@apply ml-4;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
.sts-card data-controller="satis-tabs" data-satis-tabs-persist-value=persist data-satis-tabs-key-value=key id=identifier
|
2
2
|
- if header?
|
3
|
-
.sts-card__header class="#{tabs? ? '' : 'border-b border-gray-200'}
|
3
|
+
.sts-card__header class="#{tabs? ? '' : 'border-b border-gray-200'}"
|
4
4
|
.-ml-4.-mt-4.flex.justify-between.items-center.flex-wrap.sm:flex-nowrap
|
5
5
|
- if icon
|
6
6
|
.ml-4.mt-4.flex-shrink-0.text-primary-600.dark:text-gray-300
|
@@ -520,9 +520,7 @@ export default class DropdownComponentController extends ApplicationController {
|
|
520
520
|
let matches = []
|
521
521
|
this.itemTargets.forEach((item) => {
|
522
522
|
const text = item.getAttribute("data-satis-dropdown-item-text")
|
523
|
-
const matched = this.needsExactMatchValue ?
|
524
|
-
searchValue.localeCompare(text, undefined, {sensitivity: 'base'}) === 0:
|
525
|
-
new RegExp(searchValue, "i").test(text)
|
523
|
+
const matched = this.needsExactMatchValue ? searchValue.localeCompare(text, undefined, {sensitivity: 'base'}) === 0 : text.toLowerCase().includes(searchValue.toLowerCase())
|
526
524
|
|
527
525
|
const isHidden = item.classList.contains("hidden")
|
528
526
|
if (!isHidden) {
|
@@ -622,8 +620,7 @@ export default class DropdownComponentController extends ApplicationController {
|
|
622
620
|
this.itemTargets.forEach((item) => {
|
623
621
|
const text = item.getAttribute("data-satis-dropdown-item-text")
|
624
622
|
const matched = this.needsExactMatchValue
|
625
|
-
? searchValue.localeCompare(text, undefined, { sensitivity: "base" }) === 0
|
626
|
-
: new RegExp(searchValue, "i").test(text)
|
623
|
+
? searchValue.localeCompare(text, undefined, { sensitivity: "base" }) === 0 : text.toLowerCase().includes(searchValue.toLowerCase())
|
627
624
|
|
628
625
|
const isHidden = item.classList.contains("hidden")
|
629
626
|
if (!isHidden) {
|
@@ -39,6 +39,10 @@
|
|
39
39
|
display: none;
|
40
40
|
}
|
41
41
|
|
42
|
+
.sidebar.close .sts-sidebar-menu-item:hover > .sts-sidebar-menu-item__link {
|
43
|
+
width: 40px;
|
44
|
+
}
|
45
|
+
|
42
46
|
|
43
47
|
.sidebar.close .sts-sidebar-menu-item [data-satis-sidebar-menu-item-target="submenu"] .sts-sidebar-menu-item{
|
44
48
|
display: none;
|
@@ -5,7 +5,7 @@
|
|
5
5
|
- tabs.each do |tab|
|
6
6
|
option selected=tab.selected? = ct(".#{tab.name}", scope: :tab)
|
7
7
|
.hidden.sm:block
|
8
|
-
.border-b.border-gray-200.dark:border-opacity-25.dark:bg-gray-900
|
8
|
+
.border-b.border-gray-200.bg-white.dark:border-opacity-25.dark:bg-gray-900
|
9
9
|
nav.sts-tabs__nav aria-label="Tabs"
|
10
10
|
- tabs.each.with_index do |tab, index|
|
11
11
|
- id = tab.id.present? ? tab.id : tab.name
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Satis
|
4
|
+
class AttachmentsController < ApplicationController
|
5
|
+
before_action :set_objects
|
6
|
+
|
7
|
+
|
8
|
+
def index
|
9
|
+
@attachments = @model.public_send(@attachment_type)
|
10
|
+
render json: @attachments
|
11
|
+
end
|
12
|
+
|
13
|
+
def create
|
14
|
+
params[:attachments].each do |file|
|
15
|
+
@model.public_send(@attachment_type).attach(file)
|
16
|
+
end
|
17
|
+
redirect_to request.referer || root_path, notice: "Attachment created successfully."
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def destroy
|
22
|
+
attachment = @model.public_send(@attachment_type).find_by(id: params[:id])
|
23
|
+
attachment&.purge
|
24
|
+
|
25
|
+
redirect_to request.referer || root_path, notice: "Attachment deleted successfully."
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def set_objects
|
31
|
+
@attachment_type = params[:attribute] || 'attachments'
|
32
|
+
@model = GlobalID::Locator.locate_signed(params[:sgid], for: 'satis_attachments')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -3,13 +3,5 @@ module Satis
|
|
3
3
|
def sts
|
4
4
|
@_satis_helpers_container ||= Satis::Helpers::Container.new(self)
|
5
5
|
end
|
6
|
-
|
7
|
-
def method_missing(method, *args, **kwargs, &block)
|
8
|
-
if method.to_s.ends_with?('_url') || method.to_s.ends_with?('_path') && main_app.respond_to?(method)
|
9
|
-
main_app.send(method, *args, **kwargs, &block)
|
10
|
-
else
|
11
|
-
super
|
12
|
-
end
|
13
|
-
end
|
14
6
|
end
|
15
7
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
import AttachmentUploadController from "./attachment_upload_controller";
|
3
|
+
import { get } from '@rails/request.js'
|
4
|
+
|
5
|
+
/***
|
6
|
+
* Delete attachments controller
|
7
|
+
*
|
8
|
+
* Deletes an attachments
|
9
|
+
*/
|
10
|
+
export default class AttachmentDeleteController extends Controller {
|
11
|
+
connect() {}
|
12
|
+
|
13
|
+
delete(event) {
|
14
|
+
const self = this
|
15
|
+
|
16
|
+
event.stopPropagation()
|
17
|
+
event.preventDefault()
|
18
|
+
|
19
|
+
const formData = new FormData()
|
20
|
+
formData.append("_method", "DELETE")
|
21
|
+
|
22
|
+
fetch(self.element.getAttribute("href"), {
|
23
|
+
method: "POST",
|
24
|
+
headers: {
|
25
|
+
"X-CSRF-Token": document.querySelector("meta[name=csrf-token]").content,
|
26
|
+
},
|
27
|
+
body: formData,
|
28
|
+
})
|
29
|
+
.then(self.handleErrors)
|
30
|
+
.then((response) => {
|
31
|
+
window.location.reload(true);
|
32
|
+
response.json().then(function (data) {
|
33
|
+
let node = document.querySelector(data.selector)
|
34
|
+
if (node) {
|
35
|
+
node.innerHTML = data.html
|
36
|
+
}
|
37
|
+
})
|
38
|
+
})
|
39
|
+
.catch((error) => {
|
40
|
+
console.log(error)
|
41
|
+
})
|
42
|
+
return false
|
43
|
+
}
|
44
|
+
|
45
|
+
handleErrors(response) {
|
46
|
+
if (!response.ok) throw new Error(response.status)
|
47
|
+
return response
|
48
|
+
}
|
49
|
+
}
|
@@ -0,0 +1,109 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
|
3
|
+
export default class AttachmentUploadController extends Controller {
|
4
|
+
static targets = ["input"]
|
5
|
+
|
6
|
+
connect() {
|
7
|
+
this.createFileInput()
|
8
|
+
this.addEventListeners()
|
9
|
+
}
|
10
|
+
|
11
|
+
createFileInput() {
|
12
|
+
const input = document.createElement("input")
|
13
|
+
input.setAttribute("name", this.data.get("param-name") || "file")
|
14
|
+
input.setAttribute("type", "file")
|
15
|
+
input.setAttribute("multiple", "multiple")
|
16
|
+
input.style.display = "none"
|
17
|
+
this.element.appendChild(input)
|
18
|
+
this.fileInput = input
|
19
|
+
|
20
|
+
if (!this.data.has("param-name")) {
|
21
|
+
console.warn(this.element, "has no data-upload-param attribute, uploads may not work")
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
addEventListeners() {
|
26
|
+
this.element.addEventListener("click", this.handleClick.bind(this))
|
27
|
+
this.fileInput.addEventListener("change", this.handleChange.bind(this))
|
28
|
+
this.element.addEventListener("dragover", this.handleDragOver.bind(this))
|
29
|
+
this.element.addEventListener("dragleave", this.handleDragLeave.bind(this))
|
30
|
+
this.element.addEventListener("dragenter", this.handleDragEnter.bind(this))
|
31
|
+
this.element.addEventListener("drop", this.handleDrop.bind(this))
|
32
|
+
}
|
33
|
+
|
34
|
+
handleClick(event) {
|
35
|
+
event.preventDefault()
|
36
|
+
this.fileInput.click()
|
37
|
+
}
|
38
|
+
|
39
|
+
handleChange(event) {
|
40
|
+
this.upload(event.target.files)
|
41
|
+
}
|
42
|
+
|
43
|
+
handleDragOver(event) {
|
44
|
+
event.preventDefault()
|
45
|
+
this.element.classList.add("dragging")
|
46
|
+
}
|
47
|
+
|
48
|
+
handleDragLeave(event) {
|
49
|
+
event.preventDefault()
|
50
|
+
this.element.classList.remove("dragging")
|
51
|
+
}
|
52
|
+
|
53
|
+
handleDragEnter(event) {
|
54
|
+
event.preventDefault()
|
55
|
+
this.element.classList.add("dragging")
|
56
|
+
}
|
57
|
+
|
58
|
+
handleDrop(event) {
|
59
|
+
event.preventDefault()
|
60
|
+
this.element.classList.remove("dragging")
|
61
|
+
if (event.dataTransfer.files.length > 0) {
|
62
|
+
this.upload(event.dataTransfer.files)
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
upload(files) {
|
67
|
+
// Only proceed if files are selected
|
68
|
+
if (files.length === 0) return
|
69
|
+
|
70
|
+
let formData = new FormData()
|
71
|
+
if (this.data.has("extra-data")) {
|
72
|
+
for (let [key, value] of Object.entries(JSON.parse(this.data.get("extra-data")))) {
|
73
|
+
formData.append(key, value)
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
for (let i = 0; i < files.length; i++) {
|
78
|
+
formData.append(this.data.get("param-name"), files[i])
|
79
|
+
}
|
80
|
+
|
81
|
+
this.element.classList.add("uploading")
|
82
|
+
|
83
|
+
fetch(this.data.get("url"), {
|
84
|
+
method: 'POST',
|
85
|
+
body: formData,
|
86
|
+
headers: {
|
87
|
+
'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content,
|
88
|
+
'Accept': 'text/html, application/json'
|
89
|
+
},
|
90
|
+
redirect: 'follow' // Important: follow redirects
|
91
|
+
}).then((response) => {
|
92
|
+
// Check if the response is a redirect
|
93
|
+
if (response.type === 'opaqueredirect' || response.redirected) {
|
94
|
+
window.location.href = response.url
|
95
|
+
return
|
96
|
+
}
|
97
|
+
|
98
|
+
if (response.ok) {
|
99
|
+
this.element.classList.remove("uploading")
|
100
|
+
window.location.reload(true)
|
101
|
+
} else {
|
102
|
+
throw new Error(response.statusText)
|
103
|
+
}
|
104
|
+
}).catch((error) => {
|
105
|
+
console.log(error)
|
106
|
+
this.element.classList.remove("uploading")
|
107
|
+
})
|
108
|
+
}
|
109
|
+
}
|
@@ -56,6 +56,13 @@ application.register("satis-link", LinkController);
|
|
56
56
|
import FieldsForController from "satis/controllers/fields_for_controller";
|
57
57
|
application.register("satis-fields-for", FieldsForController);
|
58
58
|
|
59
|
+
import AttachmentUploadController from "satis/controllers/attachment_upload_controller";
|
60
|
+
application.register("satis-fields-for", AttachmentUploadController);
|
61
|
+
|
62
|
+
import AttachmentDeleteController from "satis/controllers/attachment_delete_controller";
|
63
|
+
application.register("satis-fields-for", AttachmentDeleteController);
|
64
|
+
|
65
|
+
|
59
66
|
import FormController from "satis/controllers/form_controller";
|
60
67
|
application.register("satis-form", FormController);
|
61
68
|
|
data/config/routes.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
Satis::Engine.routes.draw do
|
2
2
|
resources :user_data, only: %i[show update]
|
3
3
|
resources :dialogs, only: %[show], constraints: { id: /[A-Za-z0-9\_\-\/]+/ }
|
4
|
+
resources :attachments, only: [:index, :create, :destroy]
|
4
5
|
|
5
6
|
unless Rails.env.production?
|
6
7
|
namespace :documentation do
|
@@ -15,3 +16,4 @@ Satis::Engine.routes.draw do
|
|
15
16
|
resources :documentation
|
16
17
|
end
|
17
18
|
end
|
19
|
+
|
@@ -20,6 +20,7 @@ module Satis
|
|
20
20
|
add_helper :menu, Satis::Menu::Component
|
21
21
|
add_helper :page, Satis::Page::Component
|
22
22
|
add_helper :sidebar_menu, Satis::SidebarMenu::Component
|
23
|
+
add_helper :attachments, Satis::Attachments::Component
|
23
24
|
add_helper :tabs, Satis::Tabs::Component
|
24
25
|
add_helper :input, Satis::Input::Component
|
25
26
|
add_helper :progress_bar, Satis::ProgressBar::Component
|
data/lib/satis/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: satis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.47
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tom de Grunt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-01-
|
11
|
+
date: 2025-01-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: browser
|
@@ -751,6 +751,10 @@ files:
|
|
751
751
|
- app/components/satis/appearance_switcher/component.rb
|
752
752
|
- app/components/satis/appearance_switcher/component_controller.js
|
753
753
|
- app/components/satis/application_component.rb
|
754
|
+
- app/components/satis/attachments/component.css
|
755
|
+
- app/components/satis/attachments/component.html.slim
|
756
|
+
- app/components/satis/attachments/component.rb
|
757
|
+
- app/components/satis/attachments/create.json.jbuilder
|
754
758
|
- app/components/satis/avatar/component.html.slim
|
755
759
|
- app/components/satis/avatar/component.rb
|
756
760
|
- app/components/satis/breadcrumbs/component.css
|
@@ -853,6 +857,7 @@ files:
|
|
853
857
|
- app/components/satis/tabs/component.rb
|
854
858
|
- app/components/satis/tabs/component_controller.js
|
855
859
|
- app/controllers/satis/application_controller.rb
|
860
|
+
- app/controllers/satis/attachments_controller.rb
|
856
861
|
- app/controllers/satis/dialogs_controller.rb
|
857
862
|
- app/controllers/satis/documentation/avatars_controller.rb
|
858
863
|
- app/controllers/satis/documentation/cards_controller.rb
|
@@ -866,6 +871,8 @@ files:
|
|
866
871
|
- app/javascript/satis/application.js
|
867
872
|
- app/javascript/satis/controllers/application.js
|
868
873
|
- app/javascript/satis/controllers/application_controller.js
|
874
|
+
- app/javascript/satis/controllers/attachment_delete_controller.js
|
875
|
+
- app/javascript/satis/controllers/attachment_upload_controller.js
|
869
876
|
- app/javascript/satis/controllers/fields_for_controller.js
|
870
877
|
- app/javascript/satis/controllers/file_controller.js
|
871
878
|
- app/javascript/satis/controllers/form_controller.js
|