mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-05 03:51:54 +01:00
Add upstream diff link for project workspaces
This commit is contained in:
1 parent
b70abf7112
commit
f097fe4937
2 files changed
+36
-3
No files matched your search
@@ -21,6 +21,16 @@ type WorkspaceDiffData = WorkspaceDiffResponse;
|
||||
type WorkspacePatchDiffOptions = PatchDiffProps<undefined>["options"];
|
||||
type DiffViewMode = "working-tree" | "head";
|
||||
|
||||
function readInitialView(): DiffViewMode {
|
||||
if (typeof window === "undefined") return "working-tree";
|
||||
return new URLSearchParams(window.location.search).get("diffView") === "head" ? "head" : "working-tree";
|
||||
}
|
||||
|
||||
function readInitialBaseRef() {
|
||||
if (typeof window === "undefined") return "";
|
||||
return new URLSearchParams(window.location.search).get("baseRef") ?? "";
|
||||
}
|
||||
|
||||
function buttonClass(active = false) {
|
||||
return [
|
||||
"inline-flex h-8 items-center justify-center rounded-md border px-2.5 text-xs font-medium transition-colors",
|
||||
@@ -273,8 +283,8 @@ function CollapsedFilePanel({
|
||||
export function ChangesTab({ context }: PluginDetailTabProps) {
|
||||
const toast = usePluginToast();
|
||||
const [mode, setMode] = useState<DiffRenderMode>("split");
|
||||
const [view, setView] = useState<DiffViewMode>("working-tree");
|
||||
const [baseRef, setBaseRef] = useState("");
|
||||
const [view, setView] = useState<DiffViewMode>(() => readInitialView());
|
||||
const [baseRef, setBaseRef] = useState(() => readInitialBaseRef());
|
||||
const [includeUntracked, setIncludeUntracked] = useState(false);
|
||||
const [expandedFiles, setExpandedFiles] = useState<Set<string>>(() => new Set());
|
||||
const [selectedPath, setSelectedPath] = useState<string | null>(null);
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useEffect, useMemo, useState } from "react";
|
||||
import { Link, useLocation, useNavigate, useParams } from "@/lib/router";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { isUuidLike, type ProjectWorkspace } from "@paperclipai/shared";
|
||||
import { ArrowLeft, Check, ExternalLink, Loader2, Sparkles } from "lucide-react";
|
||||
import { ArrowLeft, Check, ExternalLink, GitCompare, Loader2, Sparkles } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { Tabs } from "@/components/ui/tabs";
|
||||
@@ -41,11 +41,20 @@ type ProjectWorkspaceVisibility = ProjectWorkspace["visibility"];
|
||||
type ProjectWorkspaceBaseTab = "configuration";
|
||||
type ProjectWorkspacePluginTab = `plugin:${string}`;
|
||||
type ProjectWorkspaceTab = ProjectWorkspaceBaseTab | ProjectWorkspacePluginTab;
|
||||
const WORKSPACE_CHANGES_TAB = "plugin:paperclip.workspace-diff:workspace-changes-tab" as ProjectWorkspacePluginTab;
|
||||
|
||||
function isProjectWorkspacePluginTab(value: string | null): value is ProjectWorkspacePluginTab {
|
||||
return typeof value === "string" && value.startsWith("plugin:");
|
||||
}
|
||||
|
||||
function upstreamBaseRef(workspace: ProjectWorkspace) {
|
||||
if (workspace.defaultRef) return workspace.defaultRef;
|
||||
if (workspace.repoRef) {
|
||||
return workspace.repoRef.startsWith("origin/") ? workspace.repoRef : `origin/${workspace.repoRef.replace(/^refs\/heads\//, "")}`;
|
||||
}
|
||||
return "origin/master";
|
||||
}
|
||||
|
||||
const SOURCE_TYPE_OPTIONS: Array<{ value: ProjectWorkspaceSourceType; label: string; description: string }> = [
|
||||
{ value: "local_path", label: "Local git checkout", description: "A local path Paperclip can use directly." },
|
||||
{ value: "non_git_path", label: "Local non-git path", description: "A local folder without git semantics." },
|
||||
@@ -394,6 +403,14 @@ export function ProjectWorkspaceDetail() {
|
||||
};
|
||||
|
||||
const sourceTypeDescription = SOURCE_TYPE_OPTIONS.find((option) => option.value === form.sourceType)?.description ?? null;
|
||||
const changesVsUpstreamUrl = (() => {
|
||||
const params = new URLSearchParams({
|
||||
tab: WORKSPACE_CHANGES_TAB,
|
||||
diffView: "head",
|
||||
baseRef: upstreamBaseRef(workspace),
|
||||
});
|
||||
return `${projectWorkspaceUrl(project, routeWorkspaceId)}?${params.toString()}`;
|
||||
})();
|
||||
const handleTabChange = (tab: ProjectWorkspaceTab) => {
|
||||
const workspacePath = projectWorkspaceUrl(project, routeWorkspaceId);
|
||||
if (isProjectWorkspacePluginTab(tab)) {
|
||||
@@ -415,6 +432,12 @@ export function ProjectWorkspaceDetail() {
|
||||
<div className="inline-flex items-center rounded-full border border-border bg-background px-2.5 py-1 text-xs text-muted-foreground">
|
||||
{workspace.isPrimary ? "Primary workspace" : "Secondary workspace"}
|
||||
</div>
|
||||
<Button variant="outline" size="sm" asChild>
|
||||
<Link to={changesVsUpstreamUrl}>
|
||||
<GitCompare className="mr-1 h-4 w-4" />
|
||||
Changes vs upstream
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Tabs value={activeTab} onValueChange={(value) => handleTabChange(value as ProjectWorkspaceTab)}>
|
||||
|
||||
Reference in new issue
Block a user