Skip to content

Commit 5d9a838

Browse files
committed
tasks: fix keyboard issue; also add really minimal jupyter search
1 parent fddee81 commit 5d9a838

File tree

10 files changed

+89
-22
lines changed

10 files changed

+89
-22
lines changed

src/packages/frontend/editors/task-editor/actions.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ Task Actions
99

1010
import { fromJS, Map } from "immutable";
1111
import { throttle } from "lodash";
12-
import { delay } from "awaiting";
1312
import {
1413
close,
1514
copy_with,
@@ -120,7 +119,9 @@ export class TaskActions extends Actions<TaskState> {
120119
}
121120

122121
public disable_key_handler(): void {
123-
if (this.key_handler == null || this.redux == null) return;
122+
if (this.key_handler == null || this.redux == null) {
123+
return;
124+
}
124125
this.frameActions.erase_active_key_handler(this.key_handler);
125126
delete this.key_handler;
126127
}
@@ -532,16 +533,22 @@ export class TaskActions extends Actions<TaskState> {
532533
this.set_local_task_state(task_id, { editing_desc: false });
533534
}
534535

535-
public edit_desc(task_id: string | undefined): void {
536+
// null=unselect all.
537+
public edit_desc(task_id: string | undefined | null): void {
536538
// close any that were currently in edit state before opening new one
537539
const local = this.getFrameData("local_task_state") ?? fromJS({});
538540
for (const [id, state] of local) {
539541
if (state.get("editing_desc")) {
540542
this.stop_editing_desc(id);
541543
}
542544
}
543-
544-
this.set_local_task_state(task_id, { editing_desc: true });
545+
if (task_id !== null) {
546+
this.set_local_task_state(task_id, { editing_desc: true });
547+
}
548+
this.disable_key_handler();
549+
setTimeout(() => {
550+
this.disable_key_handler();
551+
}, 1);
545552
}
546553

547554
public set_due_date(
@@ -748,10 +755,7 @@ export class TaskActions extends Actions<TaskState> {
748755
this.disable_key_handler();
749756
}
750757

751-
public async show(): Promise<void> {
752-
await delay(1);
753-
this.enable_key_handler();
754-
}
758+
public async show(): Promise<void> {}
755759

756760
chatgptGetText(scope: "cell" | "all", current_id?): string {
757761
if (scope == "all") {

src/packages/frontend/editors/task-editor/keyboard.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { is_sortable as is_sortable_header } from "./headings-info";
1313

1414
function is_sortable(actions): boolean {
1515
return is_sortable_header(
16-
actions.store.getIn(["local_view_state", "sort", "column"]) ?? HEADINGS[0]
16+
actions.store.getIn(["local_view_state", "sort", "column"]) ?? HEADINGS[0],
1717
);
1818
}
1919

src/packages/frontend/frame-editors/generic/search/index.tsx

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@ import { useEffect, useMemo, useState } from "react";
1515
import { throttle } from "lodash";
1616
import useSearchIndex from "./use-search-index";
1717
import ShowError from "@cocalc/frontend/components/error";
18-
import { useEditorRedux } from "@cocalc/frontend/app-framework";
18+
import { useRedux } from "@cocalc/frontend/app-framework";
1919

2020
export function createSearchEditor({
2121
Preview,
2222
updateField,
2323
previewStyle,
24+
title,
2425
}: {
2526
// component for previewing search results.
2627
Preview?;
@@ -43,6 +44,7 @@ export function createSearchEditor({
4344
Preview={Preview}
4445
updateField={updateField}
4546
previewStyle={previewStyle}
47+
title={title}
4648
/>
4749
),
4850
} as EditorDescription;
@@ -66,10 +68,7 @@ function Search({
6668
title,
6769
}: Props) {
6870
const { project_id, path, actions, id } = useFrameContext();
69-
const useEditor = useEditorRedux({ project_id, path });
7071
// @ts-ignore
71-
const messages = useEditor(updateField);
72-
const [indexedMessages, setIndexedMessages] = useState<any>(messages);
7372
const [search, setSearch] = useState<string>(desc.get("data-search") ?? "");
7473
const [result, setResult] = useState<any>(null);
7574
const saveSearch = useMemo(
@@ -82,7 +81,12 @@ function Search({
8281
[project_id, path],
8382
);
8483

85-
const { error, setError, index, doRefresh, fragmentKey } = useSearchIndex();
84+
const { error, setError, index, doRefresh, fragmentKey, reduxName } =
85+
useSearchIndex();
86+
87+
const data = useRedux(reduxName ?? actions.name, updateField);
88+
89+
const [indexedData, setIndexedData] = useState<any>(data);
8690

8791
useEffect(() => {
8892
if (index == null) {
@@ -99,11 +103,11 @@ function Search({
99103
}, [search, index]);
100104

101105
useEffect(() => {
102-
if (indexedMessages != messages) {
103-
setIndexedMessages(messages);
106+
if (indexedData != data) {
107+
setIndexedData(data);
104108
doRefresh();
105109
}
106-
}, [messages]);
110+
}, [data]);
107111

108112
return (
109113
<div className="smc-vfill">
@@ -123,7 +127,7 @@ function Search({
123127
<Input.Search
124128
style={{ fontSize }}
125129
allowClear
126-
placeholder="Search messages..."
130+
placeholder={`Search ${title}...`}
127131
value={search}
128132
onChange={(e) => {
129133
const search = e.target.value ?? "";

src/packages/frontend/frame-editors/generic/search/use-search-index.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export default function useSearchIndex() {
1414
const { val: refresh, inc: doRefresh } = useCounter();
1515
const [indexTime, setIndexTime] = useState<number>(0);
1616
const [fragmentKey, setFragmentKey] = useState<string>("id");
17+
const [reduxName, setReduxName] = useState<string | undefined>(undefined);
1718

1819
useEffect(() => {
1920
if (
@@ -30,6 +31,7 @@ export default function useSearchIndex() {
3031
const newIndex = new SearchIndex({ actions });
3132
await newIndex.init();
3233
setFragmentKey(newIndex.fragmentKey ?? "id");
34+
setReduxName(newIndex.reduxName);
3335
setIndex(newIndex);
3436
setIndexTime(Date.now() - t0);
3537
//index?.close();
@@ -39,14 +41,23 @@ export default function useSearchIndex() {
3941
})();
4042
}, [project_id, path, refresh]);
4143

42-
return { index, error, doRefresh, setError, indexTime, fragmentKey };
44+
return {
45+
index,
46+
error,
47+
doRefresh,
48+
setError,
49+
indexTime,
50+
fragmentKey,
51+
reduxName,
52+
};
4353
}
4454

4555
class SearchIndex {
4656
private actions?;
4757
private state: "init" | "ready" | "failed" | "closed" = "init";
4858
private db?;
4959
public fragmentKey?: string = "id";
60+
public reduxName?: string = undefined;
5061

5162
constructor({ actions }) {
5263
this.actions = actions;
@@ -76,8 +87,9 @@ class SearchIndex {
7687
if (this.actions == null || this.state != "init") {
7788
throw Error("not in init state");
7889
}
79-
const { data, fragmentKey } = this.actions.getSearchIndexData();
90+
const { data, fragmentKey, reduxName } = this.actions.getSearchIndexData();
8091
this.fragmentKey = fragmentKey;
92+
this.reduxName = reduxName;
8193
if (data != null) {
8294
const docs: { id: string; content: string }[] = [];
8395
for (const id in data) {

src/packages/frontend/frame-editors/jupyter-editor/actions.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,22 @@ export class JupyterEditorActions extends BaseActions<JupyterEditorState> {
577577
}
578578
}
579579
}
580+
581+
getSearchIndexData = () => {
582+
const cells = this.jupyter_actions.store.get("cells");
583+
if (cells == null) {
584+
return {};
585+
}
586+
const data: { [id: string]: string } = {};
587+
for (const [id, cell] of cells) {
588+
let content = cell.get("input")?.trim();
589+
if (!content) {
590+
continue;
591+
}
592+
data[id] = content;
593+
}
594+
return { data, fragmentKey: "id", reduxName: this.jupyter_actions.name };
595+
};
580596
}
581597

582598
export { JupyterEditorActions as Actions };

src/packages/frontend/frame-editors/jupyter-editor/editor.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import { RawIPynb } from "./raw-ipynb";
2828
import { Slideshow } from "./slideshow-revealjs/slideshow";
2929
import { JupyterSnippets } from "./snippets";
3030
import { TableOfContents } from "./table-of-contents";
31+
import { search } from "./search";
3132

3233
const SNIPPET_ICON_NAME = "magic";
3334

@@ -50,6 +51,7 @@ const jupyterCommands = set([
5051
"help",
5152
"compute_server",
5253
"settings",
54+
"show_search",
5355
]);
5456

5557
const jupyter_cell_notebook: EditorDescription = {
@@ -70,6 +72,7 @@ const jupyter_cell_notebook: EditorDescription = {
7072
"jupyter-nbgrader validate",
7173
"halt_jupyter",
7274
"guide",
75+
"show_search",
7376
]),
7477
customizeCommands: {
7578
guide: {
@@ -150,6 +153,7 @@ export const EDITOR_SPEC = {
150153
time_travel,
151154
jupyter_json,
152155
jupyter_raw,
156+
search,
153157
} as const;
154158

155159
const JUPYTER_MENUS = {
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// import StaticMarkdown from "@cocalc/frontend/editors/slate/static-markdown";
2+
import { createSearchEditor } from "@cocalc/frontend/frame-editors/generic/search";
3+
4+
export const DONE = "☑ ";
5+
6+
function Preview({ content, fontSize }) {
7+
return <pre style={{ fontSize }}>{content}</pre>;
8+
// return (
9+
// <StaticMarkdown
10+
// value={content}
11+
// style={{
12+
// marginBottom: "-10px" /* account for <p> */,
13+
// }}
14+
// />
15+
// );
16+
}
17+
18+
export const search = createSearchEditor({
19+
Preview,
20+
updateField: "cells",
21+
title: "Jupyter Notebook",
22+
});

src/packages/frontend/frame-editors/task-editor/actions.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ export class Actions extends CodeEditorActions<TaskEditorState> {
144144
actions._init_frame(frameId, this);
145145
this.taskActions[frameId] = actions;
146146
actions.store = this.store;
147+
// this makes sure nothing is initially in edit mode, mainly because our keyboard handling SUCKS.
148+
actions.edit_desc(null);
147149
return actions;
148150
}
149151

src/packages/frontend/jupyter/commands.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ export function commands(actions: AllActions): {
508508

509509
"find and replace": {
510510
i: "replace",
511-
b: "Find",
511+
b: "Replace",
512512
m: jupyter.commands.find_and_replace,
513513
k: [
514514
{ mode: "escape", which: 70 },

src/packages/jupyter/redux/actions.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2803,6 +2803,9 @@ export abstract class JupyterActions extends Actions<JupyterStoreState> {
28032803
// Currently only run in the browser, but could maybe be useful
28042804
// elsewhere someday.
28052805
updateRunProgress = () => {
2806+
if (this.store == null) {
2807+
return;
2808+
}
28062809
if (this.store.get("backend_state") != "running") {
28072810
this.setState({ runProgress: 0 });
28082811
return;

0 commit comments

Comments
 (0)