lesli_view 1.0.6 → 1.0.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 23e41118aed61f81b4b11d893ac216ce39589c80fedf71717295702a05b69c13
4
- data.tar.gz: a35dbb7d5035e99900eac523d10804309d63e69da2c6fc5d5e958db4ea468b77
3
+ metadata.gz: b734297630bd20e59b5d03fd383ec96dbbe1077d017bd57140dfb26ae275fc0d
4
+ data.tar.gz: 33ebb5c222abe3e7bb14238364864640b7e3fcfe239dc1b728801a62e5501745
5
5
  SHA512:
6
- metadata.gz: 81ce9692655a2c0c07bdb28ed47444ab232aa3a090fabb55e2935bddc6a3578df1fa55904d87ae6976389b551fe3c8e030e9a880f9ff4dd7421dff32c473cdcd
7
- data.tar.gz: 6f53d41293f5486972a5295a84b56a25fce059ffed8fa4cd72b0e98d71db3636e9d19681c1066a7c5903e6633732cba2c76722b1c9c2e2eccc9bce4deea641c3
6
+ metadata.gz: c9491a1796c93dba952bc7d0bcdde90084c87d3dbe5ebf250cb56515367a1a955a9882b7c0b2ee101e70ad1d254dbca1b413345778530b5910362ea53463aaef
7
+ data.tar.gz: cf82377496af49210d2ac027f8cf3008e9c178ad42ffa83cff0ae0a94101b6b8e15e021c5c08e4d6add18570e737c07ce4c13341d17d92d9bf225973fec8c8eb
@@ -1,89 +1,47 @@
1
- <script>
2
- document.addEventListener("turbo:load", () => {
3
- const chartId = "<%= id %>";
4
- const chartElement = document.getElementById(chartId);
1
+ <%#
5
2
 
6
- if (!chartElement) {
7
- ///console.warn("Chart element not found:", chartId);
8
- return;
9
- }
3
+ Lesli
10
4
 
11
- // Clear previous chart instance (important for Turbo re-renders)
12
- chartElement.innerHTML = "";
5
+ Copyright (c) 2026, Lesli Technologies, S. A.
13
6
 
14
- var options = {
15
- series: <%= raw(series.to_json) %>,
16
- labels: <%= raw(labels.to_json) %>,
17
- grid: {
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
- // Overrides for compact view
67
- <% if compact %>
68
- options.chart.sparkline = { enabled: true };
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
- <% if type == "bar" %>
71
- options.dataLabels.formatter= function (value, { seriesIndex, dataPointIndex, w }) {
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
- <% end %>
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
- const chart = new ApexCharts(chartElement, options);
82
- chart.render()
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 mb-0 p-0 pt-1">
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
- :series,
42
+ :datasets,
43
43
  :height,
44
44
  :compact
45
45
  )
46
46
 
47
47
  def initialize(
48
- id: nil,
49
- title: nil,
50
- subtitle: nil,
48
+ id:nil,
49
+ title:nil,
50
+ subtitle:nil,
51
51
  labels:nil,
52
- series:nil,
53
- serie: nil,
54
- height: "300px",
55
- compact: false
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(100)}"
59
+ @id = id || "lesli-chart-#{rand(1000)}"
58
60
  @title = title
59
61
  @subtitle = subtitle
60
62
  @labels = labels
61
- @series = series || [{ name: title, data: serie }]
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
- <p><%= subtitle %>&nbsp;</p>
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-4">
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[:date] %></span>
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
- <h3 class="lesli-timeline-title">
13
- <%= activity[:title] %>
14
- </h3>
15
+ <h6 class="lesli-timeline-title">
16
+ <%= activity['operation'] %>
17
+ </h6>
15
18
  <p>
16
- <%= activity[:description] %>
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
- line-height: 1.4em;
6
- list-style: none;
7
- margin: 0;
8
- padding: 0;
9
- width: 100%;
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
- padding-left: 40px;
23
- position: relative;
14
+ padding-left: 40px;
15
+ position: relative;
24
16
  }
25
17
  .lesli-timeline-item:last-child {
26
- padding-bottom: 0;
18
+ padding-bottom: 0;
27
19
  }
28
20
 
29
21
  /*----- TIMELINE INFO -----*/
30
22
  .lesli-timeline-info {
31
- font-size: 12px;
32
- font-weight: 700;
33
- letter-spacing: 3px;
34
- margin: 0 0 0.5em 0;
35
- text-transform: uppercase;
36
- white-space: nowrap;
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
- position: absolute;
42
- top: 0;
43
- bottom: 0;
44
- left: 0;
45
- width: 15px;
33
+ position: absolute;
34
+ top: 0;
35
+ bottom: 0;
36
+ left: 0;
37
+ width: 15px;
46
38
  }
47
- .lesli-timeline-marker:before {
48
- background: #ff6b6b;
49
- border: 3px solid transparent;
50
- border-radius: 100%;
51
- content: "";
52
- display: block;
53
- height: 15px;
54
- position: absolute;
55
- top: 4px;
56
- left: 0;
57
- width: 15px;
58
- transition: background 0.3s ease-in-out, border 0.3s ease-in-out;
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
- content: "";
62
- width: 3px;
63
- background: #ccd5db;
64
- display: block;
65
- position: absolute;
66
- top: 24px;
67
- bottom: 0;
68
- left: 6px;
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
- content: none;
69
+ content: none;
72
70
  }
73
71
 
74
72
  .lesli-timeline-item:not(.period):hover .lesli-timeline-marker:before {
75
- background: transparent;
76
- border: 3px solid #ff6b6b;
73
+ background: transparent;
74
+ border: 3px solid #ff6b6b;
77
75
  }
78
76
 
79
77
  /*----- TIMELINE CONTENT -----*/
@@ -1,26 +1,35 @@
1
- <% tag_name = url.present? ? :a : :button %>
2
-
3
- <% attributes = {
4
- class: button_classes,
5
- data: {}
6
- } %>
7
-
8
- <% attributes[:href] = url if url.present? %>
9
- <% attributes[:data][:turbo_frame] = "_top" if url.present? %>
10
-
11
- <%# Add Alpine.js properties %>
12
- <% attributes[:"x-data"] = "" if dispatch %>
13
- <% attributes[:"@click"] = "$dispatch('#{ dispatch }')" if dispatch %>
14
-
15
- <%= content_tag(tag_name, **attributes) do %>
16
- <% if icon %>
17
- <span class="icon <%= 'is-small' if small %>">
18
- <span class="material-symbols"><%= icon %></span>
19
- </span>
20
- <% unless icon_only? %>
21
- <span><%= label %></span>
22
- <% end %>
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, :type, :dispatch
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
- type: "button",
56
- dispatch:nil
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 button_classes
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
@@ -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)
@@ -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 is-outlined"
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))
@@ -0,0 +1,88 @@
1
+ <%#
2
+
3
+ Lesli
4
+
5
+ Copyright (c) 2025, Lesli Technologies, S. A.
6
+
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.
11
+
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.
16
+
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/.
19
+
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.
24
+
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
+ <style>
33
+ .lesli-items-actions {
34
+ .lesli-items-actions-actions-action-done p {
35
+ text-decoration: line-through;
36
+ opacity: 0.6;
37
+ cursor: not-allowed;
38
+ }
39
+ }
40
+ </style>
41
+ <article class="lesli-items-actions box p-6" id="lesli-items-actions">
42
+ <div class="lesli-items-actions-form">
43
+ <%= form_with(
44
+ url: @path_to_create,
45
+ model: @resource.actions.new,
46
+ builder: LesliView::Forms::Builder
47
+ ) do |form| %>
48
+ <%= form.field_control_text(:title) %>
49
+ <%= form.field_control_submit("Add action") %>
50
+
51
+ <!--
52
+ <div class="field is-grouped">
53
+ <%= form.field_control_text(:title) %>
54
+ <%= form.field_control_submit("Add action", {class:"mt-5"}) %>
55
+ </div>
56
+ -->
57
+ <% end %>
58
+ </div>
59
+ <hr>
60
+ <div class="lesli-items-actions-actions" id="lesli-actions">
61
+ <ul>
62
+ <% @resource.actions.each do |action| %>
63
+ <% next unless action.id %>
64
+ <li class="lesli-items-actions-actions-action is-flex mt-3 mb-3 <%= "lesli-items-actions-actions-action-done" if action.done %>">
65
+ <%= form_with(
66
+ model: action,
67
+ url: @path_to_update.call(action.id),
68
+ method: :patch,
69
+ local: true
70
+ ) do |form| %>
71
+ <%= form.hidden_field :id, value: action.id %>
72
+ <%= form.button type: "submit", disabled: action.done? do %>
73
+ <p class="icon-text">
74
+ <span class="icon">
75
+ <span class="material-symbols-outlined">
76
+ <%= action.done ? "check_box" : "check_box_outline_blank" %>
77
+ </span>
78
+ </span>
79
+ <span><%= action.title %></span>
80
+ </p>
81
+ <% end %>
82
+ <% end %>
83
+ </li>
84
+ <% end %>
85
+ </ul>
86
+ </div>
87
+ </article>
88
+
@@ -0,0 +1,45 @@
1
+ =begin
2
+
3
+ Lesli
4
+
5
+ Copyright (c) 2025, Lesli Technologies, S. A.
6
+
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.
11
+
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.
16
+
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/.
19
+
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.
24
+
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
+ =end
32
+
33
+ module LesliView
34
+ module Items
35
+ class Actions < ViewComponent::Base
36
+ attr_reader :resource, :path_to_create
37
+
38
+ def initialize(resource, path_to_create:nil, path_to_update:nil)
39
+ @resource = resource
40
+ @path_to_create = path_to_create
41
+ @path_to_update = path_to_update
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,38 @@
1
+ <%#
2
+
3
+ Lesli
4
+
5
+ Copyright (c) 2025, Lesli Technologies, S. A.
6
+
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.
11
+
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.
16
+
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/.
19
+
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.
24
+
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
+
33
+
34
+
35
+ <article class="lesli-items-activities" id="lesli-items-activities">
36
+ <%= render(LesliView::Components::Timeline.new(activities:@activities, icons:@icons)) %>
37
+ </article>
38
+
@@ -0,0 +1,49 @@
1
+ =begin
2
+
3
+ Lesli
4
+
5
+ Copyright (c) 2025, Lesli Technologies, S. A.
6
+
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.
11
+
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.
16
+
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/.
19
+
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.
24
+
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
+ =end
32
+ module LesliView
33
+ module Items
34
+ class Activities < ViewComponent::Base
35
+ attr_reader :activities, :icons
36
+
37
+ def initialize(resource, icons:{})
38
+ @icons=icons
39
+ @activities = resource.activities
40
+ .select(
41
+ :id,
42
+ "description as operation",
43
+ "activity_code as icon",
44
+ Date2.new.db_column('created_at', as:'date')
45
+ ).order(id: :desc).as_json
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,39 @@
1
+ /*
2
+
3
+ Lesli
4
+
5
+ Copyright (c) 2025, Lesli Technologies, S. A.
6
+
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.
11
+
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.
16
+
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/.
19
+
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.
24
+
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
+
33
+ @use "lesli-css" as lesli;
34
+
35
+
36
+ .lesli-items-activities {
37
+ background-color: white;
38
+ padding: 2rem;
39
+ }
@@ -3,7 +3,7 @@
3
3
  <strong>Luis Donis</strong> <br>
4
4
  <%= discussion['created_at_string'] || Date2.new.date_time %>
5
5
  </div>
6
- <div class="ml-4 is-fullwidth">
6
+ <div class="ml-4 is-fullwidth lexxy-content">
7
7
  <%== discussion.message %>
8
8
  </div>
9
9
  </div>
@@ -35,7 +35,7 @@ Building a better future, one line of code at a time.
35
35
  url: @path,
36
36
  model: @resource.discussions.new,
37
37
  builder: LesliView::Forms::Builder) do |form| %>
38
- <%= form.field_text_editor(:message) %>
38
+ <%= form.field_control_textarea(:message) %>
39
39
  <%= form.field_control_submit("Add comment") %>
40
40
  <% end %>
41
41
  </div>
@@ -46,7 +46,7 @@ Building a better future, one line of code at a time.
46
46
  <strong>Luis Donis</strong> <br>
47
47
  <%= comment['created_at_string'] || Date2.new.date_time %>
48
48
  </div>
49
- <div class="ml-4 is-fullwidth">
49
+ <div class="ml-4 is-fullwidth lexxy-content">
50
50
  <%== comment.message %>
51
51
  </div>
52
52
  </div>
@@ -33,6 +33,8 @@ module LesliView
33
33
  module Items
34
34
  class Discussions < ViewComponent::Base
35
35
  attr_reader :resource, :path
36
+
37
+ delegate :lexxy_rich_textarea_tag, to: :helpers
36
38
 
37
39
  def initialize(resource, path=nil)
38
40
  @resource = resource
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LesliView
4
- VERSION = "1.0.6"
5
- BUILD = "1767477530"
4
+ VERSION = "1.0.7"
5
+ BUILD = "1771710537"
6
6
  end
@@ -20,7 +20,7 @@
20
20
  <%= render(chart_component.new(
21
21
  title: title,
22
22
  labels: data.map{ |i| i[0] },
23
- serie: data.map{ |i| i[1] },
23
+ dataset: data.map{ |i| i[1] },
24
24
  height: '132px',
25
25
  compact: true
26
26
  )) %>
data/lib/lesli_view.rb CHANGED
@@ -38,6 +38,8 @@ require "lesli_view/forms/builder_horizontal"
38
38
 
39
39
 
40
40
  # items
41
+ require "lesli_view/items/actions"
42
+ require "lesli_view/items/activities"
41
43
  require "lesli_view/items/discussion"
42
44
  require "lesli_view/items/discussions"
43
45
 
data/readme.md CHANGED
@@ -7,14 +7,17 @@
7
7
  <hr/>
8
8
 
9
9
  <div align="center" class="documentation-statics">
10
- <a target="blank" href="https://rubygems.org/gems/lesli">
11
- <img height="22" alt="Gem Version" src="https://badge.fury.io/rb/lesli.svg"/>
10
+ <a target="blank" href="https://github.com/LesliTech/LesliView/actions">
11
+ <img alt="Tests passing" src="https://img.shields.io/badge/Tests-passing-green?style=for-the-badge&logo=github">
12
12
  </a>
13
- <a class="mx-2" href="https://codecov.io/github/LesliTech/Lesli">
14
- <img height="22" src="https://codecov.io/github/LesliTech/Lesli/graph/badge.svg?token=2O12NENK5Y"/>
13
+ <a target="blank" href="https://rubygems.org/gems/lesli_view">
14
+ <img alt="Gem Version" src="https://img.shields.io/gem/v/lesli_view?style=for-the-badge&logo=ruby">
15
15
  </a>
16
- <a href="https://codecov.io/github/LesliTech/LesliBabel">
17
- <img height="22" src="https://sonarcloud.io/api/project_badges/measure?project=LesliTech_LesliBabel&metric=sqale_rating"/>
16
+ <a target="blank" href="https://codecov.io/github/LesliTech/LesliView">
17
+ <img alt="Codecov" src="https://img.shields.io/codecov/c/github/LesliTech/LesliView?style=for-the-badge&logo=codecov">
18
+ </a>
19
+ <a target="blank" href="https://sonarcloud.io/project/overview?id=LesliTech_LesliView">
20
+ <img alt="Sonar Quality Gate" src="https://img.shields.io/sonar/quality_gate/LesliTech_LesliView?server=https%3A%2F%2Fsonarcloud.io&style=for-the-badge&logo=sonarqubecloud&label=Quality">
18
21
  </a>
19
22
  </div>
20
23
 
@@ -30,45 +33,31 @@ bundle add lesli_view
30
33
  ```
31
34
 
32
35
 
33
- ### Usage
34
-
35
- ```erb
36
- # app/views/lesli_support/tickets/index.html.erb
37
-
38
- <%= render(LesliView::Layout::Container.new("support-tickets")) do %>
36
+ <br />
37
+ <hr/>
38
+ <br />
39
39
 
40
- <%= render(LesliView::Components::Header.new("Tickets")) %>
41
- <%= render(LesliView::Components::Toolbar.new()) %>
40
+ ### Demo
42
41
 
43
- <%= render(LesliView::Elements::Table.new(
44
- :columns => columns,
45
- :records => @tickets.dig(:records),
46
- link: -> (ticket) { ticket_path(ticket.id) }
47
- )) %>
48
- <% end %>
49
- ```
42
+ * [online demo](https://demo.lesli.dev/)
43
+ * [docker demo](https://github.com/LesliTech/lesli-docker-demo)
50
44
 
51
45
 
52
46
  ### Documentation
53
- - **Components:**
54
- - [Header](https://www.lesli.dev/gems/view/component-header)
55
-
56
-
57
- ### Lesli Documentation
58
47
  * [website](https://www.lesli.dev/)
59
48
  * [documentation](https://www.lesli.dev/gems/view/)
60
49
 
61
50
 
62
- ### Get in touch with Lesli
51
+ ### Connect with Lesli
63
52
 
53
+ * [X: @LesliTech](https://x.com/LesliTech)
64
54
  * [Email: hello@lesli.tech](hello@lesli.tech)
65
55
  * [Website: https://www.lesli.tech](https://www.lesli.tech)
66
- * [Twitter: @LesliTech](https://twitter.com/LesliTech)
67
56
 
68
57
 
69
58
  ### License
70
59
  -------
71
- Copyright (c) 2025, Lesli Technologies, S. A.
60
+ Copyright (c) 2026, Lesli Technologies, S. A.
72
61
 
73
62
  This program is free software: you can redistribute it and/or modify
74
63
  it under the terms of the GNU General Public License as published by
@@ -83,10 +72,17 @@ GNU General Public License for more details.
83
72
  You should have received a copy of the GNU General Public License
84
73
  along with this program. If not, see http://www.gnu.org/licenses/.
85
74
 
75
+ <br />
86
76
  <hr />
87
77
  <br />
78
+ <br />
88
79
 
89
80
  <div align="center" class="has-text-centered">
90
81
  <img width="200" alt="Lesli logo" src="https://cdn.lesli.tech/lesli/brand/app-logo.svg" />
91
- <h4 align="center" class="mt-0">Ruby on Rails SaaS Development Framework.</h4>
82
+ <h3 align="center" class="mt-0">
83
+ The Open-Source SaaS Development Framework for Ruby on Rails.
84
+ </h3>
92
85
  </div>
86
+
87
+ <br />
88
+ <br />
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lesli_view
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.6
4
+ version: 1.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - The Lesli Development Team
@@ -69,6 +69,11 @@ files:
69
69
  - lib/lesli_view/forms/fieldset.rb
70
70
  - lib/lesli_view/forms/form.scss
71
71
  - lib/lesli_view/forms/inputs.rb
72
+ - lib/lesli_view/items/actions.html.erb
73
+ - lib/lesli_view/items/actions.rb
74
+ - lib/lesli_view/items/activities.html.erb
75
+ - lib/lesli_view/items/activities.rb
76
+ - lib/lesli_view/items/activities.scss
72
77
  - lib/lesli_view/items/discussion.html.erb
73
78
  - lib/lesli_view/items/discussion.rb
74
79
  - lib/lesli_view/items/discussions.html.erb