mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-25 11:16:31 -05:00
feat: add list of aliases to note entity
One of the aliases can be primary for each note, but all can be used to get information from the apis. Signed-off-by: Philip Molares <philip.molares@udo.edu>
This commit is contained in:
parent
86d060706f
commit
17c55195c3
6 changed files with 115 additions and 13 deletions
|
@ -6,13 +6,20 @@ entity "note" {
|
||||||
*id : uuid <<generated>>
|
*id : uuid <<generated>>
|
||||||
--
|
--
|
||||||
publicId: text
|
publicId: text
|
||||||
alias : text
|
|
||||||
*viewCount : number
|
*viewCount : number
|
||||||
*ownerId : uuid <<FK user>>
|
*ownerId : uuid <<FK user>>
|
||||||
description: text
|
description: text
|
||||||
title: text
|
title: text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity "alias" {
|
||||||
|
*id: uuid <<generated>>
|
||||||
|
---
|
||||||
|
name: text
|
||||||
|
' If the alias is primary. Can be NULL, which means it's not primary
|
||||||
|
primary: boolean
|
||||||
|
}
|
||||||
|
|
||||||
entity "user" {
|
entity "user" {
|
||||||
*id : uuid <<generated>>
|
*id : uuid <<generated>>
|
||||||
--
|
--
|
||||||
|
@ -169,6 +176,7 @@ media_upload "0..*" -- "1" note
|
||||||
note "1" -d- "1..*" revision
|
note "1" -d- "1..*" revision
|
||||||
note "1" - "0..*" history_entry
|
note "1" - "0..*" history_entry
|
||||||
note "0..*" -l- "0..*" tag
|
note "0..*" -l- "0..*" tag
|
||||||
|
note "1" - "0..*" alias
|
||||||
note "0..*" -- "0..*" group
|
note "0..*" -- "0..*" group
|
||||||
user "1..*" -- "0..*" group
|
user "1..*" -- "0..*" group
|
||||||
|
|
||||||
|
|
63
src/notes/alias.entity.ts
Normal file
63
src/notes/alias.entity.ts
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
Column,
|
||||||
|
Entity,
|
||||||
|
ManyToOne,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Unique,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
import { Note } from './note.entity';
|
||||||
|
import { PrimaryValueTransformer } from './primary.value-transformer';
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
@Unique('Only one primary alias per note', ['note', 'primary'])
|
||||||
|
export class Alias {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the actual alias
|
||||||
|
*/
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
unique: true,
|
||||||
|
})
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this alias the primary alias, by which people access the note?
|
||||||
|
*/
|
||||||
|
@Column({
|
||||||
|
/*
|
||||||
|
Because of the @Unique at the top of this entity, this field must be saved as null instead of false in the DB.
|
||||||
|
If a non-primary alias would be saved with `primary: false` it would only be possible to have one non-primary and one primary alias.
|
||||||
|
But a nullable field does not have such problems.
|
||||||
|
This way the DB keeps track that one note really only has one primary alias.
|
||||||
|
*/
|
||||||
|
comment:
|
||||||
|
'This field tells you if this is the primary alias of the note. If this field is null, that means this alias is not primary.',
|
||||||
|
nullable: true,
|
||||||
|
transformer: new PrimaryValueTransformer(),
|
||||||
|
})
|
||||||
|
primary: boolean;
|
||||||
|
|
||||||
|
@ManyToOne((_) => Note, (note) => note.aliases, {
|
||||||
|
onDelete: 'CASCADE', // This deletes the Alias, when the associated Note is deleted
|
||||||
|
})
|
||||||
|
note: Note;
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
|
private constructor() {}
|
||||||
|
|
||||||
|
static create(name: string, primary = false): Alias {
|
||||||
|
const alias = new Alias();
|
||||||
|
alias.name = name;
|
||||||
|
alias.primary = primary;
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,13 +25,19 @@ export class NoteMetadataDto {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Alias of the note
|
* All aliases of the note (including the primaryAlias)
|
||||||
* Can be null
|
*/
|
||||||
|
@IsArray()
|
||||||
|
@IsString({ each: true })
|
||||||
|
@ApiProperty()
|
||||||
|
aliases: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The primary alias of the note
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsOptional()
|
@ApiProperty()
|
||||||
@ApiPropertyOptional()
|
primaryAlias: string | null;
|
||||||
alias: string | null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Title of the note
|
* Title of the note
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { NoteGroupPermission } from '../permissions/note-group-permission.entity
|
||||||
import { NoteUserPermission } from '../permissions/note-user-permission.entity';
|
import { NoteUserPermission } from '../permissions/note-user-permission.entity';
|
||||||
import { Revision } from '../revisions/revision.entity';
|
import { Revision } from '../revisions/revision.entity';
|
||||||
import { User } from '../users/user.entity';
|
import { User } from '../users/user.entity';
|
||||||
|
import { Alias } from './alias.entity';
|
||||||
import { Tag } from './tag.entity';
|
import { Tag } from './tag.entity';
|
||||||
import { generatePublicId } from './utils';
|
import { generatePublicId } from './utils';
|
||||||
|
|
||||||
|
@ -28,12 +29,12 @@ export class Note {
|
||||||
id: string;
|
id: string;
|
||||||
@Column({ type: 'text' })
|
@Column({ type: 'text' })
|
||||||
publicId: string;
|
publicId: string;
|
||||||
@Column({
|
@OneToMany(
|
||||||
unique: true,
|
(_) => Alias,
|
||||||
nullable: true,
|
(alias) => alias.note,
|
||||||
type: 'text',
|
{ cascade: true }, // This ensures that embedded Aliases are automatically saved to the database
|
||||||
})
|
)
|
||||||
alias: string | null;
|
aliases: Alias[];
|
||||||
@OneToMany(
|
@OneToMany(
|
||||||
(_) => NoteGroupPermission,
|
(_) => NoteGroupPermission,
|
||||||
(groupPermission) => groupPermission.note,
|
(groupPermission) => groupPermission.note,
|
||||||
|
@ -84,7 +85,7 @@ export class Note {
|
||||||
public static create(owner?: User, alias?: string): Note {
|
public static create(owner?: User, alias?: string): Note {
|
||||||
const newNote = new Note();
|
const newNote = new Note();
|
||||||
newNote.publicId = generatePublicId();
|
newNote.publicId = generatePublicId();
|
||||||
newNote.alias = alias ?? null;
|
newNote.aliases = alias ? [Alias.create(alias, true)] : [];
|
||||||
newNote.viewCount = 0;
|
newNote.viewCount = 0;
|
||||||
newNote.owner = owner ?? null;
|
newNote.owner = owner ?? null;
|
||||||
newNote.userPermissions = [];
|
newNote.userPermissions = [];
|
||||||
|
|
|
@ -14,6 +14,7 @@ import { NoteUserPermission } from '../permissions/note-user-permission.entity';
|
||||||
import { RevisionsModule } from '../revisions/revisions.module';
|
import { RevisionsModule } from '../revisions/revisions.module';
|
||||||
import { User } from '../users/user.entity';
|
import { User } from '../users/user.entity';
|
||||||
import { UsersModule } from '../users/users.module';
|
import { UsersModule } from '../users/users.module';
|
||||||
|
import { Alias } from './alias.entity';
|
||||||
import { Note } from './note.entity';
|
import { Note } from './note.entity';
|
||||||
import { NotesService } from './notes.service';
|
import { NotesService } from './notes.service';
|
||||||
import { Tag } from './tag.entity';
|
import { Tag } from './tag.entity';
|
||||||
|
@ -26,6 +27,7 @@ import { Tag } from './tag.entity';
|
||||||
NoteGroupPermission,
|
NoteGroupPermission,
|
||||||
NoteUserPermission,
|
NoteUserPermission,
|
||||||
User,
|
User,
|
||||||
|
Alias,
|
||||||
]),
|
]),
|
||||||
forwardRef(() => RevisionsModule),
|
forwardRef(() => RevisionsModule),
|
||||||
UsersModule,
|
UsersModule,
|
||||||
|
|
22
src/notes/primary.value-transformer.ts
Normal file
22
src/notes/primary.value-transformer.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
import { ValueTransformer } from 'typeorm';
|
||||||
|
|
||||||
|
export class PrimaryValueTransformer implements ValueTransformer {
|
||||||
|
from(value: boolean | null): boolean {
|
||||||
|
if (value === null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
to(value: boolean): boolean | null {
|
||||||
|
if (!value) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue