Skip to content

Commit 1a5f3fd

Browse files
cabhishektgianos
authored andcommitted
Ability to switch between UTC & PST timezones
This commit adds a Switch to all pages which lets you toggle between UTC & PST * All displayed time can we switch to either UTC or PST * Timezone preference is stored in a cookie for future reference * Default timezone is in UTC
1 parent 4639189 commit 1a5f3fd

20 files changed

+1934
-1704
lines changed

genie-ui/npm-shrinkwrap.json

Lines changed: 1609 additions & 1519 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

genie-ui/package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@
1919
"url": "https://github.com/Netflix/genie/issues"
2020
},
2121
"dependencies": {
22+
"create-react-class": "^15.5.3",
2223
"filesize": "^3.3.0",
2324
"install": "^0.6.2",
2425
"jquery": "^3.3.1",
25-
"moment": "^2.13.0",
26+
"moment-timezone": "^0.5.23",
2627
"prop-types": "^15.5.10",
2728
"rc-calendar": "^7.5.2",
2829
"rc-time-picker": "^2.2.1",
@@ -33,7 +34,7 @@
3334
"react-modal": "^1.4.0",
3435
"react-router": "^2.3.0",
3536
"react-select": "^1.0.0-beta13",
36-
"create-react-class": "^15.5.3"
37+
"react-switch": "^4.1.0"
3738
},
3839
"devDependencies": {
3940
"babel-core": "^6.24.1",
@@ -45,6 +46,7 @@
4546
"css-loader": "^0.23.1",
4647
"file-loader": "^0.8.5",
4748
"install": "^0.6.1",
49+
"json-loader": "^0.5.7",
4850
"npm": "^3.8.7",
4951
"prettier": "^1.3.1",
5052
"style-loader": "^0.13.1",

genie-ui/src/main/web/scripts/Application.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ export default class Application extends Page {
6060
"Status",
6161
"Version",
6262
"Tags",
63-
"Created (UTC)",
64-
"Updated (UTC)"
63+
`Created (${this.timeZone})`,
64+
`Updated (${this.timeZone})`
6565
];
6666
}
6767

genie-ui/src/main/web/scripts/Cluster.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ export default class Cluster extends Page {
5959
"Status",
6060
"Version",
6161
"Tags",
62-
"Created (UTC)",
63-
"Updated (UTC)"
62+
`Created (${this.timeZone})`,
63+
`Updated (${this.timeZone})`
6464
];
6565
}
6666

genie-ui/src/main/web/scripts/Command.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ export default class Command extends Page {
6060
"Status",
6161
"Version",
6262
"Tags",
63-
"Created (UTC)",
64-
"Updated (UTC)"
63+
`Created (${this.timeZone})`,
64+
`Updated (${this.timeZone})`
6565
];
6666
}
6767

genie-ui/src/main/web/scripts/Job.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ export default class Job extends Page {
111111
"Status",
112112
"Cluster",
113113
"Command",
114-
"Started (UTC)",
115-
"Finished (UTC)",
114+
`Started (${this.timeZone})`,
115+
`Finished (${this.timeZone})`,
116116
"Run Time"
117117
];
118118
}

genie-ui/src/main/web/scripts/Main.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,7 @@ export default class App extends React.Component {
5555
<div>
5656
<SiteHeader headers={this.props.headers} infos={this.state.infos} />
5757
<AuthCheck />
58-
<div className="container">
59-
{this.props.children}
60-
</div>
58+
<div className="container">{this.props.children}</div>
6159
<SiteFooter version={this.state.version} />
6260
</div>
6361
);

genie-ui/src/main/web/scripts/Page.js

Lines changed: 60 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import T from "prop-types";
22
import React from "react";
3+
import cookie from "react-cookie";
34
import $ from "jquery";
45

56
import SearchForm from "./components/SearchForm";
@@ -12,6 +13,7 @@ import Table from "./components/Table";
1213
import TableHeader from "./components/TableHeader";
1314
import TableBody from "./components/TableBody";
1415
import Error from "./components/Error";
16+
import ToggleTimeZone from "./components/ToggleTimeZone";
1517

1618
import { fetch, hasChanged } from "./utils";
1719

