terrazzo 0.5.2 → 0.5.3

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: c8d1fb21a6af1c708437891c1e3216a2749fb682513c40c4c583a950e92750f5
4
- data.tar.gz: 47a449b824bf9f5a2cf00e7619aa5d008526f7b8d764258022a3d3ff43109c58
3
+ metadata.gz: 6976f4987f794484e19de73da573e1b7d65dfc75a0852133c1eebf005d22167e
4
+ data.tar.gz: 4dc5597241838c5523ed2a5a50d23185a0e21199b18ae9dd07128d7687e836e6
5
5
  SHA512:
6
- metadata.gz: e3970087e358e8ef4988ff18d3dff5c9a28de0253f5358afb0b54aeada98878ac16ad2b1f85a057e0c101bea47a74d6c79a63c259781571cc1b7d95327712bf8
7
- data.tar.gz: c85f00757f7f54a86fa37d7f9509e109f672cf074eb9e88370132e74d5ccbc1e4bf0345c9410e396f85770a9b936658f5f637554e94bf7a7de46fc379c901e23
6
+ metadata.gz: 673cd873e8c295de85c4bc2d798a33d4879e37cfded9357d01c08b1617e050931502193c3be3c445f0577f4bc29372bc15867b3e4fafe519161f6209d894ca4f
7
+ data.tar.gz: ae15ddf2abd934407d97f3e17d4344e68f5ff93e7fce588f9d520998d017404f980c7f75d07709ba2e984ae49490d65d9a573d4f169949c8b03cce849402f46b
@@ -9,11 +9,11 @@ show_field_json = ->(json, field) do
9
9
 
10
10
  if field.class.associative? && field.data.present?
11
11
  if field.is_a?(Terrazzo::Field::HasMany)
