Skip to content

Commit f7d34a2

Browse files
authored
Demo module example page with usages of QueryModel API (#33)
* Add new demo module entryPoint with example usages of DetailPanelWithModel, GridPanel, and withQueryModels
1 parent a2e104c commit f7d34a2

9 files changed

Lines changed: 1053 additions & 87 deletions

File tree

demo/package-lock.json

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

demo/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
},
1414
"dependencies": {
1515
"@labkey/api": "1.1.1",
16+
"@labkey/components": "1.1.1",
1617
"react": "16.13.1",
1718
"react-dom": "16.13.1"
1819
},
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import React, { PureComponent } from 'react';
2+
import { DetailPanelWithModel, QueryConfig, SchemaQuery } from '@labkey/components';
3+
import { getServerContext } from '@labkey/api';
4+
5+
interface Props {
6+
asPanel?: boolean
7+
}
8+
9+
export class ExampleDetailPanel extends PureComponent<Props> {
10+
// This function will return the QueryConfig definition for the LabKey schema/query to use for the API call
11+
// to get data from the LabKey server about the given container (i.e. keyValue).
12+
getQueryConfig(): QueryConfig {
13+
return {
14+
schemaQuery: SchemaQuery.create('core', 'Containers'),
15+
keyValue: getServerContext().container.id
16+
};
17+
}
18+
19+
// The render function of this component just passes along the QueryConfig to the @labkey/component's
20+
// DetailPanelWithModel component. That component will make the API call to get the data and render the results.
21+
render() {
22+
return (
23+
<DetailPanelWithModel
24+
asPanel={this.props.asPanel}
25+
queryConfig={this.getQueryConfig()}
26+
/>
27+
)
28+
}
29+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import React, { PureComponent } from 'react';
2+
import { GridPanel, InjectedQueryModels, withQueryModels } from '@labkey/components';
3+
4+
// First define the properties of the component you're going to wrap with withQueryModels.
5+
interface OwnProps {
6+
title: string;
7+
asPanel: boolean;
8+
}
9+
10+
// Here we create a type that includes InjectedQueryModels because
11+
// we're wrapping the component with withQueryModels which will inject
12+
// queryModels and actions objects.
13+
type Props = OwnProps & InjectedQueryModels;
14+
15+
// Here we use the name ExampleGridPanelImpl, users will not use this
16+
// component directly, only the wrapped version below which we expose
17+
// to users as ExampleGridPanel.
18+
class ExampleGridPanelImpl extends PureComponent<Props> {
19+
onRefreshGrid = () => {
20+
const { queryModels, actions } = this.props;
21+
const { containersModel } = queryModels;
22+
23+
actions.loadModel(containersModel.id);
24+
};
25+
26+
// This is an example of a custom button bar element in your GridPanel that can interact with the QueryModel.
27+
renderGridButtons = () => {
28+
return (
29+
<button className={'labkey-button'} onClick={this.onRefreshGrid}>
30+
Refresh Grid
31+
</button>
32+
)
33+
};
34+
35+
render() {
36+
// Note that queryModels and actions come from InjectedQueryModels via withQueryModels
37+
const { queryModels, actions, title, asPanel } = this.props;
38+
const { containersModel } = queryModels;
39+
40+
return (
41+
<GridPanel
42+
model={containersModel}
43+
ButtonsComponent={this.renderGridButtons}
44+
actions={actions}
45+
title={title}
46+
asPanel={asPanel}
47+
hideEmptyChartMenu={true}
48+
hideEmptyViewMenu={true}
49+
/>
50+
);
51+
}
52+
}
53+
54+
// Next wrap your component with withQueryModels, here we set the type
55+
// to OwnProps so the returned component, ExampleGridPanel, can
56+
// be used in a type-safe manner. In this case, if the user forgets to
57+
// pass in a title or the asPanel property, we'll get a compiler error as intended.
58+
export const ExampleGridPanel = withQueryModels<OwnProps>(ExampleGridPanelImpl);
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import React, { PureComponent } from 'react';
2+
import { Query } from '@labkey/api';
3+
import { SchemaQuery } from '@labkey/components';
4+
5+
import { ExampleDetailPanel } from "./ExampleDetailPanel";
6+
import { ExampleGridPanel } from "./ExampleGridPanel";
7+
8+
import './queryModelExample.scss';
9+
10+
export class App extends PureComponent {
11+
render() {
12+
const queryConfigs = {
13+
containersModel: {
14+
schemaQuery: SchemaQuery.create('core', 'Containers'),
15+
containerFilter: Query.containerFilter.allFolders,
16+
omittedColumns: ['SortOrder','Searchable','Type','Title','ContainerType','Workbook','IdPrefixedName']
17+
}
18+
};
19+
20+
return (
21+
<>
22+
<p>
23+
This page contains two example usages of the <b>QueryModel API</b>. The first panel uses
24+
the <b>DetailPanelWithModel</b> to show a details view of some information about the current
25+
LabKey container. The second panel uses the <b>GridPanel</b> and <b>withQueryModels</b> to show a
26+
grid panel view of LabKey container information for all Labkey containers that the current,
27+
logged-in user has permissions to access. This component has options for sorting, filtering, paging,
28+
and exporting the data shown in the grid.
29+
</p>
30+
<p>
31+
Further details on these components and examples can be found in the&nbsp;
32+
<a href={'https://github.com/LabKey/labkey-ui-components/blob/master/packages/components/docs/public.md'} target={'_blank'}>Public API Docs</a>&nbsp;
33+
page for the <b>@labkey/components</b> package.
34+
</p>
35+
<ExampleDetailPanel
36+
asPanel={true}
37+
/>
38+
<ExampleGridPanel
39+
title="LabKey Server Containers"
40+
queryConfigs={queryConfigs}
41+
asPanel={true}
42+
autoLoad
43+
/>
44+
</>
45+
)
46+
}
47+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import React from 'react';
2+
import ReactDOM from 'react-dom';
3+
4+
import { App } from './QueryModelExample';
5+
6+
// Need to wait for container element to be available in labkey wrapper before render
7+
window.addEventListener('DOMContentLoaded', (event) => {
8+
ReactDOM.render(<App/>, document.getElementById('app'));
9+
});
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import React from 'react';
2+
import ReactDOM from 'react-dom';
3+
import { AppContainer } from 'react-hot-loader';
4+
5+
import { App } from './QueryModelExample';
6+
7+
const render = () => {
8+
ReactDOM.render(
9+
<AppContainer>
10+
<App />
11+
</AppContainer>,
12+
document.getElementById('app')
13+
)
14+
};
15+
16+
declare const module: any;
17+
18+
if (module.hot) {
19+
module.hot.accept();
20+
}
21+
22+
render();
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@import "~@labkey/components/dist/assets/scss/theme";

demo/src/client/entryPoints.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,10 @@ module.exports = {
2020
permission: 'read',
2121
path: './src/client/ToDoListPage/webpart',
2222
generateLib: true // used by views/demoWebpart.html
23+
},{
24+
name: 'queryModel',
25+
title: 'QueryModel Example Page',
26+
permission: 'read',
27+
path: './src/client/QueryModelPage'
2328
}]
2429
};

0 commit comments

Comments
 (0)