Skip to content

Commit b937c94

Browse files
authored
Add format section into the project setting page. (#1324)
* Add format section into the project setting page. - Click the formatter from nav side will open a new window for formatter page. - Move the project select to the top level of the page. - Move the apply button to the top level of the page.
1 parent e88f9ed commit b937c94

File tree

14 files changed

+194
-112
lines changed

14 files changed

+194
-112
lines changed

src/project-settings/assets/classpath/features/ClasspathConfigurationView.tsx

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import React, { useEffect } from "react";
55
import { useSelector, useDispatch } from "react-redux";
66
import { Dispatch } from "@reduxjs/toolkit";
77
import Output from "./components/Output";
8-
import ProjectSelector from "./components/ProjectSelector";
98
import Sources from "./components/Sources";
109
import Libraries from "./components/Libraries";
1110
import Exception from "./components/Exception";
@@ -16,7 +15,7 @@ import { ClasspathRequest } from "../../vscode/utils";
1615
import { VSCodePanelTab, VSCodePanelView, VSCodePanels, VSCodeProgressRing } from "@vscode/webview-ui-toolkit/react";
1716
import { ProjectType } from "../../../../utils/webview";
1817
import UnmanagedFolderSources from "./components/UnmanagedFolderSources";
19-
import Footer from "./components/Footer";
18+
import Hint from "./components/Hint";
2019
import "../style.scss";
2120
import { listProjects, setProjectType } from "../../mainpage/features/commonSlice";
2221

@@ -39,35 +38,32 @@ const ClasspathConfigurationView = (): JSX.Element => {
3938
content = <VSCodeProgressRing></VSCodeProgressRing>;
4039
} else {
4140
content = (
42-
<div>
43-
<div className="mb-12">
44-
<ProjectSelector />
45-
<VSCodePanels activeid={activeTab} className="setting-panels">
46-
<VSCodePanelTab id="source" onClick={() => onClickTab("source")}>Sources</VSCodePanelTab>
47-
<VSCodePanelTab id="jdk" onClick={() => onClickTab("jdk")}>JDK Runtime</VSCodePanelTab>
48-
<VSCodePanelTab id="libraries" onClick={() => onClickTab("libraries")}>Libraries</VSCodePanelTab>
49-
<VSCodePanelView className="setting-panels-view">
50-
{[ProjectType.Gradle, ProjectType.Maven].includes(projectType) && (<Sources />)}
51-
{projectType !== ProjectType.Gradle && projectType !== ProjectType.Maven && (<UnmanagedFolderSources />)}
52-
{projectType === ProjectType.UnmanagedFolder && (<Output />)}
53-
</VSCodePanelView>
54-
<VSCodePanelView className="setting-panels-view">
55-
<JdkRuntime />
56-
</VSCodePanelView>
57-
<VSCodePanelView className="setting-panels-view">
58-
<Libraries />
59-
</VSCodePanelView>
60-
</VSCodePanels>
61-
</div>
62-
<Footer />
41+
<div className="root">
42+
<VSCodePanels activeid={activeTab} className="setting-panels">
43+
<VSCodePanelTab id="source" onClick={() => onClickTab("source")}>Sources</VSCodePanelTab>
44+
<VSCodePanelTab id="jdk" onClick={() => onClickTab("jdk")}>JDK Runtime</VSCodePanelTab>
45+
<VSCodePanelTab id="libraries" onClick={() => onClickTab("libraries")}>Libraries</VSCodePanelTab>
46+
<VSCodePanelView className="setting-panels-view">
47+
{[ProjectType.Gradle, ProjectType.Maven].includes(projectType) && (<Sources />)}
48+
{projectType !== ProjectType.Gradle && projectType !== ProjectType.Maven && (<UnmanagedFolderSources />)}
49+
{projectType === ProjectType.UnmanagedFolder && (<Output />)}
50+
</VSCodePanelView>
51+
<VSCodePanelView className="setting-panels-view">
52+
<JdkRuntime />
53+
</VSCodePanelView>
54+
<VSCodePanelView className="setting-panels-view">
55+
<Libraries />
56+
</VSCodePanelView>
57+
</VSCodePanels>
58+
<Hint />
6359
</div>
6460
);
6561
}
6662

6763
const onMessage = (event: any) => {
68-
const {data} = event;
64+
const { data } = event;
6965
if (data.command === "classpath.onDidListProjects") {
70-
dispatch(initializeProjectsData({projectsNum: data.projectInfo?.length}));
66+
dispatch(initializeProjectsData({ projectsNum: data.projectInfo?.length }));
7167
dispatch(listProjects(data.projectInfo));
7268
} else if (data.command === "classpath.onDidListVmInstalls") {
7369
dispatch(listVmInstalls(data.vmInstalls))
@@ -98,11 +94,7 @@ const ClasspathConfigurationView = (): JSX.Element => {
9894
}
9995
}, []);
10096

101-
return (
102-
<div className="root">
103-
{content}
104-
</div>
105-
);
97+
return content;
10698
};
10799

