Skip to content

Commit f166960

Browse files
authored
Merge pull request #120 from mahos/loading
Add loading animations
2 parents 42b49bb + 5553aa2 commit f166960

File tree

15 files changed

+274
-16
lines changed

15 files changed

+274
-16
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Observes [Semantic Versioning](https://semver.org/spec/v2.0.0.html) standard and
77
- Added case insensitive behavior to schema and table search box (#99) PR #102
88
- CSS for making the primary keys look disabled/readonly for update mode PR #105
99
- Added number of tuples input box for fetch table viewing PR #117
10+
- Added loading animation to table list load, table content load, and table action wait time (#107) PR #120
1011

1112
### Fixed
1213
- Fixed bug of delete with datetime in primarykey crashing PR #105
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
.loadingOverlay {
2+
position: absolute;
3+
z-index: 900;
4+
left: 0;
5+
top: 0;
6+
width: 100%;
7+
height: 100%;
8+
display: flex;
9+
justify-content: center;
10+
align-items: center;
11+
background-color: #f1f1f1;
12+
}
13+
14+
.basicLoadingIcon {
15+
position: relative;
16+
border-radius: 50%;
17+
border: 12px solid #92C3C9; /* container: LabBook Logo muted lightest blue shade */
18+
border-top: 12px solid #53A6B7; /* spinning thing inside container: LabBook logo bright blue shade */
19+
border-right: 12px solid #8CBAC0;
20+
border-bottom: 12px solid #86B2B8;
21+
border-left: 12px solid #57ADBE; /* spinning thing inside container: LabBook logo brightest blue shade */
22+
animation: loaderSpin 1.5s linear infinite;
23+
}
24+
25+
@keyframes loaderSpin {
26+
0% { transform: rotate(0deg); }
27+
100% { transform: rotate(360deg); }
28+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React from 'react';
2+
import './BasicLoadingIcon.css';
3+
4+
/**
5+
* Basic Loading Icon component that shows up when user is waiting for something to load
6+
*/
7+
class BasicLoadingIcon extends React.Component<{size:number}> {
8+
constructor(props: any) {
9+
super(props);
10+
}
11+
12+
iconStyle = {
13+
width: this.props.size + 'px',
14+
height: this.props.size + 'px',
15+
marginTop: -(this.props.size / 2) + 'px'
16+
}
17+
18+
render() {
19+
return (
20+
<div className="loadingOverlay">
21+
<div className="basicLoadingIcon" style={this.iconStyle}></div>
22+
</div>
23+
)
24+
}
25+
}
26+
export default BasicLoadingIcon;
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
.tableListSkeletons {
2+
position: relative;
3+
width: 100%;
4+
height: 96%;
5+
margin-bottom: 4%;
6+
border: 1px solid lightgray;
7+
}
8+
9+
.tableSkeleton {
10+
box-sizing: border-box;
11+
min-width: 100%;
12+
border: 1px solid rgba(128, 128, 128, 0.5);
13+
position: relative;
14+
overflow: hidden;
15+
padding-bottom: 4px;
16+
}
17+
18+
.tableTierLabelSkeleton {
19+
box-sizing: border-box;
20+
position: absolute;
21+
top: 4px;
22+
left: 6px;
23+
height: 0.9rem;
24+
width: 20%;
25+
border-radius: 4px;
26+
background-color: lightgray;
27+
}
28+
29+
.tableNameSkeleton {
30+
margin: 22px 4px 4px 4px;
31+
height: 1.1rem;
32+
width: 70%;
33+
background-color: lightgray;
34+
border-radius: 4px;
35+
}
36+
37+
.tableNameSkeleton::before {
38+
content: '';
39+
display: block;
40+
position: absolute;
41+
left: -100%;
42+
height: 1.1rem;
43+
width: 70%;
44+
background: linear-gradient(to right, transparent 0%, #FFF 50%, transparent 100%);
45+
animation: load 1.8s ease-in-out infinite;
46+
}
47+
48+
.tableTierLabelSkeleton::before {
49+
content: '';
50+
display: block;
51+
position: absolute;
52+
left: -100%;
53+
height: 0.9rem;
54+
width: 100%;
55+
background: linear-gradient(to right, transparent 0%, #FFF 50%, transparent 100%);
56+
animation: load 1s ease-in-out infinite;
57+
}
58+
59+
@keyframes load {
60+
from {
61+
left: -75%;
62+
}
63+
to {
64+
left: 75%;
65+
}
66+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import React from 'react';
2+
import './TableListLoading.css';
3+
4+
/**
5+
* Empty table list loading component that shows up when user is waiting for the table list
6+
*/
7+
class TableListLoading extends React.Component {
8+
constructor(props: any) {
9+
super(props);
10+
}
11+
12+
render() {
13+
return (
14+
<div className="tableListSkeletons">
15+
{[...Array(14)].map((value: undefined, index: number) => {
16+
return (
17+
<div className="tableSkeleton" key={index}>
18+
<div className="tableTierLabelSkeleton"></div>
19+
<div className="tableNameSkeleton"></div>
20+
</div>
21+
)
22+
})
23+
}
24+
</div>
25+
)
26+
}
27+
}
28+
export default TableListLoading;

src/Components/MainTableView/DeleteTuple/DeleteTuple.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ type deleteTupleState = {
1515
dependencies: Array<any>, // list of dependencies fetched from API
1616
deleteStatusMessage: string, // for GUI to show
1717
isGettingDependencies: boolean, // for loading animation status
18-
isDeletingEntry: boolean // for loading animation status
1918
deleteAccessible: boolean // valdiation result of accessibility from check dependency component
2019
}
2120

@@ -26,7 +25,8 @@ class DeleteTuple extends React.Component<{
2625
tableAttributesInfo?: TableAttributesInfo,
2726
fetchTableContent: any,
2827
clearEntrySelection: any,
29-
selectedTableEntry?: any
28+
selectedTableEntry?: any,
29+
deleteInAction: any // for loading animation status
3030
},
3131
deleteTupleState> {
3232
constructor(props: any) {
@@ -35,7 +35,6 @@ class DeleteTuple extends React.Component<{
3535
dependencies: [],
3636
deleteStatusMessage: '',
3737
isGettingDependencies: false,
38-
isDeletingEntry: false,
3938
deleteAccessible: false,
4039
}
4140

@@ -89,7 +88,7 @@ class DeleteTuple extends React.Component<{
8988
}
9089

9190
// set status true for deleting entry, switch to false once api responds
92-
this.setState({isDeletingEntry: true})
91+
this.props.deleteInAction(true)
9392

9493
// TODO: Run api fetch for list of dependencies/permission
9594
fetch(`${process.env.REACT_APP_DJLABBOOK_BACKEND_PREFIX}/delete_tuple`, {
@@ -99,7 +98,8 @@ class DeleteTuple extends React.Component<{
9998
})
10099
.then(result => {
101100
// set deleting status to done
102-
this.setState({isDeletingEntry: false, dependencies: []})
101+
this.setState({dependencies: []})
102+
this.props.deleteInAction(false)
103103

104104
// Check for error mesage 500, if so throw error - shouldn't happen as often once real dependency check is in place
105105
if (result.status === 500 || result.status === 409) {
@@ -126,6 +126,7 @@ class DeleteTuple extends React.Component<{
126126

127127
})
128128
.catch(error => {
129+
this.props.deleteInAction(false);
129130
this.setState({deleteStatusMessage: error.message});
130131
})
131132
}
@@ -184,7 +185,6 @@ class DeleteTuple extends React.Component<{
184185
<button className="cancelActionButton" onClick={() => {this.setState({dependencies: []}); this.props.clearEntrySelection();}}>Cancel</button>
185186
</div>
186187
<div className="deleting">
187-
{this.state.isDeletingEntry ? <p>Deleting entry might take a while...</p>: '' } {/* TODO: replace with proper animation */}
188188
{this.state.deleteStatusMessage ? (
189189
<div className="errorMessage">{this.state.deleteStatusMessage}<button className="dismiss" onClick={() => this.setState({deleteStatusMessage: ''})}>dismiss</button></div>
190190
) : ''}

src/Components/MainTableView/InsertTuple/InsertTuple.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ class InsertTuple extends React.Component<{
3030
tableAttributesInfo?: TableAttributesInfo,
3131
fetchTableContent: any,
3232
clearEntrySelection: any,
33-
selectedTableEntry?: any},
33+
selectedTableEntry?: any,
34+
insertInAction: any // for loading/waiting animation while insert takes place
35+
},
3436
insertTupleState> {
3537

3638
constructor(props: any) {
@@ -155,13 +157,17 @@ class InsertTuple extends React.Component<{
155157
}
156158
}
157159

160+
// start insert in action wait animation and stop when api responds
161+
this.props.insertInAction(true);
162+
158163
// All checks passed thus attempt insert
159164
fetch(`${process.env.REACT_APP_DJLABBOOK_BACKEND_PREFIX}/insert_tuple`, {
160165
method: 'POST',
161166
headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer ' + this.props.token},
162167
body: JSON.stringify({schemaName: this.props.selectedSchemaName, tableName: this.props.selectedTableName, tuple: tupleBuffer})
163168
})
164169
.then(result => {
170+
this.props.insertInAction(false);
165171
// Check for error mesage 500, if so throw and error
166172
if (result.status === 500) {
167173
result.text()
@@ -179,6 +185,7 @@ class InsertTuple extends React.Component<{
179185
this.props.fetchTableContent();
180186
})
181187
.catch((error) => {
188+
this.props.insertInAction(false);
182189
this.setState({errorMessage: error.message});
183190
})
184191
}

src/Components/MainTableView/TableContent.css

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,4 +215,35 @@ input[type="checkbox"][disabled] {
215215
.number-of-rows-per-page-input input{
216216
margin-left: 20px;
217217
width: 40px;
218+
}
219+
220+
.loadingBackdrop {
221+
position: absolute;
222+
background-color: rgba(0, 0, 0, 0.7);
223+
top: 0;
224+
left: 0;
225+
width: 100%;
226+
height: 100%;
227+
z-index: 900;
228+
display: flex;
229+
justify-content: center;
230+
align-items: center;
231+
}
232+
233+
.loadingPopup {
234+
position: relative;
235+
background-color: rgba(255, 255, 255, 0.6);
236+
border-radius: 2px;
237+
width: 300px;
238+
height: 200px;
239+
color: #262A22;
240+
display: flex;
241+
flex-direction: column;
242+
align-items: center;
243+
}
244+
245+
.loadingPopup p {
246+
position: absolute;
247+
z-index: 999;
248+
bottom: 16px;
218249
}

0 commit comments

Comments
 (0)