terrazzo 0.2.1 → 0.2.2

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: '0668700d10e6547d3366e74348a33674733828a834d3be9dd02ddd7effab6bd8'
4
- data.tar.gz: d85d82e780f8820d1b306ac5f63c3d1a96802da1f56f301e11b8040903372601
3
+ metadata.gz: b55338dd365f9ad475e3892c34a4a5ca706625b50bd331dd6793bbd756ec75e7
4
+ data.tar.gz: a5193fda7a10ca72103816e0f47a58ba7facf375003a4af22efa0385914378b2
5
5
  SHA512:
6
- metadata.gz: 84bff5afcc8deb6b423f7112593c318b80716c384d7e1140d596e50b816de4e8c651bb76d9cfa4653b5154ec1c28a7185052928f136fcdafa044ef3d8762f4c4
7
- data.tar.gz: eaec2494d92552710c555f3f45db30688e29ca4a20af4d29c488aa8d15f62efaa42d7ae8e399c95d5c3cb291bb36f3001f9e96e5e4c47d02ae3009490b377f3c
6
+ metadata.gz: d048907fe5b71cee9100ce4cd7a1b606e666972be105a39f15c24f3119531deccc4bc7cb85144b65623faf933dbebfd1f78d61b841909872046afe754c3ea71f
7
+ data.tar.gz: 6eb4e86c0a06cd790094cc0829313894f2c9d7b6ce232327a5c46610d9d507c5215b87ec81c3a136c0e5ac2b6841c22de4f81b0544a46aba2846a1f8e762f009
@@ -43,6 +43,10 @@ json.table do
43
43
  json.fieldType field.field_type
44
44
  json.value field.serialize_value(:index)
45
45
  json.options field.serializable_options
46
+
47
+ if field.class.associative? && field.data.present?
48
+ json.showPath polymorphic_path([namespace, field.data]) rescue nil
49
+ end
46
50
  end
47
51
  end
48
52
  end
@@ -1,15 +1,29 @@
1
1
  json.pageTitle @page.page_title
2
2
 
3
+ show_field_json = ->(json, field) do
4
+ json.attribute field.attribute.to_s
5
+ json.label field.attribute.to_s.humanize
6
+ json.fieldType field.field_type
7
+ json.value field.serialize_value(:show)
8
+ json.options field.serializable_options
9
+
10
+ if field.class.associative? && field.data.present?
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
+ else
16
+ json.showPath polymorphic_path([namespace, field.data]) rescue nil
17
+ end
18
+ end
19
+ end
20
+
3
21
  json.attributeGroups do
4
22
  json.array! @page.grouped_attributes do |group|
5
23
  json.name group[:name]
6
24
  json.attributes do
7
25
  json.array! group[:fields] do |field|
8
- json.attribute field.attribute.to_s
9
- json.label field.attribute.to_s.humanize
10
- json.fieldType field.field_type
11
- json.value field.serialize_value(:show)
12
- json.options field.serializable_options
26
+ show_field_json.call(json, field)
13
27
  end
14
28
  end
15
29
  end
@@ -17,11 +31,7 @@ end
17
31
 
18
32
  json.attributes do
19
33
  json.array! @page.attributes do |field|
20
- json.attribute field.attribute.to_s
21
- json.label field.attribute.to_s.humanize
22
- json.fieldType field.field_type
23
- json.value field.serialize_value(:show)
24
- json.options field.serializable_options
34
+ show_field_json.call(json, field)
25
35
  end
26
36
  end
27
37
 
@@ -1,4 +1,4 @@
1
- import React from "react";
1
+ import React, { useState } from "react";
2
2
 
