@scm-manager/ui-components 4.0.0-REACT19-20250910-113025 → 4.0.0-REACT19-20250913-143258
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +11 -11
- package/src/Image.tsx +3 -2
- package/src/__snapshots__/storyshots.test.ts.snap +32 -15
- package/src/avatar/AvatarImage.tsx +2 -2
- package/src/layout/Footer.tsx +7 -11
- package/src/repos/DiffTypes.ts +16 -2
- package/src/repos/changesets/ChangesetAuthor.tsx +2 -2
- package/src/repos/changesets/Contributor.tsx +1 -1
- package/src/repos/changesets/SingleChangeset.tsx +1 -0
- package/src/repos/diff/DiffFileTree.tsx +89 -37
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scm-manager/ui-components",
|
|
3
|
-
"version": "4.0.0-REACT19-
|
|
3
|
+
"version": "4.0.0-REACT19-20250913-143258",
|
|
4
4
|
"description": "UI Components for SCM-Manager and its plugins",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"files": [
|
|
@@ -37,10 +37,10 @@
|
|
|
37
37
|
"@scm-manager/jest-preset": "^2.15.0-alpha1",
|
|
38
38
|
"@scm-manager/prettier-config": "^2.12.0",
|
|
39
39
|
"@scm-manager/tsconfig": "^2.13.0",
|
|
40
|
-
"@scm-manager/ui-shortcuts": "4.0.0-REACT19-
|
|
41
|
-
"@scm-manager/ui-syntaxhighlighting": "4.0.0-REACT19-
|
|
42
|
-
"@scm-manager/ui-text": "4.0.0-REACT19-
|
|
43
|
-
"@scm-manager/ui-types": "4.0.0-REACT19-
|
|
40
|
+
"@scm-manager/ui-shortcuts": "4.0.0-REACT19-20250913-143258",
|
|
41
|
+
"@scm-manager/ui-syntaxhighlighting": "4.0.0-REACT19-20250913-143258",
|
|
42
|
+
"@scm-manager/ui-text": "4.0.0-REACT19-20250913-143258",
|
|
43
|
+
"@scm-manager/ui-types": "4.0.0-REACT19-20250913-143258",
|
|
44
44
|
"@storybook/addon-actions": "^9.0.8",
|
|
45
45
|
"@storybook/addon-docs": "^9.1.5",
|
|
46
46
|
"@storybook/addon-essentials": "^9.0.0-alpha.12",
|
|
@@ -67,12 +67,12 @@
|
|
|
67
67
|
"storybook-addon-themes": "^6.1.0"
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@scm-manager/ui-api": "4.0.0-REACT19-
|
|
71
|
-
"@scm-manager/ui-buttons": "4.0.0-REACT19-
|
|
72
|
-
"@scm-manager/ui-core": "4.0.0-REACT19-
|
|
73
|
-
"@scm-manager/ui-extensions": "4.0.0-REACT19-
|
|
74
|
-
"@scm-manager/ui-layout": "4.0.0-REACT19-
|
|
75
|
-
"@scm-manager/ui-overlays": "4.0.0-REACT19-
|
|
70
|
+
"@scm-manager/ui-api": "4.0.0-REACT19-20250913-143258",
|
|
71
|
+
"@scm-manager/ui-buttons": "4.0.0-REACT19-20250913-143258",
|
|
72
|
+
"@scm-manager/ui-core": "4.0.0-REACT19-20250913-143258",
|
|
73
|
+
"@scm-manager/ui-extensions": "4.0.0-REACT19-20250913-143258",
|
|
74
|
+
"@scm-manager/ui-layout": "4.0.0-REACT19-20250913-143258",
|
|
75
|
+
"@scm-manager/ui-overlays": "4.0.0-REACT19-20250913-143258",
|
|
76
76
|
"deepmerge": "^4.2.2",
|
|
77
77
|
"hast-util-sanitize": "^3.0.2",
|
|
78
78
|
"react-diff-view": "^2.4.10",
|
package/src/Image.tsx
CHANGED
|
@@ -22,6 +22,7 @@ type Props = {
|
|
|
22
22
|
alt: string;
|
|
23
23
|
title?: string;
|
|
24
24
|
className?: string;
|
|
25
|
+
crossOrigin?: "anonymous" | "";
|
|
25
26
|
};
|
|
26
27
|
|
|
27
28
|
/**
|
|
@@ -37,8 +38,8 @@ class Image extends React.Component<Props> {
|
|
|
37
38
|
};
|
|
38
39
|
|
|
39
40
|
render() {
|
|
40
|
-
const { alt, title, className } = this.props;
|
|
41
|
-
return <img className={className} src={this.createImageSrc()} alt={alt} title={title} />;
|
|
41
|
+
const { alt, title, className, crossOrigin } = this.props;
|
|
42
|
+
return <img className={className} src={this.createImageSrc()} alt={alt} title={title} crossOrigin={crossOrigin} />;
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
|
|
@@ -1825,18 +1825,20 @@ exports[`Storyshots Footer Full 1`] = `
|
|
|
1825
1825
|
className="has-text-weight-bold mb-2"
|
|
1826
1826
|
>
|
|
1827
1827
|
<div
|
|
1828
|
+
className="is-flex"
|
|
1828
1829
|
data-testid="trillian-mcmillian"
|
|
1829
1830
|
>
|
|
1830
|
-
<
|
|
1831
|
-
className="Footer__AvatarContainer-sc-k70cxq-1 kckyuz image is-rounded"
|
|
1832
|
-
>
|
|
1831
|
+
<div>
|
|
1833
1832
|
<img
|
|
1834
1833
|
alt="trillian"
|
|
1835
|
-
className="is-rounded Footer__VCenteredAvatar-sc-k70cxq-0
|
|
1834
|
+
className="is-rounded Footer__VCenteredAvatar-sc-k70cxq-0 gNPbnb"
|
|
1835
|
+
crossOrigin="anonymous"
|
|
1836
1836
|
src="test-file-stub"
|
|
1837
1837
|
/>
|
|
1838
|
-
</
|
|
1839
|
-
|
|
1838
|
+
</div>
|
|
1839
|
+
<div>
|
|
1840
|
+
Trillian McMillian
|
|
1841
|
+
</div>
|
|
1840
1842
|
</div>
|
|
1841
1843
|
</h2>
|
|
1842
1844
|
<ul
|
|
@@ -2031,18 +2033,20 @@ exports[`Storyshots Footer With Avatar 1`] = `
|
|
|
2031
2033
|
className="has-text-weight-bold mb-2"
|
|
2032
2034
|
>
|
|
2033
2035
|
<div
|
|
2036
|
+
className="is-flex"
|
|
2034
2037
|
data-testid="trillian-mcmillian"
|
|
2035
2038
|
>
|
|
2036
|
-
<
|
|
2037
|
-
className="Footer__AvatarContainer-sc-k70cxq-1 kckyuz image is-rounded"
|
|
2038
|
-
>
|
|
2039
|
+
<div>
|
|
2039
2040
|
<img
|
|
2040
2041
|
alt="trillian"
|
|
2041
|
-
className="is-rounded Footer__VCenteredAvatar-sc-k70cxq-0
|
|
2042
|
+
className="is-rounded Footer__VCenteredAvatar-sc-k70cxq-0 gNPbnb"
|
|
2043
|
+
crossOrigin="anonymous"
|
|
2042
2044
|
src="test-file-stub"
|
|
2043
2045
|
/>
|
|
2044
|
-
</
|
|
2045
|
-
|
|
2046
|
+
</div>
|
|
2047
|
+
<div>
|
|
2048
|
+
Trillian McMillian
|
|
2049
|
+
</div>
|
|
2046
2050
|
</div>
|
|
2047
2051
|
</h2>
|
|
2048
2052
|
<ul
|
|
@@ -20073,6 +20077,7 @@ exports[`Storyshots Repositories/Annotate With Avatars 1`] = `
|
|
|
20073
20077
|
<img
|
|
20074
20078
|
alt="Arthur Dent"
|
|
20075
20079
|
className="has-rounded-border AuthorImage-sc-ygvjd8-0 dTapGF"
|
|
20080
|
+
crossOrigin="anonymous"
|
|
20076
20081
|
src="https://robohash.org/arthur.dent@hitchhiker.com.png"
|
|
20077
20082
|
/>
|
|
20078
20083
|
Arthur Dent
|
|
@@ -20135,6 +20140,7 @@ exports[`Storyshots Repositories/Annotate With Avatars 1`] = `
|
|
|
20135
20140
|
<img
|
|
20136
20141
|
alt="Tricia Marie McMillan"
|
|
20137
20142
|
className="has-rounded-border AuthorImage-sc-ygvjd8-0 dTapGF"
|
|
20143
|
+
crossOrigin="anonymous"
|
|
20138
20144
|
src="https://robohash.org/trillian@hitchhiker.com.png"
|
|
20139
20145
|
/>
|
|
20140
20146
|
Tricia Marie McMillan
|
|
@@ -20197,6 +20203,7 @@ exports[`Storyshots Repositories/Annotate With Avatars 1`] = `
|
|
|
20197
20203
|
<img
|
|
20198
20204
|
alt="Arthur Dent"
|
|
20199
20205
|
className="has-rounded-border AuthorImage-sc-ygvjd8-0 dTapGF"
|
|
20206
|
+
crossOrigin="anonymous"
|
|
20200
20207
|
src="https://robohash.org/arthur.dent@hitchhiker.com.png"
|
|
20201
20208
|
/>
|
|
20202
20209
|
Arthur Dent
|
|
@@ -20241,6 +20248,7 @@ exports[`Storyshots Repositories/Annotate With Avatars 1`] = `
|
|
|
20241
20248
|
<img
|
|
20242
20249
|
alt="Ford Prefect"
|
|
20243
20250
|
className="has-rounded-border AuthorImage-sc-ygvjd8-0 dTapGF"
|
|
20251
|
+
crossOrigin="anonymous"
|
|
20244
20252
|
src="https://robohash.org/ford.prefect@hitchhiker.com.png"
|
|
20245
20253
|
/>
|
|
20246
20254
|
Ford Prefect
|
|
@@ -20285,6 +20293,7 @@ exports[`Storyshots Repositories/Annotate With Avatars 1`] = `
|
|
|
20285
20293
|
<img
|
|
20286
20294
|
alt="Arthur Dent"
|
|
20287
20295
|
className="has-rounded-border AuthorImage-sc-ygvjd8-0 dTapGF"
|
|
20296
|
+
crossOrigin="anonymous"
|
|
20288
20297
|
src="https://robohash.org/arthur.dent@hitchhiker.com.png"
|
|
20289
20298
|
/>
|
|
20290
20299
|
Arthur Dent
|
|
@@ -20367,11 +20376,12 @@ exports[`Storyshots Repositories/Changesets Co-Authors with avatar 1`] = `
|
|
|
20367
20376
|
className="media-left mt-2 mr-2"
|
|
20368
20377
|
>
|
|
20369
20378
|
<div
|
|
20370
|
-
className="SingleChangeset__FixedSizedAvatar-sc-ytpqp9-0
|
|
20379
|
+
className="SingleChangeset__FixedSizedAvatar-sc-ytpqp9-0 gwbxYG image"
|
|
20371
20380
|
>
|
|
20372
20381
|
<img
|
|
20373
20382
|
alt="SCM Administrator"
|
|
20374
20383
|
className="has-rounded-border"
|
|
20384
|
+
crossOrigin="anonymous"
|
|
20375
20385
|
src="https://robohash.org/scm-admin@scm-manager.org"
|
|
20376
20386
|
/>
|
|
20377
20387
|
</div>
|
|
@@ -20425,6 +20435,7 @@ exports[`Storyshots Repositories/Changesets Co-Authors with avatar 1`] = `
|
|
|
20425
20435
|
<img
|
|
20426
20436
|
alt="Ford Prefect"
|
|
20427
20437
|
className="ContributorAvatar-sc-1yz8zn-0 lhgGHS"
|
|
20438
|
+
crossOrigin="anonymous"
|
|
20428
20439
|
src="https://robohash.org/ford.prefect@hitchhiker.com"
|
|
20429
20440
|
/>
|
|
20430
20441
|
</a>
|
|
@@ -20435,6 +20446,7 @@ exports[`Storyshots Repositories/Changesets Co-Authors with avatar 1`] = `
|
|
|
20435
20446
|
<img
|
|
20436
20447
|
alt="Zaphod Beeblebrox"
|
|
20437
20448
|
className="ContributorAvatar-sc-1yz8zn-0 lhgGHS"
|
|
20449
|
+
crossOrigin="anonymous"
|
|
20438
20450
|
src="https://robohash.org/zaphod.beeblebrox@hitchhiker.cm"
|
|
20439
20451
|
/>
|
|
20440
20452
|
</a>
|
|
@@ -20445,6 +20457,7 @@ exports[`Storyshots Repositories/Changesets Co-Authors with avatar 1`] = `
|
|
|
20445
20457
|
<img
|
|
20446
20458
|
alt="Tricia Marie McMillan"
|
|
20447
20459
|
className="ContributorAvatar-sc-1yz8zn-0 lhgGHS"
|
|
20460
|
+
crossOrigin="anonymous"
|
|
20448
20461
|
src="https://robohash.org/trillian@hitchhiker.cm"
|
|
20449
20462
|
/>
|
|
20450
20463
|
</a>
|
|
@@ -20541,11 +20554,12 @@ exports[`Storyshots Repositories/Changesets Commiter and Co-Authors with avatar
|
|
|
20541
20554
|
className="media-left mt-2 mr-2"
|
|
20542
20555
|
>
|
|
20543
20556
|
<div
|
|
20544
|
-
className="SingleChangeset__FixedSizedAvatar-sc-ytpqp9-0
|
|
20557
|
+
className="SingleChangeset__FixedSizedAvatar-sc-ytpqp9-0 gwbxYG image"
|
|
20545
20558
|
>
|
|
20546
20559
|
<img
|
|
20547
20560
|
alt="SCM Administrator"
|
|
20548
20561
|
className="has-rounded-border"
|
|
20562
|
+
crossOrigin="anonymous"
|
|
20549
20563
|
src="https://robohash.org/scm-admin@scm-manager.org"
|
|
20550
20564
|
/>
|
|
20551
20565
|
</div>
|
|
@@ -20594,6 +20608,7 @@ exports[`Storyshots Repositories/Changesets Commiter and Co-Authors with avatar
|
|
|
20594
20608
|
<img
|
|
20595
20609
|
alt="Zaphod Beeblebrox"
|
|
20596
20610
|
className="ContributorAvatar-sc-1yz8zn-0 lhgGHS"
|
|
20611
|
+
crossOrigin="anonymous"
|
|
20597
20612
|
src="https://robohash.org/zaphod.beeblebrox@hitchhiker.cm"
|
|
20598
20613
|
/>
|
|
20599
20614
|
</a>
|
|
@@ -20609,6 +20624,7 @@ exports[`Storyshots Repositories/Changesets Commiter and Co-Authors with avatar
|
|
|
20609
20624
|
<img
|
|
20610
20625
|
alt="Ford Prefect"
|
|
20611
20626
|
className="ContributorAvatar-sc-1yz8zn-0 lhgGHS"
|
|
20627
|
+
crossOrigin="anonymous"
|
|
20612
20628
|
src="https://robohash.org/ford.prefect@hitchhiker.com"
|
|
20613
20629
|
/>
|
|
20614
20630
|
</a>
|
|
@@ -21613,11 +21629,12 @@ exports[`Storyshots Repositories/Changesets With avatar 1`] = `
|
|
|
21613
21629
|
className="media-left mt-2 mr-2"
|
|
21614
21630
|
>
|
|
21615
21631
|
<div
|
|
21616
|
-
className="SingleChangeset__FixedSizedAvatar-sc-ytpqp9-0
|
|
21632
|
+
className="SingleChangeset__FixedSizedAvatar-sc-ytpqp9-0 gwbxYG image"
|
|
21617
21633
|
>
|
|
21618
21634
|
<img
|
|
21619
21635
|
alt="SCM Administrator"
|
|
21620
21636
|
className="has-rounded-border"
|
|
21637
|
+
crossOrigin="anonymous"
|
|
21621
21638
|
src="test-file-stub"
|
|
21622
21639
|
/>
|
|
21623
21640
|
</div>
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import React, { FC } from "react";
|
|
18
|
-
import Image from "
|
|
18
|
+
import { Image } from "@scm-manager/ui-core";
|
|
19
19
|
import { EXTENSION_POINT, Person } from "./Avatar";
|
|
20
20
|
import { useBinder } from "@scm-manager/ui-extensions";
|
|
21
21
|
|
|
@@ -36,7 +36,7 @@ const AvatarImage: FC<Props> = ({ person, representation = "rounded-border", cla
|
|
|
36
36
|
classes += " " + className;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
return <Image className={classes} src={avatar} alt={person.name} />;
|
|
39
|
+
return <Image className={classes} src={avatar} alt={person.name} crossOrigin="anonymous" />;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
return null;
|
package/src/layout/Footer.tsx
CHANGED
|
@@ -51,23 +51,19 @@ type TitleWithAvatarProps = {
|
|
|
51
51
|
};
|
|
52
52
|
|
|
53
53
|
const VCenteredAvatar = styled(AvatarImage)`
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const AvatarContainer = styled.span`
|
|
58
|
-
float: left;
|
|
54
|
+
width: 1rem !important;
|
|
55
|
+
height: 1rem !important;
|
|
59
56
|
margin-right: 0.3em;
|
|
60
57
|
padding-top: 0.2em;
|
|
61
|
-
|
|
62
|
-
height: 1em;
|
|
58
|
+
border-radius: 100%;
|
|
63
59
|
`;
|
|
64
60
|
|
|
65
61
|
const TitleWithAvatar: FC<TitleWithAvatarProps> = ({ me }) => (
|
|
66
|
-
<div {...createAttributesForTesting(me.displayName)}>
|
|
67
|
-
<
|
|
62
|
+
<div {...createAttributesForTesting(me.displayName)} className="is-flex">
|
|
63
|
+
<div>
|
|
68
64
|
<VCenteredAvatar person={me} representation="rounded" />
|
|
69
|
-
</
|
|
70
|
-
{me.displayName}
|
|
65
|
+
</div>
|
|
66
|
+
<div>{me.displayName}</div>
|
|
71
67
|
</div>
|
|
72
68
|
);
|
|
73
69
|
|
package/src/repos/DiffTypes.ts
CHANGED
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
* along with this program. If not, see https://www.gnu.org/licenses/.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { ReactNode } from "react";
|
|
17
|
+
import { FC, PropsWithChildren, ReactNode } from "react";
|
|
18
18
|
import { DefaultCollapsed } from "./defaultCollapsed";
|
|
19
|
-
import { Change, Hunk, FileDiff as File } from "@scm-manager/ui-types";
|
|
19
|
+
import { Change, Hunk, FileDiff as File, FileChangeType } from "@scm-manager/ui-types";
|
|
20
20
|
|
|
21
21
|
export type ChangeEvent = {
|
|
22
22
|
change: Change;
|
|
@@ -31,6 +31,20 @@ export type AnnotationFactoryContext = BaseContext;
|
|
|
31
31
|
|
|
32
32
|
export type FileAnnotationFactory = (file: File) => ReactNode[];
|
|
33
33
|
|
|
34
|
+
export type FileTreeNodeWrapper = FC<
|
|
35
|
+
PropsWithChildren & {
|
|
36
|
+
name: string;
|
|
37
|
+
path: string;
|
|
38
|
+
changeType?: FileChangeType;
|
|
39
|
+
iconName: string;
|
|
40
|
+
iconColor: string;
|
|
41
|
+
isFile: boolean;
|
|
42
|
+
originalIcon: ReactNode;
|
|
43
|
+
originalLabel: ReactNode;
|
|
44
|
+
isCurrentFile: boolean;
|
|
45
|
+
}
|
|
46
|
+
>;
|
|
47
|
+
|
|
34
48
|
// key = change id, value = react component
|
|
35
49
|
export type AnnotationFactory = (context: AnnotationFactoryContext) => {
|
|
36
50
|
[key: string]: any;
|
|
@@ -57,11 +57,11 @@ const ContributorWithAvatar: FC<PersonAvatarProps> = ({ person, avatar }) => {
|
|
|
57
57
|
if (person.mail) {
|
|
58
58
|
return (
|
|
59
59
|
<a href={"mailto:" + person.mail} title={t("changeset.contributors.mailto") + " " + person.mail}>
|
|
60
|
-
<ContributorAvatar src={avatar} alt={person.name} />
|
|
60
|
+
<ContributorAvatar src={avatar} alt={person.name} crossOrigin="anonymous" />
|
|
61
61
|
</a>
|
|
62
62
|
);
|
|
63
63
|
}
|
|
64
|
-
return <ContributorAvatar src={avatar} alt={person.name} title={person.name} />;
|
|
64
|
+
return <ContributorAvatar src={avatar} alt={person.name} title={person.name} crossOrigin="anonymous" />;
|
|
65
65
|
};
|
|
66
66
|
|
|
67
67
|
export const SingleContributor: FC<PersonProps> = ({ person, className, displayTextOnly }) => {
|
|
@@ -30,7 +30,7 @@ const Contributor: FC<{ person: Person }> = ({ person }) => {
|
|
|
30
30
|
if (avatar) {
|
|
31
31
|
prefix = (
|
|
32
32
|
<>
|
|
33
|
-
<ContributorAvatar src={avatar} alt={person.name} />{" "}
|
|
33
|
+
<ContributorAvatar src={avatar} alt={person.name} crossOrigin="anonymous" />{" "}
|
|
34
34
|
</>
|
|
35
35
|
);
|
|
36
36
|
}
|
|
@@ -18,12 +18,19 @@ import React, { FC } from "react";
|
|
|
18
18
|
import { Link } from "react-router-dom";
|
|
19
19
|
import { useTranslation } from "react-i18next";
|
|
20
20
|
import classNames from "classnames";
|
|
21
|
-
import { FileTree } from "@scm-manager/ui-types";
|
|
21
|
+
import { FileChangeType, FileTree } from "@scm-manager/ui-types";
|
|
22
22
|
import { FileDiffContent, StackedSpan, StyledIcon } from "./styledElements";
|
|
23
|
+
import { FileTreeNodeWrapper } from "../DiffTypes";
|
|
23
24
|
|
|
24
|
-
type Props = {
|
|
25
|
+
type Props = {
|
|
26
|
+
tree: FileTree;
|
|
27
|
+
currentFile: string;
|
|
28
|
+
setCurrentFile: (path: string) => void;
|
|
29
|
+
gap?: number;
|
|
30
|
+
FileTreeNodeWrapper?: FileTreeNodeWrapper;
|
|
31
|
+
};
|
|
25
32
|
|
|
26
|
-
const DiffFileTree: FC<Props> = ({ tree, currentFile, setCurrentFile, gap = 15 }) => {
|
|
33
|
+
const DiffFileTree: FC<Props> = ({ tree, currentFile, setCurrentFile, gap = 15, FileTreeNodeWrapper }) => {
|
|
27
34
|
return (
|
|
28
35
|
<FileDiffContent gap={gap}>
|
|
29
36
|
{Object.keys(tree.children).map((key) => (
|
|
@@ -33,6 +40,7 @@ const DiffFileTree: FC<Props> = ({ tree, currentFile, setCurrentFile, gap = 15 }
|
|
|
33
40
|
parentPath=""
|
|
34
41
|
currentFile={currentFile}
|
|
35
42
|
setCurrentFile={setCurrentFile}
|
|
43
|
+
FileTreeNodeWrapper={FileTreeNodeWrapper}
|
|
36
44
|
/>
|
|
37
45
|
))}
|
|
38
46
|
</FileDiffContent>
|
|
@@ -41,9 +49,13 @@ const DiffFileTree: FC<Props> = ({ tree, currentFile, setCurrentFile, gap = 15 }
|
|
|
41
49
|
|
|
42
50
|
export default DiffFileTree;
|
|
43
51
|
|
|
44
|
-
type
|
|
45
|
-
|
|
46
|
-
|
|
52
|
+
type NodeProps = {
|
|
53
|
+
node: FileTree;
|
|
54
|
+
parentPath: string;
|
|
55
|
+
currentFile: string;
|
|
56
|
+
setCurrentFile: (path: string) => void;
|
|
57
|
+
FileTreeNodeWrapper?: FileTreeNodeWrapper;
|
|
58
|
+
};
|
|
47
59
|
|
|
48
60
|
const addPath = (parentPath: string, path: string) => {
|
|
49
61
|
if ("" === parentPath) {
|
|
@@ -52,16 +64,31 @@ const addPath = (parentPath: string, path: string) => {
|
|
|
52
64
|
return parentPath + "/" + path;
|
|
53
65
|
};
|
|
54
66
|
|
|
55
|
-
const TreeNode: FC<NodeProps> = ({ node, parentPath, currentFile, setCurrentFile }) => {
|
|
67
|
+
const TreeNode: FC<NodeProps> = ({ node, parentPath, currentFile, setCurrentFile, FileTreeNodeWrapper }) => {
|
|
56
68
|
const [t] = useTranslation("repos");
|
|
57
69
|
|
|
70
|
+
FileTreeNodeWrapper = FileTreeNodeWrapper || (({ children }) => <>{children}</>);
|
|
71
|
+
|
|
72
|
+
const label = <div className="ml-1">{node.nodeName}</div>;
|
|
73
|
+
const icon = <StyledIcon alt={t("diff.showContent")}>folder</StyledIcon>;
|
|
58
74
|
return (
|
|
59
75
|
<li>
|
|
60
76
|
{Object.keys(node.children).length > 0 ? (
|
|
61
77
|
<ul className="py-1 pl-3">
|
|
62
78
|
<li className="is-flex has-text-grey">
|
|
63
|
-
<
|
|
64
|
-
|
|
79
|
+
<FileTreeNodeWrapper
|
|
80
|
+
path={addPath(parentPath, node.nodeName)}
|
|
81
|
+
isFile={false}
|
|
82
|
+
isCurrentFile={false}
|
|
83
|
+
name={node.nodeName}
|
|
84
|
+
iconName={"folder"}
|
|
85
|
+
iconColor={"grey"}
|
|
86
|
+
originalIcon={icon}
|
|
87
|
+
originalLabel={label}
|
|
88
|
+
>
|
|
89
|
+
{icon}
|
|
90
|
+
{label}
|
|
91
|
+
</FileTreeNodeWrapper>
|
|
65
92
|
</li>
|
|
66
93
|
{Object.keys(node.children).map((key) => (
|
|
67
94
|
<TreeNode
|
|
@@ -70,23 +97,25 @@ const TreeNode: FC<NodeProps> = ({ node, parentPath, currentFile, setCurrentFile
|
|
|
70
97
|
parentPath={addPath(parentPath, node.nodeName)}
|
|
71
98
|
currentFile={currentFile}
|
|
72
99
|
setCurrentFile={setCurrentFile}
|
|
100
|
+
FileTreeNodeWrapper={FileTreeNodeWrapper}
|
|
73
101
|
/>
|
|
74
102
|
))}
|
|
75
103
|
</ul>
|
|
76
104
|
) : (
|
|
77
105
|
<TreeFile
|
|
78
|
-
changeType={node.changeType.toLowerCase() as
|
|
106
|
+
changeType={node.changeType.toLowerCase() as FileChangeType}
|
|
79
107
|
path={node.nodeName}
|
|
80
108
|
parentPath={parentPath}
|
|
81
109
|
currentFile={currentFile}
|
|
82
110
|
setCurrentFile={setCurrentFile}
|
|
111
|
+
FileTreeNodeWrapper={FileTreeNodeWrapper}
|
|
83
112
|
/>
|
|
84
113
|
)}
|
|
85
114
|
</li>
|
|
86
115
|
);
|
|
87
116
|
};
|
|
88
117
|
|
|
89
|
-
const getColor = (changeType:
|
|
118
|
+
const getColor = (changeType: FileChangeType) => {
|
|
90
119
|
switch (changeType) {
|
|
91
120
|
case "add":
|
|
92
121
|
return "success";
|
|
@@ -99,7 +128,7 @@ const getColor = (changeType: ChangeType) => {
|
|
|
99
128
|
}
|
|
100
129
|
};
|
|
101
130
|
|
|
102
|
-
const getIcon = (changeType:
|
|
131
|
+
const getIcon = (changeType: FileChangeType) => {
|
|
103
132
|
switch (changeType) {
|
|
104
133
|
case "add":
|
|
105
134
|
case "copy":
|
|
@@ -113,14 +142,22 @@ const getIcon = (changeType: ChangeType) => {
|
|
|
113
142
|
};
|
|
114
143
|
|
|
115
144
|
type FileProps = {
|
|
116
|
-
changeType:
|
|
145
|
+
changeType: FileChangeType;
|
|
117
146
|
path: string;
|
|
118
147
|
parentPath: string;
|
|
119
148
|
currentFile: string;
|
|
120
149
|
setCurrentFile: (path: string) => void;
|
|
150
|
+
FileTreeNodeWrapper: FileTreeNodeWrapper;
|
|
121
151
|
};
|
|
122
152
|
|
|
123
|
-
const TreeFile: FC<FileProps> = ({
|
|
153
|
+
const TreeFile: FC<FileProps> = ({
|
|
154
|
+
changeType,
|
|
155
|
+
path,
|
|
156
|
+
parentPath,
|
|
157
|
+
currentFile,
|
|
158
|
+
setCurrentFile,
|
|
159
|
+
FileTreeNodeWrapper,
|
|
160
|
+
}) => {
|
|
124
161
|
const [t] = useTranslation("repos");
|
|
125
162
|
const completePath = addPath(parentPath, path);
|
|
126
163
|
|
|
@@ -128,35 +165,50 @@ const TreeFile: FC<FileProps> = ({ changeType, path, parentPath, currentFile, se
|
|
|
128
165
|
return currentFile === completePath;
|
|
129
166
|
};
|
|
130
167
|
|
|
168
|
+
const iconName = getIcon(changeType);
|
|
169
|
+
|
|
170
|
+
const icon = (
|
|
171
|
+
<StackedSpan className="fa-stack">
|
|
172
|
+
<StyledIcon
|
|
173
|
+
className={classNames("fa-stack-2x", `has-text-${getColor(changeType)}`)}
|
|
174
|
+
key={completePath + "file"}
|
|
175
|
+
type="fas"
|
|
176
|
+
alt={t("diff.showContent")}
|
|
177
|
+
>
|
|
178
|
+
file
|
|
179
|
+
</StyledIcon>
|
|
180
|
+
<StyledIcon
|
|
181
|
+
className={classNames("fa-stack-1x", "is-relative", "has-text-secondary-least")}
|
|
182
|
+
issmaller={iconName === "circle" ? "true" : "false"}
|
|
183
|
+
key={changeType}
|
|
184
|
+
alt={t(`diff.changes.${changeType}`)}
|
|
185
|
+
>
|
|
186
|
+
{iconName}
|
|
187
|
+
</StyledIcon>
|
|
188
|
+
</StackedSpan>
|
|
189
|
+
);
|
|
190
|
+
const label = <div className={classNames("ml-1", isCurrentFile() ? "has-text-weight-bold" : "")}>{path}</div>;
|
|
191
|
+
|
|
131
192
|
return (
|
|
132
193
|
<Link
|
|
133
194
|
className="is-flex py-1 pl-3 has-cursor-pointer"
|
|
134
195
|
onClick={() => setCurrentFile(completePath)}
|
|
135
196
|
to={`#diff-${encodeURIComponent(completePath)}`}
|
|
136
197
|
>
|
|
137
|
-
<
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
)}
|
|
152
|
-
issmaller={getIcon(changeType) === "circle" ? "true" : "false"}
|
|
153
|
-
key={changeType}
|
|
154
|
-
alt={t(`diff.changes.${changeType}`)}
|
|
155
|
-
>
|
|
156
|
-
{getIcon(changeType)}
|
|
157
|
-
</StyledIcon>
|
|
158
|
-
</StackedSpan>
|
|
159
|
-
<div className="ml-1">{path}</div>
|
|
198
|
+
<FileTreeNodeWrapper
|
|
199
|
+
name={path}
|
|
200
|
+
path={completePath}
|
|
201
|
+
changeType={changeType}
|
|
202
|
+
isFile={true}
|
|
203
|
+
iconName={iconName}
|
|
204
|
+
iconColor={getColor(changeType)}
|
|
205
|
+
originalIcon={icon}
|
|
206
|
+
originalLabel={label}
|
|
207
|
+
isCurrentFile={isCurrentFile()}
|
|
208
|
+
>
|
|
209
|
+
{icon}
|
|
210
|
+
{label}
|
|
211
|
+
</FileTreeNodeWrapper>
|
|
160
212
|
</Link>
|
|
161
213
|
);
|
|
162
214
|
};
|