Web-console: add history menu to supervisors modal (#8164)

* Add history menu to supervisors dialog

* add scrolling

* change how tabs render

* remove copy button

* user query manager
This commit is contained in:
mcbrewster 2019-07-30 08:07:58 -07:00 committed by Fangjin Yang
parent 80a0fbf254
commit a0270512a2
9 changed files with 361 additions and 1 deletions

View File

@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`rule editor matches snapshot 1`] = `null`;

View File

@ -0,0 +1,36 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.show-history {
position: relative;
height: 100%;
.tab-area {
position: relative;
height: 100%;
}
.panel {
position: relative;
width: 100%;
}
.bp3-tab-list {
overflow-y: auto;
}
}

View File

@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { render } from '@testing-library/react';
import React from 'react';
import { ShowHistory } from './show-history';
describe('rule editor', () => {
it('matches snapshot', () => {
const showJson = <ShowHistory endpoint={'test'} downloadFilename={'test'} />;
const { container } = render(showJson);
expect(container.firstChild).toMatchSnapshot();
});
});

View File

@ -0,0 +1,109 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Tab, Tabs } from '@blueprintjs/core';
import axios from 'axios';
import React from 'react';
import { QueryManager } from '../../utils';
import { Loader } from '../loader/loader';
import { ShowValue } from '../show-value/show-value';
import './show-history.scss';
export interface PastSupervisor {
version: string;
spec: any;
}
export interface ShowHistoryProps {
endpoint: string;
transform?: (x: any) => any;
downloadFilename?: string;
}
export interface ShowHistoryState {
data?: PastSupervisor[];
loading: boolean;
error?: string;
}
export class ShowHistory extends React.PureComponent<ShowHistoryProps, ShowHistoryState> {
private showHistoryQueryManager: QueryManager<null, string>;
constructor(props: ShowHistoryProps, context: any) {
super(props, context);
this.state = {
data: [],
loading: true,
};
this.showHistoryQueryManager = new QueryManager({
processQuery: async () => {
const resp = await axios.get(this.props.endpoint);
return resp.data;
},
onStateChange: ({ result, loading, error }) => {
this.setState({
loading,
data: result,
error,
});
},
});
}
componentDidMount(): void {
this.showHistoryQueryManager.runQuery(null);
}
render() {
const { downloadFilename, endpoint } = this.props;
const { data, loading } = this.state;
if (loading) return <Loader />;
if (!data) return;
const versions = data.map((pastSupervisor: PastSupervisor, index: number) => (
<Tab
id={index}
key={index}
title={pastSupervisor.version}
panel={
<ShowValue
jsonValue={JSON.stringify(pastSupervisor.spec, undefined, 2)}
downloadFilename={downloadFilename + 'version-' + pastSupervisor.version}
endpoint={endpoint}
/>
}
panelClassName={'panel'}
/>
));
return (
<div className="show-history">
<Tabs
animate
renderActiveTabPanelOnly
vertical
className={'tab-area'}
defaultSelectedTabId={0}
>
{versions}
<Tabs.Expander />
</Tabs>
</div>
);
}
}

View File

@ -0,0 +1,44 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`rule editor matches snapshot 1`] = `
<div
class="show-json"
>
<div
class="top-actions"
>
<div
class="bp3-button-group right-buttons"
>
<button
class="bp3-button bp3-minimal"
type="button"
>
<span
class="bp3-button-text"
>
Save
</span>
</button>
<button
class="bp3-button bp3-minimal"
type="button"
>
<span
class="bp3-button-text"
>
View raw
</span>
</button>
</div>
</div>
<div
class="main-area"
>
<textarea
class="bp3-input"
readonly=""
/>
</div>
</div>
`;

View File

@ -0,0 +1,41 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.show-value {
position: relative;
height: 100%;
.top-actions {
text-align: right;
padding-bottom: 10px;
& > * {
display: inline-block;
}
}
.main-area {
height: calc(100% - 40px);
textarea {
height: 100%;
width: 100%;
resize: none;
}
}
}

View File

@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { render } from '@testing-library/react';
import React from 'react';
import { ShowValue } from './show-value';
describe('rule editor', () => {
it('matches snapshot', () => {
const showJson = <ShowValue endpoint={'test'} downloadFilename={'test'} />;
const { container } = render(showJson);
expect(container.firstChild).toMatchSnapshot();
});
});

View File

@ -0,0 +1,66 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Button, ButtonGroup, TextArea } from '@blueprintjs/core';
import React from 'react';
import { UrlBaser } from '../../singletons/url-baser';
import { downloadFile } from '../../utils';
import './show-value.scss';
export interface ShowValueProps {
endpoint: string;
downloadFilename?: string;
jsonValue?: string;
}
export class ShowValue extends React.PureComponent<ShowValueProps> {
constructor(props: ShowValueProps, context: any) {
super(props, context);
}
render(): JSX.Element {
const { endpoint, downloadFilename, jsonValue } = this.props;
return (
<div className="show-json">
<div className="top-actions">
<ButtonGroup className="right-buttons">
{downloadFilename && (
<Button
text="Save"
minimal
onClick={() =>
jsonValue ? downloadFile(jsonValue, 'json', downloadFilename) : null
}
/>
)}
<Button
text="View raw"
minimal
onClick={() => window.open(UrlBaser.base(endpoint), '_blank')}
/>
</ButtonGroup>
</div>
<div className="main-area">
<TextArea readOnly value={jsonValue} />
</div>
</div>
);
}
}

View File

@ -20,6 +20,7 @@ import { IDialogProps } from '@blueprintjs/core';
import React from 'react';
import { ShowJson } from '../../components';
import { ShowHistory } from '../../components/show-history/show-history';
import { BasicAction, basicActionsToButtons } from '../../utils/basic-action';
import { deepGet } from '../../utils/object-change';
import { SideButtonMetaData, TableActionDialog } from '../table-action-dialog/table-action-dialog';
@ -103,7 +104,7 @@ export class SupervisorTableActionDialog extends React.PureComponent<
/>
)}
{activeTab === 'history' && (
<ShowJson
<ShowHistory
endpoint={`/druid/indexer/v1/supervisor/${supervisorId}/history`}
downloadFilename={`supervisor-history-${supervisorId}.json`}
/>