- Loading...
+
@@ -101,18 +130,18 @@
import type { NoteId } from '@/domain/entities/Note';
import useNoteSettings from '@/application/services/useNoteSettings';
import useNote from '@/application/services/useNote';
-import { useHead } from 'unhead';
+import usePageTitle from '@/application/services/usePageTitle';
import { useI18n } from 'vue-i18n';
-import { computed, ref, onMounted, watch } from 'vue';
-import { useDebounceFn } from '@vueuse/core';
+import { computed, ref, onMounted } from 'vue';
import Team from '@/presentation/components/team/Team.vue';
-import { Section, Row, Switch, Button, Heading, Fieldset, Input, Card, PageBlock } from '@codexteam/ui/vue';
+import PageHeading from '@/presentation/components/pageHeading/PageHeading.vue';
+import { Section, Row, Switch, Button, Input, PageBlock, useConfirm } from '@codexteam/ui/vue';
import { getTitle } from '@/infrastructure/utils/note';
import { getTimeFromNow } from '@/infrastructure/utils/date';
import InviteLink from '@/presentation/components/noteSettings/InviteLink.vue';
import useNavbar from '@/application/services/useNavbar';
-import { useRoute } from 'vue-router';
-import { TeamMember } from '@/domain/entities/Team';
+import { useRouter } from 'vue-router';
+import type { TeamMember } from '@/domain/entities/Team';
const { t } = useI18n();
@@ -123,112 +152,109 @@ const props = defineProps<{
id: NoteId;
}>();
-const { patchOpenedPageByUrl } = useNavbar();
-const route = useRoute();
-const { noteSettings, load: loadSettings, updateIsPublic, deleteNoteById, parentNote, setParent } = useNoteSettings();
-const { noteTitle, unlinkParent } = useNote({
+const { deleteOpenedPagesByPrefix } = useNavbar();
+const router = useRouter();
+const { confirm } = useConfirm();
+const { noteSettings, load: loadSettings, updateIsPublic, deleteNoteById, setParent } = useNoteSettings();
+const { note, noteTitle, parentNote, unlinkParent } = useNote({
id: props.id,
});
/**
- * URL of the parent note. Used to set and display the parent note
+ * URL of the note to be set as a parent
*/
const parentURL = ref
('');
+const parentError = ref('');
+
+const isParentUpdating = ref(false);
+
/**
- * Deletes the note complitely
+ * Deletes the note completely
*/
async function deleteNote() {
- const isConfirmed = window.confirm(t('noteSettings.noteDeleteConfirmation'));
+ const isConfirmed = await confirm(t('noteSettings.deleteNoteTitle'), t('noteSettings.noteDeleteConfirmation'), {
+ confirmText: t('noteSettings.deleteNote'),
+ cancelText: t('cancel'),
+ destructive: true,
+ });
if (isConfirmed) {
- deleteNoteById(props.id);
+ await deleteNoteById(props.id);
+ deleteOpenedPagesByPrefix(`/note/${props.id}`);
+ void router.push('/');
}
}
/**
- * Unlink parent note and clear the parentURL field
+ * Unlink parent note
*/
async function handleUnlinkParentClick() {
- parentURL.value = '';
- parentNote.value = undefined;
- unlinkParent();
+ if (isParentUpdating.value) {
+ return;
+ }
+
+ isParentUpdating.value = true;
+
+ try {
+ await unlinkParent();
+ } finally {
+ isParentUpdating.value = false;
+ }
}
/**
- * Set parent note with debounce
+ * Set parent note by the link from the input
*/
-const setParentDebounced = useDebounceFn(async () => {
- if (parentURL.value !== '') {
- await setParent(props.id, parentURL.value);
+async function handleSetParent() {
+ if (isParentUpdating.value || parentURL.value.trim() === '') {
+ return;
}
-}, 1000);
-const parentNoteTitle = computed(() => {
- if (parentNote.value === undefined) {
- return '';
- }
+ parentError.value = '';
+ isParentUpdating.value = true;
- return getTitle(parentNote.value.content);
-});
+ try {
+ parentNote.value = await setParent(props.id, parentURL.value.trim());
+ parentURL.value = '';
+ } catch (error) {
+ parentError.value = error instanceof Error && error.message.startsWith('Invalid')
+ ? t('noteSettings.parentNoteInvalidLink')
+ : t('noteSettings.parentNoteError');
+ } finally {
+ isParentUpdating.value = false;
+ }
+}
/**
- * Current value of isPublic field
+ * Switch emits its initial state on mount, so the value is changed only by the click handler
*/
-const isPublic = computed(() => {
- return noteSettings.value?.isPublic;
+const isPublic = computed({
+ get: () => noteSettings.value?.isPublic ?? false,
+ set: () => {},
});
/**
* Change isPublic property
*/
async function changeAccess() {
- updateIsPublic(props.id, !noteSettings.value!.isPublic);
-}
-
-/**
- * Construct the parent note URL. If the parent note is not set, return an empty string
- *
- * @param id - id of the note
- * @returns {string} URL of the parent note
- */
-function getParentURL(id: NoteId | undefined): string {
- if (parentNote.value !== undefined) {
- const websiteHostname = import.meta.env.VITE_PRODUCTION_HOSTNAME;
-
- return `${websiteHostname}/note/${id}`;
+ if (noteSettings.value !== null) {
+ await updateIsPublic(props.id, !noteSettings.value.isPublic);
}
-
- return '';
}
-/**
- * Changing the title in the browser
- */
-useHead({
- title: t('noteSettings.title'),
-});
-
-watch(noteTitle, (newTitle) => {
- const openPageInfo = {
- title: `${t('noteSettings.settings')} (${newTitle})`,
- url: route.path,
- };
-
- patchOpenedPageByUrl(route.path, openPageInfo);
-});
+usePageTitle(() => `${t('noteSettings.title')} · ${noteTitle.value}`);
onMounted(async () => {
await loadSettings(props.id);
- parentURL.value = getParentURL(parentNote.value?.id);
});
/**
- * Handle team member removal by refreshing the note settings and removing the member from the team
+ * Remove the member from the displayed team
*
- * @param userId - user id of the member to remove
+ * @param userId - user id of the removed member
*/
-async function handleTeamMemberRemoved(userId: TeamMember['user']['id']) {
+function handleTeamMemberRemoved(userId: TeamMember['user']['id']) {
if (noteSettings.value !== null) {
noteSettings.value = {
...noteSettings.value,
@@ -238,47 +264,58 @@ async function handleTeamMemberRemoved(userId: TeamMember['user']['id']) {
}
-
diff --git a/src/presentation/pages/Settings.vue b/src/presentation/pages/Settings.vue
index 65b077fd..1c780cc3 100644
--- a/src/presentation/pages/Settings.vue
+++ b/src/presentation/pages/Settings.vue
@@ -1,203 +1,178 @@
-
-
+
+
{{ t('userSettings.title') }}
-
-
-
-
-
-