Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typescript for models #3174

Merged
merged 18 commits into from
Dec 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions js/src/@types/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@ declare const app: never;
declare const m: import('mithril').Static;
declare const dayjs: typeof import('dayjs');

/**
* From https://github.com/lokesh/color-thief/issues/188
*/
declare module 'color-thief-browser' {
type Color = [number, number, number];
export default class ColorThief {
getColor: (img: HTMLImageElement | null) => Color;
getPalette: (img: HTMLImageElement | null) => Color[];
}
}

type ESModule = { __esModule: true; [key: string]: unknown };

/**
Expand Down
4 changes: 2 additions & 2 deletions js/src/admin/AdminApplication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ export default class AdminApplication extends Application {
history = {
canGoBack: () => true,
getPrevious: () => {},
backUrl: () => this.forum.attribute('baseUrl'),
backUrl: () => this.forum.attribute<string>('baseUrl'),
back: function () {
window.location = this.backUrl();
window.location.assign(this.backUrl());
},
};

Expand Down
24 changes: 7 additions & 17 deletions js/src/admin/components/UserListPage.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type Mithril from 'mithril';

import app from '../../admin/app';

import EditUserModal from '../../common/components/EditUserModal';
Expand All @@ -14,7 +16,6 @@ import classList from '../../common/utils/classList';
import extractText from '../../common/utils/extractText';

import AdminPage from './AdminPage';
import Mithril from 'mithril';

type ColumnData = {
/**
Expand All @@ -24,20 +25,9 @@ type ColumnData = {
/**
* Component(s) to show for this column.
*/
content: (user: User) => JSX.Element;
};

type ApiPayload = {
data: Record<string, unknown>[];
included: Record<string, unknown>[];
links: {
first: string;
next?: string;
};
content: (user: User) => Mithril.Children;
};

type UsersApiResponse = User[] & { payload: ApiPayload };

/**
* Admin page which displays a paginated list of all users on the forum.
*/
Expand Down Expand Up @@ -185,7 +175,7 @@ export default class UserListPage extends AdminPage {
'id',
{
name: app.translator.trans('core.admin.users.grid.columns.user_id.title'),
content: (user: User) => user.id(),
content: (user: User) => user.id() ?? '',
},
100
);
Expand Down Expand Up @@ -348,15 +338,15 @@ export default class UserListPage extends AdminPage {
if (pageNumber < 0) pageNumber = 0;

app.store
.find('users', {
.find<User[]>('users', {
page: {
limit: this.numPerPage,
offset: pageNumber * this.numPerPage,
},
})
.then((apiData: UsersApiResponse) => {
.then((apiData) => {
// Next link won't be present if there's no more data
this.moreData = !!apiData.payload.links.next;
this.moreData = !!apiData.payload?.links?.next;

let data = apiData;

Expand Down
21 changes: 13 additions & 8 deletions js/src/common/Application.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import ModalManager from './components/ModalManager';
import AlertManager from './components/AlertManager';
import RequestErrorModal from './components/RequestErrorModal';
import Translator from './Translator';
import Store from './Store';
import Store, { ApiPayload, ApiResponse, ApiResponsePlural, ApiResponseSingle, payloadIsPlural } from './Store';
import Session from './Session';
import extract from './utils/extract';
import Drawer from './utils/Drawer';
Expand All @@ -31,6 +31,7 @@ import type DefaultResolver from './resolvers/DefaultResolver';
import type Mithril from 'mithril';
import type Component from './Component';
import type { ComponentAttrs } from './Component';
import Model, { SavedModelData } from './Model';

export type FlarumScreens = 'phone' | 'tablet' | 'desktop' | 'desktop-hd';

Expand Down Expand Up @@ -210,10 +211,10 @@ export default class Application {
drawer!: Drawer;

data!: {
apiDocument: Record<string, unknown> | null;
apiDocument: ApiPayload | null;
locale: string;
locales: Record<string, string>;
resources: Record<string, unknown>[];
resources: SavedModelData[];
session: { userId: number; csrfToken: string };
[key: string]: unknown;
};
Expand Down Expand Up @@ -255,9 +256,9 @@ export default class Application {

this.store.pushPayload({ data: this.data.resources });

this.forum = this.store.getById('forums', 1);
this.forum = this.store.getById('forums', '1')!;

this.session = new Session(this.store.getById('users', this.data.session.userId), this.data.session.csrfToken);
this.session = new Session(this.store.getById<User>('users', String(this.data.session.userId)) ?? null, this.data.session.csrfToken);

this.mount();

Expand Down Expand Up @@ -317,10 +318,14 @@ export default class Application {
/**
* Get the API response document that has been preloaded into the application.
*/
preloadedApiDocument(): Record<string, unknown> | null {
preloadedApiDocument<M extends Model>(): ApiResponseSingle<M> | null;
preloadedApiDocument<Ms extends Model[]>(): ApiResponsePlural<Ms[number]> | null;
preloadedApiDocument<M extends Model | Model[]>(): ApiResponse<FlatArray<M, 1>> | null {
// If the URL has changed, the preloaded Api document is invalid.
if (this.data.apiDocument && window.location.href === this.initialRoute) {
const results = this.store.pushPayload(this.data.apiDocument);
const results = payloadIsPlural(this.data.apiDocument)
? this.store.pushPayload<FlatArray<M, 1>[]>(this.data.apiDocument)
: this.store.pushPayload<FlatArray<M, 1>>(this.data.apiDocument);

this.data.apiDocument = null;

Expand Down Expand Up @@ -450,7 +455,7 @@ export default class Application {
* @param options
* @return {Promise}
*/
request<ResponseType>(originalOptions: FlarumRequestOptions<ResponseType>): Promise<ResponseType | string> {
request<ResponseType>(originalOptions: FlarumRequestOptions<ResponseType>): Promise<ResponseType> {
const options = this.transformRequestOptions(originalOptions);

if (this.requestErrorAlert) this.alerts.dismiss(this.requestErrorAlert);
Expand Down
Loading