12
- json.itemShowPaths(field.data.each_with_object({}) do |record, paths|
13
- paths[record.id.to_s] = polymorphic_path([namespace, record]) rescue nil
14
- end)
15
- json.collectionItemActions(field.data.each_with_object({}) do |record, hash|
16
- hash[record.id.to_s] = collection_item_actions(record)
12
+ render_actions = field.options.fetch(:render_actions, true)
13
+ json.hasManyRowExtras(field.data.each_with_object({}) do |record, hash|
14
+ extras = { showPath: (polymorphic_path([namespace, record]) rescue nil) }
15
+ extras[:collectionItemActions] = collection_item_actions(record) if render_actions
16
+ hash[record.id.to_s] = extras
17
17
  end)
18
18
  else
19
19
  json.showPath polymorphic_path([namespace, field.data]) rescue nil
@@ -1,85 +1,36 @@
1
- import React, { useState, useContext } from "react";
2
- import { NavigationContext } from "@thoughtbot/superglue";
1
+ import React, { useState } from "react";
3
2
 
4
- import {
5
- Table,
6
- TableHeader,
7
- TableBody,
8
- TableRow,
9
- TableHead,
10
- TableCell,
11
- } from "terrazzo/ui";
3
+ import { ResourceTable } from "terrazzo/components";
12
4
  import { Badge } from "terrazzo/ui";
13
5
  import { Button } from "terrazzo/ui";
14
- import { CollectionItemActions } from "terrazzo/components";
15
- import { FieldRenderer } from "../FieldRenderer";
16
6
 
17
- export function ShowField({ value, itemShowPaths, collectionItemActions }) {
7
+ export function ShowField({ value, hasManyRowExtras, options }) {
18
8
  if (!value) return <span className="text-muted-foreground">None</span>;
19
9
 
20
- const { items, headers, total, initialLimit } = value;
10
+ const { rows, headers, total, initialLimit, items } = value;
21
11
  const [expanded, setExpanded] = useState(false);
22
- const { visit } = useContext(NavigationContext);
23
12
 
24
- if (!items || items.length === 0) {
25
- return <span className="text-muted-foreground">None</span>;
26
- }
13
+ // Table mode: collection_attributes specified
14
+ if (headers && rows) {
15
+ if (rows.length === 0) {
16
+ return <span className="text-muted-foreground">None</span>;
17
+ }
27
18
 
28
- const pathFor = (id) => itemShowPaths?.[String(id)];
29
- const hasMore = initialLimit && initialLimit > 0 && total > initialLimit;
30
- const visibleItems = expanded || !hasMore ? items : items.slice(0, initialLimit);
19
+ const hasMore = initialLimit && initialLimit > 0 && total > initialLimit;
20
+ const visibleRows = expanded || !hasMore ? rows : rows.slice(0, initialLimit);
31
21
 
32
- const handleRowClick = (e, showPath) => {
33
- if (!showPath) return;
34
- if (e.target.closest("a, button, form")) return;
35
- if (window.getSelection().toString()) return;
36
- visit(showPath, {});
37
- };
22
+ const enrichedRows = visibleRows.map((row) => {
23
+ const extras = hasManyRowExtras?.[String(row.id)] || {};
24
+ return {
25
+ ...row,
26
+ showPath: extras.showPath,
27
+ collectionItemActions: extras.collectionItemActions,
28
+ };
29
+ });
38
30
 
39
- // Table mode: collection_attributes specified
40
- if (headers) {
41
31
  return (
42
32
  <div>
43
- <div className="rounded-md border">
44
- <Table>
45
- <TableHeader>
46
- <TableRow>
47
- {headers.map((header) =>
48
- <TableHead key={header.attribute}>{header.label}</TableHead>
49
- )}
50
- {collectionItemActions && <TableHead></TableHead>}
51
- </TableRow>
52
- </TableHeader>
53
- <TableBody>
54
- {visibleItems.map((item) => {
55
- const showPath = pathFor(item.id);
56
- return (
57
- <TableRow
58
- key={item.id}
59
- className={showPath ? "cursor-pointer" : ""}
60
- onClick={(e) => handleRowClick(e, showPath)}>
61
- {item.columns.map((col, colIndex) =>
62
- <TableCell key={col.attribute}>
63
- {showPath && colIndex === 0 ? (
64
- <a href={showPath} data-sg-visit className="hover:underline">
65
- <FieldRenderer mode="index" {...col} />
66
- </a>
67
- ) : (
68
- <FieldRenderer mode="index" {...col} />
69
- )}
70
- </TableCell>
71
- )}
72
- {collectionItemActions && (
73
- <TableCell>
74
- <CollectionItemActions actions={collectionItemActions?.[String(item.id)]} />
75
- </TableCell>
76
- )}
77
- </TableRow>
78
- );
79
- })}
80
- </TableBody>
81
- </Table>
82
- </div>
33
+ <ResourceTable headers={headers} rows={enrichedRows} showActions={options?.renderActions !== false} />
83
34
  {hasMore && (
84
35
  <Button
85
36
  variant="link"
@@ -93,12 +44,19 @@ export function ShowField({ value, itemShowPaths, collectionItemActions }) {
93
44
  );
94
45
  }
95
46
 
96
- // Simple list mode
47
+ // Simple list mode (no collection_attributes)
48
+ if (!items || items.length === 0) {
49
+ return <span className="text-muted-foreground">None</span>;
50
+ }
51
+
52
+ const hasMore = initialLimit && initialLimit > 0 && total > initialLimit;
53
+ const visibleItems = expanded || !hasMore ? items : items.slice(0, initialLimit);
54
+
97
55
  return (
98
56
  <div>
99
57
  <div className="flex flex-wrap items-center gap-1.5">
100
58
  {visibleItems.map((item) => {
101
- const showPath = pathFor(item.id);
59
+ const showPath = hasManyRowExtras?.[String(item.id)]?.showPath;
102
60
  return showPath ? (
103
61
  <a key={item.id} href={showPath} data-sg-visit>
104
62
  <Badge variant="secondary" className="cursor-pointer">{item.display}</Badge>
@@ -1,55 +1,11 @@
1
- import React, { useContext } from "react";
2
- import { NavigationContext } from "@thoughtbot/superglue";
1
+ import React from "react";
3
2
 
4
- import { SortableHeader, CollectionItemActions } from "terrazzo/components";
5
- import { FieldRenderer } from "terrazzo/fields";
6
- import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from "terrazzo/ui";
3
+ import { ResourceTable } from "terrazzo/components";
7
4
 
8
5
  export function AdminCollection({ table }) {
9
- const { visit } = useContext(NavigationContext);
10
-
11
- const handleRowClick = (e, showPath) => {
12
- if (!showPath) return;
13
- if (e.target.closest("a, button, form")) return;
14
- if (window.getSelection().toString()) return;
15
- visit(showPath, {});
16
- };
17
-
18
6
  return (
19
- <div className="overflow-x-auto rounded-md border">
20
- <Table>
21
- <TableHeader>
22
- <TableRow>
23
- {table.headers.map((header) =>
24
- <SortableHeader key={header.attribute} {...header} />
25
- )}
26
- <TableHead className="w-[120px]">Actions</TableHead>
27
- </TableRow>
28
- </TableHeader>
29
- <TableBody>
30
- {table.rows.map((row) =>
31
- <TableRow
32
- key={row.id}
33
- className={row.showPath ? "cursor-pointer" : ""}
34
- onClick={(e) => handleRowClick(e, row.showPath)}>
35
- {row.cells.map((cell) =>
36
- <TableCell key={cell.attribute}>
37
- {cell.showPath ? (
38
- <a href={cell.showPath} data-sg-visit className="hover:underline">
39
- <FieldRenderer mode="index" {...cell} />
40
- </a>
41
- ) : (
42
- <FieldRenderer mode="index" {...cell} />
43
- )}
44
- </TableCell>
45
- )}
46
- <TableCell>
47
- <CollectionItemActions actions={row.collectionItemActions} />
48
- </TableCell>
49
- </TableRow>
50
- )}
51
- </TableBody>
52
- </Table>
7
+ <div className="overflow-x-auto">
8
+ <ResourceTable headers={table.headers} rows={table.rows} />
53
9
  </div>
54
10
  );
55
11
  }
@@ -20,8 +20,14 @@ module Terrazzo
20
20
  end
21
21
 
22
22
  def serializable_options(page = nil)
23
- return {} unless page == :form && resource
24
- { resourceOptions: resource_options }
23
+ opts = {}
24
+ if page == :form && resource
25
+ opts[:resourceOptions] = resource_options
26
+ end
27
+ if options.key?(:render_actions)
28
+ opts[:renderActions] = options[:render_actions]
29
+ end
30
+ opts
25
31
  end
26
32
 
27
33
  class << self
@@ -72,8 +78,8 @@ module Terrazzo
72
78
  { attribute: attr.to_s, label: attr.to_s.humanize }
73
79
  end
74
80
 
75
- items = records.map do |record|
76
- columns = col_attrs.map do |attr|
81
+ rows = records.map do |record|
82
+ cells = col_attrs.map do |attr|
77
83
  field = dashboard_class.new.attribute_type_for(attr).new(attr, nil, :index, resource: record)
78
84
  {
79
85
  attribute: attr.to_s,
@@ -81,12 +87,12 @@ module Terrazzo
81
87
  value: field.serialize_value(:index)
82
88
  }
83
89
  end
84
- { id: record.id.to_s, columns: columns }
90
+ { id: record.id.to_s, cells: cells }
85
91
  end
86
92
 
87
93
  {
88
94
  headers: headers,
89
- items: items,
95
+ rows: rows,
90
96
  total: total,
91
97
  initialLimit: limit
92
98
  }
@@ -1,3 +1,3 @@
1
1
  module Terrazzo
2
- VERSION = "0.5.2"
2
+ VERSION = "0.5.3"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: terrazzo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Terrazzo Contributors