3
3
  import {
4
4
  Table,
@@ -8,17 +8,24 @@ import {
8
8
  TableHead,
9
9
  TableCell,
10
10
  } from "../../components/ui/table";
11
+ import { Badge } from "../../components/ui/badge";
12
+ import { Button } from "../../components/ui/button";
11
13
  import { FieldRenderer } from "../FieldRenderer";
12
14
 
13
- export function ShowField({ value }) {
15
+ export function ShowField({ value, itemShowPaths }) {
14
16
  if (!value) return <span className="text-muted-foreground">None</span>;
15
17
 
16
- const { items, headers, total, hasMore } = value;
18
+ const { items, headers, total, initialLimit } = value;
19
+ const [expanded, setExpanded] = useState(false);
17
20
 
18
21
  if (!items || items.length === 0) {
19
22
  return <span className="text-muted-foreground">None</span>;
20
23
  }
21
24
 
25
+ const pathFor = (id) => itemShowPaths?.[String(id)];
26
+ const hasMore = initialLimit && initialLimit > 0 && total > initialLimit;
27
+ const visibleItems = expanded || !hasMore ? items : items.slice(0, initialLimit);
28
+
22
29
  // Table mode: collection_attributes specified
23
30
  if (headers) {
24
31
  return (
@@ -33,22 +40,35 @@ export function ShowField({ value }) {
33
40
  </TableRow>
34
41
  </TableHeader>
35
42
  <TableBody>
36
- {items.map((item) =>
37
- <TableRow key={item.id}>
38
- {item.columns.map((col) =>
39
- <TableCell key={col.attribute}>
40
- <FieldRenderer mode="index" {...col} />
41
- </TableCell>
42
- )}
43
- </TableRow>
44
- )}
43
+ {visibleItems.map((item) => {
44
+ const showPath = pathFor(item.id);
45
+ return (
46
+ <TableRow key={item.id}>
47
+ {item.columns.map((col, colIndex) =>
48
+ <TableCell key={col.attribute}>
49
+ {showPath && colIndex === 0 ? (
50
+ <a href={showPath} data-sg-visit className="hover:underline">
51
+ <FieldRenderer mode="index" {...col} />
52
+ </a>
53
+ ) : (
54
+ <FieldRenderer mode="index" {...col} />
55
+ )}
56
+ </TableCell>
57
+ )}
58
+ </TableRow>
59
+ );
60
+ })}
45
61
  </TableBody>
46
62
  </Table>
47
63
  </div>
48
64
  {hasMore && (
49
- <p className="text-sm text-muted-foreground mt-2">
50
- Showing {items.length} of {total}
51
- </p>
65
+ <Button
66
+ variant="link"
67
+ size="sm"
68
+ className="mt-2 px-0"
69
+ onClick={() => setExpanded(!expanded)}>
70
+ {expanded ? "Show less" : `Show ${total - initialLimit} more`}
71
+ </Button>
52
72
  )}
53
73
  </div>
54
74
  );
@@ -57,16 +77,27 @@ export function ShowField({ value }) {
57
77
  // Simple list mode
58
78
  return (
59
79
  <div>
60
- <ul className="list-disc pl-5 space-y-1">
61
- {items.map((item) =>
62
- <li key={item.id}>{item.display}</li>
80
+ <div className="flex flex-wrap items-center gap-1.5">
81
+ {visibleItems.map((item) => {
82
+ const showPath = pathFor(item.id);
83
+ return showPath ? (
84
+ <a key={item.id} href={showPath} data-sg-visit>
85
+ <Badge variant="secondary" className="cursor-pointer">{item.display}</Badge>
86
+ </a>
87
+ ) : (
88
+ <Badge key={item.id} variant="secondary">{item.display}</Badge>
89
+ );
90
+ })}
91
+ {hasMore && (
92
+ <Button
93
+ variant="link"
94
+ size="sm"
95
+ className="px-0"
96
+ onClick={() => setExpanded(!expanded)}>
97
+ {expanded ? "Show less" : `Show ${total - initialLimit} more`}
98
+ </Button>
63
99
  )}
64
- </ul>
65
- {hasMore && (
66
- <p className="text-sm text-muted-foreground mt-2">
67
- Showing {items.length} of {total}
68
- </p>
69
- )}
100
+ </div>
70
101
  </div>
71
102
  );
72
103
  }
@@ -1,5 +1,5 @@
1
- import React from "react";
2
- import { useContent } from "@thoughtbot/superglue";
1
+ import React, { useContext } from "react";
2
+ import { useContent, NavigationContext } from "@thoughtbot/superglue";
3
3
 
4
4
  import { Layout } from "../components/Layout";
5
5
  import { SearchBar } from "../components/SearchBar";
@@ -17,6 +17,7 @@ import {
17
17
  } from "../components/ui/table";
18
18
 
19
19
  export default function AdminIndex() {
20
+ const { visit } = useContext(NavigationContext);
20
21
  const {
21
22
  table,
22
23
  searchBar,
@@ -27,6 +28,13 @@ export default function AdminIndex() {
27
28
  singularResourceName
28
29
  } = useContent();
29
30
 
31
+ const handleRowClick = (e, showPath) => {
32
+ if (!showPath) return;
33
+ if (e.target.closest("a, button, form")) return;
34
+ if (window.getSelection().toString()) return;
35
+ visit(showPath, {});
36
+ };
37
+
30
38
  return (
31
39
  <Layout
32
40
  navigation={navigation}
@@ -53,10 +61,19 @@ export default function AdminIndex() {
53
61
  </TableHeader>
54
62
  <TableBody>
55
63
  {table.rows.map((row) =>
56
- <TableRow key={row.id}>
64
+ <TableRow
65
+ key={row.id}
66
+ className={row.showPath ? "cursor-pointer" : ""}
67
+ onClick={(e) => handleRowClick(e, row.showPath)}>
57
68
  {row.cells.map((cell) =>
58
69
  <TableCell key={cell.attribute}>
59
- <FieldRenderer mode="index" {...cell} />
70
+ {cell.showPath ? (
71
+ <a href={cell.showPath} data-sg-visit className="hover:underline">
72
+ <FieldRenderer mode="index" {...cell} />
73
+ </a>
74
+ ) : (
75
+ <FieldRenderer mode="index" {...cell} />
76
+ )}
60
77
  </TableCell>
61
78
  )}
62
79
  <TableCell>
@@ -69,7 +69,13 @@ export default function AdminShow() {
69
69
  {attr.label}
70
70
  </dt>
71
71
  <dd className="col-span-2 text-sm">
72
- <FieldRenderer mode="show" {...attr} />
72
+ {attr.showPath ? (
73
+ <a href={attr.showPath} data-sg-visit className="hover:underline">
74
+ <FieldRenderer mode="show" {...attr} />
75
+ </a>
76
+ ) : (
77
+ <FieldRenderer mode="show" {...attr} />
78
+ )}
73
79
  </dd>
74
80
  </div>
75
81
  )}
@@ -42,22 +42,17 @@ module Terrazzo
42
42
 
43
43
  def serialize_show_value
44
44
  limit = options.fetch(:limit, 5)
45
- total = data.size
45
+ all_records = data.to_a
46
+ total = all_records.size
46
47
  col_attrs = options[:collection_attributes]
47
48
 
48
- records = if limit && limit > 0
49
- data.respond_to?(:limit) ? data.limit(limit) : data.first(limit)
50
- else
51
- data
52
- end
53
-
54
49
  if col_attrs
55
- serialize_with_collection_attributes(records, col_attrs, total, limit)
50
+ serialize_with_collection_attributes(all_records, col_attrs, total, limit)
56
51
  else
57
52
  {
58
- items: records.map { |r| { id: r.id, display: display_name(r) } },
53
+ items: all_records.map { |r| { id: r.id, display: display_name(r) } },
59
54
  total: total,
60
- hasMore: limit && limit > 0 ? total > limit : false
55
+ initialLimit: limit
61
56
  }
62
57
  end
63
58
  end
@@ -85,7 +80,7 @@ module Terrazzo
85
80
  headers: headers,
86
81
  items: items,
87
82
  total: total,
88
- hasMore: limit && limit > 0 ? total > limit : false
83
+ initialLimit: limit
89
84
  }
90
85
  end
91
86
 
@@ -1,3 +1,3 @@
1
1
  module Terrazzo
2
- VERSION = "0.2.1"
2
+ VERSION = "0.2.2"
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.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Terrazzo Contributors