108100
export default ClasspathConfigurationView;
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
4+
import { VSCodeLink} from "@vscode/webview-ui-toolkit/react";
5+
import React, { useEffect } from "react";
6+
import { ProjectInfo } from "../../../../handlers/classpath/types";
7+
import { useSelector } from "react-redux";
8+
import { ProjectType } from "../../../../../utils/webview";
9+
import { updateMaxHeight } from "../../utils";
10+
import { ClasspathRequest } from "../../../vscode/utils";
11+
12+
const Hint = (): JSX.Element => {
13+
14+
const activeProjectIndex: number = useSelector((state: any) => state.commonConfig.ui.activeProjectIndex);
15+
const projects: ProjectInfo[] = useSelector((state: any) => state.commonConfig.data.projects);
16+
const projectType: ProjectType[] = useSelector((state: any) => state.commonConfig.data.projectType);
17+
18+
let buildFile: string = "";
19+
if (projectType[activeProjectIndex] === ProjectType.Maven) {
20+
buildFile = "pom.xml";
21+
} else if (projectType[activeProjectIndex] === ProjectType.Gradle) {
22+
buildFile = "build.gradle";
23+
}
24+
25+
const handleOpenBuildFile = () => {
26+
ClasspathRequest.onClickGotoProjectConfiguration(projects[activeProjectIndex].rootPath, projectType[activeProjectIndex]);
27+
};
28+
29+
useEffect(() => {
30+
updateMaxHeight();
31+
window.addEventListener('resize', updateMaxHeight);
32+
return () => {
33+
window.removeEventListener("resize", updateMaxHeight);
34+
}
35+
}, [projectType]);
36+
37+
return (
38+
<div id="hint" className="setting-footer pb-2">
39+
{(projectType[activeProjectIndex] === ProjectType.Gradle || projectType[activeProjectIndex] === ProjectType.Maven) &&
40+
<div className="mt-1">
41+
<span className="setting-section-warning">
42+
'{projects[activeProjectIndex].name}' is imported by {projectType[activeProjectIndex]}, changes made to the classpath might be lost after reloading.
43+
To make permanent changes, please edit the <VSCodeLink href="" onClick={() => handleOpenBuildFile()}>{buildFile}</VSCodeLink> file.
44+
</span>
45+
</div>
46+
}
47+
</div>
48+
);
49+
};
50+
51+
export default Hint;

src/project-settings/assets/classpath/features/components/JdkRuntime.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Licensed under the MIT license.
33

