Merge branch 'develop' into feature/syntax-highlighting

This commit is contained in:
Konstantin Schaper
2020-10-21 14:14:25 +02:00
committed by GitHub
16 changed files with 1437 additions and 128 deletions

View File

@@ -21,87 +21,47 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import React from "react";
import { WithTranslation, withTranslation } from "react-i18next";
import React, { FC, useEffect, useState } from "react";
import { apiClient, ErrorNotification, Loading, SyntaxHighlighter } from "@scm-manager/ui-components";
import { File, Link } from "@scm-manager/ui-types";
type Props = WithTranslation & {
type Props = {
file: File;
language: string;
};
type State = {
content: string;
error?: Error;
loaded: boolean;
currentFileRevision: string;
};
const SourcecodeViewer: FC<Props> = ({ file, language }) => {
const [content, setContent] = useState("");
const [error, setError] = useState<Error | undefined>(undefined);
const [loading, setLoading] = useState(true);
const [currentFileRevision, setCurrentFileRevision] = useState("");
class SourcecodeViewer extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
content: "",
loaded: false,
currentFileRevision: ""
};
}
componentDidMount() {
this.fetchContentIfChanged();
}
componentDidUpdate() {
this.fetchContentIfChanged();
}
private fetchContentIfChanged() {
const { file } = this.props;
const { currentFileRevision } = this.state;
useEffect(() => {
if (file.revision !== currentFileRevision) {
this.fetchContent();
getContent((file._links.self as Link).href)
.then(content => {
setContent(content);
setCurrentFileRevision(file.revision);
setLoading(false);
})
.catch(setError);
}
}, [currentFileRevision, file]);
if (error) {
return <ErrorNotification error={error} />;
}
fetchContent = () => {
const { file } = this.props;
getContent((file._links.self as Link).href)
.then(content => {
this.setState({
content,
loaded: true,
currentFileRevision: file.revision
});
})
.catch(error => {
this.setState({
error,
loaded: true
});
});
};
render() {
const { content, error, loaded } = this.state;
const language = this.props.language;
if (error) {
return <ErrorNotification error={error} />;
}
if (!loaded) {
return <Loading />;
}
if (!content) {
return null;
}
return <SyntaxHighlighter language={getLanguage(language)} value={content} />;
if (loading) {
return <Loading />;
}
}
if (!content) {
return null;
}
return <SyntaxHighlighter language={getLanguage(language)} value={content} />;
};
export function getLanguage(language: string) {
return language.toLowerCase();
@@ -111,4 +71,4 @@ export function getContent(url: string) {
return apiClient.get(url).then(response => response.text());
}
export default withTranslation("repos")(SourcecodeViewer);
export default SourcecodeViewer;

View File

@@ -21,14 +21,14 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import React from "react";
import React, { ReactNode } from "react";
import { connect } from "react-redux";
import { WithTranslation, withTranslation } from "react-i18next";
import classNames from "classnames";
import styled from "styled-components";
import { ExtensionPoint } from "@scm-manager/ui-extensions";
import { File, Repository } from "@scm-manager/ui-types";
import { DateFromNow, ErrorNotification, FileSize, Icon } from "@scm-manager/ui-components";
import { DateFromNow, ErrorNotification, FileSize, Icon, OpenInFullscreenButton } from "@scm-manager/ui-components";
import { getSources } from "../modules/sources";
import FileButtonAddons from "../components/content/FileButtonAddons";
import SourcesView from "./SourcesView";
@@ -82,6 +82,12 @@ const LighterGreyBackgroundTable = styled.table`
background-color: #fbfbfb;
`;
const BorderLessDiv = styled.div`
margin: -1.25rem;
border: none;
box-shadow: none;
`;
export type SourceViewSelection = "source" | "history" | "annotations";
class Content extends React.Component<Props, State> {
@@ -106,7 +112,7 @@ class Content extends React.Component<Props, State> {
});
};
showHeader() {
showHeader(content: ReactNode) {
const { repository, file, revision } = this.props;
const { selected, collapsed } = this.state;
const icon = collapsed ? "angle-right" : "angle-down";
@@ -129,6 +135,11 @@ class Content extends React.Component<Props, State> {
</div>
<div className="buttons is-grouped">
{selector}
<OpenInFullscreenButton
modalTitle={file?.name}
modalBody={<BorderLessDiv className="panel">{content}</BorderLessDiv>}
tooltipStyle="htmlTitle"
/>
<ExtensionPoint
name="repos.sources.content.actionbar"
props={{
@@ -211,24 +222,18 @@ class Content extends React.Component<Props, State> {
const { file, revision, repository, path, breadcrumb } = this.props;
const { selected, errorFromExtension } = this.state;
const header = this.showHeader();
let content;
switch (selected) {
case "source":
content = (
<SourcesView revision={revision} file={file} repository={repository} path={path}/>
);
content = <SourcesView revision={revision} file={file} repository={repository} path={path} />;
break;
case "history":
content = (
<HistoryView file={file} repository={repository}/>
);
content = <HistoryView file={file} repository={repository} />;
break;
case "annotations":
content = (
<AnnotateView file={file} repository={repository} />
);
content = <AnnotateView file={file} repository={repository} />;
}
const header = this.showHeader(content);
const moreInformation = this.showMoreInformation();
return (