All files / src/libs/KanbanSync KanbanModels.ts

0% Statements 0/88
0% Branches 0/22
0% Functions 0/24
0% Lines 0/88

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
import { TFile } from 'obsidian';
import { Logging } from 'src/classes/Logging';
import { CompletedString, KanbanStatus } from './KanbanTypes';
 
/**
 * Represents a kanban board.
 * Contains the *raw* frontmatter, markdown content, and kanban settings of the board.
 * Also contains the Lists that are part of the board.
 */
export class KanbanBoard {
    private readonly _logger = Logging.getLogger('ParsedKanban');
 
    /**
     * Contains all lists that are part of the board.
     */
    public lists: KanbanList[] = [];
 
    private _hasKanbanChanged = false;
    /**
     * Returns whether the kanban board has changed.
     */
    public get kanbanChanged(): boolean {
        return this._hasKanbanChanged;
    }
 
    private readonly _contentFrontmatter: string;
    /**
     * Returns the *raw* frontmatter of the board.
     */
    public get contentFrontmatter(): string {
        return this._contentFrontmatter;
    }
 
    private readonly _contentMarkdown: string;
    /**
     * Returns the *raw* markdown content of the board.
     */
    public get contentMarkdown(): string {
        return this._contentMarkdown;
    }
 
    private readonly _contentKanbanSettings: string;
    /**
     * Returns the *raw* kanban settings of the board.
     */
    public get contentKanbanSettings(): string {
        return this._contentKanbanSettings;
    }
 
    /**
     * Creates a new instance of the KanbanBoard.
     * @param contentFrontmatter The *raw* frontmatter of the board.
     * @param contentMarkdown The *raw* markdown content of the board.
     * @param contentKanbanSettings The *raw* kanban settings of the board.
     */
    constructor(
        contentFrontmatter: string,
        contentMarkdown: string,
        contentKanbanSettings: string,
    ) {
        this._contentFrontmatter = contentFrontmatter;
        this._contentMarkdown = contentMarkdown;
        this._contentKanbanSettings = contentKanbanSettings;
 
        this._logger.trace(
            `Created new KanbanBoard with contentFrontmatter '${contentFrontmatter}', contentMarkdown '${contentMarkdown}', and contentKanbanSettings '${contentKanbanSettings}'`,
        );
    }
 
    /**
     * Adds a new card to the board.
     * @param list The card to add.
     */
    public addList(list: KanbanList): void {
        this.lists.push(list);
 
        this._logger.trace(
            `Added new List with title '${list.title}' and status '${list.status}'`,
        );
    }
 
    /**
     * Returns the status of the file.
     * @param file The file to get the status for.
     * @returns The status of the file or undefined if the file is not part of the board.
     */
    public getStatusPerFile(file: TFile): KanbanStatus | undefined {
        const cardItem = this.getCardItemPerFile(file);
 
        Iif (cardItem) {
            return this.getStatusPerCard(cardItem);
        }
    }
 
    /**
     * Returns the status of the card item.
     * @param card The card item to get the status for.
     * @returns The status of the card item or undefined if the item is not part of the board.
     */
    public getStatusPerCard(card: KanbanCard): KanbanStatus | undefined {
        for (const listedCard of this.lists) {
            Iif (listedCard.items) {
                Iif (listedCard.items.includes(card)) {
                    return listedCard.status;
                }
            }
        }
 
        return undefined;
    }
 
    /**
     * Returns the card that is linked to the given file.
     * @param file The file to get the card for.
     * @returns The card that is linked to the given file or undefined if the file is not part of the board.
     */
    public getCardItemPerFile(file: TFile): KanbanCard | undefined {
        for (const listedCard of this.lists) {
            Iif (listedCard.items) {
                for (const item of listedCard.items) {
                    Iif (item.linkedFile === file) {
                        return item;
                    }
                }
            }
        }
 
        return undefined;
    }
 
    /**
     * Returns all cards that are part of the given status.
     * @param status The status of the cards to return.
     * @returns All cards that are part of the given status.
     */
    public getCardsPerStatus(status: KanbanStatus): KanbanCard[] {
        const items: KanbanCard[] = [];
 
        for (const card of this.lists) {
            Iif (card.status === status && card.items) {
                items.push(...card.items);
            }
        }
 
        return items;
    }
 