44
import React, { Dispatch, useEffect, useState } from "react";
5-
import { ClasspathRequest } from "../../../vscode/utils";
5+
import { ClasspathRequest, CommonRequest } from "../../../vscode/utils";
66
import { VSCodeDivider, VSCodeDropdown, VSCodeOption, } from "@vscode/webview-ui-toolkit/react";
77
import { useDispatch, useSelector } from "react-redux";
88
import { VmInstall } from "../../../../handlers/classpath/types";
@@ -22,7 +22,7 @@ const JdkRuntime = (): JSX.Element => {
2222
if (path === "add-new-jdk") {
2323
ClasspathRequest.onWillAddNewJdk();
2424
} else if (path === "download-jdk") {
25-
ClasspathRequest.onWillExecuteCommand("java.installJdk")
25+
CommonRequest.onWillExecuteCommand("java.installJdk")
2626
} else {
2727
dispatch(setJdks({
2828
activeProjectIndex,

src/project-settings/assets/classpath/features/components/UnmanagedFolderSources.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ const UnmanagedFolderSources = (): JSX.Element => {
6868
<VSCodeDataGridRow className={`${projectType !== ProjectType.UnmanagedFolder ? "inactive" : ""} setting-section-grid-row`} id={`sources-${index}`} onMouseEnter={() => setHoveredRow(`sources-${index}`)} onMouseLeave={() => setHoveredRow(null)} key={source.path}>
6969
<VSCodeDataGridCell className="setting-section-grid-cell setting-section-grid-cell-readonly" gridColumn="1">
7070
<div className="setting-section-grid-cell">
71-
<span className={"codicon codicon-folder mr-1"}></span>
71+
<span className="codicon codicon-folder mr-1"></span>
7272
<span>{source.path}</span>
7373
</div>
7474
{hoveredRow === `sources-${index}` && projectType === ProjectType.UnmanagedFolder && (

src/project-settings/assets/classpath/style.scss

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
11
.root {
2-
min-width: 560px;
3-
margin: 8px 18px 0;
2+
display: flex;
3+
flex-direction: column;
4+
justify-content: space-between;
5+
flex: 1;
46
}
57

68
.setting-header {
79
color: var(--vscode-settings-headerForeground);
810
}
9-
10-
.setting-footer {
11-
position: fixed;
12-
bottom: 0;
13-
width: 80%;
14-
background: var(--background);
15-
}
1611

1712
.setting-section {
1813
width: 100%;

src/project-settings/assets/classpath/utils.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ export const updateMaxHeight = () => {
1010
if (projectSelector) {
1111
maxHeight -= projectSelector.getBoundingClientRect().height;
1212
}
13+
const hinter = document.getElementById("hint");
14+
if (hinter) {
15+
maxHeight -= hinter.getBoundingClientRect().height;
16+
}
1317
const footer = document.getElementById("footer");
1418
if (footer) {
1519
maxHeight -= footer.getBoundingClientRect().height;

src/project-settings/assets/mainpage/features/ProjectSettingView.tsx

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ import ClasspathConfigurationView from "../../classpath/features/ClasspathConfig
77
import { updateActiveTab } from "../../classpath/features/classpathConfigurationViewSlice";
88
import "../style.scss";
99
import { updateActiveSection } from "./commonSlice";
10+
import ProjectSelector from "./component/ProjectSelector";
11+
import { VSCodeDivider } from "@vscode/webview-ui-toolkit/react";
12+
import Footer from "./component/Footer";
13+
import SideBar from "./component/SideBar";
1014

1115
const ProjectSettingView = (): JSX.Element => {
1216
const activeSection: string = useSelector((state: any) => state.commonConfig.ui.activeSection);
@@ -35,7 +39,7 @@ const ProjectSettingView = (): JSX.Element => {
3539
if (routes.length > 1) {
3640
switch (routes[0]) {
3741
case "classpath":
38-
// TODO: sometimes when directly trigger 'COnfigure Java Runtime', the tab won't
42+
// TODO: sometimes when directly trigger 'Configure Java Runtime', the tab won't
3943
// focus to the JDK part, need to investigate
4044
dispatch(updateActiveTab(routes[1]));
4145
break;
@@ -46,26 +50,20 @@ const ProjectSettingView = (): JSX.Element => {
4650
}
4751
}
4852

49-
const onClickNavBarItem = (panelId: string) => {
50-
dispatch(updateActiveSection(panelId));
51-
};
52-
5353
return (
54-
<div className="app-container">
55-
<div className="app-sidebar">
56-
<div className="app-sidebar-content">
57-
<div className="mt-2">
58-
<div className={`section-link ${activeSection === "classpath" ? "section-link-active" : ""}`} onClick={() => onClickNavBarItem("classpath")}>
59-
Classpath
60-
</div>
61-
</div>
62-
</div>
63-
<div className="app-sidebar-resizer" />
64-
</div>
54+
<div className="root">
55+
<ProjectSelector />
56+
<VSCodeDivider />
57+
<div className="app-container">
58+
<SideBar />
6559
<div className="app-frame">
6660
{getSectionContent()}
6761
</div>
6862
</div>
63+
<VSCodeDivider />
64+
<Footer />
65+
</div>
66+
6967
);
7068
};
7169

src/project-settings/assets/classpath/features/components/Footer.tsx renamed to src/project-settings/assets/mainpage/features/component/Footer.tsx

Lines changed: 3 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

4-
import { VSCodeButton, VSCodeDivider, VSCodeLink} from "@vscode/webview-ui-toolkit/react";
4+
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react";
55
import { Dispatch } from "@reduxjs/toolkit";
66
import React, { useEffect } from "react";
77
import { ClasspathEntry, ProjectInfo } from "../../../../handlers/classpath/types";
88
import { useDispatch, useSelector } from "react-redux";
99
import { ProjectType } from "../../../../../utils/webview";
10-
import { updateMaxHeight } from "../../utils";
11-
import { updateLoadingState } from "../classpathConfigurationViewSlice";
10+
import { updateLoadingState } from "../../../classpath/features/classpathConfigurationViewSlice";
1211
import { ClasspathRequest } from "../../../vscode/utils";
1312

1413
const Footer = (): JSX.Element => {
1514

16-
const activeProjectIndex: number = useSelector((state: any) => state.commonConfig.ui.activeProjectIndex);
1715
const projects: ProjectInfo[] = useSelector((state: any) => state.commonConfig.data.projects);
1816
const sources: ClasspathEntry[][] = useSelector((state: any) => state.classpathConfig.data.sources);
1917
const defaultOutput: string[] = useSelector((state: any) => state.classpathConfig.data.output);
@@ -24,17 +22,6 @@ const Footer = (): JSX.Element => {
2422

2523
const dispatch: Dispatch<any> = useDispatch();
2624

27-
let buildFile: string = "";
28-
if (projectType[activeProjectIndex] === ProjectType.Maven) {
29-
buildFile = "pom.xml";
30-
} else if (projectType[activeProjectIndex] === ProjectType.Gradle) {
31-
buildFile = "build.gradle";
32-
}
33-
34-
const handleOpenBuildFile = () => {
35-
ClasspathRequest.onClickGotoProjectConfiguration(projects[activeProjectIndex].rootPath, projectType[activeProjectIndex]);
36-
};
37-
3825
const handleApply = () => {
3926
ClasspathRequest.onWillUpdateClassPaths(
4027
projects.map(p => p.rootPath),
@@ -60,25 +47,8 @@ const Footer = (): JSX.Element => {
6047
}
6148
}, []);
6249

63-
useEffect(() => {
64-
updateMaxHeight();
65-
window.addEventListener('resize', updateMaxHeight);
66-
return () => {
67-
window.removeEventListener("resize", updateMaxHeight);
68-
}
69-
}, [projectType]);
70-
7150
return (
72-
<div id="footer" className="setting-footer pb-2">
73-
<VSCodeDivider/>
74-
{(projectType[activeProjectIndex] === ProjectType.Gradle || projectType[activeProjectIndex] === ProjectType.Maven) &&
75-
<div className="mb-2 mt-1">
76-
<span className="setting-section-warning">
77-
'{projects[activeProjectIndex].name}' is imported by {projectType[activeProjectIndex]}, changes made to the classpath might be lost after reloading.
78-
To make permanent changes, please edit the <VSCodeLink href="" onClick={() => handleOpenBuildFile()}>{buildFile}</VSCodeLink> file.
79-
</span>
80-
</div>
81-
}
51+
<div id="footer" className="pt-1 pb-2">
8252
{loadingState && <VSCodeButton className="ml-1" disabled>Applying...</VSCodeButton>}
8353
{!loadingState && <VSCodeButton className="ml-1" appearance="primary" onClick={() => handleApply()}>Apply Settings</VSCodeButton>}
8454
</div>

src/project-settings/assets/classpath/features/components/ProjectSelector.tsx renamed to src/project-settings/assets/mainpage/features/component/ProjectSelector.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,18 @@ const ProjectSelector = (): JSX.Element | null => {
2727
}
2828

2929
useEffect(() => {
30+
if (projects.length === 0) {
31+
return;
32+
}
33+
3034
loadProjectClasspath(projects[activeProjectIndex].rootPath);
3135
}, [activeProjectIndex, projects]);
3236

3337
const projectSelections = projects.map((project, index) => {
38+
if (projects.length === 0) {
39+
return null;
40+
}
41+
3442
return (
3543
<VSCodeOption className="setting-section-option" key={project.rootPath} onClick={() => handleActiveProjectChange(index)}>
3644
{project.name}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
4+
import React from "react";
5+
import { useSelector, useDispatch } from "react-redux";
6+
import { Dispatch } from "@reduxjs/toolkit";
7+
import { updateActiveSection } from "../commonSlice";
8+
import { CommonRequest } from "../../../vscode/utils";
9+
10+
const CLASSPATH = "classpath";
11+
const FORMATTER = "formatter";
12+
13+
const SideBar = (): JSX.Element => {
14+
15+
const activeSection: string = useSelector((state: any) => state.commonConfig.ui.activeSection);
16+
const dispatch: Dispatch<any> = useDispatch();
17+
18+
const onClickNavBarItem = (panelId: string) => {
19+
if (panelId === FORMATTER) {
20+
CommonRequest.onWillExecuteCommand("java.formatterSettings");
21+
return;
22+
}
23+
dispatch(updateActiveSection(panelId));
24+
};
25+
26+
return (
27+
<div className="app-sidebar">
28+
<div className="app-sidebar-content">
29+
<div className="mt-2">
30+
<div className={`section-link ${activeSection === CLASSPATH ? "section-link-active" : ""} mb-1`} onClick={() => onClickNavBarItem(CLASSPATH)}>
31+
Classpath
32+
</div>
33+
<div className="section-link mb-1" onClick={() => onClickNavBarItem(FORMATTER)}>
34+
Formatter <span className="codicon codicon-link-external"></span>
35+
</div>
36+
</div>
37+
</div>
38+
<div className="app-sidebar-resizer" />
39+
</div>
40+
);
41+
};
42+
43+
export default SideBar;

0 commit comments

Comments
 (0)