Skip to content

Commit 27b87ef

Browse files
authored
fix(workspace): allow browsing and comparing with local workspace version (#9549)
1 parent 0c23b66 commit 27b87ef

File tree

23 files changed

+110
-74
lines changed

23 files changed

+110
-74
lines changed

components/ui/code-compare/code-compare-view/code-compare-view.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ export function CodeCompareView({
263263
<CodeCompareEditor
264264
DiffEditor={DiffEditor}
265265
language={language}
266-
modifiedPath={modifiedPath}
266+
modifiedPath={`${modifiedPath}${componentCompareContext?.compare?.hasLocalChanges ? '-local' : ''}`}
267267
originalPath={originalPath}
268268
originalFileContent={originalFileContent}
269269
modifiedFileContent={modifiedFileContent}

components/ui/code-compare/code-compare.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,21 +35,22 @@ export function CodeCompare({ fileIconSlot, className, CodeView = CodeCompareVie
3535

3636
// todo - look into this loading flag where it needs to be used
3737
// eslint-disable-next-line @typescript-eslint/no-unused-vars
38-
const { base, compare, state: compareState, hooks: compareHooks, hidden, loading } = componentCompareContext || {};
38+
const { base, compare, state: compareState, hooks: compareHooks, hidden, loading, } = componentCompareContext || {};
3939

4040
const state = compareState?.code;
4141
const hook = compareHooks?.code;
4242

4343
const [isSidebarOpen, setSidebarOpenness] = useState(false);
44-
45-
const { fileTree: baseFileTree = [], mainFile } = useCode(hidden ? undefined : base?.model.id);
46-
const { fileTree: compareFileTree = [] } = useCode(hidden ? undefined : compare?.model.id);
44+
const baseHost = 'teambit.scope/scope';
45+
const compareHost = compare?.hasLocalChanges ? 'teambit.workspace/workspace' : 'teambit.scope/scope';
46+
const { fileTree: baseFileTree = [], mainFile } = useCode(hidden ? undefined : base?.model.id, baseHost);
47+
const { fileTree: compareFileTree = [] } = useCode(hidden ? undefined : compare?.model.id, compareHost);
4748

4849
const fileCompareDataByName = componentCompareContext?.fileCompareDataByName;
4950
const anyFileHasDiffStatus = useRef<boolean>(false);
5051

5152
const fileTree = useMemo(() => {
52-
const allFiles = uniq(baseFileTree.concat(compareFileTree));
53+
const allFiles = uniq<string>(baseFileTree.concat(compareFileTree));
5354
anyFileHasDiffStatus.current = false;
5455
// sort by diff status
5556
return !fileCompareDataByName

components/ui/code-compare/use-code-compare/use-code-compare.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,14 @@ export function useCodeCompare({ fileName }: UseCodeCompareProps): UseCodeCompar
3838
const { fileContent: downloadedCompareFileContent, loading: loadingDownloadedCompareFileContent } = useFileContent(
3939
compareId,
4040
fileName,
41-
componentCompareContext?.hidden || loadingFromContext || !!codeCompareDataForFile?.compareContent
41+
componentCompareContext?.hidden || loadingFromContext || !!codeCompareDataForFile?.compareContent,
42+
comparingLocalChanges ? 'teambit.workspace/workspace' : 'teambit.scope/scope',
4243
);
4344
const { fileContent: downloadedBaseFileContent, loading: loadingDownloadedBaseFileContent } = useFileContent(
4445
baseId,
4546
fileName,
46-
componentCompareContext?.hidden || loadingFromContext || !!codeCompareDataForFile?.baseContent
47+
componentCompareContext?.hidden || loadingFromContext || !!codeCompareDataForFile?.baseContent,
48+
'teambit.scope/scope',
4749
);
4850
const loading =
4951
loadingFromContext ||

components/ui/code-tab-page/code-tab-page.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ComponentContext } from '@teambit/component';
1+
import { ComponentContext, ComponentID } from '@teambit/component';
22
import classNames from 'classnames';
33
import React, { useContext, useState, HTMLAttributes, useMemo } from 'react';
44
import { useSearchParams } from 'react-router-dom';
@@ -119,13 +119,14 @@ export function resolveFilePath(
119119
return mainFile;
120120
}
121121

122-
export function CodePage({ className, fileIconSlot, host, codeViewClassName }: CodePageProps) {
122+
export function CodePage({ className, fileIconSlot, host: hostFromProps, codeViewClassName }: CodePageProps) {
123123
const urlParams = useCodeParams();
124124
const [searchParams] = useSearchParams();
125125
const scopeFromQueryParams = searchParams.get('scope');
126126
const component = useContext(ComponentContext);
127+
const host = useMemo(() => urlParams.version ? 'teambit.scope/scope' : hostFromProps, [urlParams.version, hostFromProps]);
127128

128-
const { mainFile, fileTree = [], dependencies, devFiles, loading: loadingCode } = useCode(component.id);
129+
const { mainFile, fileTree = [], dependencies, devFiles, loading: loadingCode } = useCode(component.id, host);
129130
const { data: artifacts = [] } = useComponentArtifacts(host, component.id.toString());
130131

131132
const currentFile = resolveFilePath(urlParams.file, fileTree, mainFile, loadingCode);
@@ -176,17 +177,19 @@ export function CodePage({ className, fileIconSlot, host, codeViewClassName }: C
176177
});
177178
}, [dependencies?.length]);
178179

180+
const componentId = urlParams.version ? component.id : ComponentID.fromString(component.id.toStringWithoutVersion());
179181
return (
180182
<SplitPane layout={sidebarOpenness} size="85%" className={classNames(styles.codePage, className)}>
181183
<Pane className={styles.left}>
182184
<CodeView
183-
componentId={component.id}
185+
componentId={componentId}
184186
currentFile={currentFile}
185187
icon={icon}
186188
currentFileContent={currentArtifactFileContent}
187189
loading={loadingArtifactFileContent || loadingCode}
188190
codeSnippetClassName={codeViewClassName}
189191
dependencies={dependencies}
192+
host={host}
190193
/>
191194
</Pane>
192195
<HoverSplitter className={styles.splitter}>

components/ui/code-view/code-view.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export type CodeViewProps = {
2222
loading?: boolean;
2323
codeSnippetClassName?: string;
2424
dependencies?: DependencyType[];
25+
host?: string
2526
} & HTMLAttributes<HTMLDivElement>;
2627

2728
SyntaxHighlighter.registerLanguage('md', markDownSyntax);
@@ -112,6 +113,7 @@ export function CodeView({
112113
codeSnippetClassName,
113114
loading: loadingFromProps,
114115
dependencies,
116+
host = 'teambit.scope/scope',
115117
}: CodeViewProps) {
116118
const depsByPackageName = new Map<string, DependencyType>(
117119
(dependencies || []).map((dep) => [(dep.packageName || dep.id).toString(), dep])
@@ -120,7 +122,8 @@ export function CodeView({
120122
const { fileContent: downloadedFileContent, loading: loadingFileContent } = useFileContent(
121123
componentId,
122124
currentFile,
123-
!!currentFileContent
125+
!!currentFileContent,
126+
host,
124127
);
125128
const loading = loadingFromProps || loadingFileContent;
126129
const location = useLocation();

components/ui/component-compare/component-compare/component-compare.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ function RenderCompareScreen(
256256
// eslint-disable-next-line complexity
257257
export function ComponentCompare(props: ComponentCompareProps) {
258258
const {
259-
host,
259+
host: hostFromProps,
260260
baseId: baseIdFromProps,
261261
compareId: compareIdFromProps,
262262
// eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -283,13 +283,14 @@ export function ComponentCompare(props: ComponentCompareProps) {
283283
const component = useContext(ComponentContext);
284284
const componentDescriptor = useContext(ComponentDescriptorContext);
285285
const location = useLocation();
286-
const isWorkspace = host === 'teambit.workspace/workspace';
287-
286+
const isWorkspace = hostFromProps === 'teambit.workspace/workspace';
287+
const compareHost = isWorkspace && !location?.search.includes('version') && !compareIdFromProps && component.logs?.length === 0 ? hostFromProps : 'teambit.scope/scope';
288+
const host = 'teambit.scope/scope';
288289
const {
289290
component: compareComponent,
290291
loading: loadingCompare,
291292
componentDescriptor: compareComponentDescriptor,
292-
} = useComponent(host, compareIdOverride?.toString() || compareIdFromProps?.toString(), {
293+
} = useComponent(compareHost, compareIdOverride?.toString() || compareIdFromProps?.toString(), {
293294
skip: hidden || (!compareIdFromProps && !compareIdOverride),
294295
customUseComponent,
295296
logFilters: {
@@ -352,7 +353,7 @@ export function ComponentCompare(props: ComponentCompareProps) {
352353
}, [compare?.id.toString()]);
353354

354355
const skipComponentCompareQuery =
355-
hidden || compareIsLocalChanges || base?.id.version?.toString() === compare?.id.version?.toString();
356+
hidden || (base?.id.version?.toString() === compare?.id.version?.toString() && !compareIsLocalChanges);
356357

357358
const { loading: compCompareLoading, componentCompareData } = useComponentCompareQuery(
358359
base?.id.toString(),

components/ui/side-bar/component-tree/component-view/component-view.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,6 @@ export function ComponentView(props: ComponentViewProps) {
135135

136136
const searchParams = new URLSearchParams(location.search);
137137
const scopeFromQueryParams = searchParams.get('scope');
138-
139138
const pathname = location.pathname.substring(1).split('?')[0];
140139
const compIdStr = component.id.toStringWithoutVersion();
141140
const compIdName = component.id.fullName;

components/ui/version-dropdown/version-dropdown.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ function _VersionDropdown({
154154
getActiveTabIndex={getActiveTabIndex}
155155
lanes={lanes}
156156
useVersions={useComponentVersions}
157+
onVersionClicked={() => setOpen(false)}
157158
open={open}
158159
/>
159160
</Dropdown>
@@ -173,6 +174,7 @@ type VersionMenuProps = {
173174
loading?: boolean;
174175
getActiveTabIndex?: GetActiveTabIndex;
175176
open?: boolean;
177+
onVersionClicked?: () => void;
176178
} & React.HTMLAttributes<HTMLDivElement>;
177179

178180
export type VersionMenuTab =
@@ -208,6 +210,7 @@ function _VersionMenu({
208210
getActiveTabIndex = defaultActiveTabIndex,
209211
loading: loadingFromProps,
210212
open,
213+
onVersionClicked,
211214
...rest
212215
}: VersionMenuProps) {
213216
const { snaps, tags, loading: loadingVersions } = useVersions?.() || {};
@@ -268,6 +271,7 @@ function _VersionMenu({
268271
latestVersion={latestVersion}
269272
overrideVersionHref={overrideVersionHref}
270273
showDetails={showVersionDetails}
274+
onVersionClicked={onVersionClicked}
271275
{...version}
272276
></VersionInfo>
273277
);
@@ -296,6 +300,7 @@ function _VersionMenu({
296300
href={'?'}
297301
active={currentVersion === LOCAL_VERSION}
298302
className={classNames(styles.versionRow, styles.localVersion)}
303+
onClick={onVersionClicked}
299304
>
300305
<div className={styles.version}>
301306
<UserAvatar size={24} account={{}} className={styles.versionUserAvatar} />

components/ui/version-dropdown/version-info/version-info.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export interface VersionInfoProps extends DropdownComponentVersion {
1414
latestVersion?: string;
1515
overrideVersionHref?: (version: string) => string;
1616
showDetails?: boolean;
17+
onVersionClicked?: () => void;
1718
}
1819

1920
export const VersionInfo = React.memo(React.forwardRef<HTMLDivElement, VersionInfoProps>(_VersionInfo));
@@ -31,6 +32,7 @@ function _VersionInfo(
3132
message,
3233
tag,
3334
profileImage,
35+
onVersionClicked,
3436
}: VersionInfoProps,
3537
ref?: React.ForwardedRef<HTMLDivElement>
3638
) {
@@ -62,7 +64,7 @@ function _VersionInfo(
6264
const isLatest = version === latestVersion;
6365

6466
return (
65-
<div ref={ref || currentVersionRef}>
67+
<div ref={ref || currentVersionRef} onClick={onVersionClicked}>
6668
<MenuLinkItem active={isCurrent} href={href} className={styles.versionRow}>
6769
<div className={styles.version}>
6870
<UserAvatar size={24} account={author} className={styles.versionUserAvatar} showTooltip={true} />

scopes/component/code/code.ui.runtime.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export class CodeUI {
2727
*/
2828
private host: string,
2929
private fileIconSlot?: FileIconSlot
30-
) {}
30+
) { }
3131

3232
getCodePage = (props?: Partial<CodePageProps>) => {
3333
return <CodePage {...(props || {})} fileIconSlot={this.fileIconSlot} host={this.host} />;

scopes/component/component-compare/component-compare.main.runtime.ts

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,13 @@ export class ComponentCompareMain {
5252
private depResolver: DependencyResolverMain,
5353
private importer: ImporterMain,
5454
private workspace?: Workspace
55-
) {}
55+
) { }
5656

5757
async compare(baseIdStr: string, compareIdStr: string): Promise<ComponentCompareResult> {
5858
const host = this.componentAspect.getHost();
5959
const [baseCompId, compareCompId] = await host.resolveMultipleComponentIds([baseIdStr, compareIdStr]);
6060
const modelComponent = await this.scope.legacyScope.getModelComponentIfExist(compareCompId);
61+
const comparingWithLocalChanges = this.workspace && baseIdStr === compareIdStr;
6162

6263
if (!modelComponent) {
6364
throw new BitError(`component ${compareCompId.toString()} doesn't have any version yet`);
@@ -71,21 +72,20 @@ export class ComponentCompareMain {
7172
const baseVersion = baseCompId.version as string;
7273
const compareVersion = compareCompId.version as string;
7374

74-
const repository = this.scope.legacyScope.objects;
75-
const baseVersionObject = await modelComponent.loadVersion(baseVersion, repository);
76-
const compareVersionObject = await modelComponent.loadVersion(compareVersion, repository);
77-
78-
const diff: DiffResults = await this.diffBetweenVersionsObjects(
79-
modelComponent,
80-
baseVersionObject,
81-
compareVersionObject,
82-
baseVersion,
83-
compareVersion,
84-
{}
85-
);
75+
const components = await host.getMany([baseCompId, compareCompId])
76+
const baseComponent = components?.[0];
77+
const compareComponent = components?.[1];
78+
const componentWithoutVersion = await host.get((baseCompId || compareCompId).changeVersion(undefined))
8679

87-
const baseComponent = await host.get(baseCompId);
88-
const compareComponent = await host.get(compareCompId);
80+
const diff = componentWithoutVersion
81+
? await this.computeDiff(
82+
componentWithoutVersion,
83+
comparingWithLocalChanges ? undefined : baseVersion,
84+
comparingWithLocalChanges ? undefined : compareVersion, {})
85+
: {
86+
filesDiff: [],
87+
fieldsDiff: []
88+
};
8989

9090
const baseTestFiles =
9191
(baseComponent && (await this.tester.getTestFiles(baseComponent).map((file) => file.relative))) || [];
@@ -117,7 +117,7 @@ export class ComponentCompareMain {
117117
if (!this.workspace) throw new OutsideWorkspaceError();
118118
const ids = pattern ? await this.workspace.idsByPattern(pattern) : await this.workspace.listTagPendingIds();
119119
const consumer = this.workspace.consumer;
120-
if (!ids.length) {
120+
if (!ids.length) {
121121
return [];
122122
}
123123
const diffResults = await this.componentsDiff(ids, version, toVersion, {
@@ -186,13 +186,10 @@ export class ComponentCompareMain {
186186
toVersion: string | undefined,
187187
diffOpts: DiffOptions
188188
) {
189-
if (!this.workspace) throw new OutsideWorkspaceError();
190-
const consumer = this.workspace.consumer;
191-
// if (!version) throw new Error('getComponentDiffOfVersion expects to get version');
192189
const consumerComponent = component.state._consumer as ConsumerComponent;
193190
const diffResult: DiffResults = { id: component.id, hasDiff: false };
194191
const modelComponent =
195-
consumerComponent.modelComponent || (await consumer.scope.getModelComponentIfExist(component.id));
192+
consumerComponent.modelComponent || (await this.scope.legacyScope.getModelComponentIfExist(component.id));
196193

197194
if (!modelComponent || !consumerComponent.componentFromModel) {
198195
if (version || toVersion) {
@@ -213,13 +210,13 @@ export class ComponentCompareMain {
213210
if (hasDiff(diffResult)) diffResult.hasDiff = true;
214211
return diffResult;
215212
}
216-
const repository = consumer.scope.objects;
213+
const repository = this.scope.legacyScope.objects;
217214
const idsToImport = compact([
218215
version ? component.id.changeVersion(version) : undefined,
219216
toVersion ? component.id.changeVersion(toVersion) : undefined,
220217
]);
221218
const idList = ComponentIdList.fromArray(idsToImport);
222-
await consumer.scope.scopeImporter.importWithoutDeps(idList, { cache: true, reason: 'to show diff' });
219+
await this.scope.legacyScope.scopeImporter.importWithoutDeps(idList, { cache: true, reason: 'to show diff' });
223220
if (diffOpts.compareToParent) {
224221
if (!version) throw new BitError('--parent flag expects to get version');
225222
if (toVersion) throw new BitError('--parent flag expects to get only one version');
@@ -240,11 +237,11 @@ export class ComponentCompareMain {
240237

241238
diffResult.filesDiff = await getFilesDiff(fromFiles, toFiles, fromVersionLabel, toVersionLabel);
242239
const fromVersionComponent = version
243-
? await modelComponent.toConsumerComponent(version, consumer.scope.name, repository)
240+
? await modelComponent.toConsumerComponent(version, this.scope.legacyScope.name, repository)
244241
: consumerComponent.componentFromModel;
245242

246243
const toVersionComponent = toVersion
247-
? await modelComponent.toConsumerComponent(toVersion, consumer.scope.name, repository)
244+
? await modelComponent.toConsumerComponent(toVersion, this.scope.legacyScope.name, repository)
248245
: consumerComponent;
249246
await updateFieldsDiff(fromVersionComponent, toVersionComponent, diffResult, diffOpts);
250247

scopes/component/component/component.graphql.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,9 @@ export function componentSchema(componentExtension: ComponentMain): Schema {
250250
errorMessage: err.message ? stripAnsi(err.message) : err.name,
251251
}));
252252
},
253-
id: async (host: ComponentFactory) => {
254-
return host.name;
253+
id: async (host: ComponentFactory, _args, _context, info) => {
254+
const extensionId = info.variableValues.extensionId;
255+
return extensionId ? `${host.name}/${extensionId}` : host.name;
255256
},
256257
name: async (host: ComponentFactory) => {
257258
return host.name;

scopes/component/component/component.main.runtime.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ export class ComponentMain {
130130
return priorityHost || hosts[0];
131131
}
132132

133+
134+
133135
getShowFragments() {
134136
const fragments = orderBy(flatten(this.showFragmentSlot.values()), ['weight', ['asc']]);
135137
return fragments;

0 commit comments

Comments
 (0)