mirror of
https://github.com/Sonny93/my-links.git
synced 2025-12-08 14:43:24 +00:00
refactor: controllers and models to adapt them to the previous version of my-links
This commit is contained in:
@@ -120,6 +120,7 @@ export default class CollectionsController {
|
|||||||
async getCollectionsByAuthorId(authorId: User['id']) {
|
async getCollectionsByAuthorId(authorId: User['id']) {
|
||||||
return await Collection.query()
|
return await Collection.query()
|
||||||
.where('author_id', authorId)
|
.where('author_id', authorId)
|
||||||
|
.orderBy('created_at')
|
||||||
.preload('links');
|
.preload('links');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ export default class UsersController {
|
|||||||
nickName,
|
nickName,
|
||||||
avatarUrl,
|
avatarUrl,
|
||||||
token,
|
token,
|
||||||
|
providerType: 'google',
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default class LogRequest {
|
|||||||
!request.url().startsWith('/@react-refresh') &&
|
!request.url().startsWith('/@react-refresh') &&
|
||||||
!request.url().includes('.ts')
|
!request.url().includes('.ts')
|
||||||
) {
|
) {
|
||||||
logger.info(`-> ${request.method()}: ${request.url()}`);
|
logger.info(`[${request.method()}]: ${request.url()}`);
|
||||||
}
|
}
|
||||||
await next();
|
await next();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +1,27 @@
|
|||||||
import { BaseModel, CamelCaseNamingStrategy, beforeCreate, column } from '@adonisjs/lucid/orm';
|
import {
|
||||||
|
BaseModel,
|
||||||
|
CamelCaseNamingStrategy,
|
||||||
|
column,
|
||||||
|
} from '@adonisjs/lucid/orm';
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
|
||||||
|
|
||||||
export default class AppBaseModel extends BaseModel {
|
export default class AppBaseModel extends BaseModel {
|
||||||
static namingStrategy = new CamelCaseNamingStrategy();
|
static namingStrategy = new CamelCaseNamingStrategy();
|
||||||
static selfAssignPrimaryKey = true;
|
static selfAssignPrimaryKey = true;
|
||||||
|
|
||||||
@column({ isPrimary: true })
|
@column({ isPrimary: true })
|
||||||
declare id: string; // UUID
|
declare id: number;
|
||||||
|
|
||||||
@column.dateTime({
|
@column.dateTime({
|
||||||
autoCreate: true,
|
autoCreate: true,
|
||||||
serializeAs: 'createdAt',
|
serializeAs: 'created_at',
|
||||||
})
|
})
|
||||||
declare createdAt: DateTime;
|
declare created_at: DateTime;
|
||||||
|
|
||||||
@column.dateTime({
|
@column.dateTime({
|
||||||
autoCreate: true,
|
autoCreate: true,
|
||||||
autoUpdate: true,
|
autoUpdate: true,
|
||||||
serializeAs: 'updatedAt',
|
serializeAs: 'updated_at',
|
||||||
})
|
})
|
||||||
declare updatedAt: DateTime;
|
declare updated_at: DateTime;
|
||||||
|
|
||||||
@beforeCreate()
|
|
||||||
static assignUuid(item: any) {
|
|
||||||
item.id = uuidv4();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ export default class Collection extends AppBaseModel {
|
|||||||
declare visibility: Visibility;
|
declare visibility: Visibility;
|
||||||
|
|
||||||
@column()
|
@column()
|
||||||
declare nextId: string;
|
declare next_id: number;
|
||||||
|
|
||||||
@column()
|
@column()
|
||||||
declare authorId: string;
|
declare authorId: number;
|
||||||
|
|
||||||
@belongsTo(() => User, { foreignKey: 'authorId' })
|
@belongsTo(() => User, { foreignKey: 'authorId' })
|
||||||
declare author: BelongsTo<typeof User>;
|
declare author: BelongsTo<typeof User>;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export default class Link extends AppBaseModel {
|
|||||||
declare name: string;
|
declare name: string;
|
||||||
|
|
||||||
@column()
|
@column()
|
||||||
declare description: string;
|
declare description: string | null;
|
||||||
|
|
||||||
@column()
|
@column()
|
||||||
declare url: string;
|
declare url: string;
|
||||||
@@ -18,13 +18,13 @@ export default class Link extends AppBaseModel {
|
|||||||
declare favorite: boolean;
|
declare favorite: boolean;
|
||||||
|
|
||||||
@column()
|
@column()
|
||||||
declare collectionId: string;
|
declare collectionId: number;
|
||||||
|
|
||||||
@belongsTo(() => Collection, { foreignKey: 'collectionId' })
|
@belongsTo(() => Collection, { foreignKey: 'collectionId' })
|
||||||
declare collection: BelongsTo<typeof Collection>;
|
declare collection: BelongsTo<typeof Collection>;
|
||||||
|
|
||||||
@column()
|
@column()
|
||||||
declare authorId: string;
|
declare authorId: number;
|
||||||
|
|
||||||
@belongsTo(() => User, { foreignKey: 'authorId' })
|
@belongsTo(() => User, { foreignKey: 'authorId' })
|
||||||
declare author: BelongsTo<typeof User>;
|
declare author: BelongsTo<typeof User>;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import Collection from '#models/collection';
|
import Collection from '#models/collection';
|
||||||
import Link from '#models/link';
|
import Link from '#models/link';
|
||||||
import type { GoogleToken } from '@adonisjs/ally/types';
|
import type { GoogleToken } from '@adonisjs/ally/types';
|
||||||
import { column, manyToMany } from '@adonisjs/lucid/orm';
|
import { column, computed, manyToMany } from '@adonisjs/lucid/orm';
|
||||||
import type { ManyToMany } from '@adonisjs/lucid/types/relations';
|
import type { ManyToMany } from '@adonisjs/lucid/types/relations';
|
||||||
import AppBaseModel from './app_base_model.js';
|
import AppBaseModel from './app_base_model.js';
|
||||||
|
|
||||||
@@ -12,20 +12,23 @@ export default class User extends AppBaseModel {
|
|||||||
@column()
|
@column()
|
||||||
declare name: string;
|
declare name: string;
|
||||||
|
|
||||||
@column({ serializeAs: 'nickName' })
|
@column()
|
||||||
declare nickName: string; // public username
|
declare nickName: string; // public username
|
||||||
|
|
||||||
@column({ serializeAs: 'avatarUrl' })
|
@column()
|
||||||
declare avatarUrl: string;
|
declare avatarUrl: string;
|
||||||
|
|
||||||
@column()
|
@column()
|
||||||
declare isAdmin: boolean;
|
declare isAdmin: boolean;
|
||||||
|
|
||||||
@column({ serializeAs: null })
|
@column({ serializeAs: null })
|
||||||
declare token: GoogleToken;
|
declare token?: GoogleToken;
|
||||||
|
|
||||||
@column({ serializeAs: null })
|
@column({ serializeAs: null })
|
||||||
declare providerId: string;
|
declare providerId: number;
|
||||||
|
|
||||||
|
@column({ serializeAs: null })
|
||||||
|
declare providerType: 'google';
|
||||||
|
|
||||||
@manyToMany(() => Collection, {
|
@manyToMany(() => Collection, {
|
||||||
relatedKey: 'authorId',
|
relatedKey: 'authorId',
|
||||||
@@ -36,4 +39,9 @@ export default class User extends AppBaseModel {
|
|||||||
relatedKey: 'authorId',
|
relatedKey: 'authorId',
|
||||||
})
|
})
|
||||||
declare links: ManyToMany<typeof Link>;
|
declare links: ManyToMany<typeof Link>;
|
||||||
|
|
||||||
|
@computed()
|
||||||
|
get fullname() {
|
||||||
|
return this.nickName || this.name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import vine, { SimpleMessagesProvider } from '@vinejs/vine';
|
|||||||
import { Visibility } from '../enums/visibility.js';
|
import { Visibility } from '../enums/visibility.js';
|
||||||
|
|
||||||
const params = vine.object({
|
const params = vine.object({
|
||||||
id: vine.string().trim(),
|
id: vine.number(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const createCollectionValidator = vine.compile(
|
export const createCollectionValidator = vine.compile(
|
||||||
@@ -10,7 +10,7 @@ export const createCollectionValidator = vine.compile(
|
|||||||
name: vine.string().trim().minLength(1).maxLength(254),
|
name: vine.string().trim().minLength(1).maxLength(254),
|
||||||
description: vine.string().trim().maxLength(254).nullable(),
|
description: vine.string().trim().maxLength(254).nullable(),
|
||||||
visibility: vine.enum(Visibility),
|
visibility: vine.enum(Visibility),
|
||||||
nextId: vine.string().optional(),
|
nextId: vine.number(),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ export const updateCollectionValidator = vine.compile(
|
|||||||
name: vine.string().trim().minLength(1).maxLength(254),
|
name: vine.string().trim().minLength(1).maxLength(254),
|
||||||
description: vine.string().trim().maxLength(254).nullable(),
|
description: vine.string().trim().maxLength(254).nullable(),
|
||||||
visibility: vine.enum(Visibility),
|
visibility: vine.enum(Visibility),
|
||||||
nextId: vine.string().optional(),
|
nextId: vine.number(),
|
||||||
|
|
||||||
params,
|
params,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import vine from '@vinejs/vine';
|
import vine from '@vinejs/vine';
|
||||||
|
|
||||||
const params = vine.object({
|
const params = vine.object({
|
||||||
id: vine.string().trim(),
|
id: vine.number(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const createLinkValidator = vine.compile(
|
export const createLinkValidator = vine.compile(
|
||||||
@@ -10,7 +10,7 @@ export const createLinkValidator = vine.compile(
|
|||||||
description: vine.string().trim().maxLength(300).optional(),
|
description: vine.string().trim().maxLength(300).optional(),
|
||||||
url: vine.string().trim(),
|
url: vine.string().trim(),
|
||||||
favorite: vine.boolean(),
|
favorite: vine.boolean(),
|
||||||
collectionId: vine.string().trim(),
|
collectionId: vine.number(),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ export const updateLinkValidator = vine.compile(
|
|||||||
description: vine.string().trim().maxLength(300).optional(),
|
description: vine.string().trim().maxLength(300).optional(),
|
||||||
url: vine.string().trim(),
|
url: vine.string().trim(),
|
||||||
favorite: vine.boolean(),
|
favorite: vine.boolean(),
|
||||||
collectionId: vine.string().trim(),
|
collectionId: vine.number(),
|
||||||
|
|
||||||
params,
|
params,
|
||||||
})
|
})
|
||||||
@@ -37,7 +37,7 @@ export const updateLinkFavoriteStatusValidator = vine.compile(
|
|||||||
favorite: vine.boolean(),
|
favorite: vine.boolean(),
|
||||||
|
|
||||||
params: vine.object({
|
params: vine.object({
|
||||||
id: vine.string().trim(),
|
id: vine.number(),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
9
app/validators/search.ts
Normal file
9
app/validators/search.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import vine from '@vinejs/vine';
|
||||||
|
|
||||||
|
export const searchValidator = vine.compile(
|
||||||
|
vine.object({
|
||||||
|
searchTerm: vine.string().trim().minLength(1).maxLength(254),
|
||||||
|
links: vine.boolean(),
|
||||||
|
collections: vine.boolean(),
|
||||||
|
})
|
||||||
|
);
|
||||||
8
database/default_table_fields.ts
Normal file
8
database/default_table_fields.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { Knex } from 'knex';
|
||||||
|
|
||||||
|
export function defaultTableFields(table: Knex.CreateTableBuilder) {
|
||||||
|
table.increments('id', { primaryKey: true }).first().unique().notNullable();
|
||||||
|
|
||||||
|
table.timestamp('created_at').notNullable();
|
||||||
|
table.timestamp('updated_at').nullable();
|
||||||
|
}
|
||||||
@@ -1,27 +1,26 @@
|
|||||||
|
import { defaultTableFields } from '#database/default_table_fields';
|
||||||
import { BaseSchema } from '@adonisjs/lucid/schema';
|
import { BaseSchema } from '@adonisjs/lucid/schema';
|
||||||
|
|
||||||
export default class extends BaseSchema {
|
export default class CreateUsersTable extends BaseSchema {
|
||||||
protected tableName = 'users';
|
static tableName = 'users';
|
||||||
|
|
||||||
async up() {
|
async up() {
|
||||||
this.schema.createTable(this.tableName, (table) => {
|
this.schema.createTableIfNotExists(CreateUsersTable.tableName, (table) => {
|
||||||
table.uuid('id').primary().unique().notNullable();
|
|
||||||
|
|
||||||
table.string('email', 254).notNullable().unique();
|
table.string('email', 254).notNullable().unique();
|
||||||
table.string('name', 254).notNullable();
|
table.string('name', 254).notNullable();
|
||||||
table.string('nick_name', 254).notNullable();
|
table.string('nick_name', 254).nullable();
|
||||||
table.text('avatar_url').notNullable();
|
table.text('avatar_url').notNullable();
|
||||||
table.boolean('is_admin').defaultTo(0).notNullable();
|
table.boolean('is_admin').defaultTo(0).notNullable();
|
||||||
|
|
||||||
table.json('token').notNullable();
|
table.json('token').nullable();
|
||||||
table.string('provider_id').notNullable();
|
table.string('provider_id').notNullable();
|
||||||
|
table.enum('provider_type', ['google']).notNullable().defaultTo('google');
|
||||||
|
|
||||||
table.timestamp('created_at').notNullable();
|
defaultTableFields(table);
|
||||||
table.timestamp('updated_at').nullable();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async down() {
|
async down() {
|
||||||
this.schema.dropTable(this.tableName);
|
this.schema.dropTable(CreateUsersTable.tableName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,44 @@
|
|||||||
|
import { defaultTableFields } from '#database/default_table_fields';
|
||||||
import { BaseSchema } from '@adonisjs/lucid/schema';
|
import { BaseSchema } from '@adonisjs/lucid/schema';
|
||||||
import { Visibility } from '../../app/enums/visibility.js';
|
import { Visibility } from '../../app/enums/visibility.js';
|
||||||
|
|
||||||
export default class extends BaseSchema {
|
export default class CreateCollectionTable extends BaseSchema {
|
||||||
protected tableName = 'collections';
|
static tableName = 'collections';
|
||||||
private visibilityEnumName = 'collection_visibility';
|
private visibilityEnumName = 'collection_visibility';
|
||||||
|
|
||||||
async up() {
|
async up() {
|
||||||
this.schema.raw(`DROP TYPE IF EXISTS ${this.visibilityEnumName}`);
|
this.schema.raw(`DROP TYPE IF EXISTS ${this.visibilityEnumName}`);
|
||||||
this.schema.createTable(this.tableName, (table) => {
|
this.schema.createTableIfNotExists(
|
||||||
table.uuid('id').primary().unique().notNullable();
|
CreateCollectionTable.tableName,
|
||||||
|
(table) => {
|
||||||
|
table.string('name', 254).notNullable();
|
||||||
|
table.string('description', 254).nullable();
|
||||||
|
table
|
||||||
|
.enum('visibility', Object.values(Visibility), {
|
||||||
|
useNative: true,
|
||||||
|
enumName: this.visibilityEnumName,
|
||||||
|
existingType: false,
|
||||||
|
})
|
||||||
|
.nullable()
|
||||||
|
.defaultTo(Visibility.PRIVATE);
|
||||||
|
table
|
||||||
|
.integer('next_id')
|
||||||
|
.references('id')
|
||||||
|
.inTable('collections')
|
||||||
|
.defaultTo(null);
|
||||||
|
table
|
||||||
|
.integer('author_id')
|
||||||
|
.references('id')
|
||||||
|
.inTable('users')
|
||||||
|
.onDelete('CASCADE');
|
||||||
|
|
||||||
table.string('name', 254).notNullable();
|
defaultTableFields(table);
|
||||||
table.string('description', 254);
|
}
|
||||||
table
|
);
|
||||||
.uuid('next_id')
|
|
||||||
.references('id')
|
|
||||||
.inTable('collections')
|
|
||||||
.defaultTo(null);
|
|
||||||
table
|
|
||||||
.uuid('author_id')
|
|
||||||
.references('id')
|
|
||||||
.inTable('users')
|
|
||||||
.onDelete('CASCADE');
|
|
||||||
table.enum('visibility', Object.values(Visibility), {
|
|
||||||
useNative: true,
|
|
||||||
enumName: this.visibilityEnumName,
|
|
||||||
existingType: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
table.timestamp('created_at');
|
|
||||||
table.timestamp('updated_at');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async down() {
|
async down() {
|
||||||
this.schema.raw(`DROP TYPE IF EXISTS ${this.visibilityEnumName}`);
|
this.schema.raw(`DROP TYPE IF EXISTS ${this.visibilityEnumName}`);
|
||||||
this.schema.dropTable(this.tableName);
|
this.schema.dropTable(CreateCollectionTable.tableName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +1,31 @@
|
|||||||
|
import { defaultTableFields } from '#database/default_table_fields';
|
||||||
import { BaseSchema } from '@adonisjs/lucid/schema';
|
import { BaseSchema } from '@adonisjs/lucid/schema';
|
||||||
|
|
||||||
export default class extends BaseSchema {
|
export default class CreateLinksTable extends BaseSchema {
|
||||||
protected tableName = 'links';
|
static tableName = 'links';
|
||||||
|
|
||||||
async up() {
|
async up() {
|
||||||
this.schema.createTable(this.tableName, (table) => {
|
this.schema.createTableIfNotExists(CreateLinksTable.tableName, (table) => {
|
||||||
table.uuid('id').primary().unique().notNullable();
|
|
||||||
|
|
||||||
table.string('name', 254).notNullable();
|
table.string('name', 254).notNullable();
|
||||||
table.string('description', 254);
|
table.string('description', 254).nullable();
|
||||||
table.text('url').notNullable();
|
table.text('url').notNullable();
|
||||||
table.boolean('favorite').notNullable().defaultTo(0);
|
table.boolean('favorite').notNullable().defaultTo(0);
|
||||||
table
|
table
|
||||||
.uuid('collection_id')
|
.integer('collection_id')
|
||||||
.references('id')
|
.references('id')
|
||||||
.inTable('collections')
|
.inTable('collections')
|
||||||
.onDelete('CASCADE');
|
.onDelete('CASCADE');
|
||||||
table
|
table
|
||||||
.uuid('author_id')
|
.integer('author_id')
|
||||||
.references('id')
|
.references('id')
|
||||||
.inTable('users')
|
.inTable('users')
|
||||||
.onDelete('CASCADE');
|
.onDelete('CASCADE');
|
||||||
|
|
||||||
table.timestamp('created_at');
|
defaultTableFields(table);
|
||||||
table.timestamp('updated_at');
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async down() {
|
async down() {
|
||||||
this.schema.dropTable(this.tableName);
|
this.schema.dropTable(CreateLinksTable.tableName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,13 +16,14 @@ export default class extends BaseSeeder {
|
|||||||
|
|
||||||
export function createRandomUser() {
|
export function createRandomUser() {
|
||||||
return {
|
return {
|
||||||
id: faker.string.uuid(),
|
id: faker.number.int(),
|
||||||
email: faker.internet.email(),
|
email: faker.internet.email(),
|
||||||
name: faker.internet.userName(),
|
name: faker.internet.userName(),
|
||||||
nickName: faker.internet.displayName(),
|
nickName: faker.internet.displayName(),
|
||||||
avatarUrl: faker.image.avatar(),
|
avatarUrl: faker.image.avatar(),
|
||||||
isAdmin: false,
|
isAdmin: false,
|
||||||
providerId: faker.string.uuid(),
|
providerId: faker.number.int(),
|
||||||
|
providerType: 'google' as const,
|
||||||
token: {} as GoogleToken,
|
token: {} as GoogleToken,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import useUser from '~/hooks/use_user';
|
|||||||
|
|
||||||
export default function UserCard() {
|
export default function UserCard() {
|
||||||
const { user, isAuthenticated } = useUser();
|
const { user, isAuthenticated } = useUser();
|
||||||
const altImage = `${user?.nickName}'s avatar`;
|
const altImage = `${user?.fullname}'s avatar`;
|
||||||
return (
|
return (
|
||||||
isAuthenticated && (
|
isAuthenticated && (
|
||||||
<Item className="disable-hover">
|
<Item className="disable-hover">
|
||||||
@@ -14,7 +14,7 @@ export default function UserCard() {
|
|||||||
alt={altImage}
|
alt={altImage}
|
||||||
referrerPolicy="no-referrer"
|
referrerPolicy="no-referrer"
|
||||||
/>
|
/>
|
||||||
{user.nickName}
|
{user.fullname}
|
||||||
</Item>
|
</Item>
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ function ProfileDropdown() {
|
|||||||
width={22}
|
width={22}
|
||||||
referrerPolicy="no-referrer"
|
referrerPolicy="no-referrer"
|
||||||
/>
|
/>
|
||||||
{user!.nickName}
|
{user!.fullname}
|
||||||
</UserCard>
|
</UserCard>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Link } from '@inertiajs/react';
|
import { Link } from '@inertiajs/react';
|
||||||
import { route } from '@izzyjs/route/client';
|
import { route } from '@izzyjs/route/client';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { BsGear } from 'react-icons/bs';
|
import { PiGearLight } from 'react-icons/pi';
|
||||||
import Modal from '~/components/common/modal/modal';
|
import Modal from '~/components/common/modal/modal';
|
||||||
import LangSelector from '~/components/lang_selector';
|
import LangSelector from '~/components/lang_selector';
|
||||||
import ThemeSwitcher from '~/components/theme_switcher';
|
import ThemeSwitcher from '~/components/theme_switcher';
|
||||||
@@ -20,7 +20,7 @@ export default function ModalSettings({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<OpenItem onClick={open}>
|
<OpenItem onClick={open}>
|
||||||
<BsGear />
|
<PiGearLight />
|
||||||
{t('settings')}
|
{t('settings')}
|
||||||
</OpenItem>
|
</OpenItem>
|
||||||
<Modal title={t('settings')} opened={isShowing} close={close}>
|
<Modal title={t('settings')} opened={isShowing} close={close}>
|
||||||
|
|||||||
3
inertia/types/app.d.ts
vendored
3
inertia/types/app.d.ts
vendored
@@ -1,10 +1,11 @@
|
|||||||
import type Collection from '#models/collection';
|
import type Collection from '#models/collection';
|
||||||
|
|
||||||
type User = {
|
type User = {
|
||||||
id: string;
|
id: number;
|
||||||
email: string;
|
email: string;
|
||||||
name: string;
|
name: string;
|
||||||
nickName: string;
|
nickName: string;
|
||||||
|
fullname: string;
|
||||||
avatarUrl: string;
|
avatarUrl: string;
|
||||||
isAdmin: boolean;
|
isAdmin: boolean;
|
||||||
collections: Collection[];
|
collections: Collection[];
|
||||||
|
|||||||
Reference in New Issue
Block a user