1
0
mirror of https://github.com/flarum/core.git synced 2025-07-25 18:51:40 +02:00

Implement basic settings page

This commit is contained in:
Toby Zerner
2015-07-29 21:00:09 +09:30
parent 9c6b1c0b21
commit 5f1db93e3d
13 changed files with 313 additions and 17 deletions

View File

@@ -0,0 +1,137 @@
import Component from 'flarum/Component';
import FieldSet from 'flarum/components/FieldSet';
import Select from 'flarum/components/Select';
import Button from 'flarum/components/Button';
export default class BasicsPage extends Component {
constructor(...args) {
super(...args);
this.loading = false;
this.fields = [
'forum_title',
'forum_description',
'default_locale',
'default_route',
'welcome_title',
'welcome_message'
];
this.values = {};
const config = app.forum.attribute('config');
this.fields.forEach(key => this.values[key] = m.prop(config[key]));
this.localeOptions = {};
const locales = app.forum.attribute('availableLocales');
for (const i in locales) {
this.localeOptions[i] = `${locales[i]} (${i})`;
}
}
view() {
return (
<div className="BasicsPage">
<div className="container">
<form onsubmit={this.onsubmit.bind(this)}>
{FieldSet.component({
label: 'Forum Title',
children: [
<input className="FormControl" value={this.values.forum_title()} oninput={m.withAttr('value', this.values.forum_title)}/>
]
})}
{FieldSet.component({
label: 'Forum Description',
children: [
<div className="helpText">
Enter a short sentence or two that describes your community. This will appear in the meta tag and show up in search engines.
</div>,
<textarea className="FormControl" value={this.values.forum_description()} oninput={m.withAttr('value', this.values.forum_description)}/>
]
})}
{Object.keys(this.localeOptions).length > 1
? FieldSet.component({
label: 'Default Language',
children: [
Select.component({
options: this.localeOptions,
onchange: this.values.default_locale
})
]
})
: ''}
{FieldSet.component({
label: 'Home Page',
className: 'BasicsPage-homePage',
children: [
<div className="helpText">
Choose the page which users will first see when they visit your forum. If entering a custom value, use the path relative to the forum root.
</div>,
<label className="checkbox">
<input type="radio" name="homePage" value="/all" checked={this.values.default_route() === '/all'} onclick={m.withAttr('value', this.values.default_route)}/>
All Discussions
</label>,
<label className="checkbox">
<input type="radio" name="homePage" value="custom" checked={this.values.default_route() !== '/all'} onclick={() => {
this.values.default_route('');
m.redraw(true);
this.$('.BasicsPage-homePage input').select();
}}/>
Custom <input className="FormControl" value={this.values.default_route()} onchange={m.withAttr('value', this.values.default_route)} style={this.values.default_route() !== '/all' ? 'margin-top: 5px' : 'display:none'}/>
</label>
]
})}
{FieldSet.component({
label: 'Welcome Banner',
className: 'BasicsPage-welcomeBanner',
children: [
<div className="helpText">
Configure the text that displays in the banner on the All Discussions page. Use this to welcome guests to your forum.
</div>,
<div className="BasicsPage-welcomeBanner-input">
<input className="FormControl" value={this.values.welcome_title()} oninput={m.withAttr('value', this.values.welcome_title)}/>
<textarea className="FormControl" value={this.values.welcome_message()} oninput={m.withAttr('value', this.values.welcome_message)}/>
</div>
]
})}
{Button.component({
type: 'submit',
className: 'Button Button--primary',
children: 'Save Changes',
loading: this.loading,
disabled: !this.changed()
})}
</form>
</div>
</div>
);
}
changed() {
const config = app.forum.attribute('config');
return this.fields.some(key => this.values[key]() !== config[key]);
}
onsubmit(e) {
e.preventDefault();
if (this.loading) return;
this.loading = true;
const config = {};
this.fields.forEach(key => config[key] = this.values[key]());
app.forum.save({config}).finally(() => {
this.loading = false;
m.redraw();
});
}
}

View File

@@ -155,7 +155,7 @@ export default class Model {
return app.request({
method: this.exists ? 'PATCH' : 'POST',
url: app.forum.attribute('apiUrl') + '/' + this.data.type + (this.exists ? '/' + this.data.id : ''),
url: app.forum.attribute('apiUrl') + this.apiEndpoint(),
data: {data}
}).then(
// If everything went well, we'll make sure the store knows that this
@@ -187,13 +187,23 @@ export default class Model {
return app.request({
method: 'DELETE',
url: app.forum.attribute('apiUrl') + '/' + this.data.type + '/' + this.data.id,
url: app.forum.attribute('apiUrl') + this.apiEndpoint(),
data
}).then(
() => this.exists = false
);
}
/**
* Construct a path to the API endpoint for this resource.
*
* @return {String}
* @protected
*/
apiEndpoint() {
return '/' + this.data.type + (this.exists ? '/' + this.data.id : '');
}
/**
* Generate a function which returns the value of the given attribute.
*

View File

@@ -1,6 +1,7 @@
import Component from 'flarum/Component';
import icon from 'flarum/helpers/icon';
import extract from 'flarum/utils/extract';
import LoadingIndicator from 'flarum/components/LoadingIndicator';
/**
* The `Button` component defines an element which, when clicked, performs an
@@ -11,6 +12,7 @@ import extract from 'flarum/utils/extract';
* - `disabled` Whether or not the button is disabled. If truthy, the button
* will be given a 'disabled' class name, and any `onclick` handler will be
* removed.
* - `loading` Whether or not the button should be in a disabled loading state.
*
* All other props will be assigned as attributes on the button element.
*
@@ -28,8 +30,9 @@ export default class Button extends Component {
const iconName = extract(attrs, 'icon');
if (iconName) attrs.className += ' hasIcon';
if (attrs.disabled) {
attrs.className += ' disabled';
const loading = extract(attrs, 'loading');
if (attrs.disabled || loading) {
attrs.className += ' disabled' + (loading ? ' loading' : '');
delete attrs.onclick;
}
@@ -47,7 +50,8 @@ export default class Button extends Component {
return [
iconName ? icon(iconName, {className: 'Button-icon'}) : '', ' ',
this.props.children ? <span className="Button-label">{this.props.children}</span> : ''
this.props.children ? <span className="Button-label">{this.props.children}</span> : '',
this.props.loading ? LoadingIndicator.component({size: 'tiny', className: 'LoadingIndicator--inline'}) : ''
];
}
}

View File

@@ -1,3 +1,7 @@
import Model from 'flarum/Model';
export default class Forum extends Model {}
export default class Forum extends Model {
apiEndpoint() {
return '/forum';
}
}