Skip to content
Snippets Groups Projects
Commit a8299435 authored by Tom Robinson's avatar Tom Robinson
Browse files

New settings page

parent abcb1360
No related branches found
No related tags found
No related merge requests found
......@@ -7,7 +7,7 @@ import PopoverWithTrigger from '../../../query_builder/popover_with_trigger.reac
export default React.createClass({
displayName: "Select",
propTypes: {
value: React.PropTypes.object,
value: React.PropTypes.any,
options: React.PropTypes.array.isRequired,
placeholder: React.PropTypes.string,
onChange: React.PropTypes.func,
......
'use strict';
/*global _*/
import SettingsHeader from "./SettingsHeader.react";
import SettingsSetting from "./SettingsSetting.react";
import cx from 'classnames';
export default React.createClass({
displayName: "SettingsEditor",
propTypes: {
sections: React.PropTypes.object.isRequired,
updateSetting: React.PropTypes.func.isRequired
},
getInitialState: function() {
return {
currentSection: Object.keys(this.props.sections)[0]
};
},
selectSection: function(section) {
this.setState({ currentSection: section });
},
updateSetting: function(setting, value) {
this.refs.header.refs.status.setSaving();
setting.value = value;
this.props.updateSetting(setting).then(() => {
this.refs.header.refs.status.setSaved();
}, (error) => {
this.refs.header.refs.status.setSaveError(error.data);
});
},
handleChangeEvent: function(setting, event) {
this.updateSetting(setting, event.target.value);
},
renderSettingsPane: function() {
var section = this.props.sections[this.state.currentSection];
var settings = section.map((setting) => {
return <SettingsSetting key={setting.key} setting={setting} updateSetting={this.updateSetting} handleChangeEvent={this.handleChangeEvent} />
});
return (
<div className="MetadataTable px2 flex-full">
<ul>{settings}</ul>
</div>
);
},
renderSettingsSections: function() {
var sections = _.map(this.props.sections, (section, sectionName, sectionIndex) => {
var classes = cx("AdminList-item", {
"selected": this.state.currentSection === sectionName,
"flex": true,
"align-center": true
});
return (
<li key={sectionName} className={classes} onClick={this.selectSection.bind(null, sectionName)}>
{sectionName}
</li>
);
});
return (
<div className="MetadataEditor-table-list AdminList">
<ul className="AdminList-items pt1">
{sections}
</ul>
</div>
);
},
render: function() {
return (
<div className="MetadataEditor flex flex-column flex-full p4">
<SettingsHeader ref="header" />
<div className="MetadataEditor-main flex flex-row flex-full mt2">
{this.renderSettingsSections()}
{this.renderSettingsPane()}
</div>
</div>
);
}
});
"use strict";
import SaveStatus from "../../metadata/components/SaveStatus.react";
export default React.createClass({
displayName: "SettingsHeader",
render: function() {
return (
<div className="MetadataEditor-header flex align-center">
<div className="MetadataEditor-header-section h2">
<span className="text-grey-4">Settings</span>
</div>
<div className="MetadataEditor-header-section flex-align-right flex align-center">
<SaveStatus ref="status" />
</div>
</div>
);
},
})
"use strict";
/*global _*/
import Input from "../../metadata/components/Input.react";
import Select from "../../metadata/components/Select.react";
import cx from 'classnames';
export default React.createClass({
displayName: "SettingsSetting",
propTypes: {
setting: React.PropTypes.object.isRequired,
updateSetting: React.PropTypes.func.isRequired,
handleChangeEvent: React.PropTypes.func.isRequired
},
renderStringInput: function(setting, type="text") {
return (
<Input
className="AdminInput bordered rounded h3 full"
type={type}
value={setting.value}
placeholder={setting.placeholder}
onBlurChange={this.props.handleChangeEvent.bind(null, setting)}
/>
);
},
renderRadioInput: function(setting) {
var options = _.map(setting.options, (name, value) => {
var classes = cx("h3", "text-bold", "text-brand-hover", "no-decoration", { "text-brand": setting.value === value });
return (
<li className="mr3" key={value}>
<a className={classes} href="#" onClick={this.props.updateSetting.bind(null, setting, value)}>{name}</a>
</li>
);
});
return <ul className="flex text-grey-4">{options}</ul>
},
renderSelectInput: function(setting) {
return (
<Select
className=""
placeholder={setting.placeholder}
value={setting.value}
options={setting.options}
onChange={this.props.updateSetting.bind(null, setting)}
optionNameFn={option => option}
optionValueFn={option => option}
/>
);
},
render: function() {
var setting = this.props.setting;
var control;
switch (setting.type) {
case "string": control = this.renderStringInput(setting); break;
case "password": control = this.renderStringInput(setting, "password"); break;
case "select": control = this.renderSelectInput(setting); break;
case "radio": control = this.renderRadioInput(setting); break;
default:
console.warn("No render method for setting type " + setting.type + ", defaulting to string input.");
control = this.renderStringInput(setting);
}
return (
<li className="m2 mb4">
<div className="text-grey-3 text-bold text-uppercase">{setting.display_name}</div>
<div className="text-grey-3 my1">{setting.description}</div>
<div>{control}</div>
</li>
);
}
});
'use strict';
/*global _*/
import SettingsEditor from './components/SettingsEditor.react';
import Humanize from "humanize";
var SettingsAdminControllers = angular.module('corvusadmin.settings.controllers', ['corvusadmin.settings.services']);
// from common.clj
var TIMEZONES = [
"GMT",
"UTC",
"US/Alaska",
"US/Arizona",
"US/Central",
"US/Eastern",
"US/Hawaii",
"US/Mountain",
"US/Pacific",
"America/Costa_Rica",
];
// temporary hardcoded metadata
var EXTRA_SETTINGS_METADATA = {
"site-name": { display_name: "Site Name", section: "General", type: "string" },
"-site-url": { display_name: "Site URL", section: "General", type: "string" },
"report-timezone": { display_name: "Report Timezone", section: "General", type: "select", options: TIMEZONES, placeholder: "Select a timezone" },
"email-from-address": { display_name: "From Address", section: "Email", type: "string" },
"email-smtp-host": { display_name: "SMTP Host", section: "Email", type: "string" },
"email-smtp-port": { display_name: "SMTP Port", section: "Email", type: "string" },
"email-smtp-security": { display_name: "SMTP Security", section: "Email", type: "radio", options: { none: "None", tls: "TLS", ssl: "SSL" } },
"email-smtp-username": { display_name: "SMTP Username", section: "Email", type: "string" },
"email-smtp-password": { display_name: "SMTP Password", section: "Email", type: "password" },
};
SettingsAdminControllers.controller('SettingsEditor', ['$scope', 'SettingsAdminServices', 'settings', function($scope, SettingsAdminServices, settings) {
$scope.SettingsEditor = SettingsEditor;
$scope.updateSetting = async function(setting) {
await SettingsAdminServices.put({ key: setting.key }, setting).$promise;
}
$scope.sections = {};
settings.forEach(function(setting) {
var defaults = { display_name: keyToDisplayName(setting.key), placeholder: setting.default };
setting = _.extend(defaults, EXTRA_SETTINGS_METADATA[setting.key], setting);
var sectionName = setting.section || "Other";
$scope.sections[sectionName] = $scope.sections[sectionName] || [];
$scope.sections[sectionName].push(setting);
});
function keyToDisplayName(key) {
return Humanize.capitalizeAll(key.replace(/-/g, " ")).trim();
}
}]);
SettingsAdminControllers.controller('SettingsAdminController', ['$scope', '$q', 'SettingsAdminServices',
function($scope, $q, SettingsAdminServices) {
$scope.settings = [];
......
......@@ -7,7 +7,16 @@ var SettingsAdmin = angular.module('corvusadmin.settings', [
SettingsAdmin.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/admin/settings/', {
templateUrl: '/app/admin/settings/partials/settings.html',
controller: 'SettingsAdminController'
template: '<div class="flex flex-column flex-full" mb-react-component="SettingsEditor"></div>',
controller: 'SettingsEditor',
resolve: {
settings: ['SettingsAdminServices', async function(SettingsAdminServices) {
var settings = await SettingsAdminServices.list().$promise
return settings.map(function(setting) {
setting.originalValue = setting.value;
return setting;
});
}]
}
});
}]);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment