datajunction-ui 0.0.30 → 0.0.34
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/TODO.md +265 -0
- package/package.json +1 -1
- package/src/app/components/ListGroupItem.jsx +2 -2
- package/src/app/components/NamespaceHeader.jsx +423 -65
- package/src/app/components/QueryInfo.jsx +2 -1
- package/src/app/components/__tests__/NamespaceHeader.test.jsx +14 -9
- package/src/app/components/__tests__/__snapshots__/ListGroupItem.test.tsx.snap +2 -2
- package/src/app/components/__tests__/__snapshots__/NamespaceHeader.test.jsx.snap +139 -34
- package/src/app/components/djgraph/__tests__/Collapse.test.jsx +6 -3
- package/src/app/pages/AddEditNodePage/index.jsx +1 -1
- package/src/app/pages/AddEditTagPage/index.jsx +1 -1
- package/src/app/pages/CubeBuilderPage/__tests__/index.test.jsx +55 -21
- package/src/app/pages/NamespacePage/index.jsx +44 -511
- package/src/app/pages/NodePage/NodeInfoTab.jsx +17 -6
- package/src/app/pages/NodePage/NodeMaterializationTab.jsx +5 -0
- package/src/app/pages/NodePage/NodePreAggregationsTab.jsx +656 -0
- package/src/app/pages/NodePage/NodeValidateTab.jsx +4 -2
- package/src/app/pages/NodePage/__tests__/NodePage.test.jsx +58 -45
- package/src/app/pages/NodePage/__tests__/NodePreAggregationsTab.test.jsx +654 -0
- package/src/app/pages/NodePage/index.jsx +9 -1
- package/src/app/pages/NotificationsPage/__tests__/index.test.jsx +19 -4
- package/src/app/pages/SQLBuilderPage/__tests__/index.test.jsx +47 -9
- package/src/app/pages/SQLBuilderPage/index.jsx +2 -2
- package/src/app/services/DJService.js +26 -0
- package/src/styles/preaggregations.css +547 -0
|
@@ -7,6 +7,7 @@ import { useCurrentUser } from '../../providers/UserProvider';
|
|
|
7
7
|
import Explorer from '../NamespacePage/Explorer';
|
|
8
8
|
import AddNodeDropdown from '../../components/AddNodeDropdown';
|
|
9
9
|
import NodeListActions from '../../components/NodeListActions';
|
|
10
|
+
import NamespaceHeader from '../../components/NamespaceHeader';
|
|
10
11
|
import LoadingIcon from '../../icons/LoadingIcon';
|
|
11
12
|
import CompactSelect from './CompactSelect';
|
|
12
13
|
import { getDJUrl } from '../../services/DJService';
|
|
@@ -65,7 +66,6 @@ export function NamespacePage() {
|
|
|
65
66
|
|
|
66
67
|
const [filters, setFilters] = useState(getFiltersFromUrl);
|
|
67
68
|
const [moreFiltersOpen, setMoreFiltersOpen] = useState(false);
|
|
68
|
-
const [deploymentsDropdownOpen, setDeploymentsDropdownOpen] = useState(false);
|
|
69
69
|
|
|
70
70
|
// Sync filters state when URL changes
|
|
71
71
|
useEffect(() => {
|
|
@@ -169,8 +169,6 @@ export function NamespacePage() {
|
|
|
169
169
|
|
|
170
170
|
const [namespaceHierarchy, setNamespaceHierarchy] = useState([]);
|
|
171
171
|
const [namespaceSources, setNamespaceSources] = useState({});
|
|
172
|
-
const [currentNamespaceSources, setCurrentNamespaceSources] = useState(null);
|
|
173
|
-
const [recentDeployments, setRecentDeployments] = useState([]);
|
|
174
172
|
|
|
175
173
|
const [sortConfig, setSortConfig] = useState({
|
|
176
174
|
key: 'updatedAt',
|
|
@@ -250,26 +248,6 @@ export function NamespacePage() {
|
|
|
250
248
|
fetchData().catch(console.error);
|
|
251
249
|
}, [djClient, djClient.namespaces]);
|
|
252
250
|
|
|
253
|
-
// Fetch sources for the current namespace (for the header badge)
|
|
254
|
-
useEffect(() => {
|
|
255
|
-
const fetchCurrentSources = async () => {
|
|
256
|
-
if (namespace) {
|
|
257
|
-
const sources = await djClient.namespaceSources(namespace);
|
|
258
|
-
setCurrentNamespaceSources(sources);
|
|
259
|
-
|
|
260
|
-
// Fetch recent deployments for this namespace
|
|
261
|
-
try {
|
|
262
|
-
const deployments = await djClient.listDeployments(namespace, 5);
|
|
263
|
-
setRecentDeployments(deployments || []);
|
|
264
|
-
} catch (err) {
|
|
265
|
-
console.error('Failed to fetch deployments:', err);
|
|
266
|
-
setRecentDeployments([]);
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
};
|
|
270
|
-
fetchCurrentSources().catch(console.error);
|
|
271
|
-
}, [djClient, namespace]);
|
|
272
|
-
|
|
273
251
|
useEffect(() => {
|
|
274
252
|
const fetchData = async () => {
|
|
275
253
|
setRetrieved(false);
|
|
@@ -826,496 +804,51 @@ export function NamespacePage() {
|
|
|
826
804
|
: null}
|
|
827
805
|
</div>
|
|
828
806
|
<div style={{ flex: 1, minWidth: 0, marginLeft: '1.5rem' }}>
|
|
829
|
-
{
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
namespace.split('.').map((part, index, arr) => (
|
|
857
|
-
<span
|
|
858
|
-
key={index}
|
|
859
|
-
style={{
|
|
860
|
-
display: 'flex',
|
|
861
|
-
alignItems: 'center',
|
|
862
|
-
gap: '8px',
|
|
863
|
-
}}
|
|
864
|
-
>
|
|
865
|
-
<a
|
|
866
|
-
href={`/namespaces/${arr
|
|
867
|
-
.slice(0, index + 1)
|
|
868
|
-
.join('.')}`}
|
|
869
|
-
style={{
|
|
870
|
-
fontWeight: '400',
|
|
871
|
-
color: '#1e293b',
|
|
872
|
-
textDecoration: 'none',
|
|
873
|
-
}}
|
|
874
|
-
>
|
|
875
|
-
{part}
|
|
876
|
-
</a>
|
|
877
|
-
{index < arr.length - 1 && (
|
|
878
|
-
<span style={{ color: '#94a3b8', fontWeight: '400' }}>
|
|
879
|
-
/
|
|
880
|
-
</span>
|
|
881
|
-
)}
|
|
882
|
-
</span>
|
|
883
|
-
))
|
|
884
|
-
) : (
|
|
885
|
-
<span style={{ fontWeight: '600', color: '#1e293b' }}>
|
|
886
|
-
All Namespaces
|
|
887
|
-
</span>
|
|
888
|
-
)}
|
|
889
|
-
{currentNamespaceSources &&
|
|
890
|
-
currentNamespaceSources.total_deployments > 0 && (
|
|
891
|
-
<div style={{ position: 'relative', marginLeft: '8px' }}>
|
|
892
|
-
<button
|
|
893
|
-
onClick={() =>
|
|
894
|
-
setDeploymentsDropdownOpen(!deploymentsDropdownOpen)
|
|
895
|
-
}
|
|
896
|
-
style={{
|
|
897
|
-
height: '32px',
|
|
898
|
-
padding: '0 12px',
|
|
899
|
-
fontSize: '12px',
|
|
900
|
-
border: 'none',
|
|
901
|
-
borderRadius: '4px',
|
|
902
|
-
backgroundColor: '#ffffff',
|
|
903
|
-
color: '#0b3d91',
|
|
904
|
-
cursor: 'pointer',
|
|
905
|
-
display: 'flex',
|
|
906
|
-
alignItems: 'center',
|
|
907
|
-
gap: '4px',
|
|
908
|
-
whiteSpace: 'nowrap',
|
|
909
|
-
}}
|
|
910
|
-
>
|
|
911
|
-
{currentNamespaceSources.primary_source?.type ===
|
|
912
|
-
'git' ? (
|
|
913
|
-
<>
|
|
914
|
-
<svg
|
|
915
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
916
|
-
width="12"
|
|
917
|
-
height="12"
|
|
918
|
-
viewBox="0 0 24 24"
|
|
919
|
-
fill="none"
|
|
920
|
-
stroke="currentColor"
|
|
921
|
-
strokeWidth="2"
|
|
922
|
-
strokeLinecap="round"
|
|
923
|
-
strokeLinejoin="round"
|
|
924
|
-
>
|
|
925
|
-
<line x1="6" y1="3" x2="6" y2="15"></line>
|
|
926
|
-
<circle cx="18" cy="6" r="3"></circle>
|
|
927
|
-
<circle cx="6" cy="18" r="3"></circle>
|
|
928
|
-
<path d="M18 9a9 9 0 0 1-9 9"></path>
|
|
929
|
-
</svg>
|
|
930
|
-
Git Managed
|
|
931
|
-
</>
|
|
932
|
-
) : (
|
|
933
|
-
<>
|
|
934
|
-
<svg
|
|
935
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
936
|
-
width="12"
|
|
937
|
-
height="12"
|
|
938
|
-
viewBox="0 0 24 24"
|
|
939
|
-
fill="none"
|
|
940
|
-
stroke="currentColor"
|
|
941
|
-
strokeWidth="2"
|
|
942
|
-
strokeLinecap="round"
|
|
943
|
-
strokeLinejoin="round"
|
|
944
|
-
>
|
|
945
|
-
<circle cx="12" cy="7" r="4" />
|
|
946
|
-
<path d="M5.5 21a6.5 6.5 0 0 1 13 0Z" />
|
|
947
|
-
</svg>
|
|
948
|
-
Local Deploy
|
|
949
|
-
</>
|
|
950
|
-
)}
|
|
951
|
-
<span style={{ fontSize: '8px' }}>
|
|
952
|
-
{deploymentsDropdownOpen ? '▲' : '▼'}
|
|
953
|
-
</span>
|
|
954
|
-
</button>
|
|
955
|
-
|
|
956
|
-
{deploymentsDropdownOpen && (
|
|
957
|
-
<div
|
|
958
|
-
style={{
|
|
959
|
-
position: 'absolute',
|
|
960
|
-
top: '100%',
|
|
961
|
-
left: 0,
|
|
962
|
-
marginTop: '4px',
|
|
963
|
-
padding: '12px',
|
|
964
|
-
backgroundColor: 'white',
|
|
965
|
-
border: '1px solid #ddd',
|
|
966
|
-
borderRadius: '8px',
|
|
967
|
-
boxShadow: '0 4px 12px rgba(0,0,0,0.15)',
|
|
968
|
-
zIndex: 1000,
|
|
969
|
-
minWidth: '340px',
|
|
970
|
-
}}
|
|
971
|
-
>
|
|
972
|
-
{currentNamespaceSources.primary_source?.type ===
|
|
973
|
-
'git' ? (
|
|
974
|
-
<a
|
|
975
|
-
href={
|
|
976
|
-
currentNamespaceSources.primary_source.repository?.startsWith(
|
|
977
|
-
'http',
|
|
978
|
-
)
|
|
979
|
-
? currentNamespaceSources.primary_source
|
|
980
|
-
.repository
|
|
981
|
-
: `https://${currentNamespaceSources.primary_source.repository}`
|
|
982
|
-
}
|
|
983
|
-
target="_blank"
|
|
984
|
-
rel="noopener noreferrer"
|
|
985
|
-
style={{
|
|
986
|
-
display: 'flex',
|
|
987
|
-
alignItems: 'center',
|
|
988
|
-
gap: '8px',
|
|
989
|
-
fontSize: '13px',
|
|
990
|
-
fontWeight: 400,
|
|
991
|
-
textDecoration: 'none',
|
|
992
|
-
marginBottom: '12px',
|
|
993
|
-
}}
|
|
994
|
-
>
|
|
995
|
-
<svg
|
|
996
|
-
width="16"
|
|
997
|
-
height="16"
|
|
998
|
-
viewBox="0 0 24 24"
|
|
999
|
-
fill="none"
|
|
1000
|
-
stroke="currentColor"
|
|
1001
|
-
strokeWidth="2"
|
|
1002
|
-
strokeLinecap="round"
|
|
1003
|
-
strokeLinejoin="round"
|
|
1004
|
-
>
|
|
1005
|
-
<line x1="6" y1="3" x2="6" y2="15" />
|
|
1006
|
-
<circle cx="18" cy="6" r="3" />
|
|
1007
|
-
<circle cx="6" cy="18" r="3" />
|
|
1008
|
-
<path d="M18 9a9 9 0 0 1-9 9" />
|
|
1009
|
-
</svg>
|
|
1010
|
-
{
|
|
1011
|
-
currentNamespaceSources.primary_source
|
|
1012
|
-
.repository
|
|
1013
|
-
}
|
|
1014
|
-
{currentNamespaceSources.primary_source
|
|
1015
|
-
.branch &&
|
|
1016
|
-
` (${currentNamespaceSources.primary_source.branch})`}
|
|
1017
|
-
</a>
|
|
1018
|
-
) : (
|
|
1019
|
-
<div
|
|
1020
|
-
style={{
|
|
1021
|
-
display: 'flex',
|
|
1022
|
-
alignItems: 'center',
|
|
1023
|
-
gap: '8px',
|
|
1024
|
-
fontSize: '13px',
|
|
1025
|
-
fontWeight: 600,
|
|
1026
|
-
color: '#0b3d91',
|
|
1027
|
-
marginBottom: '12px',
|
|
1028
|
-
}}
|
|
1029
|
-
>
|
|
1030
|
-
<svg
|
|
1031
|
-
width="16"
|
|
1032
|
-
height="16"
|
|
1033
|
-
viewBox="0 0 24 24"
|
|
1034
|
-
fill="none"
|
|
1035
|
-
stroke="currentColor"
|
|
1036
|
-
strokeWidth="2"
|
|
1037
|
-
strokeLinecap="round"
|
|
1038
|
-
strokeLinejoin="round"
|
|
1039
|
-
>
|
|
1040
|
-
<circle cx="12" cy="7" r="4" />
|
|
1041
|
-
<path d="M5.5 21a6.5 6.5 0 0 1 13 0Z" />
|
|
1042
|
-
</svg>
|
|
1043
|
-
{recentDeployments?.[0]?.created_by
|
|
1044
|
-
? `Local deploys by ${recentDeployments[0].created_by}`
|
|
1045
|
-
: 'Local/adhoc deployments'}
|
|
1046
|
-
</div>
|
|
1047
|
-
)}
|
|
1048
|
-
|
|
1049
|
-
{/* Separator */}
|
|
1050
|
-
<div
|
|
1051
|
-
style={{
|
|
1052
|
-
height: '1px',
|
|
1053
|
-
backgroundColor: '#e2e8f0',
|
|
1054
|
-
marginBottom: '8px',
|
|
1055
|
-
}}
|
|
1056
|
-
/>
|
|
1057
|
-
|
|
1058
|
-
{/* Recent deployments list (no header) */}
|
|
1059
|
-
{recentDeployments?.length > 0 ? (
|
|
1060
|
-
recentDeployments.map((d, idx) => {
|
|
1061
|
-
const isGit = d.source?.type === 'git';
|
|
1062
|
-
const statusColor =
|
|
1063
|
-
d.status === 'success'
|
|
1064
|
-
? '#22c55e'
|
|
1065
|
-
: d.status === 'failed'
|
|
1066
|
-
? '#ef4444'
|
|
1067
|
-
: '#94a3b8';
|
|
1068
|
-
|
|
1069
|
-
// Build commit URL if available
|
|
1070
|
-
const commitUrl =
|
|
1071
|
-
isGit &&
|
|
1072
|
-
d.source?.repository &&
|
|
1073
|
-
d.source?.commit_sha
|
|
1074
|
-
? `${
|
|
1075
|
-
d.source.repository.startsWith('http')
|
|
1076
|
-
? d.source.repository
|
|
1077
|
-
: `https://${d.source.repository}`
|
|
1078
|
-
}/commit/${d.source.commit_sha}`
|
|
1079
|
-
: null;
|
|
1080
|
-
|
|
1081
|
-
// For git: show branch + short SHA; for local: reason or hostname
|
|
1082
|
-
const detail = isGit
|
|
1083
|
-
? d.source?.branch || 'main'
|
|
1084
|
-
: d.source?.reason ||
|
|
1085
|
-
d.source?.hostname ||
|
|
1086
|
-
'adhoc';
|
|
1087
|
-
|
|
1088
|
-
const shortSha = d.source?.commit_sha?.slice(
|
|
1089
|
-
0,
|
|
1090
|
-
7,
|
|
1091
|
-
);
|
|
1092
|
-
|
|
1093
|
-
return (
|
|
1094
|
-
<div
|
|
1095
|
-
key={`${d.uuid}-${idx}`}
|
|
1096
|
-
style={{
|
|
1097
|
-
display: 'grid',
|
|
1098
|
-
gridTemplateColumns: '18px 1fr auto auto',
|
|
1099
|
-
alignItems: 'center',
|
|
1100
|
-
gap: '8px',
|
|
1101
|
-
padding: '6px 0',
|
|
1102
|
-
borderBottom:
|
|
1103
|
-
idx === recentDeployments.length - 1
|
|
1104
|
-
? 'none'
|
|
1105
|
-
: '1px solid #f1f5f9',
|
|
1106
|
-
fontSize: '12px',
|
|
1107
|
-
}}
|
|
1108
|
-
>
|
|
1109
|
-
{/* Status dot */}
|
|
1110
|
-
<div
|
|
1111
|
-
style={{
|
|
1112
|
-
width: '8px',
|
|
1113
|
-
height: '8px',
|
|
1114
|
-
borderRadius: '50%',
|
|
1115
|
-
backgroundColor: statusColor,
|
|
1116
|
-
}}
|
|
1117
|
-
title={d.status}
|
|
1118
|
-
/>
|
|
1119
|
-
|
|
1120
|
-
{/* User + detail */}
|
|
1121
|
-
<div
|
|
1122
|
-
style={{
|
|
1123
|
-
display: 'flex',
|
|
1124
|
-
alignItems: 'center',
|
|
1125
|
-
gap: '6px',
|
|
1126
|
-
minWidth: 0,
|
|
1127
|
-
}}
|
|
1128
|
-
>
|
|
1129
|
-
<span
|
|
1130
|
-
style={{
|
|
1131
|
-
fontWeight: 500,
|
|
1132
|
-
color: '#0f172a',
|
|
1133
|
-
whiteSpace: 'nowrap',
|
|
1134
|
-
}}
|
|
1135
|
-
>
|
|
1136
|
-
{d.created_by || 'unknown'}
|
|
1137
|
-
</span>
|
|
1138
|
-
<span style={{ color: '#cbd5e1' }}>
|
|
1139
|
-
—
|
|
1140
|
-
</span>
|
|
1141
|
-
{isGit ? (
|
|
1142
|
-
<>
|
|
1143
|
-
<span
|
|
1144
|
-
style={{
|
|
1145
|
-
color: '#64748b',
|
|
1146
|
-
whiteSpace: 'nowrap',
|
|
1147
|
-
}}
|
|
1148
|
-
>
|
|
1149
|
-
{detail}
|
|
1150
|
-
</span>
|
|
1151
|
-
{shortSha && (
|
|
1152
|
-
<>
|
|
1153
|
-
<span
|
|
1154
|
-
style={{ color: '#cbd5e1' }}
|
|
1155
|
-
>
|
|
1156
|
-
@
|
|
1157
|
-
</span>
|
|
1158
|
-
{commitUrl ? (
|
|
1159
|
-
<a
|
|
1160
|
-
href={commitUrl}
|
|
1161
|
-
target="_blank"
|
|
1162
|
-
rel="noopener noreferrer"
|
|
1163
|
-
style={{
|
|
1164
|
-
fontFamily: 'monospace',
|
|
1165
|
-
fontSize: '11px',
|
|
1166
|
-
color: '#3b82f6',
|
|
1167
|
-
textDecoration: 'none',
|
|
1168
|
-
}}
|
|
1169
|
-
>
|
|
1170
|
-
{shortSha}
|
|
1171
|
-
</a>
|
|
1172
|
-
) : (
|
|
1173
|
-
<span
|
|
1174
|
-
style={{
|
|
1175
|
-
fontFamily: 'monospace',
|
|
1176
|
-
fontSize: '11px',
|
|
1177
|
-
color: '#64748b',
|
|
1178
|
-
}}
|
|
1179
|
-
>
|
|
1180
|
-
{shortSha}
|
|
1181
|
-
</span>
|
|
1182
|
-
)}
|
|
1183
|
-
</>
|
|
1184
|
-
)}
|
|
1185
|
-
</>
|
|
1186
|
-
) : (
|
|
1187
|
-
<span
|
|
1188
|
-
style={{
|
|
1189
|
-
color: '#64748b',
|
|
1190
|
-
overflow: 'hidden',
|
|
1191
|
-
textOverflow: 'ellipsis',
|
|
1192
|
-
whiteSpace: 'nowrap',
|
|
1193
|
-
}}
|
|
1194
|
-
>
|
|
1195
|
-
{detail}
|
|
1196
|
-
</span>
|
|
1197
|
-
)}
|
|
1198
|
-
</div>
|
|
1199
|
-
|
|
1200
|
-
{/* Timestamp */}
|
|
1201
|
-
<span
|
|
1202
|
-
style={{
|
|
1203
|
-
color: '#94a3b8',
|
|
1204
|
-
fontSize: '11px',
|
|
1205
|
-
whiteSpace: 'nowrap',
|
|
1206
|
-
}}
|
|
1207
|
-
>
|
|
1208
|
-
{new Date(
|
|
1209
|
-
d.created_at,
|
|
1210
|
-
).toLocaleDateString()}
|
|
1211
|
-
</span>
|
|
1212
|
-
|
|
1213
|
-
{/* Icon */}
|
|
1214
|
-
<div
|
|
1215
|
-
style={{
|
|
1216
|
-
color: isGit ? '#155724' : '#0b3d91',
|
|
1217
|
-
}}
|
|
1218
|
-
>
|
|
1219
|
-
{isGit ? (
|
|
1220
|
-
<svg
|
|
1221
|
-
width="12"
|
|
1222
|
-
height="12"
|
|
1223
|
-
viewBox="0 0 24 24"
|
|
1224
|
-
fill="none"
|
|
1225
|
-
stroke="currentColor"
|
|
1226
|
-
strokeWidth="2"
|
|
1227
|
-
strokeLinecap="round"
|
|
1228
|
-
strokeLinejoin="round"
|
|
1229
|
-
>
|
|
1230
|
-
<line x1="6" y1="3" x2="6" y2="15" />
|
|
1231
|
-
<circle cx="18" cy="6" r="3" />
|
|
1232
|
-
<circle cx="6" cy="18" r="3" />
|
|
1233
|
-
<path d="M18 9a9 9 0 0 1-9 9" />
|
|
1234
|
-
</svg>
|
|
1235
|
-
) : (
|
|
1236
|
-
<svg
|
|
1237
|
-
width="12"
|
|
1238
|
-
height="12"
|
|
1239
|
-
viewBox="0 0 24 24"
|
|
1240
|
-
fill="none"
|
|
1241
|
-
stroke="currentColor"
|
|
1242
|
-
strokeWidth="2"
|
|
1243
|
-
strokeLinecap="round"
|
|
1244
|
-
strokeLinejoin="round"
|
|
1245
|
-
>
|
|
1246
|
-
<circle cx="12" cy="7" r="4" />
|
|
1247
|
-
<path d="M5.5 21a6.5 6.5 0 0 1 13 0Z" />
|
|
1248
|
-
</svg>
|
|
1249
|
-
)}
|
|
1250
|
-
</div>
|
|
1251
|
-
</div>
|
|
1252
|
-
);
|
|
1253
|
-
})
|
|
1254
|
-
) : (
|
|
1255
|
-
<div
|
|
1256
|
-
style={{
|
|
1257
|
-
color: '#94a3b8',
|
|
1258
|
-
fontSize: '12px',
|
|
1259
|
-
textAlign: 'center',
|
|
1260
|
-
padding: '8px 0',
|
|
1261
|
-
}}
|
|
1262
|
-
>
|
|
1263
|
-
No deployments yet
|
|
1264
|
-
</div>
|
|
1265
|
-
)}
|
|
1266
|
-
</div>
|
|
1267
|
-
)}
|
|
1268
|
-
</div>
|
|
1269
|
-
)}
|
|
1270
|
-
</div>
|
|
1271
|
-
<div
|
|
1272
|
-
style={{ display: 'flex', alignItems: 'center', gap: '8px' }}
|
|
807
|
+
<NamespaceHeader namespace={namespace}>
|
|
808
|
+
<a
|
|
809
|
+
href={`${getDJUrl()}/namespaces/${namespace}/export/yaml`}
|
|
810
|
+
download
|
|
811
|
+
style={{
|
|
812
|
+
display: 'inline-flex',
|
|
813
|
+
alignItems: 'center',
|
|
814
|
+
gap: '4px',
|
|
815
|
+
// padding: '6px 12px',
|
|
816
|
+
fontSize: '13px',
|
|
817
|
+
fontWeight: '500',
|
|
818
|
+
color: '#475569',
|
|
819
|
+
// backgroundColor: '#f8fafc',
|
|
820
|
+
// border: '1px solid #e2e8f0',
|
|
821
|
+
borderRadius: '6px',
|
|
822
|
+
textDecoration: 'none',
|
|
823
|
+
cursor: 'pointer',
|
|
824
|
+
transition: 'all 0.15s ease',
|
|
825
|
+
margin: '0.5em 0px 0px 1em',
|
|
826
|
+
}}
|
|
827
|
+
onMouseOver={e => {
|
|
828
|
+
e.currentTarget.style.color = '#333333';
|
|
829
|
+
}}
|
|
830
|
+
onMouseOut={e => {
|
|
831
|
+
e.currentTarget.style.color = '#475569';
|
|
832
|
+
}}
|
|
833
|
+
title="Export namespace to YAML"
|
|
1273
834
|
>
|
|
1274
|
-
<
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
fontWeight: '500',
|
|
1284
|
-
color: '#475569',
|
|
1285
|
-
// backgroundColor: '#f8fafc',
|
|
1286
|
-
// border: '1px solid #e2e8f0',
|
|
1287
|
-
borderRadius: '6px',
|
|
1288
|
-
textDecoration: 'none',
|
|
1289
|
-
cursor: 'pointer',
|
|
1290
|
-
transition: 'all 0.15s ease',
|
|
1291
|
-
margin: '0.5em 0px 0px 1em',
|
|
1292
|
-
}}
|
|
1293
|
-
onMouseOver={e => {
|
|
1294
|
-
e.currentTarget.style.color = '#333333';
|
|
1295
|
-
}}
|
|
1296
|
-
onMouseOut={e => {
|
|
1297
|
-
e.currentTarget.style.color = '#475569';
|
|
1298
|
-
}}
|
|
1299
|
-
title="Export namespace to YAML"
|
|
835
|
+
<svg
|
|
836
|
+
width="14"
|
|
837
|
+
height="14"
|
|
838
|
+
viewBox="0 0 24 24"
|
|
839
|
+
fill="none"
|
|
840
|
+
stroke="currentColor"
|
|
841
|
+
strokeWidth="2"
|
|
842
|
+
strokeLinecap="round"
|
|
843
|
+
strokeLinejoin="round"
|
|
1300
844
|
>
|
|
1301
|
-
<
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
strokeLinecap="round"
|
|
1309
|
-
strokeLinejoin="round"
|
|
1310
|
-
>
|
|
1311
|
-
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
|
|
1312
|
-
<polyline points="7 10 12 15 17 10"></polyline>
|
|
1313
|
-
<line x1="12" y1="15" x2="12" y2="3"></line>
|
|
1314
|
-
</svg>
|
|
1315
|
-
</a>
|
|
1316
|
-
<AddNodeDropdown namespace={namespace} />
|
|
1317
|
-
</div>
|
|
1318
|
-
</div>
|
|
845
|
+
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
|
|
846
|
+
<polyline points="7 10 12 15 17 10"></polyline>
|
|
847
|
+
<line x1="12" y1="15" x2="12" y2="3"></line>
|
|
848
|
+
</svg>
|
|
849
|
+
</a>
|
|
850
|
+
<AddNodeDropdown namespace={namespace} />
|
|
851
|
+
</NamespaceHeader>
|
|
1319
852
|
<table className="card-table table" style={{ marginBottom: 0 }}>
|
|
1320
853
|
<thead>
|
|
1321
854
|
<tr>
|
|
@@ -37,9 +37,13 @@ export default function NodeInfoTab({ node }) {
|
|
|
37
37
|
const [metricInfo, setMetricInfo] = useState(null);
|
|
38
38
|
|
|
39
39
|
const nodeTags = node?.tags.map(tag => (
|
|
40
|
-
<
|
|
40
|
+
<span
|
|
41
|
+
key={tag.name}
|
|
42
|
+
className={'badge tag_value'}
|
|
43
|
+
style={{ marginRight: '4px' }}
|
|
44
|
+
>
|
|
41
45
|
<a href={`/tags/${tag.name}`}>{tag.display_name}</a>
|
|
42
|
-
</
|
|
46
|
+
</span>
|
|
43
47
|
));
|
|
44
48
|
const djClient = useContext(DJClientContext).DataJunctionAPI;
|
|
45
49
|
|
|
@@ -314,13 +318,19 @@ export default function NodeInfoTab({ node }) {
|
|
|
314
318
|
}
|
|
315
319
|
>
|
|
316
320
|
{node?.type !== 'metric'
|
|
317
|
-
? node?.primary_key?.map(dim => (
|
|
318
|
-
<span
|
|
321
|
+
? node?.primary_key?.map((dim, idx) => (
|
|
322
|
+
<span
|
|
323
|
+
key={`pk-${idx}`}
|
|
324
|
+
className="rounded-pill badge bg-secondary-soft PrimaryKey"
|
|
325
|
+
>
|
|
319
326
|
<a href={`/nodes/${node?.name}`}>{dim}</a>
|
|
320
327
|
</span>
|
|
321
328
|
))
|
|
322
|
-
: node?.required_dimensions?.map(dim => (
|
|
323
|
-
<span
|
|
329
|
+
: node?.required_dimensions?.map((dim, idx) => (
|
|
330
|
+
<span
|
|
331
|
+
key={`rd-${idx}`}
|
|
332
|
+
className="rounded-pill badge bg-secondary-soft PrimaryKey"
|
|
333
|
+
>
|
|
324
334
|
<a href={`/nodes/${node?.upstream_node}`}>{dim.name}</a>
|
|
325
335
|
</span>
|
|
326
336
|
))}
|
|
@@ -341,6 +351,7 @@ export default function NodeInfoTab({ node }) {
|
|
|
341
351
|
<p className="mb-0 opacity-75">
|
|
342
352
|
{node?.owners.map(owner => (
|
|
343
353
|
<span
|
|
354
|
+
key={owner.username}
|
|
344
355
|
className="badge node_type__transform"
|
|
345
356
|
style={{ margin: '2px', fontSize: '16px', cursor: 'pointer' }}
|
|
346
357
|
>
|
|
@@ -11,6 +11,11 @@ import AvailabilityStateBlock from './AvailabilityStateBlock';
|
|
|
11
11
|
|
|
12
12
|
const cronstrue = require('cronstrue');
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Cube materialization tab - shows cube-specific materializations.
|
|
16
|
+
* For non-cube nodes, the parent component (index.jsx) renders
|
|
17
|
+
* NodePreAggregationsTab instead.
|
|
18
|
+
*/
|
|
14
19
|
export default function NodeMaterializationTab({ node, djClient }) {
|
|
15
20
|
const [rawMaterializations, setRawMaterializations] = useState([]);
|
|
16
21
|
const [selectedRevisionTab, setSelectedRevisionTab] = useState(null);
|