mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-11 16:05:44 +01:00
Merge branch 'feature/user_converter' of github.com:scm-manager/scm-manager into feature/user_converter
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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 (
|
||||
|
||||
Reference in New Issue
Block a user