@scm-manager/ui-components 2.27.3 → 2.27.5-20211121-150210
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 +7 -8
- package/src/Autocomplete.tsx +7 -6
- package/src/BranchSelector.tsx +2 -2
- package/src/Breadcrumb.tsx +1 -0
- package/src/CardColumnGroup.tsx +6 -6
- package/src/DangerZone.tsx +1 -0
- package/src/DateFromNow.tsx +2 -1
- package/src/DateShort.tsx +2 -1
- package/src/ErrorBoundary.tsx +2 -2
- package/src/Icon.tsx +4 -4
- package/src/Logo.stories.tsx +1 -0
- package/src/OverviewPageActions.tsx +2 -2
- package/src/SmallLoadingSpinner.stories.tsx +32 -0
- package/src/SmallLoadingSpinner.tsx +34 -0
- package/src/SplitAndReplace.tsx +3 -2
- package/src/SyntaxHighlighter.stories.tsx +1 -1
- package/src/Tooltip.tsx +1 -1
- package/src/__resources__/SearchHit.ts +97 -0
- package/src/__snapshots__/storyshots.test.ts.snap +1340 -2086
- package/src/buttons/Button.tsx +33 -34
- package/src/forms/FileInput.tsx +1 -1
- package/src/forms/FileUpload.tsx +1 -1
- package/src/forms/FilterInput.tsx +1 -0
- package/src/forms/InputField.tsx +2 -2
- package/src/forms/Select.tsx +4 -4
- package/src/forms/TriStateCheckbox.tsx +2 -2
- package/src/index.ts +4 -3
- package/src/languages.test.ts +1 -5
- package/src/languages.ts +1 -10
- package/src/layout/Footer.tsx +1 -1
- package/src/layout/Header.tsx +2 -2
- package/src/layout/SubSubtitle.tsx +41 -0
- package/src/layout/index.ts +2 -1
- package/src/modals/FullscreenModal.tsx +1 -1
- package/src/modals/Modal.tsx +6 -6
- package/src/navigation/RoutingProps.ts +3 -1
- package/src/navigation/SecondaryNavigation.stories.tsx +3 -3
- package/src/navigation/SecondaryNavigation.tsx +1 -1
- package/src/popover/Popover.tsx +7 -7
- package/src/repos/DiffFile.tsx +21 -15
- package/src/repos/HealthCheckFailureDetail.tsx +2 -2
- package/src/repos/RepositoryEntry.tsx +9 -6
- package/src/repos/RepositoryFlags.tsx +2 -2
- package/src/repos/TokenizedDiffView.tsx +20 -2
- package/src/repos/annotate/Annotate.stories.tsx +1 -1
- package/src/repos/annotate/Annotate.tsx +2 -2
- package/src/repos/annotate/AnnotateLine.tsx +1 -0
- package/src/repos/annotate/{Popover.tsx → AnnotatePopover.tsx} +2 -2
- package/src/repos/index.ts +2 -0
- package/src/repos/refractorAdapter.ts +11 -6
- package/src/search/HighlightedFragment.tsx +7 -4
- package/src/search/SyntaxHighlightedFragment.tsx +130 -0
- package/src/search/TextHitField.stories.tsx +69 -0
- package/src/search/TextHitField.tsx +58 -19
- package/src/styleConstants.ts +2 -1
- package/src/syntax-highlighting.module.css +1 -1
package/src/buttons/Button.tsx
CHANGED
|
@@ -61,32 +61,43 @@ const Button: FC<Props> = ({
|
|
|
61
61
|
loading,
|
|
62
62
|
disabled,
|
|
63
63
|
action,
|
|
64
|
-
color = "default"
|
|
64
|
+
color = "default"
|
|
65
65
|
}) => {
|
|
66
66
|
const renderIcon = () => {
|
|
67
67
|
return <>{icon ? <Icon name={icon} color="inherit" className="is-medium pr-1" /> : null}</>;
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
+
const classes = classNames(
|
|
71
|
+
"button",
|
|
72
|
+
"is-" + color,
|
|
73
|
+
{ "is-loading": loading },
|
|
74
|
+
{ "is-fullwidth": fullWidth },
|
|
75
|
+
{ "is-reduced-mobile": reducedMobile },
|
|
76
|
+
className
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
const content = (
|
|
80
|
+
<>
|
|
81
|
+
{renderIcon()}{" "}
|
|
82
|
+
{(label || children) && (
|
|
83
|
+
<>
|
|
84
|
+
{label} {children}
|
|
85
|
+
</>
|
|
86
|
+
)}
|
|
87
|
+
</>
|
|
88
|
+
);
|
|
89
|
+
|
|
70
90
|
if (link && !disabled) {
|
|
91
|
+
if (link.includes("://")) {
|
|
92
|
+
return (
|
|
93
|
+
<a className={classes} href={link} aria-label={label}>
|
|
94
|
+
{content}
|
|
95
|
+
</a>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
71
98
|
return (
|
|
72
|
-
<Link
|
|
73
|
-
|
|
74
|
-
"button",
|
|
75
|
-
"is-" + color,
|
|
76
|
-
{ "is-loading": loading },
|
|
77
|
-
{ "is-fullwidth": fullWidth },
|
|
78
|
-
{ "is-reduced-mobile": reducedMobile },
|
|
79
|
-
className
|
|
80
|
-
)}
|
|
81
|
-
to={link}
|
|
82
|
-
aria-label={label}
|
|
83
|
-
>
|
|
84
|
-
{renderIcon()}{" "}
|
|
85
|
-
{(label || children) && (
|
|
86
|
-
<>
|
|
87
|
-
{label} {children}
|
|
88
|
-
</>
|
|
89
|
-
)}
|
|
99
|
+
<Link className={classes} to={link} aria-label={label}>
|
|
100
|
+
{content}
|
|
90
101
|
</Link>
|
|
91
102
|
);
|
|
92
103
|
}
|
|
@@ -96,23 +107,11 @@ const Button: FC<Props> = ({
|
|
|
96
107
|
type={type}
|
|
97
108
|
title={title}
|
|
98
109
|
disabled={disabled}
|
|
99
|
-
onClick={
|
|
100
|
-
className={
|
|
101
|
-
"button",
|
|
102
|
-
"is-" + color,
|
|
103
|
-
{ "is-loading": loading },
|
|
104
|
-
{ "is-fullwidth": fullWidth },
|
|
105
|
-
{ "is-reduced-mobile": reducedMobile },
|
|
106
|
-
className
|
|
107
|
-
)}
|
|
110
|
+
onClick={event => action && action(event)}
|
|
111
|
+
className={classes}
|
|
108
112
|
{...createAttributesForTesting(testId)}
|
|
109
113
|
>
|
|
110
|
-
{
|
|
111
|
-
{(label || children) && (
|
|
112
|
-
<>
|
|
113
|
-
{label} {children}
|
|
114
|
-
</>
|
|
115
|
-
)}
|
|
114
|
+
{content}
|
|
116
115
|
</button>
|
|
117
116
|
);
|
|
118
117
|
};
|
package/src/forms/FileInput.tsx
CHANGED
|
@@ -102,7 +102,7 @@ const FileInput: FC<Props> = ({
|
|
|
102
102
|
{file?.name ? (
|
|
103
103
|
<span className="file-name">{file?.name}</span>
|
|
104
104
|
) : (
|
|
105
|
-
<span className="file-name has-text-weight-light has-text-
|
|
105
|
+
<span className="file-name has-text-weight-light has-text-secondary">
|
|
106
106
|
{filenamePlaceholder || t("fileInput.noFileChosen")}
|
|
107
107
|
</span>
|
|
108
108
|
)}
|
package/src/forms/FileUpload.tsx
CHANGED
|
@@ -60,7 +60,7 @@ const FileUpload: FC<Props> = ({ handleFile, filenamePlaceholder = "", disabled
|
|
|
60
60
|
{file?.name ? (
|
|
61
61
|
<span className="file-name">{file?.name}</span>
|
|
62
62
|
) : (
|
|
63
|
-
<span className="file-name has-text-weight-light has-text-
|
|
63
|
+
<span className="file-name has-text-weight-light has-text-secondary">{filenamePlaceholder}</span>
|
|
64
64
|
)}
|
|
65
65
|
</label>
|
|
66
66
|
</div>
|
|
@@ -77,6 +77,7 @@ const FilterInput: FC<Props> = ({ filter, value, testId, placeholder, autoFocus,
|
|
|
77
77
|
onChange={event => setStateValue(event.target.value)}
|
|
78
78
|
autoFocus={autoFocus || false}
|
|
79
79
|
aria-describedby={id}
|
|
80
|
+
aria-label={t("filterEntries")}
|
|
80
81
|
{...createAttributesForTesting(testId)}
|
|
81
82
|
/>
|
|
82
83
|
<span className="icon is-small is-left">
|
package/src/forms/InputField.tsx
CHANGED
|
@@ -33,7 +33,7 @@ type BaseProps = {
|
|
|
33
33
|
label?: string;
|
|
34
34
|
name?: string;
|
|
35
35
|
placeholder?: string;
|
|
36
|
-
value?: string;
|
|
36
|
+
value?: string | number;
|
|
37
37
|
type?: string;
|
|
38
38
|
autofocus?: boolean;
|
|
39
39
|
onReturnPressed?: () => void;
|
|
@@ -44,7 +44,7 @@ type BaseProps = {
|
|
|
44
44
|
helpText?: string;
|
|
45
45
|
className?: string;
|
|
46
46
|
testId?: string;
|
|
47
|
-
defaultValue?: string;
|
|
47
|
+
defaultValue?: string | number;
|
|
48
48
|
readOnly?: boolean;
|
|
49
49
|
};
|
|
50
50
|
|
package/src/forms/Select.tsx
CHANGED
|
@@ -69,7 +69,7 @@ const InnerSelect: FC<FieldProps<BaseProps, HTMLSelectElement, string>> = ({
|
|
|
69
69
|
const field = useInnerRef(props.innerRef);
|
|
70
70
|
|
|
71
71
|
let opts = options;
|
|
72
|
-
if (value && addValueToOptions && !options.some(
|
|
72
|
+
if (value && addValueToOptions && !options.some(o => o.value === value)) {
|
|
73
73
|
opts = [{ label: value, value }, ...options];
|
|
74
74
|
}
|
|
75
75
|
|
|
@@ -124,11 +124,11 @@ const InnerSelect: FC<FieldProps<BaseProps, HTMLSelectElement, string>> = ({
|
|
|
124
124
|
onChange={handleInput}
|
|
125
125
|
onBlur={handleBlur}
|
|
126
126
|
disabled={disabled}
|
|
127
|
-
aria-labelledby={a11yId}
|
|
128
|
-
aria-describedby={helpId}
|
|
127
|
+
aria-labelledby={label ? a11yId : undefined}
|
|
128
|
+
aria-describedby={helpText ? helpId : undefined}
|
|
129
129
|
{...createAttributesForTesting(testId)}
|
|
130
130
|
>
|
|
131
|
-
{opts.map(
|
|
131
|
+
{opts.map(opt => {
|
|
132
132
|
return (
|
|
133
133
|
<option value={opt.value} key={"KEY_" + opt.value}>
|
|
134
134
|
{opt.label}
|
|
@@ -51,11 +51,11 @@ const TriStateCheckbox: FC<Props> = ({ checked, indeterminate, disabled, label,
|
|
|
51
51
|
|
|
52
52
|
let color;
|
|
53
53
|
if (disabled) {
|
|
54
|
-
color = "
|
|
54
|
+
color = "secondary";
|
|
55
55
|
} else if (checked || indeterminate) {
|
|
56
56
|
color = "link";
|
|
57
57
|
} else {
|
|
58
|
-
color = "
|
|
58
|
+
color = "secondary-most";
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
// We need a tabIndex to make the checkbox accessible from keyboard.
|
package/src/index.ts
CHANGED
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
DiffEventHandler,
|
|
38
38
|
File,
|
|
39
39
|
FileChangeType,
|
|
40
|
-
Hunk
|
|
40
|
+
Hunk
|
|
41
41
|
} from "./repos";
|
|
42
42
|
|
|
43
43
|
export { validation, repositories };
|
|
@@ -51,6 +51,7 @@ export { default as ErrorPage } from "./ErrorPage";
|
|
|
51
51
|
export { default as Icon } from "./Icon";
|
|
52
52
|
export { default as Image } from "./Image";
|
|
53
53
|
export { default as Loading } from "./Loading";
|
|
54
|
+
export { default as SmallLoadingSpinner } from "./SmallLoadingSpinner";
|
|
54
55
|
export { default as Logo } from "./Logo";
|
|
55
56
|
export { default as MailLink } from "./MailLink";
|
|
56
57
|
export { default as Notification } from "./Notification";
|
|
@@ -113,7 +114,7 @@ export {
|
|
|
113
114
|
AnnotationFactory,
|
|
114
115
|
AnnotationFactoryContext,
|
|
115
116
|
DiffEventHandler,
|
|
116
|
-
DiffEventContext
|
|
117
|
+
DiffEventContext
|
|
117
118
|
};
|
|
118
119
|
|
|
119
120
|
// Re-export from ui-api
|
|
@@ -130,7 +131,7 @@ export {
|
|
|
130
131
|
MissingLinkError,
|
|
131
132
|
createBackendError,
|
|
132
133
|
isBackendError,
|
|
133
|
-
TOKEN_EXPIRED_ERROR_CODE
|
|
134
|
+
TOKEN_EXPIRED_ERROR_CODE
|
|
134
135
|
} from "@scm-manager/ui-api";
|
|
135
136
|
|
|
136
137
|
export { urls };
|
package/src/languages.test.ts
CHANGED
|
@@ -35,7 +35,7 @@ describe("syntax highlighter", () => {
|
|
|
35
35
|
expect(java).toBe("java");
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
-
it("should return text if language is
|
|
38
|
+
it("should return text if language is undefined", () => {
|
|
39
39
|
const lang = determineLanguage();
|
|
40
40
|
expect(lang).toBe("text");
|
|
41
41
|
});
|
|
@@ -45,8 +45,4 @@ describe("syntax highlighter", () => {
|
|
|
45
45
|
expect(lang).toBe("text");
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
-
it("should use alias go for golang", () => {
|
|
49
|
-
const go = determineLanguage("golang");
|
|
50
|
-
expect(go).toBe("go");
|
|
51
|
-
});
|
|
52
48
|
});
|
package/src/languages.ts
CHANGED
|
@@ -22,20 +22,11 @@
|
|
|
22
22
|
* SOFTWARE.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
// this aliases are only to map from spotter detection to prismjs
|
|
26
|
-
const languageAliases: { [key: string]: string } = {
|
|
27
|
-
golang: "go",
|
|
28
|
-
};
|
|
29
|
-
|
|
30
25
|
export const defaultLanguage = "text";
|
|
31
26
|
|
|
32
27
|
export const determineLanguage = (language?: string) => {
|
|
33
28
|
if (!language) {
|
|
34
29
|
return defaultLanguage;
|
|
35
30
|
}
|
|
36
|
-
|
|
37
|
-
if (languageAliases[lang]) {
|
|
38
|
-
return languageAliases[lang];
|
|
39
|
-
}
|
|
40
|
-
return lang;
|
|
31
|
+
return language.toLowerCase();
|
|
41
32
|
};
|
package/src/layout/Footer.tsx
CHANGED
|
@@ -97,7 +97,7 @@ const Footer: FC<Props> = ({ me, version, links }) => {
|
|
|
97
97
|
<div className="columns is-size-7">
|
|
98
98
|
{me ? (
|
|
99
99
|
<FooterSection title={meSectionTile}>
|
|
100
|
-
<NavLink to="/me" label={t("footer.user.profile")} testId="footer-user-profile" />
|
|
100
|
+
<NavLink to="/me/settings/theme" label={t("footer.user.profile")} testId="footer-user-profile" />
|
|
101
101
|
{me?._links?.password && (
|
|
102
102
|
<NavLink to="/me/settings/password" label={t("profile.changePasswordNavLink")} />
|
|
103
103
|
)}
|
package/src/layout/Header.tsx
CHANGED
|
@@ -37,7 +37,7 @@ const SmallHeader: FC<{ children: ReactNode }> = ({ children }) => {
|
|
|
37
37
|
|
|
38
38
|
const LargeHeader: FC = () => {
|
|
39
39
|
return (
|
|
40
|
-
<
|
|
40
|
+
<div className="hero has-scm-background is-small">
|
|
41
41
|
<div className="hero-body">
|
|
42
42
|
<div className="container">
|
|
43
43
|
<div className="columns is-vcentered">
|
|
@@ -47,7 +47,7 @@ const LargeHeader: FC = () => {
|
|
|
47
47
|
</div>
|
|
48
48
|
</div>
|
|
49
49
|
</div>
|
|
50
|
-
</
|
|
50
|
+
</div>
|
|
51
51
|
);
|
|
52
52
|
};
|
|
53
53
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* MIT License
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
|
5
|
+
*
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
* in the Software without restriction, including without limitation the rights
|
|
9
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
* furnished to do so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
* SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
import React from "react";
|
|
25
|
+
import classNames from "classnames";
|
|
26
|
+
|
|
27
|
+
type Props = {
|
|
28
|
+
className?: string;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
class SubSubtitle extends React.Component<Props> {
|
|
32
|
+
render() {
|
|
33
|
+
const { className, children } = this.props;
|
|
34
|
+
if (children) {
|
|
35
|
+
return <h3 className={classNames("is-size-5", className)}>{children}</h3>;
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default SubSubtitle;
|
package/src/layout/index.ts
CHANGED
|
@@ -29,8 +29,9 @@ export { default as Header } from "./Header";
|
|
|
29
29
|
export { default as Level } from "./Level";
|
|
30
30
|
export { default as Page } from "./Page";
|
|
31
31
|
export { default as PageActions } from "./PageActions";
|
|
32
|
-
export { default as Subtitle } from "./Subtitle";
|
|
33
32
|
export { default as Title } from "./Title";
|
|
33
|
+
export { default as Subtitle } from "./Subtitle";
|
|
34
|
+
export { default as SubSubtitle } from "./SubSubtitle";
|
|
34
35
|
export { default as CustomQueryFlexWrappedColumns } from "./CustomQueryFlexWrappedColumns";
|
|
35
36
|
export { default as PrimaryContentColumn } from "./PrimaryContentColumn";
|
|
36
37
|
export { default as SecondaryNavigationColumn } from "./SecondaryNavigationColumn";
|
|
@@ -45,7 +45,7 @@ const FullSizedModal = styled(Modal)`
|
|
|
45
45
|
|
|
46
46
|
const FullscreenModal: FC<Props> = ({ title, closeFunction, body, active, closeButtonLabel }) => {
|
|
47
47
|
const [t] = useTranslation("repos");
|
|
48
|
-
const footer = <Button label={closeButtonLabel || t("diff.fullscreen.close")} action={closeFunction} color="
|
|
48
|
+
const footer = <Button label={closeButtonLabel || t("diff.fullscreen.close")} action={closeFunction} color="secondary" />;
|
|
49
49
|
|
|
50
50
|
return <FullSizedModal title={title} closeFunction={closeFunction} body={body} footer={footer} active={active} />;
|
|
51
51
|
};
|
package/src/modals/Modal.tsx
CHANGED
|
@@ -45,7 +45,7 @@ type Props = {
|
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
const SizedModal = styled.div<{ size?: ModalSize }>`
|
|
48
|
-
width: ${
|
|
48
|
+
width: ${props => (props.size ? `${modalSizes[props.size]}%` : "640px")};
|
|
49
49
|
`;
|
|
50
50
|
|
|
51
51
|
export const Modal: FC<Props> = ({
|
|
@@ -55,9 +55,9 @@ export const Modal: FC<Props> = ({
|
|
|
55
55
|
footer,
|
|
56
56
|
active,
|
|
57
57
|
className,
|
|
58
|
-
headColor = "
|
|
59
|
-
headTextColor = "
|
|
60
|
-
size
|
|
58
|
+
headColor = "secondary-less",
|
|
59
|
+
headTextColor = "secondary-most",
|
|
60
|
+
size
|
|
61
61
|
}) => {
|
|
62
62
|
const portalRootElement = usePortalRootElement("modalsRoot");
|
|
63
63
|
const initialFocusRef = useRef(null);
|
|
@@ -65,7 +65,7 @@ export const Modal: FC<Props> = ({
|
|
|
65
65
|
includeContainer: true,
|
|
66
66
|
initialFocus: initialFocusRef.current,
|
|
67
67
|
returnFocus: true,
|
|
68
|
-
updateNodes: false
|
|
68
|
+
updateNodes: false
|
|
69
69
|
});
|
|
70
70
|
|
|
71
71
|
if (!portalRootElement) {
|
|
@@ -90,7 +90,7 @@ export const Modal: FC<Props> = ({
|
|
|
90
90
|
<div className="modal-background" onClick={closeFunction} />
|
|
91
91
|
<SizedModal className="modal-card" size={size}>
|
|
92
92
|
<header className={classNames("modal-card-head", `has-background-${headColor}`)}>
|
|
93
|
-
<
|
|
93
|
+
<h2 className={`modal-card-title m-0 has-text-${headTextColor}`}>{title}</h2>
|
|
94
94
|
<button className="delete" aria-label="close" onClick={closeFunction} ref={initialFocusRef} autoFocus />
|
|
95
95
|
</header>
|
|
96
96
|
<section className="modal-card-body">{body}</section>
|
|
@@ -22,8 +22,10 @@
|
|
|
22
22
|
* SOFTWARE.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
+
import { RouteProps } from "react-router-dom";
|
|
26
|
+
|
|
25
27
|
export type RoutingProps = {
|
|
26
28
|
to: string;
|
|
27
29
|
activeOnlyWhenExact?: boolean;
|
|
28
|
-
activeWhenMatch?: (route:
|
|
30
|
+
activeWhenMatch?: (route: RouteProps) => boolean;
|
|
29
31
|
};
|
|
@@ -53,8 +53,8 @@ const withRoute = (route: string) => {
|
|
|
53
53
|
};
|
|
54
54
|
|
|
55
55
|
storiesOf("Secondary Navigation", module)
|
|
56
|
-
.addDecorator(
|
|
57
|
-
.addDecorator(
|
|
56
|
+
.addDecorator(story => <StateMenuContextProvider>{story()}</StateMenuContextProvider>)
|
|
57
|
+
.addDecorator(story => (
|
|
58
58
|
<Columns className="columns">
|
|
59
59
|
<div className="column is-3">{story()}</div>
|
|
60
60
|
</Columns>
|
|
@@ -92,7 +92,7 @@ storiesOf("Secondary Navigation", module)
|
|
|
92
92
|
<SecondaryNavigation label="Hitchhiker">
|
|
93
93
|
<SecondaryNavigationItem to="/42" icon="fas fa-puzzle-piece" label="Puzzle 42" title="Puzzle 42" />
|
|
94
94
|
<SecondaryNavigationItem
|
|
95
|
-
activeWhenMatch={
|
|
95
|
+
activeWhenMatch={route => route.location?.pathname === "/hog"}
|
|
96
96
|
to="/heart-of-gold"
|
|
97
97
|
icon="fas fa-star"
|
|
98
98
|
label="Heart Of Gold"
|
|
@@ -91,7 +91,7 @@ const SecondaryNavigation: FC<Props> = ({ label, children, collapsible = true })
|
|
|
91
91
|
aria-label={menuAriaLabel}
|
|
92
92
|
>
|
|
93
93
|
{collapsible ? (
|
|
94
|
-
<Icon
|
|
94
|
+
<Icon className="is-medium" collapsed={isCollapsed}>
|
|
95
95
|
{arrowIcon}
|
|
96
96
|
</Icon>
|
|
97
97
|
) : null}
|
package/src/popover/Popover.tsx
CHANGED
|
@@ -43,7 +43,7 @@ type ContainerProps = {
|
|
|
43
43
|
const PopoverContainer = styled.div<ContainerProps>`
|
|
44
44
|
position: absolute;
|
|
45
45
|
z-index: 100;
|
|
46
|
-
width: ${
|
|
46
|
+
width: ${props => props.width}px;
|
|
47
47
|
display: block;
|
|
48
48
|
|
|
49
49
|
&:before {
|
|
@@ -54,7 +54,7 @@ const PopoverContainer = styled.div<ContainerProps>`
|
|
|
54
54
|
height: 0;
|
|
55
55
|
width: 0;
|
|
56
56
|
top: 100%;
|
|
57
|
-
left: ${
|
|
57
|
+
left: ${props => props.width / 2}px;
|
|
58
58
|
border-color: transparent;
|
|
59
59
|
border-bottom-color: white;
|
|
60
60
|
border-left-color: white;
|
|
@@ -71,7 +71,7 @@ const PopoverHeading = styled.div`
|
|
|
71
71
|
height: 1.5em;
|
|
72
72
|
`;
|
|
73
73
|
|
|
74
|
-
const Popover: FC<Props> =
|
|
74
|
+
const Popover: FC<Props> = props => {
|
|
75
75
|
if (!props.show) {
|
|
76
76
|
return null;
|
|
77
77
|
}
|
|
@@ -89,13 +89,13 @@ const InnerPopover: FC<Props> = ({ title, show, width, offsetTop, offsetLeft, di
|
|
|
89
89
|
|
|
90
90
|
const onMouseEnter = () => {
|
|
91
91
|
dispatch({
|
|
92
|
-
type: "enter-popover"
|
|
92
|
+
type: "enter-popover"
|
|
93
93
|
});
|
|
94
94
|
};
|
|
95
95
|
|
|
96
96
|
const onMouseLeave = () => {
|
|
97
97
|
dispatch({
|
|
98
|
-
type: "leave-popover"
|
|
98
|
+
type: "leave-popover"
|
|
99
99
|
});
|
|
100
100
|
};
|
|
101
101
|
|
|
@@ -105,7 +105,7 @@ const InnerPopover: FC<Props> = ({ title, show, width, offsetTop, offsetLeft, di
|
|
|
105
105
|
<PopoverContainer
|
|
106
106
|
onMouseEnter={onMouseEnter}
|
|
107
107
|
onMouseLeave={onMouseLeave}
|
|
108
|
-
className="box"
|
|
108
|
+
className="box popover"
|
|
109
109
|
style={{ top: `${top}px`, left: `${left}px` }}
|
|
110
110
|
width={width!}
|
|
111
111
|
ref={ref}
|
|
@@ -118,7 +118,7 @@ const InnerPopover: FC<Props> = ({ title, show, width, offsetTop, offsetLeft, di
|
|
|
118
118
|
};
|
|
119
119
|
|
|
120
120
|
Popover.defaultProps = {
|
|
121
|
-
width: 120
|
|
121
|
+
width: 120
|
|
122
122
|
};
|
|
123
123
|
|
|
124
124
|
export default Popover;
|
package/src/repos/DiffFile.tsx
CHANGED
|
@@ -81,7 +81,7 @@ const MarginlessModalContent = styled.div`
|
|
|
81
81
|
class DiffFile extends React.Component<Props, State> {
|
|
82
82
|
static defaultProps: Partial<Props> = {
|
|
83
83
|
defaultCollapse: false,
|
|
84
|
-
markConflicts: true
|
|
84
|
+
markConflicts: true
|
|
85
85
|
};
|
|
86
86
|
|
|
87
87
|
constructor(props: Props) {
|
|
@@ -90,14 +90,14 @@ class DiffFile extends React.Component<Props, State> {
|
|
|
90
90
|
collapsed: this.defaultCollapse(),
|
|
91
91
|
sideBySide: props.sideBySide,
|
|
92
92
|
diffExpander: new DiffExpander(props.file),
|
|
93
|
-
file: props.file
|
|
93
|
+
file: props.file
|
|
94
94
|
};
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
componentDidUpdate(prevProps: Readonly<Props>) {
|
|
98
98
|
if (!this.props.isCollapsed && this.props.defaultCollapse !== prevProps.defaultCollapse) {
|
|
99
99
|
this.setState({
|
|
100
|
-
collapsed: this.defaultCollapse()
|
|
100
|
+
collapsed: this.defaultCollapse()
|
|
101
101
|
});
|
|
102
102
|
}
|
|
103
103
|
}
|
|
@@ -120,8 +120,8 @@ class DiffFile extends React.Component<Props, State> {
|
|
|
120
120
|
if (onCollapseStateChange) {
|
|
121
121
|
onCollapseStateChange(file);
|
|
122
122
|
} else {
|
|
123
|
-
this.setState(
|
|
124
|
-
collapsed: !state.collapsed
|
|
123
|
+
this.setState(state => ({
|
|
124
|
+
collapsed: !state.collapsed
|
|
125
125
|
}));
|
|
126
126
|
}
|
|
127
127
|
}
|
|
@@ -129,8 +129,8 @@ class DiffFile extends React.Component<Props, State> {
|
|
|
129
129
|
|
|
130
130
|
toggleSideBySide = (callback: () => void) => {
|
|
131
131
|
this.setState(
|
|
132
|
-
|
|
133
|
-
sideBySide: !state.sideBySide
|
|
132
|
+
state => ({
|
|
133
|
+
sideBySide: !state.sideBySide
|
|
134
134
|
}),
|
|
135
135
|
() => callback()
|
|
136
136
|
);
|
|
@@ -142,7 +142,7 @@ class DiffFile extends React.Component<Props, State> {
|
|
|
142
142
|
onCollapseStateChange(this.state.file, collapsed);
|
|
143
143
|
} else {
|
|
144
144
|
this.setState({
|
|
145
|
-
collapsed
|
|
145
|
+
collapsed
|
|
146
146
|
});
|
|
147
147
|
}
|
|
148
148
|
};
|
|
@@ -236,13 +236,19 @@ class DiffFile extends React.Component<Props, State> {
|
|
|
236
236
|
|
|
237
237
|
expandHead = (expandableHunk: ExpandableHunk, count: number) => {
|
|
238
238
|
return () => {
|
|
239
|
-
return expandableHunk
|
|
239
|
+
return expandableHunk
|
|
240
|
+
.expandHead(count)
|
|
241
|
+
.then(this.diffExpanded)
|
|
242
|
+
.catch(this.diffExpansionFailed);
|
|
240
243
|
};
|
|
241
244
|
};
|
|
242
245
|
|
|
243
246
|
expandBottom = (expandableHunk: ExpandableHunk, count: number) => {
|
|
244
247
|
return () => {
|
|
245
|
-
return expandableHunk
|
|
248
|
+
return expandableHunk
|
|
249
|
+
.expandBottom(count)
|
|
250
|
+
.then(this.diffExpanded)
|
|
251
|
+
.catch(this.diffExpansionFailed);
|
|
246
252
|
};
|
|
247
253
|
};
|
|
248
254
|
|
|
@@ -260,7 +266,7 @@ class DiffFile extends React.Component<Props, State> {
|
|
|
260
266
|
if (annotationFactory) {
|
|
261
267
|
return annotationFactory({
|
|
262
268
|
hunk,
|
|
263
|
-
file
|
|
269
|
+
file
|
|
264
270
|
});
|
|
265
271
|
} else {
|
|
266
272
|
return EMPTY_ANNOTATION_FACTORY;
|
|
@@ -274,7 +280,7 @@ class DiffFile extends React.Component<Props, State> {
|
|
|
274
280
|
changeId: getChangeKey(change),
|
|
275
281
|
change,
|
|
276
282
|
hunk,
|
|
277
|
-
file
|
|
283
|
+
file
|
|
278
284
|
};
|
|
279
285
|
if (onClick) {
|
|
280
286
|
onClick(context);
|
|
@@ -287,7 +293,7 @@ class DiffFile extends React.Component<Props, State> {
|
|
|
287
293
|
return {
|
|
288
294
|
onClick: (event: ChangeEvent) => {
|
|
289
295
|
this.handleClickEvent(event.change, hunk);
|
|
290
|
-
}
|
|
296
|
+
}
|
|
291
297
|
};
|
|
292
298
|
}
|
|
293
299
|
};
|
|
@@ -496,9 +502,9 @@ class DiffFile extends React.Component<Props, State> {
|
|
|
496
502
|
title={this.hoverFileTitle(file)}
|
|
497
503
|
>
|
|
498
504
|
{collapseIcon}
|
|
499
|
-
<
|
|
505
|
+
<h4 className={classNames("has-text-weight-bold", "is-ellipsis-overflow", "is-size-6", "ml-1")}>
|
|
500
506
|
{this.renderFileTitle(file)}
|
|
501
|
-
</
|
|
507
|
+
</h4>
|
|
502
508
|
{this.renderChangeTag(file)}
|
|
503
509
|
</FullWidthTitleHeader>
|
|
504
510
|
{headerButtons}
|
|
@@ -38,7 +38,7 @@ type Props = {
|
|
|
38
38
|
const HealthCheckFailureDetail: FC<Props> = ({ active, closeFunction, failures }) => {
|
|
39
39
|
const [t] = useTranslation("repos");
|
|
40
40
|
|
|
41
|
-
const footer = <Button label={t("healthCheckFailure.close")} action={closeFunction} color="
|
|
41
|
+
const footer = <Button label={t("healthCheckFailure.close")} action={closeFunction} color="secondary" />;
|
|
42
42
|
|
|
43
43
|
return (
|
|
44
44
|
<Modal
|
|
@@ -52,7 +52,7 @@ const HealthCheckFailureDetail: FC<Props> = ({ active, closeFunction, failures }
|
|
|
52
52
|
active={active}
|
|
53
53
|
footer={footer}
|
|
54
54
|
headColor={"danger"}
|
|
55
|
-
headTextColor=
|
|
55
|
+
headTextColor="secondary-least"
|
|
56
56
|
/>
|
|
57
57
|
);
|
|
58
58
|
};
|
|
@@ -49,9 +49,6 @@ const ContentRightContainer = styled.div`
|
|
|
49
49
|
|
|
50
50
|
const QuickAction = styled(Icon)`
|
|
51
51
|
margin-top: 0.2rem;
|
|
52
|
-
:hover {
|
|
53
|
-
color: #363636 !important;
|
|
54
|
-
}
|
|
55
52
|
`;
|
|
56
53
|
|
|
57
54
|
const ContactAvatar = styled.img`
|
|
@@ -79,9 +76,15 @@ const RepositoryEntry: FC<Props> = ({ repository, baseDate }) => {
|
|
|
79
76
|
|
|
80
77
|
const renderContactIcon = () => {
|
|
81
78
|
if (avatarFactory) {
|
|
82
|
-
return
|
|
79
|
+
return (
|
|
80
|
+
<ContactAvatar
|
|
81
|
+
className="has-rounded-border"
|
|
82
|
+
src={avatarFactory({ mail: repository.contact })}
|
|
83
|
+
alt={repository.contact}
|
|
84
|
+
/>
|
|
85
|
+
);
|
|
83
86
|
}
|
|
84
|
-
return <QuickAction className={classNames("is-clickable")} name="envelope" color="info" />;
|
|
87
|
+
return <QuickAction className={classNames("is-clickable", "has-hover-visible")} name="envelope" color="info" />;
|
|
85
88
|
};
|
|
86
89
|
|
|
87
90
|
const createContentRight = () => (
|
|
@@ -124,7 +127,7 @@ const RepositoryEntry: FC<Props> = ({ repository, baseDate }) => {
|
|
|
124
127
|
</ContactActionWrapper>
|
|
125
128
|
) : null}
|
|
126
129
|
<QuickAction
|
|
127
|
-
className={classNames("is-clickable", "is-size-5")}
|
|
130
|
+
className={classNames("is-clickable", "is-size-5", "has-hover-visible")}
|
|
128
131
|
name="download"
|
|
129
132
|
color="info"
|
|
130
133
|
onClick={() => setOpenCloneModal(true)}
|