Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/application/i18n/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@
"availabilityTitle": "Availability",
"availabilityCaption": "Should the Note be available by its URL for people who knows it?",
"availabilityRowTitle": "Note is published",
"noteHierarchyTitle": "Note hierarchy",
"noteHierarchyCaption": "Show the note hierarchy on the left menu?",
"noteHierarchyRowTitle": "Show note hierarchy",
"inviteCollaboratorTitle": "Invite a collaborator",
"inviteCollaboratorCaption": "Send this link to someone you want to add as an editor or reader.",
"revokeHashButton": "Revoke",
Expand Down
37 changes: 25 additions & 12 deletions src/application/services/useNote.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { onMounted, ref, type Ref, type MaybeRefOrGetter, computed, toValue, watch } from 'vue';
import { ref, type Ref, type MaybeRefOrGetter, computed, toValue, watch } from 'vue';
import { noteService, editorToolsService } from '@/domain';
import type { Note, NoteContent, NoteId } from '@/domain/entities/Note';
import type { NoteTool } from '@/domain/entities/Note';
Expand All @@ -10,6 +10,13 @@ import useNavbar from './useNavbar';
import { getTitle } from '@/infrastructure/utils/note';
import type { NoteHierarchy } from '@/domain/entities/NoteHierarchy';

/**
* Note-specific load options
*/
export interface NoteLoadOptions {
loadHierarchy?: boolean;
}

/**
* Creates base structure for the empty note:
* First block is Header, second is an empty Paragraph
Expand Down Expand Up @@ -96,6 +103,13 @@ interface UseNoteComposableState {
* Note hierarchy
*/
noteHierarchy: Ref<NoteHierarchy | null>;

/**
* Load note by id with configurable options
* @param id - Note identifier
* @param loadOptions - Load options for customizing what data to fetch
*/
load: (id: NoteId, loadOptions?: NoteLoadOptions) => Promise<void>;
}

