mirror of
https://github.com/flarum/core.git
synced 2025-08-08 01:16:52 +02:00
update prettier to v2 & format files
This commit is contained in:
6
js/dist/admin.js
vendored
6
js/dist/admin.js
vendored
@@ -993,7 +993,7 @@ var __WEBPACK_AMD_DEFINE_RESULT__;/*** IMPORTS FROM imports-loader ***/
|
|||||||
},
|
},
|
||||||
scrollTop: function scrollTop(value) {
|
scrollTop: function scrollTop(value) {
|
||||||
if (!this.length) return;
|
if (!this.length) return;
|
||||||
var hasScrollTop = 'scrollTop' in this[0];
|
var hasScrollTop = ('scrollTop' in this[0]);
|
||||||
if (value === undefined) return hasScrollTop ? this[0].scrollTop : this[0].pageYOffset;
|
if (value === undefined) return hasScrollTop ? this[0].scrollTop : this[0].pageYOffset;
|
||||||
return this.each(hasScrollTop ? function () {
|
return this.each(hasScrollTop ? function () {
|
||||||
this.scrollTop = value;
|
this.scrollTop = value;
|
||||||
@@ -1003,7 +1003,7 @@ var __WEBPACK_AMD_DEFINE_RESULT__;/*** IMPORTS FROM imports-loader ***/
|
|||||||
},
|
},
|
||||||
scrollLeft: function scrollLeft(value) {
|
scrollLeft: function scrollLeft(value) {
|
||||||
if (!this.length) return;
|
if (!this.length) return;
|
||||||
var hasScrollLeft = 'scrollLeft' in this[0];
|
var hasScrollLeft = ('scrollLeft' in this[0]);
|
||||||
if (value === undefined) return hasScrollLeft ? this[0].scrollLeft : this[0].pageXOffset;
|
if (value === undefined) return hasScrollLeft ? this[0].scrollLeft : this[0].pageXOffset;
|
||||||
return this.each(hasScrollLeft ? function () {
|
return this.each(hasScrollLeft ? function () {
|
||||||
this.scrollLeft = value;
|
this.scrollLeft = value;
|
||||||
@@ -1147,7 +1147,7 @@ var __WEBPACK_AMD_DEFINE_RESULT__;/*** IMPORTS FROM imports-loader ***/
|
|||||||
},
|
},
|
||||||
handlers = {},
|
handlers = {},
|
||||||
specialEvents = {},
|
specialEvents = {},
|
||||||
focusinSupported = 'onfocusin' in window,
|
focusinSupported = ('onfocusin' in window),
|
||||||
focus = {
|
focus = {
|
||||||
focus: 'focusin',
|
focus: 'focusin',
|
||||||
blur: 'focusout'
|
blur: 'focusout'
|
||||||
|
2
js/dist/admin.js.map
vendored
2
js/dist/admin.js.map
vendored
File diff suppressed because one or more lines are too long
2657
js/dist/forum.js
vendored
2657
js/dist/forum.js
vendored
File diff suppressed because it is too large
Load Diff
2
js/dist/forum.js.map
vendored
2
js/dist/forum.js.map
vendored
File diff suppressed because one or more lines are too long
825
js/package-lock.json
generated
825
js/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -22,19 +22,19 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "webpack --mode development --watch",
|
"dev": "webpack --mode development --watch",
|
||||||
"build": "webpack --mode production",
|
"build": "webpack --mode production",
|
||||||
"lint": "prettier --single-quote --trailing-comma es5 --print-width 150 --tab-width 4 --write \"src/**/*\" \"*.{ts,js}\""
|
"lint": "prettier --single-quote --trailing-comma es5 --print-width 150 --tab-width 4 --write src \"*.{ts,js}\""
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.8.7",
|
"@babel/core": "^7.9.0",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
||||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||||
"@babel/plugin-transform-object-assign": "^7.8.3",
|
"@babel/plugin-transform-object-assign": "^7.8.3",
|
||||||
"@babel/plugin-transform-react-jsx": "^7.8.3",
|
"@babel/plugin-transform-react-jsx": "^7.9.4",
|
||||||
"@babel/plugin-transform-runtime": "^7.8.3",
|
"@babel/plugin-transform-runtime": "^7.9.0",
|
||||||
"@babel/preset-env": "^7.8.7",
|
"@babel/preset-env": "^7.9.0",
|
||||||
"@babel/preset-react": "^7.8.3",
|
"@babel/preset-react": "^7.9.4",
|
||||||
"@babel/preset-typescript": "^7.8.3",
|
"@babel/preset-typescript": "^7.9.0",
|
||||||
"@babel/runtime": "^7.8.7",
|
"@babel/runtime": "^7.9.2",
|
||||||
"@types/classnames": "^2.2.10",
|
"@types/classnames": "^2.2.10",
|
||||||
"@types/mithril": "^2.0.2",
|
"@types/mithril": "^2.0.2",
|
||||||
"@types/zepto": "^1.0.30",
|
"@types/zepto": "^1.0.30",
|
||||||
@@ -42,10 +42,10 @@
|
|||||||
"expose-loader": "^0.7.5",
|
"expose-loader": "^0.7.5",
|
||||||
"friendly-errors-webpack-plugin": "^1.7.0",
|
"friendly-errors-webpack-plugin": "^1.7.0",
|
||||||
"imports-loader": "^0.8.0",
|
"imports-loader": "^0.8.0",
|
||||||
"prettier": "^1.19.1",
|
"prettier": "^2.0.2",
|
||||||
"source-map-loader": "^0.2.4",
|
"source-map-loader": "^0.2.4",
|
||||||
"typescript": "^3.8.3",
|
"typescript": "^3.8.3",
|
||||||
"webpack": "^4.42.0",
|
"webpack": "^4.42.1",
|
||||||
"webpack-bundle-analyzer": "^3.6.1",
|
"webpack-bundle-analyzer": "^3.6.1",
|
||||||
"webpack-cli": "^3.3.11",
|
"webpack-cli": "^3.3.11",
|
||||||
"webpack-merge": "^4.2.2"
|
"webpack-merge": "^4.2.2"
|
||||||
|
@@ -113,7 +113,7 @@ export default abstract class Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
boot() {
|
boot() {
|
||||||
this.initializers.toArray().forEach(initializer => initializer(this));
|
this.initializers.toArray().forEach((initializer) => initializer(this));
|
||||||
|
|
||||||
this.store.pushPayload({ data: this.data.resources });
|
this.store.pushPayload({ data: this.data.resources });
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ export default abstract class Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bootExtensions(extensions) {
|
bootExtensions(extensions) {
|
||||||
Object.keys(extensions).forEach(name => {
|
Object.keys(extensions).forEach((name) => {
|
||||||
const extension = extensions[name];
|
const extension = extensions[name];
|
||||||
|
|
||||||
const extenders = flattenDeep(extension.extend);
|
const extenders = flattenDeep(extension.extend);
|
||||||
@@ -145,13 +145,13 @@ export default abstract class Application {
|
|||||||
|
|
||||||
if ($modal) m.mount($modal, (this.modal = new ModalManager()));
|
if ($modal) m.mount($modal, (this.modal = new ModalManager()));
|
||||||
|
|
||||||
if ($alerts) m.mount($alerts, (this.alerts = new AlertManager({ oninit: vnode => (this.alerts = vnode.state) })));
|
if ($alerts) m.mount($alerts, (this.alerts = new AlertManager({ oninit: (vnode) => (this.alerts = vnode.state) })));
|
||||||
|
|
||||||
if ($content) m.route($content, basePath + '/', mapRoutes(this.routes, basePath));
|
if ($content) m.route($content, basePath + '/', mapRoutes(this.routes, basePath));
|
||||||
|
|
||||||
// Add a class to the body which indicates that the page has been scrolled
|
// Add a class to the body which indicates that the page has been scrolled
|
||||||
// down.
|
// down.
|
||||||
new ScrollListener(top => {
|
new ScrollListener((top) => {
|
||||||
const $app = $('#app');
|
const $app = $('#app');
|
||||||
const offset = $app.offset().top;
|
const offset = $app.offset().top;
|
||||||
|
|
||||||
@@ -248,11 +248,11 @@ export default abstract class Application {
|
|||||||
// When we deserialize JSON data, if for some reason the server has provided
|
// When we deserialize JSON data, if for some reason the server has provided
|
||||||
// a dud response, we don't want the application to crash. We'll show an
|
// a dud response, we don't want the application to crash. We'll show an
|
||||||
// error message to the user instead.
|
// error message to the user instead.
|
||||||
options.deserialize = options.deserialize || (responseText => responseText);
|
options.deserialize = options.deserialize || ((responseText) => responseText);
|
||||||
|
|
||||||
options.errorHandler =
|
options.errorHandler =
|
||||||
options.errorHandler ||
|
options.errorHandler ||
|
||||||
(error => {
|
((error) => {
|
||||||
throw error;
|
throw error;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -260,7 +260,7 @@ export default abstract class Application {
|
|||||||
// response code and show an error message to the user if something's gone
|
// response code and show an error message to the user if something's gone
|
||||||
// awry.
|
// awry.
|
||||||
const original = options.extract;
|
const original = options.extract;
|
||||||
options.extract = xhr => {
|
options.extract = (xhr) => {
|
||||||
let responseText;
|
let responseText;
|
||||||
|
|
||||||
if (original) {
|
if (original) {
|
||||||
@@ -292,8 +292,8 @@ export default abstract class Application {
|
|||||||
// Now make the request. If it's a failure, inspect the error that was
|
// Now make the request. If it's a failure, inspect the error that was
|
||||||
// returned and show an alert containing its contents.
|
// returned and show an alert containing its contents.
|
||||||
return m.request(options).then(
|
return m.request(options).then(
|
||||||
res => res,
|
(res) => res,
|
||||||
error => {
|
(error) => {
|
||||||
this.requestError = error;
|
this.requestError = error;
|
||||||
|
|
||||||
let children;
|
let children;
|
||||||
@@ -301,7 +301,7 @@ export default abstract class Application {
|
|||||||
switch (error.status) {
|
switch (error.status) {
|
||||||
case 422:
|
case 422:
|
||||||
children = error.response.errors
|
children = error.response.errors
|
||||||
.map(error => [error.detail, m('br')])
|
.map((error) => [error.detail, m('br')])
|
||||||
.reduce((a, b) => a.concat(b), [])
|
.reduce((a, b) => a.concat(b), [])
|
||||||
.slice(0, -1);
|
.slice(0, -1);
|
||||||
break;
|
break;
|
||||||
|
@@ -164,7 +164,7 @@ export default abstract class Model {
|
|||||||
// If everything went well, we'll make sure the store knows that this
|
// If everything went well, we'll make sure the store knows that this
|
||||||
// model exists now (if it didn't already), and we'll push the data that
|
// model exists now (if it didn't already), and we'll push the data that
|
||||||
// the API returned into the store.
|
// the API returned into the store.
|
||||||
payload => {
|
(payload) => {
|
||||||
this.store.data[payload.data.type] = this.store.data[payload.data.type] || {};
|
this.store.data[payload.data.type] = this.store.data[payload.data.type] || {};
|
||||||
this.store.data[payload.data.type][payload.data.id] = this;
|
this.store.data[payload.data.type][payload.data.id] = this;
|
||||||
return this.store.pushPayload(payload);
|
return this.store.pushPayload(payload);
|
||||||
@@ -172,7 +172,7 @@ export default abstract class Model {
|
|||||||
|
|
||||||
// If something went wrong, though... good thing we backed up our model's
|
// If something went wrong, though... good thing we backed up our model's
|
||||||
// old data! We'll revert to that and let others handle the error.
|
// old data! We'll revert to that and let others handle the error.
|
||||||
response => {
|
(response) => {
|
||||||
this.pushData(oldData);
|
this.pushData(oldData);
|
||||||
m.redraw();
|
m.redraw();
|
||||||
throw response;
|
throw response;
|
||||||
@@ -272,7 +272,7 @@ export default abstract class Model {
|
|||||||
const relationship = this.data.relationships[name];
|
const relationship = this.data.relationships[name];
|
||||||
|
|
||||||
if (relationship && Array.isArray(relationship.data)) {
|
if (relationship && Array.isArray(relationship.data)) {
|
||||||
return relationship.data.map(data => app.store.getById(data.type, data.id));
|
return relationship.data.map((data) => app.store.getById(data.type, data.id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -119,7 +119,7 @@ export default class Store {
|
|||||||
* @param value The value of the model attribute.
|
* @param value The value of the model attribute.
|
||||||
*/
|
*/
|
||||||
getBy<T extends Model = Model>(type: string, key: string, value: any): T {
|
getBy<T extends Model = Model>(type: string, key: string, value: any): T {
|
||||||
return this.all<T>(type).filter(model => model[key]() === value)[0];
|
return this.all<T>(type).filter((model) => model[key]() === value)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -128,7 +128,7 @@ export default class Store {
|
|||||||
all<T extends Model = Model>(type: string): T[] {
|
all<T extends Model = Model>(type: string): T[] {
|
||||||
const records = this.data[type];
|
const records = this.data[type];
|
||||||
|
|
||||||
return records ? Object.keys(records).map(id => records[id]) : [];
|
return records ? Object.keys(records).map((id) => records[id]) : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -52,7 +52,7 @@ export default class Translator {
|
|||||||
const hydrated: any[] = [];
|
const hydrated: any[] = [];
|
||||||
const open: any[][] = [hydrated];
|
const open: any[][] = [hydrated];
|
||||||
|
|
||||||
parts.forEach(part => {
|
parts.forEach((part) => {
|
||||||
const match = part.match(new RegExp('{([a-z0-9_]+)}|<(/?)([a-z0-9_]+)>', 'i'));
|
const match = part.match(new RegExp('{([a-z0-9_]+)}|<(/?)([a-z0-9_]+)>', 'i'));
|
||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
@@ -72,7 +72,7 @@ export default class Translator {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return hydrated.filter(part => part);
|
return hydrated.filter((part) => part);
|
||||||
}
|
}
|
||||||
|
|
||||||
pluralize(translation: string, number: number): string | undefined {
|
pluralize(translation: string, number: number): string | undefined {
|
||||||
@@ -84,7 +84,7 @@ export default class Translator {
|
|||||||
standardRules = [],
|
standardRules = [],
|
||||||
explicitRules = [];
|
explicitRules = [];
|
||||||
|
|
||||||
translation.split('|').forEach(part => {
|
translation.split('|').forEach((part) => {
|
||||||
if (cPluralRegex.test(part)) {
|
if (cPluralRegex.test(part)) {
|
||||||
const matches = part.match(cPluralRegex);
|
const matches = part.match(cPluralRegex);
|
||||||
explicitRules[matches[0]] = matches[matches.length - 1];
|
explicitRules[matches[0]] = matches[matches.length - 1];
|
||||||
|
@@ -15,7 +15,7 @@ export default class AlertManager extends Component {
|
|||||||
view() {
|
view() {
|
||||||
return (
|
return (
|
||||||
<div className="AlertManager">
|
<div className="AlertManager">
|
||||||
{this.components.map(vnode => (
|
{this.components.map((vnode) => (
|
||||||
<div className="AlertManager-alert">{vnode}</div>
|
<div className="AlertManager-alert">{vnode}</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -81,11 +81,7 @@ export default abstract class Modal<T extends ComponentProps = ComponentProps> e
|
|||||||
* Focus on the first input when the modal is ready to be used.
|
* Focus on the first input when the modal is ready to be used.
|
||||||
*/
|
*/
|
||||||
onready() {
|
onready() {
|
||||||
this.$('form')
|
this.$('form').find('input, select, textarea').first().focus().select();
|
||||||
.find('input, select, textarea')
|
|
||||||
.first()
|
|
||||||
.focus()
|
|
||||||
.select();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onhide() {}
|
onhide() {}
|
||||||
|
@@ -51,9 +51,7 @@ export default class ModalManager extends Component {
|
|||||||
m.redraw();
|
m.redraw();
|
||||||
|
|
||||||
if (!$('.modal-backdrop').length) {
|
if (!$('.modal-backdrop').length) {
|
||||||
$('<div />')
|
$('<div />').addClass('modal-backdrop').appendTo('body');
|
||||||
.addClass('modal-backdrop')
|
|
||||||
.appendTo('body');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MicroModal.show('Modal', {
|
MicroModal.show('Modal', {
|
||||||
|
@@ -25,7 +25,7 @@ export default class SelectDropdown extends Dropdown<SelectDropdownProps> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getButtonContent() {
|
getButtonContent() {
|
||||||
const activeChild = this.props.children.filter(child => child.attrs.active)[0];
|
const activeChild = this.props.children.filter((child) => child.attrs.active)[0];
|
||||||
let label = (activeChild && activeChild.attrs.children) || this.props.defaultLabel;
|
let label = (activeChild && activeChild.attrs.children) || this.props.defaultLabel;
|
||||||
|
|
||||||
if (label instanceof Array) label = label[0];
|
if (label instanceof Array) label = label[0];
|
||||||
|
@@ -28,9 +28,7 @@ export default function highlight(string: string, phrase: string | RegExp, lengt
|
|||||||
|
|
||||||
// Convert the string into HTML entities, then highlight all matches with
|
// Convert the string into HTML entities, then highlight all matches with
|
||||||
// <mark> tags. Then we will return the result as a trusted HTML string.
|
// <mark> tags. Then we will return the result as a trusted HTML string.
|
||||||
highlighted = $('<div/>')
|
highlighted = $('<div/>').text(highlighted).html();
|
||||||
.text(highlighted)
|
|
||||||
.html();
|
|
||||||
|
|
||||||
if (phrase) highlighted = highlighted.replace(regexp, '<mark>$&</mark>');
|
if (phrase) highlighted = highlighted.replace(regexp, '<mark>$&</mark>');
|
||||||
|
|
||||||
|
@@ -28,7 +28,7 @@ export function withoutUnnecessarySeparators(items) {
|
|||||||
export default function listItems(items) {
|
export default function listItems(items) {
|
||||||
if (!(items instanceof Array)) items = [items];
|
if (!(items instanceof Array)) items = [items];
|
||||||
|
|
||||||
return withoutUnnecessarySeparators(items).map(item => {
|
return withoutUnnecessarySeparators(items).map((item) => {
|
||||||
const isListItem = item.tag?.isListItem;
|
const isListItem = item.tag?.isListItem;
|
||||||
const active = item.tag?.isActive && item.tag.isActive(item.attrs);
|
const active = item.tag?.isActive && item.tag.isActive(item.attrs);
|
||||||
const className = item.attrs?.itemClassName || item.itemClassName;
|
const className = item.attrs?.itemClassName || item.itemClassName;
|
||||||
|
@@ -20,18 +20,18 @@ export default class Discussion extends Model {
|
|||||||
lastPostNumber = Model.attribute('lastPostNumber') as () => number;
|
lastPostNumber = Model.attribute('lastPostNumber') as () => number;
|
||||||
|
|
||||||
commentCount = Model.attribute('commentCount') as () => number;
|
commentCount = Model.attribute('commentCount') as () => number;
|
||||||
replyCount = computed('commentCount', commentCount => Math.max(0, commentCount - 1)) as () => number;
|
replyCount = computed('commentCount', (commentCount) => Math.max(0, commentCount - 1)) as () => number;
|
||||||
posts = Model.hasMany('posts') as () => Post[];
|
posts = Model.hasMany('posts') as () => Post[];
|
||||||
mostRelevantPost = Model.hasOne('mostRelevantPost') as () => Post;
|
mostRelevantPost = Model.hasOne('mostRelevantPost') as () => Post;
|
||||||
|
|
||||||
lastReadAt = Model.attribute('lastReadAt', Model.transformDate) as () => Date;
|
lastReadAt = Model.attribute('lastReadAt', Model.transformDate) as () => Date;
|
||||||
lastReadPostNumber = Model.attribute('lastReadPostNumber') as () => number;
|
lastReadPostNumber = Model.attribute('lastReadPostNumber') as () => number;
|
||||||
isUnread = computed('unreadCount', unreadCount => !!unreadCount) as () => boolean;
|
isUnread = computed('unreadCount', (unreadCount) => !!unreadCount) as () => boolean;
|
||||||
isRead = computed('unreadCount', unreadCount => app.session.user && !unreadCount) as () => boolean;
|
isRead = computed('unreadCount', (unreadCount) => app.session.user && !unreadCount) as () => boolean;
|
||||||
|
|
||||||
hiddenAt = Model.attribute('hiddenAt', Model.transformDate) as () => Date;
|
hiddenAt = Model.attribute('hiddenAt', Model.transformDate) as () => Date;
|
||||||
hiddenUser = Model.hasOne('hiddenUser') as () => User;
|
hiddenUser = Model.hasOne('hiddenUser') as () => User;
|
||||||
isHidden = computed('hiddenAt', hiddenAt => !!hiddenAt) as () => boolean;
|
isHidden = computed('hiddenAt', (hiddenAt) => !!hiddenAt) as () => boolean;
|
||||||
|
|
||||||
canReply = Model.attribute('canReply') as () => boolean;
|
canReply = Model.attribute('canReply') as () => boolean;
|
||||||
canRename = Model.attribute('canRename') as () => boolean;
|
canRename = Model.attribute('canRename') as () => boolean;
|
||||||
@@ -90,6 +90,6 @@ export default class Discussion extends Model {
|
|||||||
postIds(): string[] {
|
postIds(): string[] {
|
||||||
const posts = this.data.relationships?.posts;
|
const posts = this.data.relationships?.posts;
|
||||||
|
|
||||||
return posts ? posts.data.map(link => link.id) : [];
|
return posts ? posts.data.map((link) => link.id) : [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,11 +18,11 @@ export default class Post extends Model {
|
|||||||
|
|
||||||
editedAt = Model.attribute('editedAt', Model.transformDate) as () => Date;
|
editedAt = Model.attribute('editedAt', Model.transformDate) as () => Date;
|
||||||
editedUser = Model.hasOne('editedUser') as () => User;
|
editedUser = Model.hasOne('editedUser') as () => User;
|
||||||
isEdited = computed('editedAt', editedAt => !!editedAt) as () => boolean;
|
isEdited = computed('editedAt', (editedAt) => !!editedAt) as () => boolean;
|
||||||
|
|
||||||
hiddenAt = Model.attribute('hiddenAt', Model.transformDate) as () => Date;
|
hiddenAt = Model.attribute('hiddenAt', Model.transformDate) as () => Date;
|
||||||
hiddenUser = Model.hasOne('hiddenUser') as () => User;
|
hiddenUser = Model.hasOne('hiddenUser') as () => User;
|
||||||
isHidden = computed('hiddenAt', hiddenAt => !!hiddenAt) as () => boolean;
|
isHidden = computed('hiddenAt', (hiddenAt) => !!hiddenAt) as () => boolean;
|
||||||
|
|
||||||
canEdit = Model.attribute('canEdit') as () => boolean;
|
canEdit = Model.attribute('canEdit') as () => boolean;
|
||||||
canHide = Model.attribute('canHide') as () => boolean;
|
canHide = Model.attribute('canHide') as () => boolean;
|
||||||
|
@@ -54,12 +54,7 @@ export default class User extends Model {
|
|||||||
}) as () => string;
|
}) as () => string;
|
||||||
|
|
||||||
isOnline(): boolean {
|
isOnline(): boolean {
|
||||||
return (
|
return this.lastSeenAt() > dayjs().subtract(5, 'minutes').toDate();
|
||||||
this.lastSeenAt() >
|
|
||||||
dayjs()
|
|
||||||
.subtract(5, 'minutes')
|
|
||||||
.toDate()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -70,7 +65,7 @@ export default class User extends Model {
|
|||||||
const groups = this.groups();
|
const groups = this.groups();
|
||||||
|
|
||||||
if (groups) {
|
if (groups) {
|
||||||
groups.forEach(group => {
|
groups.forEach((group) => {
|
||||||
items.add('group' + group.id(), GroupBadge.component({ group }));
|
items.add('group' + group.id(), GroupBadge.component({ group }));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -9,7 +9,7 @@ export default class Drawer {
|
|||||||
constructor() {
|
constructor() {
|
||||||
// Set up an event handler so that whenever the content area is tapped,
|
// Set up an event handler so that whenever the content area is tapped,
|
||||||
// the drawer will close.
|
// the drawer will close.
|
||||||
$('#content').click(e => {
|
$('#content').click((e) => {
|
||||||
if (this.isOpen()) {
|
if (this.isOpen()) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.hide();
|
this.hide();
|
||||||
|
@@ -26,7 +26,7 @@ export default class Evented {
|
|||||||
* @param args Arguments to pass to event handlers.
|
* @param args Arguments to pass to event handlers.
|
||||||
*/
|
*/
|
||||||
public trigger(event: string, ...args: any): this {
|
public trigger(event: string, ...args: any): this {
|
||||||
this.getHandlers(event).forEach(handler => handler.apply(this, args));
|
this.getHandlers(event).forEach((handler) => handler.apply(this, args));
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@@ -83,6 +83,6 @@ export default class ItemList<T = any> {
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
})
|
})
|
||||||
.map(item => item.content);
|
.map((item) => item.content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,7 @@ const later =
|
|||||||
window.mozRequestAnimationFrame ||
|
window.mozRequestAnimationFrame ||
|
||||||
window.msRequestAnimationFrame ||
|
window.msRequestAnimationFrame ||
|
||||||
window.oRequestAnimationFrame ||
|
window.oRequestAnimationFrame ||
|
||||||
(callback => window.setTimeout(callback, 1000 / 60));
|
((callback) => window.setTimeout(callback, 1000 / 60));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `ScrollListener` class sets up a listener that handles window scroll
|
* The `ScrollListener` class sets up a listener that handles window scroll
|
||||||
|
@@ -17,7 +17,7 @@ export default function computed(dependentKeys: string | string[], compute: Func
|
|||||||
|
|
||||||
// Read all of the dependent values. If any of them have changed since last
|
// Read all of the dependent values. If any of them have changed since last
|
||||||
// time, then we'll want to recompute our output.
|
// time, then we'll want to recompute our output.
|
||||||
keys.forEach(key => {
|
keys.forEach((key) => {
|
||||||
const value = typeof this[key] === 'function' ? this[key]() : this[key];
|
const value = typeof this[key] === 'function' ? this[key]() : this[key];
|
||||||
|
|
||||||
if (dependentValues[key] !== value) {
|
if (dependentValues[key] !== value) {
|
||||||
@@ -29,7 +29,7 @@ export default function computed(dependentKeys: string | string[], compute: Func
|
|||||||
if (recompute) {
|
if (recompute) {
|
||||||
computedValue = compute.apply(
|
computedValue = compute.apply(
|
||||||
this,
|
this,
|
||||||
keys.map(key => dependentValues[key])
|
keys.map((key) => dependentValues[key])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
export default function extractText(vdom: any): string {
|
export default function extractText(vdom: any): string {
|
||||||
if (vdom instanceof Array) {
|
if (vdom instanceof Array) {
|
||||||
return vdom.map(element => extractText(element)).join('');
|
return vdom.map((element) => extractText(element)).join('');
|
||||||
} else if (typeof vdom === 'object' && vdom !== null) {
|
} else if (typeof vdom === 'object' && vdom !== null) {
|
||||||
return vdom.text || extractText(vdom.children);
|
return vdom.text || extractText(vdom.children);
|
||||||
} else {
|
} else {
|
||||||
|
@@ -34,7 +34,7 @@ export default () => {
|
|||||||
return node;
|
return node;
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.keys(mo).forEach(key => (_m[key] = mo[key]));
|
Object.keys(mo).forEach((key) => (_m[key] = mo[key]));
|
||||||
|
|
||||||
_m.withAttr = (key: string, cb: Function) =>
|
_m.withAttr = (key: string, cb: Function) =>
|
||||||
function () {
|
function () {
|
||||||
|
@@ -28,10 +28,7 @@ export function getPlainContent(string: string): string {
|
|||||||
|
|
||||||
dom.find(getPlainContent.removeSelectors.join(',')).remove();
|
dom.find(getPlainContent.removeSelectors.join(',')).remove();
|
||||||
|
|
||||||
return dom
|
return dom.text().replace(/\s+/g, ' ').trim();
|
||||||
.text()
|
|
||||||
.replace(/\s+/g, ' ')
|
|
||||||
.trim();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -146,7 +146,7 @@ export default class AvatarEditor extends Component<AvatarEditorProps> {
|
|||||||
.appendTo('body')
|
.appendTo('body')
|
||||||
.hide()
|
.hide()
|
||||||
.click()
|
.click()
|
||||||
.on('change', e => {
|
.on('change', (e) => {
|
||||||
this.upload($(e.target)[0].files[0]);
|
this.upload($(e.target)[0].files[0]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -167,7 +167,7 @@ export default class AvatarEditor extends Component<AvatarEditorProps> {
|
|||||||
app.request({
|
app.request({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: `${app.forum.attribute('apiUrl')}/users/${user.id()}/avatar`,
|
url: `${app.forum.attribute('apiUrl')}/users/${user.id()}/avatar`,
|
||||||
serialize: raw => raw,
|
serialize: (raw) => raw,
|
||||||
body,
|
body,
|
||||||
}).then(this.success.bind(this), this.failure.bind(this));
|
}).then(this.success.bind(this), this.failure.bind(this));
|
||||||
}
|
}
|
||||||
|
@@ -60,7 +60,7 @@ export default class DiscussionList<T extends DiscussionListProps = DiscussionLi
|
|||||||
return (
|
return (
|
||||||
<div className={'DiscussionList' + (this.props.params.q ? ' DiscussionList--searchResults' : '')}>
|
<div className={'DiscussionList' + (this.props.params.q ? ' DiscussionList--searchResults' : '')}>
|
||||||
<ul className="DiscussionList-discussions">
|
<ul className="DiscussionList-discussions">
|
||||||
{this.discussions.map(discussion => {
|
{this.discussions.map((discussion) => {
|
||||||
return (
|
return (
|
||||||
<li key={discussion.id()} data-id={discussion.id()}>
|
<li key={discussion.id()} data-id={discussion.id()}>
|
||||||
{DiscussionListItem.component({ discussion, params })}
|
{DiscussionListItem.component({ discussion, params })}
|
||||||
@@ -121,7 +121,7 @@ export default class DiscussionList<T extends DiscussionListProps = DiscussionLi
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this.loadResults().then(
|
return this.loadResults().then(
|
||||||
results => {
|
(results) => {
|
||||||
this.discussions = [];
|
this.discussions = [];
|
||||||
this.parseResults(results);
|
this.parseResults(results);
|
||||||
},
|
},
|
||||||
|
@@ -97,7 +97,7 @@ export default class DiscussionListItem<T extends DiscussionListItemProps = Disc
|
|||||||
user: user,
|
user: user,
|
||||||
ago: humanTime(discussion.createdAt()),
|
ago: humanTime(discussion.createdAt()),
|
||||||
})}
|
})}
|
||||||
oncreate={vnode => $(vnode.dom).tooltip({ placement: 'right' })}
|
oncreate={(vnode) => $(vnode.dom).tooltip({ placement: 'right' })}
|
||||||
>
|
>
|
||||||
{avatar(user, { title: '' })}
|
{avatar(user, { title: '' })}
|
||||||
</LinkButton>
|
</LinkButton>
|
||||||
|
@@ -97,7 +97,7 @@ export default class DiscussionPage extends Page {
|
|||||||
<PostStream
|
<PostStream
|
||||||
discussion={discussion}
|
discussion={discussion}
|
||||||
includedPosts={this.includedPosts}
|
includedPosts={this.includedPosts}
|
||||||
oninit={vnode => {
|
oninit={(vnode) => {
|
||||||
this.stream = vnode.state;
|
this.stream = vnode.state;
|
||||||
this.scrubber.stream = vnode.state;
|
this.scrubber.stream = vnode.state;
|
||||||
|
|
||||||
@@ -196,13 +196,13 @@ export default class DiscussionPage extends Page {
|
|||||||
|
|
||||||
this.includedPosts = discussion.payload.included
|
this.includedPosts = discussion.payload.included
|
||||||
.filter(
|
.filter(
|
||||||
record =>
|
(record) =>
|
||||||
record.type === 'posts' &&
|
record.type === 'posts' &&
|
||||||
record.relationships &&
|
record.relationships &&
|
||||||
record.relationships.discussion &&
|
record.relationships.discussion &&
|
||||||
record.relationships.discussion.data.id === discussionId
|
record.relationships.discussion.data.id === discussionId
|
||||||
)
|
)
|
||||||
.map(record => app.store.getById('posts', record.id))
|
.map((record) => app.store.getById('posts', record.id))
|
||||||
.sort((a, b) => a.id() - b.id())
|
.sort((a, b) => a.id() - b.id())
|
||||||
.slice(0, 20);
|
.slice(0, 20);
|
||||||
}
|
}
|
||||||
@@ -262,7 +262,7 @@ export default class DiscussionPage extends Page {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
items.add('scrubber', <PostStreamScrubber oninit={vnode => (this.scrubber = vnode.state)} className="App-titleControl" />, -100);
|
items.add('scrubber', <PostStreamScrubber oninit={(vnode) => (this.scrubber = vnode.state)} className="App-titleControl" />, -100);
|
||||||
|
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,7 @@ export default class DiscussionsSearchSource extends SearchSource {
|
|||||||
include: 'mostRelevantPost',
|
include: 'mostRelevantPost',
|
||||||
};
|
};
|
||||||
|
|
||||||
return app.store.find<Discussion>('discussions', params).then(results => (this.results[query] = results));
|
return app.store.find<Discussion>('discussions', params).then((results) => (this.results[query] = results));
|
||||||
}
|
}
|
||||||
|
|
||||||
view(query: string) {
|
view(query: string) {
|
||||||
@@ -38,7 +38,7 @@ export default class DiscussionsSearchSource extends SearchSource {
|
|||||||
href: app.route('index', { q: query }),
|
href: app.route('index', { q: query }),
|
||||||
})}
|
})}
|
||||||
</li>,
|
</li>,
|
||||||
results.map(discussion => {
|
results.map((discussion) => {
|
||||||
const mostRelevantPost = discussion.mostRelevantPost();
|
const mostRelevantPost = discussion.mostRelevantPost();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@@ -48,7 +48,7 @@ export default class IndexPage extends Page {
|
|||||||
// are currently present in the cached discussion list. If they differ, we
|
// are currently present in the cached discussion list. If they differ, we
|
||||||
// will clear the cache and set up a new discussion list component with
|
// will clear the cache and set up a new discussion list component with
|
||||||
// the new parameters.
|
// the new parameters.
|
||||||
Object.keys(params).some(key => {
|
Object.keys(params).some((key) => {
|
||||||
if (app.cache.discussionList!.props.params[key] !== params[key]) {
|
if (app.cache.discussionList!.props.params[key] !== params[key]) {
|
||||||
app.cache.discussionList = null;
|
app.cache.discussionList = null;
|
||||||
return true;
|
return true;
|
||||||
@@ -57,7 +57,7 @@ export default class IndexPage extends Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!app.cache.discussionList) {
|
if (!app.cache.discussionList) {
|
||||||
app.cache.discussionList = new DiscussionList({ params, oninit: vnode => (app.cache.discussionList = vnode.state) });
|
app.cache.discussionList = new DiscussionList({ params, oninit: (vnode) => (app.cache.discussionList = vnode.state) });
|
||||||
}
|
}
|
||||||
|
|
||||||
app.history.push('index', app.translator.transText('core.forum.header.back_to_index_tooltip'));
|
app.history.push('index', app.translator.transText('core.forum.header.back_to_index_tooltip'));
|
||||||
@@ -225,8 +225,8 @@ export default class IndexPage extends Page {
|
|||||||
'sort',
|
'sort',
|
||||||
Dropdown.component({
|
Dropdown.component({
|
||||||
buttonClassName: 'Button',
|
buttonClassName: 'Button',
|
||||||
label: sortOptions[this.params().sort] || Object.keys(sortMap).map(key => sortOptions[key])[0],
|
label: sortOptions[this.params().sort] || Object.keys(sortMap).map((key) => sortOptions[key])[0],
|
||||||
children: Object.keys(sortOptions).map(value => {
|
children: Object.keys(sortOptions).map((value) => {
|
||||||
const label = sortOptions[value];
|
const label = sortOptions[value];
|
||||||
const active = (this.params().sort || Object.keys(sortMap)[0]) === value;
|
const active = (this.params().sort || Object.keys(sortMap)[0]) === value;
|
||||||
|
|
||||||
|
@@ -51,8 +51,8 @@ export default class NotificationGrid extends Component<NotificationGridProps> {
|
|||||||
|
|
||||||
// For each of the notification type-method combinations, create and store a
|
// For each of the notification type-method combinations, create and store a
|
||||||
// new checkbox component instance, which we will render in the view.
|
// new checkbox component instance, which we will render in the view.
|
||||||
this.types.forEach(type =>
|
this.types.forEach((type) =>
|
||||||
this.methods.forEach(method => {
|
this.methods.forEach((method) => {
|
||||||
const key = this.preferenceKey(type.name, method.name);
|
const key = this.preferenceKey(type.name, method.name);
|
||||||
const preference = this.props.user.preferences()[key];
|
const preference = this.props.user.preferences()[key];
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ export default class NotificationGrid extends Component<NotificationGridProps> {
|
|||||||
state: !!preference,
|
state: !!preference,
|
||||||
disabled: typeof preference === 'undefined',
|
disabled: typeof preference === 'undefined',
|
||||||
onchange: () => this.toggle([key]),
|
onchange: () => this.toggle([key]),
|
||||||
oninit: vnode => (this.inputs[key] = vnode.state),
|
oninit: (vnode) => (this.inputs[key] = vnode.state),
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -72,7 +72,7 @@ export default class NotificationGrid extends Component<NotificationGridProps> {
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td />
|
<td />
|
||||||
{this.methods.map(method => (
|
{this.methods.map((method) => (
|
||||||
<th className="NotificationGrid-groupToggle" onclick={this.toggleMethod.bind(this, method.name)}>
|
<th className="NotificationGrid-groupToggle" onclick={this.toggleMethod.bind(this, method.name)}>
|
||||||
{icon(method.icon)} {method.label}
|
{icon(method.icon)} {method.label}
|
||||||
</th>
|
</th>
|
||||||
@@ -81,12 +81,12 @@ export default class NotificationGrid extends Component<NotificationGridProps> {
|
|||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody>
|
<tbody>
|
||||||
{this.types.map(type => (
|
{this.types.map((type) => (
|
||||||
<tr>
|
<tr>
|
||||||
<td className="NotificationGrid-groupToggle" onclick={this.toggleType.bind(this, type.name)}>
|
<td className="NotificationGrid-groupToggle" onclick={this.toggleType.bind(this, type.name)}>
|
||||||
{icon(type.icon)} {type.label}
|
{icon(type.icon)} {type.label}
|
||||||
</td>
|
</td>
|
||||||
{this.methods.map(method => (
|
{this.methods.map((method) => (
|
||||||
<td className="NotificationGrid-checkbox">{this.inputs[this.preferenceKey(type.name, method.name)].render()}</td>
|
<td className="NotificationGrid-checkbox">{this.inputs[this.preferenceKey(type.name, method.name)].render()}</td>
|
||||||
))}
|
))}
|
||||||
</tr>
|
</tr>
|
||||||
@@ -124,7 +124,7 @@ export default class NotificationGrid extends Component<NotificationGridProps> {
|
|||||||
const preferences = user.preferences();
|
const preferences = user.preferences();
|
||||||
const enabled = !preferences[keys[0]];
|
const enabled = !preferences[keys[0]];
|
||||||
|
|
||||||
keys.forEach(key => {
|
keys.forEach((key) => {
|
||||||
const control = this.inputs[key];
|
const control = this.inputs[key];
|
||||||
|
|
||||||
control.loading = true;
|
control.loading = true;
|
||||||
@@ -135,7 +135,7 @@ export default class NotificationGrid extends Component<NotificationGridProps> {
|
|||||||
m.redraw();
|
m.redraw();
|
||||||
|
|
||||||
user.save({ preferences }).then(() => {
|
user.save({ preferences }).then(() => {
|
||||||
keys.forEach(key => (this.inputs[key].loading = false));
|
keys.forEach((key) => (this.inputs[key].loading = false));
|
||||||
|
|
||||||
m.redraw();
|
m.redraw();
|
||||||
});
|
});
|
||||||
@@ -145,7 +145,7 @@ export default class NotificationGrid extends Component<NotificationGridProps> {
|
|||||||
* Toggle all notification types for the given method.
|
* Toggle all notification types for the given method.
|
||||||
*/
|
*/
|
||||||
toggleMethod(method: string) {
|
toggleMethod(method: string) {
|
||||||
const keys = this.types.map(type => this.preferenceKey(type.name, method)).filter(key => !this.inputs[key].props.disabled);
|
const keys = this.types.map((type) => this.preferenceKey(type.name, method)).filter((key) => !this.inputs[key].props.disabled);
|
||||||
|
|
||||||
this.toggle(keys);
|
this.toggle(keys);
|
||||||
}
|
}
|
||||||
@@ -154,7 +154,7 @@ export default class NotificationGrid extends Component<NotificationGridProps> {
|
|||||||
* Toggle all notification methods for the given type.
|
* Toggle all notification methods for the given type.
|
||||||
*/
|
*/
|
||||||
toggleType(type: string) {
|
toggleType(type: string) {
|
||||||
const keys = this.methods.map(method => this.preferenceKey(type, method.name)).filter(key => !this.inputs[key].props.disabled);
|
const keys = this.methods.map((method) => this.preferenceKey(type, method.name)).filter((key) => !this.inputs[key].props.disabled);
|
||||||
|
|
||||||
this.toggle(keys);
|
this.toggle(keys);
|
||||||
}
|
}
|
||||||
|
@@ -45,11 +45,11 @@ export default class NotificationList extends Component {
|
|||||||
|
|
||||||
<div className="NotificationList-content">
|
<div className="NotificationList-content">
|
||||||
{pages.length
|
{pages.length
|
||||||
? pages.map(notifications => {
|
? pages.map((notifications) => {
|
||||||
const groups: { discussion: Discussion; notifications: Notification[] }[] = [];
|
const groups: { discussion: Discussion; notifications: Notification[] }[] = [];
|
||||||
const discussions = {};
|
const discussions = {};
|
||||||
|
|
||||||
notifications.forEach(notification => {
|
notifications.forEach((notification) => {
|
||||||
const subject = notification.subject();
|
const subject = notification.subject();
|
||||||
|
|
||||||
if (typeof subject === 'undefined') return;
|
if (typeof subject === 'undefined') return;
|
||||||
@@ -72,7 +72,7 @@ export default class NotificationList extends Component {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return groups.map(group => {
|
return groups.map((group) => {
|
||||||
const badges = group.discussion?.badges().toArray();
|
const badges = group.discussion?.badges().toArray();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -91,7 +91,7 @@ export default class NotificationList extends Component {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<ul className="NotificationGroup-content">
|
<ul className="NotificationGroup-content">
|
||||||
{group.notifications.map(notification => {
|
{group.notifications.map((notification) => {
|
||||||
const NotificationComponent = app.notificationComponents[notification.contentType()];
|
const NotificationComponent = app.notificationComponents[notification.contentType()];
|
||||||
return NotificationComponent ? <li>{NotificationComponent.component({ notification })}</li> : '';
|
return NotificationComponent ? <li>{NotificationComponent.component({ notification })}</li> : '';
|
||||||
})}
|
})}
|
||||||
@@ -199,8 +199,8 @@ export default class NotificationList extends Component {
|
|||||||
|
|
||||||
app.session.user.pushAttributes({ unreadNotificationCount: 0 });
|
app.session.user.pushAttributes({ unreadNotificationCount: 0 });
|
||||||
|
|
||||||
app.cache.notifications.forEach(notifications => {
|
app.cache.notifications.forEach((notifications) => {
|
||||||
notifications.forEach(notification => notification.pushAttributes({ isRead: true }));
|
notifications.forEach((notification) => notification.pushAttributes({ isRead: true }));
|
||||||
});
|
});
|
||||||
|
|
||||||
app.request({
|
app.request({
|
||||||
|
@@ -37,9 +37,7 @@ export default class PostEdited extends Component<PostProp> {
|
|||||||
super.onupdate(vnode);
|
super.onupdate(vnode);
|
||||||
|
|
||||||
if (this.shouldUpdateTooltip) {
|
if (this.shouldUpdateTooltip) {
|
||||||
this.$()
|
this.$().tooltip('destroy').tooltip();
|
||||||
.tooltip('destroy')
|
|
||||||
.tooltip();
|
|
||||||
this.shouldUpdateTooltip = false;
|
this.shouldUpdateTooltip = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -14,12 +14,7 @@ export default class PostMeta extends Component<PostProp> {
|
|||||||
// When the dropdown menu is shown, select the contents of the permalink
|
// When the dropdown menu is shown, select the contents of the permalink
|
||||||
// input so that the user can quickly copy the URL.
|
// input so that the user can quickly copy the URL.
|
||||||
const selectPermalink = function (this: HTMLElement) {
|
const selectPermalink = function (this: HTMLElement) {
|
||||||
setTimeout(() =>
|
setTimeout(() => $(this).parent().find('.PostMeta-permalink').select());
|
||||||
$(this)
|
|
||||||
.parent()
|
|
||||||
.find('.PostMeta-permalink')
|
|
||||||
.select()
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -36,7 +31,7 @@ export default class PostMeta extends Component<PostProp> {
|
|||||||
{permalink}
|
{permalink}
|
||||||
</a>
|
</a>
|
||||||
) : (
|
) : (
|
||||||
<input className="FormControl PostMeta-permalink" value={permalink} onclick={e => e.stopPropagation()} />
|
<input className="FormControl PostMeta-permalink" value={permalink} onclick={(e) => e.stopPropagation()} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -184,7 +184,7 @@ class PostStream<T extends PostStreamProps = PostStreamProps> extends Component<
|
|||||||
return this.discussion
|
return this.discussion
|
||||||
.postIds()
|
.postIds()
|
||||||
.slice(this.visibleStart, this.visibleEnd)
|
.slice(this.visibleStart, this.visibleEnd)
|
||||||
.map(id => {
|
.map((id) => {
|
||||||
const post = app.store.getById<Post>('posts', id);
|
const post = app.store.getById<Post>('posts', id);
|
||||||
|
|
||||||
return post && post.discussion() && typeof post.canEdit() !== 'undefined' ? post : null;
|
return post && post.discussion() && typeof post.canEdit() !== 'undefined' ? post : null;
|
||||||
@@ -193,10 +193,7 @@ class PostStream<T extends PostStreamProps = PostStreamProps> extends Component<
|
|||||||
|
|
||||||
view() {
|
view() {
|
||||||
function fadeIn(vnode) {
|
function fadeIn(vnode) {
|
||||||
if (!vnode.state.fadedIn)
|
if (!vnode.state.fadedIn) $(vnode.dom).hide().fadeIn();
|
||||||
$(vnode.dom)
|
|
||||||
.hide()
|
|
||||||
.fadeIn();
|
|
||||||
vnode.state.fadedIn = true;
|
vnode.state.fadedIn = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,7 +406,7 @@ class PostStream<T extends PostStreamProps = PostStreamProps> extends Component<
|
|||||||
this.discussion
|
this.discussion
|
||||||
.postIds()
|
.postIds()
|
||||||
.slice(start, end)
|
.slice(start, end)
|
||||||
.forEach(id => {
|
.forEach((id) => {
|
||||||
const post = app.store.getById<Post>('posts', id);
|
const post = app.store.getById<Post>('posts', id);
|
||||||
|
|
||||||
if (post && post.discussion() && typeof post.canEdit() !== 'undefined') {
|
if (post && post.discussion() && typeof post.canEdit() !== 'undefined') {
|
||||||
@@ -428,7 +425,7 @@ class PostStream<T extends PostStreamProps = PostStreamProps> extends Component<
|
|||||||
* resolved immediately.
|
* resolved immediately.
|
||||||
*/
|
*/
|
||||||
loadNearNumber(number: string | number): Promise<void> {
|
loadNearNumber(number: string | number): Promise<void> {
|
||||||
if (this.posts().some(post => post && Number(post.number()) === Number(number))) {
|
if (this.posts().some((post) => post && Number(post.number()) === Number(number))) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,7 +551,7 @@ class PostStream<T extends PostStreamProps = PostStreamProps> extends Component<
|
|||||||
// TODO const top = bottom ? itemBottom - $(window).height() + app.composer.computedHeight() : $item.is(':first-child') ? 0 : itemTop;
|
// TODO const top = bottom ? itemBottom - $(window).height() + app.composer.computedHeight() : $item.is(':first-child') ? 0 : itemTop;
|
||||||
const top = bottom ? itemBottom - $(window).height() : $item.is(':first-child') ? 0 : itemTop;
|
const top = bottom ? itemBottom - $(window).height() : $item.is(':first-child') ? 0 : itemTop;
|
||||||
|
|
||||||
return new Promise<void>(resolve => {
|
return new Promise<void>((resolve) => {
|
||||||
if (noAnimation) {
|
if (noAnimation) {
|
||||||
$container.scrollTop(top);
|
$container.scrollTop(top);
|
||||||
resolve();
|
resolve();
|
||||||
|
@@ -268,14 +268,14 @@ export default class PostStreamScrubber extends Component {
|
|||||||
// Now we want to make the scrollbar handle draggable. Let's start by
|
// Now we want to make the scrollbar handle draggable. Let's start by
|
||||||
// preventing default browser events from messing things up.
|
// preventing default browser events from messing things up.
|
||||||
.css({ cursor: 'pointer', 'user-select': 'none' })
|
.css({ cursor: 'pointer', 'user-select': 'none' })
|
||||||
.on('dragstart mousedown touchstart', e => e.preventDefault());
|
.on('dragstart mousedown touchstart', (e) => e.preventDefault());
|
||||||
|
|
||||||
this.$('.Scrubber-handle')
|
this.$('.Scrubber-handle')
|
||||||
.css('cursor', 'move')
|
.css('cursor', 'move')
|
||||||
.on('mousedown touchstart', this.onmousedown.bind(this) as ZeptoEventHandler)
|
.on('mousedown touchstart', this.onmousedown.bind(this) as ZeptoEventHandler)
|
||||||
|
|
||||||
// Exempt the scrollbar handle from the 'jump to' click event.
|
// Exempt the scrollbar handle from the 'jump to' click event.
|
||||||
.click(e => e.stopPropagation());
|
.click((e) => e.stopPropagation());
|
||||||
|
|
||||||
// When the mouse moves and when it is released, we pass the
|
// When the mouse moves and when it is released, we pass the
|
||||||
// information that we captured when the mouse was first pressed onto
|
// information that we captured when the mouse was first pressed onto
|
||||||
@@ -293,9 +293,7 @@ export default class PostStreamScrubber extends Component {
|
|||||||
|
|
||||||
$(window).off('resize', this.handlers.onresize);
|
$(window).off('resize', this.handlers.onresize);
|
||||||
|
|
||||||
$(document)
|
$(document).off('mousemove touchmove', this.handlers.onmousemove).off('mouseup touchend', this.handlers.onmouseup);
|
||||||
.off('mousemove touchmove', this.handlers.onmousemove)
|
|
||||||
.off('mouseup touchend', this.handlers.onmouseup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -70,7 +70,7 @@ export default class PostsUserPage extends UserPage {
|
|||||||
return (
|
return (
|
||||||
<div className="PostsUserPage">
|
<div className="PostsUserPage">
|
||||||
<ul className="PostsUserPage-list">
|
<ul className="PostsUserPage-list">
|
||||||
{this.posts.map(post => (
|
{this.posts.map((post) => (
|
||||||
<li>
|
<li>
|
||||||
<div className="PostsUserPage-discussion">
|
<div className="PostsUserPage-discussion">
|
||||||
{app.translator.trans('core.forum.user.in_discussion_text', {
|
{app.translator.trans('core.forum.user.in_discussion_text', {
|
||||||
|
@@ -105,7 +105,7 @@ export default class Search extends Component {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<ul className="Dropdown-menu Search-results">
|
<ul className="Dropdown-menu Search-results">
|
||||||
{this.value() && this.hasFocus ? this.sources.map(source => source.view(this.value())) : ''}
|
{this.value() && this.hasFocus ? this.sources.map((source) => source.view(this.value())) : ''}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -120,7 +120,7 @@ export default class Search extends Component {
|
|||||||
const search = this;
|
const search = this;
|
||||||
|
|
||||||
this.$('.Search-results')
|
this.$('.Search-results')
|
||||||
.on('mousedown', e => e.preventDefault())
|
.on('mousedown', (e) => e.preventDefault())
|
||||||
.on('click', () => this.$('input').blur())
|
.on('click', () => this.$('input').blur())
|
||||||
|
|
||||||
// Whenever the mouse is hovered over a search result, highlight it.
|
// Whenever the mouse is hovered over a search result, highlight it.
|
||||||
@@ -149,7 +149,7 @@ export default class Search extends Component {
|
|||||||
if (search.searched.indexOf(query) !== -1) return;
|
if (search.searched.indexOf(query) !== -1) return;
|
||||||
|
|
||||||
if (query.length >= 3 && search.sources) {
|
if (query.length >= 3 && search.sources) {
|
||||||
search.sources.map(source => {
|
search.sources.map((source) => {
|
||||||
if (!source.search) return;
|
if (!source.search) return;
|
||||||
|
|
||||||
search.loadingSources++;
|
search.loadingSources++;
|
||||||
@@ -168,7 +168,7 @@ export default class Search extends Component {
|
|||||||
|
|
||||||
.on('focus', function (this: HTMLElement) {
|
.on('focus', function (this: HTMLElement) {
|
||||||
$(this)
|
$(this)
|
||||||
.one('mouseup', e => e.preventDefault())
|
.one('mouseup', (e) => e.preventDefault())
|
||||||
.select();
|
.select();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -188,11 +188,7 @@ export default class Search extends Component {
|
|||||||
this.loadingSources = 0;
|
this.loadingSources = 0;
|
||||||
|
|
||||||
if (this.value()) {
|
if (this.value()) {
|
||||||
m.route.set(
|
m.route.set(this.getItem(this.index).find('a').attr('href'));
|
||||||
this.getItem(this.index)
|
|
||||||
.find('a')
|
|
||||||
.attr('href')
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
this.clear();
|
this.clear();
|
||||||
}
|
}
|
||||||
@@ -274,10 +270,7 @@ export default class Search extends Component {
|
|||||||
fixedIndex = 0;
|
fixedIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const $item = $items
|
const $item = $items.removeClass('active').eq(fixedIndex).addClass('active');
|
||||||
.removeClass('active')
|
|
||||||
.eq(fixedIndex)
|
|
||||||
.addClass('active');
|
|
||||||
|
|
||||||
this.index = Number($item.attr('data-index') || fixedIndex);
|
this.index = Number($item.attr('data-index') || fixedIndex);
|
||||||
|
|
||||||
|
@@ -85,7 +85,7 @@ export default abstract class UserPage extends Page {
|
|||||||
|
|
||||||
this.username = lowercaseUsername;
|
this.username = lowercaseUsername;
|
||||||
|
|
||||||
app.store.all<User>('users').some(user => {
|
app.store.all<User>('users').some((user) => {
|
||||||
if ((user.username().toLowerCase() === lowercaseUsername || user.id() === username) && user.joinTime()) {
|
if ((user.username().toLowerCase() === lowercaseUsername || user.id() === username) && user.joinTime()) {
|
||||||
this.show(user);
|
this.show(user);
|
||||||
return true;
|
return true;
|
||||||
|
@@ -19,7 +19,7 @@ export default class UsersSearchSource extends SearchSource {
|
|||||||
filter: { q: query },
|
filter: { q: query },
|
||||||
page: { limit: 5 },
|
page: { limit: 5 },
|
||||||
})
|
})
|
||||||
.then(results => {
|
.then((results) => {
|
||||||
this.results[query] = results;
|
this.results[query] = results;
|
||||||
m.redraw();
|
m.redraw();
|
||||||
});
|
});
|
||||||
@@ -32,7 +32,7 @@ export default class UsersSearchSource extends SearchSource {
|
|||||||
.concat(
|
.concat(
|
||||||
app.store
|
app.store
|
||||||
.all<User>('users')
|
.all<User>('users')
|
||||||
.filter(user => [user.username(), user.displayName()].some(value => value.toLowerCase().substr(0, query.length) === query))
|
.filter((user) => [user.username(), user.displayName()].some((value) => value.toLowerCase().substr(0, query.length) === query))
|
||||||
)
|
)
|
||||||
.filter((e, i, arr) => arr.lastIndexOf(e) === i)
|
.filter((e, i, arr) => arr.lastIndexOf(e) === i)
|
||||||
.sort((a, b) => a.displayName().localeCompare(b.displayName()));
|
.sort((a, b) => a.displayName().localeCompare(b.displayName()));
|
||||||
@@ -41,7 +41,7 @@ export default class UsersSearchSource extends SearchSource {
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
<li className="Dropdown-header">{app.translator.trans('core.forum.search.users_heading')}</li>,
|
<li className="Dropdown-header">{app.translator.trans('core.forum.search.users_heading')}</li>,
|
||||||
results.map(user => {
|
results.map((user) => {
|
||||||
const name = username(user);
|
const name = username(user);
|
||||||
|
|
||||||
if (!name.children) {
|
if (!name.children) {
|
||||||
|
@@ -8,7 +8,7 @@ import Discussion from '../common/models/Discussion';
|
|||||||
import Post from '../common/models/Post';
|
import Post from '../common/models/Post';
|
||||||
import User from '../common/models/User';
|
import User from '../common/models/User';
|
||||||
|
|
||||||
export default app => {
|
export default (app) => {
|
||||||
app.routes = {
|
app.routes = {
|
||||||
index: { path: '/all', component: IndexPage },
|
index: { path: '/all', component: IndexPage },
|
||||||
|
|
||||||
|
@@ -24,10 +24,10 @@ export default {
|
|||||||
controls(discussion: Discussion, context: any): ItemList {
|
controls(discussion: Discussion, context: any): ItemList {
|
||||||
const items = new ItemList();
|
const items = new ItemList();
|
||||||
|
|
||||||
['user', 'moderation', 'destructive'].forEach(section => {
|
['user', 'moderation', 'destructive'].forEach((section) => {
|
||||||
const controls = this[section](discussion, context).toArray();
|
const controls = this[section](discussion, context).toArray();
|
||||||
if (controls.length) {
|
if (controls.length) {
|
||||||
controls.forEach(item => items.add(item.itemName, item));
|
controls.forEach((item) => items.add(item.itemName, item));
|
||||||
items.add(section + 'Separator', Separator.component());
|
items.add(section + 'Separator', Separator.component());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@@ -26,7 +26,7 @@ export default class KeyboardNavigatable {
|
|||||||
* This will be triggered by the Up key.
|
* This will be triggered by the Up key.
|
||||||
*/
|
*/
|
||||||
onUp(callback: KeyboardEventCallback): this {
|
onUp(callback: KeyboardEventCallback): this {
|
||||||
this.callbacks[38] = e => {
|
this.callbacks[38] = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
callback(e);
|
callback(e);
|
||||||
};
|
};
|
||||||
@@ -40,7 +40,7 @@ export default class KeyboardNavigatable {
|
|||||||
* This will be triggered by the Down key.
|
* This will be triggered by the Down key.
|
||||||
*/
|
*/
|
||||||
onDown(callback: KeyboardEventCallback): this {
|
onDown(callback: KeyboardEventCallback): this {
|
||||||
this.callbacks[40] = e => {
|
this.callbacks[40] = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
callback(e);
|
callback(e);
|
||||||
};
|
};
|
||||||
@@ -54,7 +54,7 @@ export default class KeyboardNavigatable {
|
|||||||
* This will be triggered by the Return and Tab keys..
|
* This will be triggered by the Return and Tab keys..
|
||||||
*/
|
*/
|
||||||
onSelect(callback: KeyboardEventCallback): this {
|
onSelect(callback: KeyboardEventCallback): this {
|
||||||
this.callbacks[9] = this.callbacks[13] = e => {
|
this.callbacks[9] = this.callbacks[13] = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
callback(e);
|
callback(e);
|
||||||
};
|
};
|
||||||
@@ -68,7 +68,7 @@ export default class KeyboardNavigatable {
|
|||||||
* This will be triggered by the Escape key.
|
* This will be triggered by the Escape key.
|
||||||
*/
|
*/
|
||||||
onCancel(callback: Function): this {
|
onCancel(callback: Function): this {
|
||||||
this.callbacks[27] = e => {
|
this.callbacks[27] = (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
callback(e);
|
callback(e);
|
||||||
@@ -83,7 +83,7 @@ export default class KeyboardNavigatable {
|
|||||||
* This will be triggered by the Backspace key.
|
* This will be triggered by the Backspace key.
|
||||||
*/
|
*/
|
||||||
onRemove(callback: Function): this {
|
onRemove(callback: Function): this {
|
||||||
this.callbacks[8] = e => {
|
this.callbacks[8] = (e) => {
|
||||||
if (e.target.selectionStart === 0 && e.target.selectionEnd === 0) {
|
if (e.target.selectionStart === 0 && e.target.selectionEnd === 0) {
|
||||||
callback(e);
|
callback(e);
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@@ -23,11 +23,11 @@ export default {
|
|||||||
controls(post: Post, context: any) {
|
controls(post: Post, context: any) {
|
||||||
const items = new ItemList();
|
const items = new ItemList();
|
||||||
|
|
||||||
['user', 'moderation', 'destructive'].forEach(section => {
|
['user', 'moderation', 'destructive'].forEach((section) => {
|
||||||
const controls = this[section](post, context).toArray();
|
const controls = this[section](post, context).toArray();
|
||||||
|
|
||||||
if (controls.length) {
|
if (controls.length) {
|
||||||
controls.forEach(item => items.add(item.itemName, item));
|
controls.forEach((item) => items.add(item.itemName, item));
|
||||||
items.add(section + 'Separator', Separator.component());
|
items.add(section + 'Separator', Separator.component());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -128,7 +128,7 @@ export default {
|
|||||||
* Open the composer to edit a post.
|
* Open the composer to edit a post.
|
||||||
*/
|
*/
|
||||||
editAction(this: Post) {
|
editAction(this: Post) {
|
||||||
return new Promise<EditPostComposer>(resolve => {
|
return new Promise<EditPostComposer>((resolve) => {
|
||||||
const component = new EditPostComposer({ post: this });
|
const component = new EditPostComposer({ post: this });
|
||||||
|
|
||||||
app.composer.load(component);
|
app.composer.load(component);
|
||||||
|
@@ -21,10 +21,10 @@ export default {
|
|||||||
controls(user: User, context: any): ItemList {
|
controls(user: User, context: any): ItemList {
|
||||||
const items = new ItemList();
|
const items = new ItemList();
|
||||||
|
|
||||||
['user', 'moderation', 'destructive'].forEach(section => {
|
['user', 'moderation', 'destructive'].forEach((section) => {
|
||||||
const controls = this[section](user, context).toArray();
|
const controls = this[section](user, context).toArray();
|
||||||
if (controls.length) {
|
if (controls.length) {
|
||||||
controls.forEach(item => items.add(item.itemName, item));
|
controls.forEach((item) => items.add(item.itemName, item));
|
||||||
items.add(section + 'Separator', Separator.component());
|
items.add(section + 'Separator', Separator.component());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user