add settings edit form

This commit is contained in:
Sacha Greif 2016-04-15 11:11:13 +09:00
parent 5679ecf7e8
commit 3fd1a2412e
10 changed files with 203 additions and 37 deletions

View file

@ -154,7 +154,7 @@ underscore@1.0.7
url@1.0.8
utilities:avatar@0.9.2
utilities:react-list-container@0.1.8
utilities:smart-methods@0.1.3
utilities:smart-methods@0.1.4
utilities:smart-publications@0.1.4
webapp@1.2.7
webapp-hashing@1.0.8

3
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,3 @@
Before starting on a new feature, please [check out the roadmap](https://trello.com/b/dwPR0LTz/nova-roadmap) and come check-in in the [Telescope Slack channel](http://slack.telescopeapp.org/).
Also, all PRs should be made to the `devel` branch, not `master`.

View file

@ -0,0 +1,43 @@
import React, { PropTypes, Component } from 'react';
import NovaForm from "meteor/nova:forms";
import SmartContainers from "meteor/utilities:react-list-container";
const DocumentContainer = SmartContainers.DocumentContainer;
import Core from "meteor/nova:core";
const Messages = Core.Messages;
class SettingsEditForm extends Component{
render() {
return (
<div className="edit-post-form">
<DocumentContainer
collection={Telescope.settings.collection}
publication="settings.admin"
selector={{}}
terms={{}}
component={NovaForm}
componentProps={{
// note: the document prop will be passed from DocumentContainer
collection: Telescope.settings.collection,
currentUser: this.context.currentUser,
methodName: "settings.edit",
successCallback: (category)=>{
Messages.flash("Settings edited (please reload).", "success");
},
labelFunction: fieldName => Telescope.utils.getFieldLabel(fieldName, Telescope.settings.collection)
}}
/>
</div>
)
}
}
SettingsEditForm.contextTypes = {
currentUser: React.PropTypes.object
};
module.exports = SettingsEditForm;
export default SettingsEditForm;

View file

@ -15,6 +15,7 @@ Telescope.registerComponent("AppLoading", require('./common/AppLoading
Telescope.registerComponent("Error404", require('./common/Error404.jsx'));
Telescope.registerComponent("Loading", require('./common/Loading.jsx'));
Telescope.registerComponent("Vote", require('./common/Vote.jsx'));
Telescope.registerComponent("SettingsEditForm", require('./common/SettingsEditForm.jsx'));
// posts

View file

@ -2,25 +2,74 @@ import React, { PropTypes, Component } from 'react';
import { Meteor } from 'meteor/meteor';
import { Accounts } from 'meteor/std:accounts-ui';
import Router from '../router.js';
import { Dropdown, MenuItem } from 'react-bootstrap';
import { Modal, Dropdown, MenuItem } from 'react-bootstrap';
import Core from "meteor/nova:core";
const ContextPasser = Core.ContextPasser;
const UserMenu = ({user}) => {
class UserMenu extends Component {
({UserAvatar, UserName} = Telescope.components);
constructor() {
super();
this.openModal = this.openModal.bind(this);
this.closeModal = this.closeModal.bind(this);
this.state = {modalOpen: false};
}
return (
<Dropdown id="user-dropdown" className="user-menu-dropdown">
<Dropdown.Toggle>
<UserAvatar size="small" user={user} link={false} />
<div>{Users.getDisplayName(user)}</div>
</Dropdown.Toggle>
<Dropdown.Menu>
<MenuItem className="dropdown-item" eventKey="1" href={Router.path("users.single", {slug: user.telescope.slug})}>Profile</MenuItem>
<MenuItem className="dropdown-item" eventKey="2" href={Router.path("account")}>Edit Account</MenuItem>
<MenuItem className="dropdown-item" eventKey="3" onClick={() => Meteor.logout(Accounts.ui._options.onSignedOutHook())}>Log Out</MenuItem>
</Dropdown.Menu>
</Dropdown>
)
openModal() {
this.setState({modalOpen: true});
}
closeModal() {
this.setState({modalOpen: false});
}
renderSettingsModal() {
const SettingsEditForm = Telescope.components.SettingsEditForm;
return (
<Modal show={this.state.modalOpen} onHide={this.closeModal}>
<Modal.Header closeButton>
<Modal.Title>Edit Settings</Modal.Title>
</Modal.Header>
<Modal.Body>
<ContextPasser currentUser={this.props.user} closeCallback={this.closeModal}>
<SettingsEditForm/>
</ContextPasser>
</Modal.Body>
</Modal>
)
}
render() {
({UserAvatar, UserName} = Telescope.components);
const user = this.props.user;
return (
<div>
<Dropdown id="user-dropdown" className="user-menu-dropdown">
<Dropdown.Toggle>
<UserAvatar size="small" user={user} link={false} />
<div>{Users.getDisplayName(user)}</div>
</Dropdown.Toggle>
<Dropdown.Menu>
<MenuItem className="dropdown-item" eventKey="1" href={Router.path("users.single", {slug: user.telescope.slug})}>Profile</MenuItem>
<MenuItem className="dropdown-item" eventKey="2" href={Router.path("account")}>Edit Account</MenuItem>
{Users.is.admin(user) ? <MenuItem className="dropdown-item" eventKey="3" onClick={this.openModal}>Settings</MenuItem> : null}
<MenuItem className="dropdown-item" eventKey="4" onClick={() => Meteor.logout(Accounts.ui._options.onSignedOutHook())}>Log Out</MenuItem>
</Dropdown.Menu>
</Dropdown>
{this.renderSettingsModal()}
</div>
)
}
}
UserMenu.propTypes = {
user: React.PropTypes.object
}
module.exports = UserMenu;

View file

@ -8,6 +8,8 @@ Telescope.settings.schema = new SimpleSchema({
title: {
type: String,
optional: true,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: "01_general"
}
@ -16,6 +18,8 @@ Telescope.settings.schema = new SimpleSchema({
type: String,
optional: true,
// regEx: SimpleSchema.RegEx.Url,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: "01_general",
type: "bootstrap-url",
@ -25,6 +29,8 @@ Telescope.settings.schema = new SimpleSchema({
tagline: {
type: String,
optional: true,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: "01_general"
}
@ -32,6 +38,8 @@ Telescope.settings.schema = new SimpleSchema({
description: {
type: String,
optional: true,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: "01_general",
rows: 5,
@ -41,6 +49,8 @@ Telescope.settings.schema = new SimpleSchema({
siteImage: {
type: String,
optional: true,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
regEx: SimpleSchema.RegEx.Url,
autoform: {
group: "01_general",
@ -50,6 +60,8 @@ Telescope.settings.schema = new SimpleSchema({
requireViewInvite: {
type: Boolean,
optional: true,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: 'invites',
leftLabel: 'Require View Invite'
@ -58,6 +70,8 @@ Telescope.settings.schema = new SimpleSchema({
requirePostInvite: {
type: Boolean,
optional: true,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: 'invites',
leftLabel: 'Require Post Invite'
@ -66,6 +80,8 @@ Telescope.settings.schema = new SimpleSchema({
requirePostsApproval: {
type: Boolean,
optional: true,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: "01_general",
instructions: "Posts must be approved by admin",
@ -76,6 +92,8 @@ Telescope.settings.schema = new SimpleSchema({
type: String,
optional: true,
private: true,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: "06_email",
instructions: 'The address all outgoing emails will be sent from.',
@ -86,6 +104,8 @@ Telescope.settings.schema = new SimpleSchema({
type: String,
optional: true,
private: true,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: "06_email",
instructions: 'MAIL_URL environment variable (requires restart).',
@ -97,6 +117,8 @@ Telescope.settings.schema = new SimpleSchema({
optional: true,
defaultValue: 30,
private: true,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: '01_general',
instructions: 'How often to recalculate scores, in seconds (default to 30)',
@ -107,6 +129,8 @@ Telescope.settings.schema = new SimpleSchema({
type: Number,
optional: true,
defaultValue: 30,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: "02_posts",
instructions: 'Minimum time between posts, in seconds (defaults to 30)'
@ -115,6 +139,8 @@ Telescope.settings.schema = new SimpleSchema({
RSSLinksPointTo: {
type: String,
optional: true,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: "02_posts",
options: [
@ -127,6 +153,8 @@ Telescope.settings.schema = new SimpleSchema({
type: Number,
optional: true,
defaultValue: 15,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: "03_comments",
instructions: 'Minimum time between comments, in seconds (defaults to 15)'
@ -136,6 +164,8 @@ Telescope.settings.schema = new SimpleSchema({
type: Number,
optional: true,
defaultValue: 30,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: "02_posts",
instructions: 'Maximum number of posts a user can post in a day (default to 30).'
@ -145,6 +175,8 @@ Telescope.settings.schema = new SimpleSchema({
type: Number,
defaultValue: 3,
optional: true,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: 'invites'
}
@ -153,6 +185,8 @@ Telescope.settings.schema = new SimpleSchema({
type: Number,
defaultValue: 10,
optional: true,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: "02_posts"
}
@ -160,6 +194,8 @@ Telescope.settings.schema = new SimpleSchema({
logoUrl: {
type: String,
optional: true,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: "04_logo"
}
@ -167,6 +203,8 @@ Telescope.settings.schema = new SimpleSchema({
logoHeight: {
type: Number,
optional: true,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: "04_logo"
}
@ -174,6 +212,8 @@ Telescope.settings.schema = new SimpleSchema({
logoWidth: {
type: Number,
optional: true,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: "04_logo"
}
@ -181,31 +221,37 @@ Telescope.settings.schema = new SimpleSchema({
faviconUrl: {
type: String,
optional: true,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: "04_logo"
}
},
language: {
type: String,
defaultValue: 'en',
optional: true,
autoform: {
group: "01_general",
instructions: 'The app\'s language. Defaults to English.',
options: function () {
var languages = _.map(TAPi18n.getLanguages(), function (item, key) {
return {
value: key,
label: item.name
};
});
return languages;
}
}
},
// language: {
// type: String,
// defaultValue: 'en',
// optional: true,
// insertableIf: Users.is.admin,
// editableIf: Users.is.admin,
// autoform: {
// group: "01_general",
// instructions: 'The app\'s language. Defaults to English.',
// options: function () {
// var languages = _.map(TAPi18n.getLanguages(), function (item, key) {
// return {
// value: key,
// label: item.name
// };
// });
// return languages;
// }
// }
// },
twitterAccount: {
type: String,
optional: true,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: "07_integrations"
}
@ -213,6 +259,8 @@ Telescope.settings.schema = new SimpleSchema({
facebookPage: {
type: String,
optional: true,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: "07_integrations"
}
@ -220,6 +268,8 @@ Telescope.settings.schema = new SimpleSchema({
googleAnalyticsId: {
type: String,
optional: true,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
autoform: {
group: "07_integrations"
}
@ -227,6 +277,8 @@ Telescope.settings.schema = new SimpleSchema({
emailFooter: {
type: String,
optional: true,
insertableIf: Users.is.admin,
editableIf: Users.is.admin,
private: true,
autoform: {
group: "06_email",

View file

@ -0,0 +1,5 @@
Meteor.startup(function () {
if (Telescope.settings.collection.find().count() === 0) {
Telescope.settings.collection.insert({});
}
});

View file

@ -0,0 +1,3 @@
Telescope.settings.collection.smartMethods({
editName: "settings.edit"
});

View file

@ -14,3 +14,11 @@ Meteor.publish('settings', function() {
return Telescope.settings.collection.find({}, options);
});
Meteor.publish('settings.admin', function() {
if (Users.is.adminById(this.userId)) {
return Telescope.settings.collection.find({}, {});
} else {
return [];
}
});

View file

@ -6,19 +6,21 @@ Package.describe({
});
Package.onUse(function(api) {
var both = ['server', 'client'];
api.versionsFrom(['METEOR@1.0']);
api.use([
'nova:lib@0.26.0-nova',
'nova:users@0.26.0-nova'
// 'nova:i18n@0.26.0-nova'
]);
api.addFiles([
'lib/collection.js',
'lib/init.js',
'lib/methods.js',
// 'package-tap.i18n'
], both);
], ['server', 'client']);
api.addFiles([
'lib/server/publications.js',