Skip to content

Commit 19c3748

Browse files
Merge pull request #8621 from sagemathinc/projects-listing-cleanup-20251010
frontend/projects: redesign of projects list
2 parents 153e1b3 + 23c8d4b commit 19c3748

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+3686
-1420
lines changed

src/packages/frontend/_project_page.sass

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,7 @@ dl.cc-project-settings-features
6161
padding: 5px !important
6262
code
6363
font-size: 90%
64+
65+
.cc-project-expanded-row
66+
.ant-table-expanded-row-cell
67+
padding: 0 !important

src/packages/frontend/account/avatar/avatar.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import { Tooltip } from "antd";
77
import { CSSProperties, useState } from "react";
8+
89
import { isChatBot } from "@cocalc/frontend/account/chatbot";
910
import {
1011
React,

src/packages/frontend/app/context.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,19 @@ export function useAppContextProvider(): AppState {
5858
}
5959
}
6060

61+
function displayI18N(
62+
label: string | IntlMessage | ReactNode,
63+
): string | ReactNode {
64+
if (isIntlMessage(label)) {
65+
return intl.formatMessage(label);
66+
} else {
67+
return label;
68+
}
69+
}
70+
6171
return {
6272
formatIntl,
73+
displayI18N,
6374
pageWidthPx,
6475
pageStyle,
6576
showActBarLabels,

src/packages/frontend/app/use-context.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { ThemeConfig } from "antd";
88
import type { SizeType } from "antd/es/config-provider/SizeContext";
99
import { createContext, ReactNode, useContext } from "react";
1010

11-
import type { IntlMessage } from "@cocalc/util/i18n/types";
11+
import { isIntlMessage, type IntlMessage } from "@cocalc/util/i18n/types";
1212
import { COLORS } from "@cocalc/util/theme";
1313

1414
import { ACTIVITY_BAR_LABELS_DEFAULT } from "@cocalc/frontend/project/page/activity-bar-consts";
@@ -26,6 +26,7 @@ export interface AppState {
2626
antdComponentSize?: SizeType;
2727
antdTheme?: ThemeConfig;
2828
formatIntl: (msg: IntlMessage | ReactNode | string) => ReactNode | string;
29+
displayI18N: (label: string | IntlMessage | ReactNode) => string | ReactNode;
2930
timeAgoAbsolute?: boolean;
3031
setTimeAgoAbsolute?: (boolean) => void;
3132
showActBarLabels?: boolean; // whether to show labels on the vertical fixed bar
@@ -35,6 +36,13 @@ export const DEFAULT_CONTEXT = {
3536
pageWidthPx: 1000, // gets updated
3637
pageStyle: calcStyle(false), // gets updated
3738
formatIntl: () => "Loading…",
39+
displayI18N: (label: string | IntlMessage | ReactNode) => {
40+
// Fallback when intl is not available
41+
if (isIntlMessage(label)) {
42+
return label.defaultMessage;
43+
}
44+
return label;
45+
},
3846
showActBarLabels: ACTIVITY_BAR_LABELS_DEFAULT,
3947
};
4048

src/packages/frontend/components/time-elapsed.tsx

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,29 @@ import { seconds2hms, server_time } from "@cocalc/util/misc";
1111
interface Props {
1212
start_ts: number;
1313
interval_s?: number;
14+
longform?: boolean; // 22 hours 32 minutes vs 22h 32m
15+
show_seconds?: boolean;
16+
show_minutes?: boolean;
1417
}
1518

16-
export function TimeElapsed({ start_ts, interval_s = 1 }: Props) {
19+
export function TimeElapsed({
20+
start_ts,
21+
interval_s = 1,
22+
longform = true,
23+
show_seconds = true,
24+
show_minutes = true,
25+
}: Props) {
1726
const [elapsed, setElapsed] = React.useState<string>(getUptimeStr());
1827

1928
function getUptimeStr() {
2029
if (start_ts == null) return "";
2130
const delta_s = (server_time().getTime() - start_ts) / 1000;
22-
const uptime_str = seconds2hms(delta_s, true);
31+
const uptime_str = seconds2hms(
32+
delta_s,
33+
longform,
34+
show_seconds,
35+
show_minutes,
36+
);
2337
return uptime_str;
2438
}
2539

src/packages/frontend/editors/task-editor/hashtag-bar.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,18 @@ Hashtag bar for selecting which tasks are shown by tags
88
*/
99

1010
import { CSSProperties } from "react";
11-
import { cmp, trunc } from "@cocalc/util/misc";
1211
import { Tag } from "antd";
12+
13+
import { cmp, trunc } from "@cocalc/util/misc";
14+
1315
const { CheckableTag } = Tag;
14-
import {
16+
17+
import type {
1518
HashtagsOfVisibleTasks,
1619
HashtagState,
1720
SelectedHashtags,
1821
} from "./types";
22+
1923
import { STYLE as GENERIC_STYLE } from "../../projects/hashtags";
2024

2125
const STYLE: CSSProperties = {

src/packages/frontend/i18n/common.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,11 @@ export const labels = defineMessages({
217217
id: "labels.status",
218218
defaultMessage: "Status",
219219
},
220+
state: {
221+
id: "labels.state",
222+
defaultMessage: "State",
223+
description: "The state some object is in, e.g. running, stopped, ...",
224+
},
220225
published_files: {
221226
id: "labels.published_files",
222227
defaultMessage: "Published",
@@ -512,6 +517,11 @@ export const labels = defineMessages({
512517
defaultMessage:
513518
"Collaborators are other users, who can access this project. They can view and edit the same files as you.",
514519
},
520+
collaborators: {
521+
id: "labels.collaborators",
522+
defaultMessage: "Collaborators",
523+
description: "Collaborators (people) on a project, working together",
524+
},
515525
chat: {
516526
id: "labels.chat",
517527
defaultMessage: "Chat",
@@ -545,6 +555,11 @@ export const labels = defineMessages({
545555
defaultMessage: "Recent",
546556
description: "Something that happened recently",
547557
},
558+
recent_files: {
559+
id: "labels.recent_files",
560+
defaultMessage: "Recent Files",
561+
description: "Recently opened or edited files",
562+
},
548563
files: {
549564
id: "labels.files",
550565
defaultMessage: "Files",
@@ -858,6 +873,10 @@ export const labels = defineMessages({
858873
id: "labels.last_active",
859874
defaultMessage: "Last Active",
860875
},
876+
last_edited: {
877+
id: "labels.last_edited",
878+
defaultMessage: "Last Edited",
879+
},
861880
project_status: {
862881
id: "labels.project_status",
863882
defaultMessage: "Project Status",

src/packages/frontend/misc/local-storage.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export const LS = new LocalStorageLRU({
3232
fallback: true,
3333
});
3434

35-
export function set_local_storage(key: string, val: string): void {
35+
export function set_local_storage(key: string, val: string | object): void {
3636
LS.set(key, val);
3737
}
3838

src/packages/frontend/project/page/flyouts/settings.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,14 +135,14 @@ export function SettingsFlyout(_: Readonly<Props>): React.JSX.Element {
135135
<Title level={4}>
136136
Status: <span style={{ float: "right" }}>{renderState()}</span>
137137
</Title>
138-
<Button.Group>
138+
<Space.Compact>
139139
<RestartProject project_id={project_id} short={true} />
140140
<StopProject
141141
project_id={project_id}
142142
disabled={status.get("state") !== "running"}
143143
short={true}
144144
/>
145-
</Button.Group>
145+
</Space.Compact>
146146
</div>
147147
);
148148
}
@@ -180,7 +180,7 @@ export function SettingsFlyout(_: Readonly<Props>): React.JSX.Element {
180180
});
181181
}
182182

183-
function featuresRealodButton() {
183+
function featuresReloadButton() {
184184
return (
185185
<Tooltip title="Reload features and configuration">
186186
<Button
@@ -197,7 +197,7 @@ export function SettingsFlyout(_: Readonly<Props>): React.JSX.Element {
197197
);
198198
}
199199

200-
function renderDatastoreRelaod() {
200+
function renderDatastoreReload() {
201201
return (
202202
<Tooltip title={`Reload ${DATASTORE_TITLE} information`}>
203203
<Button
@@ -316,7 +316,7 @@ export function SettingsFlyout(_: Readonly<Props>): React.JSX.Element {
316316
</>
317317
),
318318
className: "cc-project-flyout-settings-panel",
319-
extra: renderDatastoreRelaod(),
319+
extra: renderDatastoreReload(),
320320
children: (
321321
<Datastore
322322
project_id={project_id}
@@ -335,7 +335,7 @@ export function SettingsFlyout(_: Readonly<Props>): React.JSX.Element {
335335
</>
336336
),
337337
style: { borderRadius: 0 },
338-
extra: featuresRealodButton(),
338+
extra: featuresReloadButton(),
339339
children: (
340340
<ProjectCapabilities
341341
project={project}

src/packages/frontend/project/page/flyouts/store.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,21 @@ import type { FlyoutActiveStarred } from "./state";
2828

2929
// Starred files are now managed entirely through conat with in-memory state.
3030
// No local storage dependency - conat handles synchronization and persistence.
31-
export function useStarredFilesManager(project_id: string) {
31+
export function useStarredFilesManager(
32+
project_id: string,
33+
enabled: boolean = true,
34+
) {
3235
const [starred, setStarred] = useState<FlyoutActiveStarred>([]);
3336
const [bookmarks, setBookmarks] = useState<any>(null);
3437
const [isInitialized, setIsInitialized] = useState(false);
3538

3639
// Initialize conat bookmarks once on mount, waiting for authentication
3740
useAsyncEffect(async () => {
41+
if (!enabled) {
42+
setIsInitialized(true);
43+
return;
44+
}
45+
3846
// Wait until account is authenticated
3947
const store = redux.getStore("account");
4048
await store.async_wait({
@@ -44,7 +52,7 @@ export function useStarredFilesManager(project_id: string) {
4452

4553
const account_id = store.get_account_id();
4654
await initializeConatBookmarks(account_id);
47-
}, []);
55+
}, [enabled]);
4856

4957
async function initializeConatBookmarks(account_id: string) {
5058
try {
@@ -53,6 +61,8 @@ export function useStarredFilesManager(project_id: string) {
5361
name: CONAT_BOOKMARKS_KEY,
5462
});
5563

64+
conatBookmarks.setMaxListeners(100);
65+
5666
setBookmarks(conatBookmarks);
5767

5868
// Listen for changes from other clients

0 commit comments

Comments
 (0)