mirror of
https://github.com/zadam/trilium.git
synced 2025-10-21 15:49:00 +02:00
feat(react/ribbon): port toggle protected note
This commit is contained in:
parent
5945f2860a
commit
1964fb90d5
@ -1,39 +0,0 @@
|
|||||||
import type { EventData } from "../components/app_context.js";
|
|
||||||
import type FNote from "../entities/fnote.js";
|
|
||||||
import { t } from "../services/i18n.js";
|
|
||||||
import protectedSessionService from "../services/protected_session.js";
|
|
||||||
import SwitchWidget from "./switch.js";
|
|
||||||
|
|
||||||
export default class ProtectedNoteSwitchWidget extends SwitchWidget {
|
|
||||||
doRender() {
|
|
||||||
super.doRender();
|
|
||||||
|
|
||||||
this.switchOnName = t("protect_note.toggle-on");
|
|
||||||
this.switchOnTooltip = t("protect_note.toggle-on-hint");
|
|
||||||
|
|
||||||
this.switchOffName = t("protect_note.toggle-off");
|
|
||||||
this.switchOffTooltip = t("protect_note.toggle-off-hint");
|
|
||||||
}
|
|
||||||
|
|
||||||
switchOn() {
|
|
||||||
if (this.noteId) {
|
|
||||||
protectedSessionService.protectNote(this.noteId, true, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switchOff() {
|
|
||||||
if (this.noteId) {
|
|
||||||
protectedSessionService.protectNote(this.noteId, false, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async refreshWithNote(note: FNote) {
|
|
||||||
this.isToggled = note.isProtected;
|
|
||||||
}
|
|
||||||
|
|
||||||
entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) {
|
|
||||||
if (loadResults.isNoteReloaded(this.noteId)) {
|
|
||||||
this.refresh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
98
apps/client/src/widgets/react/FormToggle.css
Normal file
98
apps/client/src/widgets/react/FormToggle.css
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
.switch-widget {
|
||||||
|
--switch-track-width: 50px;
|
||||||
|
--switch-track-height: 24px;
|
||||||
|
--switch-off-track-background: var(--more-accented-background-color);
|
||||||
|
--switch-on-track-background: var(--main-text-color);
|
||||||
|
|
||||||
|
--switch-thumb-width: 16px;
|
||||||
|
--switch-thumb-height: 16px;
|
||||||
|
--switch-off-thumb-background: var(--main-background-color);
|
||||||
|
--switch-on-thumb-background: var(--main-background-color);
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The track of the toggle switch */
|
||||||
|
|
||||||
|
.switch-widget .switch-button {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
margin-left: 8px;
|
||||||
|
width: var(--switch-track-width);
|
||||||
|
height: var(--switch-track-height);
|
||||||
|
border-radius: 24px;
|
||||||
|
background-color: var(--switch-off-track-background);
|
||||||
|
transition: background 200ms ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-widget .switch-button.on {
|
||||||
|
background: var(--switch-on-track-background);
|
||||||
|
transition: background 100ms ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The thumb of the toggle switch */
|
||||||
|
|
||||||
|
.switch-widget .switch-button:after {
|
||||||
|
--y: calc((var(--switch-track-height) - var(--switch-thumb-height)) / 2);
|
||||||
|
--x: var(--y);
|
||||||
|
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: var(--switch-thumb-width);
|
||||||
|
height: var(--switch-thumb-height);
|
||||||
|
background-color: var(--switch-off-thumb-background);
|
||||||
|
border-radius: 50%;
|
||||||
|
transform: translate(var(--x), var(--y));
|
||||||
|
transition: transform 600ms cubic-bezier(0.22, 1, 0.36, 1),
|
||||||
|
background 200ms ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-widget .switch-button.on:after {
|
||||||
|
--x: calc(var(--switch-track-width) - var(--switch-thumb-width) - var(--y));
|
||||||
|
|
||||||
|
background: var(--switch-on-thumb-background);
|
||||||
|
transition: transform 200ms cubic-bezier(0.64, 0, 0.78, 0),
|
||||||
|
background 100ms ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.switch-widget .switch-button input[type="checkbox"] {
|
||||||
|
/* A hidden check box for accesibility purposes */
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disabled state */
|
||||||
|
.switch-widget .switch-button:not(.disabled) input[type="checkbox"],
|
||||||
|
.switch-widget .switch-button:not(.disabled) {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-widget .switch-button:has(input[type="checkbox"]:focus-visible) {
|
||||||
|
outline: 2px solid var(--button-border-color);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-widget .switch-button.disabled {
|
||||||
|
opacity: 70%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-widget .switch-help-button {
|
||||||
|
border: 0;
|
||||||
|
margin-left: 4px;
|
||||||
|
background: none;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 1.1em;
|
||||||
|
color: var(--muted-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-widget .switch-help-button:hover {
|
||||||
|
color: var(--main-text-color);
|
||||||
|
}
|
47
apps/client/src/widgets/react/FormToggle.tsx
Normal file
47
apps/client/src/widgets/react/FormToggle.tsx
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import { t } from "../../services/i18n";
|
||||||
|
import { openInAppHelpFromUrl } from "../../services/utils";
|
||||||
|
import "./FormToggle.css";
|
||||||
|
|
||||||
|
interface FormToggleProps {
|
||||||
|
currentValue: boolean | null;
|
||||||
|
onChange(newValue: boolean): void;
|
||||||
|
switchOnName: string;
|
||||||
|
switchOnTooltip: string;
|
||||||
|
switchOffName: string;
|
||||||
|
switchOffTooltip: string;
|
||||||
|
helpPage?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function FormToggle({ currentValue, helpPage, switchOnName, switchOnTooltip, switchOffName, switchOffTooltip, onChange }: FormToggleProps) {
|
||||||
|
return (
|
||||||
|
<div className="switch-widget">
|
||||||
|
<span className="switch-name">{ currentValue ? switchOffName : switchOnName }</span>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
<div
|
||||||
|
className={`switch-button ${currentValue ? "on" : ""}`}
|
||||||
|
title={currentValue ? switchOffTooltip : switchOnTooltip }
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
className="switch-toggle"
|
||||||
|
type="checkbox"
|
||||||
|
checked={currentValue === true}
|
||||||
|
onInput={(e) => {
|
||||||
|
onChange(!currentValue);
|
||||||
|
e.preventDefault();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
{ helpPage && (
|
||||||
|
<button
|
||||||
|
class="switch-help-button icon-action bx bx-help-circle"
|
||||||
|
type="button"
|
||||||
|
onClick={() => openInAppHelpFromUrl(helpPage)}
|
||||||
|
title={t("open-help-page")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
@ -8,22 +8,27 @@ import mime_types from "../../services/mime_types";
|
|||||||
import { NoteType } from "@triliumnext/commons";
|
import { NoteType } from "@triliumnext/commons";
|
||||||
import server from "../../services/server";
|
import server from "../../services/server";
|
||||||
import dialog from "../../services/dialog";
|
import dialog from "../../services/dialog";
|
||||||
|
import FormToggle from "../react/FormToggle";
|
||||||
|
import FNote from "../../entities/fnote";
|
||||||
|
import protected_session from "../../services/protected_session";
|
||||||
|
|
||||||
export default function BasicPropertiesTab() {
|
export default function BasicPropertiesTab() {
|
||||||
|
const { note } = useNoteContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="basic-properties-widget">
|
<div className="basic-properties-widget">
|
||||||
<NoteTypeWidget />
|
<NoteTypeWidget note={note} />
|
||||||
|
<ProtectedNoteSwitch note={note} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function NoteTypeWidget() {
|
function NoteTypeWidget({ note }: { note?: FNote | null }) {
|
||||||
const noteTypes = useMemo(() => NOTE_TYPES.filter((nt) => !nt.reserved && !nt.static), []);
|
const noteTypes = useMemo(() => NOTE_TYPES.filter((nt) => !nt.reserved && !nt.static), []);
|
||||||
const [ codeNotesMimeTypes ] = useTriliumOption("codeNotesMimeTypes");
|
const [ codeNotesMimeTypes ] = useTriliumOption("codeNotesMimeTypes");
|
||||||
const mimeTypes = useMemo(() => mime_types.getMimeTypes().filter(mimeType => mimeType.enabled), [ codeNotesMimeTypes ]);
|
const mimeTypes = useMemo(() => mime_types.getMimeTypes().filter(mimeType => mimeType.enabled), [ codeNotesMimeTypes ]);
|
||||||
const notSelectableNoteTypes = useMemo(() => NOTE_TYPES.filter((nt) => nt.reserved || nt.static).map((nt) => nt.type), []);
|
const notSelectableNoteTypes = useMemo(() => NOTE_TYPES.filter((nt) => nt.reserved || nt.static).map((nt) => nt.type), []);
|
||||||
|
|
||||||
const { note } = useNoteContext();
|
|
||||||
const currentNoteType = useNoteProperty(note, "type") ?? undefined;
|
const currentNoteType = useNoteProperty(note, "type") ?? undefined;
|
||||||
const currentNoteMime = useNoteProperty(note, "mime");
|
const currentNoteMime = useNoteProperty(note, "mime");
|
||||||
|
|
||||||
@ -101,6 +106,21 @@ function NoteTypeWidget() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ProtectedNoteSwitch({ note }: { note?: FNote | null }) {
|
||||||
|
const isProtected = useNoteProperty(note, "isProtected");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="protected-note-switch-container">
|
||||||
|
<FormToggle
|
||||||
|
currentValue={isProtected}
|
||||||
|
onChange={(shouldProtect) => note && protected_session.protectNote(note.noteId, shouldProtect, false)}
|
||||||
|
switchOnName={t("protect_note.toggle-on")} switchOnTooltip={t("protect_note.toggle-on-hint")}
|
||||||
|
switchOffName={t("protect_note.toggle-off")} switchOffTooltip={t("protect_note.toggle-off-hint")}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function findTypeTitle(type?: NoteType, mime?: string | null) {
|
function findTypeTitle(type?: NoteType, mime?: string | null) {
|
||||||
if (type === "code") {
|
if (type === "code") {
|
||||||
const mimeTypes = mime_types.getMimeTypes();
|
const mimeTypes = mime_types.getMimeTypes();
|
||||||
|
@ -10,8 +10,6 @@ import type FNote from "../../entities/fnote.js";
|
|||||||
import NoteLanguageWidget from "../note_language.js";
|
import NoteLanguageWidget from "../note_language.js";
|
||||||
|
|
||||||
const TPL = /*html*/`
|
const TPL = /*html*/`
|
||||||
<div class="protected-note-switch-container"></div>
|
|
||||||
|
|
||||||
<div class="editability-select-container">
|
<div class="editability-select-container">
|
||||||
<span>${t("basic_properties.editable")}:</span>
|
<span>${t("basic_properties.editable")}:</span>
|
||||||
</div>
|
</div>
|
||||||
@ -40,8 +38,6 @@ export default class BasicPropertiesWidget extends NoteContextAwareWidget {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.noteTypeWidget = new NoteTypeWidget().contentSized();
|
|
||||||
this.protectedNoteSwitchWidget = new ProtectedNoteSwitchWidget().contentSized();
|
|
||||||
this.editabilitySelectWidget = new EditabilitySelectWidget().contentSized();
|
this.editabilitySelectWidget = new EditabilitySelectWidget().contentSized();
|
||||||
this.bookmarkSwitchWidget = new BookmarkSwitchWidget().contentSized();
|
this.bookmarkSwitchWidget = new BookmarkSwitchWidget().contentSized();
|
||||||
this.sharedSwitchWidget = new SharedSwitchWidget().contentSized();
|
this.sharedSwitchWidget = new SharedSwitchWidget().contentSized();
|
||||||
|
@ -4,162 +4,22 @@ import NoteContextAwareWidget from "./note_context_aware_widget.js";
|
|||||||
const TPL = /*html*/`
|
const TPL = /*html*/`
|
||||||
<div class="switch-widget">
|
<div class="switch-widget">
|
||||||
<style>
|
<style>
|
||||||
.switch-widget {
|
|
||||||
--switch-track-width: 50px;
|
|
||||||
--switch-track-height: 24px;
|
|
||||||
--switch-off-track-background: var(--more-accented-background-color);
|
|
||||||
--switch-on-track-background: var(--main-text-color);
|
|
||||||
|
|
||||||
--switch-thumb-width: 16px;
|
|
||||||
--switch-thumb-height: 16px;
|
|
||||||
--switch-off-thumb-background: var(--main-background-color);
|
|
||||||
--switch-on-thumb-background: var(--main-background-color);
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The track of the toggle switch */
|
|
||||||
|
|
||||||
.switch-widget .switch-button {
|
|
||||||
display: block;
|
|
||||||
position: relative;
|
|
||||||
margin-left: 8px;
|
|
||||||
width: var(--switch-track-width);
|
|
||||||
height: var(--switch-track-height);
|
|
||||||
border-radius: 24px;
|
|
||||||
background-color: var(--switch-off-track-background);
|
|
||||||
transition: background 200ms ease-in;
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-widget .switch-button.on {
|
|
||||||
background: var(--switch-on-track-background);
|
|
||||||
transition: background 100ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The thumb of the toggle switch */
|
|
||||||
|
|
||||||
.switch-widget .switch-button:after {
|
|
||||||
--y: calc((var(--switch-track-height) - var(--switch-thumb-height)) / 2);
|
|
||||||
--x: var(--y);
|
|
||||||
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: var(--switch-thumb-width);
|
|
||||||
height: var(--switch-thumb-height);
|
|
||||||
background-color: var(--switch-off-thumb-background);
|
|
||||||
border-radius: 50%;
|
|
||||||
transform: translate(var(--x), var(--y));
|
|
||||||
transition: transform 600ms cubic-bezier(0.22, 1, 0.36, 1),
|
|
||||||
background 200ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-widget .switch-button.on:after {
|
|
||||||
--x: calc(var(--switch-track-width) - var(--switch-thumb-width) - var(--y));
|
|
||||||
|
|
||||||
background: var(--switch-on-thumb-background);
|
|
||||||
transition: transform 200ms cubic-bezier(0.64, 0, 0.78, 0),
|
|
||||||
background 100ms ease-in;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.switch-widget .switch-button input[type="checkbox"] {
|
|
||||||
/* A hidden check box for accesibility purposes */
|
|
||||||
position: absolute:
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Disabled state */
|
|
||||||
.switch-widget .switch-button:not(.disabled) input[type="checkbox"],
|
|
||||||
.switch-widget .switch-button:not(.disabled) {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-widget .switch-button:has(input[type="checkbox"]:focus-visible) {
|
|
||||||
outline: 2px solid var(--button-border-color);
|
|
||||||
outline-offset: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-widget .switch-button.disabled {
|
|
||||||
opacity: 70%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-widget .switch-help-button {
|
|
||||||
border: 0;
|
|
||||||
margin-left: 4px;
|
|
||||||
background: none;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 1.1em;
|
|
||||||
color: var(--muted-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-widget .switch-help-button:hover {
|
|
||||||
color: var(--main-text-color);
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="switch-widget">
|
|
||||||
<span class="switch-name"></span>
|
|
||||||
|
|
||||||
<label>
|
|
||||||
<div class="switch-button">
|
|
||||||
<input class="switch-toggle" type="checkbox" />
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<button class="switch-help-button icon-action bx bx-help-circle" type="button" data-help-page="" title="${t("open-help-page")}" style="display: none;"></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
export default class SwitchWidget extends NoteContextAwareWidget {
|
export default class SwitchWidget extends NoteContextAwareWidget {
|
||||||
|
|
||||||
private $switchButton!: JQuery<HTMLElement>;
|
|
||||||
private $switchToggle!: JQuery<HTMLElement>;
|
|
||||||
private $switchName!: JQuery<HTMLElement>;
|
|
||||||
protected $helpButton!: JQuery<HTMLElement>;
|
|
||||||
|
|
||||||
protected switchOnName = "";
|
|
||||||
protected switchOnTooltip = "";
|
|
||||||
|
|
||||||
protected switchOffName = "";
|
|
||||||
protected switchOffTooltip = "";
|
|
||||||
|
|
||||||
protected disabledTooltip = "";
|
|
||||||
|
|
||||||
private currentState = false;
|
|
||||||
|
|
||||||
doRender() {
|
doRender() {
|
||||||
this.$widget = $(TPL);
|
this.$widget = $(TPL);
|
||||||
this.$switchButton = this.$widget.find(".switch-button");
|
this.$switchButton = this.$widget.find(".switch-button");
|
||||||
|
|
||||||
this.$switchToggle = this.$widget.find(".switch-toggle");
|
this.$switchToggle = this.$widget.find(".switch-toggle");
|
||||||
this.$switchToggle.on("click", (e) => {
|
|
||||||
this.toggle(!this.currentState);
|
|
||||||
|
|
||||||
// Prevent the check box from being toggled by the click, the value of the check box
|
|
||||||
// should be set exclusively by the 'isToggled' property setter.
|
|
||||||
e.preventDefault();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.$switchName = this.$widget.find(".switch-name");
|
this.$switchName = this.$widget.find(".switch-name");
|
||||||
this.$helpButton = this.$widget.find(".switch-help-button");
|
this.$helpButton = this.$widget.find(".switch-help-button");
|
||||||
}
|
}
|
||||||
|
|
||||||
toggle(state: boolean) {
|
|
||||||
if (state) {
|
|
||||||
this.switchOn();
|
|
||||||
} else {
|
|
||||||
this.switchOff();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switchOff() {}
|
switchOff() {}
|
||||||
switchOn() {}
|
switchOn() {}
|
||||||
|
|
||||||
@ -172,15 +32,6 @@ export default class SwitchWidget extends NoteContextAwareWidget {
|
|||||||
this.currentState = !!state;
|
this.currentState = !!state;
|
||||||
|
|
||||||
this.$switchButton.toggleClass("on", this.currentState);
|
this.$switchButton.toggleClass("on", this.currentState);
|
||||||
this.$switchToggle.prop("checked", this.currentState);
|
|
||||||
|
|
||||||
if (this.currentState) {
|
|
||||||
this.$switchName.text(this.switchOffName);
|
|
||||||
this.$switchButton.attr("title", this.switchOffTooltip);
|
|
||||||
} else {
|
|
||||||
this.$switchName.text(this.switchOnName);
|
|
||||||
this.$switchButton.attr("title", this.switchOnTooltip);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets or sets whether the switch is enabled. */
|
/** Gets or sets whether the switch is enabled. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user