mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-15 17:56:17 +01:00
Merged in feature/ui-repoContent (pull request #96)
Feature/ui repoContent
This commit is contained in:
@@ -48,6 +48,14 @@ class ApiClient {
|
|||||||
return this.httpRequestWithJSONBody("PUT", url, contentType, payload);
|
return this.httpRequestWithJSONBody("PUT", url, contentType, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
head(url: string) {
|
||||||
|
let options: RequestOptions = {
|
||||||
|
method: "HEAD"
|
||||||
|
};
|
||||||
|
options = Object.assign(options, fetchOptions);
|
||||||
|
return fetch(createUrl(url), options).then(handleStatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
delete(url: string): Promise<Response> {
|
delete(url: string): Promise<Response> {
|
||||||
let options: RequestOptions = {
|
let options: RequestOptions = {
|
||||||
method: "DELETE"
|
method: "DELETE"
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
//@flow
|
||||||
|
import React from "react";
|
||||||
|
import Button, { type ButtonProps } from "./Button";
|
||||||
|
import type {File} from "@scm-manager/ui-types";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
displayName: string,
|
||||||
|
url: string
|
||||||
|
};
|
||||||
|
|
||||||
|
class DownloadButton extends React.Component<Props> {
|
||||||
|
render() {
|
||||||
|
const {displayName, url} = this.props;
|
||||||
|
return (
|
||||||
|
<a className="button is-large is-info" href={url}>
|
||||||
|
<span className="icon is-medium">
|
||||||
|
<i className="fas fa-arrow-circle-down" />
|
||||||
|
</span>
|
||||||
|
<span>{displayName}</span>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DownloadButton;
|
||||||
@@ -7,4 +7,4 @@ export { default as DeleteButton } from "./DeleteButton.js";
|
|||||||
export { default as EditButton } from "./EditButton.js";
|
export { default as EditButton } from "./EditButton.js";
|
||||||
export { default as RemoveEntryOfTableButton } from "./RemoveEntryOfTableButton.js";
|
export { default as RemoveEntryOfTableButton } from "./RemoveEntryOfTableButton.js";
|
||||||
export { default as SubmitButton } from "./SubmitButton.js";
|
export { default as SubmitButton } from "./SubmitButton.js";
|
||||||
|
export {default as DownloadButton} from "./DownloadButton.js";
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
"react-redux": "^5.0.7",
|
"react-redux": "^5.0.7",
|
||||||
"react-router-dom": "^4.3.1",
|
"react-router-dom": "^4.3.1",
|
||||||
"react-router-redux": "^5.0.0-alpha.9",
|
"react-router-redux": "^5.0.0-alpha.9",
|
||||||
|
"react-syntax-highlighter": "^9.0.1",
|
||||||
"redux": "^4.0.0",
|
"redux": "^4.0.0",
|
||||||
"redux-devtools-extension": "^2.13.5",
|
"redux-devtools-extension": "^2.13.5",
|
||||||
"redux-logger": "^3.0.6",
|
"redux-logger": "^3.0.6",
|
||||||
|
|||||||
@@ -51,7 +51,11 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"length": "Length",
|
"length": "Length",
|
||||||
"lastModified": "Last modified",
|
"lastModified": "Last modified",
|
||||||
"description": "Description"
|
"description": "Description",
|
||||||
|
"branch": "Branch"
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"downloadButton": "Download"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"changesets": {
|
"changesets": {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import {
|
|||||||
modifyConfigReset
|
modifyConfigReset
|
||||||
} from "../modules/config";
|
} from "../modules/config";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import type { Config, Link } from "@scm-manager/ui-types";
|
import type { Config } from "@scm-manager/ui-types";
|
||||||
import ConfigForm from "../components/form/ConfigForm";
|
import ConfigForm from "../components/form/ConfigForm";
|
||||||
import { getConfigLink } from "../../modules/indexResource";
|
import { getConfigLink } from "../../modules/indexResource";
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import reducer, {
|
|||||||
getConfig,
|
getConfig,
|
||||||
getConfigUpdatePermission
|
getConfigUpdatePermission
|
||||||
} from "./config";
|
} from "./config";
|
||||||
import { getConfigLink } from "../../modules/indexResource";
|
|
||||||
|
|
||||||
const CONFIG_URL = "/config";
|
const CONFIG_URL = "/config";
|
||||||
const URL = "/api/v2" + CONFIG_URL;
|
const URL = "/api/v2" + CONFIG_URL;
|
||||||
|
|||||||
@@ -19,9 +19,8 @@ import {
|
|||||||
Footer,
|
Footer,
|
||||||
Header
|
Header
|
||||||
} from "@scm-manager/ui-components";
|
} from "@scm-manager/ui-components";
|
||||||
import type { Me, Link } from "@scm-manager/ui-types";
|
import type { Me } from "@scm-manager/ui-types";
|
||||||
import {
|
import {
|
||||||
fetchIndexResources,
|
|
||||||
getConfigLink,
|
getConfigLink,
|
||||||
getFetchIndexResourcesFailure,
|
getFetchIndexResourcesFailure,
|
||||||
getGroupsLink,
|
getGroupsLink,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
getLogoutFailure
|
getLogoutFailure
|
||||||
} from "../modules/auth";
|
} from "../modules/auth";
|
||||||
import { Loading, ErrorPage } from "@scm-manager/ui-components";
|
import { Loading, ErrorPage } from "@scm-manager/ui-components";
|
||||||
import { fetchIndexResources, getLogoutLink } from "../modules/indexResource";
|
import { getLogoutLink } from "../modules/indexResource";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
authenticated: boolean,
|
authenticated: boolean,
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ import {
|
|||||||
createGroup,
|
createGroup,
|
||||||
isCreateGroupPending,
|
isCreateGroupPending,
|
||||||
getCreateGroupFailure,
|
getCreateGroupFailure,
|
||||||
createGroupReset,
|
createGroupReset
|
||||||
getCreateGroupLink
|
|
||||||
} from "../modules/groups";
|
} from "../modules/groups";
|
||||||
import type { Group } from "@scm-manager/ui-types";
|
import type { Group } from "@scm-manager/ui-types";
|
||||||
import type { History } from "history";
|
import type { History } from "history";
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import type { BrowserHistory } from "history/createBrowserHistory";
|
|||||||
|
|
||||||
import createReduxStore from "./createReduxStore";
|
import createReduxStore from "./createReduxStore";
|
||||||
import { ConnectedRouter } from "react-router-redux";
|
import { ConnectedRouter } from "react-router-redux";
|
||||||
import PluginLoader from "./containers/PluginLoader";
|
|
||||||
|
|
||||||
import { urls } from "@scm-manager/ui-components";
|
import { urls } from "@scm-manager/ui-components";
|
||||||
|
|
||||||
@@ -37,7 +36,7 @@ ReactDOM.render(
|
|||||||
<I18nextProvider i18n={i18n}>
|
<I18nextProvider i18n={i18n}>
|
||||||
{/* ConnectedRouter will use the store from Provider automatically */}
|
{/* ConnectedRouter will use the store from Provider automatically */}
|
||||||
<ConnectedRouter history={history}>
|
<ConnectedRouter history={history}>
|
||||||
<Index />
|
<Index />
|
||||||
</ConnectedRouter>
|
</ConnectedRouter>
|
||||||
</I18nextProvider>
|
</I18nextProvider>
|
||||||
</Provider>,
|
</Provider>,
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import { isPending } from "./pending";
|
|||||||
import { getFailure } from "./failure";
|
import { getFailure } from "./failure";
|
||||||
import {
|
import {
|
||||||
callFetchIndexResources,
|
callFetchIndexResources,
|
||||||
FETCH_INDEXRESOURCES_SUCCESS,
|
fetchIndexResources,
|
||||||
fetchIndexResources, fetchIndexResourcesPending,
|
fetchIndexResourcesPending,
|
||||||
fetchIndexResourcesSuccess
|
fetchIndexResourcesSuccess
|
||||||
} from "./indexResource";
|
} from "./indexResource";
|
||||||
|
|
||||||
@@ -156,7 +156,7 @@ export const login = (
|
|||||||
return apiClient
|
return apiClient
|
||||||
.post(loginLink, login_data)
|
.post(loginLink, login_data)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
dispatch(fetchIndexResourcesPending())
|
dispatch(fetchIndexResourcesPending());
|
||||||
return callFetchIndexResources();
|
return callFetchIndexResources();
|
||||||
})
|
})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import FileTreeLeaf from "./FileTreeLeaf";
|
|||||||
import type { Repository, File } from "@scm-manager/ui-types";
|
import type { Repository, File } from "@scm-manager/ui-types";
|
||||||
import { ErrorNotification, Loading } from "@scm-manager/ui-components";
|
import { ErrorNotification, Loading } from "@scm-manager/ui-components";
|
||||||
import {
|
import {
|
||||||
fetchSources,
|
|
||||||
getFetchSourcesFailure,
|
getFetchSourcesFailure,
|
||||||
isFetchSourcesPending,
|
isFetchSourcesPending,
|
||||||
getSources
|
getSources
|
||||||
@@ -29,7 +28,6 @@ type Props = {
|
|||||||
revision: string,
|
revision: string,
|
||||||
path: string,
|
path: string,
|
||||||
baseUrl: string,
|
baseUrl: string,
|
||||||
fetchSources: (Repository, string, string) => void,
|
|
||||||
// context props
|
// context props
|
||||||
classes: any,
|
classes: any,
|
||||||
t: string => string,
|
t: string => string,
|
||||||
@@ -49,19 +47,6 @@ export function findParent(path: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class FileTree extends React.Component<Props> {
|
class FileTree extends React.Component<Props> {
|
||||||
componentDidMount() {
|
|
||||||
const { fetchSources, repository, revision, path } = this.props;
|
|
||||||
|
|
||||||
fetchSources(repository, revision, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
|
||||||
const { fetchSources, repository, revision, path } = this.props;
|
|
||||||
if (prevProps.revision !== revision || prevProps.path !== path) {
|
|
||||||
fetchSources(repository, revision, path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
error,
|
error,
|
||||||
@@ -167,18 +152,7 @@ const mapStateToProps = (state: any, ownProps: Props) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
|
||||||
return {
|
|
||||||
fetchSources: (repository: Repository, revision: string, path: string) => {
|
|
||||||
dispatch(fetchSources(repository, revision, path));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withRouter,
|
withRouter,
|
||||||
connect(
|
connect(mapStateToProps)
|
||||||
mapStateToProps,
|
|
||||||
mapDispatchToProps
|
|
||||||
)
|
|
||||||
)(injectSheet(styles)(translate("repos")(FileTree)));
|
)(injectSheet(styles)(translate("repos")(FileTree)));
|
||||||
|
|||||||
@@ -49,14 +49,18 @@ class FileTreeLeaf extends React.Component<Props> {
|
|||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return <FileIcon file={file} />;
|
return (
|
||||||
|
<Link to={this.createLink(file)}>
|
||||||
|
<FileIcon file={file} />
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
createFileName = (file: File) => {
|
createFileName = (file: File) => {
|
||||||
if (file.directory) {
|
if (file.directory) {
|
||||||
return <Link to={this.createLink(file)}>{file.name}</Link>;
|
return <Link to={this.createLink(file)}>{file.name}</Link>;
|
||||||
}
|
}
|
||||||
return file.name;
|
return <Link to={this.createLink(file)}>{file.name}</Link>;
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// @flow
|
||||||
|
import React from "react";
|
||||||
|
import { translate } from "react-i18next";
|
||||||
|
import type { File } from "@scm-manager/ui-types";
|
||||||
|
import { DownloadButton } from "@scm-manager/ui-components";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
t: string => string,
|
||||||
|
file: File
|
||||||
|
};
|
||||||
|
|
||||||
|
class DownloadViewer extends React.Component<Props> {
|
||||||
|
render() {
|
||||||
|
const { t, file } = this.props;
|
||||||
|
return (
|
||||||
|
<div className="has-text-centered">
|
||||||
|
<DownloadButton
|
||||||
|
url={file._links.self.href}
|
||||||
|
displayName={t("sources.content.downloadButton")}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default translate("repos")(DownloadViewer);
|
||||||
24
scm-ui/src/repos/sources/components/content/ImageViewer.js
Normal file
24
scm-ui/src/repos/sources/components/content/ImageViewer.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
// @flow
|
||||||
|
import React from "react";
|
||||||
|
import { translate } from "react-i18next";
|
||||||
|
import type { File } from "@scm-manager/ui-types";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
t: string => string,
|
||||||
|
file: File
|
||||||
|
};
|
||||||
|
|
||||||
|
class ImageViewer extends React.Component<Props> {
|
||||||
|
render() {
|
||||||
|
const { file } = this.props;
|
||||||
|
return (
|
||||||
|
<div className="has-text-centered">
|
||||||
|
<figure>
|
||||||
|
<img src={file._links.self.href} alt={file._links.self.href} />
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default translate("repos")(ImageViewer);
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
// @flow
|
||||||
|
import React from "react";
|
||||||
|
import { translate } from "react-i18next";
|
||||||
|
import { apiClient } from "@scm-manager/ui-components";
|
||||||
|
import type { File } from "@scm-manager/ui-types";
|
||||||
|
import { ErrorNotification, Loading } from "@scm-manager/ui-components";
|
||||||
|
import SyntaxHighlighter from "react-syntax-highlighter";
|
||||||
|
import { arduinoLight } from "react-syntax-highlighter/styles/hljs";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
t: string => string,
|
||||||
|
file: File,
|
||||||
|
language: string
|
||||||
|
};
|
||||||
|
|
||||||
|
type State = {
|
||||||
|
content: string,
|
||||||
|
error?: Error,
|
||||||
|
loaded: boolean
|
||||||
|
};
|
||||||
|
|
||||||
|
class SourcecodeViewer extends React.Component<Props, State> {
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
content: "",
|
||||||
|
loaded: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const { file } = this.props;
|
||||||
|
getContent(file._links.self.href)
|
||||||
|
.then(result => {
|
||||||
|
if (result.error) {
|
||||||
|
this.setState({
|
||||||
|
...this.state,
|
||||||
|
error: result.error,
|
||||||
|
loaded: true
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
...this.state,
|
||||||
|
content: result,
|
||||||
|
loaded: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
showLineNumbers="true"
|
||||||
|
language={getLanguage(language)}
|
||||||
|
style={arduinoLight}
|
||||||
|
>
|
||||||
|
{content}
|
||||||
|
</SyntaxHighlighter>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getLanguage(language: string) {
|
||||||
|
return language.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getContent(url: string) {
|
||||||
|
return apiClient
|
||||||
|
.get(url)
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(response => {
|
||||||
|
return response;
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
return { error: err };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default translate("repos")(SourcecodeViewer);
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
//@flow
|
||||||
|
import fetchMock from "fetch-mock";
|
||||||
|
import {
|
||||||
|
getContent,
|
||||||
|
getLanguage
|
||||||
|
} from "./SourcecodeViewer";
|
||||||
|
|
||||||
|
describe("get content", () => {
|
||||||
|
const CONTENT_URL = "/repositories/scmadmin/TestRepo/content/testContent";
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
fetchMock.reset();
|
||||||
|
fetchMock.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return content", done => {
|
||||||
|
fetchMock.getOnce("/api/v2" + CONTENT_URL, "This is a testContent");
|
||||||
|
|
||||||
|
getContent(CONTENT_URL).then(content => {
|
||||||
|
expect(content).toBe("This is a testContent");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("get correct language type", () => {
|
||||||
|
it("should return javascript", () => {
|
||||||
|
expect(getLanguage("JAVASCRIPT")).toBe("javascript");
|
||||||
|
});
|
||||||
|
it("should return nothing for plain text", () => {
|
||||||
|
expect(getLanguage("")).toBe("");
|
||||||
|
});
|
||||||
|
});
|
||||||
217
scm-ui/src/repos/sources/containers/Content.js
Normal file
217
scm-ui/src/repos/sources/containers/Content.js
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
// @flow
|
||||||
|
import React from "react";
|
||||||
|
import { translate } from "react-i18next";
|
||||||
|
import { getSources } from "../modules/sources";
|
||||||
|
import type { Repository, File } from "@scm-manager/ui-types";
|
||||||
|
import {
|
||||||
|
ErrorNotification,
|
||||||
|
Loading,
|
||||||
|
DateFromNow
|
||||||
|
} from "@scm-manager/ui-components";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import ImageViewer from "../components/content/ImageViewer";
|
||||||
|
import SourcecodeViewer from "../components/content/SourcecodeViewer";
|
||||||
|
import DownloadViewer from "../components/content/DownloadViewer";
|
||||||
|
import FileSize from "../components/FileSize";
|
||||||
|
import injectSheet from "react-jss";
|
||||||
|
import classNames from "classnames";
|
||||||
|
import { ExtensionPoint } from "@scm-manager/ui-extensions";
|
||||||
|
import { getContentType } from "./contentType";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
loading: boolean,
|
||||||
|
error: Error,
|
||||||
|
file: File,
|
||||||
|
repository: Repository,
|
||||||
|
revision: string,
|
||||||
|
path: string,
|
||||||
|
classes: any,
|
||||||
|
t: string => string
|
||||||
|
};
|
||||||
|
|
||||||
|
type State = {
|
||||||
|
contentType: string,
|
||||||
|
language: string,
|
||||||
|
loaded: boolean,
|
||||||
|
collapsed: boolean,
|
||||||
|
error?: Error
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
toCenterContent: {
|
||||||
|
display: "block"
|
||||||
|
},
|
||||||
|
pointer: {
|
||||||
|
cursor: "pointer"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Content extends React.Component<Props, State> {
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
contentType: "",
|
||||||
|
language: "",
|
||||||
|
loaded: false,
|
||||||
|
collapsed: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const { file } = this.props;
|
||||||
|
getContentType(file._links.self.href)
|
||||||
|
.then(result => {
|
||||||
|
if (result.error) {
|
||||||
|
this.setState({
|
||||||
|
...this.state,
|
||||||
|
error: result.error,
|
||||||
|
loaded: true
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
...this.state,
|
||||||
|
contentType: result.type,
|
||||||
|
language: result.language,
|
||||||
|
loaded: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleCollapse = () => {
|
||||||
|
this.setState(prevState => ({
|
||||||
|
collapsed: !prevState.collapsed
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
showHeader() {
|
||||||
|
const { file, classes } = this.props;
|
||||||
|
const collapsed = this.state.collapsed;
|
||||||
|
const icon = collapsed ? "fa-angle-right" : "fa-angle-down";
|
||||||
|
const fileSize = file.directory ? "" : <FileSize bytes={file.length} />;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span className={classes.pointer} onClick={this.toggleCollapse}>
|
||||||
|
<article className="media">
|
||||||
|
<div className="media-left">
|
||||||
|
<i className={classNames("fa", icon)} />
|
||||||
|
</div>
|
||||||
|
<div className="media-content">
|
||||||
|
<div className="content">{file.name}</div>
|
||||||
|
</div>
|
||||||
|
<p className="media-right">{fileSize}</p>
|
||||||
|
</article>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
showMoreInformation() {
|
||||||
|
const collapsed = this.state.collapsed;
|
||||||
|
const { classes, file, revision } = this.props;
|
||||||
|
const date = <DateFromNow date={file.lastModified} />;
|
||||||
|
const description = file.description ? (
|
||||||
|
<p>
|
||||||
|
{file.description.split("\n").map((item, key) => {
|
||||||
|
return (
|
||||||
|
<span key={key}>
|
||||||
|
{item}
|
||||||
|
<br />
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</p>
|
||||||
|
) : null;
|
||||||
|
if (!collapsed) {
|
||||||
|
return (
|
||||||
|
<div className={classNames("panel-block", classes.toCenterContent)}>
|
||||||
|
<table className="table">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Path</td>
|
||||||
|
<td>{file.path}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Branch</td>
|
||||||
|
<td>{revision}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Last modified</td>
|
||||||
|
<td>{date}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Description</td>
|
||||||
|
<td>{description}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
showContent() {
|
||||||
|
const { file, revision } = this.props;
|
||||||
|
const { contentType, language } = this.state;
|
||||||
|
if (contentType.startsWith("image/")) {
|
||||||
|
return <ImageViewer file={file} />;
|
||||||
|
} else if (language) {
|
||||||
|
return <SourcecodeViewer file={file} language={language} />;
|
||||||
|
} else if (contentType.startsWith("text/")) {
|
||||||
|
return <SourcecodeViewer file={file} language="none" />;
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<ExtensionPoint
|
||||||
|
name="repos.sources.view"
|
||||||
|
props={{ file, contentType, revision }}
|
||||||
|
>
|
||||||
|
<DownloadViewer file={file} />
|
||||||
|
</ExtensionPoint>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { file, classes } = this.props;
|
||||||
|
const { loaded, error } = this.state;
|
||||||
|
|
||||||
|
if (!file || !loaded) {
|
||||||
|
return <Loading />;
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
return <ErrorNotification error={error} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const header = this.showHeader();
|
||||||
|
const content = this.showContent();
|
||||||
|
const moreInformation = this.showMoreInformation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<nav className="panel">
|
||||||
|
<article className="panel-heading">{header}</article>
|
||||||
|
{moreInformation}
|
||||||
|
<div className={classNames("panel-block", classes.toCenterContent)}>
|
||||||
|
{content}
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state: any, ownProps: Props) => {
|
||||||
|
const { repository, revision, path } = ownProps;
|
||||||
|
|
||||||
|
const file = getSources(state, repository, revision, path);
|
||||||
|
|
||||||
|
return {
|
||||||
|
file
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default injectSheet(styles)(
|
||||||
|
connect(mapStateToProps)(translate("repos")(Content))
|
||||||
|
);
|
||||||
@@ -13,6 +13,8 @@ import {
|
|||||||
isFetchBranchesPending
|
isFetchBranchesPending
|
||||||
} from "../../modules/branches";
|
} from "../../modules/branches";
|
||||||
import { compose } from "redux";
|
import { compose } from "redux";
|
||||||
|
import Content from "./Content";
|
||||||
|
import { fetchSources, isDirectory } from "../modules/sources";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
repository: Repository,
|
repository: Repository,
|
||||||
@@ -22,9 +24,11 @@ type Props = {
|
|||||||
branches: Branch[],
|
branches: Branch[],
|
||||||
revision: string,
|
revision: string,
|
||||||
path: string,
|
path: string,
|
||||||
|
currentFileIsDirectory: boolean,
|
||||||
|
|
||||||
// dispatch props
|
// dispatch props
|
||||||
fetchBranches: Repository => void,
|
fetchBranches: Repository => void,
|
||||||
|
fetchSources: (Repository, string, string) => void,
|
||||||
|
|
||||||
// Context props
|
// Context props
|
||||||
history: any,
|
history: any,
|
||||||
@@ -33,14 +37,26 @@ type Props = {
|
|||||||
|
|
||||||
class Sources extends React.Component<Props> {
|
class Sources extends React.Component<Props> {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { fetchBranches, repository } = this.props;
|
const {
|
||||||
|
fetchBranches,
|
||||||
|
repository,
|
||||||
|
revision,
|
||||||
|
path,
|
||||||
|
fetchSources
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
fetchBranches(repository);
|
fetchBranches(repository);
|
||||||
|
fetchSources(repository, revision, path);
|
||||||
|
}
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
const { fetchSources, repository, revision, path } = this.props;
|
||||||
|
if (prevProps.revision !== revision || prevProps.path !== path) {
|
||||||
|
fetchSources(repository, revision, path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
branchSelected = (branch?: Branch) => {
|
branchSelected = (branch?: Branch) => {
|
||||||
const { baseUrl, history, path } = this.props;
|
const { baseUrl, history, path } = this.props;
|
||||||
|
|
||||||
let url;
|
let url;
|
||||||
if (branch) {
|
if (branch) {
|
||||||
if (path) {
|
if (path) {
|
||||||
@@ -55,7 +71,15 @@ class Sources extends React.Component<Props> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { repository, baseUrl, loading, error, revision, path } = this.props;
|
const {
|
||||||
|
repository,
|
||||||
|
baseUrl,
|
||||||
|
loading,
|
||||||
|
error,
|
||||||
|
revision,
|
||||||
|
path,
|
||||||
|
currentFileIsDirectory
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return <ErrorNotification error={error} />;
|
return <ErrorNotification error={error} />;
|
||||||
@@ -65,21 +89,28 @@ class Sources extends React.Component<Props> {
|
|||||||
return <Loading />;
|
return <Loading />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
if (currentFileIsDirectory) {
|
||||||
<>
|
return (
|
||||||
{this.renderBranchSelector()}
|
<>
|
||||||
<FileTree
|
{this.renderBranchSelector()}
|
||||||
repository={repository}
|
<FileTree
|
||||||
revision={revision}
|
repository={repository}
|
||||||
path={path}
|
revision={revision}
|
||||||
baseUrl={baseUrl}
|
path={path}
|
||||||
/>
|
baseUrl={baseUrl}
|
||||||
</>
|
/>
|
||||||
);
|
</>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<Content repository={repository} revision={revision} path={path} />
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderBranchSelector = () => {
|
renderBranchSelector = () => {
|
||||||
const { repository, branches, revision } = this.props;
|
const { repository, branches, revision } = this.props;
|
||||||
|
|
||||||
if (repository._links.branches) {
|
if (repository._links.branches) {
|
||||||
return (
|
return (
|
||||||
<BranchSelector
|
<BranchSelector
|
||||||
@@ -99,10 +130,12 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
const { repository, match } = ownProps;
|
const { repository, match } = ownProps;
|
||||||
const { revision, path } = match.params;
|
const { revision, path } = match.params;
|
||||||
const decodedRevision = revision ? decodeURIComponent(revision) : undefined;
|
const decodedRevision = revision ? decodeURIComponent(revision) : undefined;
|
||||||
|
|
||||||
const loading = isFetchBranchesPending(state, repository);
|
const loading = isFetchBranchesPending(state, repository);
|
||||||
const error = getFetchBranchesFailure(state, repository);
|
const error = getFetchBranchesFailure(state, repository);
|
||||||
const branches = getBranches(state, repository);
|
const branches = getBranches(state, repository);
|
||||||
|
const currentFileIsDirectory = decodedRevision
|
||||||
|
? isDirectory(state, repository, decodedRevision, path)
|
||||||
|
: isDirectory(state, repository, revision, path);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
repository,
|
repository,
|
||||||
@@ -110,7 +143,8 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
path,
|
path,
|
||||||
loading,
|
loading,
|
||||||
error,
|
error,
|
||||||
branches
|
branches,
|
||||||
|
currentFileIsDirectory
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -118,6 +152,9 @@ const mapDispatchToProps = dispatch => {
|
|||||||
return {
|
return {
|
||||||
fetchBranches: (repository: Repository) => {
|
fetchBranches: (repository: Repository) => {
|
||||||
dispatch(fetchBranches(repository));
|
dispatch(fetchBranches(repository));
|
||||||
|
},
|
||||||
|
fetchSources: (repository: Repository, revision: string, path: string) => {
|
||||||
|
dispatch(fetchSources(repository, revision, path));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
16
scm-ui/src/repos/sources/containers/contentType.js
Normal file
16
scm-ui/src/repos/sources/containers/contentType.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
//@flow
|
||||||
|
import { apiClient } from "@scm-manager/ui-components";
|
||||||
|
|
||||||
|
export function getContentType(url: string) {
|
||||||
|
return apiClient
|
||||||
|
.head(url)
|
||||||
|
.then(response => {
|
||||||
|
return {
|
||||||
|
type: response.headers.get("Content-Type"),
|
||||||
|
language: response.headers.get("X-Programming-Language")
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
return { error: err };
|
||||||
|
});
|
||||||
|
}
|
||||||
29
scm-ui/src/repos/sources/containers/contentType.test.js
Normal file
29
scm-ui/src/repos/sources/containers/contentType.test.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
//@flow
|
||||||
|
import fetchMock from "fetch-mock";
|
||||||
|
import { getContentType } from "./contentType";
|
||||||
|
|
||||||
|
describe("get content type", () => {
|
||||||
|
const CONTENT_URL = "/repositories/scmadmin/TestRepo/content/testContent";
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
fetchMock.reset();
|
||||||
|
fetchMock.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return content", done => {
|
||||||
|
let headers = {
|
||||||
|
"Content-Type": "application/text",
|
||||||
|
"X-Programming-Language": "JAVA"
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchMock.head("/api/v2" + CONTENT_URL, {
|
||||||
|
headers
|
||||||
|
});
|
||||||
|
|
||||||
|
getContentType(CONTENT_URL).then(content => {
|
||||||
|
expect(content.type).toBe("application/text");
|
||||||
|
expect(content.language).toBe("JAVA");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -102,6 +102,20 @@ export default function reducer(
|
|||||||
|
|
||||||
// selectors
|
// selectors
|
||||||
|
|
||||||
|
export function isDirectory(
|
||||||
|
state: any,
|
||||||
|
repository: Repository,
|
||||||
|
revision: string,
|
||||||
|
path: string
|
||||||
|
): boolean {
|
||||||
|
const currentFile = getSources(state, repository, revision, path);
|
||||||
|
if (currentFile && !currentFile.directory) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true; //also return true if no currentFile is found since it is the "default" path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function getSources(
|
export function getSources(
|
||||||
state: any,
|
state: any,
|
||||||
repository: Repository,
|
repository: Repository,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import type { Repository } from "@scm-manager/ui-types";
|
import type { Repository, File } from "@scm-manager/ui-types";
|
||||||
import configureMockStore from "redux-mock-store";
|
import configureMockStore from "redux-mock-store";
|
||||||
import thunk from "redux-thunk";
|
import thunk from "redux-thunk";
|
||||||
import fetchMock from "fetch-mock";
|
import fetchMock from "fetch-mock";
|
||||||
@@ -14,7 +14,8 @@ import {
|
|||||||
isFetchSourcesPending,
|
isFetchSourcesPending,
|
||||||
default as reducer,
|
default as reducer,
|
||||||
getSources,
|
getSources,
|
||||||
fetchSourcesSuccess
|
fetchSourcesSuccess,
|
||||||
|
isDirectory
|
||||||
} from "./sources";
|
} from "./sources";
|
||||||
|
|
||||||
const sourcesUrl =
|
const sourcesUrl =
|
||||||
@@ -79,6 +80,21 @@ const collection = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const noDirectory: File = {
|
||||||
|
name: "src",
|
||||||
|
path: "src",
|
||||||
|
directory: true,
|
||||||
|
length: 176,
|
||||||
|
revision: "abc",
|
||||||
|
_links: {
|
||||||
|
self: {
|
||||||
|
href:
|
||||||
|
"http://localhost:8081/scm/rest/api/v2/repositories/scm/core/sources/76aae4bb4ceacf0e88938eb5b6832738b7d537b4/src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_embedded: collection
|
||||||
|
};
|
||||||
|
|
||||||
describe("sources fetch", () => {
|
describe("sources fetch", () => {
|
||||||
const mockStore = configureMockStore([thunk]);
|
const mockStore = configureMockStore([thunk]);
|
||||||
|
|
||||||
@@ -168,6 +184,28 @@ describe("reducer tests", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("selector tests", () => {
|
describe("selector tests", () => {
|
||||||
|
it("should return false if it is no directory", () => {
|
||||||
|
const state = {
|
||||||
|
sources: {
|
||||||
|
"scm/core/abc/src/main/package.json": {
|
||||||
|
noDirectory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
expect(
|
||||||
|
isDirectory(state, repository, "abc", "src/main/package.json")
|
||||||
|
).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return true if it is directory", () => {
|
||||||
|
const state = {
|
||||||
|
sources: {
|
||||||
|
"scm/core/abc/src": noDirectory
|
||||||
|
}
|
||||||
|
};
|
||||||
|
expect(isDirectory(state, repository, "abc", "src")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
it("should return null", () => {
|
it("should return null", () => {
|
||||||
expect(getSources({}, repository)).toBeFalsy();
|
expect(getSources({}, repository)).toBeFalsy();
|
||||||
});
|
});
|
||||||
@@ -181,7 +219,7 @@ describe("selector tests", () => {
|
|||||||
expect(getSources(state, repository)).toBe(collection);
|
expect(getSources(state, repository)).toBe(collection);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return the source collection without revision and path", () => {
|
it("should return the source collection with revision and path", () => {
|
||||||
const state = {
|
const state = {
|
||||||
sources: {
|
sources: {
|
||||||
"scm/core/abc/src/main": collection
|
"scm/core/abc/src/main": collection
|
||||||
|
|||||||
150
scm-ui/yarn.lock
150
scm-ui/yarn.lock
@@ -1181,7 +1181,7 @@ babel-register@^6.26.0:
|
|||||||
mkdirp "^0.5.1"
|
mkdirp "^0.5.1"
|
||||||
source-map-support "^0.4.15"
|
source-map-support "^0.4.15"
|
||||||
|
|
||||||
babel-runtime@^6.22.0, babel-runtime@^6.26.0:
|
babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0:
|
||||||
version "6.26.0"
|
version "6.26.0"
|
||||||
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
|
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -1739,6 +1739,18 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0:
|
|||||||
escape-string-regexp "^1.0.5"
|
escape-string-regexp "^1.0.5"
|
||||||
supports-color "^5.3.0"
|
supports-color "^5.3.0"
|
||||||
|
|
||||||
|
character-entities-legacy@^1.0.0:
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz#7c6defb81648498222c9855309953d05f4d63a9c"
|
||||||
|
|
||||||
|
character-entities@^1.0.0:
|
||||||
|
version "1.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.2.tgz#58c8f371c0774ef0ba9b2aca5f00d8f100e6e363"
|
||||||
|
|
||||||
|
character-reference-invalid@^1.0.0:
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz#21e421ad3d84055952dab4a43a04e73cd425d3ed"
|
||||||
|
|
||||||
chardet@^0.7.0:
|
chardet@^0.7.0:
|
||||||
version "0.7.0"
|
version "0.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
|
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
|
||||||
@@ -1840,6 +1852,14 @@ cli-width@^2.0.0:
|
|||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
|
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
|
||||||
|
|
||||||
|
clipboard@^2.0.0:
|
||||||
|
version "2.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.1.tgz#a12481e1c13d8a50f5f036b0560fe5d16d74e46a"
|
||||||
|
dependencies:
|
||||||
|
good-listener "^1.2.2"
|
||||||
|
select "^1.1.2"
|
||||||
|
tiny-emitter "^2.0.0"
|
||||||
|
|
||||||
cliui@^3.2.0:
|
cliui@^3.2.0:
|
||||||
version "3.2.0"
|
version "3.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
|
resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
|
||||||
@@ -1946,6 +1966,12 @@ combined-stream@^1.0.5, combined-stream@~1.0.5, combined-stream@~1.0.6:
|
|||||||
dependencies:
|
dependencies:
|
||||||
delayed-stream "~1.0.0"
|
delayed-stream "~1.0.0"
|
||||||
|
|
||||||
|
comma-separated-tokens@^1.0.0:
|
||||||
|
version "1.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.5.tgz#b13793131d9ea2d2431cf5b507ddec258f0ce0db"
|
||||||
|
dependencies:
|
||||||
|
trim "0.0.1"
|
||||||
|
|
||||||
commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0:
|
commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0:
|
||||||
version "2.18.0"
|
version "2.18.0"
|
||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970"
|
resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970"
|
||||||
@@ -2327,6 +2353,10 @@ delayed-stream@~1.0.0:
|
|||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||||
|
|
||||||
|
delegate@^3.1.2:
|
||||||
|
version "3.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166"
|
||||||
|
|
||||||
delegates@^1.0.0:
|
delegates@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
|
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
|
||||||
@@ -3068,6 +3098,12 @@ fast-xml-parser@^3.12.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
nimnjs "^1.3.2"
|
nimnjs "^1.3.2"
|
||||||
|
|
||||||
|
fault@^1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.2.tgz#c3d0fec202f172a3a4d414042ad2bb5e2a3ffbaa"
|
||||||
|
dependencies:
|
||||||
|
format "^0.2.2"
|
||||||
|
|
||||||
fb-watchman@^2.0.0:
|
fb-watchman@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58"
|
resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58"
|
||||||
@@ -3280,6 +3316,10 @@ form-data@~2.3.1, form-data@~2.3.2:
|
|||||||
combined-stream "1.0.6"
|
combined-stream "1.0.6"
|
||||||
mime-types "^2.1.12"
|
mime-types "^2.1.12"
|
||||||
|
|
||||||
|
format@^0.2.2:
|
||||||
|
version "0.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b"
|
||||||
|
|
||||||
fragment-cache@^0.2.1:
|
fragment-cache@^0.2.1:
|
||||||
version "0.2.1"
|
version "0.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
|
resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
|
||||||
@@ -3569,6 +3609,12 @@ glogg@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
sparkles "^1.0.0"
|
sparkles "^1.0.0"
|
||||||
|
|
||||||
|
good-listener@^1.2.2:
|
||||||
|
version "1.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50"
|
||||||
|
dependencies:
|
||||||
|
delegate "^3.1.2"
|
||||||
|
|
||||||
got@^7.1.0:
|
got@^7.1.0:
|
||||||
version "7.1.0"
|
version "7.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a"
|
resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a"
|
||||||
@@ -3814,6 +3860,19 @@ hash.js@^1.0.0, hash.js@^1.0.3:
|
|||||||
inherits "^2.0.3"
|
inherits "^2.0.3"
|
||||||
minimalistic-assert "^1.0.1"
|
minimalistic-assert "^1.0.1"
|
||||||
|
|
||||||
|
hast-util-parse-selector@^2.2.0:
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.2.0.tgz#2175f18cdd697308fc3431d5c29a9e48dfa4817a"
|
||||||
|
|
||||||
|
hastscript@^4.0.0:
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-4.1.0.tgz#ea5593fa6f6709101fc790ced818393ddaa045ce"
|
||||||
|
dependencies:
|
||||||
|
comma-separated-tokens "^1.0.0"
|
||||||
|
hast-util-parse-selector "^2.2.0"
|
||||||
|
property-information "^4.0.0"
|
||||||
|
space-separated-tokens "^1.0.0"
|
||||||
|
|
||||||
hawk@~3.1.3:
|
hawk@~3.1.3:
|
||||||
version "3.1.3"
|
version "3.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4"
|
resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4"
|
||||||
@@ -3823,6 +3882,10 @@ hawk@~3.1.3:
|
|||||||
hoek "2.x.x"
|
hoek "2.x.x"
|
||||||
sntp "1.x.x"
|
sntp "1.x.x"
|
||||||
|
|
||||||
|
highlight.js@~9.12.0:
|
||||||
|
version "9.12.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e"
|
||||||
|
|
||||||
history@^4.7.2:
|
history@^4.7.2:
|
||||||
version "4.7.2"
|
version "4.7.2"
|
||||||
resolved "https://registry.yarnpkg.com/history/-/history-4.7.2.tgz#22b5c7f31633c5b8021c7f4a8a954ac139ee8d5b"
|
resolved "https://registry.yarnpkg.com/history/-/history-4.7.2.tgz#22b5c7f31633c5b8021c7f4a8a954ac139ee8d5b"
|
||||||
@@ -4115,6 +4178,17 @@ is-accessor-descriptor@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
kind-of "^6.0.0"
|
kind-of "^6.0.0"
|
||||||
|
|
||||||
|
is-alphabetical@^1.0.0:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.2.tgz#1fa6e49213cb7885b75d15862fb3f3d96c884f41"
|
||||||
|
|
||||||
|
is-alphanumerical@^1.0.0:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz#1138e9ae5040158dc6ff76b820acd6b7a181fd40"
|
||||||
|
dependencies:
|
||||||
|
is-alphabetical "^1.0.0"
|
||||||
|
is-decimal "^1.0.0"
|
||||||
|
|
||||||
is-arrayish@^0.2.1:
|
is-arrayish@^0.2.1:
|
||||||
version "0.2.1"
|
version "0.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
|
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
|
||||||
@@ -4165,6 +4239,10 @@ is-date-object@^1.0.1:
|
|||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16"
|
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16"
|
||||||
|
|
||||||
|
is-decimal@^1.0.0:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.2.tgz#894662d6a8709d307f3a276ca4339c8fa5dff0ff"
|
||||||
|
|
||||||
is-descriptor@^0.1.0:
|
is-descriptor@^0.1.0:
|
||||||
version "0.1.6"
|
version "0.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca"
|
resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca"
|
||||||
@@ -4251,6 +4329,10 @@ is-glob@^4.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-extglob "^2.1.1"
|
is-extglob "^2.1.1"
|
||||||
|
|
||||||
|
is-hexadecimal@^1.0.0:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz#b6e710d7d07bb66b98cb8cece5c9b4921deeb835"
|
||||||
|
|
||||||
is-in-browser@^1.0.2, is-in-browser@^1.1.3:
|
is-in-browser@^1.0.2, is-in-browser@^1.1.3:
|
||||||
version "1.1.3"
|
version "1.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/is-in-browser/-/is-in-browser-1.1.3.tgz#56ff4db683a078c6082eb95dad7dc62e1d04f835"
|
resolved "https://registry.yarnpkg.com/is-in-browser/-/is-in-browser-1.1.3.tgz#56ff4db683a078c6082eb95dad7dc62e1d04f835"
|
||||||
@@ -5320,6 +5402,13 @@ lowercase-keys@^1.0.0:
|
|||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
|
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
|
||||||
|
|
||||||
|
lowlight@~1.9.1:
|
||||||
|
version "1.9.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.9.2.tgz#0b9127e3cec2c3021b7795dd81005c709a42fdd1"
|
||||||
|
dependencies:
|
||||||
|
fault "^1.0.2"
|
||||||
|
highlight.js "~9.12.0"
|
||||||
|
|
||||||
lru-cache@2:
|
lru-cache@2:
|
||||||
version "2.7.3"
|
version "2.7.3"
|
||||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952"
|
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952"
|
||||||
@@ -6175,6 +6264,17 @@ parse-asn1@^5.0.0:
|
|||||||
evp_bytestokey "^1.0.0"
|
evp_bytestokey "^1.0.0"
|
||||||
pbkdf2 "^3.0.3"
|
pbkdf2 "^3.0.3"
|
||||||
|
|
||||||
|
parse-entities@^1.1.2:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.2.0.tgz#9deac087661b2e36814153cb78d7e54a4c5fd6f4"
|
||||||
|
dependencies:
|
||||||
|
character-entities "^1.0.0"
|
||||||
|
character-entities-legacy "^1.0.0"
|
||||||
|
character-reference-invalid "^1.0.0"
|
||||||
|
is-alphanumerical "^1.0.0"
|
||||||
|
is-decimal "^1.0.0"
|
||||||
|
is-hexadecimal "^1.0.0"
|
||||||
|
|
||||||
parse-filepath@^1.0.1:
|
parse-filepath@^1.0.1:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891"
|
resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891"
|
||||||
@@ -6422,6 +6522,12 @@ pretty-hrtime@^1.0.0:
|
|||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
|
resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
|
||||||
|
|
||||||
|
prismjs@^1.8.4, prismjs@~1.15.0:
|
||||||
|
version "1.15.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.15.0.tgz#8801d332e472091ba8def94976c8877ad60398d9"
|
||||||
|
optionalDependencies:
|
||||||
|
clipboard "^2.0.0"
|
||||||
|
|
||||||
private@^0.1.6, private@^0.1.8:
|
private@^0.1.6, private@^0.1.8:
|
||||||
version "0.1.8"
|
version "0.1.8"
|
||||||
resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
|
resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
|
||||||
@@ -6456,6 +6562,12 @@ prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2:
|
|||||||
loose-envify "^1.3.1"
|
loose-envify "^1.3.1"
|
||||||
object-assign "^4.1.1"
|
object-assign "^4.1.1"
|
||||||
|
|
||||||
|
property-information@^4.0.0:
|
||||||
|
version "4.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/property-information/-/property-information-4.2.0.tgz#f0e66e07cbd6fed31d96844d958d153ad3eb486e"
|
||||||
|
dependencies:
|
||||||
|
xtend "^4.0.1"
|
||||||
|
|
||||||
ps-tree@^1.1.0:
|
ps-tree@^1.1.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.1.0.tgz#b421b24140d6203f1ed3c76996b4427b08e8c014"
|
resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.1.0.tgz#b421b24140d6203f1ed3c76996b4427b08e8c014"
|
||||||
@@ -6653,6 +6765,16 @@ react-router@^4.2.0, react-router@^4.3.1:
|
|||||||
prop-types "^15.6.1"
|
prop-types "^15.6.1"
|
||||||
warning "^4.0.1"
|
warning "^4.0.1"
|
||||||
|
|
||||||
|
react-syntax-highlighter@^9.0.1:
|
||||||
|
version "9.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-syntax-highlighter/-/react-syntax-highlighter-9.0.1.tgz#cad91692e1976f68290f24762ac3451b1fec3d26"
|
||||||
|
dependencies:
|
||||||
|
babel-runtime "^6.18.0"
|
||||||
|
highlight.js "~9.12.0"
|
||||||
|
lowlight "~1.9.1"
|
||||||
|
prismjs "^1.8.4"
|
||||||
|
refractor "^2.4.1"
|
||||||
|
|
||||||
react-test-renderer@^16.0.0-0, react-test-renderer@^16.4.1:
|
react-test-renderer@^16.0.0-0, react-test-renderer@^16.4.1:
|
||||||
version "16.5.2"
|
version "16.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.5.2.tgz#92e9d2c6f763b9821b2e0b22f994ee675068b5ae"
|
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.5.2.tgz#92e9d2c6f763b9821b2e0b22f994ee675068b5ae"
|
||||||
@@ -6811,6 +6933,14 @@ redux@^4.0.0:
|
|||||||
loose-envify "^1.1.0"
|
loose-envify "^1.1.0"
|
||||||
symbol-observable "^1.2.0"
|
symbol-observable "^1.2.0"
|
||||||
|
|
||||||
|
refractor@^2.4.1:
|
||||||
|
version "2.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/refractor/-/refractor-2.6.0.tgz#6b0d88f654c8534eefed3329a35bc7bb74ae0979"
|
||||||
|
dependencies:
|
||||||
|
hastscript "^4.0.0"
|
||||||
|
parse-entities "^1.1.2"
|
||||||
|
prismjs "~1.15.0"
|
||||||
|
|
||||||
regenerate-unicode-properties@^7.0.0:
|
regenerate-unicode-properties@^7.0.0:
|
||||||
version "7.0.0"
|
version "7.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz#107405afcc4a190ec5ed450ecaa00ed0cafa7a4c"
|
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz#107405afcc4a190ec5ed450ecaa00ed0cafa7a4c"
|
||||||
@@ -7172,6 +7302,10 @@ scss-tokenizer@^0.2.3:
|
|||||||
js-base64 "^2.1.8"
|
js-base64 "^2.1.8"
|
||||||
source-map "^0.4.2"
|
source-map "^0.4.2"
|
||||||
|
|
||||||
|
select@^1.1.2:
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
|
||||||
|
|
||||||
"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1:
|
"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1:
|
||||||
version "5.5.1"
|
version "5.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477"
|
||||||
@@ -7440,6 +7574,12 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
|
|||||||
version "0.6.1"
|
version "0.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||||
|
|
||||||
|
space-separated-tokens@^1.0.0:
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.2.tgz#e95ab9d19ae841e200808cd96bc7bd0adbbb3412"
|
||||||
|
dependencies:
|
||||||
|
trim "0.0.1"
|
||||||
|
|
||||||
sparkles@^1.0.0:
|
sparkles@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c"
|
resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c"
|
||||||
@@ -7834,6 +7974,10 @@ timers-ext@^0.1.5:
|
|||||||
es5-ext "~0.10.46"
|
es5-ext "~0.10.46"
|
||||||
next-tick "1"
|
next-tick "1"
|
||||||
|
|
||||||
|
tiny-emitter@^2.0.0:
|
||||||
|
version "2.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.0.2.tgz#82d27468aca5ade8e5fd1e6d22b57dd43ebdfb7c"
|
||||||
|
|
||||||
tmp@^0.0.33:
|
tmp@^0.0.33:
|
||||||
version "0.0.33"
|
version "0.0.33"
|
||||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
|
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
|
||||||
@@ -7917,6 +8061,10 @@ trim-right@^1.0.1:
|
|||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
|
resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
|
||||||
|
|
||||||
|
trim@0.0.1:
|
||||||
|
version "0.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd"
|
||||||
|
|
||||||
"true-case-path@^1.0.2":
|
"true-case-path@^1.0.2":
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.3.tgz#f813b5a8c86b40da59606722b144e3225799f47d"
|
resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.3.tgz#f813b5a8c86b40da59606722b144e3225799f47d"
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ public class ContentResource {
|
|||||||
private void appendContentHeader(String path, byte[] head, Response.ResponseBuilder responseBuilder) {
|
private void appendContentHeader(String path, byte[] head, Response.ResponseBuilder responseBuilder) {
|
||||||
ContentType contentType = ContentTypes.detect(path, head);
|
ContentType contentType = ContentTypes.detect(path, head);
|
||||||
responseBuilder.header("Content-Type", contentType.getRaw());
|
responseBuilder.header("Content-Type", contentType.getRaw());
|
||||||
contentType.getLanguage().ifPresent(language -> responseBuilder.header("Language", language));
|
contentType.getLanguage().ifPresent(language -> responseBuilder.header("X-Programming-Language", language));
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] getHead(String revision, String path, RepositoryService repositoryService) throws IOException, PathNotFoundException, RevisionNotFoundException {
|
private byte[] getHead(String revision, String path, RepositoryService repositoryService) throws IOException, PathNotFoundException, RevisionNotFoundException {
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ public class ContentResourceTest {
|
|||||||
Response response = contentResource.get(NAMESPACE, REPO_NAME, REV, "SomeGoCode.go");
|
Response response = contentResource.get(NAMESPACE, REPO_NAME, REV, "SomeGoCode.go");
|
||||||
assertEquals(200, response.getStatus());
|
assertEquals(200, response.getStatus());
|
||||||
|
|
||||||
assertEquals("GO", response.getHeaderString("Language"));
|
assertEquals("GO", response.getHeaderString("X-Programming-Language"));
|
||||||
assertEquals("text/x-go", response.getHeaderString("Content-Type"));
|
assertEquals("text/x-go", response.getHeaderString("Content-Type"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ public class ContentResourceTest {
|
|||||||
Response response = contentResource.get(NAMESPACE, REPO_NAME, REV, "Dockerfile");
|
Response response = contentResource.get(NAMESPACE, REPO_NAME, REV, "Dockerfile");
|
||||||
assertEquals(200, response.getStatus());
|
assertEquals(200, response.getStatus());
|
||||||
|
|
||||||
assertEquals("DOCKERFILE", response.getHeaderString("Language"));
|
assertEquals("DOCKERFILE", response.getHeaderString("X-Programming-Language"));
|
||||||
assertEquals("text/plain", response.getHeaderString("Content-Type"));
|
assertEquals("text/plain", response.getHeaderString("Content-Type"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user