Skip to content

Commit

Permalink
Merge pull request Marklogic-retired#19 in PROD/explorer-ui from ~BAN…
Browse files Browse the repository at this point in the history
…/explorer-ui:dhfprod-3128 to develop

* commit '86a1343d6d962371b64f33f868feee6209509bdb':
  fixed unit test
  added entity link to browse documents and added search context
  • Loading branch information
Bruce An authored and Bruce An committed Sep 16, 2019
2 parents 766a75a + 86a1343 commit 668dff8
Show file tree
Hide file tree
Showing 10 changed files with 219 additions and 66 deletions.
17 changes: 17 additions & 0 deletions jmeter/.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>jmeter</name>
<comment>Project jmeter created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>
2 changes: 2 additions & 0 deletions jmeter/.settings/org.eclipse.buildship.core.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
connection.project.dir=
eclipse.preferences.version=1
15 changes: 9 additions & 6 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useContext, useEffect } from 'react';
import { Switch } from 'react-router';
import { Route, Redirect, RouteComponentProps, withRouter } from 'react-router-dom';
import { AuthContext } from './util/auth-context';
import SearchProvider from './util/search-context';
import Header from './components/header/header';
import Home from './pages/Home';
import View from './pages/View';
Expand Down Expand Up @@ -40,12 +41,14 @@ const App: React.FC<Props> = ({history, location}) => {
return (
<>
<Header/>
<Switch>
<Route path="/" exact render={() => <Home/>}/>
<PrivateRoute path="/view" exact component={View} />
<PrivateRoute path="/browse" exact component={Browse}/>
<PrivateRoute path="/detail" exact component={Detail}/>
</Switch>
<SearchProvider>
<Switch>
<Route path="/" exact render={() => <Home/>}/>
<PrivateRoute path="/view" exact component={View} />
<PrivateRoute path="/browse" exact component={Browse}/>
<PrivateRoute path="/detail" exact component={Detail}/>
</Switch>
</SearchProvider>
</>
);
}
Expand Down
10 changes: 9 additions & 1 deletion src/components/entity-table/entity-table.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { mount } from 'enzyme';
import { BrowserRouter as Router, Link } from 'react-router-dom';
import EntityTable from './entity-table';
import { entityFromJSON } from '../../util/data-conversion';
import MockEntities from '../../assets/mock-data/model-response';
Expand All @@ -10,7 +11,14 @@ describe("Entity Table component", () => {

beforeAll(() => {
let entites = entityFromJSON(MockEntities);
wrapper = mount(<EntityTable entities={entites} facetValues={EntityProperties.Collection.facetValues}/>)
wrapper = mount(
<Router>
<EntityTable
entities={entites}
facetValues={EntityProperties.Collection.facetValues}
/>
</Router>
)
});

it("entity table renders", () => {
Expand Down
13 changes: 12 additions & 1 deletion src/components/entity-table/entity-table.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import React from 'react';
import React, { useContext } from 'react';
import { Link } from 'react-router-dom';
// import styles from './entity-table.module.scss';
import { Table } from 'antd';
import { SearchContext } from '../../util/search-context';

type Props = {
entities: any[];
facetValues: any[];
}

const EntityTable:React.FC<Props> = (props) => {
const { setEntity } = useContext(SearchContext);

const expandedRowRender = (entity) => {
const columns = [
Expand Down Expand Up @@ -62,6 +65,14 @@ const EntityTable:React.FC<Props> = (props) => {
title: 'Entity Name',
dataIndex: 'name',
width: 200,
render: text => { return (
<Link to={{
pathname: "/browse",
state: { entity: text} }}
>
{text}
</Link>
)},
sorter: (a, b) => { return a.name.localeCompare(b.name) }
},
{
Expand Down
34 changes: 28 additions & 6 deletions src/components/search-bar/search-bar.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,53 @@
import React from 'react';
import React, { useContext, useEffect, useState } from 'react';
import { Select, Input } from 'antd';
import styles from './search-bar.module.scss';
import { SearchContext } from '../../util/search-context';

const SearchBar = ({ searchCallback, optionSelectCallback, entities }) => {
const SearchBar = ({ entities }) => {
const { Search } = Input;
const { Option } = Select;

const { searchOptions, setQuery, clearEntity, setEntity } = useContext(SearchContext);
const [ searchString, setSearchString] = useState(searchOptions.query);
entities = ['All Entities', ...entities];

const options = entities.map((e, i) =>
<Option value={e} key={i}>{e}</Option>
);
const entityMenu = (
<Select defaultValue="All Entities" style={{ width: 180 }} onChange={value => optionSelectCallback(value)}>
<Select style={{ width: 180 }} value={searchOptions.entityNames[0] || 'All Entities'} onChange={value => handleOptionSelect(value)}>
{options}
</Select>
);

const handleOptionSelect = (option: any) => {
option === 'All Entities' ? clearEntity() : setEntity(option);
}

const handleSearch = (searchString: string) => {
setQuery(searchString);
}

const onChange = (e) => {
setSearchString(e.target.value);
}

useEffect(() => {
if (searchString !== searchOptions.query) {
setSearchString(searchOptions.query);
}
}, [searchOptions.query]);

return (
<div className={styles.searchBar}>
<div className={styles.searchInput}>
<Search
<Search
value={searchString}
onChange={onChange}
addonBefore={entityMenu}
placeholder="Type search text"
enterButton="Search"
size="large"
onSearch={value => searchCallback(value)}
onSearch={value => handleSearch(value)}
/>
</div>
</div>
Expand Down
89 changes: 43 additions & 46 deletions src/pages/Browse.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React, { useState, useEffect, useContext } from 'react';
import axios from 'axios';
import { RouteComponentProps, withRouter, Link } from 'react-router-dom';
import { AuthContext } from '../util/auth-context';
import { SearchContext } from '../util/search-context';
import Sidebar from '../components/sidebar/sidebar';
import SearchBar from '../components/search-bar/search-bar';
import SearchPagination from '../components/search-pagination/search-pagination';
Expand All @@ -9,26 +11,38 @@ import SearchSummary from '../components/search-summary/search-summary';
import SearchResults from '../components/search-results/search-results';
import { entityFromJSON } from '../util/data-conversion';

const Browse: React.FC = () => {
interface Props extends RouteComponentProps<any> { }

const Browse: React.FC<Props> = ({location}) => {
const { Content, Sider } = Layout;

const { userNotAuthenticated } = useContext(AuthContext);
const {
searchOptions,
setPage,
setPageLength,
setSearchFacets,
setEntityClearQuery,
} = useContext(SearchContext);

const [data, setData] = useState();
const [entities, setEntites] = useState<any[]>([]);
const [facets, setFacets] = useState();
const [searchUrl, setSearchUrl] = useState<any>({ url: `/datahub/v2/search`, method: 'post' });
const [searchQuery, setSearchQuery] = useState();
const [searchParams, setSearchParams] = useState({ start: 1, pageLength: 10, entities: entities });
const [searchFacets, setSearchFacets] = useState({});
const [isLoading, setIsLoading] = useState(false);
const [entitiesLoaded, setEntitiesLoaded] = useState(false);
const [totalDocuments, setTotalDocuments] = useState();

const getEntityModel = async () => {
try {
const response = await axios(`/datahub/v2/models`);
setEntites([ ...entityFromJSON(response.data).map(entity => entity.info.title)]);
setEntitiesLoaded(true);
} catch (error) {
// console.log('error', error.response);
if (error.response.status === 401) {
userNotAuthenticated();
}
}
}

Expand All @@ -39,11 +53,11 @@ const Browse: React.FC = () => {
method: searchUrl.method,
url: searchUrl.url,
data: {
query: searchQuery,
entityNames: searchParams.entities,
start: searchParams.start,
pageLength: searchParams.pageLength,
facets: searchFacets
query: searchOptions.query,
entityNames: searchOptions.entityNames,
start: searchOptions.start,
pageLength: searchOptions.pageLength,
facets: searchOptions.searchFacets
}
});
console.log('response.data', response.data);
Expand All @@ -53,48 +67,31 @@ const Browse: React.FC = () => {
setIsLoading(false);
} catch (error) {
// console.log('error', error.response);
if (error.response.status === 401) {
userNotAuthenticated();
}
}
}

useEffect(() => {
if(location.state && location.state.entity){
setEntityClearQuery(location.state.entity);
}
getEntityModel();
getSearchResults();
}, [searchQuery, searchParams, searchFacets]);
}, []);

const handleSearch = (searchString: string) => {
console.log('The user typed string is ' + searchString);
setSearchQuery(searchString);
setSearchParams({ ...searchParams, start: 1});
}
useEffect(() => {
if (entitiesLoaded) {
getSearchResults();
}
}, [searchOptions, entitiesLoaded]);

const handlePageChange = (pageNumber: number) => {
console.log('The user selected page ' + pageNumber);
setSearchParams({ ...searchParams, start: pageNumber});
setPage(pageNumber);
}

const handlePageLengthChange = (current: number, pageSize: number) => {
console.log('The user changed page length ' + pageSize);
setSearchParams({ ...searchParams, pageLength: pageSize, start: 1});
setPageLength(current, pageSize);
}

const handleFacetClick = (constraint, vals) => {
console.log('Updated a facet ' + constraint + ': ' + vals);
if (vals.length > 0) {
setSearchFacets({ ...searchFacets, [constraint]: vals});
} else {
let newSearchFacets = { ...searchFacets };
delete newSearchFacets[constraint];
setSearchFacets(newSearchFacets);
}
setSearchParams({ ...searchParams, start: 1});
}

const handleOptionSelect = (option: string) => {
console.log('Selected Option is ' + option);
option === 'All Entities' ? setSearchParams({ ...searchParams, entities: []}) : setSearchParams({ ...searchParams, entities: [option]});
setSearchFacets(constraint, vals);
}

return (
Expand All @@ -106,30 +103,30 @@ const Browse: React.FC = () => {
/>
</Sider>
<Content style={{ background: '#fff', padding: '24px' }}>
<SearchBar searchCallback={handleSearch} optionSelectCallback={handleOptionSelect} entities={entities}/>
<SearchBar entities={entities}/>
{isLoading ?
<Spin tip="Loading..." style={{ margin: '100px auto', width: '100%'}} />
:
<>
<SearchSummary total={totalDocuments} start={searchParams.start} length={searchParams.pageLength} />
<SearchSummary total={totalDocuments} start={searchOptions.start} length={searchOptions.pageLength} />
<SearchPagination
total={totalDocuments}
onPageChange={handlePageChange}
onPageLengthChange={handlePageLengthChange}
currentPage={searchParams.start}
pageLength={searchParams.pageLength}
currentPage={searchOptions.start}
pageLength={searchOptions.pageLength}
/>
<br />
<br />
<SearchResults data={data} />
<br />
<SearchSummary total={totalDocuments} start={searchParams.start} length={searchParams.pageLength} />
<SearchSummary total={totalDocuments} start={searchOptions.start} length={searchOptions.pageLength} />
<SearchPagination
total={totalDocuments}
onPageChange={handlePageChange}
onPageLengthChange={handlePageLengthChange}
currentPage={searchParams.start}
pageLength={searchParams.pageLength}
currentPage={searchOptions.start}
pageLength={searchOptions.pageLength}
/>
</>
}
Expand All @@ -138,4 +135,4 @@ const Browse: React.FC = () => {
);
}

export default Browse;
export default withRouter(Browse);
10 changes: 5 additions & 5 deletions src/pages/Detail.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState, useEffect, useContext } from 'react';
import axios from 'axios';
import { RouteComponentProps, Link } from 'react-router-dom';
import { RouteComponentProps, withRouter, Link } from 'react-router-dom';
import { AuthContext } from '../util/auth-context';
import styles from './Detail.module.scss';
import TableView from '../components/table-view/table-view';
Expand All @@ -10,16 +10,16 @@ import { Layout, Menu, PageHeader, Spin } from 'antd';

interface Props extends RouteComponentProps<any> { }

const Detail: React.FC<Props> = ({ history }) => {
const Detail: React.FC<Props> = ({ history, location }) => {

const { Content } = Layout;
const { userNotAuthenticated } = useContext(AuthContext);
const [selected, setSelected] = useState('instance');
const [data, setData] = useState();
const [query, setQuery] = useState(history.location.state.uri);
const [query, setQuery] = useState(location.state.uri);
const [isLoading, setIsLoading] = useState(false);

let database = history.location.state.database;
let database = location.state.database;

useEffect(() => {
setIsLoading(true);
Expand Down Expand Up @@ -78,4 +78,4 @@ const Detail: React.FC<Props> = ({ history }) => {
);
}

export default Detail as any;
export default withRouter(Detail);
2 changes: 1 addition & 1 deletion src/util/auth-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const AuthContext = React.createContext<IAuthContextInterface>({

const AuthProvider: React.FC<{ children: any }> = ({children}) => {

const [user, setUser] = useState({ name: '', authenticated: false });
const [user, setUser] = useState(defaultUserData);
const sessionUser = sessionStorage.getItem('dataHubExplorerUser');

const userAuthenticated = (username: string) => {
Expand Down
Loading

0 comments on commit 668dff8

Please sign in to comment.