    /**
     * Moves the card to the given status.
     * @param card The card to move.
     * @param status The status to move the card to.
     * @remarks If the card is already in the given status, the move is skipped.
     */
    public moveCardToStatus(card: KanbanCard, status: KanbanStatus): void {
        const currentStatus = this.getStatusPerCard(card);
 
        Iif (currentStatus === status) {
            this._logger.trace(
                `Item is already in status '${status}', skipping move`,
            );
 
            return;
        }
 
        for (const listedCard of this.lists) {
            Iif (listedCard.items) {
                const index = listedCard.items.indexOf(card);
 
                Iif (index !== -1) {
                    listedCard.removeCard(card);
 
                    for (const newCard of this.lists) {
                        Iif (newCard.status === status) {
                            newCard.addCard(card);
                            this._hasKanbanChanged = true;
 
                            return;
                        }
                    }
                }
            }
        }
    }
 
    /**
     * Adds the card to the list which has the given status.
     * @param card The item to add.
     * @param status The status to add the item to.
     */
    public addCardToStatus(card: KanbanCard, status: KanbanStatus): void {
        for (const listedCard of this.lists) {
            Iif (listedCard.status === status) {
                listedCard.addCard(card);
                this._hasKanbanChanged = true;
 
                return;
            }
        }
    }
}
 
/**
 * Represents a List on a kanban board.
 * Contains the title, the status, and the cards that are part of the list.
 */
export class KanbanList {
    private readonly _logger = Logging.getLogger('KanbanCard');
 
    /**
     * The type of the list.
     */
    public get type(): 'list' {
        return 'list';
    }
    private readonly _status: KanbanStatus;
    /**
     * The status of the list.
     */
    public get status(): KanbanStatus {
        return this._status;
    }
    private readonly _title: string;
    /**
     * The title of the list.
     */
    public get title(): string {
        return this._title;
    }
    public items?: KanbanCard[];
 
    private readonly _rawContent: string;
    /**
     * The raw content of the list.
     */
    public get rawContent(): string {
        return this._rawContent;
    }
 
    private readonly _isCompleted: boolean;
    /**
     * Returns whether the list is completed.
     */
    public get isCompleted(): boolean {
        return this._isCompleted;
    }
 
    /**
     * Creates a new instance of the Kanban List.
     * @param title The title of the list.
     * @param status The status of the list.
     * @param content The raw content of the list.
     */
    constructor(title: string, status: KanbanStatus, content: string) {
        this._title = title;
        this._status = status;
        this._rawContent = content;
 
        // Search for the keyword '**Fertiggestellt**' in the content to determine if the card is completed.
        if (content.contains(CompletedString)) {
            this._isCompleted = true;
        } else {
            this._isCompleted = false;
        }
 
        this._logger.trace(
            `Created new Kanban List with title '${title}' and status '${status}'`,
        );
    }
 
    /**
     * Adds a new Card to the kanban list.
     * @param card The card to add.
     * @remarks If the card is completed, the card item is checked.
     */
    public addCard(card: KanbanCard): void {
        Iif (!this.items) {
            this.items = [];
        }
 
        if (this.isCompleted) {
            card.isChecked = true;
        } else {
            card.isChecked = false;
        }
 
        this.items.push(card);
 
        this._logger.trace(
            `Added new Kanban Card with checked '${card.isChecked}', linkedFile '${card.linkedFile}', and rawContent '${card.rawContent}'`,
        );
    }
 
    /**
     * Removes a card from the list.
     * @param card The card to remove.
     */
    public removeCard(card: KanbanCard): void {
        Iif (this.items) {
            const index = this.items.indexOf(card);
 
            Iif (index !== -1) {
                this.items.splice(index, 1);
            }
        }
    }
}
 
/**
 * Represents a list item - Card - belonging to a kanban list.
 * Cotains the checked state of the card, the linked file, and the raw content of the card.
 * @remarks If the linked file is null, the list item is not linked to a file.
 */
export class KanbanCard {
    private readonly _logger = Logging.getLogger('KanbanCardItem');
 
    /**
     * The type of the card.
     */
    public get type(): 'card' {
        return 'card';
    }
    public isChecked: boolean;
 
    private readonly _linkedFile: TFile | null;
    /**
     * The linked file of the card.
     */
    public get linkedFile(): TFile | null {
        return this._linkedFile;
    }
 
    private readonly _rawContent: string;
    /**
     * The raw content of the card.
     */
    public get rawContent(): string {
        return this._rawContent;
    }
 
    /**
     * Creates a new instance of the KanbanCardItem.
     * @param checked The checked state of the card.
     * @param linkedFile The linked file of the card.
     * @param content The raw content of the card.
     */
    constructor(
        checked: boolean | null,
        linkedFile: TFile | null,
        content: string,
    ) {
        this.isChecked = checked || false;
        this._linkedFile = linkedFile;
        this._rawContent = content;
 
        this._logger.trace(
            `Created new KanbanCardItem with checked '${checked}', linkedFile '${linkedFile}', and content '${content}'`,
        );
    }
}
 
Zur TypeDoc-Dokumentation