interface UseNoteComposableOptions {
Expand Down Expand Up @@ -196,8 +210,9 @@ export default function (options: UseNoteComposableOptions): UseNoteComposableSt
/**
* Load note by id
* @param id - Note identifier got from composable argument
* @param loadOptions - Loading options
*/
async function load(id: NoteId): Promise<void> {
async function load(id: NoteId, loadOptions?: NoteLoadOptions): Promise<void> {
try {
const response = await noteService.getNoteById(id);

Expand All @@ -206,7 +221,13 @@ export default function (options: UseNoteComposableOptions): UseNoteComposableSt
noteTools.value = response.tools;
parentNote.value = response.parentNote;
noteParents.value = response.parents;
void getNoteHierarchy(id);

// Default to false if not specified
const shouldLoadHierarchy = loadOptions?.loadHierarchy ?? false;

if (shouldLoadHierarchy) {
void getNoteHierarchy(id);
}
} catch (error) {
deleteOpenedPageByUrl(route.path);
if (error instanceof DomainError) {
Expand Down Expand Up @@ -320,15 +341,6 @@ export default function (options: UseNoteComposableOptions): UseNoteComposableSt
note.value = (await noteService.getNoteByHostname(location.hostname)).note;
};

onMounted(() => {
/**
* If we have id, load note and note hierarchy
*/
if (currentId.value !== null) {
void load(currentId.value);
}
});

/**
* Reset note to the initial state
*/
Expand Down Expand Up @@ -414,5 +426,6 @@ export default function (options: UseNoteComposableOptions): UseNoteComposableSt
noteParents,
parentNote,
noteHierarchy,
load,
};
}
24 changes: 24 additions & 0 deletions src/application/services/useNoteSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ interface UseNoteSettingsComposableState {
*/
updateIsPublic: (id: NoteId, newIsPublicValue: boolean) => Promise<void>;

/**
* Update field showNoteHierarchy in note settings
* @param id - Note id
* @param newShowNoteHierarchyValue - new showNoteHierarchy
*/
updateShowNoteHierarchy: (id: NoteId, newShowNoteHierarchyValue: boolean) => Promise<void>;

/**
* Revoke invitation hash
* @param id - note id
Expand Down Expand Up @@ -116,6 +123,22 @@ export default function (): UseNoteSettingsComposableState {
}
}

/**
* Update field showNoteHierarchy in note settings
* @param id - Note id
* @param newShowNoteHierarchyValue - new showNoteHierarchy
*/
async function updateShowNoteHierarchy(id: NoteId, newShowNoteHierarchyValue: boolean): Promise<void> {
const { showNoteHierarchy } = await noteSettingsService.patchNoteSettingsByNoteId(id, { showNoteHierarchy: newShowNoteHierarchyValue });

/**
* If note settings were not loaded till this moment for some reason, do nothing
*/
if (noteSettings.value) {
noteSettings.value.showNoteHierarchy = showNoteHierarchy;
}
}

/**
* Revoke invitation hash
* @param id - Note id
Expand Down Expand Up @@ -198,5 +221,6 @@ export default function (): UseNoteSettingsComposableState {
revokeHash,
changeRole,
deleteNoteById,
updateShowNoteHierarchy,
};
}
5 changes: 5 additions & 0 deletions src/domain/entities/NoteSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,9 @@ export default interface NoteSettings {
* Note cover image id
*/
cover: string;

/**
* Show note heirarchy
*/
showNoteHierarchy: boolean;
}
45 changes: 27 additions & 18 deletions src/presentation/pages/Note.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@
<PageBlock>
<template #left>
<VerticalMenu
v-if="noteSettings && noteSettings.showNoteHierarchy && verticalMenuItems.length > 0"
class="menu"
:items="[verticalMenuItems]"
:items="verticalMenuItems"
/>
</template>
<template #default>
Expand All @@ -66,7 +67,7 @@
<script lang="ts" setup>
import { computed, ref, toRef, watch } from 'vue';
import { Button, Editor, PageBlock, VerticalMenu, type VerticalMenuItem } from '@codexteam/ui/vue';
import useNote from '@/application/services/useNote';
import useNote, { type NoteLoadOptions } from '@/application/services/useNote';
import { useRoute, useRouter } from 'vue-router';
import { NoteContent } from '@/domain/entities/Note';
import { useHead } from 'unhead';
Expand Down Expand Up @@ -99,10 +100,13 @@ const props = defineProps<{

const noteId = toRef(props, 'id');

const { note, noteTools, save, noteTitle, canEdit, noteParents, noteHierarchy } = useNote({
const { note, noteTools, save, noteTitle, canEdit, noteParents, noteHierarchy, load } = useNote({
id: noteId,
});

// Note settings composable - used directly in the page
const { noteSettings, load: loadNoteSettings, updateCover } = useNoteSettings();

/**
* Create new child note
*/
Expand All @@ -123,8 +127,6 @@ function redirectToNoteSettings(): void {
router.push(`/note/${props.id}/settings`);
}

const { updateCover } = useNoteSettings();

const { isEditorReady, editorConfig } = useNoteEditor({
noteTools,
isDraftResolver: () => noteId.value === null,
Expand Down Expand Up @@ -183,18 +185,10 @@ async function noteChanged(data: NoteContent): Promise<void> {
* @returns menuItem - VerticalMenuItem
*/

function transformNoteHierarchy(noteHierarchyObj: NoteHierarchy | null, currentNoteTitle: string): VerticalMenuItem {
if (!noteHierarchyObj) {
return {
title: 'Untitled',
isActive: true,
items: undefined,
};
}

function transformNoteHierarchy(noteHierarchyObj: NoteHierarchy, currentNoteTitle: string): VerticalMenuItem {
// Transform the current note into a VerticalMenuItem
return {
title: noteHierarchyObj?.noteTitle || 'Untitled',
title: noteHierarchyObj.noteTitle || 'Untitled',
isActive: route.path === `/note/${noteHierarchyObj.noteId}`,
items: noteHierarchyObj.childNotes ? noteHierarchyObj.childNotes.map(child => transformNoteHierarchy(child, currentNoteTitle)) : undefined,
onActivate: () => {
Expand All @@ -203,18 +197,33 @@ function transformNoteHierarchy(noteHierarchyObj: NoteHierarchy | null, currentN
};
}

const verticalMenuItems = computed<VerticalMenuItem>(() => {
return transformNoteHierarchy(noteHierarchy.value, noteTitle.value);
const verticalMenuItems = computed<VerticalMenuItem[]>(() => {
if (!noteHierarchy.value) {
return [];
}

return [transformNoteHierarchy(noteHierarchy.value, noteTitle.value)];
});

watch(
() => props.id,
() => {
async () => {
/** If new child note is created, refresh editor with empty data */
if (props.id === null) {
useHead({
title: t('note.new'),
});
} else {
// Load note settings first
await loadNoteSettings(props.id);

// Create load options based on note settings
const loadOptions: NoteLoadOptions = {
loadHierarchy: noteSettings.value?.showNoteHierarchy === true,
};

// Load note with the configured options
await load(props.id, loadOptions);
}
},
{ immediate: true }
Expand Down
27 changes: 26 additions & 1 deletion src/presentation/pages/NoteSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,20 @@
</Row>
</Section>

<Section
:title="t('noteSettings.noteHierarchyTitle')"
:caption="t('noteSettings.noteHierarchyCaption')"
>
<Row :title="t('noteSettings.noteHierarchyRowTitle')">
<template #right>
<Switch
v-model="showNoteHierarchy"
@click="changeShowNoteHierarchy"
/>
</template>
</Row>
</Section>

<Fieldset
:title="t('noteSettings.teamFormFieldSetTitle')"
>
Expand Down Expand Up @@ -123,7 +137,7 @@ const props = defineProps<{

const { patchOpenedPageByUrl } = useNavbar();
const route = useRoute();
const { noteSettings, load: loadSettings, updateIsPublic, deleteNoteById, parentNote, setParent } = useNoteSettings();
const { noteSettings, load: loadSettings, updateIsPublic, deleteNoteById, parentNote, setParent, updateShowNoteHierarchy } = useNoteSettings();
const { noteTitle, unlinkParent } = useNote({
id: props.id,
});
Expand Down Expand Up @@ -177,13 +191,24 @@ const isPublic = computed(() => {
return noteSettings.value?.isPublic;
});

/**
* Current value of showNoteHierarchy field
*/
const showNoteHierarchy = computed(() => {
return noteSettings.value?.showNoteHierarchy;
});

/**
* Change isPublic property
*/
async function changeAccess() {
updateIsPublic(props.id, !noteSettings.value!.isPublic);
}

async function changeShowNoteHierarchy() {
updateShowNoteHierarchy(props.id, !noteSettings.value!.showNoteHierarchy);
}

/**
* Construct the parent note URL. If the parent note is not set, return an empty string
*
Expand Down
Loading