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:
137
framework/core/js/admin/src/components/BasicsPage.js
Normal file
137
framework/core/js/admin/src/components/BasicsPage.js
Normal 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();
|
||||
});
|
||||
}
|
||||
}
|
@@ -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.
|
||||
*
|
||||
|
@@ -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'}) : ''
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -1,3 +1,7 @@
|
||||
import Model from 'flarum/Model';
|
||||
|
||||
export default class Forum extends Model {}
|
||||
export default class Forum extends Model {
|
||||
apiEndpoint() {
|
||||
return '/forum';
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user