mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-07 10:16:03 -10:00
fix(project-tree): sort workspace projects by folder name (#1583)
Workspace member roots were listed in manifest order. The Project and Project Files views now sort them by the displayed folder name with the same natural, case-insensitive comparison as tree entries; the stored member order is unchanged. Co-authored-by: shohruh-genius <[email protected]>
This commit is contained in:
1 parent
31e477b7fb
commit
af0ffb809e
4 files changed
+31
-14
No files matched your search
@@ -664,10 +664,24 @@ describe("Show Members", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("renders workspace member roots with their own paths, without the settings directory", async () => {
|
||||
fs = new MemoryFs({ "/z/first.txt": "", "/a/second.txt": "", "/workspace/.openidea/workspace.json": "{}" });
|
||||
it("sorts workspace member roots by the folder names shown in the tree", async () => {
|
||||
fs = new MemoryFs({
|
||||
"/a/service10/ten.txt": "",
|
||||
"/z/Service2/two.txt": "",
|
||||
"/m/alpha/first.txt": "",
|
||||
"/workspace/.openidea/workspace.json": "{}",
|
||||
});
|
||||
setProjectFsForTests(fs, "/workspace");
|
||||
initProjectTree("/workspace", "Workspace", ["/z", "/a"]);
|
||||
initProjectTree("/workspace", "Workspace", ["/a/service10", "/z/Service2", "/m/alpha"]);
|
||||
const { rows } = setup();
|
||||
await waitFor(() => expect(rows()).toEqual(["z/z", "first.txt", "a/a", "second.txt"]));
|
||||
await waitFor(() =>
|
||||
expect(rows()).toEqual([
|
||||
"alpha/m/alpha",
|
||||
"first.txt",
|
||||
"Service2/z/Service2",
|
||||
"two.txt",
|
||||
"service10/a/service10",
|
||||
"ten.txt",
|
||||
]),
|
||||
);
|
||||
});
|
||||
@@ -100,6 +100,10 @@ export function isVisible(entry: FileEntry, opts: TreeOptions): boolean {
|
||||
|
||||
const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: "base" });
|
||||
|
||||
export function compareNames(a: string, b: string): number {
|
||||
return collator.compare(a, b) || (a < b ? -1 : a > b ? 1 : 0);
|
||||
}
|
||||
|
||||
/** Symlinks report the target's metadata; folders have size 0 (the entry has no target kind). */
|
||||
export const isDirEntry = (e: FileEntry) => e.kind === "dir" || (e.kind === "symlink" && e.size === 0);
|
||||
|
||||
@@ -125,7 +129,7 @@ export function sortEntries(
|
||||
const m = (b.mtimeMs ?? 0) - (a.mtimeMs ?? 0);
|
||||
if (m) return m;
|
||||
}
|
||||
return collator.compare(a.name, b.name) || (a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
||||
return compareNames(a.name, b.name);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -104,12 +104,13 @@ describe("creating packages", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("uses only manifest members in order in workspace Project and Project Files views", () => {
|
||||
it("shows manifest members in name order in workspace Project and Project Files views", () => {
|
||||
for (const mode of ["project", "projectFiles"] as const) {
|
||||
initProjectTree("/workspace", "Workspace", ["/z", "/a"]);
|
||||
useProjectTree.setState({ mode });
|
||||
const model = selectModel(useProjectTree.getState());
|
||||
expect(model.roots.map((r) => r.path)).toEqual(["/z", "/a"]);
|
||||
expect(model.roots.map((r) => r.path)).toEqual(["/a", "/z"]);
|
||||
expect(useProjectTree.getState().members).toEqual(["/z", "/a"]);
|
||||
expect(model.byKey.has("/workspace")).toBe(false);
|
||||
initProjectTree("/workspace", "Workspace", ["/a"]);
|
||||
expect(selectModel(useProjectTree.getState()).roots.map((r) => r.path)).toEqual(["/a"]);
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
GROUP_PREFIX,
|
||||
buildModel,
|
||||
buildPathsModel,
|
||||
compareNames,
|
||||
extraFolders,
|
||||
isGroupKey,
|
||||
isLibKey,
|
||||
@@ -34,7 +35,7 @@ import {
|
||||
} from "./model";
|
||||
import { projectFs } from "./fs";
|
||||
import { projectViewRoots, useProjectViewRoots, type ProjectViewRootContribution } from "@/workbench/contributions";
|
||||
import { ancestorsWithin, isSameOrInside, type PackageKind } from "./paths";
|
||||
import { ancestorsWithin, isSameOrInside, nameOf, type PackageKind } from "./paths";
|
||||
|
||||
export interface ViewOptions extends TreeOptions {
|
||||
/** Select the active editor's file in the tree. */
|
||||
@@ -218,12 +219,9 @@ export function selectModel(s: ProjectTreeState): TreeModel {
|
||||
const extras = useProjectViewRoots.getState().roots;
|
||||
const options = treeOptions(s);
|
||||
const contributed = projectViewRoots(extras);
|
||||
const memberRoots = s.members?.map((path) => ({
|
||||
path,
|
||||
label: path.slice(path.lastIndexOf("/") + 1),
|
||||
icon: "",
|
||||
detail: path,
|
||||
}));
|
||||
const memberRoots = s.members
|
||||
?.map((path) => ({ path, label: nameOf(path), icon: "", detail: path }))
|
||||
.sort((a, b) => compareNames(a.label, b.label));
|
||||
const project = () =>
|
||||
memberRoots
|
||||
? withExtraRoots(EMPTY_MODEL, memberRoots, s.listings, options, placeholder)
|
||||
|
||||
Reference in new issue
Block a user