feat: improve UI of all dialogs

This commit is contained in:
thecodrr
2020-09-27 15:35:11 +05:00
parent 1781115ab2
commit 27c0163781
19 changed files with 447 additions and 297 deletions

View File

@@ -6,7 +6,7 @@ import { store as editorStore } from "../stores/editor-store";
import { store as trashStore } from "../stores/trash-store";
import { db } from "./index";
import { showMoveNoteDialog } from "../components/dialogs/movenotedialog";
import { confirm } from "../components/dialogs/confirm";
import { confirm, showDeleteConfirmation } from "../components/dialogs/confirm";
function createOption(key, icon, onClick) {
return {
@@ -26,12 +26,10 @@ function createOptions(options = []) {
const DeleteOption = createOption("deleteOption", Icon.Trash, async function (
state
) {
if (
!(await confirm(Icon.Trash, "Delete", "Are you sure you want to proceed?"))
)
return;
const item = state.selectedItems[0];
if (!(await showDeleteConfirmation(item.type, true))) return;
var isAnyNoteOpened = false;
const items = state.selectedItems.map((item) => {
if (item.id === editorStore.get().session.id) isAnyNoteOpened = true;

View File

@@ -1,5 +1,5 @@
import React from "react";
import { Flex, Box, Text, Button as RebassButton } from "rebass";
import { Flex, Box, Button as RebassButton } from "rebass";
import { Input } from "@rebass/forms";
import * as Icon from "../icons";
import Dialog, { showDialog } from "./dialog";
@@ -86,10 +86,13 @@ class AddNotebookDialog extends React.Component {
return (
<Dialog
isOpen={props.isOpen}
title="Notebook"
title={props.edit ? "Edit this Notebook" : "Create a Notebook"}
description={
props.edit ? "" : "Notebooks are the best way to organize your notes."
}
icon={Icon.Notebook}
positiveButton={{
text: props.edit ? "Edit" : "Add",
text: "Create notebook",
onClick: () => {
props.onDone({
title: this.title,
@@ -104,7 +107,7 @@ class AddNotebookDialog extends React.Component {
}}
negativeButton={{ text: "Cancel", onClick: props.close }}
>
<Box my={1}>
<Box>
<Input
autoFocus
onChange={(e) => (this.title = e.target.value)}
@@ -112,19 +115,16 @@ class AddNotebookDialog extends React.Component {
defaultValue={this.title}
/>
<Input
sx={{ marginTop: 1 }}
sx={{ marginTop: 2 }}
onChange={(e) => (this.description = e.target.value)}
placeholder="Enter description (optional)"
defaultValue={this.description}
/>
<Text variant="body" fontWeight="bold" my={1}>
Topics (optional):
</Text>
<Box
mt={2}
sx={{
maxHeight: this.MAX_AVAILABLE_HEIGHT,
overflowY: "auto",
marginBottom: 1,
}}
>
{this.state.topics.map(
@@ -164,7 +164,7 @@ class AddNotebookDialog extends React.Component {
/>
<RebassButton
variant="tertiary"
sx={{ marginLeft: 1 }}
sx={{ marginLeft: 2 }}
px={2}
py={1}
onClick={() => this.performActionOnTopic(index)}

View File

@@ -1,6 +1,7 @@
import React from "react";
import { Box, Text } from "rebass";
import Dialog, { showDialog } from "./dialog";
import * as Icon from "../icons";
function Confirm(props) {
return (
@@ -8,14 +9,15 @@ function Confirm(props) {
isOpen={true}
title={props.title}
icon={props.icon}
description={props.subtitle}
positiveButton={{
text: "Yes",
text: props.yesText,
onClick: props.onYes,
}}
negativeButton={{ text: "No", onClick: props.onNo }}
negativeButton={{ text: props.noText, onClick: props.onNo }}
>
<Box my={1}>
<Text textAlign="center" variant="body">
<Box my={2}>
<Text as="span" variant="body" fontSize={18}>
{props.message}
</Text>
</Box>
@@ -23,14 +25,67 @@ function Confirm(props) {
);
}
export function confirm(icon, title, message) {
export function confirm(icon, { title, subtitle, message, yesText, noText }) {
return showDialog((perform) => (
<Confirm
title={title}
subtitle={subtitle}
message={message}
yesText={yesText}
noText={noText}
icon={icon}
onNo={() => perform(false)}
onYes={() => perform(true)}
/>
));
}
/**
*
* @param {"note"|"notebook"} type
*/
export function showDeleteConfirmation(type, multi = false) {
let noun = type === "note" ? "Note" : "Notebook";
if (multi) noun += "s";
let lowerCaseNoun = noun.toLowerCase();
let [firstPronoun, secondPronoun] = multi
? ["these", "they"]
: ["this", "it"];
return confirm(Icon.Trash, {
title: `Delete ${noun}`,
subtitle: `Are you sure you want to delete ${firstPronoun} ${lowerCaseNoun}?`,
message: (
<Text as="span">
The {lowerCaseNoun} will be{" "}
<Text as="span" color="primary">
kept in your Trash for 7 days
</Text>{" "}
after which {secondPronoun} will be permanently removed.
</Text>
),
yesText: `Delete ${lowerCaseNoun}`,
noText: "Cancel",
});
}
export function showMultiDeleteConfirmation(type) {
let noun = type === "note" ? "Notes" : "Notebooks";
return confirm(Icon.Trash, {
title: `Delete these ${noun}`,
subtitle: `Are you sure you want to delete these ${type}s?`,
message: (
<Text as="span">
These {type}s will be{" "}
<Text as="span" color="primary">
kept in your Trash for 7 days
</Text>{" "}
after which they will be permanently removed.
</Text>
),
yesText: `Delete these ${type}s`,
noText: "Cancel",
});
}

View File

@@ -5,13 +5,13 @@ import ThemeProvider from "../theme-provider";
import * as Icon from "../icons";
import Modal from "react-modal";
import useMobile from "../../utils/use-mobile";
import { useTheme } from "emotion-theming";
function Dialog(props) {
const isMobile = useMobile();
const theme = useTheme();
return (
<ThemeProvider>
{(theme) => (
<Modal
isOpen={props.isOpen || false}
shouldCloseOnOverlayClick={true}
@@ -28,10 +28,9 @@ function Dialog(props) {
borderRadius: theme.radii["default"],
backgroundColor: theme.colors.background,
color: theme.colors.text,
//boxShadow: theme.shadows["3"],
width: isMobile ? "80%" : "25%",
paddingRight: 20,
paddingLeft: 20,
boxShadow: "4px 5px 18px 2px #00000038",
width: isMobile ? "80%" : "30%",
padding: 0,
overflowY: "hidden",
},
overlay: {
@@ -40,21 +39,31 @@ function Dialog(props) {
},
}}
>
<Flex flexDirection="column">
<Flex variant="rowCenter" pb={2}>
<Flex p={30} flexDirection="column">
<Flex
variant="columnCenter"
pb={2}
mb={3}
sx={{ borderBottom: "1px solid", borderColor: "border" }}
>
<props.icon size={props.iconSize || 38} color="primary" />
<Text variant="heading" color="primary" mx={1}>
<Text variant="heading" textAlign="center" color="text" mx={1} mt={1}>
{props.title}
</Text>
<Text variant="body" textAlign="center" color="gray" mx={1} mt={1}>
{props.description}
</Text>
</Flex>
{props.children}
<Flex variant="rowCenter" mt={3}>
<Flex
sx={{ justifyContent: props.buttonsAlignment || "flex-end" }}
mt={3}
>
{props.positiveButton && (
<RebassButton
variant="primary"
sx={{ opacity: props.positiveButton.disabled ? 0.7 : 1 }}
mx={1}
width={"50%"}
disabled={props.positiveButton.disabled || false}
onClick={
!props.positiveButton.disabled
@@ -69,21 +78,18 @@ function Dialog(props) {
)}
</RebassButton>
)}
{props.negativeButton && (
<RebassButton
variant="secondary"
width={"50%"}
onClick={props.negativeButton.onClick}
>
{props.negativeButton.text || "Cancel"}
</RebassButton>
)}
</Flex>
{props.footer}
</Flex>
</Modal>
)}
</ThemeProvider>
);
}
export default Dialog;
@@ -97,7 +103,7 @@ export function showDialog(dialog) {
if (root) {
return new Promise((resolve) => {
const PropDialog = dialog(perform.bind(this, resolve));
ReactDOM.render(PropDialog, root);
ReactDOM.render(<ThemeProvider>{PropDialog}</ThemeProvider>, root);
});
}
return Promise.reject("No element with id 'dialogContainer'");

View File

@@ -1,5 +1,5 @@
import React from "react";
import { Flex, Button, Text, Box } from "rebass";
import { Flex, Button, Text } from "rebass";
import { db } from "../../common";
import download from "../../utils/download";
import { showToast } from "../../utils/toast";
@@ -12,38 +12,33 @@ function ExportDialog(props) {
isOpen={true}
title={props.title}
icon={props.icon}
negativeButton={{ onClick: props.onClose, text: "Cancel" }}
description="You can export your note to Markdown, HTML, or Text."
buttonsAlignment="center"
negativeButton={{
onClick: props.onClose,
text: "I don't want to export anymore",
}}
>
<Box>
<Text variant="body" mb={2}>
Please choose a format to export the note into:
</Text>
<Flex my={1} justifyContent="center" alignItems="center">
<Button
variant="tertiary"
mr={2}
onClick={() => props.exportNote("html")}
>
<Icon.HTML size={100} color="dimPrimary" /> HTML
<Flex justifyContent="center" alignItems="center">
<Button mr={2} onClick={() => props.exportNote("html")}>
<Flex variant="rowCenter">
<Icon.HTML color="static" />
<Text ml={1}>HTML</Text>
</Flex>
</Button>
<Button
variant="tertiary"
mr={2}
onClick={() => props.exportNote("md")}
>
<Icon.Markdown size={100} color="dimPrimary" />
Markdown
<Button mr={2} onClick={() => props.exportNote("md")}>
<Flex variant="rowCenter">
<Icon.Markdown color="static" />
<Text ml={1}>Markdown</Text>
</Flex>
</Button>
<Button
variant="tertiary"
mr={2}
onClick={() => props.exportNote("txt")}
>
<Icon.Text size={100} color="dimPrimary" />
Text
<Button mr={2} onClick={() => props.exportNote("txt")}>
<Flex variant="rowCenter">
<Icon.Text color="static" />
<Text ml={1}>Text</Text>
</Flex>
</Button>
</Flex>
</Box>
</Dialog>
);
}
@@ -51,7 +46,7 @@ function ExportDialog(props) {
export function showExportDialog(noteId) {
return showDialog((perform) => (
<ExportDialog
title={"Export Note"}
title={"Export your Note"}
icon={Icon.Export}
onClose={() => perform(false)}
exportNote={async (format) => {

View File

@@ -1,5 +1,5 @@
import React, { useState } from "react";
import { Box, Button, Text } from "rebass";
import { Flex, Button, Text } from "rebass";
import Input from "../inputs";
import * as Icon from "../icons";
import Dialog, { showDialog } from "./dialog";
@@ -18,19 +18,38 @@ function LoginDialog(props) {
return (
<Dialog
isOpen={true}
title={"Login"}
title={"Sign in to Your Account"}
description={"Signing in allows you to sync your notes across devices."}
icon={Icon.Login}
onCloseClick={onClose}
negativeButton={{ onClick: onClose }}
negativeButton={{ text: "I don't want to", onClick: onClose }}
positiveButton={{
text: "Login",
text: "Sign me in",
loading: isLoggingIn,
disabled: isLoggingIn,
onClick: () => submit(setError, form, login, onClose),
}}
buttonsAlignment="center"
footer={
<>
<Text textAlign="center" color="gray" mt={3}>
Don't have an account?
</Text>
<Button
mt={3}
variant="anchor"
justifySelf="center"
alignSelf="center"
fontSize="body"
onClick={showSignUpDialog}
>
<Box
mt={1}
Sign up here
</Button>
</>
}
>
<Flex
variant="columnFill"
onKeyDown={(e) => {
if (e.key === "Enter") submit(setError, form, login, onClose);
}}
@@ -39,11 +58,11 @@ function LoginDialog(props) {
<Input autoFocus name="username" title="Username" />
<PasswordInput />
</Dropper>
<Button variant="anchor" onClick={showSignUpDialog}>
Create a New Account
</Button>
{error && <Text variant="error">{error}</Text>}
</Box>
{/* <Button variant="anchor" onClick={showSignUpDialog}>
I don't have an account
</Button> */}
</Flex>
</Dialog>
);
}

View File

@@ -1,5 +1,5 @@
import React from "react";
import { Flex, Box, Text } from "rebass";
import { Flex, Box, Text, Button } from "rebass";
import { Input } from "@rebass/forms";
import * as Icon from "../icons";
import { db } from "../../common";
@@ -14,73 +14,32 @@ class MoveDialog extends React.Component {
selectedNotebook;
selectedTopic;
state = {
items: db.notebooks.all,
type: "notebooks",
title: "Notebooks",
mode: "read",
currentOpenedIndex: -1,
notebooks: db.notebooks.all,
};
render() {
const { items, type, title, mode } = this.state;
const { notebooks, currentOpenedIndex } = this.state;
const props = this.props;
return (
<Dialog
isOpen={true}
title={
type === "notes"
? "Move Note"
: "Select " + toTitleCase(type.substring(0, type.length - 1))
}
icon={
type === "notes"
? Icon.Move
: type === "topics"
? Icon.Topic
: Icon.Notebook
}
positiveButton={{
text: "Move",
onClick: async () => {
try {
const notebook = {
id: this.selectedNotebook.id,
topic: this.selectedTopic,
};
const note = db.notes.note(props.noteIds[0]).data;
await db.notes.move(notebook, ...props.noteIds);
showNotesMovedToast(note, props.noteIds, notebook);
props.onMove();
} catch (e) {
showToast("error", e.message);
console.error(e);
} finally {
props.onClose();
}
},
disabled: type !== "notes",
title={"Add Note to Notebook"}
description={"Organize your notes by adding them to notebooks."}
icon={Icon.Move}
buttonsAlignment="center"
negativeButton={{
text: "Get me out of here",
onClick: props.onClose,
}}
negativeButton={{ text: "Cancel", onClick: props.onClose }}
>
<Box>
<Flex alignContent="center" justifyContent="space-between" my={1}>
<Flex>
<Text
onClick={() => {
let item = this.history.pop();
this.setState({ ...item });
}}
sx={{
display: this.history.length ? "block" : "none",
":hover": { color: "primary" },
marginRight: 2,
}}
>
<Icon.ArrowLeft />
</Text>
<Text variant="title">{title}</Text>
</Flex>
<Text
onClick={() => {
<Flex alignItems="center" justifyContent="space-between" mb={2}>
<Text variant="title">Notebooks</Text>
<Button
variant="anchor"
fontSize="body"
/* onClick={() => {
if (mode === "write") {
this.setState({ mode: "read" });
return;
@@ -89,16 +48,12 @@ class MoveDialog extends React.Component {
setTimeout(() => {
this._inputRef.focus();
}, 0);
}}
sx={{
display: type === "notes" ? "none" : "block",
":hover": { color: "primary" },
}}
}} */
>
{mode === "read" ? <Icon.Plus /> : <Icon.Minus />}
</Text>
Create
</Button>
</Flex>
<Input
{/* <Input
ref={(ref) => (this._inputRef = ref)}
sx={{ display: mode === "write" ? "block" : "none" }}
my={1}
@@ -123,7 +78,7 @@ class MoveDialog extends React.Component {
this.setState({ mode: "read" });
}
}}
/>
/> */}
<Box
sx={{
borderWidth: 1,
@@ -133,20 +88,11 @@ class MoveDialog extends React.Component {
overflowY: "auto",
}}
>
{items.length ? (
items.map((item) => {
return (
{notebooks.map((notebook, index) => (
<Flex
key={item.title + item.dateCreated}
sx={{
borderWidth: 1,
padding: 2,
borderBottomColor: "border",
borderBottomStyle: "solid",
cursor: "pointer",
":hover": { borderBottomColor: "primary" },
}}
onClick={() => {
variant="columnFill"
key={notebook.id}
/* onClick={() => {
this.history.push({
title,
items,
@@ -169,31 +115,59 @@ class MoveDialog extends React.Component {
});
this.selectedTopic = item.title;
}
}} */
>
<Item
icon={Icon.Notebook}
title={notebook.title}
totalNotes={notebook.totalNotes}
onClick={() =>
this.setState({
currentOpenedIndex:
this.state.currentOpenedIndex === index ? -1 : index,
})
}
/>
<Flex
variant="columnFill"
style={{
display: currentOpenedIndex === index ? "flex" : "none",
}}
>
<Text sx={{ width: "80%" }} fontSize="body">
{item.title}
{notebook.topics.map((topic) => (
<Item
key={topic.id}
onClick={async () => {
try {
const nb = {
id: notebook.id,
topic: topic.id,
};
const note = db.notes.note(props.noteIds[0]).data;
await db.notes.move(nb, ...props.noteIds);
showNotesMovedToast(note, props.noteIds, nb);
props.onMove();
} catch (e) {
showToast("error", e.message);
console.error(e);
} finally {
props.onClose();
}
}}
indent={1}
icon={Icon.Topic}
title={topic.title}
totalNotes={topic.totalNotes}
action={
<Text color="primary" fontSize="body">
Move here
</Text>
{item.totalNotes !== undefined && (
<Text
sx={{ width: "20%", textAlign: "right" }}
fontSize="body"
>
{item.totalNotes + " Notes"}
</Text>
)}
}
/>
))}
</Flex>
);
})
) : (
<Text
py={2}
px={2}
sx={{ textAlign: "center", fontStyle: "italic" }}
>
Nothing here
</Text>
)}
</Flex>
))}
</Box>
</Box>
</Dialog>
@@ -210,3 +184,35 @@ export function showMoveNoteDialog(noteIds) {
/>
));
}
function Item(props) {
const { icon: Icon, indent = 0, title, totalNotes, onClick, action } = props;
return (
<Flex
p={2}
justifyContent="space-between"
alignItems="center"
pl={!indent ? 2 : indent * 30}
sx={{
borderWidth: 1,
borderBottomColor: "border",
borderBottomStyle: "solid",
cursor: "pointer",
":hover": { borderBottomColor: "primary" },
}}
onClick={onClick}
>
<Flex alignItems="center" justifyContent="center">
<Icon />
<Text as="span" ml={1} fontSize="body">
{title}
</Text>
</Flex>
{action || (
<Text sx={{ textAlign: "right" }} fontSize="body">
{totalNotes + " Notes"}
</Text>
)}
</Flex>
);
}

View File

@@ -20,6 +20,7 @@ function PasswordDialog(props) {
<Dialog
isOpen={true}
title={props.title}
description={props.subtitle}
icon={props.icon}
positiveButton={{
text: props.positiveButtonText,
@@ -59,21 +60,24 @@ function getDialogData(type) {
switch (type) {
case "create_vault":
return {
title: "Set Up Your Vault",
title: "Create Your Vault",
subtitle: "Your vault will encrypt everything locally.",
icon: Icon.Vault,
positiveButtonText: "Done",
positiveButtonText: "Create my vault",
};
case "unlock_vault":
return {
title: "Unlock Vault",
title: "Unlock your Vault",
subtitle: "Your vault will remain unlocked for 30 minutes.",
icon: Icon.Unlock,
positiveButtonText: "Unlock",
positiveButtonText: "Unlock my vault",
};
case "unlock_note":
return {
title: "Unlock Note",
title: "Unlock your Note",
subtitle: "Unlocking will make this note openly available.",
icon: Icon.Unlock,
positiveButtonText: "Unlock",
positiveButtonText: "Unlock this note",
};
default:
return;
@@ -81,10 +85,11 @@ function getDialogData(type) {
}
export function showPasswordDialog(type, validate) {
const { title, icon, positiveButtonText } = getDialogData(type);
const { title, subtitle, icon, positiveButtonText } = getDialogData(type);
return showDialog((perform) => (
<PasswordDialog
title={title}
subtitle={subtitle}
icon={icon}
positiveButtonText={positiveButtonText}
onCancel={() => perform(false)}

View File

@@ -1,5 +1,5 @@
import React, { useState } from "react";
import { Text, Box } from "rebass";
import { Text, Box, Button } from "rebass";
import Input from "../inputs";
import * as Icon from "../icons";
import Dialog, { showDialog } from "./dialog";
@@ -8,6 +8,7 @@ import EmailInput from "../inputs/email";
import PasswordInput from "../inputs/password";
import Dropper from "../dropper";
import { useStore } from "../../stores/user-store";
import { showLogInDialog } from "./logindialog";
const form = { error: true };
function SignUpDialog(props) {
@@ -19,19 +20,35 @@ function SignUpDialog(props) {
return (
<Dialog
isOpen={true}
title={"Sign Up"}
icon={Icon.User}
title={"Create a new Account"}
description={"Sign up for a 14-day free trial (no credit card)."}
icon={Icon.Signup}
onCloseClick={onClose}
negativeButton={{ onClick: onClose }}
negativeButton={{ text: "I don't want to", onClick: onClose }}
buttonsAlignment="center"
positiveButton={{
text: "Sign Up",
text: "Create my account",
loading: isSigningIn,
disabled: isSigningIn,
onClick: () => submit(setError, form, signup, onClose),
}}
footer={
<>
<Text textAlign="center" color="gray" mt={3}>
Already have an account?
</Text>
<Button
variant="anchor"
mt={2}
fontSize="body"
onClick={showLogInDialog}
>
Sign in here.
</Button>
</>
}
>
<Box
mt={1}
onKeyDown={(e) => {
if (e.key === "Enter") submit(setError, form, signup, onClose);
}}

View File

@@ -13,9 +13,10 @@ function TopicDialog(props) {
<Dialog
isOpen={true}
title={props.title}
description="You can create as many topics as you want."
icon={props.icon}
positiveButton={{
text: "Add",
text: "Create topic",
onClick: () => {
props.onYes(ref.current.value);
},
@@ -37,7 +38,7 @@ function TopicDialog(props) {
export function showTopicDialog(notebook) {
return showDialog((perform) => (
<TopicDialog
title={"Topic"}
title={"Create a Topic"}
icon={Icon.Topic}
onNo={() => {
perform(false);

View File

@@ -38,7 +38,7 @@ export const Plus = createIcon(Icons.mdiPlus);
export const Minus = createIcon(Icons.mdiMinus);
export const Notebook = createIcon(Icons.mdiBookOutline);
export const ArrowLeft = createIcon(Icons.mdiArrowLeft);
export const Move = createIcon(Icons.mdiArrowAll);
export const Move = createIcon(Icons.mdiBookPlusMultipleOutline);
export const Topic = createIcon(Icons.mdiFormatTitle);
export const Alert = createIcon(Icons.mdiAlert);
export const Vault = createIcon(Icons.mdiShieldOutline);
@@ -54,6 +54,7 @@ export const Trash = createIcon(Icons.mdiTrashCanOutline);
export const Search = createIcon(Icons.mdiMagnify);
export const Menu = createIcon(Icons.mdiMenu);
export const Login = createIcon(Icons.mdiLoginVariant);
export const Signup = createIcon(Icons.mdiAccountPlusOutline);
export const Logout = createIcon(Icons.mdiLogoutVariant);
export const FocusMode = createIcon(Icons.mdiFullscreen);
export const NormalMode = createIcon(Icons.mdiFullscreenExit);
@@ -62,7 +63,7 @@ export const Home = createIcon(Icons.mdiHomeOutline);
export const Restore = createIcon(Icons.mdiRecycle);
export const Sync = createIcon(Icons.mdiSync);
export const Loading = createIcon(Icons.mdiLoading, true);
export const Export = createIcon(Icons.mdiExport);
export const Export = createIcon(Icons.mdiExportVariant);
export const AddToNotebook = createIcon(Icons.mdiBookPlusMultipleOutline);
/** Properties Icons */

View File

@@ -3,7 +3,7 @@ import { Flex, Box, Text } from "rebass";
import * as Icon from "../icons";
import TimeAgo from "timeago-react";
import ListItem from "../list-item";
import { confirm } from "../dialogs/confirm";
import { confirm, showDeleteConfirmation } from "../dialogs/confirm";
import { showMoveNoteDialog } from "../dialogs/movenotedialog";
import { store, useStore } from "../../stores/note-store";
import { store as editorStore } from "../../stores/editor-store";
@@ -65,17 +65,31 @@ function menuItems(note, context) {
},
{
visible: context?.type === "topic",
title: "Remove",
title: "Remove from topic",
onClick: async () => {
confirm(
Icon.Topic,
"Remove from Topic",
"Are you sure you want to remove this note?"
).then(async (res) => {
confirm(Icon.Topic, {
title: "Remove Note from Topic",
subtitle: "Are you sure you want to remove the note from this topic?",
yesText: "Remove note",
noText: "Cancel",
message: (
<Text as="span">
<Text as="span" color="primary">
This action does not delete the note.
</Text>{" "}
The note will only be removed from this notebook. You will still
be able to{" "}
<Text as="span" color="primary">
access it from Home and other places.
</Text>
</Text>
),
}).then(async (res) => {
if (res) {
console.log(context);
await db.notebooks
.notebook(context.notebook.id)
.topics.topic(context.value)
.notebook(context.value.id)
.topics.topic(context.value.topic)
.delete(note.id);
store.setContext(context);
}
@@ -95,11 +109,7 @@ function menuItems(note, context) {
});
if (!res) return;
}
confirm(
Icon.Trash,
"Delete",
"Are you sure you want to delete this note?"
).then(async (res) => {
showDeleteConfirmation("note").then(async (res) => {
if (res) {
await store.delete(note.id).then(() => showItemDeletedToast(note));
}

View File

@@ -4,7 +4,7 @@ import ListItem from "../list-item";
import { store } from "../../stores/notebook-store";
import * as Icon from "../icons";
import { showEditNoteDialog } from "../dialogs/addnotebookdialog";
import { confirm } from "../dialogs/confirm";
import { confirm, showDeleteConfirmation } from "../dialogs/confirm";
import { showItemDeletedToast, showUnpinnedToast } from "../../common/toasts";
const pin = async (notebook, index) => {
await store.pin(notebook, index);
@@ -24,11 +24,7 @@ function menuItems(notebook, index) {
title: "Delete",
color: "red",
onClick: () => {
confirm(
Icon.Trash,
"Delete Notebook",
"Are you sure you want to delete this notebook?"
).then(async (res) => {
showDeleteConfirmation("notebook").then(async (res) => {
if (res) {
await store
.delete(notebook.id, index)

View File

@@ -5,6 +5,7 @@ import { confirm } from "../dialogs/confirm";
import * as Icon from "../icons";
import { db } from "../../common";
import { store } from "../../stores/notebook-store";
import { Text } from "rebass";
const menuItems = (item) => [
{
@@ -19,11 +20,24 @@ const menuItems = (item) => [
visible: item.title !== "General",
color: "red",
onClick: () => {
confirm(
Icon.Trash,
"Delete Topic",
"Are you sure you want to delete this topic?"
).then(async (res) => {
confirm(Icon.Trash, {
title: "Delete topic",
subtitle: "Are you sure you want to delete this topic?",
yesText: "Delete topic",
noText: "Cancel",
message: (
<>
This action is{" "}
<Text as="span" color="error">
IRREVERSIBLE
</Text>
. Deleting this topic{" "}
<Text as="span" color="primary">
will not delete the notes contained in it.
</Text>
</>
),
}).then(async (res) => {
if (res) {
await db.notebooks.notebook(item.notebookId).topics.delete(item.id);
store.setSelectedNotebookTopics(item.notebookId);

View File

@@ -25,11 +25,24 @@ function menuItems(item, index) {
title: "Delete",
color: "red",
onClick: () => {
confirm(
Icon.Trash,
"Delete",
`Are you sure you want to permanently delete this item?`
).then(async (res) => {
confirm(Icon.Trash, {
title: `Permanently Delete ${toTitleCase(item.itemType)}`,
subtitle: `Are you sure you want to permanently delete this ${item.itemType}?`,
yesText: `Delete ${item.itemType}`,
noText: "Cancel",
message: (
<>
This action is{" "}
<Text as="span" color="error">
IRREVERSIBLE
</Text>
. You will{" "}
<Text as="span" color="primary">
not be able to recover this {item.itemType}.
</Text>
</>
),
}).then(async (res) => {
if (res) {
await store.delete(item.id, index);
showPermanentDeleteToast(item, index);
@@ -54,7 +67,7 @@ function TrashItem({ item, index }) {
<Text as="span" mx={1}>
</Text>
<Text color="primary">{toTitleCase(item.type)}</Text>
<Text color="primary">{toTitleCase(item.itemType)}</Text>
</Flex>
}
menuData={item}

View File

@@ -7,7 +7,7 @@ class FontSizeFactory {
subtitle: 16 * scaleFactor,
body: 16 * scaleFactor,
menu: 14 * scaleFactor,
subBody: 11 * scaleFactor,
subBody: 12 * scaleFactor,
};
}
}

View File

@@ -36,7 +36,7 @@ const routes = {
<Notes
context={{
type: "topic",
value: { id: notebook, topic: topicItem.title },
value: { id: notebook, topic: topic },
}}
/>
}

View File

@@ -31,7 +31,7 @@ function Topics(props) {
context={{ notebookId }}
placeholder={Flex}
button={{
content: "Add more topics",
content: "Create a new topic",
onClick: async () => {
await showTopicDialog(notebookId);
},

View File

@@ -5,6 +5,7 @@ import { confirm } from "../components/dialogs/confirm";
import { useStore, store } from "../stores/trash-store";
import TrashPlaceholder from "../components/placeholders/trash-placeholder";
import { showToast } from "../utils/toast";
import { Text } from "rebass";
function Trash() {
useEffect(() => store.refresh(), []);
@@ -19,11 +20,24 @@ function Trash() {
content: "Clear Trash",
icon: Icon.Trash,
onClick: function () {
confirm(
Icon.Trash,
"Clear",
`This action is irreversible. Are you sure you want to proceed?`
).then(async (res) => {
confirm(Icon.Trash, {
title: "Clear Trash",
subtitle: "Are you sure you want to clear all the trash?",
yesText: "Clear trash",
noText: "Cancel",
message: (
<>
This action is{" "}
<Text as="span" color="error">
IRREVERSIBLE
</Text>
. You will{" "}
<Text as="span" color="primary">
not be able to recover any of these items.
</Text>
</>
),
}).then(async (res) => {
if (res) {
try {
await clearTrash();