Massive JavaScript cleanup

- Use JSX for templates
- Docblock/comment everything
- Mostly passes ESLint (still some work to do)
- Lots of renaming, refactoring, etc.

CSS hasn't been updated yet.
This commit is contained in:
Toby Zerner
2015-07-15 14:00:11 +09:30
parent 4480e0a83f
commit ab6c03c0cc
220 changed files with 9785 additions and 5919 deletions

View File

@ -1,12 +1,11 @@
import Model from 'flarum/model';
import Model from 'flarum/Model';
import mixin from 'flarum/utils/mixin';
class Activity extends Model {}
export default class Activity extends mixin(Model, {
contentType: Model.attribute('contentType'),
content: Model.attribute('content'),
time: Model.attribute('time', Model.transformDate),
Activity.prototype.contentType = Model.attribute('contentType');
Activity.prototype.content = Model.attribute('content');
Activity.prototype.time = Model.attribute('time', Model.transformDate);
Activity.prototype.user = Model.hasOne('user');
Activity.prototype.subject = Model.hasOne('subject');
export default Activity;
user: Model.hasOne('user'),
subject: Model.hasOne('subject')
}) {}

View File

@ -1,16 +1,43 @@
import Model from 'flarum/model';
import Model from 'flarum/Model';
import mixin from 'flarum/utils/mixin';
import computed from 'flarum/utils/computed';
import ItemList from 'flarum/utils/item-list';
import ItemList from 'flarum/utils/ItemList';
import { slug } from 'flarum/utils/string';
class Discussion extends Model {
export default class Discussion extends mixin(Model, {
title: Model.attribute('title'),
slug: computed('title', slug),
startTime: Model.attribute('startTime', Model.transformDate),
startUser: Model.hasOne('startUser'),
startPost: Model.hasOne('startPost'),
lastTime: Model.attribute('lastTime', Model.transformDate),
lastUser: Model.hasOne('lastUser'),
lastPost: Model.hasOne('lastPost'),
lastPostNumber: Model.attribute('lastPostNumber'),
commentsCount: Model.attribute('commentsCount'),
repliesCount: computed('commentsCount', commentsCount => Math.max(0, commentsCount - 1)),
posts: Model.hasMany('posts'),
relevantPosts: Model.hasMany('relevantPosts'),
readTime: Model.attribute('readTime', Model.transformDate),
readNumber: Model.attribute('readNumber'),
isUnread: computed('unreadCount', unreadCount => !!unreadCount),
canReply: Model.attribute('canReply'),
canRename: Model.attribute('canRename'),
canDelete: Model.attribute('canDelete')
}) {
/**
* Remove a post from the discussion's posts relationship.
*
* @param {int} id The ID of the post to remove.
* @return {void}
* @param {Integer} id The ID of the post to remove.
* @public
*/
removePost(id) {
const relationships = this.data().relationships;
const relationships = this.data.relationships;
const posts = relationships && relationships.posts;
if (posts) {
@ -23,47 +50,40 @@ class Discussion extends Model {
}
}
/**
* Get the estimated number of unread posts in this discussion for the current
* user.
*
* @return {Integer}
* @public
*/
unreadCount() {
var user = app.session.user();
const user = app.session.user;
if (user && user.readTime() < this.lastTime()) {
return Math.max(0, this.lastPostNumber() - (this.readNumber() || 0))
}
return 0;
}
/**
* Get the Badge components that apply to this discussion.
*
* @return {ItemList}
* @public
*/
badges() {
return new ItemList();
}
/**
* Get a list of all of the post IDs in this discussion.
*
* @return {Array}
* @public
*/
postIds() {
return this.data.relationships.posts.data.map(link => link.id);
}
}
Discussion.prototype.title = Model.attribute('title');
Discussion.prototype.slug = computed('title', title => title.toLowerCase().replace(/[^a-z0-9]/gi, '-').replace(/-+/g, '-').replace(/-$|^-/g, '') || '-');
Discussion.prototype.startTime = Model.attribute('startTime', Model.transformDate);
Discussion.prototype.startUser = Model.hasOne('startUser');
Discussion.prototype.startPost = Model.hasOne('startPost');
Discussion.prototype.lastTime = Model.attribute('lastTime', Model.transformDate);
Discussion.prototype.lastUser = Model.hasOne('lastUser');
Discussion.prototype.lastPost = Model.hasOne('lastPost');
Discussion.prototype.lastPostNumber = Model.attribute('lastPostNumber');
Discussion.prototype.canReply = Model.attribute('canReply');
Discussion.prototype.canRename = Model.attribute('canRename');
Discussion.prototype.canDelete = Model.attribute('canDelete');
Discussion.prototype.commentsCount = Model.attribute('commentsCount');
Discussion.prototype.repliesCount = computed('commentsCount', commentsCount => Math.max(0, commentsCount - 1));
Discussion.prototype.posts = Model.hasMany('posts');
Discussion.prototype.postIds = function() { return this.data().relationships.posts.data.map((link) => link.id); };
Discussion.prototype.relevantPosts = Model.hasMany('relevantPosts');
Discussion.prototype.addedPosts = Model.hasMany('addedPosts');
Discussion.prototype.removedPosts = Model.attribute('removedPosts');
Discussion.prototype.readTime = Model.attribute('readTime', Model.transformDate);
Discussion.prototype.readNumber = Model.attribute('readNumber');
Discussion.prototype.isUnread = computed('unreadCount', unreadCount => !!unreadCount);
export default Discussion;

View File

@ -1,5 +1,3 @@
import Model from 'flarum/model';
import Model from 'flarum/Model';
class Forum extends Model {}
export default Forum;
export default class Forum extends Model {}

View File

@ -1,11 +1,12 @@
import Model from 'flarum/model';
import Model from 'flarum/Model';
import mixin from 'flarum/utils/mixin';
class Group extends Model {}
Group.prototype.nameSingular = Model.attribute('nameSingular');
Group.prototype.namePlural = Model.attribute('namePlural');
Group.prototype.color = Model.attribute('color');
Group.prototype.icon = Model.attribute('icon');
class Group extends mixin(Model, {
nameSingular: Model.attribute('nameSingular'),
namePlural: Model.attribute('namePlural'),
color: Model.attribute('color'),
icon: Model.attribute('icon')
}) {}
Group.ADMINISTRATOR_ID = 1;
Group.GUEST_ID = 2;

View File

@ -1,18 +1,18 @@
import Model from 'flarum/model';
import Model from 'flarum/Model';
import mixin from 'flarum/utils/mixin';
import computed from 'flarum/utils/computed';
class Notification extends Model {}
export default class Notification extends mixin(Model, {
contentType: Model.attribute('contentType'),
subjectId: Model.attribute('subjectId'),
content: Model.attribute('content'),
time: Model.attribute('time', Model.date),
Notification.prototype.contentType = Model.attribute('contentType');
Notification.prototype.subjectId = Model.attribute('subjectId');
Notification.prototype.content = Model.attribute('content');
Notification.prototype.time = Model.attribute('time', Model.date);
Notification.prototype.isRead = Model.attribute('isRead');
Notification.prototype.unreadCount = Model.attribute('unreadCount');
Notification.prototype.additionalUnreadCount = computed('unreadCount', unreadCount => Math.max(0, unreadCount - 1));
isRead: Model.attribute('isRead'),
unreadCount: Model.attribute('unreadCount'),
additionalUnreadCount: computed('unreadCount', unreadCount => Math.max(0, unreadCount - 1)),
Notification.prototype.user = Model.hasOne('user');
Notification.prototype.sender = Model.hasOne('sender');
Notification.prototype.subject = Model.hasOne('subject');
export default Notification;
user: Model.hasOne('user'),
sender: Model.hasOne('sender'),
subject: Model.hasOne('subject')
}) {}

View File

@ -1,27 +1,27 @@
import Model from 'flarum/model';
import Model from 'flarum/Model';
import mixin from 'flarum/utils/mixin';
import computed from 'flarum/utils/computed';
import { getPlainContent } from 'flarum/utils/string';
class Post extends Model {}
export default class Post extends mixin(Model, {
number: Model.attribute('number'),
discussion: Model.hasOne('discussion'),
Post.prototype.number = Model.attribute('number');
Post.prototype.discussion = Model.hasOne('discussion');
time: Model.attribute('time', Model.transformDate),
user: Model.hasOne('user'),
contentType: Model.attribute('contentType'),
content: Model.attribute('content'),
contentHtml: Model.attribute('contentHtml'),
contentPlain: computed('contentHtml', getPlainContent),
Post.prototype.time = Model.attribute('time', Model.transformDate);
Post.prototype.user = Model.hasOne('user');
Post.prototype.contentType = Model.attribute('contentType');
Post.prototype.content = Model.attribute('content');
Post.prototype.contentHtml = Model.attribute('contentHtml');
Post.prototype.contentPlain = computed('contentHtml', contentHtml => $('<div/>').html(contentHtml.replace(/(<\/p>|<br>)/g, '$1 ')).text());
editTime: Model.attribute('editTime', Model.transformDate),
editUser: Model.hasOne('editUser'),
isEdited: computed('editTime', editTime => !!editTime),
Post.prototype.editTime = Model.attribute('editTime', Model.transformDate);
Post.prototype.editUser = Model.hasOne('editUser');
Post.prototype.isEdited = computed('editTime', editTime => !!editTime);
hideTime: Model.attribute('hideTime', Model.transformDate),
hideUser: Model.hasOne('hideUser'),
isHidden: computed('hideTime', hideTime => !!hideTime),
Post.prototype.hideTime = Model.attribute('hideTime', Model.transformDate);
Post.prototype.hideUser = Model.hasOne('hideUser');
Post.prototype.isHidden = computed('hideTime', hideTime => !!hideTime);
Post.prototype.canEdit = Model.attribute('canEdit');
Post.prototype.canDelete = Model.attribute('canDelete');
export default Post;
canEdit: Model.attribute('canEdit'),
canDelete: Model.attribute('canDelete')
}) {}

View File

@ -1,69 +1,98 @@
import Model from 'flarum/model'
import stringToColor from 'flarum/utils/string-to-color';
import ItemList from 'flarum/utils/item-list';
/*global ColorThief*/
import Model from 'flarum/Model';
import mixin from 'flarum/utils/mixin';
import stringToColor from 'flarum/utils/stringToColor';
import ItemList from 'flarum/utils/ItemList';
import computed from 'flarum/utils/computed';
import Badge from 'flarum/components/badge';
import Badge from 'flarum/components/Badge';
class User extends Model {}
export default class User extends mixin(Model, {
username: Model.attribute('username'),
email: Model.attribute('email'),
isConfirmed: Model.attribute('isConfirmed'),
password: Model.attribute('password'),
User.prototype.username = Model.attribute('username');
User.prototype.email = Model.attribute('email');
User.prototype.isConfirmed = Model.attribute('isConfirmed');
User.prototype.password = Model.attribute('password');
User.prototype.avatarUrl = Model.attribute('avatarUrl');
User.prototype.bio = Model.attribute('bio');
User.prototype.bioHtml = Model.attribute('bioHtml');
User.prototype.preferences = Model.attribute('preferences');
avatarUrl: Model.attribute('avatarUrl'),
bio: Model.attribute('bio'),
bioHtml: Model.attribute('bioHtml'),
preferences: Model.attribute('preferences'),
groups: Model.hasMany('groups'),
User.prototype.groups = Model.hasMany('groups');
joinTime: Model.attribute('joinTime', Model.transformDate),
lastSeenTime: Model.attribute('lastSeenTime', Model.transformDate),
readTime: Model.attribute('readTime', Model.transformDate),
unreadNotificationsCount: Model.attribute('unreadNotificationsCount'),
User.prototype.joinTime = Model.attribute('joinTime', Model.transformDate);
User.prototype.lastSeenTime = Model.attribute('lastSeenTime', Model.transformDate);
User.prototype.online = function() { return this.lastSeenTime() > moment().subtract(5, 'minutes').toDate(); };
User.prototype.readTime = Model.attribute('readTime', Model.transformDate);
User.prototype.unreadNotificationsCount = Model.attribute('unreadNotificationsCount');
discussionsCount: Model.attribute('discussionsCount'),
commentsCount: Model.attribute('commentsCount'),
User.prototype.discussionsCount = Model.attribute('discussionsCount');
User.prototype.commentsCount = Model.attribute('commentsCount');
;
User.prototype.canEdit = Model.attribute('canEdit');
User.prototype.canDelete = Model.attribute('canDelete');
canEdit: Model.attribute('canEdit'),
canDelete: Model.attribute('canDelete'),
User.prototype.color = computed('username', 'avatarUrl', 'avatarColor', function(username, avatarUrl, avatarColor) {
if (avatarColor) {
return 'rgb('+avatarColor[0]+', '+avatarColor[1]+', '+avatarColor[2]+')';
} else if (avatarUrl) {
var image = new Image();
var user = this;
image.onload = function() {
var colorThief = new ColorThief();
user.avatarColor = colorThief.getColor(this);
user.freshness = new Date();
m.redraw();
};
image.src = avatarUrl;
return '';
} else {
return '#'+stringToColor(username);
avatarColor: null,
color: computed('username', 'avatarUrl', 'avatarColor', function(username, avatarUrl, avatarColor) {
// If we've already calculated and cached the dominant color of the user's
// avatar, then we can return that in RGB format. If we haven't, we'll want
// to calculate it. Unless the user doesn't have an avatar, in which case
// we generate a color from their username.
if (avatarColor) {
return 'rgb(' + avatarColor.join(', ') + ')';
} else if (avatarUrl) {
this.calculateAvatarColor();
return '';
}
return '#' + stringToColor(username);
})
}) {
/**
* Check whether or not the user has been seen in the last 5 minutes.
*
* @return {Boolean}
* @public
*/
isOnline() {
return this.lastSeenTime() > moment().subtract(5, 'minutes').toDate();
}
});
User.prototype.badges = function() {
var items = new ItemList();
/**
* Get the Badge components that apply to this user.
*
* @return {ItemList}
*/
badges() {
const items = new ItemList();
this.groups().forEach(group => {
if (group.id() != 3) {
items.add('group'+group.id(),
this.groups().forEach(group => {
items.add('group' + group.id(),
Badge.component({
label: group.nameSingular(),
icon: group.icon(),
style: {backgroundColor: group.color()}
})
);
}
});
});
return items;
return items;
}
/**
* Calculate the dominant color of the user's avatar. The dominant color will
* be set to the `avatarColor` property once it has been calculated.
*
* @protected
*/
calculateAvatarColor() {
const image = new Image();
const user = this;
image.onload = function() {
const colorThief = new ColorThief();
user.avatarColor = colorThief.getColor(this);
user.freshness = new Date();
m.redraw();
};
image.src = this.avatarUrl();
}
}
export default User;