mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-23 15:09:33 +01:00
feat: impl tag create & edit
This commit is contained in:
@@ -166,7 +166,7 @@ test("edit topics individually", async () => {
|
||||
await page.click(Menu.new("menuitem").item("edit").build());
|
||||
|
||||
const editedTopicTitle = "Topic " + index + " edit 1";
|
||||
await page.fill(getTestId("dialog-edit-topic"), editedTopicTitle);
|
||||
await page.fill(getTestId("item-dialog-title"), editedTopicTitle);
|
||||
|
||||
await page.click(getTestId("dialog-yes"));
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { hashNavigate } from "../navigation";
|
||||
import ThemeProvider from "../components/theme-provider";
|
||||
import { qclone } from "qclone";
|
||||
import { store as notebookStore } from "../stores/notebook-store";
|
||||
import { store as tagStore } from "../stores/tag-store";
|
||||
import { store as appStore } from "../stores/app-store";
|
||||
import { db } from "./db";
|
||||
import { showToast } from "../utils/toast";
|
||||
@@ -491,9 +492,8 @@ export function showSignUpDialog() {
|
||||
export function showTopicDialog() {
|
||||
return showDialog((Dialogs, perform) => (
|
||||
<Dialogs.TopicDialog
|
||||
title={"Create a Topic"}
|
||||
title={"Create topic"}
|
||||
subtitle={"You can create as many topics as you want."}
|
||||
icon={Icon.Topic}
|
||||
onClose={() => {
|
||||
perform(false);
|
||||
}}
|
||||
@@ -502,6 +502,7 @@ export function showTopicDialog() {
|
||||
const notebookId = notebookStore.get().selectedNotebookId;
|
||||
await db.notebooks.notebook(notebookId).topics.add(topic);
|
||||
notebookStore.setSelectedNotebook(notebookId);
|
||||
showToast("success", "Topic created!");
|
||||
perform(true);
|
||||
}}
|
||||
/>
|
||||
@@ -515,17 +516,56 @@ export function showEditTopicDialog(notebookId, topicId) {
|
||||
if (!topic) return;
|
||||
return showDialog((Dialogs, perform) => (
|
||||
<Dialogs.TopicDialog
|
||||
title={"Edit Topic"}
|
||||
title={"Edit topic"}
|
||||
subtitle={`You are editing "${topic.title}" topic.`}
|
||||
icon={Icon.Topic}
|
||||
topic={topic}
|
||||
item={topic}
|
||||
onClose={() => perform(false)}
|
||||
onAction={async (t) => {
|
||||
await db.notebooks
|
||||
.notebook(topic.notebookId)
|
||||
.topics.add({ ...topic, title: t });
|
||||
notebookStore.setSelectedNotebook(topic.notebookId);
|
||||
showToast("success", "Topic edited successfully!");
|
||||
showToast("success", "Topic edited!");
|
||||
perform(true);
|
||||
}}
|
||||
/>
|
||||
));
|
||||
}
|
||||
|
||||
export function showCreateTagDialog() {
|
||||
return showDialog((Dialogs, perform) => (
|
||||
<Dialogs.ItemDialog
|
||||
title={"Create tag"}
|
||||
subtitle={"You can create multiple tags."}
|
||||
onClose={() => {
|
||||
perform(false);
|
||||
}}
|
||||
onAction={async (title) => {
|
||||
if (!title) return;
|
||||
await db.tags.add(title);
|
||||
showToast("success", "Tag created!");
|
||||
tagStore.refresh();
|
||||
perform(true);
|
||||
}}
|
||||
/>
|
||||
));
|
||||
}
|
||||
|
||||
export function showEditTagDialog(tagId) {
|
||||
const tag = db.tags.tag(tagId);
|
||||
if (!tag) return;
|
||||
return showDialog((Dialogs, perform) => (
|
||||
<Dialogs.ItemDialog
|
||||
title={"Edit tag"}
|
||||
subtitle={`You are editing #${tag.alias || tag.title}.`}
|
||||
item={tag}
|
||||
onClose={() => perform(false)}
|
||||
onAction={async (title) => {
|
||||
if (!title) return;
|
||||
await db.tags.rename(tagId, title);
|
||||
showToast("success", "Tag edited!");
|
||||
tagStore.refresh();
|
||||
perform(true);
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -52,9 +52,13 @@ export const CREATE_BUTTON_MAP = {
|
||||
onClick: () => hashNavigate("/notebooks/create"),
|
||||
},
|
||||
topics: {
|
||||
title: "Add a topic",
|
||||
title: "Create a topic",
|
||||
onClick: () => hashNavigate(`/topics/create`),
|
||||
},
|
||||
tags: {
|
||||
title: "Create a tag",
|
||||
onClick: () => hashNavigate(`/tags/create`),
|
||||
},
|
||||
};
|
||||
|
||||
export async function introduceFeatures() {
|
||||
|
||||
@@ -10,7 +10,7 @@ import MoveDialog from "./movenotedialog";
|
||||
import PasswordDialog from "./passworddialog";
|
||||
import RecoveryKeyDialog from "./recoverykeydialog";
|
||||
import SignUpDialog from "./signupdialog";
|
||||
import TopicDialog from "./topicdialog";
|
||||
import ItemDialog from "./itemdialog";
|
||||
import SessionExpiredDialog from "./sessionexpireddialog";
|
||||
import FeatureDialog from "./feature-dialog";
|
||||
|
||||
@@ -27,7 +27,7 @@ const Dialogs = {
|
||||
PasswordDialog,
|
||||
RecoveryKeyDialog,
|
||||
SignUpDialog,
|
||||
TopicDialog,
|
||||
ItemDialog,
|
||||
SessionExpiredDialog,
|
||||
FeatureDialog,
|
||||
};
|
||||
|
||||
46
apps/web/src/components/dialogs/item-dialog.js
Normal file
46
apps/web/src/components/dialogs/item-dialog.js
Normal file
@@ -0,0 +1,46 @@
|
||||
import React, { useRef } from "react";
|
||||
import { Box } from "rebass";
|
||||
import { Input } from "@rebass/forms";
|
||||
import Dialog from "./dialog";
|
||||
import Field from "../field";
|
||||
|
||||
function ItemDialog(props) {
|
||||
return (
|
||||
<Dialog
|
||||
isOpen={true}
|
||||
title={props.title}
|
||||
description={props.subtitle}
|
||||
positiveButton={{
|
||||
props: {
|
||||
form: "itemForm",
|
||||
type: "submit",
|
||||
},
|
||||
text: props.title,
|
||||
}}
|
||||
onClose={props.onClose}
|
||||
negativeButton={{ text: "Cancel", onClick: props.onClose }}
|
||||
>
|
||||
<Box
|
||||
as="form"
|
||||
id="itemForm"
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
const title = e.target.title.value;
|
||||
props.onAction(title);
|
||||
}}
|
||||
>
|
||||
<Field
|
||||
required
|
||||
label="Title"
|
||||
id="title"
|
||||
name="title"
|
||||
autoFocus
|
||||
data-test-id="item-dialog-title"
|
||||
defaultValue={props.item?.alias || props.item?.title}
|
||||
/>
|
||||
</Box>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export default ItemDialog;
|
||||
@@ -1,36 +0,0 @@
|
||||
import React, { useRef } from "react";
|
||||
import { Box } from "rebass";
|
||||
import { Input } from "@rebass/forms";
|
||||
import Dialog from "./dialog";
|
||||
|
||||
function TopicDialog(props) {
|
||||
const ref = useRef();
|
||||
return (
|
||||
<Dialog
|
||||
isOpen={true}
|
||||
title={props.title}
|
||||
description={props.subtitle}
|
||||
icon={props.icon}
|
||||
positiveButton={{
|
||||
text: "Create topic",
|
||||
onClick: () => {
|
||||
props.onAction(ref.current.value);
|
||||
},
|
||||
}}
|
||||
onClose={props.onClose}
|
||||
negativeButton={{ text: "Cancel", onClick: props.onClose }}
|
||||
>
|
||||
<Box my={1}>
|
||||
<Input
|
||||
data-test-id="dialog-edit-topic"
|
||||
autoFocus
|
||||
ref={ref}
|
||||
placeholder="Topic title"
|
||||
defaultValue={props.topic && props.topic.title}
|
||||
></Input>
|
||||
</Box>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export default TopicDialog;
|
||||
@@ -148,7 +148,7 @@ function NavigationMenu(props) {
|
||||
{pins.map((pin) => (
|
||||
<NavigationItem
|
||||
key={pin.id}
|
||||
title={pin.title}
|
||||
title={pin.alias || pin.title}
|
||||
menu={{
|
||||
items: [
|
||||
{
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
import React from "react";
|
||||
import ListItem from "../list-item";
|
||||
import { navigate } from "../../navigation";
|
||||
import { hashNavigate, navigate } from "../../navigation";
|
||||
import { Text } from "rebass";
|
||||
import { store as appStore } from "../../stores/app-store";
|
||||
import { db } from "../../common/db";
|
||||
import * as Icon from "../icons";
|
||||
|
||||
const menuItems = [
|
||||
{
|
||||
title: () => "Edit",
|
||||
icon: Icon.Edit,
|
||||
onClick: ({ tag }) => {
|
||||
hashNavigate(`/tags/${tag.id}/edit`);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: ({ tag }) =>
|
||||
db.settings.isPinned(tag.id) ? "Remove shortcut" : "Create shortcut",
|
||||
@@ -16,13 +23,13 @@ const menuItems = [
|
||||
];
|
||||
|
||||
function Tag({ item, index }) {
|
||||
const { id, title, noteIds } = item;
|
||||
const { id, title, alias, noteIds } = item;
|
||||
return (
|
||||
<ListItem
|
||||
item={item}
|
||||
selectable={false}
|
||||
index={index}
|
||||
title={<TagNode title={title} />}
|
||||
title={<TagNode title={alias || title} />}
|
||||
footer={
|
||||
<Text mt={1} variant="subBody">
|
||||
{noteIds.length} notes
|
||||
|
||||
@@ -2,6 +2,8 @@ import React from "react";
|
||||
import Vault from "../common/vault";
|
||||
import {
|
||||
showBuyDialog,
|
||||
showCreateTagDialog,
|
||||
showEditTagDialog,
|
||||
showEmailVerificationDialog,
|
||||
} from "../common/dialog-controller";
|
||||
import {
|
||||
@@ -47,6 +49,12 @@ const hashroutes = {
|
||||
"/notebooks/:notebookId/topics/:topicId/edit": ({ notebookId, topicId }) => {
|
||||
showEditTopicDialog(notebookId, topicId);
|
||||
},
|
||||
"/tags/create": () => {
|
||||
showCreateTagDialog();
|
||||
},
|
||||
"/tags/:tagId/edit": ({ tagId }) => {
|
||||
showEditTagDialog(tagId);
|
||||
},
|
||||
"/notes/create": () => {
|
||||
closeOpenedDialog();
|
||||
hashNavigate("/notes/create", { addNonce: true, replace: true });
|
||||
|
||||
Reference in New Issue
Block a user