moved state to redux, renamed entities

This commit is contained in:
Peter Holmberg
2018-10-26 14:15:37 +02:00
parent a98f7e548f
commit affb04a3ce
8 changed files with 172 additions and 92 deletions

View File

@@ -6,18 +6,28 @@ import ResetStyles from './ResetStyles';
interface Props { interface Props {
options: any[]; options: any[];
className?: string; className?: string;
placeholder?: string;
width: number;
onSelected: (item: any) => {} | void; onSelected: (item: any) => {} | void;
getOptionValue: (item: any) => string; getOptionValue: (item: any) => string;
getOptionLabel: (item: any) => string; getOptionLabel: (item: any) => string;
} }
const SimplePicker: SFC<Props> = ({ className, getOptionLabel, getOptionValue, onSelected, options }) => { const SimplePicker: SFC<Props> = ({
className,
getOptionLabel,
getOptionValue,
onSelected,
options,
placeholder,
width,
}) => {
return ( return (
<Select <Select
isSearchable={false} isSearchable={false}
classNamePrefix={`gf-form-select-box`} classNamePrefix={`gf-form-select-box`}
className={`width-7 gf-form-input gf-form-input--form-dropdown ${className || ''}`} className={`width-${width} gf-form-input gf-form-input--form-dropdown ${className || ''}`}
placeholder="Choose" placeholder={placeholder || 'Choose'}
options={options} options={options}
onChange={onSelected} onChange={onSelected}
components={{ components={{

View File

@@ -3,88 +3,84 @@ import { hot } from 'react-hot-loader';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import PageHeader from '../../core/components/PageHeader/PageHeader'; import PageHeader from '../../core/components/PageHeader/PageHeader';
import PageLoader from '../../core/components/PageLoader/PageLoader'; import PageLoader from '../../core/components/PageLoader/PageLoader';
import { loadOrganization, loadOrganizationPreferences } from './state/actions';
import { DashboardAcl, NavModel, Organization, OrganisationPreferences, StoreState } from 'app/types';
import { getNavModel } from '../../core/selectors/navModel';
import OrgProfile from './OrgProfile'; import OrgProfile from './OrgProfile';
import OrgPreferences from './OrgPreferences'; import OrgPreferences from './OrgPreferences';
import {
loadOrganization,
loadOrganizationPreferences,
setOrganizationName,
setOrganizationTheme,
setOrganizationHomeDashboard,
setOrganizationTimezone,
} from './state/actions';
import { DashboardAcl, NavModel, Organization, OrganizationPreferences, StoreState } from 'app/types';
import { getNavModel } from '../../core/selectors/navModel';
export interface Props { export interface Props {
navModel: NavModel; navModel: NavModel;
organization: Organization; organization: Organization;
preferences: OrganisationPreferences; preferences: OrganizationPreferences;
starredDashboards: DashboardAcl[]; starredDashboards: DashboardAcl[];
loadOrganization: typeof loadOrganization; loadOrganization: typeof loadOrganization;
loadOrganizationPreferences: typeof loadOrganizationPreferences; loadOrganizationPreferences: typeof loadOrganizationPreferences;
setOrganizationName: typeof setOrganizationName;
setOrganizationHomeDashboard: typeof setOrganizationHomeDashboard;
setOrganizationTheme: typeof setOrganizationTheme;
setOrganizationTimezone: typeof setOrganizationTimezone;
} }
interface State { export class OrgDetailsPage extends PureComponent<Props> {
orgName: string;
theme: string;
isReady: boolean;
selectedDashboard: DashboardAcl;
}
export class OrgDetailsPage extends PureComponent<Props, State> {
state = {
orgName: '',
theme: '',
isReady: false,
selectedDashboard: null,
};
async componentDidMount() { async componentDidMount() {
this.fetchOrganisation(); this.fetchOrganisation();
} }
async fetchOrganisation() { async fetchOrganisation() {
const organization = await this.props.loadOrganization(); await this.props.loadOrganization();
// const preferences = await this.props.loadOrganizationPreferences(); await this.props.loadOrganizationPreferences();
this.setState({
orgName: organization.name,
// theme: preferences.theme,
isReady: true,
});
} }
onOrgNameChange = event => { onOrgNameChange = event => {
this.setState({ this.props.setOrganizationName(event.target.value);
orgName: event.target.value,
});
}; };
onSubmitForm = () => {}; onSubmitForm = () => {};
onSubmitPreferences = () => {}; onSubmitPreferences = () => {};
onDashboardSelected = dashboard => { onThemeChange = theme => {
this.setState({ this.props.setOrganizationTheme(theme);
selectedDashboard: dashboard, };
});
onHomeDashboardChange = dashboardId => {
this.props.setOrganizationHomeDashboard(dashboardId);
};
onTimeZoneChange = timeZone => {
this.props.setOrganizationTimezone(timeZone);
}; };
render() { render() {
const { navModel, preferences, starredDashboards } = this.props; const { navModel, organization, preferences, starredDashboards } = this.props;
return ( return (
<div> <div>
<PageHeader model={navModel} /> <PageHeader model={navModel} />
<div className="page-container page-body"> <div className="page-container page-body">
{!this.state.isReady ? ( {Object.keys(organization).length === 0 || Object.keys(preferences).length === 0 ? (
<PageLoader pageName="Organisation" /> <PageLoader pageName="Organization" />
) : ( ) : (
<div> <div>
<OrgProfile <OrgProfile
onOrgNameChange={name => this.onOrgNameChange(name)} onOrgNameChange={name => this.onOrgNameChange(name)}
onSubmit={this.onSubmitForm} onSubmit={this.onSubmitForm}
orgName={this.state.orgName} orgName={organization.name}
/> />
<OrgPreferences <OrgPreferences
preferences={preferences} preferences={preferences}
starredDashboards={starredDashboards} starredDashboards={starredDashboards}
onDashboardSelected={dashboard => this.onDashboardSelected(dashboard)} onDashboardChange={dashboardId => this.onHomeDashboardChange(dashboardId)}
onTimeZoneChange={() => {}} onThemeChange={theme => this.onThemeChange(theme)}
onTimeZoneChange={timeZone => this.onTimeZoneChange(timeZone)}
onSubmit={this.onSubmitPreferences} onSubmit={this.onSubmitPreferences}
/> />
</div> </div>
@@ -98,15 +94,19 @@ export class OrgDetailsPage extends PureComponent<Props, State> {
function mapStateToProps(state: StoreState) { function mapStateToProps(state: StoreState) {
return { return {
navModel: getNavModel(state.navIndex, 'org-settings'), navModel: getNavModel(state.navIndex, 'org-settings'),
organisation: state.organisation.organisation, organization: state.organization.organization,
preferences: state.organisation.preferences, preferences: state.organization.preferences,
starredDashboards: state.organisation.starredDashboards, starredDashboards: state.organization.starredDashboards,
}; };
} }
const mapDispatchToProps = { const mapDispatchToProps = {
loadOrganization, loadOrganization,
loadOrganizationPreferences, loadOrganizationPreferences,
setOrganizationName,
setOrganizationTheme,
setOrganizationHomeDashboard,
setOrganizationTimezone,
}; };
export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(OrgDetailsPage)); export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(OrgDetailsPage));

View File

@@ -1,22 +1,24 @@
import React, { SFC } from 'react'; import React, { SFC } from 'react';
import Tooltip from '../../core/components/Tooltip/Tooltip'; import Tooltip from '../../core/components/Tooltip/Tooltip';
import { DashboardAcl, OrganisationPreferences } from 'app/types';
import SimplePicker from '../../core/components/Picker/SimplePicker'; import SimplePicker from '../../core/components/Picker/SimplePicker';
import { DashboardAcl, OrganizationPreferences } from 'app/types';
interface Props { interface Props {
preferences: OrganisationPreferences; preferences: OrganizationPreferences;
starredDashboards: DashboardAcl[]; starredDashboards: DashboardAcl[];
onDashboardSelected: (dashboard: DashboardAcl) => void; onDashboardChange: (dashboardId: number) => void;
onTimeZoneChange: (timeZone: string) => void; onTimeZoneChange: (timeZone: string) => void;
onThemeChange: (theme: string) => void;
onSubmit: () => void; onSubmit: () => void;
} }
const OrgPreferences: SFC<Props> = ({ const OrgPreferences: SFC<Props> = ({
preferences, preferences,
starredDashboards, starredDashboards,
onDashboardSelected, onDashboardChange,
onSubmit, onSubmit,
onTimeZoneChange, onTimeZoneChange,
onThemeChange,
}) => { }) => {
const themes = [{ value: '', text: 'Default' }, { value: 'dark', text: 'Dark' }, { value: 'light', text: 'Light' }]; const themes = [{ value: '', text: 'Default' }, { value: 'dark', text: 'Dark' }, { value: 'light', text: 'Light' }];
@@ -35,9 +37,8 @@ const OrgPreferences: SFC<Props> = ({
options={themes} options={themes}
getOptionValue={i => i.value} getOptionValue={i => i.value}
getOptionLabel={i => i.text} getOptionLabel={i => i.text}
onSelected={theme => { onSelected={theme => onThemeChange(theme)}
console.log(theme); width={20}
}}
/> />
</div> </div>
<div className="gf-form"> <div className="gf-form">
@@ -52,23 +53,22 @@ const OrgPreferences: SFC<Props> = ({
</Tooltip> </Tooltip>
</span> </span>
<SimplePicker <SimplePicker
getOptionLabel={i => i.title}
getOptionValue={i => i.id} getOptionValue={i => i.id}
onSelected={dashboard => onDashboardSelected(dashboard)} getOptionLabel={i => i.title}
onSelected={(dashboard: DashboardAcl) => onDashboardChange(dashboard.id)}
options={starredDashboards} options={starredDashboards}
placeholder="Chose default dashboard"
width={20}
/> />
</div> </div>
<div className="gf-form"> <div className="gf-form">
<label className="gf-form-label width-11">Timezone</label> <label className="gf-form-label width-11">Timezone</label>
<SimplePicker <SimplePicker
className="gf-form-input"
onSelected={timezone => {
console.log(timezone);
}}
options={timezones}
getOptionLabel={i => i.text}
getOptionValue={i => i.value} getOptionValue={i => i.value}
getOptionLabel={i => i.text}
onSelected={timezone => onTimeZoneChange(timezone)}
options={timezones}
width={20}
/> />
</div> </div>
<div className="gf-form-button-row"> <div className="gf-form-button-row">

View File

@@ -1,21 +1,27 @@
import { ThunkAction } from 'redux-thunk'; import { ThunkAction } from 'redux-thunk';
import { DashboardAcl, Organization, OrganisationPreferences, StoreState } from 'app/types'; import { DashboardAcl, Organization, OrganizationPreferences, StoreState } from 'app/types';
import { getBackendSrv } from '../../../core/services/backend_srv'; import { getBackendSrv } from '../../../core/services/backend_srv';
type ThunkResult<R> = ThunkAction<R, StoreState, undefined, any>;
export enum ActionTypes { export enum ActionTypes {
LoadOrganisation = 'LOAD_ORGANISATION', LoadOrganization = 'LOAD_ORGANISATION',
LoadPreferences = 'LOAD_PREFERENCES', LoadPreferences = 'LOAD_PREFERENCES',
LoadStarredDashboards = 'LOAD_STARRED_DASHBOARDS', LoadStarredDashboards = 'LOAD_STARRED_DASHBOARDS',
SetOrganizationName = 'SET_ORGANIZATION_NAME',
SetOrganizationTheme = 'SET_ORGANIZATION_THEME',
SetOrganizationHomeDashboard = 'SET_ORGANIZATION_HOME_DASHBOARD',
SetOrganizationTimezone = 'SET_ORGANIZATION_TIMEZONE',
} }
interface LoadOrganizationAction { interface LoadOrganizationAction {
type: ActionTypes.LoadOrganisation; type: ActionTypes.LoadOrganization;
payload: Organization; payload: Organization;
} }
interface LoadPreferencesAction { interface LoadPreferencesAction {
type: ActionTypes.LoadPreferences; type: ActionTypes.LoadPreferences;
payload: OrganisationPreferences; payload: OrganizationPreferences;
} }
interface LoadStarredDashboardsAction { interface LoadStarredDashboardsAction {
@@ -23,12 +29,32 @@ interface LoadStarredDashboardsAction {
payload: DashboardAcl[]; payload: DashboardAcl[];
} }
interface SetOrganizationNameAction {
type: ActionTypes.SetOrganizationName;
payload: string;
}
interface SetOrganizationThemeAction {
type: ActionTypes.SetOrganizationTheme;
payload: string;
}
interface SetOrganizationHomeDashboardAction {
type: ActionTypes.SetOrganizationHomeDashboard;
payload: number;
}
interface SetOrganizationTimezoneAction {
type: ActionTypes.SetOrganizationTimezone;
payload: string;
}
const organisationLoaded = (organisation: Organization) => ({ const organisationLoaded = (organisation: Organization) => ({
type: ActionTypes.LoadOrganisation, type: ActionTypes.LoadOrganization,
payload: organisation, payload: organisation,
}); });
const preferencesLoaded = (preferences: OrganisationPreferences) => ({ const preferencesLoaded = (preferences: OrganizationPreferences) => ({
type: ActionTypes.LoadPreferences, type: ActionTypes.LoadPreferences,
payload: preferences, payload: preferences,
}); });
@@ -38,12 +64,38 @@ const starredDashboardsLoaded = (dashboards: DashboardAcl[]) => ({
payload: dashboards, payload: dashboards,
}); });
export type Action = LoadOrganizationAction | LoadPreferencesAction | LoadStarredDashboardsAction; export const setOrganizationName = (orgName: string) => ({
type ThunkResult<R> = ThunkAction<R, StoreState, undefined, any>; type: ActionTypes.SetOrganizationName,
payload: orgName,
});
export const setOrganizationTheme = (theme: string) => ({
type: ActionTypes.SetOrganizationTheme,
payload: theme,
});
export const setOrganizationHomeDashboard = (id: number) => ({
type: ActionTypes.SetOrganizationHomeDashboard,
payload: id,
});
export const setOrganizationTimezone = (timezone: string) => ({
type: ActionTypes.SetOrganizationTimezone,
payload: timezone,
});
export type Action =
| LoadOrganizationAction
| LoadPreferencesAction
| LoadStarredDashboardsAction
| SetOrganizationNameAction
| SetOrganizationThemeAction
| SetOrganizationHomeDashboardAction
| SetOrganizationTimezoneAction;
export function loadOrganization(): ThunkResult<void> { export function loadOrganization(): ThunkResult<void> {
return async dispatch => { return async dispatch => {
const organisationResponse = await getBackendSrv().get('/api/org'); const organisationResponse = await loadOrg();
dispatch(organisationLoaded(organisationResponse)); dispatch(organisationLoaded(organisationResponse));
return organisationResponse; return organisationResponse;
@@ -52,12 +104,18 @@ export function loadOrganization(): ThunkResult<void> {
export function loadOrganizationPreferences(): ThunkResult<void> { export function loadOrganizationPreferences(): ThunkResult<void> {
return async dispatch => { return async dispatch => {
const preferencesResponse = await getBackendSrv().get('/api/org/preferences'); const preferencesResponse = await loadPreferences();
dispatch(preferencesLoaded(preferencesResponse)); dispatch(preferencesLoaded(preferencesResponse));
const starredDashboards = await getBackendSrv().search({ starred: true }); const starredDashboards = await getBackendSrv().search({ starred: true });
dispatch(starredDashboardsLoaded(starredDashboards)); dispatch(starredDashboardsLoaded(starredDashboards));
return preferencesResponse;
}; };
} }
export async function loadOrg() {
return await await getBackendSrv().get('/api/org');
}
export async function loadPreferences() {
return await getBackendSrv().get('/api/org/preferences');
}

View File

@@ -1,27 +1,39 @@
import { DashboardAcl, Organization, OrganisationPreferences, OrganisationState } from 'app/types'; import { DashboardAcl, Organization, OrganizationPreferences, OrganizationState } from 'app/types';
import { Action, ActionTypes } from './actions'; import { Action, ActionTypes } from './actions';
const initialState: OrganisationState = { const initialState: OrganizationState = {
organisation: {} as Organization, organization: {} as Organization,
preferences: {} as OrganisationPreferences, preferences: {} as OrganizationPreferences,
starredDashboards: [] as DashboardAcl[], starredDashboards: [] as DashboardAcl[],
}; };
const organisationReducer = (state = initialState, action: Action): OrganisationState => { const organizationReducer = (state = initialState, action: Action): OrganizationState => {
switch (action.type) { switch (action.type) {
case ActionTypes.LoadOrganisation: case ActionTypes.LoadOrganization:
return { ...state, organisation: action.payload }; return { ...state, organization: action.payload };
case ActionTypes.LoadPreferences: case ActionTypes.LoadPreferences:
return { ...state, preferences: action.payload }; return { ...state, preferences: action.payload };
case ActionTypes.LoadStarredDashboards: case ActionTypes.LoadStarredDashboards:
return { ...state, starredDashboards: action.payload }; return { ...state, starredDashboards: action.payload };
case ActionTypes.SetOrganizationName:
return { ...state, organization: { ...state.organization, name: action.payload } };
case ActionTypes.SetOrganizationTheme:
return { ...state, preferences: { ...state.preferences, theme: action.payload } };
case ActionTypes.SetOrganizationHomeDashboard:
return { ...state, preferences: { ...state.preferences, homeDashboardId: action.payload } };
case ActionTypes.SetOrganizationTimezone:
return { ...state, preferences: { ...state.preferences, timezone: action.payload } };
} }
return state; return state;
}; };
export default { export default {
organisation: organisationReducer, organization: organizationReducer,
}; };

View File

@@ -10,7 +10,7 @@ import dashboardReducers from 'app/features/dashboard/state/reducers';
import pluginReducers from 'app/features/plugins/state/reducers'; import pluginReducers from 'app/features/plugins/state/reducers';
import dataSourcesReducers from 'app/features/datasources/state/reducers'; import dataSourcesReducers from 'app/features/datasources/state/reducers';
import usersReducers from 'app/features/users/state/reducers'; import usersReducers from 'app/features/users/state/reducers';
import organisationReducers from 'app/features/org/state/reducers'; import organizationReducers from 'app/features/org/state/reducers';
const rootReducers = { const rootReducers = {
...sharedReducers, ...sharedReducers,
@@ -22,7 +22,7 @@ const rootReducers = {
...pluginReducers, ...pluginReducers,
...dataSourcesReducers, ...dataSourcesReducers,
...usersReducers, ...usersReducers,
...organisationReducers, ...organizationReducers,
}; };
export let store; export let store;

View File

@@ -22,7 +22,7 @@ import {
} from './series'; } from './series';
import { PanelProps } from './panel'; import { PanelProps } from './panel';
import { PluginDashboard, PluginMeta, Plugin, PluginsState } from './plugins'; import { PluginDashboard, PluginMeta, Plugin, PluginsState } from './plugins';
import { Organization, OrganisationPreferences, OrganisationState } from './organization'; import { Organization, OrganizationPreferences, OrganizationState } from './organization';
export { export {
Team, Team,
@@ -72,8 +72,8 @@ export {
DataQueryOptions, DataQueryOptions,
PluginDashboard, PluginDashboard,
Organization, Organization,
OrganisationState, OrganizationState,
OrganisationPreferences, OrganizationPreferences,
}; };
export interface StoreState { export interface StoreState {
@@ -86,5 +86,5 @@ export interface StoreState {
dashboard: DashboardState; dashboard: DashboardState;
dataSources: DataSourcesState; dataSources: DataSourcesState;
users: UsersState; users: UsersState;
organisation: OrganisationState; organization: OrganizationState;
} }

View File

@@ -5,14 +5,14 @@ export interface Organization {
id: number; id: number;
} }
export interface OrganisationPreferences { export interface OrganizationPreferences {
homeDashboardId: number; homeDashboardId: number;
theme: string; theme: string;
timezone: string; timezone: string;
} }
export interface OrganisationState { export interface OrganizationState {
organisation: Organization; organization: Organization;
preferences: OrganisationPreferences; preferences: OrganizationPreferences;
starredDashboards: DashboardAcl[]; starredDashboards: DashboardAcl[];
} }