lesli_view 1.0.6 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +4 -6
- data/lib/lesli_view/charts/general.html.erb +35 -77
- data/lib/lesli_view/charts/general.rb +62 -10
- data/lib/lesli_view/components/header.html.erb +3 -1
- data/lib/lesli_view/components/timeline.html.erb +11 -8
- data/lib/lesli_view/components/timeline.rb +3 -2
- data/lib/lesli_view/components/timeline.scss +48 -50
- data/lib/lesli_view/elements/button.html.erb +33 -24
- data/lib/lesli_view/elements/button.rb +39 -5
- data/lib/lesli_view/engine.rb +0 -7
- data/lib/lesli_view/forms/fields.rb +13 -13
- data/lib/lesli_view/forms/inputs.rb +3 -2
- data/lib/lesli_view/items/actions.html.erb +88 -0
- data/lib/lesli_view/items/actions.rb +45 -0
- data/lib/lesli_view/items/activities.html.erb +38 -0
- data/lib/lesli_view/items/activities.rb +49 -0
- data/lib/lesli_view/items/activities.scss +39 -0
- data/lib/lesli_view/items/attachments.html.erb +68 -0
- data/lib/lesli_view/items/attachments.rb +45 -0
- data/lib/lesli_view/items/discussion.html.erb +1 -1
- data/lib/lesli_view/items/discussions.html.erb +17 -16
- data/lib/lesli_view/items/discussions.rb +2 -0
- data/lib/lesli_view/items/task.html.erb +55 -0
- data/lib/lesli_view/items/task.rb +44 -0
- data/lib/lesli_view/items/tasks.html.erb +66 -0
- data/lib/lesli_view/items/tasks.rb +43 -0
- data/lib/lesli_view/version.rb +2 -2
- data/lib/lesli_view/widgets/chart.html.erb +1 -1
- data/lib/lesli_view.rb +5 -0
- data/readme.md +14 -38
- metadata +36 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dea27d123b49acd9375db16afb5ad126fb232e5b639c0f9699dc2c4825117fdf
|
|
4
|
+
data.tar.gz: a86fa765debb5db1d8b5a0ec487e8ee01ded407f9e6e14d32118ca8ec8ef7ca8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8974bf2767aabad29a0606509bffb635e8f6d2384e1ffaca68dff3fa495763108178e1afc46941e55bcf0592ea9530b7015c2fe2608bc609b6a38d9dc41d03e1
|
|
7
|
+
data.tar.gz: 8c2d7fb73fecf7a251defb3010a45f68f2cfb1f3a77c091890e899a469e407298dbe623adb4499cf3ea748e493ecc8ef591864f753ef1b1266d40e7aad32b0be
|
data/Rakefile
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
require "bundler/setup"
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
RSpec::Core::RakeTask.new(:spec)
|
|
3
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
|
4
|
+
load "rails/tasks/engine.rake"
|
|
7
5
|
|
|
8
|
-
|
|
6
|
+
require "bundler/gem_tasks"
|
|
@@ -1,89 +1,47 @@
|
|
|
1
|
-
|
|
2
|
-
document.addEventListener("turbo:load", () => {
|
|
3
|
-
const chartId = "<%= id %>";
|
|
4
|
-
const chartElement = document.getElementById(chartId);
|
|
1
|
+
<%#
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
///console.warn("Chart element not found:", chartId);
|
|
8
|
-
return;
|
|
9
|
-
}
|
|
3
|
+
Lesli
|
|
10
4
|
|
|
11
|
-
|
|
12
|
-
chartElement.innerHTML = "";
|
|
5
|
+
Copyright (c) 2026, Lesli Technologies, S. A.
|
|
13
6
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
show: false,
|
|
19
|
-
padding: { top: 0, right: 0, bottom: 0, left: 0 }
|
|
20
|
-
},
|
|
21
|
-
chart: {
|
|
22
|
-
type: "<%= type %>",
|
|
23
|
-
height: "<%= height %>",
|
|
24
|
-
toolbar: { show: false },
|
|
25
|
-
events: {
|
|
26
|
-
markerClick: function(event, chartContext, { seriesIndex, dataPointIndex }) {
|
|
27
|
-
emit("markerClick", { seriesIndex, dataPointIndex });
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
legend: {
|
|
32
|
-
show: true,
|
|
33
|
-
position: "top",
|
|
34
|
-
horizontalAlign: "center"
|
|
35
|
-
},
|
|
36
|
-
plotOptions: {
|
|
37
|
-
bar: {
|
|
38
|
-
borderRadius: 6,
|
|
39
|
-
borderRadiusApplication: 'end',
|
|
40
|
-
dataLabels: {
|
|
41
|
-
position: 'top', // top, center, bottom
|
|
42
|
-
},
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
dataLabels: { enabled: true },
|
|
46
|
-
stroke: {
|
|
47
|
-
show: true,
|
|
48
|
-
curve: "smooth",
|
|
49
|
-
lineCap: "round"
|
|
50
|
-
},
|
|
51
|
-
xaxis: {
|
|
52
|
-
categories: <%= raw(labels.to_json) %>,
|
|
53
|
-
tickPlacement: "between",
|
|
54
|
-
labels: {
|
|
55
|
-
show: true,
|
|
56
|
-
rotate: -65,
|
|
57
|
-
rotateAlways: false,
|
|
58
|
-
trim: false,
|
|
59
|
-
offsetY: 5,
|
|
60
|
-
style: { fontSize: "15px" }
|
|
61
|
-
}
|
|
62
|
-
},
|
|
63
|
-
yaxis: { show: true }
|
|
64
|
-
};
|
|
7
|
+
This program is free software: you can redistribute it and/or modify
|
|
8
|
+
it under the terms of the GNU General Public License as published by
|
|
9
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
10
|
+
(at your option) any later version.
|
|
65
11
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
12
|
+
This program is distributed in the hope that it will be useful,
|
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
GNU General Public License for more details.
|
|
69
16
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const label = w.globals.labels[dataPointIndex];
|
|
73
|
-
return `${label}: ${value}`;
|
|
74
|
-
}
|
|
75
|
-
<% elsif type == "line" %>
|
|
76
|
-
options.grid.padding = { top: 14, right: 0, bottom: 6, left: 0 }
|
|
77
|
-
<% end %>
|
|
17
|
+
You should have received a copy of the GNU General Public License
|
|
18
|
+
along with this program. If not, see http://www.gnu.org/licenses/.
|
|
78
19
|
|
|
79
|
-
|
|
20
|
+
Lesli · Ruby on Rails SaaS Development Framework.
|
|
21
|
+
|
|
22
|
+
Made with ♥ by LesliTech
|
|
23
|
+
Building a better future, one line of code at a time.
|
|
80
24
|
|
|
81
|
-
|
|
82
|
-
|
|
25
|
+
@contact hello@lesli.tech
|
|
26
|
+
@website https://www.lesli.tech
|
|
27
|
+
@license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
|
|
28
|
+
|
|
29
|
+
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
|
30
|
+
// ·
|
|
31
|
+
%>
|
|
32
|
+
<script>
|
|
33
|
+
document.addEventListener("turbo:load", () => {
|
|
34
|
+
new LesliChart({
|
|
35
|
+
id: "<%= id %>",
|
|
36
|
+
type: "<%= type %>",
|
|
37
|
+
datasets: <%= raw(datasets.to_json) %>,
|
|
38
|
+
labels: <%= raw(labels.to_json) %>,
|
|
39
|
+
compact: <%= compact ? "true" : "false" %>
|
|
40
|
+
});
|
|
83
41
|
});
|
|
84
42
|
</script>
|
|
85
43
|
|
|
86
|
-
<div class="lesli-charts lesli-charts-<%= type %> section box
|
|
44
|
+
<div class="lesli-charts lesli-charts-<%= type %> section box m-0 p-2">
|
|
87
45
|
|
|
88
46
|
<% if title.present? %>
|
|
89
47
|
<%= tag.h3(title, class: (compact ? "is-size-7 has-text-centered" : "ml-2")) %>
|
|
@@ -93,5 +51,5 @@ document.addEventListener("turbo:load", () => {
|
|
|
93
51
|
<p class="ml-2"><b><%= subtitle %></b></p>
|
|
94
52
|
<% end %>
|
|
95
53
|
|
|
96
|
-
<div id="<%= id %>"></div>
|
|
54
|
+
<div id="<%= id %>" style="min-height:<%= height %>"></div>
|
|
97
55
|
</div>
|
|
@@ -39,33 +39,85 @@ module LesliView
|
|
|
39
39
|
:title,
|
|
40
40
|
:subtitle,
|
|
41
41
|
:labels,
|
|
42
|
-
:
|
|
42
|
+
:datasets,
|
|
43
43
|
:height,
|
|
44
44
|
:compact
|
|
45
45
|
)
|
|
46
46
|
|
|
47
47
|
def initialize(
|
|
48
|
-
id:
|
|
49
|
-
title:
|
|
50
|
-
subtitle:
|
|
48
|
+
id:nil,
|
|
49
|
+
title:nil,
|
|
50
|
+
subtitle:nil,
|
|
51
51
|
labels:nil,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
dataset:nil,
|
|
53
|
+
datasets:nil,
|
|
54
|
+
database_to_dataset:nil,
|
|
55
|
+
database_to_datasets:nil,
|
|
56
|
+
height:"400px",
|
|
57
|
+
compact:false
|
|
56
58
|
)
|
|
57
|
-
@id = id || "lesli-chart-#{rand(
|
|
59
|
+
@id = id || "lesli-chart-#{rand(1000)}"
|
|
58
60
|
@title = title
|
|
59
61
|
@subtitle = subtitle
|
|
60
62
|
@labels = labels
|
|
61
|
-
@
|
|
63
|
+
@datasets = datasets
|
|
62
64
|
@height = height
|
|
63
65
|
@compact = compact
|
|
66
|
+
|
|
67
|
+
@datasets = [{ name: title, data: dataset }] if dataset
|
|
68
|
+
@datasets = database_to_dataset(database_to_dataset) if database_to_dataset
|
|
69
|
+
@datasets = database_to_datasets(database_to_datasets) if database_to_datasets
|
|
64
70
|
end
|
|
65
71
|
|
|
66
72
|
def type
|
|
67
73
|
nil
|
|
68
74
|
end
|
|
75
|
+
|
|
76
|
+
def database_to_dataset(data)
|
|
77
|
+
[{ data: data.map { |d| { x: d['xaxiskey'], y: d['yaxiskey'] }}}]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Transforms a database query result into a structure compatible with Chart.js
|
|
81
|
+
#
|
|
82
|
+
# Expected input:
|
|
83
|
+
# An enumerable of records responding to:
|
|
84
|
+
# - :name → series name (ex: browser, category, status)
|
|
85
|
+
# - :label → x-axis value (ex: date, category label)
|
|
86
|
+
# - :data → y-axis value (numeric)
|
|
87
|
+
#
|
|
88
|
+
# Example:
|
|
89
|
+
# browsers = current_user.account.audit.account_devices
|
|
90
|
+
# .group(:agent_browser, :created_at)
|
|
91
|
+
# .select(
|
|
92
|
+
# 'created_at as label',
|
|
93
|
+
# 'agent_browser as name',
|
|
94
|
+
# 'sum(agent_count) as data'
|
|
95
|
+
# )
|
|
96
|
+
#
|
|
97
|
+
def database_to_datasets(data)
|
|
98
|
+
|
|
99
|
+
# Group records by series name
|
|
100
|
+
# Example: group all "Chrome" rows together
|
|
101
|
+
data
|
|
102
|
+
.group_by { |records| records['dataname'] }
|
|
103
|
+
.map do |name, records|
|
|
104
|
+
{
|
|
105
|
+
# Series name (used in legend and tooltips)
|
|
106
|
+
label: name,
|
|
107
|
+
|
|
108
|
+
# Convert each database row into an (x, y) point
|
|
109
|
+
data: records.map do |record|
|
|
110
|
+
{
|
|
111
|
+
# X-axis value (date, category, etc.)
|
|
112
|
+
x: record['xaxiskey'],
|
|
113
|
+
|
|
114
|
+
# Y-axis value (must be numeric)
|
|
115
|
+
y: record['yaxiskey']
|
|
116
|
+
}
|
|
117
|
+
end
|
|
118
|
+
}
|
|
119
|
+
end
|
|
120
|
+
end
|
|
69
121
|
end
|
|
70
122
|
end
|
|
71
123
|
end
|
|
@@ -13,7 +13,9 @@
|
|
|
13
13
|
<h1 class="subtitle is-size-3 mb-1"><%= title %></h1>
|
|
14
14
|
<% end %>
|
|
15
15
|
</div>
|
|
16
|
-
|
|
16
|
+
<% if subtitle.present? %>
|
|
17
|
+
<p><%= subtitle %></p>
|
|
18
|
+
<% end %>
|
|
17
19
|
</div>
|
|
18
20
|
<div class="lesli-element-header-items is-flex is-flex-grow-1 is-justify-content-end">
|
|
19
21
|
<% if new_path %>
|
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
|
|
2
1
|
<div class="lesli-timelines">
|
|
3
|
-
<div class="py-6 pl-
|
|
2
|
+
<div class="py-6 pl-6">
|
|
4
3
|
<ul class="lesli-timeline lesli-timeline-split">
|
|
5
4
|
<% @activities.each do |activity| %>
|
|
6
5
|
<li class="lesli-timeline-item">
|
|
7
6
|
<div class="lesli-timeline-info">
|
|
8
|
-
<span><%= activity[
|
|
7
|
+
<span><%= activity['date'] %></span>
|
|
8
|
+
</div>
|
|
9
|
+
<div class="lesli-timeline-marker">
|
|
10
|
+
<span class="material-symbols-outlined">
|
|
11
|
+
<%= @icons.dig(activity['icon']&.to_sym) || 'radio_button_checked' %>
|
|
12
|
+
</span>
|
|
9
13
|
</div>
|
|
10
|
-
<div class="lesli-timeline-marker"></div>
|
|
11
14
|
<div class="lesli-timeline-content">
|
|
12
|
-
<
|
|
13
|
-
<%= activity[
|
|
14
|
-
</
|
|
15
|
+
<h6 class="lesli-timeline-title">
|
|
16
|
+
<%= activity['operation'] %>
|
|
17
|
+
</h6>
|
|
15
18
|
<p>
|
|
16
|
-
<%= activity[
|
|
19
|
+
<%= activity['description'] %>
|
|
17
20
|
</p>
|
|
18
21
|
</div>
|
|
19
22
|
</li>
|
|
@@ -35,9 +35,10 @@ Building a better future, one line of code at a time.
|
|
|
35
35
|
module LesliView
|
|
36
36
|
module Components
|
|
37
37
|
class Timeline < ViewComponent::Base
|
|
38
|
-
attr_reader :activities
|
|
38
|
+
attr_reader :activities, :icons
|
|
39
39
|
|
|
40
|
-
def initialize(activities: nil)
|
|
40
|
+
def initialize(activities: nil, icons:{})
|
|
41
|
+
@icons=icons
|
|
41
42
|
@activities = activities
|
|
42
43
|
end
|
|
43
44
|
end
|
|
@@ -2,78 +2,76 @@
|
|
|
2
2
|
.lesli-timelines {
|
|
3
3
|
|
|
4
4
|
.lesli-timeline {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
.lesli-timeline h1,
|
|
12
|
-
.lesli-timeline h2,
|
|
13
|
-
.lesli-timeline h3,
|
|
14
|
-
.lesli-timeline h4,
|
|
15
|
-
.lesli-timeline h5,
|
|
16
|
-
.lesli-timeline h6 {
|
|
17
|
-
line-height: inherit;
|
|
5
|
+
line-height: 1.4em;
|
|
6
|
+
list-style: none;
|
|
7
|
+
margin: 0;
|
|
8
|
+
padding: 0;
|
|
9
|
+
width: 100%;
|
|
18
10
|
}
|
|
19
11
|
|
|
20
12
|
/*----- TIMELINE ITEM -----*/
|
|
21
13
|
.lesli-timeline-item {
|
|
22
|
-
|
|
23
|
-
|
|
14
|
+
padding-left: 40px;
|
|
15
|
+
position: relative;
|
|
24
16
|
}
|
|
25
17
|
.lesli-timeline-item:last-child {
|
|
26
|
-
|
|
18
|
+
padding-bottom: 0;
|
|
27
19
|
}
|
|
28
20
|
|
|
29
21
|
/*----- TIMELINE INFO -----*/
|
|
30
22
|
.lesli-timeline-info {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
23
|
+
font-size: 12px;
|
|
24
|
+
font-weight: 700;
|
|
25
|
+
letter-spacing: 3px;
|
|
26
|
+
margin: 0 0 0.5em 0;
|
|
27
|
+
text-transform: uppercase;
|
|
28
|
+
white-space: nowrap;
|
|
37
29
|
}
|
|
38
30
|
|
|
39
31
|
/*----- TIMELINE MARKER -----*/
|
|
40
32
|
.lesli-timeline-marker {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
33
|
+
position: absolute;
|
|
34
|
+
top: 0;
|
|
35
|
+
bottom: 0;
|
|
36
|
+
left: 0;
|
|
37
|
+
width: 15px;
|
|
46
38
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
39
|
+
|
|
40
|
+
.lesli-timeline-marker:before2 {
|
|
41
|
+
background: #ff6b6b;
|
|
42
|
+
border: 3px solid transparent;
|
|
43
|
+
border-radius: 100%;
|
|
44
|
+
content: "";
|
|
45
|
+
display: block;
|
|
46
|
+
height: 15px;
|
|
47
|
+
position: absolute;
|
|
48
|
+
top: 4px;
|
|
49
|
+
left: 0;
|
|
50
|
+
width: 15px;
|
|
51
|
+
transition: background 0.3s ease-in-out, border 0.3s ease-in-out;
|
|
59
52
|
}
|
|
53
|
+
|
|
60
54
|
.lesli-timeline-marker:after {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
55
|
+
content: "";
|
|
56
|
+
width: 2px;
|
|
57
|
+
background: #ccd5db;
|
|
58
|
+
display: block;
|
|
59
|
+
position: absolute;
|
|
60
|
+
top: 24px;
|
|
61
|
+
bottom: 0;
|
|
62
|
+
left: 0;
|
|
63
|
+
right: 0;
|
|
64
|
+
margin-left: auto;
|
|
65
|
+
margin-right: auto;
|
|
69
66
|
}
|
|
67
|
+
|
|
70
68
|
.lesli-timeline-item:last-child .lesli-timeline-marker:after {
|
|
71
|
-
|
|
69
|
+
content: none;
|
|
72
70
|
}
|
|
73
71
|
|
|
74
72
|
.lesli-timeline-item:not(.period):hover .lesli-timeline-marker:before {
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
background: transparent;
|
|
74
|
+
border: 3px solid #ff6b6b;
|
|
77
75
|
}
|
|
78
76
|
|
|
79
77
|
/*----- TIMELINE CONTENT -----*/
|
|
@@ -1,26 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
<%
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
<%
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
<% else %>
|
|
24
|
-
<%= label %>
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
<% if mode == :button_to %>
|
|
4
|
+
|
|
5
|
+
<%= button_to(
|
|
6
|
+
@url,
|
|
7
|
+
method: @method,
|
|
8
|
+
params: @params,
|
|
9
|
+
class: html_classes,
|
|
10
|
+
data: { turbo_frame: "_top" },
|
|
11
|
+
**alpine_attributes) do %>
|
|
12
|
+
<%= button_content %>
|
|
13
|
+
<% end %>
|
|
14
|
+
|
|
15
|
+
<% elsif mode == :link %>
|
|
16
|
+
|
|
17
|
+
<%= link_to(
|
|
18
|
+
@url,
|
|
19
|
+
class: html_classes,
|
|
20
|
+
data: { turbo_frame: "_top" },
|
|
21
|
+
**alpine_attributes) do %>
|
|
22
|
+
<%= button_content %>
|
|
25
23
|
<% end %>
|
|
24
|
+
|
|
25
|
+
<% else %>
|
|
26
|
+
|
|
27
|
+
<%= content_tag(
|
|
28
|
+
:button,
|
|
29
|
+
type: "button",
|
|
30
|
+
class: html_classes,
|
|
31
|
+
**alpine_attributes) do %>
|
|
32
|
+
<%= button_content %>
|
|
33
|
+
<% end %>
|
|
34
|
+
|
|
26
35
|
<% end %>
|
|
@@ -35,7 +35,7 @@ Building a better future, one line of code at a time.
|
|
|
35
35
|
module LesliView
|
|
36
36
|
module Elements
|
|
37
37
|
class Button < ViewComponent::Base
|
|
38
|
-
attr_reader :label, :url, :icon, :loading, :solid, :info, :success, :warning, :danger, :small, :
|
|
38
|
+
attr_reader :label, :url, :icon, :loading, :solid, :info, :success, :warning, :danger, :small, :dispatch, :method, :params, :css_class
|
|
39
39
|
|
|
40
40
|
# Adds two numbers together.
|
|
41
41
|
# @param [Integer] a The first number.
|
|
@@ -52,8 +52,10 @@ module LesliView
|
|
|
52
52
|
warning: false,
|
|
53
53
|
danger: false,
|
|
54
54
|
small: false,
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
dispatch:nil,
|
|
56
|
+
method: nil,
|
|
57
|
+
params:nil,
|
|
58
|
+
css_class:nil
|
|
57
59
|
)
|
|
58
60
|
@label = label
|
|
59
61
|
@url = url
|
|
@@ -65,15 +67,33 @@ module LesliView
|
|
|
65
67
|
@warning = warning
|
|
66
68
|
@danger = danger
|
|
67
69
|
@small = small
|
|
68
|
-
@type = type
|
|
69
70
|
@dispatch = dispatch
|
|
71
|
+
@method = method
|
|
72
|
+
@params = params
|
|
73
|
+
@css_class = css_class
|
|
70
74
|
end
|
|
71
75
|
|
|
72
|
-
def
|
|
76
|
+
def mode
|
|
77
|
+
return :button_to if @method.present?
|
|
78
|
+
return :link if @url.present?
|
|
79
|
+
:button
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def alpine_attributes
|
|
83
|
+
return {} unless @dispatch
|
|
84
|
+
|
|
85
|
+
{
|
|
86
|
+
"x-data": "",
|
|
87
|
+
"@click": "$dispatch('#{@dispatch}')"
|
|
88
|
+
}
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def html_classes
|
|
73
92
|
classes = ["button", button_variant]
|
|
74
93
|
classes << "is-light" << "is-outlined" unless solid
|
|
75
94
|
classes << "is-loading" if loading
|
|
76
95
|
classes << "is-small" if small
|
|
96
|
+
classes << css_class
|
|
77
97
|
classes.join(" ")
|
|
78
98
|
end
|
|
79
99
|
|
|
@@ -88,6 +108,20 @@ module LesliView
|
|
|
88
108
|
def icon_only?
|
|
89
109
|
icon && !label
|
|
90
110
|
end
|
|
111
|
+
|
|
112
|
+
def button_content
|
|
113
|
+
if @icon
|
|
114
|
+
safe_join([
|
|
115
|
+
content_tag(:span,
|
|
116
|
+
content_tag(:span, @icon, class: "material-symbols"),
|
|
117
|
+
class: "icon #{'is-small' if @small}"
|
|
118
|
+
),
|
|
119
|
+
(@icon_only ? nil : content_tag(:span, @label))
|
|
120
|
+
].compact)
|
|
121
|
+
else
|
|
122
|
+
@label
|
|
123
|
+
end
|
|
124
|
+
end
|
|
91
125
|
end
|
|
92
126
|
end
|
|
93
127
|
end
|
data/lib/lesli_view/engine.rb
CHANGED
|
@@ -33,12 +33,5 @@ Building a better future, one line of code at a time.
|
|
|
33
33
|
module LesliView
|
|
34
34
|
class Engine < ::Rails::Engine
|
|
35
35
|
isolate_namespace LesliView
|
|
36
|
-
|
|
37
|
-
initializer "lesli_view" do |app|
|
|
38
|
-
|
|
39
|
-
# autoloading sass style sheet files
|
|
40
|
-
app.config.assets.precompile += %w[lesli_view/lesli_view.scss]
|
|
41
|
-
|
|
42
|
-
end
|
|
43
36
|
end
|
|
44
37
|
end
|
|
@@ -39,19 +39,6 @@ module LesliView
|
|
|
39
39
|
)
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
-
def field_text_editor(attribute, label:nil, message:nil, category:nil, icon:nil, horizontal: false)
|
|
43
|
-
|
|
44
|
-
label_html = label(attribute, label)
|
|
45
|
-
control_html = text_editor(attribute)
|
|
46
|
-
|
|
47
|
-
field_control_builder(
|
|
48
|
-
label_html: label_html,
|
|
49
|
-
control_html: control_html,
|
|
50
|
-
horizontal: horizontal,
|
|
51
|
-
icon:icon
|
|
52
|
-
)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
42
|
def field_control_select(attribute, choices, label: nil, message:nil, category:nil, icon:nil, horizontal: false, humanize:true)
|
|
56
43
|
choices = choices.map { |k, v| [k.humanize.capitalize, v] } if humanize
|
|
57
44
|
value = @object.send(attribute)
|
|
@@ -65,6 +52,19 @@ module LesliView
|
|
|
65
52
|
)
|
|
66
53
|
end
|
|
67
54
|
|
|
55
|
+
def field_control_textarea(attribute, label:nil, message:nil, category:nil, icon:nil, horizontal: false)
|
|
56
|
+
|
|
57
|
+
label_html = label == false ? '' : label(attribute, label)
|
|
58
|
+
control_html = rich_textarea(attribute)
|
|
59
|
+
|
|
60
|
+
field_control_builder(
|
|
61
|
+
label_html: label_html,
|
|
62
|
+
control_html: control_html,
|
|
63
|
+
horizontal: horizontal,
|
|
64
|
+
icon:icon
|
|
65
|
+
)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
68
|
def field_control_submit(value = nil, options = {}, horizontal: false)
|
|
69
69
|
submit_html = submit(value, options)
|
|
70
70
|
field_control_builder(control_html: submit_html, horizontal: horizontal)
|
|
@@ -11,7 +11,7 @@ module LesliView
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def text_field(method, options = {})
|
|
14
|
-
value = @object.send(method)
|
|
14
|
+
value = @object.send(method) if @object
|
|
15
15
|
super(method, options.merge(value: value, class: 'input'))
|
|
16
16
|
end
|
|
17
17
|
|
|
@@ -24,6 +24,7 @@ module LesliView
|
|
|
24
24
|
@template.content_tag("trix-editor", "", toolbar: editor_id, input: input_id)
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
+
|
|
27
28
|
def email_field(method, options = {})
|
|
28
29
|
value = @object.send(method)
|
|
29
30
|
super(method, options.merge(value: value, class: 'input'))
|
|
@@ -36,7 +37,7 @@ module LesliView
|
|
|
36
37
|
|
|
37
38
|
def submit(value=nil, options = {})
|
|
38
39
|
# Extract and merge classes properly
|
|
39
|
-
default_classes = "button is-primary
|
|
40
|
+
default_classes = "button is-primary"
|
|
40
41
|
custom_classes = options[:class] || ""
|
|
41
42
|
merged_classes = "#{default_classes} #{custom_classes}".strip
|
|
42
43
|
super(value, options.merge(class: merged_classes))
|