mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-08 22:45:45 +01:00
Fix review findings
This commit is contained in:
@@ -22,12 +22,14 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { FC } from "react";
|
import { FC, ReactNode, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
import FullscreenModal from "../modals/FullscreenModal";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onClick?: () => void;
|
modalTitle: string;
|
||||||
|
modalBody: ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Button = styled.a`
|
const Button = styled.a`
|
||||||
@@ -37,13 +39,22 @@ const Button = styled.a`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const OpenInFullscreenButton: FC<Props> = ({ onClick }) => {
|
const OpenInFullscreenButton: FC<Props> = ({ modalTitle, modalBody }) => {
|
||||||
const [t] = useTranslation("repos");
|
const [t] = useTranslation("repos");
|
||||||
|
const [showModal, setShowModal] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button title={t("diff.fullscreen.open")} className="button" onClick={onClick}>
|
<>
|
||||||
|
<Button title={t("diff.fullscreen.open")} className="button" onClick={() => setShowModal(true)}>
|
||||||
<i className="fas fa-search-plus" />
|
<i className="fas fa-search-plus" />
|
||||||
</Button>
|
</Button>
|
||||||
|
<FullscreenModal
|
||||||
|
title={modalTitle}
|
||||||
|
closeFunction={() => setShowModal(false)}
|
||||||
|
body={modalBody}
|
||||||
|
active={showModal}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import Icon from "../Icon";
|
|||||||
import { Change, ChangeEvent, DiffObjectProps, File, Hunk as HunkType } from "./DiffTypes";
|
import { Change, ChangeEvent, DiffObjectProps, File, Hunk as HunkType } from "./DiffTypes";
|
||||||
import TokenizedDiffView from "./TokenizedDiffView";
|
import TokenizedDiffView from "./TokenizedDiffView";
|
||||||
import DiffButton from "./DiffButton";
|
import DiffButton from "./DiffButton";
|
||||||
import { MenuContext, OpenInFullscreenButton, FullscreenModal } from "@scm-manager/ui-components";
|
import { MenuContext, OpenInFullscreenButton } from "@scm-manager/ui-components";
|
||||||
import DiffExpander, { ExpandableHunk } from "./DiffExpander";
|
import DiffExpander, { ExpandableHunk } from "./DiffExpander";
|
||||||
import HunkExpandLink from "./HunkExpandLink";
|
import HunkExpandLink from "./HunkExpandLink";
|
||||||
import { Modal } from "../modals";
|
import { Modal } from "../modals";
|
||||||
@@ -57,7 +57,6 @@ type State = Collapsible & {
|
|||||||
sideBySide?: boolean;
|
sideBySide?: boolean;
|
||||||
diffExpander: DiffExpander;
|
diffExpander: DiffExpander;
|
||||||
expansionError?: any;
|
expansionError?: any;
|
||||||
showFullscreenModal: boolean;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const DiffFilePanel = styled.div`
|
const DiffFilePanel = styled.div`
|
||||||
@@ -108,8 +107,7 @@ class DiffFile extends React.Component<Props, State> {
|
|||||||
collapsed: this.defaultCollapse(),
|
collapsed: this.defaultCollapse(),
|
||||||
sideBySide: props.sideBySide,
|
sideBySide: props.sideBySide,
|
||||||
diffExpander: new DiffExpander(props.file),
|
diffExpander: new DiffExpander(props.file),
|
||||||
file: props.file,
|
file: props.file
|
||||||
showFullscreenModal: false
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,18 +148,6 @@ class DiffFile extends React.Component<Props, State> {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
openModal = () => {
|
|
||||||
this.setState({
|
|
||||||
showFullscreenModal: true
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
closeModal = () => {
|
|
||||||
this.setState({
|
|
||||||
showFullscreenModal: false
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
setCollapse = (collapsed: boolean) => {
|
setCollapse = (collapsed: boolean) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
collapsed
|
collapsed
|
||||||
@@ -421,7 +407,7 @@ class DiffFile extends React.Component<Props, State> {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { fileControlFactory, fileAnnotationFactory, t } = this.props;
|
const { fileControlFactory, fileAnnotationFactory, t } = this.props;
|
||||||
const { file, collapsed, sideBySide, diffExpander, expansionError, showFullscreenModal } = this.state;
|
const { file, collapsed, sideBySide, diffExpander, expansionError } = this.state;
|
||||||
const viewType = sideBySide ? "split" : "unified";
|
const viewType = sideBySide ? "split" : "unified";
|
||||||
|
|
||||||
let body = null;
|
let body = null;
|
||||||
@@ -444,7 +430,12 @@ class DiffFile extends React.Component<Props, State> {
|
|||||||
}
|
}
|
||||||
const collapseIcon = this.hasContent(file) ? <Icon name={icon} color="inherit" /> : null;
|
const collapseIcon = this.hasContent(file) ? <Icon name={icon} color="inherit" /> : null;
|
||||||
const fileControls = fileControlFactory ? fileControlFactory(file, this.setCollapse) : null;
|
const fileControls = fileControlFactory ? fileControlFactory(file, this.setCollapse) : null;
|
||||||
const openInFullscreen = file?.hunks?.length ? <OpenInFullscreenButton onClick={this.openModal} /> : null;
|
const openInFullscreen = file?.hunks?.length ? (
|
||||||
|
<OpenInFullscreenButton
|
||||||
|
modalTitle={file.type === "delete" ? file.oldPath : file.newPath}
|
||||||
|
modalBody={<MarginlessModalContent>{body}</MarginlessModalContent>}
|
||||||
|
/>
|
||||||
|
) : null;
|
||||||
const sideBySideToggle = file?.hunks?.length && (
|
const sideBySideToggle = file?.hunks?.length && (
|
||||||
<MenuContext.Consumer>
|
<MenuContext.Consumer>
|
||||||
{({ setCollapsed }) => (
|
{({ setCollapsed }) => (
|
||||||
@@ -484,18 +475,6 @@ class DiffFile extends React.Component<Props, State> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let modalContent;
|
|
||||||
if (file?.hunks?.length) {
|
|
||||||
modalContent = (
|
|
||||||
<FullscreenModal
|
|
||||||
title={file.type === "delete" ? file.oldPath : file.newPath}
|
|
||||||
closeFunction={() => this.closeModal()}
|
|
||||||
body={<MarginlessModalContent>{body}</MarginlessModalContent>}
|
|
||||||
active={showFullscreenModal}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DiffFilePanel
|
<DiffFilePanel
|
||||||
className={classNames("panel", "is-size-6")}
|
className={classNames("panel", "is-size-6")}
|
||||||
@@ -520,7 +499,6 @@ class DiffFile extends React.Component<Props, State> {
|
|||||||
</FlexWrapLevel>
|
</FlexWrapLevel>
|
||||||
</div>
|
</div>
|
||||||
{body}
|
{body}
|
||||||
{modalContent}
|
|
||||||
</DiffFilePanel>
|
</DiffFilePanel>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,32 +37,25 @@ const SourcecodeViewer: FC<Props> = ({ file, language }) => {
|
|||||||
const [currentFileRevision, setCurrentFileRevision] = useState("");
|
const [currentFileRevision, setCurrentFileRevision] = useState("");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function fetchContent() {
|
if (file.revision !== currentFileRevision) {
|
||||||
getContent((file._links.self as Link).href)
|
getContent((file._links.self as Link).href)
|
||||||
.then(content => {
|
.then(content => {
|
||||||
setLoading(false);
|
|
||||||
setContent(content);
|
setContent(content);
|
||||||
setCurrentFileRevision(file.revision);
|
setCurrentFileRevision(file.revision);
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setError(error);
|
})
|
||||||
});
|
.catch(setError);
|
||||||
}
|
|
||||||
|
|
||||||
if (file.revision !== currentFileRevision) {
|
|
||||||
fetchContent();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (loading) {
|
|
||||||
return <Loading />;
|
|
||||||
}
|
}
|
||||||
|
}, [currentFileRevision, file]);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return <ErrorNotification error={error} />;
|
return <ErrorNotification error={error} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return <Loading />;
|
||||||
|
}
|
||||||
|
|
||||||
if (!content) {
|
if (!content) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,21 +21,14 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
import React from "react";
|
import React, { ReactNode } from "react";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { WithTranslation, withTranslation } from "react-i18next";
|
import { WithTranslation, withTranslation } from "react-i18next";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { ExtensionPoint } from "@scm-manager/ui-extensions";
|
import { ExtensionPoint } from "@scm-manager/ui-extensions";
|
||||||
import { File, Repository } from "@scm-manager/ui-types";
|
import { File, Repository } from "@scm-manager/ui-types";
|
||||||
import {
|
import { DateFromNow, ErrorNotification, FileSize, Icon, OpenInFullscreenButton } from "@scm-manager/ui-components";
|
||||||
DateFromNow,
|
|
||||||
ErrorNotification,
|
|
||||||
FileSize,
|
|
||||||
Icon,
|
|
||||||
OpenInFullscreenButton,
|
|
||||||
FullscreenModal
|
|
||||||
} from "@scm-manager/ui-components";
|
|
||||||
import { getSources } from "../modules/sources";
|
import { getSources } from "../modules/sources";
|
||||||
import FileButtonAddons from "../components/content/FileButtonAddons";
|
import FileButtonAddons from "../components/content/FileButtonAddons";
|
||||||
import SourcesView from "./SourcesView";
|
import SourcesView from "./SourcesView";
|
||||||
@@ -55,7 +48,6 @@ type State = {
|
|||||||
collapsed: boolean;
|
collapsed: boolean;
|
||||||
selected: SourceViewSelection;
|
selected: SourceViewSelection;
|
||||||
errorFromExtension?: Error;
|
errorFromExtension?: Error;
|
||||||
showFullscreenModal: boolean;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const Header = styled.div`
|
const Header = styled.div`
|
||||||
@@ -104,8 +96,7 @@ class Content extends React.Component<Props, State> {
|
|||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
collapsed: true,
|
collapsed: true,
|
||||||
selected: "source",
|
selected: "source"
|
||||||
showFullscreenModal: false
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,25 +106,13 @@ class Content extends React.Component<Props, State> {
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
openModal = () => {
|
|
||||||
this.setState({
|
|
||||||
showFullscreenModal: true
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
closeModal = () => {
|
|
||||||
this.setState({
|
|
||||||
showFullscreenModal: false
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
handleExtensionError = (error: Error) => {
|
handleExtensionError = (error: Error) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
errorFromExtension: error
|
errorFromExtension: error
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
showHeader() {
|
showHeader(content: ReactNode) {
|
||||||
const { repository, file, revision } = this.props;
|
const { repository, file, revision } = this.props;
|
||||||
const { selected, collapsed } = this.state;
|
const { selected, collapsed } = this.state;
|
||||||
const icon = collapsed ? "angle-right" : "angle-down";
|
const icon = collapsed ? "angle-right" : "angle-down";
|
||||||
@@ -156,7 +135,10 @@ class Content extends React.Component<Props, State> {
|
|||||||
</div>
|
</div>
|
||||||
<div className="buttons is-grouped">
|
<div className="buttons is-grouped">
|
||||||
{selector}
|
{selector}
|
||||||
<OpenInFullscreenButton onClick={this.openModal} />
|
<OpenInFullscreenButton
|
||||||
|
modalTitle={file?.name}
|
||||||
|
modalBody={<BorderLessDiv className="panel">{content}</BorderLessDiv>}
|
||||||
|
/>
|
||||||
<ExtensionPoint
|
<ExtensionPoint
|
||||||
name="repos.sources.content.actionbar"
|
name="repos.sources.content.actionbar"
|
||||||
props={{
|
props={{
|
||||||
@@ -237,9 +219,8 @@ class Content extends React.Component<Props, State> {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { file, revision, repository, path, breadcrumb } = this.props;
|
const { file, revision, repository, path, breadcrumb } = this.props;
|
||||||
const { selected, errorFromExtension, showFullscreenModal } = this.state;
|
const { selected, errorFromExtension } = this.state;
|
||||||
|
|
||||||
const header = this.showHeader();
|
|
||||||
let content;
|
let content;
|
||||||
switch (selected) {
|
switch (selected) {
|
||||||
case "source":
|
case "source":
|
||||||
@@ -251,6 +232,7 @@ class Content extends React.Component<Props, State> {
|
|||||||
case "annotations":
|
case "annotations":
|
||||||
content = <AnnotateView file={file} repository={repository} />;
|
content = <AnnotateView file={file} repository={repository} />;
|
||||||
}
|
}
|
||||||
|
const header = this.showHeader(content);
|
||||||
const moreInformation = this.showMoreInformation();
|
const moreInformation = this.showMoreInformation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -260,12 +242,6 @@ class Content extends React.Component<Props, State> {
|
|||||||
<Header>{header}</Header>
|
<Header>{header}</Header>
|
||||||
{moreInformation}
|
{moreInformation}
|
||||||
{content}
|
{content}
|
||||||
<FullscreenModal
|
|
||||||
title={file?.name}
|
|
||||||
closeFunction={() => this.closeModal()}
|
|
||||||
body={<BorderLessDiv className="panel">{content}</BorderLessDiv>}
|
|
||||||
active={showFullscreenModal}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
{errorFromExtension && <ErrorNotification error={errorFromExtension} />}
|
{errorFromExtension && <ErrorNotification error={errorFromExtension} />}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user