@@ -21,13 +23,16 @@ export default class Page extends React.Component {
2123

2224
constructor(props) {
2325
super(props);
26+
//load timezone preference
27+
const utcChecked = cookie.load("genie.utcChecked");
2428
this.state = {
2529
data: [],
2630
links: {},
2731
page: {},
2832
error: null,
2933
noSearchResult: false,
30-
showSearchForm: true
34+
showSearchForm: true,
35+
utcChecked: utcChecked == null ? true : JSON.parse(utcChecked) //default preference is UTC
3136
};
3237
}
3338

@@ -43,20 +48,28 @@ export default class Page extends React.Component {
4348
}
4449
}
4550

46-
toggleRowDetails = id => {
51+
get timeZone() {
52+
return this.state.utcChecked ? "UTC" : "PST";
53+
}
54+
55+
toggleRowDetails = id =>
4756
this.setState({ rowId: this.state.rowId === id ? null : id });
48-
};
4957

50-
toggleSearchForm = () => {
58+
toggleSearchForm = () =>
5159
this.setState({ showSearchForm: !this.state.showSearchForm });
60+
61+
toggleTimeZone = utcChecked => {
62+
// save tz preference in a cookie for future loads
63+
cookie.save("genie.utcChecked", utcChecked);
64+
this.setState({ utcChecked });
5265
};
5366

5467
loadPageData(query) {
5568
if ($.isEmptyObject(query)) {
5669
query = { size: 100 };
5770
}
5871
const { rowId = null, showSearchForm = "true" } = query;
59-
this.setState({ query, data: [] });
72+
this.setState({ query });
6073

6174
fetch(this.url, query)
6275
.done(data => {
@@ -81,47 +94,60 @@ export default class Page extends React.Component {
8194
}
8295

8396
render() {
84-
const sideBar = this.state.showSearchForm
85-
? <SearchForm
86-
query={this.state.query}
87-
formFields={this.formFields}
88-
hiddenFormFields={this.hiddenFormFields}
89-
toggleSearchForm={this.toggleSearchForm}
90-
searchPath={this.searchPath}
91-
/>
92-
: <SearchBar toggleSearchForm={this.toggleSearchForm} />;
97+
const sideBar = this.state.showSearchForm ? (
98+
<SearchForm
99+
query={this.state.query}
100+
formFields={this.formFields}
101+
hiddenFormFields={this.hiddenFormFields}
102+
toggleSearchForm={this.toggleSearchForm}
103+
searchPath={this.searchPath}
104+
/>
105+
) : (
106+
<SearchBar toggleSearchForm={this.toggleSearchForm} />
107+
);
93108

94109
let resultPanel = null;
95110
if (this.state.error != null) {
96111
resultPanel = <Error error={this.state.error} />;
97112
} else {
98113
resultPanel =
99-
this.state.data.length > 0
100-
? <div
101-
className={this.state.showSearchForm ? "col-md-10" : "col-md-12"}
102-
>
103-
<Table>
104-
<TableHeader headers={this.tableHeader} />
105-
<TableBody
106-
rows={this.state.data}
107-
rowId={this.state.rowId}
108-
rowType={this.rowType}
109-
detailsTable={this.detailsTable}
110-
toggleRowDetails={this.toggleRowDetails}
111-
/>
112-
</Table>
113-
<Pagination
114-
page={this.state.page}
115-
pageType={this.searchPath}
116-
links={this.state.links}
114+
this.state.data.length > 0 ? (
115+
<div
116+
className={this.state.showSearchForm ? "col-md-10" : "col-md-12"}
117+
>
118+
<Table>
119+
<TableHeader headers={this.tableHeader} />
120+
<TableBody
121+
rows={this.state.data}
122+
rowId={this.state.rowId}
123+
rowType={this.rowType}
124+
detailsTable={this.detailsTable}
125+
toggleRowDetails={this.toggleRowDetails}
126+
timeZone={this.timeZone}
117127
/>
118-
</div>
119-
: this.state.noSearchResult ? <NoSearchResult /> : <Loading />; // Default to loading...
128+
</Table>
129+
<Pagination
130+
page={this.state.page}
131+
pageType={this.searchPath}
132+
links={this.state.links}
133+
/>
134+
</div>
135+
) : this.state.noSearchResult ? (
136+
<NoSearchResult />
137+
) : (
138+
<Loading />
139+
); // Default to loading...
120140
}
121141

122142
return (
123143
<div className="row">
124144
{sideBar}
145+
<div className="timezone-toggle">
146+
<ToggleTimeZone
147+
checked={this.state.utcChecked}
148+
handleChange={this.toggleTimeZone}
149+
/>
150+
</div>
125151
{resultPanel}
126152
</div>
127153
);

genie-ui/src/main/web/scripts/components/ApplicationDetails.js

Lines changed: 40 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ import React from "react";
44
import { momentFormat, fetch } from "../utils";
55
import $ from "jquery";
66

7-
import {
8-
activeCommandUrl,
9-
stripHateoasTemplateUrl
10-
} from "../utils";
7+
import { activeCommandUrl, stripHateoasTemplateUrl } from "../utils";
118

129
import InfoTable from "./InfoTable";
1310

1411
export default class ApplicationDetails extends React.Component {
15-
static propTypes = { row: T.object.isRequired };
12+
static propTypes = {
13+
row: T.object.isRequired,
14+
timeZone: T.string.isRequired
15+
};
1616

1717
constructor(props) {
1818
super(props);
@@ -40,13 +40,12 @@ export default class ApplicationDetails extends React.Component {
4040
const commandsUrl = activeCommandUrl(row._links.commands.href);
4141
const allCommandsUrl = stripHateoasTemplateUrl(row._links.commands.href);
4242

43-
$.when(
44-
fetch(applicationUrl),
45-
fetch(commandsUrl)
46-
).done((application, commands) => {
47-
application[0]._links.commands.href = allCommandsUrl
48-
this.setState({ application: application[0], commands: commands[0] });
49-
});
43+
$.when(fetch(applicationUrl), fetch(commandsUrl)).done(
44+
(application, commands) => {
45+
application[0]._links.commands.href = allCommandsUrl;
46+
this.setState({ application: application[0], commands: commands[0] });
47+
}
48+
);
5049
}
5150

5251
render() {
@@ -59,64 +58,68 @@ export default class ApplicationDetails extends React.Component {
5958
<tbody>
6059
<tr>
6160
<td className="col-xs-2 align-right">Type:</td>
62-
<td>
63-
{this.state.application.type}
64-
</td>
61+
<td>{this.state.application.type}</td>
6562
</tr>
6663
<tr>
6764
<td className="col-xs-2 align-right">Description:</td>
68-
<td>
69-
{this.state.application.description}
70-
</td>
65+
<td>{this.state.application.description}</td>
7166
</tr>
7267
<tr>
7368
<td className="col-xs-2 align-right">Setup File:</td>
74-
<td>
75-
{this.state.application.setupFile}
76-
</td>
69+
<td>{this.state.application.setupFile}</td>
7770
</tr>
7871
<tr>
7972
<td className="col-xs-2 align-right">Config:</td>
8073
<td>
8174
<ul>
82-
{this.state.application.configs.map((config, index) =>
83-
<li key={index}>
84-
{config}
85-
</li>
86-
)}
75+
{this.state.application.configs.map((config, index) => (
76+
<li key={index}>{config}</li>
77+
))}
8778
</ul>
8879
</td>
8980
</tr>
9081
<tr>
9182
<td className="col-xs-2 align-right">Dependencies:</td>
9283
<td>
9384
<ul>
94-
{this.state.application.dependencies.map((data, index) =>
95-
<li key={index}>
96-
{data}
97-
</li>
85+
{this.state.application.dependencies.map(
86+
(data, index) => (
87+
<li key={index}>{data}</li>
88+
)
9889
)}
9990
</ul>
10091
</td>
10192
</tr>
10293
<tr>
103-
<td className="col-xs-2 align-right">Created:</td>
94+
<td className="col-xs-2 align-right">
95+
{`Created (${this.props.timeZone})`}:
96+
</td>
10497
<td>
105-
{momentFormat(this.state.application.created)}
98+
{momentFormat(
99+
this.state.application.created,
100+
this.props.timeZone
101+
)}
106102
</td>
107103
</tr>
108104
<tr>
109-
<td className="col-xs-2 align-right">Updated:</td>
105+
<td className="col-xs-2 align-right">
106+
{`Updated (${this.props.timeZone})`}:
107+
</td>
110108
<td>
111-
{momentFormat(this.state.application.updated)}
109+
{momentFormat(
110+
this.state.application.updated,
111+
this.props.timeZone
112+
)}
112113
</td>
113114
</tr>
114115
<tr>
115116
<td className="col-xs-2 align-right">Active Commands:</td>
116117
<td>
117-
{this.state.commands.length > 0
118-
? <InfoTable data={this.state.commands} type="commands" />
119-
: <div />}
118+
{this.state.commands.length > 0 ? (
119+
<InfoTable data={this.state.commands} type="commands" />
120+
) : (
121+
<div />
122+
)}
120123
</td>
121124
</tr>
122125
<tr>

0 commit comments

Comments
 (0)