Commit a98f7e54 by Peter Holmberg

simple select

parent 1f8b61f9
import React, { SFC } from 'react';
import Select from 'react-select';
import DescriptionOption from './DescriptionOption';
import ResetStyles from './ResetStyles';
interface Props {
options: any[];
className?: string;
onSelected: (item: any) => {} | void;
getOptionValue: (item: any) => string;
getOptionLabel: (item: any) => string;
}
const SimplePicker: SFC<Props> = ({ className, getOptionLabel, getOptionValue, onSelected, options }) => {
return (
<Select
isSearchable={false}
classNamePrefix={`gf-form-select-box`}
className={`width-7 gf-form-input gf-form-input--form-dropdown ${className || ''}`}
placeholder="Choose"
options={options}
onChange={onSelected}
components={{
Option: DescriptionOption,
}}
styles={ResetStyles}
getOptionValue={getOptionValue}
getOptionLabel={getOptionLabel}
/>
);
};
export default SimplePicker;
import React from 'react';
import React, { PureComponent } from 'react';
import withTooltip from './withTooltip';
import { Target } from 'react-popper';
interface TooltipProps {
interface Props {
tooltipSetState: (prevState: object) => void;
}
class Tooltip extends React.Component<TooltipProps, any> {
constructor(props) {
super(props);
this.showTooltip = this.showTooltip.bind(this);
this.hideTooltip = this.hideTooltip.bind(this);
}
showTooltip() {
class Tooltip extends PureComponent<Props> {
showTooltip = () => {
const { tooltipSetState } = this.props;
tooltipSetState(prevState => {
return {
...prevState,
show: true,
};
});
}
hideTooltip() {
tooltipSetState(prevState => ({
...prevState,
show: true,
}));
};
hideTooltip = () => {
const { tooltipSetState } = this.props;
tooltipSetState(prevState => {
return {
...prevState,
show: false,
};
});
}
tooltipSetState(prevState => ({
...prevState,
show: false,
}));
};
render() {
return (
......
import { Action, ActionTypes } from './actions';
import { OrgRole, PermissionLevel, DashboardState } from 'app/types';
import { inititalState, dashboardReducer } from './reducers';
import { initialState, dashboardReducer } from './reducers';
describe('dashboard reducer', () => {
describe('loadDashboardPermissions', () => {
......@@ -14,7 +14,7 @@ describe('dashboard reducer', () => {
{ id: 3, dashboardId: 1, role: OrgRole.Editor, permission: PermissionLevel.Edit },
],
};
state = dashboardReducer(inititalState, action);
state = dashboardReducer(initialState, action);
});
it('should add permissions to state', async () => {
......
......@@ -2,11 +2,11 @@ import { DashboardState } from 'app/types';
import { Action, ActionTypes } from './actions';
import { processAclItems } from 'app/core/utils/acl';
export const inititalState: DashboardState = {
export const initialState: DashboardState = {
permissions: [],
};
export const dashboardReducer = (state = inititalState, action: Action): DashboardState => {
export const dashboardReducer = (state = initialState, action: Action): DashboardState => {
switch (action.type) {
case ActionTypes.LoadDashboardPermissions:
return {
......
......@@ -2,30 +2,50 @@ import React, { PureComponent } from 'react';
import { hot } from 'react-hot-loader';
import { connect } from 'react-redux';
import PageHeader from '../../core/components/PageHeader/PageHeader';
import { loadOrganisation } from './state/actions';
import { NavModel, Organisation, OrganisationPreferences, StoreState } from 'app/types';
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 OrgPreferences from './OrgPreferences';
export interface Props {
navModel: NavModel;
organisation: Organisation;
organization: Organization;
preferences: OrganisationPreferences;
loadOrganisation: typeof loadOrganisation;
starredDashboards: DashboardAcl[];
loadOrganization: typeof loadOrganization;
loadOrganizationPreferences: typeof loadOrganizationPreferences;
}
interface State {
orgName: string;
hasSet: boolean;
theme: string;
isReady: boolean;
selectedDashboard: DashboardAcl;
}
export class OrgDetailsPage extends PureComponent<Props, State> {
state = {
orgName: '',
hasSet: false,
theme: '',
isReady: false,
selectedDashboard: null,
};
async componentDidMount() {
await this.props.loadOrganisation();
this.fetchOrganisation();
}
async fetchOrganisation() {
const organization = await this.props.loadOrganization();
// const preferences = await this.props.loadOrganizationPreferences();
this.setState({
orgName: organization.name,
// theme: preferences.theme,
isReady: true,
});
}
onOrgNameChange = event => {
......@@ -34,82 +54,41 @@ export class OrgDetailsPage extends PureComponent<Props, State> {
});
};
onSubmitForm = event => {};
onSubmitForm = () => {};
render() {
const { navModel, preferences } = this.props;
onSubmitPreferences = () => {};
const themes: any = [
{ value: '', text: 'Default' },
{ value: 'dark', text: 'Dark' },
{ value: 'light', text: 'Light' },
];
onDashboardSelected = dashboard => {
this.setState({
selectedDashboard: dashboard,
});
};
render() {
const { navModel, preferences, starredDashboards } = this.props;
return (
<div>
<PageHeader model={navModel} />
<div className="page-container page-body">
<h3 className="page-sub-heading">Organisation profile</h3>
<form name="orgForm" className="gf-form-group" onSubmit={this.onSubmitForm}>
<div className="gf-form-inline">
<div className="gf-form max-width-28">
<span className="gf-form-label">Organization name</span>
<input
className="gf-form-input"
type="text"
onChange={this.onOrgNameChange}
value={this.state.orgName}
/>
</div>
</div>
<div className="gf-form-button-row">
<button type="submit" className="btn btn-success">
Save
</button>
</div>
</form>
<form name="ctrl.prefsForm" className="section gf-form-group">
<h3 className="page-heading">Preferences</h3>
<div className="gf-form">
<span className="gf-form-label width-11">UI Theme</span>
<div className="gf-form-select-wrapper max-width-20">
<select className="gf-form-input" value={preferences.theme}>
{themes.map((theme, index) => {
return (
<option key={`${theme.value}-${index}`} value={theme.value}>
{theme.text}
</option>
);
})}
</select>
</div>
</div>
<div className="gf-form">
<span className="gf-form-label width-11">
Home Dashboard
{/*<info-popover mode="right-normal">*/}
{/*Not finding dashboard you want? Star it first, then it should appear in this select box.*/}
{/*</info-popover>*/}
</span>
{/*<dashboard-selector className="gf-form-select-wrapper max-width-20" model="ctrl.prefs.homeDashboardId" />*/}
</div>
<div className="gf-form">
<label className="gf-form-label width-11">Timezone</label>
<div className="gf-form-select-wrapper max-width-20">
<select className="gf-form-input" ng-model="ctrl.prefs.timezone" />
</div>
</div>
<div className="gf-form-button-row">
<button type="submit" className="btn btn-success" ng-click="ctrl.updatePrefs()">
Save
</button>
{!this.state.isReady ? (
<PageLoader pageName="Organisation" />
) : (
<div>
<OrgProfile
onOrgNameChange={name => this.onOrgNameChange(name)}
onSubmit={this.onSubmitForm}
orgName={this.state.orgName}
/>
<OrgPreferences
preferences={preferences}
starredDashboards={starredDashboards}
onDashboardSelected={dashboard => this.onDashboardSelected(dashboard)}
onTimeZoneChange={() => {}}
onSubmit={this.onSubmitPreferences}
/>
</div>
</form>
)}
</div>
</div>
);
......@@ -121,11 +100,13 @@ function mapStateToProps(state: StoreState) {
navModel: getNavModel(state.navIndex, 'org-settings'),
organisation: state.organisation.organisation,
preferences: state.organisation.preferences,
starredDashboards: state.organisation.starredDashboards,
};
}
const mapDispatchToProps = {
loadOrganisation,
loadOrganization,
loadOrganizationPreferences,
};
export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(OrgDetailsPage));
import React, { SFC } from 'react';
import Tooltip from '../../core/components/Tooltip/Tooltip';
import { DashboardAcl, OrganisationPreferences } from 'app/types';
import SimplePicker from '../../core/components/Picker/SimplePicker';
interface Props {
preferences: OrganisationPreferences;
starredDashboards: DashboardAcl[];
onDashboardSelected: (dashboard: DashboardAcl) => void;
onTimeZoneChange: (timeZone: string) => void;
onSubmit: () => void;
}
const OrgPreferences: SFC<Props> = ({
preferences,
starredDashboards,
onDashboardSelected,
onSubmit,
onTimeZoneChange,
}) => {
const themes = [{ value: '', text: 'Default' }, { value: 'dark', text: 'Dark' }, { value: 'light', text: 'Light' }];
const timezones = [
{ value: '', text: 'Default' },
{ value: 'browser', text: 'Local browser time' },
{ value: 'utc', text: 'UTC' },
];
return (
<form className="section gf-form-group" onSubmit={onSubmit}>
<h3 className="page-heading">Preferences</h3>
<div className="gf-form">
<span className="gf-form-label width-11">UI Theme</span>
<SimplePicker
options={themes}
getOptionValue={i => i.value}
getOptionLabel={i => i.text}
onSelected={theme => {
console.log(theme);
}}
/>
</div>
<div className="gf-form">
<span className="gf-form-label width-11">
Home Dashboard
<Tooltip
className="gf-form-help-icon gf-form-help-icon--right-normal"
placement="right"
content="Not finding dashboard you want? Star it first, then it should appear in this select box."
>
<i className="fa fa-info-circle" />
</Tooltip>
</span>
<SimplePicker
getOptionLabel={i => i.title}
getOptionValue={i => i.id}
onSelected={dashboard => onDashboardSelected(dashboard)}
options={starredDashboards}
/>
</div>
<div className="gf-form">
<label className="gf-form-label width-11">Timezone</label>
<SimplePicker
className="gf-form-input"
onSelected={timezone => {
console.log(timezone);
}}
options={timezones}
getOptionLabel={i => i.text}
getOptionValue={i => i.value}
/>
</div>
<div className="gf-form-button-row">
<button type="submit" className="btn btn-success">
Save
</button>
</div>
</form>
);
};
export default OrgPreferences;
import React, { SFC } from 'react';
interface Props {
orgName: string;
onSubmit: () => void;
onOrgNameChange: (orgName: string) => void;
}
const OrgProfile: SFC<Props> = ({ onSubmit, onOrgNameChange, orgName }) => {
return (
<div>
<h3 className="page-sub-heading">Organization profile</h3>
<form name="orgForm" className="gf-form-group" onSubmit={onSubmit}>
<div className="gf-form-inline">
<div className="gf-form max-width-28">
<span className="gf-form-label">Organization name</span>
<input
className="gf-form-input"
type="text"
onChange={event => {
onOrgNameChange(event.target.value);
}}
value={orgName}
/>
</div>
</div>
<div className="gf-form-button-row">
<button type="submit" className="btn btn-success">
Save
</button>
</div>
</form>
</div>
);
};
export default OrgProfile;
import { ThunkAction } from 'redux-thunk';
import { Organisation, OrganisationPreferences, StoreState } from 'app/types';
import { DashboardAcl, Organization, OrganisationPreferences, StoreState } from 'app/types';
import { getBackendSrv } from '../../../core/services/backend_srv';
export enum ActionTypes {
LoadOrganisation = 'LOAD_ORGANISATION',
LoadPreferences = 'LOAD_PREFERENCES',
LoadStarredDashboards = 'LOAD_STARRED_DASHBOARDS',
}
interface LoadOrganisationAction {
interface LoadOrganizationAction {
type: ActionTypes.LoadOrganisation;
payload: Organisation;
payload: Organization;
}
interface LoadPreferencesAction {
......@@ -17,7 +18,12 @@ interface LoadPreferencesAction {
payload: OrganisationPreferences;
}
const organisationLoaded = (organisation: Organisation) => ({
interface LoadStarredDashboardsAction {
type: ActionTypes.LoadStarredDashboards;
payload: DashboardAcl[];
}
const organisationLoaded = (organisation: Organization) => ({
type: ActionTypes.LoadOrganisation,
payload: organisation,
});
......@@ -27,14 +33,31 @@ const preferencesLoaded = (preferences: OrganisationPreferences) => ({
payload: preferences,
});
export type Action = LoadOrganisationAction | LoadPreferencesAction;
const starredDashboardsLoaded = (dashboards: DashboardAcl[]) => ({
type: ActionTypes.LoadStarredDashboards,
payload: dashboards,
});
export type Action = LoadOrganizationAction | LoadPreferencesAction | LoadStarredDashboardsAction;
type ThunkResult<R> = ThunkAction<R, StoreState, undefined, any>;
export function loadOrganisation(): ThunkResult<void> {
export function loadOrganization(): ThunkResult<void> {
return async dispatch => {
const organisationResponse = await getBackendSrv().get('/api/org');
const preferencesResponse = await getBackendSrv().get('/api/org/preferences');
dispatch(organisationLoaded(organisationResponse));
return organisationResponse;
};
}
export function loadOrganizationPreferences(): ThunkResult<void> {
return async dispatch => {
const preferencesResponse = await getBackendSrv().get('/api/org/preferences');
dispatch(preferencesLoaded(preferencesResponse));
const starredDashboards = await getBackendSrv().search({ starred: true });
dispatch(starredDashboardsLoaded(starredDashboards));
return preferencesResponse;
};
}
import { Organisation, OrganisationPreferences, OrganisationState } from 'app/types';
import { DashboardAcl, Organization, OrganisationPreferences, OrganisationState } from 'app/types';
import { Action, ActionTypes } from './actions';
const initialState: OrganisationState = {
organisation: {} as Organisation,
organisation: {} as Organization,
preferences: {} as OrganisationPreferences,
starredDashboards: [] as DashboardAcl[],
};
const organisationReducer = (state = initialState, action: Action): OrganisationState => {
......@@ -13,6 +14,9 @@ const organisationReducer = (state = initialState, action: Action): Organisation
case ActionTypes.LoadPreferences:
return { ...state, preferences: action.payload };
case ActionTypes.LoadStarredDashboards:
return { ...state, starredDashboards: action.payload };
}
return state;
......
......@@ -22,7 +22,7 @@ import {
} from './series';
import { PanelProps } from './panel';
import { PluginDashboard, PluginMeta, Plugin, PluginsState } from './plugins';
import { Organisation, OrganisationPreferences, OrganisationState } from './organisation';
import { Organization, OrganisationPreferences, OrganisationState } from './organization';
export {
Team,
......@@ -71,7 +71,7 @@ export {
DataQueryResponse,
DataQueryOptions,
PluginDashboard,
Organisation,
Organization,
OrganisationState,
OrganisationPreferences,
};
......
export interface Organisation {
import { DashboardAcl } from './acl';
export interface Organization {
name: string;
id: number;
}
......@@ -10,6 +12,7 @@ export interface OrganisationPreferences {
}
export interface OrganisationState {
organisation: Organisation;
organisation: Organization;
preferences: OrganisationPreferences;
starredDashboards: DashboardAcl[];
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment