mirror of
https://github.com/flarum/core.git
synced 2025-08-07 08:56:38 +02:00
Added some more type hinting, changed arguments for computed util
This commit is contained in:
@@ -12,6 +12,8 @@
|
|||||||
- `app.bus` for some event hooking
|
- `app.bus` for some event hooking
|
||||||
* Translator
|
* Translator
|
||||||
- Added `app.translator.transText`, automatically extracts text from `translator.trans` output
|
- Added `app.translator.transText`, automatically extracts text from `translator.trans` output
|
||||||
|
* Utils
|
||||||
|
- Changed `computed` util to require multiple keys to be passed as an array
|
||||||
|
|
||||||
#### Forum
|
#### Forum
|
||||||
* Forum Application
|
* Forum Application
|
||||||
|
12
js/dist/admin.js
vendored
12
js/dist/admin.js
vendored
File diff suppressed because one or more lines are too long
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
8
js/dist/forum.js
vendored
8
js/dist/forum.js
vendored
File diff suppressed because one or more lines are too long
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
@@ -65,7 +65,9 @@ export default abstract class Application {
|
|||||||
* A local cache that can be used to store data at the application level, so
|
* A local cache that can be used to store data at the application level, so
|
||||||
* that is persists between different routes.
|
* that is persists between different routes.
|
||||||
*/
|
*/
|
||||||
cache = {};
|
cache = {
|
||||||
|
notifications: null,
|
||||||
|
};
|
||||||
|
|
||||||
routes = {};
|
routes = {};
|
||||||
|
|
||||||
|
@@ -107,7 +107,7 @@ export default class Model {
|
|||||||
* @param [options]
|
* @param [options]
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
save(attributes: any, options: any = {}): Promise {
|
save(attributes: any, options: any = {}): Promise<Model|Model[]> {
|
||||||
const data = {
|
const data = {
|
||||||
type: this.data.type,
|
type: this.data.type,
|
||||||
id: this.data.id,
|
id: this.data.id,
|
||||||
@@ -162,7 +162,7 @@ export default class Model {
|
|||||||
// 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.lazyRedraw();
|
m.redraw();
|
||||||
throw response;
|
throw response;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -171,13 +171,13 @@ export default class Model {
|
|||||||
/**
|
/**
|
||||||
* Send a request to delete the resource.
|
* Send a request to delete the resource.
|
||||||
*
|
*
|
||||||
* @param {Object} data Data to send along with the DELETE request.
|
* @param {Object} body Data to send along with the DELETE request.
|
||||||
* @param {Object} [options]
|
* @param {Object} [options]
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
delete(body, options = {}) {
|
delete(body = {}, options = {}) {
|
||||||
if (!this.exists) return m.deferred.resolve().promise;
|
if (!this.exists) return Promise.resolve();
|
||||||
|
|
||||||
return app.request(Object.assign({
|
return app.request(Object.assign({
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
|
@@ -24,7 +24,7 @@ export default class Session {
|
|||||||
/**
|
/**
|
||||||
* Attempt to log in a user.
|
* Attempt to log in a user.
|
||||||
*/
|
*/
|
||||||
login(body: { identification: string, password: string }, options = {}) {
|
login(body: { identification: string, password: string, remember?: string }, options = {}) {
|
||||||
return app.request(Object.assign({
|
return app.request(Object.assign({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: `${app.forum.attribute('baseUrl')}/login`,
|
url: `${app.forum.attribute('baseUrl')}/login`,
|
||||||
|
@@ -9,7 +9,7 @@ export default class Store {
|
|||||||
* The local data store. A tree of resource types to IDs, such that
|
* The local data store. A tree of resource types to IDs, such that
|
||||||
* accessing data[type][id] will return the model for that type/ID.
|
* accessing data[type][id] will return the model for that type/ID.
|
||||||
*/
|
*/
|
||||||
protected data: { [key: string]: { [key: number]: Model }} = {};
|
data: { [key: string]: { [key: number]: Model }} = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The model registry. A map of resource types to the model class that
|
* The model registry. A map of resource types to the model class that
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
import Mithril from 'mithril';
|
||||||
|
|
||||||
import Component, {ComponentProps} from '../Component';
|
import Component, {ComponentProps} from '../Component';
|
||||||
import Button from './Button';
|
import Button from './Button';
|
||||||
import RequestError from "../utils/RequestError";
|
import RequestError from "../utils/RequestError";
|
||||||
|
@@ -17,8 +17,6 @@ export default class ModalManager extends Component {
|
|||||||
super.oncreate(vnode);
|
super.oncreate(vnode);
|
||||||
|
|
||||||
app.modal = this;
|
app.modal = this;
|
||||||
|
|
||||||
window.vnode = vnode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
view() {
|
view() {
|
||||||
@@ -44,7 +42,7 @@ export default class ModalManager extends Component {
|
|||||||
|
|
||||||
// if (app.current) app.current.retain = true;
|
// if (app.current) app.current.retain = true;
|
||||||
|
|
||||||
m.redraw(true);
|
m.redraw();
|
||||||
|
|
||||||
if (!$('.modal-backdrop').length) {
|
if (!$('.modal-backdrop').length) {
|
||||||
$('<div />').addClass('modal-backdrop')
|
$('<div />').addClass('modal-backdrop')
|
||||||
@@ -99,7 +97,7 @@ export default class ModalManager extends Component {
|
|||||||
|
|
||||||
app.current.retain = false;
|
app.current.retain = false;
|
||||||
|
|
||||||
m.lazyRedraw();
|
m.redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -109,7 +107,7 @@ export default class ModalManager extends Component {
|
|||||||
*/
|
*/
|
||||||
onready() {
|
onready() {
|
||||||
if (this.component && this.component.onready) {
|
if (this.component && this.component.onready) {
|
||||||
this.component.onready(this.$());
|
this.component.onready();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -30,7 +30,7 @@ export default class User extends Model {
|
|||||||
canDelete = Model.attribute('canDelete') as () => boolean;
|
canDelete = Model.attribute('canDelete') as () => boolean;
|
||||||
|
|
||||||
avatarColor = null;
|
avatarColor = null;
|
||||||
color = computed('username', 'avatarUrl', 'avatarColor', function(username, avatarUrl, avatarColor) {
|
color = computed(['username', 'avatarUrl', 'avatarColor'], function(username, avatarUrl, avatarColor) {
|
||||||
// If we've already calculated and cached the dominant color of the user's
|
// 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
|
// 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
|
// to calculate it. Unless the user doesn't have an avatar, in which case
|
||||||
@@ -92,6 +92,6 @@ export default class User extends Model {
|
|||||||
|
|
||||||
Object.assign(preferences, newPreferences);
|
Object.assign(preferences, newPreferences);
|
||||||
|
|
||||||
return this.save({preferences});
|
return <Promise<User>> this.save({preferences});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,9 +6,8 @@
|
|||||||
* @param {function} compute The function which computes the value using the
|
* @param {function} compute The function which computes the value using the
|
||||||
* dependent values.
|
* dependent values.
|
||||||
*/
|
*/
|
||||||
export default function computed(...dependentKeys: string[]|Function[]): () => any {
|
export default function computed(dependentKeys: string|string[], compute: Function): () => any {
|
||||||
const keys = <string[]> dependentKeys.slice(0, -1);
|
const keys = Array.from(dependentKeys);
|
||||||
const compute = <Function> dependentKeys.slice(-1)[0];
|
|
||||||
|
|
||||||
const dependentValues = {};
|
const dependentValues = {};
|
||||||
let computedValue;
|
let computedValue;
|
||||||
|
@@ -1,9 +1,10 @@
|
|||||||
|
import m from 'mithril';
|
||||||
import prop from 'mithril/stream';
|
import prop from 'mithril/stream';
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const mo = global.m;
|
const mo = window['m'];
|
||||||
|
|
||||||
const m = function (comp, ...args) {
|
const _m = function (comp, ...args) {
|
||||||
const node = mo.apply(this, arguments);
|
const node = mo.apply(this, arguments);
|
||||||
|
|
||||||
if (!node.attrs) node.attrs = {};
|
if (!node.attrs) node.attrs = {};
|
||||||
@@ -22,13 +23,13 @@ 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) => function () {
|
_m.withAttr = (key: string, cb: Function) => function () {
|
||||||
cb(this.getAttribute(key) || this[key]);
|
cb(this.getAttribute(key) || this[key]);
|
||||||
};
|
};
|
||||||
|
|
||||||
m.prop = prop;
|
_m.prop = prop;
|
||||||
|
|
||||||
global.m = m;
|
window['m'] = _m;
|
||||||
}
|
}
|
||||||
|
@@ -4,8 +4,12 @@ import History from './utils/History';
|
|||||||
import HeaderPrimary from './components/HeaderPrimary';
|
import HeaderPrimary from './components/HeaderPrimary';
|
||||||
import HeaderSecondary from './components/HeaderSecondary';
|
import HeaderSecondary from './components/HeaderSecondary';
|
||||||
|
|
||||||
|
import Page from './components/Page';
|
||||||
import IndexPage from './components/IndexPage';
|
import IndexPage from './components/IndexPage';
|
||||||
import PostsUserPage from './components/PostsUserPage';
|
import PostsUserPage from './components/PostsUserPage';
|
||||||
|
import User from "../common/models/User";
|
||||||
|
import Post from "../common/models/Post";
|
||||||
|
import Discussion from "../common/models/Discussion";
|
||||||
|
|
||||||
export default class Forum extends Application {
|
export default class Forum extends Application {
|
||||||
routes = {
|
routes = {
|
||||||
@@ -26,6 +30,9 @@ export default class Forum extends Application {
|
|||||||
*/
|
*/
|
||||||
history: History = new History();
|
history: History = new History();
|
||||||
|
|
||||||
|
previous: Page;
|
||||||
|
current: Page;
|
||||||
|
|
||||||
mount() {
|
mount() {
|
||||||
// Get the configured default route and update that route's path to be '/'.
|
// Get the configured default route and update that route's path to be '/'.
|
||||||
// Push the homepage as the first route, so that the user will always be
|
// Push the homepage as the first route, so that the user will always be
|
||||||
@@ -72,7 +79,7 @@ export default class Forum extends Application {
|
|||||||
setupRoutes() {
|
setupRoutes() {
|
||||||
super.setupRoutes();
|
super.setupRoutes();
|
||||||
|
|
||||||
this.route.discussion = (discussion, near) => {
|
this.route.discussion = (discussion: Discussion, near?: number): string => {
|
||||||
const slug = discussion.slug();
|
const slug = discussion.slug();
|
||||||
return this.route(near && near !== 1 ? 'discussion.near' : 'discussion', {
|
return this.route(near && near !== 1 ? 'discussion.near' : 'discussion', {
|
||||||
id: discussion.id() + (slug.trim() ? '-' + slug : ''),
|
id: discussion.id() + (slug.trim() ? '-' + slug : ''),
|
||||||
@@ -82,21 +89,15 @@ export default class Forum extends Application {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a URL to a post.
|
* Generate a URL to a post.
|
||||||
*
|
|
||||||
* @param {Post} post
|
|
||||||
* @return {String}
|
|
||||||
*/
|
*/
|
||||||
this.route.post = post => {
|
this.route.post = (post: Post): string => {
|
||||||
return this.route.discussion(post.discussion(), post.number());
|
return this.route.discussion(post.discussion(), post.number());
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a URL to a user.
|
* Generate a URL to a user.
|
||||||
*
|
|
||||||
* @param {User} user
|
|
||||||
* @return {String}
|
|
||||||
*/
|
*/
|
||||||
this.route.user = user => {
|
this.route.user = (user: User): string => {
|
||||||
return this.route('user', {
|
return this.route('user', {
|
||||||
username: user.username()
|
username: user.username()
|
||||||
});
|
});
|
||||||
|
@@ -21,7 +21,7 @@ export default class DiscussionsSearchSource extends SearchSource {
|
|||||||
include: 'mostRelevantPost'
|
include: 'mostRelevantPost'
|
||||||
};
|
};
|
||||||
|
|
||||||
return app.store.find('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) {
|
||||||
|
@@ -158,7 +158,7 @@ export default class NotificationList extends Component {
|
|||||||
|
|
||||||
const params = app.cache.notifications ? {page: {offset: app.cache.notifications.length * 10}} : null;
|
const params = app.cache.notifications ? {page: {offset: app.cache.notifications.length * 10}} : null;
|
||||||
|
|
||||||
return app.store.find('notifications', params)
|
return app.store.find<Notification>('notifications', params)
|
||||||
.then(this.parseResults.bind(this))
|
.then(this.parseResults.bind(this))
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -170,7 +170,7 @@ export default class NotificationList extends Component {
|
|||||||
/**
|
/**
|
||||||
* Parse results and append them to the notification list.
|
* Parse results and append them to the notification list.
|
||||||
*/
|
*/
|
||||||
parseResults(results: Notification[]|any): Notification[]|any {
|
parseResults(results: Notification[]): Notification[] {
|
||||||
app.cache.notifications = app.cache.notifications || [];
|
app.cache.notifications = app.cache.notifications || [];
|
||||||
|
|
||||||
if (results.length) app.cache.notifications.push(results);
|
if (results.length) app.cache.notifications.push(results);
|
||||||
|
@@ -82,7 +82,7 @@ export default abstract class UserPage extends Page {
|
|||||||
|
|
||||||
this.username = lowercaseUsername;
|
this.username = lowercaseUsername;
|
||||||
|
|
||||||
app.store.all('users').some(user => {
|
app.store.all<User>('users').some(user => {
|
||||||
if (user.username().toLowerCase() === lowercaseUsername && user.joinTime()) {
|
if (user.username().toLowerCase() === lowercaseUsername && user.joinTime()) {
|
||||||
this.show(user);
|
this.show(user);
|
||||||
return true;
|
return true;
|
||||||
|
@@ -27,7 +27,7 @@ export default class UsersSearchSource extends SearchSource {
|
|||||||
query = query.toLowerCase();
|
query = query.toLowerCase();
|
||||||
|
|
||||||
const results = (this.results[query] || [])
|
const results = (this.results[query] || [])
|
||||||
.concat(app.store.all<User>('users').filter((user: User) => [user.username(), user.displayName()].some(value => value.toLowerCase().substr(0, query.length) === query)))
|
.concat(app.store.all<User>('users').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()));
|
||||||
|
|
||||||
|
@@ -75,8 +75,8 @@ export default {
|
|||||||
/**
|
/**
|
||||||
* Delete the user.
|
* Delete the user.
|
||||||
*/
|
*/
|
||||||
deleteAction() {
|
deleteAction(this: User) {
|
||||||
if (confirm(app.translator.trans('core.forum.user_controls.delete_confirmation'))) {
|
if (confirm(app.translator.transText('core.forum.user_controls.delete_confirmation'))) {
|
||||||
this.delete().then(() => {
|
this.delete().then(() => {
|
||||||
if (app.current instanceof UserPage && app.current.user === this) {
|
if (app.current instanceof UserPage && app.current.user === this) {
|
||||||
app.history.back();
|
app.history.back();
|
||||||
@@ -90,7 +90,7 @@ export default {
|
|||||||
/**
|
/**
|
||||||
* Edit the user.
|
* Edit the user.
|
||||||
*/
|
*/
|
||||||
editAction() {
|
editAction(this: User) {
|
||||||
app.modal.show(new EditUserModal({user: this}));
|
app.modal.show(new EditUserModal({user: this}));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user