Skip to content

Commit 735ebc8

Browse files
authored
Merge pull request #56 from webdevstar/bugfix272
Bugfix272
2 parents 9c3e2e7 + 7ccac13 commit 735ebc8

File tree

24 files changed

+3556
-966
lines changed

24 files changed

+3556
-966
lines changed

server/dashboards/preconfigured/bot-framework-inst.ts

Lines changed: 1472 additions & 0 deletions
Large diffs are not rendered by default.

server/dashboards/preconfigured/bot-framework.ts

Lines changed: 1103 additions & 860 deletions
Large diffs are not rendered by default.

server/dashboards/preconfigured/cosmosdb-handoff.ts

Lines changed: 349 additions & 77 deletions
Large diffs are not rendered by default.

src/data-sources/plugins/ApplicationInsights/ai.d.ts renamed to src/@types/ai.d.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
/* tslint:disable */
2-
31
interface IQueryResults {
42
Tables: IQueryResult[]
53
}
File renamed without changes.

src/components/Home/index.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ export default class Home extends React.Component<any, IHomeState> {
183183
return null;
184184
}
185185

186-
let templateCards = templates.map((temp, index) => (
186+
let createCard = (temp, index) => (
187187
<div key={index} className="md-cell" style={styles.card}>
188188
<Card className="md-block-centered" key={index} >
189189
<Media>
@@ -202,10 +202,22 @@ export default class Home extends React.Component<any, IHomeState> {
202202
</CardActions>
203203
</Card>
204204
</div>
205-
));
205+
);
206+
207+
// Finding featured
208+
let featuredCards = templates
209+
.filter(temp => temp.id === 'bot_analytics_dashboard' || temp.id === 'bot_analytics_inst')
210+
.map(createCard);
211+
let templateCards = templates.map(createCard);
206212

207213
return (
208214
<div>
215+
<h1>Bot Analytics</h1>
216+
<div className="md-grid">
217+
{featuredCards}
218+
</div>
219+
220+
<h1>All Dashboards</h1>
209221
<div className="md-grid">
210222
{templateCards}
211223
</div>
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import * as React from 'react';
2+
import * as _ from 'lodash';
3+
4+
import ListItem from 'react-md/lib/Lists/ListItem';
5+
import List from 'react-md/lib/Lists/List';
6+
7+
import plugins from '../../../data-sources/plugins';
8+
9+
interface IDataSourceSettingsProps {
10+
settings: IDataSourceContainer;
11+
}
12+
13+
interface IDataSourceSettingsState {
14+
selectedIndex: number;
15+
}
16+
17+
/// This class displays a UI to edit the different data sources of the config file.
18+
export default class DataSourceSettings extends React.Component<IDataSourceSettingsProps, IDataSourceSettingsState> {
19+
20+
static uniqueId = 0;
21+
22+
state = {
23+
selectedIndex: 0
24+
};
25+
26+
constructor(props: IDataSourceSettingsProps) {
27+
super(props);
28+
29+
this.onMenuClick = this.onMenuClick.bind(this);
30+
this.getSettings = this.getSettings.bind(this);
31+
this.getSettingsEditor = this.getSettingsEditor.bind(this);
32+
}
33+
34+
/**
35+
* Each element is expected to expose a static 'editor' property, which is the UI editor for this specific
36+
* data source node.
37+
*/
38+
getSettingsEditor(element: DataSource): JSX.Element {
39+
40+
if (!element) { return null; }
41+
42+
let ReactElementClass = plugins[element.type];
43+
if (ReactElementClass && ReactElementClass.editor) {
44+
let SettingsEditor = ReactElementClass.editor;
45+
return <SettingsEditor key={DataSourceSettings.uniqueId++} settings={element} />;
46+
}
47+
return null;
48+
}
49+
50+
onMenuClick(index: number) {
51+
this.setState({ selectedIndex: index });
52+
}
53+
54+
/**
55+
* Get the selected settings from the provided array of settings, based on the user selection.
56+
*/
57+
getSettings(): IDataSource {
58+
if (this.props && this.props.settings && this.props.settings.dataSources) {
59+
return this.props.settings.dataSources.length > this.state.selectedIndex ?
60+
this.props.settings.dataSources[this.state.selectedIndex] :
61+
null;
62+
}
63+
return null;
64+
}
65+
66+
render() {
67+
68+
let renderSettingsEditor = (): JSX.Element => {
69+
let selectedSettings = this.getSettings();
70+
if (!selectedSettings) {
71+
return <h1>No data-sources were found</h1>;
72+
}
73+
74+
let editor = this.getSettingsEditor(selectedSettings);
75+
if (editor) { return editor; }
76+
77+
return <h1>No settings yet for {selectedSettings.type}</h1>;
78+
};
79+
80+
let renderMenuItems = (): JSX.Element => {
81+
let { selectedIndex } = this.state;
82+
let items = this.props.settings.dataSources.map((item, idx) => (
83+
<ListItem
84+
key={idx}
85+
primaryText={item.id}
86+
onClick={this.onMenuClick.bind(this, idx)}
87+
className={selectedIndex === idx ? 'active-item' : ''}
88+
active={selectedIndex === idx}
89+
/>
90+
));
91+
92+
return (
93+
<List className="md-cell md-paper md-paper--1 md-cell--top md-cell--left md-cell--2 vertical-menu">
94+
{items}
95+
</List>
96+
);
97+
};
98+
99+
return (
100+
<div className="md-grid md-cell md-cell--12">
101+
{renderMenuItems()}
102+
<div className="md-cell md-cell--top md-cell--stretch md-cell--10">
103+
{renderSettingsEditor()}
104+
</div>
105+
</div>
106+
);
107+
}
108+
}

src/components/Settings/SettingsButton.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { ToastActions } from '../Toast';
1313

1414
import ConnectionsSettings from './ConnectionsSettings';
1515
import ElementsSettings from './ElementsSettings';
16+
import DatasourceSettings from './DatasourceSettings';
1617
import SettingsStore, { ISettingsStoreState } from '../../stores/SettingsStore';
1718
import SettingsActions from '../../actions/SettingsActions';
1819
import ConfigurationsActions from '../../actions/ConfigurationsActions';
@@ -157,15 +158,16 @@ export default class SettingsButton extends React.Component<ISettingsButtonProps
157158
<ConnectionsSettings connections={dashboard.config.connections} />
158159
</div>
159160
</Tab>
161+
{/* For now, we are deprecating the settings view
160162
<Tab label={VIEWS.Elements}>
161163
<ElementsSettings settings={dashboard} />
162164
</Tab>
163165
<Tab label={VIEWS.DataSources}>
164-
<h1>{VIEWS.DataSources} - is not implemented yet</h1>
166+
<h1><DatasourceSettings settings={dashboard} /></h1>
165167
</Tab>
166168
<Tab label={VIEWS.Filters}>
167169
<h1>{VIEWS.Filters} - is not implemented yet</h1>
168-
</Tab>
170+
</Tab>*/}
169171
</Tabs>
170172
</TabsContainer>
171173
</Dialog>
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import * as React from 'react';
2+
import * as _ from 'lodash';
3+
4+
import Card from 'react-md/lib/Cards/Card';
5+
import TextField from 'react-md/lib/TextFields';
6+
import FontIcon from 'react-md/lib/FontIcons';
7+
import CardTitle from 'react-md/lib/Cards/CardTitle';
8+
import Switch from 'react-md/lib/SelectionControls/Switch';
9+
import Avatar from 'react-md/lib/Avatars';
10+
import SelectField from 'react-md/lib/SelectFields';
11+
12+
import SettingsActions from '../../actions/SettingsActions';
13+
14+
export interface IBaseSettingsProps {
15+
settings: DataSource;
16+
}
17+
18+
export interface IBaseSettingsState {
19+
}
20+
21+
/**
22+
* This base class encapsules shared methods for all types of data sources
23+
*/
24+
export abstract class BaseDataSourceSettings<T extends IBaseSettingsState>
25+
extends React.Component<IBaseSettingsProps, T> {
26+
27+
// an icon to be displayed when selecting the specific data source settings in the settings dialog
28+
abstract icon: string;
29+
30+
// Implement this menthod with your desired UI implementation.
31+
abstract renderChildren();
32+
33+
constructor(props: IBaseSettingsProps) {
34+
super(props);
35+
36+
this.onParamChange = this.onParamChange.bind(this);
37+
this.onParamSelectChange = this.onParamSelectChange.bind(this);
38+
this.getProperty = this.getProperty.bind(this);
39+
this.updateProperty = this.updateProperty.bind(this);
40+
this.renderChildren = this.renderChildren.bind(this);
41+
}
42+
43+
/**
44+
* A helper method for finding an object by a given dot notation string representation.
45+
* e.g: data.size.x
46+
*/
47+
protected getProperty(property: string, defaultValue: any = null): any {
48+
let { settings } = this.props;
49+
let arr = property.split('.');
50+
let obj = settings;
51+
let parent = obj;
52+
53+
while (arr.length && (obj = obj && obj[arr.shift()])) { }
54+
55+
if (typeof obj !== 'undefined') { return obj; }
56+
57+
return defaultValue;
58+
}
59+
60+
/**
61+
* A helper method for updaing an object by a given dot notation string representation.
62+
* e.g: data.size.x
63+
*/
64+
protected updateProperty(property: string, value: any): void {
65+
let { settings } = this.props;
66+
let arr = property.split('.');
67+
let object: any = settings;
68+
let parent: any;
69+
let key: string;
70+
71+
while (arr.length && (parent = object) && (key = arr.shift()) && (object = object[key])) { }
72+
if (parent) { parent[key] = value; }
73+
}
74+
75+
onParamChange(value: string, event: UIEvent) {
76+
var t: any = event.target;
77+
this.updateProperty(t.id, value);
78+
}
79+
80+
onParamSelectChange(newValue: string, newActiveIndex: number, event: any) {
81+
82+
// a little hacking to get the id of the parent,
83+
// because event does not contain the outer element, but only the inner li
84+
let cur = event.target;
85+
86+
while (cur && !cur.classList.contains('ddl')) {
87+
cur = cur.parentNode;
88+
}
89+
90+
if (cur) {
91+
cur = cur.querySelector('input');
92+
var id = cur.id;
93+
this.updateProperty(id, newValue);
94+
}
95+
}
96+
97+
render() {
98+
let { settings } = this.props;
99+
let { id, type } = settings;
100+
return (
101+
<Card>
102+
<CardTitle title={type} avatar={<Avatar random icon={<FontIcon>{this.icon}</FontIcon>} />} />
103+
<div className="md-grid">
104+
<TextField
105+
id="id"
106+
label="Id"
107+
placeholder="id"
108+
leftIcon={<FontIcon>settings</FontIcon>}
109+
className="md-cell md-cell--bottom md-cell--6"
110+
defaultValue={id}
111+
onChange={this.onParamChange}
112+
/>
113+
{this.renderChildren()}
114+
</div>
115+
</Card>
116+
);
117+
}
118+
};

src/components/common/TokenInput.tsx

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import * as React from 'react';
2+
import * as _ from 'lodash';
3+
import Paper from 'react-md/lib/Papers';
4+
import Button from 'react-md/lib/Buttons';
5+
import TextField from 'react-md/lib/TextFields';
6+
import Chip from 'react-md/lib/Chips';
7+
import Divider from 'react-md/lib/Dividers';
8+
9+
interface ITokenInputProps {
10+
tokens: any[];
11+
zDepth: number;
12+
onTokensChanged(): void;
13+
};
14+
15+
interface ITokenInputState {
16+
newToken: any;
17+
};
18+
19+
/**
20+
* This is a UI for editing a string array.
21+
*/
22+
export default class TokenInput extends React.Component<ITokenInputProps, ITokenInputState> {
23+
24+
state: ITokenInputState = {
25+
newToken: ''
26+
};
27+
28+
constructor(props: ITokenInputProps) {
29+
super(props);
30+
this.removeToken = this.removeToken.bind(this);
31+
this.onNewTokenChange = this.onNewTokenChange.bind(this);
32+
this.addToken = this.addToken.bind(this);
33+
}
34+
35+
removeToken(token: any) {
36+
let tokens = this.props.tokens;
37+
_.remove(tokens, x => x === token);
38+
if (this.props.onTokensChanged) {
39+
this.props.onTokensChanged();
40+
}
41+
this.setState(this.state); // foce the component to update
42+
}
43+
44+
onNewTokenChange(newData: any) {
45+
this.setState({ newToken: newData });
46+
}
47+
48+
addToken() {
49+
if (this.state.newToken) {
50+
let {tokens} = this.props;
51+
tokens = tokens || [];
52+
tokens.push(this.state.newToken);
53+
this.setState({
54+
newToken: ''
55+
});
56+
if (this.props.onTokensChanged) {
57+
this.props.onTokensChanged();
58+
}
59+
}
60+
}
61+
62+
render() {
63+
let { tokens, zDepth } = this.props;
64+
let { newToken } = this.state;
65+
66+
let chips = tokens.map((token: string, index: number) => (
67+
<Chip
68+
key={index}
69+
onClick={this.removeToken.bind(this, token)}
70+
removable
71+
label={token}
72+
/>
73+
));
74+
75+
return (
76+
<Paper zDepth={zDepth} >
77+
<div style={{ padding: 5 }}>
78+
{chips}
79+
</div>
80+
<Divider />
81+
<div className="md-grid">
82+
<TextField
83+
id="addTokenInput"
84+
lineDirection="center"
85+
placeholder="Add a value"
86+
className="md-cell md-cell--bottom"
87+
value={newToken}
88+
onChange={this.onNewTokenChange}
89+
/>
90+
<Button icon primary onClick={this.addToken} className="md-cell">add_circle</Button>
91+
</div>
92+
</Paper>
93+
);
94+
}
95+
};

0 commit comments

Comments
 (0)