enabling multi dashboards API+client

This commit is contained in:
morsh 2017-04-27 18:49:07 -07:00
Родитель 4a95285161
Коммит a83a7076e8
8 изменённых файлов: 229 добавлений и 24 удалений

Просмотреть файл

@ -44,7 +44,132 @@ router.post('/dashboard.js', (req, res) => {
})
});
function isAuthoeizedToSetup(req) {
router.get('/dashboards', (req, res) => {
let privateDashboard = path.join(__dirname, '..', 'dashboards');
let preconfDashboard = path.join(__dirname, '..', 'dashboards', 'preconfigured');
let script = '';
let files = fs.readdirSync(privateDashboard);
if (files && files.length) {
files.forEach((fileName) => {
let filePath = path.join(privateDashboard, fileName);
let stats = fs.statSync(filePath);
if (stats.isFile()) {
let content = fs.readFileSync(filePath, 'utf8');
// Ensuing this dashboard is loaded into the dashboards array on the page
script += `
(function (window) {
var dashboard = (function () {
${content}
})();
window.dashboardDefinitions = window.dashboardDefinitions || [];
window.dashboardDefinitions.push(dashboard);
})(window);
`;
}
});
}
let templates = fs.readdirSync(preconfDashboard);
if (templates && templates.length) {
templates.forEach((fileName) => {
let filePath = path.join(preconfDashboard, fileName);
let stats = fs.statSync(filePath);
if (stats.isFile()) {
let content = fs.readFileSync(filePath, 'utf8');
// Ensuing this dashboard is loaded into the dashboards array on the page
script += `
(function (window) {
var dashboardTemplate = (function () {
${content}
})();
window.dashboardTemplates = window.dashboardTemplates || [];
window.dashboardTemplates.push(dashboardTemplate);
})(window);
`;
}
});
}
res.send(script);
});
router.get('/dashboards/:id', (req, res) => {
let dashboardId = req.params.id;
let privateDashboard = path.join(__dirname, '..', 'dashboards');
let preconfDashboard = path.join(__dirname, '..', 'dashboards', 'preconfigured');
let script = '';
let files = fs.readdirSync(privateDashboard) || [];
// Make sure the array only contains files
files = files.filter(fileName => fs.statSync(path.join(privateDashboard, fileName)).isFile());
if (files.length) {
let dashboardFile = null;
let dashboardIndex = parseInt(dashboardId);
if (!isNaN(dashboardIndex) && files.length > dashboardIndex) {
dashboardFile = files[dashboardIndex];
}
if (!dashboardFile) {
files.forEach(fileName => {
let filePath = path.join(privateDashboard, fileName);
let stats = fs.statSync(filePath);
if (stats.isFile()) {
let dashboard = getJSONFromScript(filePath);
if (dashboard.url && dashboard.url.toLowerCase() === dashboardId.toLowerCase()) {
dashboardFile = fileName;
}
}
})
}
if (dashboardFile) {
let filePath = path.join(privateDashboard, dashboardFile);
let stats = fs.statSync(filePath);
if (stats.isFile()) {
let content = fs.readFileSync(filePath, 'utf8');
// Ensuing this dashboard is loaded into the dashboards array on the page
script += `
(function (window) {
var dashboard = (function () {
${content}
})();
window.dashboard = dashboard || null;
})(window);
`;
}
}
}
res.send(script);
});
router.post('/dashboards/:id', (req, res) => {
let dashboardName = req.params.dashboard;
var content = (req.body && req.body.script) || '';
console.dir(content);
fs.writeFile(path.join(__dirname, '..', 'dashboards', 'dashboard.private.js'), content, err => {
if (err) {
console.error(err);
return res.end(err);
}
res.end(content);
})
});
function isAuthorizedToSetup(req) {
if (!fs.existsSync(privateSetupPath)) { return true; }
let configString = fs.readFileSync(privateSetupPath, 'utf8');
@ -61,7 +186,7 @@ function isAuthoeizedToSetup(req) {
router.get('/setup', (req, res) => {
if (!isAuthoeizedToSetup(req)) {
if (!isAuthorizedToSetup(req)) {
return res.send({ error: new Error('User is not authorized to setup') });
}
@ -76,7 +201,7 @@ router.get('/setup', (req, res) => {
router.post('/setup', (req, res) => {
if (!isAuthoeizedToSetup(req)) {
if (!isAuthorizedToSetup(req)) {
return res.send({ error: new Error('User is not authorized to setup') });
}
@ -96,3 +221,16 @@ router.post('/setup', (req, res) => {
module.exports = {
router
}
function getJSONFromScript(filePath) {
if (!fs.existsSync(filePath)) { return {}; }
let jsonScript = {};
let stats = fs.statSync(filePath);
if (stats.isFile()) {
let content = fs.readFileSync(filePath, 'utf8');
eval('jsonScript = (function () { ' + content + ' })();');
}
return jsonScript;
}

Просмотреть файл

@ -3,6 +3,7 @@ import * as request from 'xhr-request';
interface IConfigurationsActions {
loadConfiguration(): any;
loadDashboard(id: string): any;
saveConfiguration(dashboard: IDashboardConfig): any;
failure(error: any): void;
}
@ -14,17 +15,33 @@ class ConfigurationsActions extends AbstractActions implements IConfigurationsAc
loadConfiguration() {
return (dispatcher: (dashboard: IDashboardConfig) => void) => {
return (dispatcher: (result: { dashboards: IDashboardConfig[], templates: IDashboardConfig[] }) => void) => {
this.getScript('/api/dashboard.js', () => {
let dashboards: IDashboardConfig[] = (window as any)['dashboards'];
this.getScript('/api/dashboards', () => {
let dashboards: IDashboardConfig[] = (window as any)['dashboardDefinitions'];
let templates: IDashboardConfig[] = (window as any)['dashboardTemplates'];
if (!dashboards || !dashboards.length) {
return this.failure(new Error('Could not load configuration'));
}
let dashboard = dashboards[0];
return dispatcher(dashboard);
return dispatcher({ dashboards, templates });
});
};
}
loadDashboard(id: string) {
return (dispatcher: (result: { dashboard: IDashboardConfig }) => void) => {
this.getScript('/api/dashboards/' + id, () => {
let dashboard: IDashboardConfig = (window as any)['dashboard'];
if (!dashboard) {
return this.failure(new Error('Could not load configuration for dashboard ' + id));
}
return dispatcher({ dashboard });
});
};
}

Просмотреть файл

@ -35,7 +35,7 @@ export default class ConfigDashboard extends React.Component<IConfigDashboardPro
this.onSave = this.onSave.bind(this);
this.onSaveGoToDashboard = this.onSaveGoToDashboard.bind(this);
ConfigurationsActions.loadConfiguration();
//ConfigurationsActions.loadConfiguration();
}
onParamChange(connectionKey, paramKey, value) {

Просмотреть файл

@ -12,6 +12,8 @@ import Chip from 'react-md/lib/Chips';
import AccountStore from '../../stores/AccountStore';
import AccountActions from '../../actions/AccountActions';
import ConfigurationsStore from '../../stores/ConfigurationsStore';
import './style.css';
const avatarSrc = 'https://cloud.githubusercontent.com/assets/13041/19686250/971bf7f8-9ac0-11e6-975c-188defd82df1.png';
@ -47,9 +49,16 @@ export default class Navbar extends React.Component<any, any> {
this.setState(state);
});
AccountActions.updateAccount();
ConfigurationsStore.listen((state) => {
this.setState({
dashboards: state.dashboards
});
});
}
render() {
let { dashboards } = this.state;
let { children, title } = this.props;
let pathname = '/';
try { pathname = window.location.pathname; } catch (e) { }
@ -81,17 +90,6 @@ export default class Navbar extends React.Component<any, any> {
<ListItem
key="2"
component={Link}
href="/dashboard"
active={pathname === '/dashboard'}
leftIcon={<FontIcon>dashboard</FontIcon>}
tileClassName="md-list-tile--mini"
primaryText={'Dashboard'}
/>
),
(
<ListItem
key="3"
component={Link}
href="/setup"
active={pathname === '/setup'}
leftIcon={<FontIcon>settings</FontIcon>}
@ -101,6 +99,30 @@ export default class Navbar extends React.Component<any, any> {
)
];
(dashboards || []).forEach((dashboard, index) => {
let name = dashboard.name || null;
let url = '/dashboard/' + (dashboard.url || index.toString());
let active = pathname === url;
if (!title && active && name) {
title = name;
}
navigationItems.push(
(
<ListItem
key={index + 4}
component={Link}
href={url}
active={active}
leftIcon={<FontIcon>{dashboard.icon || 'dashboard'}</FontIcon>}
tileClassName="md-list-tile--mini"
primaryText={name || 'Dashboard'}
/>
)
)
});
let toolbarActions =
this.state.account ?
<Chip style={{ marginRight: 30 }} label={'Hello, ' + this.state.account.displayName} /> :
@ -129,6 +151,7 @@ export default class Navbar extends React.Component<any, any> {
break;
default:
title = 'Ibex Dashboard';
break;
}

Просмотреть файл

@ -22,7 +22,7 @@ export default class Config extends React.Component<any, IDashboardState> {
constructor(props: any) {
super(props);
ConfigurationsActions.loadConfiguration();
//ConfigurationsActions.loadConfiguration();
}
componentDidMount() {

Просмотреть файл

@ -23,7 +23,7 @@ export default class Dashboard extends React.Component<any, IDashboardState> {
constructor(props: any) {
super(props);
ConfigurationsActions.loadConfiguration();
// ConfigurationsActions.loadConfiguration();
}
componentDidMount() {

Просмотреть файл

@ -16,6 +16,7 @@ export default (
<Route path="/about" component={About} />
<Route path="/dashboard" component={Dashboard} />
<Route path="/dashboard/config" component={Config} />
<Route path="/dashboard/:id" component={Dashboard}/>
<Route path="/setup" component={Setup} />
<Route path="*" component={NotFound} />
</Route>

Просмотреть файл

@ -7,6 +7,8 @@ import configurationActions from '../actions/ConfigurationsActions';
interface IConfigurationsStoreState {
dashboard: IDashboardConfig;
dashboards: IDashboardConfig[];
templates: IDashboardConfig[];
connections: IDictionary;
connectionsMissing: boolean;
loaded: boolean;
@ -15,6 +17,8 @@ interface IConfigurationsStoreState {
class ConfigurationsStore extends AbstractStoreModel<IConfigurationsStoreState> implements IConfigurationsStoreState {
dashboard: IDashboardConfig;
dashboards: IDashboardConfig[];
templates: IDashboardConfig[];
connections: IDictionary;
connectionsMissing: boolean;
loaded: boolean;
@ -23,16 +27,38 @@ class ConfigurationsStore extends AbstractStoreModel<IConfigurationsStoreState>
super();
this.dashboard = null;
this.dashboards = null;
this.templates = null;
this.connections = {};
this.connectionsMissing = false;
this.loaded = false;
this.bindListeners({
loadConfiguration: configurationActions.loadConfiguration
loadConfiguration: configurationActions.loadConfiguration,
loadDashboard: configurationActions.loadDashboard
});
configurationActions.loadConfiguration();
let pathname = window.location.pathname;
if (pathname === '/dashboard') {
configurationActions.loadDashboard("0");
}
loadConfiguration(dashboard: IDashboardConfig) {
if (pathname.startsWith('/dashboard/')) {
let dashboardId = pathname.substring('/dashboard/'.length);
configurationActions.loadDashboard(dashboardId);
}
}
loadConfiguration(result: { dashboards: IDashboardConfig[], templates: IDashboardConfig[] }) {
let { dashboards,templates } = result;
this.dashboards = dashboards;
this.templates = templates;
}
loadDashboard(result: { dashboard: IDashboardConfig }) {
let { dashboard } = result;
this.dashboard = dashboard;
if (this.dashboard && !this.loaded) {