datajunction-ui 0.0.1-a59 → 0.0.1-a61

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "datajunction-ui",
3
- "version": "0.0.1a59",
3
+ "version": "0.0.1a61",
4
4
  "description": "DataJunction Metrics Platform UI",
5
5
  "module": "src/index.tsx",
6
6
  "repository": {
@@ -165,7 +165,7 @@
165
165
  "coverageThreshold": {
166
166
  "global": {
167
167
  "statements": 87,
168
- "branches": 75,
168
+ "branches": 74,
169
169
  "lines": 80,
170
170
  "functions": 85
171
171
  }
@@ -0,0 +1,43 @@
1
+ export default function AddNodeDropDown({ namespace }) {
2
+ return (
3
+ <span className="menu-link">
4
+ <span className="menu-title">
5
+ <div className="dropdown">
6
+ <span className="add_node">+ Add Node</span>
7
+ <div className="dropdown-content">
8
+ <a href={`/create/source`}>
9
+ <div className="node_type__source node_type_creation_heading">
10
+ Register Table
11
+ </div>
12
+ </a>
13
+ <a href={`/create/transform/${namespace}`}>
14
+ <div className="node_type__transform node_type_creation_heading">
15
+ Transform
16
+ </div>
17
+ </a>
18
+ <a href={`/create/metric/${namespace}`}>
19
+ <div className="node_type__metric node_type_creation_heading">
20
+ Metric
21
+ </div>
22
+ </a>
23
+ <a href={`/create/dimension/${namespace}`}>
24
+ <div className="node_type__dimension node_type_creation_heading">
25
+ Dimension
26
+ </div>
27
+ </a>
28
+ <a href={`/create/tag`}>
29
+ <div className="entity__tag node_type_creation_heading">
30
+ Tag
31
+ </div>
32
+ </a>
33
+ <a href={`/create/cube/${namespace}`}>
34
+ <div className="node_type__cube node_type_creation_heading">
35
+ Cube
36
+ </div>
37
+ </a>
38
+ </div>
39
+ </div>
40
+ </span>
41
+ </span>
42
+ );
43
+ }
@@ -4,11 +4,18 @@ import { useContext, useEffect, useState } from 'react';
4
4
  import NodeStatus from '../NodePage/NodeStatus';
5
5
  import DJClientContext from '../../providers/djclient';
6
6
  import Explorer from '../NamespacePage/Explorer';
7
+ import AddNodeDropdown from '../../components/AddNodeDropdown';
7
8
  import NodeListActions from '../../components/NodeListActions';
8
9
  import AddNamespacePopover from './AddNamespacePopover';
9
10
  import 'styles/node-list.css';
11
+ import 'styles/sorted-table.css';
10
12
 
11
13
  export function NamespacePage() {
14
+ const ASC = 'ascending';
15
+ const DESC = 'descending';
16
+
17
+ const fields = ['name', 'display_name', 'type', 'status', 'updated_at'];
18
+
12
19
  const djClient = useContext(DJClientContext).DataJunctionAPI;
13
20
  var { namespace } = useParams();
14
21
 
@@ -19,6 +26,38 @@ export function NamespacePage() {
19
26
 
20
27
  const [namespaceHierarchy, setNamespaceHierarchy] = useState([]);
21
28
 
29
+ const [sortConfig, setSortConfig] = useState({ key: 'updated_at', direction: DESC });
30
+ const sortedNodes = React.useMemo(() => {
31
+ let sortableData = [...Object.values(state.nodes)];
32
+ if (sortConfig !== null) {
33
+ sortableData.sort((a, b) => {
34
+ if (a[sortConfig.key] < b[sortConfig.key]) {
35
+ return sortConfig.direction === ASC ? -1 : 1;
36
+ }
37
+ if (a[sortConfig.key] > b[sortConfig.key]) {
38
+ return sortConfig.direction === ASC ? 1 : -1;
39
+ }
40
+ return 0;
41
+ });
42
+ }
43
+ return sortableData;
44
+ }, [state.nodes, sortConfig]);
45
+
46
+ const requestSort = (key) => {
47
+ let direction = ASC;
48
+ if (sortConfig.key === key && sortConfig.direction === ASC) {
49
+ direction = DESC;
50
+ }
51
+ setSortConfig({ key, direction });
52
+ };
53
+
54
+ const getClassNamesFor = (name) => {
55
+ if (sortConfig.key === name) {
56
+ return sortConfig.direction;
57
+ }
58
+ return undefined;
59
+ };
60
+
22
61
  const createNamespaceHierarchy = namespaceList => {
23
62
  const hierarchy = [];
24
63
 
@@ -71,7 +110,7 @@ export function NamespacePage() {
71
110
  fetchData().catch(console.error);
72
111
  }, [djClient, namespace, namespaceHierarchy]);
73
112
 
74
- const nodesList = state.nodes.map(node => (
113
+ const nodesList = sortedNodes.map(node => (
75
114
  <tr>
76
115
  <td>
77
116
  <a href={'/nodes/' + node.name} className="link-table">
@@ -97,9 +136,6 @@ export function NamespacePage() {
97
136
  <td>
98
137
  <NodeStatus node={node} revalidate={false} />
99
138
  </td>
100
- <td>
101
- <span className="status">{node.mode}</span>
102
- </td>
103
139
  <td>
104
140
  <span className="status">
105
141
  {new Date(node.updated_at).toLocaleString('en-us')}
@@ -116,46 +152,7 @@ export function NamespacePage() {
116
152
  <div className="card">
117
153
  <div className="card-header">
118
154
  <h2>Explore</h2>
119
-
120
- <span className="menu-link">
121
- <span className="menu-title">
122
- <div className="dropdown">
123
- <span className="add_node">+ Add Node</span>
124
- <div className="dropdown-content">
125
- <a href={`/create/source`}>
126
- <div className="node_type__source node_type_creation_heading">
127
- Register Table
128
- </div>
129
- </a>
130
- <a href={`/create/transform/${namespace}`}>
131
- <div className="node_type__transform node_type_creation_heading">
132
- Transform
133
- </div>
134
- </a>
135
- <a href={`/create/metric/${namespace}`}>
136
- <div className="node_type__metric node_type_creation_heading">
137
- Metric
138
- </div>
139
- </a>
140
- <a href={`/create/dimension/${namespace}`}>
141
- <div className="node_type__dimension node_type_creation_heading">
142
- Dimension
143
- </div>
144
- </a>
145
- <a href={`/create/tag`}>
146
- <div className="entity__tag node_type_creation_heading">
147
- Tag
148
- </div>
149
- </a>
150
- <a href={`/create/cube/${namespace}`}>
151
- <div className="node_type__cube node_type_creation_heading">
152
- Cube
153
- </div>
154
- </a>
155
- </div>
156
- </div>
157
- </span>
158
- </span>
155
+ <AddNodeDropdown namespace={namespace} />
159
156
  <div className="table-responsive">
160
157
  <div className={`sidebar`}>
161
158
  <span
@@ -182,12 +179,15 @@ export function NamespacePage() {
182
179
  <table className="card-table table">
183
180
  <thead>
184
181
  <tr>
185
- <th>Name</th>
186
- <th>Display Name</th>
187
- <th>Type</th>
188
- <th>Status</th>
189
- <th>Mode</th>
190
- <th>Last Updated</th>
182
+ {fields.map(field => {
183
+ return (
184
+ <th>
185
+ <button type="button" onClick={() => requestSort(field)} className={'sortable ' + getClassNamesFor(field)}>
186
+ {field.replace('_', ' ')}
187
+ </button>
188
+ </th>
189
+ );
190
+ })}
191
191
  <th>Actions</th>
192
192
  </tr>
193
193
  </thead>
@@ -730,6 +730,11 @@ pre {
730
730
  margin: 0;
731
731
  list-style: none;
732
732
  }
733
+ .menu-link {
734
+ display: inline-grid;
735
+ margin: 2em 1em 0 0;
736
+ float: right;
737
+ }
733
738
  .menu-item .menu-link {
734
739
  cursor: pointer;
735
740
  align-items: center;
@@ -773,6 +778,7 @@ pre {
773
778
 
774
779
  .card-header h2 {
775
780
  font-family: 'Jost';
781
+ display: inline-block;
776
782
  }
777
783
 
778
784
  .text-gray-400 {
@@ -0,0 +1,15 @@
1
+ .sortable {
2
+ background: none;
3
+ border: none;
4
+ cursor: pointer;
5
+ font-weight: bold;
6
+ font-family: inherit;
7
+ color: inherit;
8
+ text-transform: uppercase;
9
+ }
10
+ .sortable.ascending::after {
11
+ content: ' ▲';
12
+ }
13
+ .sortable.descending::after {
14
+ content: ' ▼';
15
+ }