Hangar/frontend/plugins/utils.ts

145 lines
4.5 KiB
TypeScript
Raw Normal View History

2021-02-06 00:56:21 +08:00
import { Context } from '@nuxt/types';
import { Inject } from '@nuxt/types/app';
import { AxiosError } from 'axios';
import { HangarException, User } from 'hangar-api';
import { NamedPermission } from '~/types/enums';
import { RootState } from '~/store';
2021-02-06 03:50:18 +08:00
import { ErrorPayload } from '~/store/snackbar';
2021-01-23 02:44:49 +08:00
2021-02-05 14:51:51 +08:00
type Validation = (v: string) => boolean | string;
type ValidationArgument = (field?: string) => Validation;
2021-02-06 00:56:21 +08:00
const createUtil = ({ store, error }: Context) => {
2021-01-23 02:44:49 +08:00
class Util {
2021-02-05 23:29:14 +08:00
dummyUser(): User {
return {
2021-02-06 00:56:21 +08:00
name: 'Dummy',
2021-02-05 23:29:14 +08:00
id: 42,
tagline: null,
createdAt: this.prettyDate(new Date()),
roles: [],
headerData: {
2021-02-06 00:56:21 +08:00
globalPermission: '',
2021-02-05 23:29:14 +08:00
hasNotice: true,
hasProjectApprovals: true,
hasReviewQueue: true,
hasUnreadNotifications: true,
2021-02-06 00:56:21 +08:00
unresolvedFlags: true,
2021-02-05 23:29:14 +08:00
},
2021-02-06 00:56:21 +08:00
joinDate: this.prettyDate(new Date()),
};
2021-02-05 23:29:14 +08:00
}
avatarUrl(_name: string): string {
2021-01-23 02:44:49 +08:00
return 'https://paper.readthedocs.io/en/latest/_images/papermc_logomark_500.png';
// TODO avatar url
// return '/avatar/' + name + '?size=120x120';
}
2021-02-05 23:29:14 +08:00
forumUrl(name: string): string {
2021-01-23 02:44:49 +08:00
return 'https://papermc.io/forums/u/' + name;
}
2021-02-05 23:29:14 +08:00
prettyDate(date: Date): string {
2021-02-05 04:30:47 +08:00
return date.toLocaleDateString(undefined, {
day: 'numeric',
month: 'long',
year: 'numeric',
});
2021-01-23 02:44:49 +08:00
}
2021-01-23 15:37:57 +08:00
2021-02-05 08:22:22 +08:00
/**
* Checks if the supplier permission has all named permissions.
* @param perms user permissions
* @param namedPermission perms required
*/
hasPerms(perms: bigint | string, ...namedPermission: NamedPermission[]): boolean {
2021-01-23 15:37:57 +08:00
let _perms: bigint;
2021-02-05 08:22:22 +08:00
let result = false;
for (const np of namedPermission) {
const perm = (store.state as RootState).permissions.get(np);
if (!perm) {
throw new Error(namedPermission + ' is not valid');
}
if (typeof perms === 'string') {
_perms = BigInt('0b' + perm.value);
} else {
_perms = perms;
}
result = result && (_perms & perm.permission) === perm.permission;
2021-01-23 15:37:57 +08:00
}
2021-02-05 08:22:22 +08:00
return result;
}
// TODO have boolean for doing error toast notification instead of error page;
handleAxiosError(err: AxiosError) {
if (err.response) {
// response outside of 2xx
const statusCode = err.response.status;
2021-02-06 15:45:13 +08:00
if (err.response.data.isHangarApiException || err.response.data.isHangarValidationException) {
2021-02-05 08:22:22 +08:00
const data: HangarException = err.response.data;
error({
2021-02-06 15:45:13 +08:00
statusCode: data.httpError.statusCode,
message: data.message,
2021-02-05 08:22:22 +08:00
});
} else {
error({
statusCode,
message: err.response.statusText,
});
}
2021-01-23 15:37:57 +08:00
} else {
2021-02-05 08:22:22 +08:00
error({
message: 'No response from the server: ' + err.message,
});
2021-01-23 15:37:57 +08:00
}
}
2021-02-05 14:51:51 +08:00
$vc: Record<string, ValidationArgument> = {
require: ((name: string = 'Field') => (v: string) => !!v || `${name} is required`) as ValidationArgument,
};
$v: Record<string, Validation> = {};
2021-02-06 03:50:18 +08:00
error(err: string | ErrorPayload) {
if (typeof err === 'string') {
store.dispatch('snackbar/SHOW_ERROR', { message: err });
} else {
store.dispatch('snackbar/SHOW_ERROR', err);
}
}
2021-01-23 02:44:49 +08:00
}
return new Util();
};
type utilType = ReturnType<typeof createUtil>;
declare module 'vue/types/vue' {
interface Vue {
$util: utilType;
}
}
declare module '@nuxt/types' {
interface NuxtAppOptions {
$util: utilType;
}
interface Context {
$util: utilType;
}
}
declare module 'vuex/types/index' {
2021-01-31 10:00:11 +08:00
// eslint-disable-next-line no-unused-vars,@typescript-eslint/no-unused-vars
2021-01-23 02:44:49 +08:00
interface Store<S> {
$util: utilType;
}
}
export default (ctx: Context, inject: Inject) => {
inject('util', createUtil(ctx));
};