datajunction-ui 0.0.1-a1
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/.babel-plugin-macrosrc.js +5 -0
- package/.env +3 -0
- package/.eslintrc.js +20 -0
- package/.gitattributes +201 -0
- package/.husky/pre-commit +6 -0
- package/.nvmrc +1 -0
- package/.prettierignore +6 -0
- package/.prettierrc +9 -0
- package/.stylelintrc +7 -0
- package/LICENSE +22 -0
- package/Makefile +3 -0
- package/README.md +10 -0
- package/dj-logo.svg +10 -0
- package/internals/testing/loadable.mock.tsx +6 -0
- package/package.json +189 -0
- package/public/favicon.ico +0 -0
- package/public/index.html +26 -0
- package/public/manifest.json +15 -0
- package/public/robots.txt +3 -0
- package/src/__tests__/reportWebVitals.test.jsx +44 -0
- package/src/app/__tests__/__snapshots__/index.test.tsx.snap +9 -0
- package/src/app/__tests__/index.test.tsx +14 -0
- package/src/app/components/DeleteNode.jsx +55 -0
- package/src/app/components/ListGroupItem.jsx +24 -0
- package/src/app/components/NamespaceHeader.jsx +31 -0
- package/src/app/components/QueryInfo.jsx +77 -0
- package/src/app/components/Tab.jsx +25 -0
- package/src/app/components/ToggleSwitch.jsx +20 -0
- package/src/app/components/__tests__/DeleteNode.test.jsx +53 -0
- package/src/app/components/__tests__/ListGroupItem.test.tsx +16 -0
- package/src/app/components/__tests__/NamespaceHeader.test.jsx +14 -0
- package/src/app/components/__tests__/QueryInfo.test.jsx +55 -0
- package/src/app/components/__tests__/Tab.test.jsx +27 -0
- package/src/app/components/__tests__/ToggleSwitch.test.jsx +43 -0
- package/src/app/components/__tests__/__snapshots__/ListGroupItem.test.tsx.snap +29 -0
- package/src/app/components/__tests__/__snapshots__/NamespaceHeader.test.jsx.snap +47 -0
- package/src/app/components/djgraph/Collapse.jsx +46 -0
- package/src/app/components/djgraph/DJNode.jsx +89 -0
- package/src/app/components/djgraph/DJNodeColumns.jsx +71 -0
- package/src/app/components/djgraph/DJNodeDimensions.jsx +75 -0
- package/src/app/components/djgraph/LayoutFlow.jsx +104 -0
- package/src/app/components/djgraph/__tests__/Collapse.test.jsx +51 -0
- package/src/app/components/djgraph/__tests__/DJNode.test.tsx +24 -0
- package/src/app/components/djgraph/__tests__/DJNodeColumns.test.jsx +83 -0
- package/src/app/components/djgraph/__tests__/DJNodeDimensions.test.jsx +118 -0
- package/src/app/components/djgraph/__tests__/__snapshots__/DJNode.test.tsx.snap +117 -0
- package/src/app/constants.js +2 -0
- package/src/app/icons/AlertIcon.jsx +32 -0
- package/src/app/icons/CollapsedIcon.jsx +15 -0
- package/src/app/icons/DJLogo.jsx +36 -0
- package/src/app/icons/DeleteIcon.jsx +21 -0
- package/src/app/icons/EditIcon.jsx +18 -0
- package/src/app/icons/ExpandedIcon.jsx +15 -0
- package/src/app/icons/HorizontalHierarchyIcon.jsx +15 -0
- package/src/app/icons/InvalidIcon.jsx +14 -0
- package/src/app/icons/LoadingIcon.jsx +14 -0
- package/src/app/icons/PythonIcon.jsx +52 -0
- package/src/app/icons/TableIcon.jsx +14 -0
- package/src/app/icons/ValidIcon.jsx +14 -0
- package/src/app/index.tsx +108 -0
- package/src/app/pages/AddEditNodePage/FormikSelect.jsx +46 -0
- package/src/app/pages/AddEditNodePage/FullNameField.jsx +37 -0
- package/src/app/pages/AddEditNodePage/Loadable.jsx +16 -0
- package/src/app/pages/AddEditNodePage/NodeQueryField.jsx +89 -0
- package/src/app/pages/AddEditNodePage/__tests__/AddEditNodePageFormFailed.test.jsx +103 -0
- package/src/app/pages/AddEditNodePage/__tests__/AddEditNodePageFormSuccess.test.jsx +132 -0
- package/src/app/pages/AddEditNodePage/__tests__/FormikSelect.test.jsx +75 -0
- package/src/app/pages/AddEditNodePage/__tests__/FullNameField.test.jsx +31 -0
- package/src/app/pages/AddEditNodePage/__tests__/NodeQueryField.test.jsx +30 -0
- package/src/app/pages/AddEditNodePage/__tests__/__snapshots__/AddEditNodePageFormFailed.test.jsx.snap +54 -0
- package/src/app/pages/AddEditNodePage/__tests__/__snapshots__/AddEditNodePageFormSuccess.test.jsx.snap +3 -0
- package/src/app/pages/AddEditNodePage/__tests__/__snapshots__/index.test.jsx.snap +3 -0
- package/src/app/pages/AddEditNodePage/__tests__/index.test.jsx +180 -0
- package/src/app/pages/AddEditNodePage/index.jsx +396 -0
- package/src/app/pages/AddEditTagPage/Loadable.jsx +16 -0
- package/src/app/pages/AddEditTagPage/__tests__/AddEditTagPage.test.jsx +107 -0
- package/src/app/pages/AddEditTagPage/index.jsx +132 -0
- package/src/app/pages/LoginPage/LoginForm.jsx +124 -0
- package/src/app/pages/LoginPage/SignupForm.jsx +156 -0
- package/src/app/pages/LoginPage/__tests__/index.test.jsx +97 -0
- package/src/app/pages/LoginPage/assets/sign-in-with-github.png +0 -0
- package/src/app/pages/LoginPage/assets/sign-in-with-google.png +0 -0
- package/src/app/pages/LoginPage/index.jsx +17 -0
- package/src/app/pages/NamespacePage/AddNamespacePopover.jsx +85 -0
- package/src/app/pages/NamespacePage/Explorer.jsx +57 -0
- package/src/app/pages/NamespacePage/Loadable.jsx +16 -0
- package/src/app/pages/NamespacePage/__tests__/index.test.jsx +217 -0
- package/src/app/pages/NamespacePage/index.jsx +199 -0
- package/src/app/pages/NodePage/AddBackfillPopover.jsx +166 -0
- package/src/app/pages/NodePage/AddMaterializationPopover.jsx +161 -0
- package/src/app/pages/NodePage/ClientCodePopover.jsx +46 -0
- package/src/app/pages/NodePage/EditColumnPopover.jsx +116 -0
- package/src/app/pages/NodePage/LinkDimensionPopover.jsx +149 -0
- package/src/app/pages/NodePage/Loadable.jsx +16 -0
- package/src/app/pages/NodePage/NodeColumnTab.jsx +200 -0
- package/src/app/pages/NodePage/NodeGraphTab.jsx +112 -0
- package/src/app/pages/NodePage/NodeHistory.jsx +212 -0
- package/src/app/pages/NodePage/NodeInfoTab.jsx +212 -0
- package/src/app/pages/NodePage/NodeLineageTab.jsx +84 -0
- package/src/app/pages/NodePage/NodeMaterializationTab.jsx +233 -0
- package/src/app/pages/NodePage/NodeSQLTab.jsx +82 -0
- package/src/app/pages/NodePage/NodeStatus.jsx +28 -0
- package/src/app/pages/NodePage/NodesWithDimension.jsx +42 -0
- package/src/app/pages/NodePage/PartitionColumnPopover.jsx +153 -0
- package/src/app/pages/NodePage/__tests__/AddBackfillPopover.test.jsx +47 -0
- package/src/app/pages/NodePage/__tests__/ClientCodePopover.test.jsx +49 -0
- package/src/app/pages/NodePage/__tests__/EditColumnPopover.test.jsx +148 -0
- package/src/app/pages/NodePage/__tests__/LinkDimensionPopover.test.jsx +165 -0
- package/src/app/pages/NodePage/__tests__/NodeGraphTab.test.jsx +591 -0
- package/src/app/pages/NodePage/__tests__/NodeLineageTab.test.jsx +57 -0
- package/src/app/pages/NodePage/__tests__/NodePage.test.jsx +757 -0
- package/src/app/pages/NodePage/__tests__/NodeWithDimension.test.jsx +175 -0
- package/src/app/pages/NodePage/__tests__/__snapshots__/NodePage.test.jsx.snap +403 -0
- package/src/app/pages/NodePage/index.jsx +210 -0
- package/src/app/pages/NotFoundPage/Loadable.tsx +14 -0
- package/src/app/pages/NotFoundPage/__tests__/index.test.jsx +16 -0
- package/src/app/pages/NotFoundPage/index.tsx +23 -0
- package/src/app/pages/RegisterTablePage/Loadable.jsx +16 -0
- package/src/app/pages/RegisterTablePage/__tests__/RegisterTablePage.test.jsx +110 -0
- package/src/app/pages/RegisterTablePage/__tests__/__snapshots__/RegisterTablePage.test.jsx.snap +37 -0
- package/src/app/pages/RegisterTablePage/index.jsx +142 -0
- package/src/app/pages/Root/Loadable.tsx +14 -0
- package/src/app/pages/Root/__tests__/index.test.jsx +77 -0
- package/src/app/pages/Root/assets/dj-logo.png +0 -0
- package/src/app/pages/Root/index.tsx +70 -0
- package/src/app/pages/SQLBuilderPage/Loadable.jsx +16 -0
- package/src/app/pages/SQLBuilderPage/__tests__/index.test.jsx +173 -0
- package/src/app/pages/SQLBuilderPage/index.jsx +390 -0
- package/src/app/pages/TagPage/Loadable.jsx +16 -0
- package/src/app/pages/TagPage/__tests__/TagPage.test.jsx +70 -0
- package/src/app/pages/TagPage/index.jsx +79 -0
- package/src/app/providers/djclient.jsx +5 -0
- package/src/app/services/DJService.js +665 -0
- package/src/app/services/__tests__/DJService.test.jsx +804 -0
- package/src/index.tsx +48 -0
- package/src/mocks/mockNodes.jsx +1430 -0
- package/src/react-app-env.d.ts +4 -0
- package/src/reportWebVitals.ts +15 -0
- package/src/setupTests.ts +36 -0
- package/src/styles/dag.css +228 -0
- package/src/styles/index.css +1083 -0
- package/src/styles/loading.css +34 -0
- package/src/styles/login.css +81 -0
- package/src/styles/node-creation.scss +197 -0
- package/src/styles/styles.scss +44 -0
- package/src/styles/styles.scss.d.ts +9 -0
- package/src/utils/__tests__/__snapshots__/loadable.test.tsx.snap +17 -0
- package/src/utils/__tests__/loadable.test.tsx +53 -0
- package/src/utils/__tests__/request.test.ts +82 -0
- package/src/utils/form.jsx +23 -0
- package/src/utils/loadable.tsx +30 -0
- package/src/utils/request.ts +54 -0
- package/tsconfig.json +34 -0
- package/webpack.config.js +118 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
.lds-ring {
|
|
2
|
+
display: inline-block;
|
|
3
|
+
position: relative;
|
|
4
|
+
width: 25px;
|
|
5
|
+
height: 25px;
|
|
6
|
+
}
|
|
7
|
+
.lds-ring div {
|
|
8
|
+
box-sizing: border-box;
|
|
9
|
+
display: block;
|
|
10
|
+
position: absolute;
|
|
11
|
+
width: 25px;
|
|
12
|
+
height: 25px;
|
|
13
|
+
border: 8px solid #fff;
|
|
14
|
+
border-radius: 50%;
|
|
15
|
+
animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
|
|
16
|
+
border-color: #fff transparent transparent transparent;
|
|
17
|
+
}
|
|
18
|
+
.lds-ring div:nth-child(1) {
|
|
19
|
+
animation-delay: -0.45s;
|
|
20
|
+
}
|
|
21
|
+
.lds-ring div:nth-child(2) {
|
|
22
|
+
animation-delay: -0.3s;
|
|
23
|
+
}
|
|
24
|
+
.lds-ring div:nth-child(3) {
|
|
25
|
+
animation-delay: -0.15s;
|
|
26
|
+
}
|
|
27
|
+
@keyframes lds-ring {
|
|
28
|
+
0% {
|
|
29
|
+
transform: rotate(0deg);
|
|
30
|
+
}
|
|
31
|
+
100% {
|
|
32
|
+
transform: rotate(360deg);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
.login form {
|
|
2
|
+
border-radius: 25px;
|
|
3
|
+
border: 2px solid #000000;
|
|
4
|
+
background: linear-gradient(120deg, #ffed7c, #fef7c8);
|
|
5
|
+
width: 40vw;
|
|
6
|
+
height: 45rem;
|
|
7
|
+
box-sizing: border-box;
|
|
8
|
+
padding: 2rem;
|
|
9
|
+
display: grid;
|
|
10
|
+
grid-template-columns: 1fr;
|
|
11
|
+
margin: auto;
|
|
12
|
+
position: absolute;
|
|
13
|
+
top: 0;
|
|
14
|
+
bottom: 0;
|
|
15
|
+
left: 0;
|
|
16
|
+
right: 0;
|
|
17
|
+
cursor: pointer;
|
|
18
|
+
grid-row-gap: 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.login form div {
|
|
22
|
+
display: block;
|
|
23
|
+
text-align: center;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.login form button {
|
|
27
|
+
width: 15vw;
|
|
28
|
+
margin: auto;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.login form span {
|
|
32
|
+
padding: 0.5rem;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.login input[type='text'] {
|
|
36
|
+
width: 20vw;
|
|
37
|
+
padding: 12px 20px;
|
|
38
|
+
margin: auto;
|
|
39
|
+
display: inline-block;
|
|
40
|
+
border: 2px solid #000000;
|
|
41
|
+
border-radius: 4px;
|
|
42
|
+
box-sizing: border-box;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.login input[type='password'] {
|
|
46
|
+
-webkit-text-security: disc;
|
|
47
|
+
width: 20vw;
|
|
48
|
+
padding: 12px 20px;
|
|
49
|
+
margin: auto;
|
|
50
|
+
display: inline-block;
|
|
51
|
+
border: 2px solid #000000;
|
|
52
|
+
border-radius: 4px;
|
|
53
|
+
box-sizing: border-box;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.login button[type='submit'] {
|
|
57
|
+
width: 10vw;
|
|
58
|
+
background-color: #5d2e85;
|
|
59
|
+
border: 2px solid #000000;
|
|
60
|
+
color: white;
|
|
61
|
+
padding: 14px 20px;
|
|
62
|
+
border-radius: 4px;
|
|
63
|
+
cursor: pointer;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.login .logo-title {
|
|
67
|
+
display: flex;
|
|
68
|
+
margin: auto;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.login .logo-title img {
|
|
72
|
+
padding: 0.5rem;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.signup form {
|
|
76
|
+
height: 50rem;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.form-error {
|
|
80
|
+
color: red;
|
|
81
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
// Fonts
|
|
2
|
+
form {
|
|
3
|
+
text-align: left;
|
|
4
|
+
|
|
5
|
+
select {
|
|
6
|
+
background-color: #eeeeee;
|
|
7
|
+
border-radius: 10px;
|
|
8
|
+
border-style: none;
|
|
9
|
+
padding: 1rem;
|
|
10
|
+
font-family: Lato, 'sans-serif';
|
|
11
|
+
font-size: 110%;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
input {
|
|
15
|
+
background-color: #eeeeee;
|
|
16
|
+
border-radius: 10px;
|
|
17
|
+
border-style: none;
|
|
18
|
+
border-width: 1px;
|
|
19
|
+
box-sizing: border-box;
|
|
20
|
+
padding: 1rem;
|
|
21
|
+
font-size: 110%;
|
|
22
|
+
box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 6px -1px,
|
|
23
|
+
rgba(0, 0, 0, 0.06) 0px 2px 4px -1px;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
label {
|
|
27
|
+
font-family: 'Lato', sans-serif;
|
|
28
|
+
display: block;
|
|
29
|
+
text-transform: uppercase;
|
|
30
|
+
margin-bottom: 5px;
|
|
31
|
+
font-size: 90%;
|
|
32
|
+
font-weight: 600;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.NodeCreationInput {
|
|
36
|
+
margin: 0.5rem 0;
|
|
37
|
+
display: inline-grid;
|
|
38
|
+
width: 35%;
|
|
39
|
+
padding: 0 20px;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.DisplayNameInput,
|
|
43
|
+
.FullNameInput,
|
|
44
|
+
.NamespaceInput {
|
|
45
|
+
span {
|
|
46
|
+
color: red;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.DisplayNameInput,
|
|
51
|
+
.FullNameInput,
|
|
52
|
+
.NamespaceInput {
|
|
53
|
+
display: inline-grid;
|
|
54
|
+
box-sizing: border-box;
|
|
55
|
+
flex-wrap: nowrap;
|
|
56
|
+
margin: 1rem 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.DisplayNameInput {
|
|
60
|
+
width: 45%;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.FullNameInput {
|
|
64
|
+
width: 100%;
|
|
65
|
+
|
|
66
|
+
input {
|
|
67
|
+
width: 75%;
|
|
68
|
+
color: #275c86;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.NamespaceInput {
|
|
73
|
+
padding: 0 20px;
|
|
74
|
+
width: 30%;
|
|
75
|
+
|
|
76
|
+
div:first-child {
|
|
77
|
+
flex: 1 0 auto;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
input {
|
|
81
|
+
width: 35%;
|
|
82
|
+
border: 0;
|
|
83
|
+
font-family: 'Lato', sans-serif;
|
|
84
|
+
padding: 5px 0;
|
|
85
|
+
font-size: 18px;
|
|
86
|
+
font-weight: 300;
|
|
87
|
+
outline: none;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.SelectInput {
|
|
92
|
+
background-color: #eee;
|
|
93
|
+
border-radius: 10px;
|
|
94
|
+
border-style: none;
|
|
95
|
+
border-color: transparent;
|
|
96
|
+
box-sizing: border-box;
|
|
97
|
+
padding: 0.5rem;
|
|
98
|
+
font-size: 110%;
|
|
99
|
+
box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 6px -1px,
|
|
100
|
+
rgba(0, 0, 0, 0.06) 0px 2px 4px -1px;
|
|
101
|
+
}
|
|
102
|
+
.SelectInput div,
|
|
103
|
+
.SelectInput div div {
|
|
104
|
+
border: none;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.SelectInput div:first-child {
|
|
108
|
+
background-color: #eee !important;
|
|
109
|
+
border: none;
|
|
110
|
+
color: #0c4128;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.DescriptionInput {
|
|
114
|
+
width: 100%;
|
|
115
|
+
|
|
116
|
+
textarea {
|
|
117
|
+
width: 75%;
|
|
118
|
+
background-color: #eeeeee;
|
|
119
|
+
border-radius: 10px;
|
|
120
|
+
border-style: none;
|
|
121
|
+
border-width: 1px;
|
|
122
|
+
box-sizing: border-box;
|
|
123
|
+
padding: 1rem;
|
|
124
|
+
font-family: Lato, Sans;
|
|
125
|
+
font-size: 110%;
|
|
126
|
+
margin: 0.5rem 0;
|
|
127
|
+
height: 100px;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.QueryInput {
|
|
132
|
+
width: 75%;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.NodeModeInput {
|
|
136
|
+
select {
|
|
137
|
+
background-color: #eeeeee;
|
|
138
|
+
border-radius: 10px;
|
|
139
|
+
border-style: none;
|
|
140
|
+
padding: 1rem;
|
|
141
|
+
font-family: Lato, Sans;
|
|
142
|
+
font-size: 110%;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
button {
|
|
147
|
+
display: block;
|
|
148
|
+
border-radius: 10px;
|
|
149
|
+
border-style: none;
|
|
150
|
+
padding: 1rem;
|
|
151
|
+
margin: 0.5rem 20px;
|
|
152
|
+
text-transform: uppercase;
|
|
153
|
+
font-family: Lato, Sans;
|
|
154
|
+
font-weight: 600;
|
|
155
|
+
font-size: 110%;
|
|
156
|
+
background-size: 200% auto;
|
|
157
|
+
background-color: #ffd559;
|
|
158
|
+
box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 6px -1px,
|
|
159
|
+
rgba(0, 0, 0, 0.06) 0px 2px 4px -1px;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.message {
|
|
164
|
+
padding: 20px;
|
|
165
|
+
opacity: 1;
|
|
166
|
+
margin-bottom: 15px;
|
|
167
|
+
border-radius: 0.5rem;
|
|
168
|
+
line-height: 1.25rem;
|
|
169
|
+
font-size: 1.2rem;
|
|
170
|
+
svg {
|
|
171
|
+
margin-right: 0.3rem;
|
|
172
|
+
height: 1.5rem;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
.success {
|
|
176
|
+
background-color: rgb(245, 253, 242);
|
|
177
|
+
color: rgb(53, 110, 35);
|
|
178
|
+
svg {
|
|
179
|
+
filter: invert(34%) sepia(86%) saturate(465%) hue-rotate(60deg)
|
|
180
|
+
brightness(82%) contrast(80%);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
.alert {
|
|
184
|
+
background-color: rgb(253 242 242/1);
|
|
185
|
+
color: rgb(155 28 28/1);
|
|
186
|
+
svg {
|
|
187
|
+
filter: invert(16%) sepia(68%) saturate(2827%) hue-rotate(344deg)
|
|
188
|
+
brightness(96%) contrast(100%);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.SourceCreationInput {
|
|
193
|
+
margin: 0.5rem 0;
|
|
194
|
+
display: inline-grid;
|
|
195
|
+
width: 20%;
|
|
196
|
+
padding: 0 20px;
|
|
197
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
@use 'sass:color';
|
|
2
|
+
|
|
3
|
+
.svg-font-color svg > path {
|
|
4
|
+
fill: var(--ifm-font-color-base);
|
|
5
|
+
}
|
|
6
|
+
select {
|
|
7
|
+
border-radius: 0.25rem;
|
|
8
|
+
font-size: 0.875rem;
|
|
9
|
+
padding-bottom: 0.25rem;
|
|
10
|
+
padding-left: 0.5rem;
|
|
11
|
+
padding-top: 0.25rem;
|
|
12
|
+
max-width: 20vw;
|
|
13
|
+
}
|
|
14
|
+
.queryBuilder {
|
|
15
|
+
min-width: 420px;
|
|
16
|
+
|
|
17
|
+
.ruleGroup div select,
|
|
18
|
+
.ruleGroup div input {
|
|
19
|
+
-webkit-text-security: none;
|
|
20
|
+
border-radius: 0.25rem;
|
|
21
|
+
font-size: 0.875rem;
|
|
22
|
+
padding-bottom: 0.35rem;
|
|
23
|
+
padding-left: 0.5rem;
|
|
24
|
+
padding-top: 0.35rem;
|
|
25
|
+
border: none;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.ruleGroup div button {
|
|
29
|
+
background-color: #f0f8ff;
|
|
30
|
+
color: #24518f;
|
|
31
|
+
border: 1px solid #365b8f;
|
|
32
|
+
border-radius: 0.25rem;
|
|
33
|
+
cursor: pointer;
|
|
34
|
+
display: inline-block;
|
|
35
|
+
font-size: 0.875rem;
|
|
36
|
+
font-weight: 400;
|
|
37
|
+
line-height: 1.5;
|
|
38
|
+
padding: 0.25rem 0.5rem;
|
|
39
|
+
text-align: center;
|
|
40
|
+
text-decoration: none;
|
|
41
|
+
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out,
|
|
42
|
+
border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`loadable should render LazyComponent after waiting for it to load 1`] = `
|
|
4
|
+
<div>
|
|
5
|
+
My lazy-loaded component
|
|
6
|
+
</div>
|
|
7
|
+
`;
|
|
8
|
+
|
|
9
|
+
exports[`loadable should render fallback if given one 1`] = `
|
|
10
|
+
<div>
|
|
11
|
+
Loading
|
|
12
|
+
</div>
|
|
13
|
+
`;
|
|
14
|
+
|
|
15
|
+
exports[`loadable should render null by default 1`] = `null`;
|
|
16
|
+
|
|
17
|
+
exports[`loadable should render null by default with empty options 1`] = `null`;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
import { lazyLoad } from '../loadable';
|
|
4
|
+
|
|
5
|
+
const LoadingIndicator = () => <div>Loading</div>;
|
|
6
|
+
|
|
7
|
+
const LazyComponenWithDefaultExport = lazyLoad(
|
|
8
|
+
() => import('../../../internals/testing/loadable.mock'),
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
const LazyComponentWithExportedFunction = lazyLoad(
|
|
12
|
+
() => import('../../../internals/testing/loadable.mock'),
|
|
13
|
+
module => module.ExportedFunc,
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
const LazyComponentWithFallback = lazyLoad(
|
|
17
|
+
() => import('../../../internals/testing/loadable.mock'),
|
|
18
|
+
undefined,
|
|
19
|
+
{
|
|
20
|
+
fallback: <LoadingIndicator />,
|
|
21
|
+
},
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
describe('loadable', () => {
|
|
25
|
+
it('should render null by default', () => {
|
|
26
|
+
const {
|
|
27
|
+
container: { firstChild },
|
|
28
|
+
} = render(<LazyComponenWithDefaultExport />);
|
|
29
|
+
expect(firstChild).toMatchSnapshot();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should render null by default with empty options', () => {
|
|
33
|
+
const {
|
|
34
|
+
container: { firstChild },
|
|
35
|
+
} = render(<LazyComponentWithExportedFunction />);
|
|
36
|
+
expect(firstChild).toMatchSnapshot();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should render fallback if given one', () => {
|
|
40
|
+
const {
|
|
41
|
+
container: { firstChild },
|
|
42
|
+
} = render(<LazyComponentWithFallback />);
|
|
43
|
+
expect(firstChild).toMatchSnapshot();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should render LazyComponent after waiting for it to load', async () => {
|
|
47
|
+
const {
|
|
48
|
+
container: { firstChild },
|
|
49
|
+
} = render(<LazyComponentWithExportedFunction />);
|
|
50
|
+
LazyComponentWithExportedFunction({});
|
|
51
|
+
expect(firstChild).toMatchSnapshot();
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test the request function
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import 'whatwg-fetch';
|
|
6
|
+
import { request } from '../request';
|
|
7
|
+
|
|
8
|
+
declare let window: { fetch: jest.Mock };
|
|
9
|
+
|
|
10
|
+
describe('request', () => {
|
|
11
|
+
// Before each test, stub the fetch function
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
window.fetch = jest.fn();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
describe('stubbing successful response', () => {
|
|
17
|
+
// Before each test, pretend we got a successful response
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
const res = new Response('{"hello":"world"}', {
|
|
20
|
+
status: 200,
|
|
21
|
+
headers: {
|
|
22
|
+
'Content-type': 'application/json',
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
window.fetch.mockReturnValue(Promise.resolve(res));
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('should format the response correctly', done => {
|
|
30
|
+
request('/thisurliscorrect')
|
|
31
|
+
.catch(done)
|
|
32
|
+
.then(json => {
|
|
33
|
+
expect(json.hello).toBe('world');
|
|
34
|
+
done();
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe('stubbing 204 response', () => {
|
|
40
|
+
// Before each test, pretend we got a successful response
|
|
41
|
+
beforeEach(() => {
|
|
42
|
+
const res = new Response('', {
|
|
43
|
+
status: 204,
|
|
44
|
+
statusText: 'No Content',
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
window.fetch.mockReturnValue(Promise.resolve(res));
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should return null on 204 response', done => {
|
|
51
|
+
request('/thisurliscorrect')
|
|
52
|
+
.catch(done)
|
|
53
|
+
.then(json => {
|
|
54
|
+
expect(json).toBeNull();
|
|
55
|
+
done();
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
describe('stubbing error response', () => {
|
|
61
|
+
// Before each test, pretend we got an unsuccessful response
|
|
62
|
+
beforeEach(() => {
|
|
63
|
+
const res = new Response('', {
|
|
64
|
+
status: 404,
|
|
65
|
+
statusText: 'Not Found',
|
|
66
|
+
headers: {
|
|
67
|
+
'Content-type': 'application/json',
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
window.fetch.mockReturnValue(Promise.resolve(res));
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should catch errors', done => {
|
|
75
|
+
request('/thisdoesntexist').catch(err => {
|
|
76
|
+
expect(err.response.status).toBe(404);
|
|
77
|
+
expect(err.response.statusText).toBe('Not Found');
|
|
78
|
+
done();
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import ValidIcon from '../app/icons/ValidIcon';
|
|
2
|
+
import AlertIcon from '../app/icons/AlertIcon';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
|
|
5
|
+
export const displayMessageAfterSubmit = status => {
|
|
6
|
+
return status?.success !== undefined ? (
|
|
7
|
+
<div className="message success" data-testid="success">
|
|
8
|
+
<ValidIcon />
|
|
9
|
+
{status?.success}
|
|
10
|
+
</div>
|
|
11
|
+
) : status?.failure !== undefined ? (
|
|
12
|
+
<div className="message alert" data-testid="failure">
|
|
13
|
+
<AlertIcon />
|
|
14
|
+
{status?.failure}
|
|
15
|
+
</div>
|
|
16
|
+
) : (
|
|
17
|
+
''
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const labelize = name => {
|
|
22
|
+
return name.replace(/_/g, ' ').replace(/\b(\w)/g, char => char.toUpperCase());
|
|
23
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React, { lazy, Suspense } from 'react';
|
|
2
|
+
|
|
3
|
+
interface Opts {
|
|
4
|
+
fallback: React.ReactNode;
|
|
5
|
+
}
|
|
6
|
+
type Unpromisify<T> = T extends Promise<infer P> ? P : never;
|
|
7
|
+
|
|
8
|
+
export const lazyLoad = <
|
|
9
|
+
T extends Promise<any>,
|
|
10
|
+
U extends React.ComponentType<any>,
|
|
11
|
+
>(
|
|
12
|
+
importFunc: () => T,
|
|
13
|
+
selectorFunc?: (s: Unpromisify<T>) => U,
|
|
14
|
+
opts: Opts = { fallback: null },
|
|
15
|
+
) => {
|
|
16
|
+
let lazyFactory: () => Promise<{ default: U }> = importFunc;
|
|
17
|
+
|
|
18
|
+
if (selectorFunc) {
|
|
19
|
+
lazyFactory = () =>
|
|
20
|
+
importFunc().then(module => ({ default: selectorFunc(module) }));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const LazyComponent = lazy(lazyFactory);
|
|
24
|
+
|
|
25
|
+
return (props: React.ComponentProps<U>): JSX.Element => (
|
|
26
|
+
<Suspense fallback={opts.fallback!}>
|
|
27
|
+
<LazyComponent {...props} />
|
|
28
|
+
</Suspense>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export class ResponseError extends Error {
|
|
2
|
+
public response: Response;
|
|
3
|
+
|
|
4
|
+
constructor(response: Response) {
|
|
5
|
+
super(response.statusText);
|
|
6
|
+
this.response = response;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Parses the JSON returned by a network request
|
|
11
|
+
*
|
|
12
|
+
* @param {object} response A response from a network request
|
|
13
|
+
*
|
|
14
|
+
* @return {object} The parsed JSON from the request
|
|
15
|
+
*/
|
|
16
|
+
function parseJSON(response: Response) {
|
|
17
|
+
if (response.status === 204 || response.status === 205) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
return response.json();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Checks if a network request came back fine, and throws an error if not
|
|
25
|
+
*
|
|
26
|
+
* @param {object} response A response from a network request
|
|
27
|
+
*
|
|
28
|
+
* @return {object|undefined} Returns either the response, or throws an error
|
|
29
|
+
*/
|
|
30
|
+
function checkStatus(response: Response) {
|
|
31
|
+
if (response.status >= 200 && response.status < 300) {
|
|
32
|
+
return response;
|
|
33
|
+
}
|
|
34
|
+
const error = new ResponseError(response);
|
|
35
|
+
error.response = response;
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Requests a URL, returning a promise
|
|
41
|
+
*
|
|
42
|
+
* @param {string} url The URL we want to request
|
|
43
|
+
* @param {object} [options] The options we want to pass to "fetch"
|
|
44
|
+
*
|
|
45
|
+
* @return {object} The response data
|
|
46
|
+
*/
|
|
47
|
+
export async function request(
|
|
48
|
+
url: string,
|
|
49
|
+
options?: RequestInit,
|
|
50
|
+
): Promise<{} | { err: ResponseError }> {
|
|
51
|
+
const fetchResponse = await fetch(url, options);
|
|
52
|
+
const response = checkStatus(fetchResponse);
|
|
53
|
+
return parseJSON(response);
|
|
54
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"noImplicitAny": false,
|
|
4
|
+
"target": "es5",
|
|
5
|
+
"lib": ["dom", "dom.iterable", "esnext", "es2015"],
|
|
6
|
+
"allowJs": true,
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"allowSyntheticDefaultImports": true,
|
|
10
|
+
"strict": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"module": "commonjs",
|
|
13
|
+
"moduleResolution": "node",
|
|
14
|
+
"resolveJsonModule": true,
|
|
15
|
+
"isolatedModules": true,
|
|
16
|
+
"noEmit": true,
|
|
17
|
+
"noFallthroughCasesInSwitch": true,
|
|
18
|
+
"jsx": "react-jsx",
|
|
19
|
+
"baseUrl": "./src",
|
|
20
|
+
"preserveConstEnums": true,
|
|
21
|
+
"removeComments": true,
|
|
22
|
+
"sourceMap": true
|
|
23
|
+
},
|
|
24
|
+
"include": ["src/**/*.ts", "src/**/*.tsx", "internals/startingTemplate/**/*"],
|
|
25
|
+
"ts-node": {
|
|
26
|
+
"compilerOptions": {
|
|
27
|
+
"esModuleInterop": true,
|
|
28
|
+
"module": "commonjs",
|
|
29
|
+
"moduleResolution": "node",
|
|
30
|
+
"noEmit": false,
|
|
31
|
+
"allowSyntheticDefaultImports": true
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|