Skip to content

Commit b8ba179

Browse files
committed
feat: add select team command
1 parent a61f5cb commit b8ba179

File tree

7 files changed

+152
-9
lines changed

7 files changed

+152
-9
lines changed

.vscode/settings.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,8 @@
88
},
99
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
1010
"typescript.tsc.autoDetect": "off",
11-
"editor.formatOnSave": true
12-
}
11+
"editor.formatOnSave": true,
12+
"cSpell.words": [
13+
"zustand"
14+
]
15+
}

package-lock.json

Lines changed: 48 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,15 @@
183183
"viewsWelcome": [
184184
{
185185
"view": "hackmd.tree.my-notes",
186-
"contents": "No notes found. Login first.\n[Login HackMD](command:HackMD.login)"
186+
"contents": "Loading data... \nEnsure that the access token and correct API endpoint have been properly configured."
187+
},
188+
{
189+
"view": "hackmd.tree.recent-notes",
190+
"contents": "Loading data... \nEnsure that the access token and correct API endpoint have been properly configured."
191+
},
192+
{
193+
"view": "hackmd.tree.team-notes",
194+
"contents": "Loading data... \nEnsure that the access token and correct API endpoint have been properly configured."
187195
}
188196
]
189197
},
@@ -258,8 +266,10 @@
258266
"mobx": "^5.15.4",
259267
"node-fetch": "^2.6.7",
260268
"react": "^17.0.2",
269+
"react-reconciler": "^0.26.2",
261270
"react-vsc-treeview": "^0.2.3",
262271
"string": "git+ssh://[email protected]/hackmdio/string.js.git#a68176b3d",
263-
"swr": "^1.3.0"
272+
"swr": "^1.3.0",
273+
"zustand": "^4.1.5"
264274
}
265275
}

src/commands/treeView.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import * as vscode from 'vscode';
22

3+
import { Team } from '@hackmd/api/dist/type';
4+
5+
import { teamNotesStore } from '../treeReactApp/store';
6+
37
import { API } from './../api';
48
import { MdTextDocumentContentProvider, getNoteIdPublishLink } from './../mdTextDocument';
59
import { ReactVSCTreeNode } from './../tree/nodes';
@@ -23,6 +27,24 @@ export async function registerTreeViewCommands(context: vscode.ExtensionContext)
2327
})
2428
);
2529

30+
context.subscriptions.push(
31+
vscode.commands.registerCommand('selectTeam', async () => {
32+
const teams = await API.getTeams();
33+
34+
const getTeamLabel = (team: Team) => `${team.name} [${team.path}]`;
35+
36+
await vscode.window.showQuickPick(teams.map(getTeamLabel)).then((selectedTeam) => {
37+
if (!selectedTeam) {
38+
return;
39+
}
40+
41+
const selectedTeamId = teams.find((team) => getTeamLabel(team) === selectedTeam)?.id;
42+
43+
teamNotesStore.setState({ selectedTeamId });
44+
});
45+
})
46+
);
47+
2648
context.subscriptions.push(
2749
vscode.commands.registerCommand('HackMD.showPreview', async (noteNode: ReactVSCTreeNode) => {
2850
if (noteNode) {

src/extension.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,9 @@ export async function activate(context: vscode.ExtensionContext) {
211211

212212
registerCommands(context);
213213

214-
ReactTreeView.render(React.createElement(MyNotes), 'hackmd.tree.my-notes');
215-
ReactTreeView.render(React.createElement(History), 'hackmd.tree.recent-notes');
216-
ReactTreeView.render(React.createElement(TeamNotes), 'hackmd.tree.team-notes');
214+
context.subscriptions.push(ReactTreeView.render(React.createElement(MyNotes), 'hackmd.tree.my-notes'));
215+
context.subscriptions.push(ReactTreeView.render(React.createElement(History), 'hackmd.tree.recent-notes'));
216+
context.subscriptions.push(ReactTreeView.render(React.createElement(TeamNotes), 'hackmd.tree.team-notes'));
217217

218218
return {
219219
extendMarkdownIt(md: any) {

src/treeReactApp/pages/TeamNotes.tsx

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,52 @@
1+
import { Team } from '@hackmd/api/dist/type';
2+
import { useEffect, useMemo, useState } from 'react';
13
import { TreeItem } from 'react-vsc-treeview';
4+
import useSWR from 'swr';
5+
6+
import { API } from '../../api';
7+
import { NoteTreeItem } from '../components/NoteTreeItem';
8+
import { useTeamNotesStore } from '../store';
9+
10+
const TeamTreeItem = ({ team }: { team: Team }) => {
11+
const { data: notes = [] } = useSWR(
12+
() => (team ? `/teams/${team.id}/notes` : null),
13+
() => API.getTeamNotes(team.path)
14+
);
15+
16+
return (
17+
<TreeItem label={team.name} expanded>
18+
{notes.map((note) => {
19+
return <NoteTreeItem key={note.id} note={note} />;
20+
})}
21+
22+
{notes.length === 0 && <TreeItem label="No notes" />}
23+
</TreeItem>
24+
);
25+
};
226

327
export const TeamNotes = () => {
4-
return <TreeItem label="Hello World"></TreeItem>;
28+
const { data: teams = [] } = useSWR('/teams', () => API.getTeams());
29+
const [selectedTeamId, setSelectedTeamId] = useState(useTeamNotesStore.getState().selectedTeamId);
30+
31+
// I'm not sure why using useTeamNotesStore doesn't trigger re-render
32+
// So we use useEffect to subscribe to the zustand store and update the useState we use in the component
33+
useEffect(() => {
34+
useTeamNotesStore.subscribe((state) => setSelectedTeamId(state.selectedTeamId));
35+
}, []);
36+
37+
const selectedTeam = useMemo(() => teams.find((t) => t.id === selectedTeamId), [teams, selectedTeamId]);
38+
39+
return (
40+
<>
41+
<TreeItem
42+
label="Click to select a team"
43+
command={{
44+
title: 'Select a team',
45+
command: 'selectTeam',
46+
}}
47+
/>
48+
49+
{selectedTeam && <TeamTreeItem team={selectedTeam} />}
50+
</>
51+
);
552
};

src/treeReactApp/store.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import createReact from 'zustand';
2+
import create from 'zustand/vanilla';
3+
4+
type TeamNoteStore = {
5+
selectedTeamId: string;
6+
setSelectedTeamId: (id: string) => void;
7+
};
8+
9+
export const teamNotesStore = create<TeamNoteStore>()((set) => ({
10+
selectedTeamId: null,
11+
setSelectedTeamId: (id: string) => set({ selectedTeamId: id }),
12+
}));
13+
14+
export const useTeamNotesStore = createReact(teamNotesStore);

0 commit comments

Comments
 (0)