mirror of
https://github.com/docmost/docmost.git
synced 2025-11-19 17:41:13 +10:00
refactor layout
* ui polishing * frontend and backend fixes
This commit is contained in:
@ -1,9 +1,19 @@
|
||||
import { IsBoolean, IsNumber, IsOptional, IsString } from 'class-validator';
|
||||
import {
|
||||
IsBoolean,
|
||||
IsNotEmpty,
|
||||
IsNumber,
|
||||
IsOptional,
|
||||
IsString,
|
||||
} from 'class-validator';
|
||||
|
||||
export class SearchDTO {
|
||||
@IsString()
|
||||
query: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
spaceId: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
creatorId?: string;
|
||||
|
||||
@ -1,34 +1,51 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
ForbiddenException,
|
||||
HttpCode,
|
||||
HttpStatus,
|
||||
NotImplementedException,
|
||||
Post,
|
||||
Query,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { SearchService } from './search.service';
|
||||
import { SearchDTO, SearchSuggestionDTO } from './dto/search.dto';
|
||||
import { AuthWorkspace } from '../../decorators/auth-workspace.decorator';
|
||||
import { JwtAuthGuard } from '../../guards/jwt-auth.guard';
|
||||
import { Workspace } from '@docmost/db/types/entity.types';
|
||||
import { User, Workspace } from '@docmost/db/types/entity.types';
|
||||
import SpaceAbilityFactory from '../casl/abilities/space-ability.factory';
|
||||
import {
|
||||
SpaceCaslAction,
|
||||
SpaceCaslSubject,
|
||||
} from '../casl/interfaces/space-ability.type';
|
||||
import { AuthUser } from '../../decorators/auth-user.decorator';
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Controller('search')
|
||||
export class SearchController {
|
||||
constructor(private readonly searchService: SearchService) {}
|
||||
constructor(
|
||||
private readonly searchService: SearchService,
|
||||
private readonly spaceAbility: SpaceAbilityFactory,
|
||||
) {}
|
||||
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Post()
|
||||
async pageSearch(
|
||||
@Body() searchDto: SearchDTO,
|
||||
@AuthWorkspace() workspace: Workspace,
|
||||
) {
|
||||
return this.searchService.searchPage(
|
||||
searchDto.query,
|
||||
searchDto,
|
||||
workspace.id,
|
||||
);
|
||||
async pageSearch(@Body() searchDto: SearchDTO, @AuthUser() user: User) {
|
||||
if (searchDto.spaceId) {
|
||||
const ability = await this.spaceAbility.createForUser(
|
||||
user,
|
||||
searchDto.spaceId,
|
||||
);
|
||||
|
||||
if (ability.cannot(SpaceCaslAction.Read, SpaceCaslSubject.Page)) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
return this.searchService.searchPage(searchDto.query, searchDto);
|
||||
}
|
||||
|
||||
// TODO: search all spaces user is a member of if no spaceId provided
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@Post('suggest')
|
||||
|
||||
@ -4,17 +4,20 @@ import { SearchResponseDto } from './dto/search-response.dto';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { KyselyDB } from '@docmost/db/types/kysely.types';
|
||||
import { sql } from 'kysely';
|
||||
import { PageRepo } from '@docmost/db/repos/page/page.repo';
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const tsquery = require('pg-tsquery')();
|
||||
|
||||
@Injectable()
|
||||
export class SearchService {
|
||||
constructor(@InjectKysely() private readonly db: KyselyDB) {}
|
||||
constructor(
|
||||
@InjectKysely() private readonly db: KyselyDB,
|
||||
private pageRepo: PageRepo,
|
||||
) {}
|
||||
|
||||
async searchPage(
|
||||
query: string,
|
||||
searchParams: SearchDTO,
|
||||
workspaceId: string,
|
||||
): Promise<SearchResponseDto[]> {
|
||||
if (query.length < 1) {
|
||||
return;
|
||||
@ -28,6 +31,7 @@ export class SearchService {
|
||||
'title',
|
||||
'icon',
|
||||
'parentPageId',
|
||||
'slugId',
|
||||
'creatorId',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
@ -36,7 +40,8 @@ export class SearchService {
|
||||
'highlight',
|
||||
),
|
||||
])
|
||||
.where('workspaceId', '=', workspaceId)
|
||||
.select((eb) => this.pageRepo.withSpace(eb))
|
||||
.where('spaceId', '=', searchParams.spaceId)
|
||||
.where('tsv', '@@', sql<string>`to_tsquery(${searchQuery})`)
|
||||
.$if(Boolean(searchParams.creatorId), (qb) =>
|
||||
qb.where('creatorId', '=', searchParams.creatorId),
|
||||
|
||||
Reference in New Issue
Block a user