Improve a11y (#1841)

Improve accessibility by removing unnecessary tags without hrefs. Also remove many eslint errors and warnings.
This commit is contained in:
Eduard Heimbuch
2021-11-04 09:16:08 +01:00
committed by GitHub
parent 0efdd2a483
commit 6f61fefec5
213 changed files with 1924 additions and 2068 deletions

View File

@@ -0,0 +1,4 @@
- type: fixed
description: Fix <a> tags without hrefs ([#1841](https://github.com/scm-manager/scm-manager/pull/1841))
- type: fixed
description: Fix eslint errors and warnings ([#1841](https://github.com/scm-manager/scm-manager/pull/1841))

View File

@@ -32,7 +32,7 @@ import {
Loading,
Subtitle,
Level,
SubmitButton
SubmitButton,
} from "@scm-manager/ui-components";
type Props = WithTranslation & {
@@ -67,40 +67,40 @@ class RepositoryConfig extends React.Component<Props, State> {
nonFastForwardDisallowed: false,
changesSubmitted: false,
disabled: true,
changed: false
changed: false,
};
}
componentDidMount() {
const { repository } = this.props;
this.setState({
loadingBranches: true
loadingBranches: true,
});
const branchesLink = repository._links.branches as Link;
apiClient
.get(branchesLink.href)
.then(response => response.json())
.then(payload => payload._embedded.branches)
.then(branches =>
.then((response) => response.json())
.then((payload) => payload._embedded.branches)
.then((branches) =>
this.setState({
branches,
loadingBranches: false
loadingBranches: false,
})
)
.catch(error =>
.catch((error) =>
this.setState({
error
error,
})
);
const configurationLink = repository._links.configuration as Link;
this.setState({
loadingDefaultBranch: true
loadingDefaultBranch: true,
});
apiClient
.get(configurationLink.href)
.then(response => response.json())
.then(payload => {
.then((response) => response.json())
.then((payload) => {
const defaultBranch =
payload.defaultBranch || this.state.branches?.filter((b: Branch) => b.defaultBranch)[0]?.name;
this.setState({
@@ -108,12 +108,12 @@ class RepositoryConfig extends React.Component<Props, State> {
nonFastForwardDisallowed: payload.nonFastForwardDisallowed,
disabled: !payload._links.update,
loadingDefaultBranch: false,
changed: false
changed: false,
});
})
.catch(error =>
.catch((error) =>
this.setState({
error
error,
})
);
}
@@ -123,13 +123,13 @@ class RepositoryConfig extends React.Component<Props, State> {
this.setState({
selectedBranchName: "",
changesSubmitted: false,
changed: true
changed: true,
});
} else {
this.setState({
selectedBranchName: branch.name,
changesSubmitted: false,
changed: true
changed: true,
});
}
};
@@ -137,7 +137,7 @@ class RepositoryConfig extends React.Component<Props, State> {
onNonFastForwardDisallowed = (value: boolean) => {
this.setState({
nonFastForwardDisallowed: value,
changed: true
changed: true,
});
};
@@ -148,10 +148,10 @@ class RepositoryConfig extends React.Component<Props, State> {
const { selectedBranchName, nonFastForwardDisallowed } = this.state;
const newConfig = {
defaultBranch: selectedBranchName,
nonFastForwardDisallowed
nonFastForwardDisallowed,
};
this.setState({
submitPending: true
submitPending: true,
});
const configurationLink = repository._links.configuration as Link;
apiClient
@@ -160,12 +160,12 @@ class RepositoryConfig extends React.Component<Props, State> {
this.setState({
submitPending: false,
changesSubmitted: true,
changed: false
changed: false,
})
)
.catch(error =>
.catch((error) =>
this.setState({
error
error,
})
);
};
@@ -233,7 +233,7 @@ class RepositoryConfig extends React.Component<Props, State> {
onClick={() =>
this.setState({
changesSubmitted: false,
changed: false
changed: false,
})
}
/>

View File

@@ -31,14 +31,14 @@ describe("test git predicate", () => {
expect(gitPredicate({})).toBe(false);
expect(
gitPredicate({
repository: {}
repository: {},
})
).toBe(false);
expect(
gitPredicate({
repository: {
type: "hg"
}
type: "hg",
},
})
).toBe(false);
});
@@ -47,8 +47,8 @@ describe("test git predicate", () => {
expect(
gitPredicate({
repository: {
type: "git"
}
type: "git",
},
})
).toBe(true);
});

View File

@@ -50,7 +50,7 @@ class HgConfigurationForm extends React.Component<Props, State> {
super(props);
this.state = {
...props.initialConfiguration,
validationErrors: []
validationErrors: [],
};
}
@@ -66,7 +66,7 @@ class HgConfigurationForm extends React.Component<Props, State> {
}
this.setState({
validationErrors
validationErrors,
});
return validationErrors.length === 0;
@@ -83,7 +83,7 @@ class HgConfigurationForm extends React.Component<Props, State> {
this.setState(
// @ts-ignore
{
[name]: value
[name]: value,
},
() => this.props.onConfigurationChange(this.state, this.updateValidationStatus())
);
@@ -99,7 +99,7 @@ class HgConfigurationForm extends React.Component<Props, State> {
.then(() =>
apiClient
.get((this.props.initialConfiguration._links.self as Link).href)
.then(r => r.json())
.then((r) => r.json())
.then((config: Configuration) => this.setState({ hgBinary: config.hgBinary }))
)
.then(() => this.updateValidationStatus());

View File

@@ -52,7 +52,7 @@ const HgRepositoryConfigurationForm: FC<Props> = ({ repository }) => {
const encoding = value ? value : undefined;
setConfiguration({
...configuration,
encoding
encoding,
});
};

View File

@@ -41,11 +41,11 @@ export const useHgRepositoryConfiguration = (repository: Repository) => {
setLoading(true);
apiClient
.get(link)
.then(response => response.json())
.then((response) => response.json())
.then((config: HgRepositoryConfiguration) => {
setData(config);
})
.catch(e => setError(e))
.catch((e) => setError(e))
.finally(() => setLoading(false));
}
}, [link]);
@@ -53,7 +53,7 @@ export const useHgRepositoryConfiguration = (repository: Repository) => {
return {
isLoading,
error,
data
data,
};
};
@@ -73,7 +73,7 @@ export const useUpdateHgRepositoryConfiguration = () => {
apiClient
.put(link, configuration, "application/vnd.scmm-hgConfig-repo+json;v=2")
.then(() => setUpdated(true))
.catch(e => setError(e))
.catch((e) => setError(e))
.finally(() => setLoading(false));
};
@@ -81,6 +81,6 @@ export const useUpdateHgRepositoryConfiguration = () => {
isLoading,
error,
update,
updated
updated,
};
};

View File

@@ -45,7 +45,7 @@ class SvnConfigurationForm extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
...props.initialConfiguration
...props.initialConfiguration,
};
}
@@ -56,7 +56,7 @@ class SvnConfigurationForm extends React.Component<Props, State> {
this.setState(
// @ts-ignore
{
[name]: value
[name]: value,
},
() => this.props.onConfigurationChange(this.state, true)
);
@@ -73,7 +73,7 @@ class SvnConfigurationForm extends React.Component<Props, State> {
compatibilityOption = (value: string) => {
return {
value,
label: this.props.t("scm-svn-plugin.config.compatibility-values." + value.toLowerCase())
label: this.props.t("scm-svn-plugin.config.compatibility-values." + value.toLowerCase()),
};
};

View File

@@ -36,7 +36,7 @@ describe("ApiProvider tests", () => {
it("should register QueryClient", () => {
const { result } = renderHook(() => useQueryClient(), {
wrapper: createWrapper()
wrapper: createWrapper(),
});
expect(result.current).toBeDefined();
});
@@ -48,7 +48,7 @@ describe("ApiProvider tests", () => {
};
const { result } = renderHook(() => useLegacyContext(), {
wrapper: createWrapper({ onIndexFetched })
wrapper: createWrapper({ onIndexFetched }),
});
if (result.current?.onIndexFetched) {

View File

@@ -31,9 +31,9 @@ import { reset } from "./reset";
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false
}
}
retry: false,
},
},
});
type Props = LegacyContext & {

View File

@@ -34,7 +34,7 @@ describe("LegacyContext tests", () => {
it("should return provided context", () => {
const { result } = renderHook(() => useLegacyContext(), {
wrapper: createWrapper()
wrapper: createWrapper(),
});
expect(result.current).toBeDefined();
});

View File

@@ -35,7 +35,7 @@ describe("Test admin hooks", () => {
it("should get update info", async () => {
const updateInfo: UpdateInfo = {
latestVersion: "x.y.z",
link: "http://heartofgold@hitchhiker.com/x.y.z"
link: "http://heartofgold@hitchhiker.com/x.y.z",
};
fetchMock.getOnce("/api/v2/updateInfo", updateInfo);
@@ -43,7 +43,7 @@ describe("Test admin hooks", () => {
setIndexLink(queryClient, "updateInfo", "/updateInfo");
const { result, waitFor } = renderHook(() => useUpdateInfo(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => {
return !!result.current.data;

View File

@@ -45,9 +45,9 @@ describe("error handling tests", () => {
context: [
{
type: "planet",
id: "earth"
}
]
id: "earth",
},
],
};
afterEach(() => {
@@ -55,9 +55,9 @@ describe("error handling tests", () => {
fetchMock.restore();
});
it("should create a normal error, if the content type is not scmm-error", done => {
it("should create a normal error, if the content type is not scmm-error", (done) => {
fetchMock.getOnce("/api/v2/error", {
status: 404
status: 404,
});
apiClient.get("/error").catch((err: Error) => {
@@ -67,13 +67,13 @@ describe("error handling tests", () => {
});
});
it("should create an backend error, if the content type is scmm-error", done => {
it("should create an backend error, if the content type is scmm-error", (done) => {
fetchMock.getOnce("/api/v2/error", {
status: 404,
headers: {
"Content-Type": "application/vnd.scmm-error+json;v=2"
"Content-Type": "application/vnd.scmm-error+json;v=2",
},
body: earthNotFoundError
body: earthNotFoundError,
});
apiClient.get("/error").catch((err: BackendError) => {
@@ -87,8 +87,8 @@ describe("error handling tests", () => {
expect(err.context).toEqual([
{
type: "planet",
id: "earth"
}
id: "earth",
},
]);
done();
});

View File

@@ -30,7 +30,7 @@ import {
isBackendError,
TOKEN_EXPIRED_ERROR_CODE,
TokenExpiredError,
UnauthorizedError
UnauthorizedError,
} from "./errors";
type SubscriptionEvent = {
@@ -62,12 +62,7 @@ type SubscriptionArgument = MessageListeners | SubscriptionContext;
type Cancel = () => void;
const sessionId = (
Date.now().toString(36) +
Math.random()
.toString(36)
.substr(2, 5)
).toUpperCase();
const sessionId = (Date.now().toString(36) + Math.random().toString(36).substr(2, 5)).toUpperCase();
const extractXsrfTokenFromJwt = (jwt: string) => {
const parts = jwt.split(".");
@@ -102,7 +97,7 @@ const createRequestHeaders = () => {
// identify the web interface
"X-SCM-Client": "WUI",
// identify the window session
"X-SCM-Session-ID": sessionId
"X-SCM-Session-ID": sessionId,
};
const xsrf = extractXsrfToken();
@@ -112,10 +107,10 @@ const createRequestHeaders = () => {
return headers;
};
const applyFetchOptions: (p: RequestInit) => RequestInit = o => {
const applyFetchOptions: (p: RequestInit) => RequestInit = (o) => {
if (o.headers) {
o.headers = {
...createRequestHeaders()
...createRequestHeaders(),
};
} else {
o.headers = createRequestHeaders();
@@ -174,9 +169,7 @@ class ApiClient {
requestListeners: RequestListener[] = [];
get = (url: string): Promise<Response> => {
return this.request(url, applyFetchOptions({}))
.then(handleFailure)
.catch(this.notifyAndRethrow);
return this.request(url, applyFetchOptions({})).then(handleFailure).catch(this.notifyAndRethrow);
};
post = (
@@ -203,7 +196,7 @@ class ApiClient {
const options: RequestInit = {
method: "POST",
body: formData,
headers: additionalHeaders
headers: additionalHeaders,
};
return this.httpRequestWithBinaryBody(options, url);
};
@@ -214,22 +207,18 @@ class ApiClient {
head = (url: string) => {
let options: RequestInit = {
method: "HEAD"
method: "HEAD",
};
options = applyFetchOptions(options);
return this.request(url, options)
.then(handleFailure)
.catch(this.notifyAndRethrow);
return this.request(url, options).then(handleFailure).catch(this.notifyAndRethrow);
};
delete = (url: string): Promise<Response> => {
let options: RequestInit = {
method: "DELETE"
method: "DELETE",
};
options = applyFetchOptions(options);
return this.request(url, options)
.then(handleFailure)
.catch(this.notifyAndRethrow);
return this.request(url, options).then(handleFailure).catch(this.notifyAndRethrow);
};
httpRequestWithJSONBody = (
@@ -241,7 +230,7 @@ class ApiClient {
): Promise<Response> => {
const options: RequestInit = {
method: method,
headers: additionalHeaders
headers: additionalHeaders,
};
if (payload) {
options.body = JSON.stringify(payload);
@@ -257,7 +246,7 @@ class ApiClient {
) => {
const options: RequestInit = {
method: method,
headers: additionalHeaders
headers: additionalHeaders,
};
options.body = payload;
return this.httpRequestWithBinaryBody(options, url, "text/plain");
@@ -273,14 +262,12 @@ class ApiClient {
options.headers["Content-Type"] = contentType;
}
return this.request(url, options)
.then(handleFailure)
.catch(this.notifyAndRethrow);
return this.request(url, options).then(handleFailure).catch(this.notifyAndRethrow);
};
subscribe(url: string, argument: SubscriptionArgument): Cancel {
const es = new EventSource(createUrlWithIdentifiers(url), {
withCredentials: true
withCredentials: true,
});
let listeners: MessageListeners;
@@ -321,11 +308,11 @@ class ApiClient {
};
private notifyRequestListeners = (url: string, options: RequestInit) => {
this.requestListeners.forEach(requestListener => requestListener(url, options));
this.requestListeners.forEach((requestListener) => requestListener(url, options));
};
private notifyAndRethrow = (error: Error): never => {
this.errorListeners.forEach(errorListener => errorListener(error));
this.errorListeners.forEach((errorListener) => errorListener(error));
throw error;
};
}

View File

@@ -34,7 +34,7 @@ describe("Test base api hooks", () => {
describe("useIndex tests", () => {
fetchMock.get("/api/v2/", {
version: "x.y.z",
_links: {}
_links: {},
});
it("should return index", async () => {
@@ -48,9 +48,9 @@ describe("Test base api hooks", () => {
it("should call onIndexFetched of LegacyContext", async () => {
let index: IndexResources;
const context: LegacyContext = {
onIndexFetched: fetchedIndex => {
onIndexFetched: (fetchedIndex) => {
index = fetchedIndex;
}
},
};
const { result, waitFor } = renderHook(() => useIndex(), { wrapper: createWrapper(context) });
await waitFor(() => {
@@ -70,10 +70,10 @@ describe("Test base api hooks", () => {
const queryClient = new QueryClient();
queryClient.setQueryData("index", {
version: "x.y.z",
_links: {}
_links: {},
});
const { result } = renderHook(() => useIndexLink("spaceships"), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
expect(result.current).toBeUndefined();
});
@@ -86,17 +86,17 @@ describe("Test base api hooks", () => {
spaceships: [
{
name: "heartOfGold",
href: "/spaceships/heartOfGold"
href: "/spaceships/heartOfGold",
},
{
name: "razorCrest",
href: "/spaceships/razorCrest"
}
]
}
href: "/spaceships/razorCrest",
},
],
},
});
const { result } = renderHook(() => useIndexLink("spaceships"), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
expect(result.current).toBeUndefined();
});
@@ -107,12 +107,12 @@ describe("Test base api hooks", () => {
version: "x.y.z",
_links: {
spaceships: {
href: "/api/spaceships"
}
}
href: "/api/spaceships",
},
},
});
const { result } = renderHook(() => useIndexLink("spaceships"), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
expect(result.current).toBe("/api/spaceships");
});
@@ -130,12 +130,12 @@ describe("Test base api hooks", () => {
version: "x.y.z",
_links: {
spaceships: {
href: "/api/spaceships"
}
}
href: "/api/spaceships",
},
},
});
const { result } = renderHook(() => useIndexLinks(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
expect((result.current!.spaceships as Link).href).toBe("/api/spaceships");
});
@@ -150,10 +150,10 @@ describe("Test base api hooks", () => {
it("should return version", () => {
const queryClient = new QueryClient();
queryClient.setQueryData("index", {
version: "x.y.z"
version: "x.y.z",
});
const { result } = renderHook(() => useVersion(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
expect(result.current).toBe("x.y.z");
});
@@ -164,10 +164,10 @@ describe("Test base api hooks", () => {
const queryClient = new QueryClient();
queryClient.setQueryData("index", {
version: "x.y.z",
_links: {}
_links: {},
});
const { result } = renderHook(() => useRequiredIndexLink("spaceships"), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
expect(result.error).toBeDefined();
});
@@ -178,12 +178,12 @@ describe("Test base api hooks", () => {
version: "x.y.z",
_links: {
spaceships: {
href: "/api/spaceships"
}
}
href: "/api/spaceships",
},
},
});
const { result } = renderHook(() => useRequiredIndexLink("spaceships"), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
expect(result.current).toBe("/api/spaceships");
});
@@ -196,19 +196,19 @@ describe("Test base api hooks", () => {
version: "x.y.z",
_links: {
spaceships: {
href: "/spaceships"
}
}
href: "/spaceships",
},
},
});
const spaceship = {
name: "heartOfGold"
name: "heartOfGold",
};
fetchMock.get("/api/v2/spaceships", spaceship);
const { result, waitFor } = renderHook(() => useIndexJsonResource<typeof spaceship>("spaceships"), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => {
@@ -223,11 +223,11 @@ describe("Test base api hooks", () => {
const queryClient = new QueryClient();
queryClient.setQueryData("index", {
version: "x.y.z",
_links: {}
_links: {},
});
const { result } = renderHook(() => useIndexJsonResource<{}>("spaceships"), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
expect(result.current.isLoading).toBe(false);

View File

@@ -60,9 +60,9 @@ describe("Test config hooks", () => {
skipFailedAuthenticators: false,
_links: {
update: {
href: "/config"
}
}
href: "/config",
},
},
};
afterEach(() => {
@@ -75,7 +75,7 @@ describe("Test config hooks", () => {
setIndexLink(queryClient, "config", "/config");
fetchMock.get("/api/v2/config", config);
const { result, waitFor } = renderHook(() => useConfig(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(config);
@@ -89,15 +89,15 @@ describe("Test config hooks", () => {
const newConfig = {
...config,
baseUrl: "/hog"
baseUrl: "/hog",
};
fetchMock.putOnce("/api/v2/config", {
status: 200
status: 200,
});
const { result, waitForNextUpdate } = renderHook(() => useUpdateConfig(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await act(() => {

View File

@@ -30,20 +30,20 @@ import { requiredLink } from "./links";
export const useConfig = (): ApiResult<Config> => {
const indexLink = useIndexLink("config");
return useQuery<Config, Error>("config", () => apiClient.get(indexLink!).then(response => response.json()), {
enabled: !!indexLink
return useQuery<Config, Error>("config", () => apiClient.get(indexLink!).then((response) => response.json()), {
enabled: !!indexLink,
});
};
export const useUpdateConfig = () => {
const queryClient = useQueryClient();
const { mutate, isLoading, error, data, reset } = useMutation<unknown, Error, Config>(
config => {
(config) => {
const updateUrl = requiredLink(config, "update");
return apiClient.put(updateUrl, config, "application/vnd.scmm-config+json;v=2");
},
{
onSuccess: () => queryClient.invalidateQueries("config")
onSuccess: () => queryClient.invalidateQueries("config"),
}
);
return {
@@ -51,6 +51,6 @@ export const useUpdateConfig = () => {
isLoading,
error,
isUpdated: !!data,
reset
reset,
};
};

View File

@@ -50,26 +50,25 @@ describe("Test diff", () => {
content: "0",
type: "insert",
lineNumber: 1,
isInsert: true
}
]
}
isInsert: true,
},
],
},
],
_links: {
lines: {
href:
"/api/v2/repositories/scmadmin/HeartOfGold-git/content/one_to_onehundred/0.txt?start={start}&end={end}",
templated: true
}
}
}
href: "/api/v2/repositories/scmadmin/HeartOfGold-git/content/one_to_onehundred/0.txt?start={start}&end={end}",
templated: true,
},
},
},
],
partial: false,
_links: {
self: {
href: "/api/v2/diff"
}
}
href: "/api/v2/diff",
},
},
};
const partialDiff1: Diff = {
@@ -93,29 +92,28 @@ describe("Test diff", () => {
content: "0",
type: "insert",
lineNumber: 1,
isInsert: true
}
]
}
isInsert: true,
},
],
},
],
_links: {
lines: {
href:
"/api/v2/repositories/scmadmin/HeartOfGold-git/content/one_to_onehundred/0.txt?start={start}&end={end}",
templated: true
}
}
}
href: "/api/v2/repositories/scmadmin/HeartOfGold-git/content/one_to_onehundred/0.txt?start={start}&end={end}",
templated: true,
},
},
},
],
partial: true,
_links: {
self: {
href: "/diff"
href: "/diff",
},
next: {
href: "/diff?offset=1&limit=1"
}
}
href: "/diff?offset=1&limit=1",
},
},
};
const partialDiff2: Diff = {
@@ -139,26 +137,25 @@ describe("Test diff", () => {
content: "1",
type: "insert",
lineNumber: 1,
isInsert: true
}
]
}
isInsert: true,
},
],
},
],
_links: {
lines: {
href:
"/api/v2/repositories/scmadmin/HeartOfGold-git/content/one_to_onehundred/1.txt?start={start}&end={end}",
templated: true
}
}
}
href: "/api/v2/repositories/scmadmin/HeartOfGold-git/content/one_to_onehundred/1.txt?start={start}&end={end}",
templated: true,
},
},
},
],
partial: false,
_links: {
self: {
href: "/diff"
}
}
href: "/diff",
},
},
};
beforeEach(() => {
@@ -168,10 +165,10 @@ describe("Test diff", () => {
it("should return simple parsed diff", async () => {
fetchMock.getOnce("/api/v2/diff", {
body: simpleDiff,
headers: { "Content-Type": "application/vnd.scmm-diffparsed+json;v=2" }
headers: { "Content-Type": "application/vnd.scmm-diffparsed+json;v=2" },
});
const { result, waitFor } = renderHook(() => useDiff("/diff"), {
wrapper: createWrapper()
wrapper: createWrapper(),
});
await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(simpleDiff);
@@ -188,10 +185,10 @@ describe("Test diff", () => {
+i am new!
\\ No newline at end of file
`,
headers: { "Content-Type": "text/plain" }
headers: { "Content-Type": "text/plain" },
});
const { result, waitFor } = renderHook(() => useDiff("/diff"), {
wrapper: createWrapper()
wrapper: createWrapper(),
});
await waitFor(() => !!result.current.data);
expect(result.current.data?.files).toHaveLength(1);
@@ -200,14 +197,14 @@ describe("Test diff", () => {
it("should return parsed diff in multiple chunks", async () => {
fetchMock.getOnce("/api/v2/diff?limit=1", {
body: partialDiff1,
headers: { "Content-Type": "application/vnd.scmm-diffparsed+json;v=2" }
headers: { "Content-Type": "application/vnd.scmm-diffparsed+json;v=2" },
});
fetchMock.getOnce("/api/v2/diff?offset=1&limit=1", {
body: partialDiff2,
headers: { "Content-Type": "application/vnd.scmm-diffparsed+json;v=2" }
headers: { "Content-Type": "application/vnd.scmm-diffparsed+json;v=2" },
});
const { result, waitFor, waitForNextUpdate } = renderHook(() => useDiff("/diff?limit=1"), {
wrapper: createWrapper()
wrapper: createWrapper(),
});
await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(partialDiff1);
@@ -226,10 +223,10 @@ describe("Test diff", () => {
it("should append query parameters to url which has already query params", async () => {
fetchMock.getOnce("/api/v2/diff?format=GIT&limit=25", {
body: simpleDiff,
headers: { "Content-Type": "application/vnd.scmm-diffparsed+json;v=2" }
headers: { "Content-Type": "application/vnd.scmm-diffparsed+json;v=2" },
});
const { result, waitFor } = renderHook(() => useDiff("/diff?format=GIT", { limit: 25 }), {
wrapper: createWrapper()
wrapper: createWrapper(),
});
await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(simpleDiff);

View File

@@ -32,10 +32,10 @@ describe("test createBackendError", () => {
context: [
{
type: "planet",
id: "earth"
}
id: "earth",
},
],
violations: []
violations: [],
};
it("should return a default backend error", () => {

View File

@@ -40,21 +40,21 @@ describe("Test group hooks", () => {
type: "xml",
_links: {
delete: {
href: "/groups/jedis"
href: "/groups/jedis",
},
update: {
href: "/groups/jedis"
}
href: "/groups/jedis",
},
},
_embedded: {
members: []
}
members: [],
},
};
const jedisCollection = {
_embedded: {
groups: [jedis]
}
groups: [jedis],
},
};
afterEach(() => {
@@ -67,7 +67,7 @@ describe("Test group hooks", () => {
setIndexLink(queryClient, "groups", "/groups");
fetchMock.get("/api/v2/groups", jedisCollection);
const { result, waitFor } = renderHook(() => useGroups(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(jedisCollection);
@@ -78,11 +78,11 @@ describe("Test group hooks", () => {
setIndexLink(queryClient, "groups", "/groups");
fetchMock.get("/api/v2/groups", jedisCollection, {
query: {
page: "42"
}
page: "42",
},
});
const { result, waitFor } = renderHook(() => useGroups({ page: 42 }), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(jedisCollection);
@@ -93,11 +93,11 @@ describe("Test group hooks", () => {
setIndexLink(queryClient, "groups", "/groups");
fetchMock.get("/api/v2/groups", jedisCollection, {
query: {
q: "jedis"
}
q: "jedis",
},
});
const { result, waitFor } = renderHook(() => useGroups({ search: "jedis" }), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(jedisCollection);
@@ -108,7 +108,7 @@ describe("Test group hooks", () => {
setIndexLink(queryClient, "groups", "/groups");
fetchMock.get("/api/v2/groups", jedisCollection);
const { result, waitFor } = renderHook(() => useGroups(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => !!result.current.data);
expect(queryClient.getQueryData(["group", "jedis"])).toEqual(jedis);
@@ -121,7 +121,7 @@ describe("Test group hooks", () => {
setIndexLink(queryClient, "groups", "/groups");
fetchMock.get("/api/v2/groups/jedis", jedis);
const { result, waitFor } = renderHook(() => useGroup("jedis"), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(jedis);
@@ -136,14 +136,14 @@ describe("Test group hooks", () => {
fetchMock.postOnce("/api/v2/groups", {
status: 201,
headers: {
Location: "/groups/jedis"
}
Location: "/groups/jedis",
},
});
fetchMock.getOnce("/api/v2/groups/jedis", jedis);
const { result, waitForNextUpdate } = renderHook(() => useCreateGroup(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await act(() => {
@@ -160,13 +160,13 @@ describe("Test group hooks", () => {
setIndexLink(queryClient, "groups", "/groups");
fetchMock.postOnce("/api/v2/groups", {
status: 201
status: 201,
});
fetchMock.getOnce("/api/v2/groups/jedis", jedis);
const { result, waitForNextUpdate } = renderHook(() => useCreateGroup(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await act(() => {
@@ -185,11 +185,11 @@ describe("Test group hooks", () => {
setIndexLink(queryClient, "groups", "/groups");
fetchMock.deleteOnce("/api/v2/groups/jedis", {
status: 200
status: 200,
});
const { result, waitForNextUpdate } = renderHook(() => useDeleteGroup(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await act(() => {
@@ -212,17 +212,17 @@ describe("Test group hooks", () => {
const newJedis = {
...jedis,
description: "may the 4th be with you"
description: "may the 4th be with you",
};
fetchMock.putOnce("/api/v2/groups/jedis", {
status: 200
status: 200,
});
fetchMock.getOnce("/api/v2/groups/jedis", newJedis);
const { result, waitForNextUpdate } = renderHook(() => useUpdateGroup(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await act(() => {

View File

@@ -29,9 +29,9 @@ describe("requireLink tests", () => {
{
_links: {
spaceship: {
href: "/v2/ship"
}
}
href: "/v2/ship",
},
},
},
"spaceship"
);
@@ -49,14 +49,14 @@ describe("requireLink tests", () => {
spaceship: [
{
name: "one",
href: "/v2/one"
href: "/v2/one",
},
{
name: "two",
href: "/v2/two"
}
]
}
href: "/v2/two",
},
],
},
};
expect(() => requiredLink(object, "spaceship")).toThrowError();
});
@@ -67,14 +67,14 @@ describe("requireLink tests", () => {
spaceship: [
{
name: "one",
href: "/v2/one"
href: "/v2/one",
},
{
name: "two",
href: "/v2/two"
}
]
}
href: "/v2/two",
},
],
},
};
expect(requiredLink(object, "spaceship", "one")).toBe("/v2/one");
});
@@ -85,14 +85,14 @@ describe("requireLink tests", () => {
spaceship: [
{
name: "one",
href: "/v2/one"
href: "/v2/one",
},
{
name: "two",
href: "/v2/two"
}
]
}
href: "/v2/two",
},
],
},
};
expect(() => requiredLink(object, "spaceship", "three")).toThrowError();
});

View File

@@ -37,7 +37,7 @@ describe("Test login hooks", () => {
name: "tricia",
displayName: "Tricia",
groups: [],
_links: {}
_links: {},
};
describe("useMe tests", () => {
@@ -45,7 +45,7 @@ describe("Test login hooks", () => {
name: "tricia",
displayName: "Tricia",
groups: [],
_links: {}
_links: {},
});
it("should return me", async () => {
@@ -65,9 +65,9 @@ describe("Test login hooks", () => {
let me: Me;
const context: LegacyContext = {
onMeFetched: fetchedMe => {
onMeFetched: (fetchedMe) => {
me = fetchedMe;
}
},
};
const { result, waitFor } = renderHook(() => useMe(), { wrapper: createWrapper(context, queryClient) });
@@ -130,7 +130,7 @@ describe("Test login hooks", () => {
name: "_anonymous",
displayName: "Anonymous",
groups: [],
_links: {}
_links: {},
});
const { result } = renderHook(() => useSubject(), { wrapper: createWrapper(undefined, queryClient) });
@@ -158,8 +158,8 @@ describe("Test login hooks", () => {
cookie: true,
grant_type: "password",
username: "tricia",
password: "hitchhikersSecret!"
}
password: "hitchhikersSecret!",
},
});
// required because we invalidate the whole cache and react-query refetches the index
@@ -167,13 +167,13 @@ describe("Test login hooks", () => {
version: "x.y.z",
_links: {
login: {
href: "/second/login"
}
}
href: "/second/login",
},
},
});
const { result, waitForNextUpdate } = renderHook(() => useLogin(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
const { login } = result.current;
expect(login).toBeDefined();
@@ -194,7 +194,7 @@ describe("Test login hooks", () => {
queryClient.setQueryData("me", tricia);
const { result } = renderHook(() => useLogin(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
expect(result.current.login).toBeUndefined();
@@ -209,7 +209,7 @@ describe("Test login hooks", () => {
fetchMock.deleteOnce("/api/v2/logout", {});
const { result, waitForNextUpdate } = renderHook(() => useLogout(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
const { logout } = result.current;
expect(logout).toBeDefined();
@@ -229,7 +229,7 @@ describe("Test login hooks", () => {
setEmptyIndex(queryClient);
const { result } = renderHook(() => useLogout(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
const { logout } = result.current;

View File

@@ -32,13 +32,13 @@ import { useReset } from "./reset";
export const useMe = (): ApiResult<Me> => {
const legacy = useLegacyContext();
const link = useIndexLink("me");
return useQuery<Me, Error>("me", () => apiClient.get(link!).then(response => response.json()), {
return useQuery<Me, Error>("me", () => apiClient.get(link!).then((response) => response.json()), {
enabled: !!link,
onSuccess: me => {
onSuccess: (me) => {
if (legacy.onMeFetched) {
legacy.onMeFetched(me);
}
}
},
});
};
@@ -60,7 +60,7 @@ export const useSubject = () => {
isAnonymous,
isLoading,
error,
me
me,
};
};
@@ -75,9 +75,9 @@ export const useLogin = () => {
const link = useIndexLink("login");
const reset = useReset();
const { mutate, isLoading, error } = useMutation<unknown, Error, Credentials>(
credentials => apiClient.post(link!, credentials),
(credentials) => apiClient.post(link!, credentials),
{
onSuccess: reset
onSuccess: reset,
}
);
@@ -91,7 +91,7 @@ export const useLogin = () => {
return {
login: link ? login : undefined,
isLoading,
error
error,
};
};
@@ -104,14 +104,14 @@ export const useLogout = () => {
const reset = useReset();
const { mutate, isLoading, error, data } = useMutation<LogoutResponse, Error, unknown>(
() => apiClient.delete(link!).then(r => (r.status === 200 ? r.json() : {})),
() => apiClient.delete(link!).then((r) => (r.status === 200 ? r.json() : {})),
{
onSuccess: response => {
onSuccess: (response) => {
if (response?.logoutRedirect) {
window.location.assign(response.logoutRedirect);
}
return reset();
}
},
}
);
@@ -122,6 +122,6 @@ export const useLogout = () => {
return {
logout: link && !data ? logout : undefined,
isLoading,
error
error,
};
};

View File

@@ -38,14 +38,14 @@ describe("Test namespace hooks", () => {
namespaces: [
{
namespace: "spaceships",
_links: {}
}
]
}
_links: {},
},
],
},
});
const { result, waitFor } = renderHook(() => useNamespaces(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => {
return !!result.current.data;
@@ -61,11 +61,11 @@ describe("Test namespace hooks", () => {
fetchMock.get("/api/v2/ns", {
current: "awesome",
available: [],
_links: {}
_links: {},
});
const { result, waitFor } = renderHook(() => useNamespaceStrategies(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => {
return !!result.current.data;
@@ -80,11 +80,11 @@ describe("Test namespace hooks", () => {
setIndexLink(queryClient, "namespaces", "/ns");
fetchMock.get("/api/v2/ns/awesome", {
namespace: "awesome",
_links: {}
_links: {},
});
const { result, waitFor } = renderHook(() => useNamespace("awesome"), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => {
return !!result.current.data;

View File

@@ -34,7 +34,7 @@ export const useNamespaces = () => {
export const useNamespace = (name: string): ApiResult<Namespace> => {
const namespacesLink = useRequiredIndexLink("namespaces");
return useQuery<Namespace, Error>(["namespace", name], () =>
apiClient.get(concat(namespacesLink, name)).then(response => response.json())
apiClient.get(concat(namespacesLink, name)).then((response) => response.json())
);
};

View File

@@ -40,26 +40,28 @@ const waitForRestartAfter = (
const endTime = Number(new Date()) + 60000;
let started = false;
const executor = <T = any>(data: T) => (resolve: (result: T) => void, reject: (error: Error) => void) => {
// we need some initial delay
if (!started) {
started = true;
setTimeout(executor(data), initialDelay, resolve, reject);
} else {
apiClient
.get("")
.then(() => resolve(data))
.catch(() => {
if (Number(new Date()) < endTime) {
setTimeout(executor(data), timeout, resolve, reject);
} else {
reject(new Error("timeout reached"));
}
});
}
};
const executor =
<T = any>(data: T) =>
(resolve: (result: T) => void, reject: (error: Error) => void) => {
// we need some initial delay
if (!started) {
started = true;
setTimeout(executor(data), initialDelay, resolve, reject);
} else {
apiClient
.get("")
.then(() => resolve(data))
.catch(() => {
if (Number(new Date()) < endTime) {
setTimeout(executor(data), timeout, resolve, reject);
} else {
reject(new Error("timeout reached"));
}
});
}
};
return promise.then(data => new Promise<void>(executor(data)));
return promise.then((data) => new Promise<void>(executor(data)));
};
export type UseAvailablePluginsOptions = {
@@ -70,10 +72,10 @@ export const useAvailablePlugins = ({ enabled }: UseAvailablePluginsOptions = {}
const indexLink = useRequiredIndexLink("availablePlugins");
return useQuery<PluginCollection, Error>(
["plugins", "available"],
() => apiClient.get(indexLink).then(response => response.json()),
() => apiClient.get(indexLink).then((response) => response.json()),
{
enabled,
retry: 3
retry: 3,
}
);
};
@@ -86,10 +88,10 @@ export const useInstalledPlugins = ({ enabled }: UseInstalledPluginsOptions = {}
const indexLink = useRequiredIndexLink("installedPlugins");
return useQuery<PluginCollection, Error>(
["plugins", "installed"],
() => apiClient.get(indexLink).then(response => response.json()),
() => apiClient.get(indexLink).then((response) => response.json()),
{
enabled,
retry: 3
retry: 3,
}
);
};
@@ -98,10 +100,10 @@ export const usePendingPlugins = (): ApiResult<PendingPlugins> => {
const indexLink = useIndexLink("pendingPlugins");
return useQuery<PendingPlugins, Error>(
["plugins", "pending"],
() => apiClient.get(indexLink!).then(response => response.json()),
() => apiClient.get(indexLink!).then((response) => response.json()),
{
enabled: !!indexLink,
retry: 3
retry: 3,
}
);
};
@@ -133,19 +135,19 @@ export const useInstallPlugin = () => {
return promise;
},
{
onSuccess: () => queryClient.invalidateQueries("plugins")
onSuccess: () => queryClient.invalidateQueries("plugins"),
}
);
return {
install: (plugin: Plugin, restartOptions: RestartOptions = {}) =>
mutate({
plugin,
restartOptions
restartOptions,
}),
isLoading,
error,
data,
isInstalled: !!data
isInstalled: !!data,
};
};
@@ -160,18 +162,18 @@ export const useUninstallPlugin = () => {
return promise;
},
{
onSuccess: () => queryClient.invalidateQueries("plugins")
onSuccess: () => queryClient.invalidateQueries("plugins"),
}
);
return {
uninstall: (plugin: Plugin, restartOptions: RestartOptions = {}) =>
mutate({
plugin,
restartOptions
restartOptions,
}),
isLoading,
error,
isUninstalled: !!data
isUninstalled: !!data,
};
};
@@ -194,18 +196,18 @@ export const useUpdatePlugins = () => {
return promise;
},
{
onSuccess: () => queryClient.invalidateQueries("plugins")
onSuccess: () => queryClient.invalidateQueries("plugins"),
}
);
return {
update: (plugin: Plugin | PluginCollection, restartOptions: RestartOptions = {}) =>
mutate({
plugins: plugin,
restartOptions
restartOptions,
}),
isLoading,
error,
isUpdated: !!data
isUpdated: !!data,
};
};
@@ -220,7 +222,7 @@ export const useExecutePendingPlugins = () => {
({ pending, restartOptions }) =>
waitForRestartAfter(apiClient.post(requiredLink(pending, "execute")), restartOptions),
{
onSuccess: () => queryClient.invalidateQueries("plugins")
onSuccess: () => queryClient.invalidateQueries("plugins"),
}
);
return {
@@ -228,22 +230,22 @@ export const useExecutePendingPlugins = () => {
mutate({ pending, restartOptions }),
isLoading,
error,
isExecuted: !!data
isExecuted: !!data,
};
};
export const useCancelPendingPlugins = () => {
const queryClient = useQueryClient();
const { mutate, isLoading, error, data } = useMutation<unknown, Error, PendingPlugins>(
pending => apiClient.post(requiredLink(pending, "cancel")),
(pending) => apiClient.post(requiredLink(pending, "cancel")),
{
onSuccess: () => queryClient.invalidateQueries("plugins")
onSuccess: () => queryClient.invalidateQueries("plugins"),
}
);
return {
update: (pending: PendingPlugins) => mutate(pending),
isLoading,
error,
isCancelled: !!data
isCancelled: !!data,
};
};

View File

@@ -32,8 +32,9 @@ import { act } from "react-test-renderer";
import {
useCreateRepositoryRole,
useDeleteRepositoryRole,
useRepositoryRole, useRepositoryRoles,
useUpdateRepositoryRole
useRepositoryRole,
useRepositoryRoles,
useUpdateRepositoryRole,
} from "./repository-roles";
describe("Test repository-roles hooks", () => {
@@ -43,12 +44,12 @@ describe("Test repository-roles hooks", () => {
verbs: ["rocking"],
_links: {
delete: {
href: "/repositoryRoles/theroleingstones"
href: "/repositoryRoles/theroleingstones",
},
update: {
href: "/repositoryRoles/theroleingstones"
}
}
href: "/repositoryRoles/theroleingstones",
},
},
};
const roleCollection: RepositoryRoleCollection = {
@@ -56,8 +57,8 @@ describe("Test repository-roles hooks", () => {
pageTotal: 0,
_links: {},
_embedded: {
repositoryRoles: [role]
}
repositoryRoles: [role],
},
};
afterEach(() => {
@@ -70,7 +71,7 @@ describe("Test repository-roles hooks", () => {
setIndexLink(queryClient, "repositoryRoles", "/repositoryRoles");
fetchMock.get("/api/v2/repositoryRoles", roleCollection);
const { result, waitFor } = renderHook(() => useRepositoryRoles(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(roleCollection);
@@ -81,11 +82,11 @@ describe("Test repository-roles hooks", () => {
setIndexLink(queryClient, "repositoryRoles", "/repositoryRoles");
fetchMock.get("/api/v2/repositoryRoles", roleCollection, {
query: {
page: "42"
}
page: "42",
},
});
const { result, waitFor } = renderHook(() => useRepositoryRoles({ page: 42 }), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(roleCollection);
@@ -96,7 +97,7 @@ describe("Test repository-roles hooks", () => {
setIndexLink(queryClient, "repositoryRoles", "/repositoryRoles");
fetchMock.get("/api/v2/repositoryRoles", roleCollection);
const { result, waitFor } = renderHook(() => useRepositoryRoles(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => !!result.current.data);
expect(queryClient.getQueryData(["repositoryRole", roleName])).toEqual(role);
@@ -109,7 +110,7 @@ describe("Test repository-roles hooks", () => {
setIndexLink(queryClient, "repositoryRoles", "/repositoryRoles");
fetchMock.get("/api/v2/repositoryRoles/" + roleName, role);
const { result, waitFor } = renderHook(() => useRepositoryRole(roleName), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(role);
@@ -124,14 +125,14 @@ describe("Test repository-roles hooks", () => {
fetchMock.postOnce("/api/v2/repositoryRoles", {
status: 201,
headers: {
Location: "/repositoryRoles/" + roleName
}
Location: "/repositoryRoles/" + roleName,
},
});
fetchMock.getOnce("/api/v2/repositoryRoles/" + roleName, role);
const { result, waitForNextUpdate } = renderHook(() => useCreateRepositoryRole(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await act(() => {
@@ -148,13 +149,13 @@ describe("Test repository-roles hooks", () => {
setIndexLink(queryClient, "repositoryRoles", "/repositoryRoles");
fetchMock.postOnce("/api/v2/repositoryRoles", {
status: 201
status: 201,
});
fetchMock.getOnce("/api/v2/repositoryRoles/" + roleName, role);
const { result, waitForNextUpdate } = renderHook(() => useCreateRepositoryRole(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await act(() => {
@@ -173,11 +174,11 @@ describe("Test repository-roles hooks", () => {
setIndexLink(queryClient, "repositoryRoles", "/repositoryRoles");
fetchMock.deleteOnce("/api/v2/repositoryRoles/" + roleName, {
status: 200
status: 200,
});
const { result, waitForNextUpdate } = renderHook(() => useDeleteRepositoryRole(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await act(() => {
@@ -200,15 +201,15 @@ describe("Test repository-roles hooks", () => {
const newRole: RepositoryRole = {
...role,
name: "newname"
name: "newname",
};
fetchMock.putOnce("/api/v2/repositoryRoles/" + roleName, {
status: 200
status: 200,
});
const { result, waitForNextUpdate } = renderHook(() => useUpdateRepositoryRole(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await act(() => {

View File

@@ -25,7 +25,7 @@ import { QueryClient, useQueryClient } from "react-query";
export const reset = (queryClient: QueryClient) => {
queryClient.removeQueries({
predicate: ({ queryKey }) => queryKey !== "index"
predicate: ({ queryKey }) => queryKey !== "index",
});
return queryClient.invalidateQueries("index");
};

View File

@@ -35,9 +35,9 @@ describe("Test sources hooks", () => {
type: "git",
_links: {
sources: {
href: "/src"
}
}
href: "/src",
},
},
};
const readmeMd: File = {
@@ -49,8 +49,8 @@ describe("Test sources hooks", () => {
description: "Awesome readme",
_links: {},
_embedded: {
children: []
}
children: [],
},
};
const rootDirectory: File = {
@@ -60,8 +60,8 @@ describe("Test sources hooks", () => {
revision: "abc",
_links: {},
_embedded: {
children: [readmeMd]
}
children: [readmeMd],
},
};
const sepecialMd: File = {
@@ -73,20 +73,20 @@ describe("Test sources hooks", () => {
description: "Awesome special file",
_links: {},
_embedded: {
children: []
}
children: [],
},
};
const sepecialMdPartial: File = {
...sepecialMd,
partialResult: true,
computationAborted: false
computationAborted: false,
};
const sepecialMdComputationAborted: File = {
...sepecialMd,
partialResult: true,
computationAborted: true
computationAborted: true,
};
const mainDirectoryTruncated: File = {
@@ -97,20 +97,20 @@ describe("Test sources hooks", () => {
truncated: true,
_links: {
proceed: {
href: "src/2"
}
href: "src/2",
},
},
_embedded: {
children: []
}
children: [],
},
};
const mainDirectory: File = {
...mainDirectoryTruncated,
truncated: false,
_embedded: {
children: [sepecialMd]
}
children: [sepecialMd],
},
};
beforeEach(() => {
@@ -128,7 +128,7 @@ describe("Test sources hooks", () => {
const queryClient = createInfiniteCachingClient();
fetchMock.getOnce("/api/v2/src", rootDirectory);
const { result, waitFor } = renderHook(() => useSources(puzzle42), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(rootDirectory);
@@ -138,7 +138,7 @@ describe("Test sources hooks", () => {
const queryClient = createInfiniteCachingClient();
fetchMock.getOnce("/api/v2/src/abc/README.md", readmeMd);
const { result, waitFor } = renderHook(() => useSources(puzzle42, { revision: "abc", path: "README.md" }), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(readmeMd);
@@ -149,7 +149,7 @@ describe("Test sources hooks", () => {
fetchMock.getOnce("/api/v2/src", mainDirectoryTruncated);
fetchMock.getOnce("/api/v2/src/2", mainDirectory);
const { result, waitFor, waitForNextUpdate } = renderHook(() => useSources(puzzle42), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => !!result.current.data);
@@ -172,11 +172,11 @@ describe("Test sources hooks", () => {
{
...mainDirectory,
_embedded: {
children: [sepecialMdPartial]
}
children: [sepecialMdPartial],
},
},
{
repeat: 1
repeat: 1,
}
);
fetchMock.get(
@@ -184,17 +184,17 @@ describe("Test sources hooks", () => {
{
...mainDirectory,
_embedded: {
children: [sepecialMd]
}
children: [sepecialMd],
},
},
{
repeat: 1,
overwriteRoutes: false
overwriteRoutes: false,
}
);
const { result, waitFor } = renderHook(() => useSources(puzzle42, { refetchPartialInterval: 100 }), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => !!firstChild(result.current.data));
@@ -210,23 +210,23 @@ describe("Test sources hooks", () => {
// should never be called
fetchMock.getOnce("/api/v2/src/abc/main/special.md", sepecialMd, {
repeat: 1,
overwriteRoutes: false
overwriteRoutes: false,
});
const { result, waitFor } = renderHook(
() =>
useSources(puzzle42, {
revision: "abc",
path: "main/special.md",
refetchPartialInterval: 100
refetchPartialInterval: 100,
}),
{
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
}
);
await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(sepecialMdComputationAborted);
await new Promise(r => setTimeout(r, 200));
await new Promise((r) => setTimeout(r, 200));
expect(result.current.data).toEqual(sepecialMdComputationAborted);
});
});

View File

@@ -37,25 +37,25 @@ export type UseSourcesOptions = {
const UseSourcesDefaultOptions: UseSourcesOptions = {
enabled: true,
refetchPartialInterval: 3000
refetchPartialInterval: 3000,
};
export const useSources = (repository: Repository, opts: UseSourcesOptions = UseSourcesDefaultOptions) => {
const options = {
...UseSourcesDefaultOptions,
...opts
...opts,
};
const link = createSourcesLink(repository, options);
const { isLoading, error, data, isFetchingNextPage, fetchNextPage, refetch } = useInfiniteQuery<File, Error, File>(
repoQueryKey(repository, "sources", options.revision || "", options.path || ""),
({ pageParam }) => {
return apiClient.get(pageParam || link).then(response => response.json());
return apiClient.get(pageParam || link).then((response) => response.json());
},
{
enabled: options.enabled,
getNextPageParam: lastPage => {
getNextPageParam: (lastPage) => {
return (lastPage._links.proceed as Link)?.href;
}
},
}
);
@@ -64,7 +64,7 @@ export const useSources = (repository: Repository, opts: UseSourcesOptions = Use
const intervalId = setInterval(() => {
if (isPartial(file)) {
refetch({
throwOnError: true
throwOnError: true,
});
}
}, options.refetchPartialInterval);
@@ -79,7 +79,7 @@ export const useSources = (repository: Repository, opts: UseSourcesOptions = Use
fetchNextPage: () => {
// wrapped because we do not want to leak react-query types in our api
fetchNextPage();
}
},
};
};
@@ -108,8 +108,8 @@ const merge = (files?: File[]): File | undefined => {
...lastPage,
_embedded: {
...lastPage._embedded,
children
}
children,
},
};
};

View File

@@ -36,9 +36,9 @@ describe("Test Tag hooks", () => {
type: "git",
_links: {
tags: {
href: "/hog/tags"
}
}
href: "/hog/tags",
},
},
};
const changeset: Changeset = {
@@ -46,14 +46,14 @@ describe("Test Tag hooks", () => {
description: "Awesome change",
date: new Date(),
author: {
name: "Arthur Dent"
name: "Arthur Dent",
},
_embedded: {},
_links: {
tag: {
href: "/hog/tag"
}
}
href: "/hog/tag",
},
},
};
const tagOneDotZero = {
@@ -61,17 +61,17 @@ describe("Test Tag hooks", () => {
revision: "42",
signatures: [],
_links: {
"delete": {
href: "/hog/tags/1.0"
}
}
delete: {
href: "/hog/tags/1.0",
},
},
};
const tags: TagCollection = {
_embedded: {
tags: [tagOneDotZero]
tags: [tagOneDotZero],
},
_links: {}
_links: {},
};
const queryClient = createInfiniteCachingClient();
@@ -87,7 +87,7 @@ describe("Test Tag hooks", () => {
fetchMock.getOnce("/api/v2/hog/tags", tags);
const { result, waitFor } = renderHook(() => useTags(repository), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => {
return !!result.current.data;
@@ -114,7 +114,7 @@ describe("Test Tag hooks", () => {
fetchMock.getOnce("/api/v2/hog/tags/1.0", tagOneDotZero);
const { result, waitFor } = renderHook(() => useTag(repository, "1.0"), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => {
return !!result.current.data;
@@ -141,14 +141,14 @@ describe("Test Tag hooks", () => {
fetchMock.postOnce("/api/v2/hog/tag", {
status: 201,
headers: {
Location: "/hog/tags/1.0"
}
Location: "/hog/tags/1.0",
},
});
fetchMock.getOnce("/api/v2/hog/tags/1.0", tagOneDotZero);
const { result, waitForNextUpdate } = renderHook(() => useCreateTag(repository, changeset), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await act(() => {
@@ -195,11 +195,11 @@ describe("Test Tag hooks", () => {
it("should fail without location header", async () => {
fetchMock.postOnce("/api/v2/hog/tag", {
status: 201
status: 201,
});
const { result, waitForNextUpdate } = renderHook(() => useCreateTag(repository, changeset), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await act(() => {
@@ -215,11 +215,11 @@ describe("Test Tag hooks", () => {
describe("useDeleteTags tests", () => {
const deleteTag = async () => {
fetchMock.deleteOnce("/api/v2/hog/tags/1.0", {
status: 204
status: 204,
});
const { result, waitForNextUpdate } = renderHook(() => useDeleteTag(repository), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await act(() => {

View File

@@ -28,9 +28,9 @@ const createInfiniteCachingClient = () => {
return new QueryClient({
defaultOptions: {
queries: {
staleTime: Infinity
}
}
staleTime: Infinity,
},
},
});
};

View File

@@ -22,22 +22,22 @@
* SOFTWARE.
*/
import { QueryClient} from "react-query";
import { QueryClient } from "react-query";
export const setIndexLink = (queryClient: QueryClient, name: string, href: string) => {
queryClient.setQueryData("index", {
version: "x.y.z",
_links: {
[name]: {
href: href
}
}
href: href,
},
},
});
};
export const setEmptyIndex = (queryClient: QueryClient) => {
queryClient.setQueryData("index", {
version: "x.y.z",
_links: {}
_links: {},
});
};

View File

@@ -22,12 +22,7 @@
* SOFTWARE.
*/
import {
concat,
getNamespaceAndPageFromMatch,
getQueryStringFromLocation,
withEndingSlash
} from "./urls";
import { concat, getNamespaceAndPageFromMatch, getQueryStringFromLocation, withEndingSlash } from "./urls";
describe("tests for withEndingSlash", () => {
it("should append missing slash", () => {
@@ -50,7 +45,7 @@ describe("concat tests", () => {
describe("tests for getNamespaceAndPageFromMatch", () => {
function createMatch(namespace?: string, page?: string) {
return {
params: { namespace, page }
params: { namespace, page },
};
}
@@ -88,7 +83,7 @@ describe("tests for getNamespaceAndPageFromMatch", () => {
describe("tests for getQueryStringFromLocation", () => {
function createLocation(search: string) {
return {
search
search,
};
}

View File

@@ -36,7 +36,7 @@ import {
useDeleteUser,
useUpdateUser,
useUser,
useUsers
useUsers,
} from "./users";
describe("Test user hooks", () => {
@@ -48,21 +48,21 @@ describe("Test user hooks", () => {
name: "yoda",
_links: {
delete: {
href: "/users/yoda"
href: "/users/yoda",
},
update: {
href: "/users/yoda"
href: "/users/yoda",
},
convertToInternal: {
href: "/users/yoda/convertToInternal"
href: "/users/yoda/convertToInternal",
},
convertToExternal: {
href: "/users/yoda/convertToExternal"
}
href: "/users/yoda/convertToExternal",
},
},
_embedded: {
members: []
}
members: [],
},
};
const userCollection: UserCollection = {
@@ -70,8 +70,8 @@ describe("Test user hooks", () => {
page: 0,
pageTotal: 0,
_embedded: {
users: [yoda]
}
users: [yoda],
},
};
afterEach(() => {
@@ -84,7 +84,7 @@ describe("Test user hooks", () => {
setIndexLink(queryClient, "users", "/users");
fetchMock.get("/api/v2/users", userCollection);
const { result, waitFor } = renderHook(() => useUsers(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(userCollection);
@@ -95,11 +95,11 @@ describe("Test user hooks", () => {
setIndexLink(queryClient, "users", "/users");
fetchMock.get("/api/v2/users", userCollection, {
query: {
page: "42"
}
page: "42",
},
});
const { result, waitFor } = renderHook(() => useUsers({ page: 42 }), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(userCollection);
@@ -110,11 +110,11 @@ describe("Test user hooks", () => {
setIndexLink(queryClient, "users", "/users");
fetchMock.get("/api/v2/users", userCollection, {
query: {
q: "yoda"
}
q: "yoda",
},
});
const { result, waitFor } = renderHook(() => useUsers({ search: "yoda" }), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(userCollection);
@@ -125,7 +125,7 @@ describe("Test user hooks", () => {
setIndexLink(queryClient, "users", "/users");
fetchMock.get("/api/v2/users", userCollection);
const { result, waitFor } = renderHook(() => useUsers(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => !!result.current.data);
expect(queryClient.getQueryData(["user", "yoda"])).toEqual(yoda);
@@ -138,7 +138,7 @@ describe("Test user hooks", () => {
setIndexLink(queryClient, "users", "/users");
fetchMock.get("/api/v2/users/yoda", yoda);
const { result, waitFor } = renderHook(() => useUser("yoda"), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(yoda);
@@ -153,14 +153,14 @@ describe("Test user hooks", () => {
fetchMock.postOnce("/api/v2/users", {
status: 201,
headers: {
Location: "/users/yoda"
}
Location: "/users/yoda",
},
});
fetchMock.getOnce("/api/v2/users/yoda", yoda);
const { result, waitForNextUpdate } = renderHook(() => useCreateUser(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await act(() => {
@@ -177,13 +177,13 @@ describe("Test user hooks", () => {
setIndexLink(queryClient, "users", "/users");
fetchMock.postOnce("/api/v2/users", {
status: 201
status: 201,
});
fetchMock.getOnce("/api/v2/users/yoda", yoda);
const { result, waitForNextUpdate } = renderHook(() => useCreateUser(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await act(() => {
@@ -202,11 +202,11 @@ describe("Test user hooks", () => {
setIndexLink(queryClient, "users", "/users");
fetchMock.deleteOnce("/api/v2/users/yoda", {
status: 200
status: 200,
});
const { result, waitForNextUpdate } = renderHook(() => useDeleteUser(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await act(() => {
@@ -229,17 +229,17 @@ describe("Test user hooks", () => {
const newJedis = {
...yoda,
description: "may the 4th be with you"
description: "may the 4th be with you",
};
fetchMock.putOnce("/api/v2/users/yoda", {
status: 200
status: 200,
});
fetchMock.getOnce("/api/v2/users/yoda", newJedis);
const { result, waitForNextUpdate } = renderHook(() => useUpdateUser(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await act(() => {
@@ -261,11 +261,11 @@ describe("Test user hooks", () => {
const queryClient = createInfiniteCachingClient();
fetchMock.putOnce("/api/v2/users/yoda/convertToInternal", {
status: 200
status: 200,
});
const { result, waitForNextUpdate } = renderHook(() => useConvertToInternal(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await act(() => {
@@ -287,11 +287,11 @@ describe("Test user hooks", () => {
const queryClient = createInfiniteCachingClient();
fetchMock.putOnce("/api/v2/users/yoda/convertToExternal", {
status: 200
status: 200,
});
const { result, waitForNextUpdate } = renderHook(() => useConvertToExternal(), {
wrapper: createWrapper(undefined, queryClient)
wrapper: createWrapper(undefined, queryClient),
});
await act(() => {

View File

@@ -24,6 +24,6 @@
export const createQueryString = (params: Record<string, string>) => {
return Object.keys(params)
.map(k => encodeURIComponent(k) + "=" + encodeURIComponent(params[k]))
.map((k) => encodeURIComponent(k) + "=" + encodeURIComponent(params[k]))
.join("&");
};

View File

@@ -47,7 +47,7 @@ class Autocomplete extends React.Component<Props, State> {
static defaultProps = {
placeholder: "Type here",
loadingMessage: "Loading...",
noOptionsMessage: "No suggestion available"
noOptionsMessage: "No suggestion available",
};
handleInputChange = (newValue: ValueType<SelectValue>, action: ActionMeta) => {
@@ -64,7 +64,7 @@ class Autocomplete extends React.Component<Props, State> {
selectValue: ValueType<SelectValue>,
selectOptions: readonly SelectValue[]
): boolean => {
const isNotDuplicated = !selectOptions.map(option => option.label).includes(inputValue);
const isNotDuplicated = !selectOptions.map((option) => option.label).includes(inputValue);
const isNotEmpty = inputValue !== "";
return isNotEmpty && isNotDuplicated;
};
@@ -79,7 +79,7 @@ class Autocomplete extends React.Component<Props, State> {
noOptionsMessage,
loadSuggestions,
creatable,
className
className,
} = this.props;
return (
<div className={classNames("field", className)}>
@@ -95,13 +95,13 @@ class Autocomplete extends React.Component<Props, State> {
loadingMessage={() => loadingMessage}
noOptionsMessage={() => noOptionsMessage}
isValidNewOption={this.isValidNewOption}
onCreateOption={value => {
onCreateOption={(value) => {
this.selectValue({
label: value,
value: {
id: value,
displayName: value
}
displayName: value,
},
});
}}
/>

View File

@@ -41,5 +41,5 @@ const Wrapper = styled.div`
`;
storiesOf("BranchSelector", module)
.addDecorator(storyFn => <Wrapper>{storyFn()}</Wrapper>)
.addDecorator((storyFn) => <Wrapper>{storyFn()}</Wrapper>)
.add("Default", () => <BranchSelector branches={branches} onSelectBranch={branchSelected} label="Select Branch" />);

View File

@@ -128,7 +128,10 @@ const Breadcrumb: FC<Props> = ({
if (path) {
const paths = path.split("/");
return paths.map((pathFragment, index) => {
let currPath = paths.slice(0, index + 1).map(encodeURIComponent).join("/");
let currPath = paths
.slice(0, index + 1)
.map(encodeURIComponent)
.join("/");
if (!currPath.endsWith("/")) {
currPath = currPath + "/";
}

View File

@@ -43,8 +43,8 @@ const footerRight = <small>right footer</small>;
const baseDate = "2020-03-26T12:13:42+02:00";
storiesOf("CardColumn", module)
.addDecorator(story => <MemoryRouter initialEntries={["/"]}>{story()}</MemoryRouter>)
.addDecorator(storyFn => <Wrapper>{storyFn()}</Wrapper>)
.addDecorator((story) => <MemoryRouter initialEntries={["/"]}>{story()}</MemoryRouter>)
.addDecorator((storyFn) => <Wrapper>{storyFn()}</Wrapper>)
.add("Default", () => (
<CardColumn
link={link}

View File

@@ -69,13 +69,12 @@ const CardColumn: FC<Props> = ({
createLink = <Link className="overlay-column" to={link} />;
} else if (action) {
createLink = (
<a
<button
className="overlay-column"
onClick={(e) => {
e.preventDefault();
action();
}}
href="#"
/>
);
}

View File

@@ -28,6 +28,8 @@ type Props = {
className?: string;
};
const HelpIcon: FC<Props> = ({ className }) => <Icon name="question-circle" color="blue-light" className={className} alt="" />;
const HelpIcon: FC<Props> = ({ className }) => (
<Icon name="question-circle" color="blue-light" className={className} alt="" />
);
export default HelpIcon;

View File

@@ -36,7 +36,7 @@ const colors = ["primary", "link", "info", "success", "warning", "danger", "whit
const sizing = ["xs", "sm", "lg", "2x", "3x", "5x", "7x", "10x"];
storiesOf("Icon", module)
.addDecorator(storyFn => <Wrapper>{storyFn()}</Wrapper>)
.addDecorator((storyFn) => <Wrapper>{storyFn()}</Wrapper>)
.add("Default", () => (
<>
<Icon name="cat" />
@@ -48,7 +48,7 @@ storiesOf("Icon", module)
.add("Colors", () => (
<>
<Icon title="default color" name="cat" />
{colors.map(color => (
{colors.map((color) => (
<Icon key={color} title={color} name="cat" color={color} />
))}
</>
@@ -56,7 +56,7 @@ storiesOf("Icon", module)
.add("Sizing", () => (
<>
<Icon title="default size" name="cat" />
{sizing.map(size => (
{sizing.map((size) => (
<Icon key={size} title={"fa-" + size} name={"cat fa-" + size} />
))}
</>

View File

@@ -44,7 +44,7 @@ const RoutingDecorator = (story: () => ReactNode) => <MemoryRouter initialEntrie
storiesOf("Notification", module)
.addDecorator(RoutingDecorator)
.addDecorator(storyFn => <Wrapper>{storyFn()}</Wrapper>)
.addDecorator((storyFn) => <Wrapper>{storyFn()}</Wrapper>)
.add("Primary", () => <Notification type="primary">{content}</Notification>)
.add("Success", () => <Notification type="success">{content}</Notification>)
.add("Info", () => <Notification type="info">{content}</Notification>)

View File

@@ -28,7 +28,7 @@ import Paginator from "./Paginator";
xdescribe("paginator rendering tests", () => {
const dummyLink = {
href: "https://dummy"
href: "https://dummy",
};
it("should render all buttons but disabled, without links", () => {
@@ -36,13 +36,13 @@ xdescribe("paginator rendering tests", () => {
page: 10,
pageTotal: 20,
_links: {},
_embedded: {}
_embedded: {},
};
const paginator = shallow(<Paginator collection={collection} />);
const buttons = paginator.find("Button");
expect(buttons.length).toBe(7);
buttons.forEach(button => {
buttons.forEach((button) => {
// @ts-ignore ???
expect(button.props.disabled).toBeTruthy();
});
@@ -55,9 +55,9 @@ xdescribe("paginator rendering tests", () => {
_links: {
first: dummyLink,
next: dummyLink,
last: dummyLink
last: dummyLink,
},
_embedded: {}
_embedded: {},
};
const paginator = shallow(<Paginator collection={collection} />);
@@ -92,9 +92,9 @@ xdescribe("paginator rendering tests", () => {
first: dummyLink,
prev: dummyLink,
next: dummyLink,
last: dummyLink
last: dummyLink,
},
_embedded: {}
_embedded: {},
};
const paginator = shallow(<Paginator collection={collection} />);
@@ -132,9 +132,9 @@ xdescribe("paginator rendering tests", () => {
pageTotal: 148,
_links: {
first: dummyLink,
prev: dummyLink
prev: dummyLink,
},
_embedded: {}
_embedded: {},
};
const paginator = shallow(<Paginator collection={collection} />);
@@ -169,9 +169,9 @@ xdescribe("paginator rendering tests", () => {
first: dummyLink,
prev: dummyLink,
next: dummyLink,
last: dummyLink
last: dummyLink,
},
_embedded: {}
_embedded: {},
};
const paginator = shallow(<Paginator collection={collection} />);
@@ -211,9 +211,9 @@ xdescribe("paginator rendering tests", () => {
first: dummyLink,
prev: dummyLink,
next: dummyLink,
last: dummyLink
last: dummyLink,
},
_embedded: {}
_embedded: {},
};
const paginator = shallow(<Paginator collection={collection} />);
@@ -258,12 +258,12 @@ xdescribe("paginator rendering tests", () => {
_links: {
first: dummyLink,
prev: {
href: "https://www.scm-manager.org"
href: "https://www.scm-manager.org",
},
next: dummyLink,
last: dummyLink
last: dummyLink,
},
_embedded: {}
_embedded: {},
};
let urlToOpen;

View File

@@ -33,7 +33,7 @@ class ProtectedRoute extends Component<Props> {
constructor(props: Props) {
super(props);
this.state = {
error: undefined
error: undefined,
};
}
@@ -49,8 +49,8 @@ class ProtectedRoute extends Component<Props> {
to={{
pathname: "/login",
state: {
from: routeProps.location
}
from: routeProps.location,
},
}}
/>
);

View File

@@ -64,7 +64,7 @@ const Tag: FC<Props> = ({
}
let showDelete = null;
if (onRemove) {
showDelete = <a className="tag is-delete" onClick={onRemove} />;
showDelete = <button className="tag is-delete" onClick={onRemove} />;
}
return (

View File

@@ -46,40 +46,40 @@ export default {
type: "normal",
oldLineNumber: 5,
newLineNumber: 5,
isNormal: true
isNormal: true,
},
{
content: "and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).",
type: "normal",
oldLineNumber: 6,
newLineNumber: 6,
isNormal: true
isNormal: true,
},
{
content: "",
type: "normal",
oldLineNumber: 7,
newLineNumber: 7,
isNormal: true
isNormal: true,
},
{
content: "## Unreleased",
type: "delete",
lineNumber: 8,
isDelete: true
isDelete: true,
},
{
content: "## [2.7.1] - 2020-10-14",
type: "insert",
lineNumber: 8,
isInsert: true
isInsert: true,
},
{
content: "### Fixed",
type: "normal",
oldLineNumber: 9,
newLineNumber: 9,
isNormal: true
isNormal: true,
},
{
content:
@@ -87,7 +87,7 @@ export default {
type: "normal",
oldLineNumber: 10,
newLineNumber: 10,
isNormal: true
isNormal: true,
},
{
content:
@@ -95,24 +95,22 @@ export default {
type: "normal",
oldLineNumber: 11,
newLineNumber: 11,
isNormal: true
}
]
}
isNormal: true,
},
],
},
],
_links: {
lines: {
href:
"http://localhost:8081/scm/api/v2/repositories/scmadmin/scm-manager/content/fbffdea2a566dc4ac54ea38d4aade5aaf541e7f2/CHANGELOG.md?start={start}&end={end}",
templated: true
}
}
}
href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/scm-manager/content/fbffdea2a566dc4ac54ea38d4aade5aaf541e7f2/CHANGELOG.md?start={start}&end={end}",
templated: true,
},
},
},
],
_links: {
self: {
href:
"http://localhost:8081/scm/api/v2/repositories/scmadmin/scm-manager/diff/fbffdea2a566dc4ac54ea38d4aade5aaf541e7f2/parsed"
}
}
href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/scm-manager/diff/fbffdea2a566dc4ac54ea38d4aade5aaf541e7f2/parsed",
},
},
};

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
import {Changeset, ChangesetCollection, PagedCollection} from "@scm-manager/ui-types";
import { Changeset, ChangesetCollection, PagedCollection } from "@scm-manager/ui-types";
const one: Changeset = {
id: "a88567ef1e9528a700555cad8c4576b72fc7c6dd",
@@ -33,31 +33,26 @@ const one: Changeset = {
contributors: [
{
type: "Committed-by",
person: { mail: "zaphod.beeblebrox@hitchhiker.cm", name: "Zaphod Beeblebrox" }
person: { mail: "zaphod.beeblebrox@hitchhiker.cm", name: "Zaphod Beeblebrox" },
},
{ type: "Co-authored-by", person: { mail: "ford.prefect@hitchhiker.com", name: "Ford Prefect" } }
{ type: "Co-authored-by", person: { mail: "ford.prefect@hitchhiker.com", name: "Ford Prefect" } },
],
_links: {
self: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/a88567ef1e9528a700555cad8c4576b72fc7c6dd"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/a88567ef1e9528a700555cad8c4576b72fc7c6dd",
},
diff: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/a88567ef1e9528a700555cad8c4576b72fc7c6dd"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/a88567ef1e9528a700555cad8c4576b72fc7c6dd",
},
sources: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/sources/a88567ef1e9528a700555cad8c4576b72fc7c6dd"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/sources/a88567ef1e9528a700555cad8c4576b72fc7c6dd",
},
modifications: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/modifications/a88567ef1e9528a700555cad8c4576b72fc7c6dd"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/modifications/a88567ef1e9528a700555cad8c4576b72fc7c6dd",
},
diffParsed: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/a88567ef1e9528a700555cad8c4576b72fc7c6dd/parsed"
}
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/a88567ef1e9528a700555cad8c4576b72fc7c6dd/parsed",
},
},
_embedded: {
tags: [],
@@ -67,17 +62,15 @@ const one: Changeset = {
id: "d21cc6c359270aef2196796f4d96af65f51866dc",
_links: {
self: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/d21cc6c359270aef2196796f4d96af65f51866dc"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/d21cc6c359270aef2196796f4d96af65f51866dc",
},
diff: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/d21cc6c359270aef2196796f4d96af65f51866dc"
}
}
}
]
}
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/d21cc6c359270aef2196796f4d96af65f51866dc",
},
},
},
],
},
};
const two: Changeset = {
@@ -88,30 +81,25 @@ const two: Changeset = {
contributors: [
{
type: "Committed-by",
person: { mail: "zaphod.beeblebrox@hitchhiker.cm", name: "Zaphod Beeblebrox" }
}
person: { mail: "zaphod.beeblebrox@hitchhiker.cm", name: "Zaphod Beeblebrox" },
},
],
_links: {
self: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/d21cc6c359270aef2196796f4d96af65f51866dc"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/d21cc6c359270aef2196796f4d96af65f51866dc",
},
diff: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/d21cc6c359270aef2196796f4d96af65f51866dc"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/d21cc6c359270aef2196796f4d96af65f51866dc",
},
sources: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/sources/d21cc6c359270aef2196796f4d96af65f51866dc"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/sources/d21cc6c359270aef2196796f4d96af65f51866dc",
},
modifications: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/modifications/d21cc6c359270aef2196796f4d96af65f51866dc"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/modifications/d21cc6c359270aef2196796f4d96af65f51866dc",
},
diffParsed: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/d21cc6c359270aef2196796f4d96af65f51866dc/parsed"
}
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/d21cc6c359270aef2196796f4d96af65f51866dc/parsed",
},
},
_embedded: {
tags: [],
@@ -121,17 +109,15 @@ const two: Changeset = {
id: "e163c8f632db571c9aa51a8eb440e37cf550b825",
_links: {
self: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/e163c8f632db571c9aa51a8eb440e37cf550b825"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/e163c8f632db571c9aa51a8eb440e37cf550b825",
},
diff: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/e163c8f632db571c9aa51a8eb440e37cf550b825"
}
}
}
]
}
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/e163c8f632db571c9aa51a8eb440e37cf550b825",
},
},
},
],
},
};
const three: Changeset = {
@@ -142,27 +128,22 @@ const three: Changeset = {
contributors: [],
_links: {
self: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/e163c8f632db571c9aa51a8eb440e37cf550b825"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/e163c8f632db571c9aa51a8eb440e37cf550b825",
},
diff: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/e163c8f632db571c9aa51a8eb440e37cf550b825"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/e163c8f632db571c9aa51a8eb440e37cf550b825",
},
sources: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/sources/e163c8f632db571c9aa51a8eb440e37cf550b825"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/sources/e163c8f632db571c9aa51a8eb440e37cf550b825",
},
modifications: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/modifications/e163c8f632db571c9aa51a8eb440e37cf550b825"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/modifications/e163c8f632db571c9aa51a8eb440e37cf550b825",
},
diffParsed: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/e163c8f632db571c9aa51a8eb440e37cf550b825/parsed"
}
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/e163c8f632db571c9aa51a8eb440e37cf550b825/parsed",
},
},
_embedded: { tags: [], branches: [], parents: [] }
_embedded: { tags: [], branches: [], parents: [] },
};
const four: Changeset = {
@@ -173,29 +154,24 @@ const four: Changeset = {
contributors: [
{ type: "Co-authored-by", person: { mail: "ford.prefect@hitchhiker.com", name: "Ford Prefect" } },
{ type: "Co-authored-by", person: { mail: "zaphod.beeblebrox@hitchhiker.cm", name: "Zaphod Beeblebrox" } },
{ type: "Co-authored-by", person: { mail: "trillian@hitchhiker.cm", name: "Tricia Marie McMillan" } }
{ type: "Co-authored-by", person: { mail: "trillian@hitchhiker.cm", name: "Tricia Marie McMillan" } },
],
_links: {
self: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/b6c6f8fbd0d490936fae7d26ffdd4695cc2a0930"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/b6c6f8fbd0d490936fae7d26ffdd4695cc2a0930",
},
diff: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/b6c6f8fbd0d490936fae7d26ffdd4695cc2a0930"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/b6c6f8fbd0d490936fae7d26ffdd4695cc2a0930",
},
sources: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/sources/b6c6f8fbd0d490936fae7d26ffdd4695cc2a0930"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/sources/b6c6f8fbd0d490936fae7d26ffdd4695cc2a0930",
},
modifications: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/modifications/b6c6f8fbd0d490936fae7d26ffdd4695cc2a0930"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/modifications/b6c6f8fbd0d490936fae7d26ffdd4695cc2a0930",
},
diffParsed: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/b6c6f8fbd0d490936fae7d26ffdd4695cc2a0930/parsed"
}
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/b6c6f8fbd0d490936fae7d26ffdd4695cc2a0930/parsed",
},
},
_embedded: {
tags: [],
@@ -205,17 +181,15 @@ const four: Changeset = {
id: "a88567ef1e9528a700555cad8c4576b72fc7c6dd",
_links: {
self: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/a88567ef1e9528a700555cad8c4576b72fc7c6dd"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/a88567ef1e9528a700555cad8c4576b72fc7c6dd",
},
diff: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/a88567ef1e9528a700555cad8c4576b72fc7c6dd"
}
}
}
]
}
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/a88567ef1e9528a700555cad8c4576b72fc7c6dd",
},
},
},
],
},
};
const five: Changeset = {
@@ -225,25 +199,20 @@ const five: Changeset = {
description: "HOG-42 Change mail to arthur@guide.galaxy\n\n",
_links: {
self: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/d21cc6c359270aef2196796f4d96af65f51866dc"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/d21cc6c359270aef2196796f4d96af65f51866dc",
},
diff: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/d21cc6c359270aef2196796f4d96af65f51866dc"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/d21cc6c359270aef2196796f4d96af65f51866dc",
},
sources: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/sources/d21cc6c359270aef2196796f4d96af65f51866dc"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/sources/d21cc6c359270aef2196796f4d96af65f51866dc",
},
modifications: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/modifications/d21cc6c359270aef2196796f4d96af65f51866dc"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/modifications/d21cc6c359270aef2196796f4d96af65f51866dc",
},
diffParsed: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/d21cc6c359270aef2196796f4d96af65f51866dc/parsed"
}
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/d21cc6c359270aef2196796f4d96af65f51866dc/parsed",
},
},
_embedded: {
tags: [],
@@ -253,17 +222,15 @@ const five: Changeset = {
id: "e163c8f632db571c9aa51a8eb440e37cf550b825",
_links: {
self: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/e163c8f632db571c9aa51a8eb440e37cf550b825"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/e163c8f632db571c9aa51a8eb440e37cf550b825",
},
diff: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/e163c8f632db571c9aa51a8eb440e37cf550b825"
}
}
}
]
}
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/e163c8f632db571c9aa51a8eb440e37cf550b825",
},
},
},
],
},
};
const changesets: ChangesetCollection = {
@@ -271,27 +238,24 @@ const changesets: ChangesetCollection = {
pageTotal: 1,
_links: {
self: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/branches/master/changesets/?page=0&pageSize=10"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/branches/master/changesets/?page=0&pageSize=10",
},
first: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/branches/master/changesets/?page=0&pageSize=10"
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/branches/master/changesets/?page=0&pageSize=10",
},
last: {
href:
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/branches/master/changesets/?page=0&pageSize=10"
}
href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/branches/master/changesets/?page=0&pageSize=10",
},
},
_embedded: {
changesets: [one, two, three, four],
branch: {
name: "master",
_links: {
self: { href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/branches/master" }
}
}
}
self: { href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/branches/master" },
},
},
},
};
export { one, two, three, four, five };

View File

@@ -37,31 +37,31 @@ export default {
permissions: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/permissions/" },
protocol: [
{ href: "ssh://scmadmin@localhost:4567/repo/scmadmin/Git", name: "ssh" },
{ href: "http://localhost:8081/scm/repo/scmadmin/Git", name: "http" }
{ href: "http://localhost:8081/scm/repo/scmadmin/Git", name: "http" },
],
tags: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/tags/" },
branches: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/branches/" },
incomingChangesets: {
href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/incoming/{source}/{target}/changesets",
templated: true
templated: true,
},
incomingDiff: {
href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/incoming/{source}/{target}/diff",
templated: true
templated: true,
},
incomingDiffParsed: {
href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/incoming/{source}/{target}/diff/parsed",
templated: true
templated: true,
},
changesets: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/changesets/" },
sources: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/sources/" },
authorMappingConfig: {
href: "http://localhost:8081/scm/api/v2/authormapping/configuration/scmadmin/Git"
href: "http://localhost:8081/scm/api/v2/authormapping/configuration/scmadmin/Git",
},
unfavorize: { href: "http://localhost:8081/scm/api/v2/unfavorize/scmadmin/Git" },
favorites: [
{ href: "http://localhost:8081/scm/api/v2/unfavorize/scmadmin/Git", name: "unfavorize" },
{ href: "http://localhost:8081/scm/api/v2/favorize/scmadmin/Git", name: "favorize" }
]
}
{ href: "http://localhost:8081/scm/api/v2/favorize/scmadmin/Git", name: "favorize" },
],
},
};

File diff suppressed because it is too large Load Diff

View File

@@ -21,9 +21,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import React, { MouseEvent, ReactNode } from "react";
import React, { FC, MouseEvent, ReactNode } from "react";
import classNames from "classnames";
import { RouteComponentProps, withRouter } from "react-router-dom";
import { Link } from "react-router-dom";
import Icon from "../Icon";
import { createAttributesForTesting } from "../devBuild";
@@ -42,90 +42,79 @@ export type ButtonProps = {
testId?: string;
};
type Props = ButtonProps &
RouteComponentProps & {
type?: "button" | "submit" | "reset";
color?: string;
type Props = ButtonProps & {
type?: "button" | "submit" | "reset";
color?: string;
};
const Button: FC<Props> = ({
link,
className,
icon,
fullWidth,
reducedMobile,
testId,
children,
label,
type = "button",
title,
loading,
disabled,
action,
color = "default",
}) => {
const renderIcon = () => {
return <>{icon ? <Icon name={icon} color="inherit" className="is-medium pr-1" /> : null}</>;
};
class Button extends React.Component<Props> {
static defaultProps: Partial<Props> = {
type: "button",
color: "default",
};
onClick = (event: React.MouseEvent) => {
const { action, link, history } = this.props;
if (action) {
action(event);
} else if (link) {
history.push(link);
}
};
render() {
const {
label,
title,
loading,
disabled,
type,
color,
className,
icon,
fullWidth,
reducedMobile,
children,
testId,
} = this.props;
if (icon) {
return (
<button
type={type}
title={title}
disabled={disabled}
onClick={this.onClick}
className={classNames(
"button",
"is-" + color,
{ "is-loading": loading },
{ "is-fullwidth": fullWidth },
{ "is-reduced-mobile": reducedMobile },
className
)}
{...createAttributesForTesting(testId)}
>
<span className="icon is-medium">
<Icon name={icon} color="inherit" />
</span>
{(label || children) && (
<span>
{label} {children}
</span>
)}
</button>
);
}
if (link) {
return (
<button
type={type}
title={title}
disabled={disabled}
onClick={this.onClick}
<Link
className={classNames(
"button",
"is-" + color,
{ "is-loading": loading },
{ "is-fullwidth": fullWidth },
{ "is-reduced-mobile": reducedMobile },
className
)}
{...createAttributesForTesting(testId)}
to={link}
aria-label={label}
>
{label} {children}
</button>
{renderIcon()}{" "}
{(label || children) && (
<>
{label} {children}
</>
)}
</Link>
);
}
}
export default withRouter(Button);
return (
<button
type={type}
title={title}
disabled={disabled}
onClick={(event) => action && action(event)}
className={classNames(
"button",
"is-" + color,
{ "is-loading": loading },
{ "is-fullwidth": fullWidth },
{ "is-reduced-mobile": reducedMobile },
className
)}
{...createAttributesForTesting(testId)}
>
{renderIcon()}{" "}
{(label || children) && (
<>
{label} {children}
</>
)}
</button>
);
};
export default Button;

View File

@@ -41,7 +41,7 @@ class ButtonAddons extends React.Component<Props> {
const { className, children } = this.props;
const childWrapper: ReactNode[] = [];
React.Children.forEach(children, child => {
React.Children.forEach(children, (child) => {
if (child) {
childWrapper.push(
<p className="control" key={childWrapper.length}>

View File

@@ -34,7 +34,7 @@ class ButtonGroup extends React.Component<Props> {
const { className, children } = this.props;
const childWrapper: ReactNode[] = [];
React.Children.forEach(children, child => {
React.Children.forEach(children, (child) => {
if (child) {
childWrapper.push(
<div className="control" key={childWrapper.length}>

View File

@@ -31,7 +31,7 @@ type SubmitButtonProps = ButtonProps & {
class SubmitButton extends React.Component<SubmitButtonProps> {
static defaultProps = {
scrollToTop: true
scrollToTop: true,
};
render() {

View File

@@ -46,7 +46,7 @@ storiesOf("Buttons/Button", module)
.addDecorator(RoutingDecorator)
.add("Colors", () => (
<div>
{colors.map(color => (
{colors.map((color) => (
<Spacing key={color}>
<Button color={color} label={color} />
</Spacing>
@@ -62,7 +62,7 @@ storiesOf("Buttons/Button", module)
))
.add("Disabled", () => (
<div>
{colors.map(color => (
{colors.map((color) => (
<Spacing key={color}>
<Button color={color} label={color} disabled={true} />
</Spacing>

View File

@@ -26,12 +26,12 @@ import { byKey, byValueLength, byNestedKeys } from "./comparators";
const createObject = (key: string, value?: string) => {
return {
[key]: value
[key]: value,
};
};
const createObjects = (key: string, values: Array<string | undefined>) => {
return values.map(v => createObject(key, v));
return values.map((v) => createObject(key, v));
};
describe("key comparator tests", () => {
@@ -98,18 +98,18 @@ describe("nested key comparator tests", () => {
const createObject = (key: string, nested?: string, value?: string) => {
if (!nested) {
return {
[key]: undefined
[key]: undefined,
};
}
return {
[key]: {
[nested]: value
}
[nested]: value,
},
};
};
const createObjects = (key: string, nested: string, values: Array<string | undefined>) => {
return values.map(v => createObject(key, nested, v));
return values.map((v) => createObject(key, nested, v));
};
it("should sort array", () => {

View File

@@ -95,5 +95,5 @@ export const byNestedKeys = (key: string, nestedKey: string) => {
export default {
byKey,
byValueLength,
byNestedKeys
byNestedKeys,
};

View File

@@ -31,7 +31,7 @@ export const createAttributesForTesting = (testId?: string) => {
return undefined;
}
return {
"data-testid": normalizeTestId(testId)
"data-testid": normalizeTestId(testId),
};
};

View File

@@ -53,7 +53,7 @@ const AutocompleteAddEntryToTableField: FC<Props> = ({
loadSuggestions,
placeholder,
loadingMessage,
noOptionsMessage
noOptionsMessage,
}) => {
const [selectedValue, setSelectedValue] = useState<SelectValue | undefined>(undefined);

View File

@@ -64,8 +64,8 @@ const ReactHookForm: FC = () => {
const { register, handleSubmit } = useForm<Settings>({
defaultValues: {
disabled: true,
readonly: true
}
readonly: true,
},
});
const [stored, setStored] = useState<Settings>();
@@ -106,7 +106,7 @@ const LegacyEvents: FC = () => {
};
storiesOf("Forms/Checkbox", module)
.addDecorator(storyFn => <MemoryRouter>{storyFn()}</MemoryRouter>)
.addDecorator((storyFn) => <MemoryRouter>{storyFn()}</MemoryRouter>)
.add("Default", () => (
<Spacing>
<Checkbox label="Not checked" checked={false} />

View File

@@ -41,10 +41,10 @@ storiesOf("Forms/DropDown", module)
options={[
"The Hitchhiker's Guide to the Galaxy",
"Dirk Gentlys Holistic Detective Agency",
"The Meaning Of Liff"
"The Meaning Of Liff",
]}
preselectedOption={"dirk"}
optionSelected={selection => {
optionSelected={(selection) => {
// nothing to do
}}
/>
@@ -54,7 +54,7 @@ storiesOf("Forms/DropDown", module)
optionValues={["alpha", "beta", "gamma"]}
options={["A", "B", "C"]}
preselectedOption={"D"}
optionSelected={selection => {
optionSelected={(selection) => {
// nothing to do
}}
/>

View File

@@ -45,7 +45,7 @@ class DropDown extends React.Component<Props> {
render() {
const { options, optionValues, preselectedOption, className, disabled } = this.props;
if (preselectedOption && options.filter(o => o === preselectedOption).length === 0) {
if (preselectedOption && options.filter((o) => o === preselectedOption).length === 0) {
options.push(preselectedOption);
}

View File

@@ -77,7 +77,7 @@ const FilterInput: FC<Props> = ({ filter, value, testId, placeholder, autoFocus,
type="search"
placeholder={placeholder || t("filterEntries")}
value={stateValue}
onChange={event => setStateValue(event.target.value)}
onChange={(event) => setStateValue(event.target.value)}
autoFocus={autoFocus || false}
/>
<span className="icon is-small is-left">

View File

@@ -36,11 +36,11 @@ type Props = WithTranslation & {
class MemberNameTagGroup extends React.Component<Props> {
render() {
const { members, label, helpText, t } = this.props;
const membersExtended = members.map(id => {
const membersExtended = members.map((id) => {
return {
id,
displayName: id,
mail: ""
mail: "",
};
});
return (
@@ -54,7 +54,7 @@ class MemberNameTagGroup extends React.Component<Props> {
}
removeEntry = (membersExtended: DisplayedUser[]) => {
const members = membersExtended.map(function(item) {
const members = membersExtended.map(function (item) {
return item["id"];
});
this.props.memberListChanged(members);

View File

@@ -44,7 +44,7 @@ class PasswordConfirmation extends React.Component<Props, State> {
password: "",
confirmedPassword: "",
passwordValid: true,
passwordConfirmationFailed: false
passwordConfirmationFailed: false,
};
}
@@ -53,7 +53,7 @@ class PasswordConfirmation extends React.Component<Props, State> {
password: "",
confirmedPassword: "",
passwordValid: true,
passwordConfirmationFailed: false
passwordConfirmationFailed: false,
});
}
@@ -101,7 +101,7 @@ class PasswordConfirmation extends React.Component<Props, State> {
this.setState(
{
confirmedPassword,
passwordConfirmationFailed: !passwordConfirmed
passwordConfirmationFailed: !passwordConfirmed,
},
this.propagateChange
);
@@ -114,7 +114,7 @@ class PasswordConfirmation extends React.Component<Props, State> {
{
passwordValid: this.validatePassword(password),
passwordConfirmationFailed,
password: password
password: password,
},
this.propagateChange
);

View File

@@ -113,7 +113,7 @@ const LegacyEvents: FC = () => {
};
storiesOf("Forms/Radio", module)
.addDecorator(storyFn => <MemoryRouter>{storyFn()}</MemoryRouter>)
.addDecorator((storyFn) => <MemoryRouter>{storyFn()}</MemoryRouter>)
.add("Default", () => (
<Spacing>
<Radio label="Not checked" checked={false} />

View File

@@ -187,8 +187,8 @@ const PreselectOption: FC = () => {
},
{
label: "USCSS Prometheus",
value: "uscss-prometheus"
}
value: "uscss-prometheus",
},
]}
onChange={setValue}
value={value}
@@ -204,5 +204,4 @@ storiesOf("Forms/Select", module)
.add("Ref", () => <Ref />)
.add("Legacy Events", () => <LegacyEvents />)
.add("ReactHookForm", () => <ReactHookForm />)
.add("Preselect option", () => <PreselectOption />)
;
.add("Preselect option", () => <PreselectOption />);

View File

@@ -24,7 +24,7 @@
// this aliases are only to map from spotter detection to prismjs
const languageAliases: { [key: string]: string } = {
golang: "go"
golang: "go",
};
export const defaultLanguage = "text";

View File

@@ -40,7 +40,7 @@ const trillian: Me = {
displayName: "Trillian McMillian",
mail: "tricia@hitchhiker.com",
groups: ["crew"],
_links: {}
_links: {},
};
const bindAvatar = (binder: Binder, avatar: string) => {
@@ -65,7 +65,7 @@ const withBinder = (binder: Binder) => {
};
storiesOf("Footer", module)
.addDecorator(story => <MemoryRouter initialEntries={["/"]}>{story()}</MemoryRouter>)
.addDecorator((story) => <MemoryRouter initialEntries={["/"]}>{story()}</MemoryRouter>)
.add("Default", () => {
return <Footer me={trillian} version="2.0.0" links={{}} />;
})

View File

@@ -29,7 +29,7 @@ const SecondaryColumn = styled.div<{ collapsed: boolean }>`
/* In Bulma there is unfortunately no intermediate step between .is-1 and .is-2, hence the size.
Navigation size should be as constant as possible. */
flex: none;
width: ${props => (props.collapsed ? "5.5rem" : "20.5rem")};
width: ${(props) => (props.collapsed ? "5.5rem" : "20.5rem")};
max-width: ${(props: { collapsed: boolean }) => (props.collapsed ? "11.3%" : "25%")};
/* Render this column to full size if column construct breaks (page size too small). */
@media (max-width: 785px) {

View File

@@ -31,7 +31,7 @@ type Props = {
className?: string;
};
const Title: FC<Props> = ({ title, preventRefreshingPageTitle, customPageTitle, className , children}) => {
const Title: FC<Props> = ({ title, preventRefreshingPageTitle, customPageTitle, className, children }) => {
useEffect(() => {
if (!preventRefreshingPageTitle) {
if (customPageTitle) {
@@ -51,7 +51,7 @@ const Title: FC<Props> = ({ title, preventRefreshingPageTitle, customPageTitle,
};
Title.defaultProps = {
preventRefreshingPageTitle: false
preventRefreshingPageTitle: false,
};
export default Title;

View File

@@ -32,7 +32,7 @@ type Props = {
value: string;
};
const MarkdownCodeRenderer: FC<Props> = props => {
const MarkdownCodeRenderer: FC<Props> = (props) => {
const binder = useBinder();
const indexLinks = useIndexLinks();
const { language } = props;

View File

@@ -94,7 +94,7 @@ const MarkdownHeadingRenderer: FC<Props> = ({ children, level, permalink, id })
<Icon name="link" onClick={copyPermalink} alt={t("sources.content.copyPermalink")} />
</Tooltip>
);
const headingElement = React.createElement("h" + level, {id: anchorId}, [...reactChildren, CopyButton]);
const headingElement = React.createElement("h" + level, { id: anchorId }, [...reactChildren, CopyButton]);
const href = urls.withContextPath(location.pathname + "#" + anchorId);
const permalinkHref =
window.location.protocol +
@@ -110,7 +110,7 @@ const MarkdownHeadingRenderer: FC<Props> = ({ children, level, permalink, id })
};
export const create = (permalink: string): FC<Props> => {
return props => <MarkdownHeadingRenderer {...props} permalink={permalink} />;
return (props) => <MarkdownHeadingRenderer {...props} permalink={permalink} />;
};
export default MarkdownHeadingRenderer;

View File

@@ -26,7 +26,7 @@ import {
isExternalLink,
isLinkWithProtocol,
createLocalLink,
isInternalScmRepoLink
isInternalScmRepoLink,
} from "./MarkdownLinkRenderer";
describe("test isAnchorLink", () => {

View File

@@ -136,7 +136,7 @@ const MarkdownLinkRenderer: FC<Props> = ({ href = "", base, children, ...props }
// we use a factory method, because react-markdown does not pass
// base as prop down to our link component.
export const create = (base?: string, protocolExtensions: ProtocolLinkRendererExtensionMap = {}): FC<LinkProps> => {
return props => {
return (props) => {
const protocolLinkContext = isLinkWithProtocol(props.href || "");
if (protocolLinkContext) {
const { link, protocol } = protocolLinkContext;

View File

@@ -46,8 +46,8 @@ const Spacing = styled.div`
`;
storiesOf("MarkdownView", module)
.addDecorator(story => <MemoryRouter initialEntries={["/"]}>{story()}</MemoryRouter>)
.addDecorator(story => <Spacing>{story()}</Spacing>)
.addDecorator((story) => <MemoryRouter initialEntries={["/"]}>{story()}</MemoryRouter>)
.addDecorator((story) => <Spacing>{story()}</Spacing>)
.add("Default", () => <MarkdownView content={TestPage} skipHtml={false} />)
.add("Skip Html", () => <MarkdownView content={TestPage} skipHtml={true} />)
.add("Code without Lang", () => <MarkdownView content={MarkdownWithoutLang} skipHtml={false} />)
@@ -63,7 +63,7 @@ storiesOf("MarkdownView", module)
const binder = new Binder("custom protocol link renderer");
binder.bind("markdown-renderer.link.protocol", {
protocol: "scw",
renderer: ProtocolLinkRenderer
renderer: ProtocolLinkRenderer,
} as ProtocolLinkRendererExtension);
return (
<BinderContext.Provider value={binder}>
@@ -75,7 +75,7 @@ storiesOf("MarkdownView", module)
const binder = new Binder("custom protocol link renderer");
binder.bind("markdown-renderer.link.protocol", {
protocol: "scw",
renderer: ProtocolLinkRenderer
renderer: ProtocolLinkRenderer,
} as ProtocolLinkRendererExtension);
return (
<BinderContext.Provider value={binder}>

View File

@@ -85,7 +85,7 @@ const MarkdownErrorNotification: FC = () => {
</pre>
<p>
{t("markdownErrorNotification.spec")}:{" "}
<a href="https://github.github.com/gfm/" target="_blank">
<a href="https://github.github.com/gfm/" target="_blank" rel="noreferrer">
GitHub Flavored Markdown Spec
</a>
</p>
@@ -99,13 +99,13 @@ class MarkdownView extends React.Component<Props, State> {
static defaultProps: Partial<Props> = {
enableAnchorHeadings: false,
skipHtml: false
skipHtml: false,
};
constructor(props: Props) {
super(props);
this.state = {
contentRef: null
contentRef: null,
};
}
@@ -143,7 +143,7 @@ class MarkdownView extends React.Component<Props, State> {
basePath,
permalink,
t,
mdastPlugins = []
mdastPlugins = [],
} = this.props;
const rendererFactory = this.context.getExtension("markdown-renderer-factory");
@@ -200,25 +200,25 @@ class MarkdownView extends React.Component<Props, State> {
sanitize,
merge(gh, {
attributes: {
code: ["className"] // Allow className for code elements, this is necessary to extract the code language
code: ["className"], // Allow className for code elements, this is necessary to extract the code language
},
clobberPrefix: "", // Do not prefix user-provided ids and class names,
protocols: {
href: Object.keys(protocolLinkRendererExtensions)
}
href: Object.keys(protocolLinkRendererExtensions),
},
})
)
.use(rehype2react, {
createElement: React.createElement,
passNode: true,
components: createComponentList(remarkRendererList, { permalink })
components: createComponentList(remarkRendererList, { permalink }),
});
const renderedMarkdown: any = processor.processSync(content).result;
return (
<ErrorBoundary fallback={MarkdownErrorNotification}>
<div ref={el => this.setState({ contentRef: el })} className="content is-word-break">
<div ref={(el) => this.setState({ contentRef: el })} className="content is-word-break">
{renderedMarkdown}
</div>
</ErrorBoundary>

View File

@@ -24,7 +24,7 @@
import {
createRemark2RehypeCodeRendererAdapter,
createRemark2RehypeHeadingRendererAdapterFactory,
createRemark2RehypeLinkRendererAdapter
createRemark2RehypeLinkRendererAdapter,
} from "./remarkToRehypeRendererAdapters";
export type CreateComponentListOptions = {

View File

@@ -34,7 +34,7 @@ export default function createMdastPlugin(plugin: AstPlugin): any {
return function attach() {
return function transform(tree: any) {
plugin({
visit: (type, visitor) => visit(tree, type, visitor)
visit: (type, visitor) => visit(tree, type, visitor),
});
return tree;
};

View File

@@ -35,4 +35,4 @@ export type ProtocolLinkRendererExtension = {
export type ProtocolLinkRendererExtensionMap = {
[protocol: string]: FC<ProtocolLinkRendererProps>;
}
};

View File

@@ -59,7 +59,7 @@ export const createTransformer = (t: TFunction): AstPlugin => {
if (i > 0) {
children.push({
type: "text",
value: nodeText.substring(0, i)
value: nodeText.substring(0, i),
});
}
@@ -69,14 +69,14 @@ export const createTransformer = (t: TFunction): AstPlugin => {
title: t("changeset.shortlink.title", {
namespace: m[1],
name: m[2],
id: m[3]
id: m[3],
}),
children: [
{
type: "text",
value: m[0]
}
]
value: m[0],
},
],
});
nodeText = nodeText.substring(i + m[0].length);
@@ -85,13 +85,13 @@ export const createTransformer = (t: TFunction): AstPlugin => {
if (nodeText.length > 0) {
children.push({
type: "text",
value: nodeText
value: nodeText,
});
}
parent.children[index] = {
type: "text",
children
children,
};
}
});

View File

@@ -28,7 +28,7 @@ export const createRemark2RehypeCodeRendererAdapter = (remarkRenderer: any) => {
children = children || [];
const renderProps = {
value: children[0],
language: Array.isArray(node.properties.className) ? node.properties.className[0].split("language-")[1] : ""
language: Array.isArray(node.properties.className) ? node.properties.className[0].split("language-")[1] : "",
};
return React.createElement(remarkRenderer, renderProps, ...children);
};
@@ -54,13 +54,14 @@ export const createRemark2RehypeLinkRendererAdapter = (remarkRenderer: any) => {
};
export const createRemark2RehypeHeadingRendererAdapterFactory = (remarkRenderer: any, permalink?: string) => {
return (level: number) => ({ node, children }: any) => {
const renderProps = {
id: node.properties.id,
level,
permalink
return (level: number) =>
({ node, children }: any) => {
const renderProps = {
id: node.properties.id,
level,
permalink,
};
children = children || [];
return React.createElement(remarkRenderer, renderProps, ...children);
};
children = children || [];
return React.createElement(remarkRenderer, renderProps, ...children);
};
};

View File

@@ -37,15 +37,15 @@ const buttons = [
{
className: "is-outlined",
label: "Cancel",
onClick: () => null
onClick: () => null,
},
{
label: "Submit"
}
label: "Submit",
},
];
storiesOf("Modal/ConfirmAlert", module)
.addDecorator(story => <MemoryRouter initialEntries={["/"]}>{story()}</MemoryRouter>)
.addDecorator((story) => <MemoryRouter initialEntries={["/"]}>{story()}</MemoryRouter>)
.add("Default", () => <ConfirmAlert message={body} title={"Are you sure about that?"} buttons={buttons} />)
.add("WithButton", () => {
const buttonClick = () => {

View File

@@ -65,13 +65,13 @@ export const ConfirmAlert: FC<Props> = ({ title, message, buttons, close }) => {
<div className="field is-grouped">
{buttons.map((button, index) => (
<p className="control" key={index}>
<a
<button
className={classNames("button", "is-info", button.className, button.isLoading ? "is-loading" : "")}
key={index}
onClick={() => handleClickButton(button)}
>
{button.label}
</a>
</button>
</p>
))}
</div>

View File

@@ -48,8 +48,8 @@ const CreateTagModal: FC<Props> = ({ t, onClose, tagCreationLink, existingTagsLi
useEffect(() => {
apiClient
.get(existingTagsLink)
.then(response => response.json())
.then(json => setTagNames(json._embedded.tags.map((tag: Tag) => tag.name)));
.then((response) => response.json())
.then((json) => setTagNames(json._embedded.tags.map((tag: Tag) => tag.name)));
}, [existingTagsLink]);
const createTag = () => {
@@ -57,7 +57,7 @@ const CreateTagModal: FC<Props> = ({ t, onClose, tagCreationLink, existingTagsLi
apiClient
.post(tagCreationLink, {
revision,
name: newTagName
name: newTagName,
})
.then(onCreated)
.catch(onError)
@@ -83,7 +83,7 @@ const CreateTagModal: FC<Props> = ({ t, onClose, tagCreationLink, existingTagsLi
<InputField
name="name"
label={t("tags.create.form.field.name.label")}
onChange={val => setNewTagName(val)}
onChange={(val) => setNewTagName(val)}
value={newTagName}
validationError={!!validationError}
errorMessage={t(validationError)}

View File

@@ -33,7 +33,7 @@ export const MenuContext = React.createContext<MenuContext>({
isCollapsed() {
return false;
},
setCollapsed() {}
setCollapsed() {},
});
export const StateMenuContextProvider: FC = ({ children }) => {
@@ -43,7 +43,7 @@ export const StateMenuContextProvider: FC = ({ children }) => {
isCollapsed() {
return collapsed;
},
setCollapsed
setCollapsed,
};
return <MenuContext.Provider value={context}>{children}</MenuContext.Provider>;

View File

@@ -39,17 +39,17 @@ class NavAction extends React.Component<Props> {
if (icon) {
showIcon = (
<>
<i className={icon}></i>{" "}
<i className={icon} />{" "}
</>
);
}
return (
<li>
<a onClick={action} href="javascript:void(0);">
<button onClick={action}>
{showIcon}
{label}
</a>
</button>
</li>
);
}

View File

@@ -53,8 +53,8 @@ const withRoute = (route: string) => {
};
storiesOf("Secondary Navigation", module)
.addDecorator(story => <StateMenuContextProvider>{story()}</StateMenuContextProvider>)
.addDecorator(story => (
.addDecorator((story) => <StateMenuContextProvider>{story()}</StateMenuContextProvider>)
.addDecorator((story) => (
<Columns className="columns">
<div className="column is-3">{story()}</div>
</Columns>
@@ -92,7 +92,7 @@ storiesOf("Secondary Navigation", module)
<SecondaryNavigation label="Hitchhiker">
<SecondaryNavigationItem to="/42" icon="fas fa-puzzle-piece" label="Puzzle 42" title="Puzzle 42" />
<SecondaryNavigationItem
activeWhenMatch={route => route.location.pathname === "/hog"}
activeWhenMatch={(route) => route.location.pathname === "/hog"}
to="/heart-of-gold"
icon="fas fa-star"
label="Heart Of Gold"

View File

@@ -44,7 +44,7 @@ const SubNavigation: FC<Props> = ({
title,
label,
children,
testId
testId,
}) => {
const context = useMenuContext();
const collapsed = context.isCollapsed();
@@ -56,7 +56,7 @@ const SubNavigation: FC<Props> = ({
const active = useActiveMatch({
to: parent,
activeOnlyWhenExact,
activeWhenMatch
activeWhenMatch,
});
let defaultIcon = "fas fa-cog";

View File

@@ -34,40 +34,42 @@ const Wrapper = styled.div`
`;
storiesOf("Popover", module)
.addDecorator(storyFn => <Wrapper>{storyFn()}</Wrapper>)
.add("Default", () => React.createElement(() => {
const { triggerProps, popoverProps } = usePopover();
.addDecorator((storyFn) => <Wrapper>{storyFn()}</Wrapper>)
.add("Default", () =>
React.createElement(() => {
const { triggerProps, popoverProps } = usePopover();
return (
<div>
<Popover title={<strong>Spaceship Heart of Gold</strong>} width={512} {...popoverProps}>
<p>
The Heart of Gold is the sleekest, most advanced, coolest spaceship in the galaxy. Its stunning good looks
mirror its awesome speed and power. It is powered by the revolutionary new Infinite Improbability Drive,
which lets the ship pass through every point in every universe simultaneously.
</p>
</Popover>
<button className="button" {...triggerProps}>
Trigger
</button>
</div>
);
}))
.add("Link", () => React.createElement(() => {
const { triggerProps, popoverProps } = usePopover();
return (
<div>
<Popover title={<strong>Spaceship Heart of Gold</strong>} width={512} {...popoverProps}>
<p>
The Heart of Gold is the sleekest, most advanced, coolest spaceship in the galaxy. Its stunning good looks
mirror its awesome speed and power. It is powered by the revolutionary new Infinite Improbability Drive,
which lets the ship pass through every point in every universe simultaneously.
</p>
</Popover>
<button className="button" {...triggerProps}>
Trigger
</button>
</div>
);
})
)
.add("Link", () =>
React.createElement(() => {
const { triggerProps, popoverProps } = usePopover();
return (
<div>
<Popover title={<strong>Spaceship Heart of Gold</strong>} width={512} {...popoverProps}>
<p>
The Heart of Gold is the sleekest, most advanced, coolest spaceship in the galaxy. Its stunning good looks
mirror its awesome speed and power. It is powered by the revolutionary new Infinite Improbability Drive,
which lets the ship pass through every point in every universe simultaneously.
</p>
</Popover>
<a href="#" {...triggerProps}>
Trigger
</a>
</div>
);
}));
return (
<div>
<Popover title={<strong>Spaceship Heart of Gold</strong>} width={512} {...popoverProps}>
<p>
The Heart of Gold is the sleekest, most advanced, coolest spaceship in the galaxy. Its stunning good looks
mirror its awesome speed and power. It is powered by the revolutionary new Infinite Improbability Drive,
which lets the ship pass through every point in every universe simultaneously.
</p>
</Popover>
<button {...triggerProps}>Trigger</button>
</div>
);
})
);

View File

@@ -53,7 +53,7 @@ type State = {
const initialState = {
onPopover: false,
onTrigger: false
onTrigger: false,
};
const reducer = (state: State, action: Action): State => {
@@ -66,14 +66,14 @@ const reducer = (state: State, action: Action): State => {
offsetTop: action.offsetTop,
offsetLeft: action.offsetLeft,
onTrigger: true,
onPopover: false
onPopover: false,
};
}
case "leave-trigger": {
if (state.onPopover) {
return {
...state,
onTrigger: false
onTrigger: false,
};
}
return initialState;
@@ -81,14 +81,14 @@ const reducer = (state: State, action: Action): State => {
case "enter-popover": {
return {
...state,
onPopover: true
onPopover: true,
};
}
case "leave-popover": {
if (state.onTrigger) {
return {
...state,
onPopover: false
onPopover: false,
};
}
return initialState;
@@ -109,13 +109,13 @@ const usePopover = () => {
dispatchDeferred(dispatch, {
type: "enter-trigger",
offsetTop: current.offsetTop,
offsetLeft: current.offsetLeft + current.offsetWidth / 2
offsetLeft: current.offsetLeft + current.offsetWidth / 2,
});
};
const onMouseLeave = () => {
dispatchDeferred(dispatch, {
type: "leave-trigger"
type: "leave-trigger",
});
};
@@ -123,14 +123,14 @@ const usePopover = () => {
triggerProps: {
onMouseOver,
onMouseLeave,
ref: (node: HTMLElement | null) => (triggerRef.current = node)
ref: (node: HTMLElement | null) => (triggerRef.current = node),
},
popoverProps: {
dispatch,
show: state.onPopover || state.onTrigger,
offsetTop: state.offsetTop,
offsetLeft: state.offsetLeft
}
offsetLeft: state.offsetLeft,
},
};
};

View File

@@ -42,8 +42,8 @@ const HUNK_0: Hunk = {
{ content: "line", type: "insert", lineNumber: 5, isInsert: true },
{ content: "line", type: "normal", oldLineNumber: 6, newLineNumber: 6, isNormal: true },
{ content: "line", type: "normal", oldLineNumber: 7, newLineNumber: 7, isNormal: true },
{ content: "line", type: "normal", oldLineNumber: 8, newLineNumber: 8, isNormal: true }
]
{ content: "line", type: "normal", oldLineNumber: 8, newLineNumber: 8, isNormal: true },
],
};
const HUNK_1: Hunk = {
content: "@@ -14,6 +14,7 @@",
@@ -58,8 +58,8 @@ const HUNK_1: Hunk = {
{ content: "line", type: "insert", lineNumber: 17, isInsert: true },
{ content: "line", type: "normal", oldLineNumber: 17, newLineNumber: 18, isNormal: true },
{ content: "line", type: "normal", oldLineNumber: 18, newLineNumber: 19, isNormal: true },
{ content: "line", type: "normal", oldLineNumber: 19, newLineNumber: 20, isNormal: true }
]
{ content: "line", type: "normal", oldLineNumber: 19, newLineNumber: 20, isNormal: true },
],
};
const HUNK_2: Hunk = {
content: "@@ -21,7 +22,7 @@",
@@ -75,8 +75,8 @@ const HUNK_2: Hunk = {
{ content: "line", type: "insert", lineNumber: 25, isInsert: true },
{ content: "line", type: "normal", oldLineNumber: 25, newLineNumber: 26, isNormal: true },
{ content: "line", type: "normal", oldLineNumber: 26, newLineNumber: 27, isNormal: true },
{ content: "line", type: "normal", oldLineNumber: 27, newLineNumber: 28, isNormal: true }
]
{ content: "line", type: "normal", oldLineNumber: 27, newLineNumber: 28, isNormal: true },
],
};
const HUNK_3: Hunk = {
content: "@@ -33,6 +34,7 @@",
@@ -91,8 +91,8 @@ const HUNK_3: Hunk = {
{ content: "line", type: "insert", lineNumber: 37, isInsert: true },
{ content: "line", type: "normal", oldLineNumber: 36, newLineNumber: 38, isNormal: true },
{ content: "line", type: "normal", oldLineNumber: 37, newLineNumber: 39, isNormal: true },
{ content: "line", type: "normal", oldLineNumber: 38, newLineNumber: 40, isNormal: true }
]
{ content: "line", type: "normal", oldLineNumber: 38, newLineNumber: 40, isNormal: true },
],
};
const TEST_CONTENT_WITH_HUNKS: FileDiff = {
hunks: [HUNK_0, HUNK_1, HUNK_2, HUNK_3],
@@ -107,9 +107,9 @@ const TEST_CONTENT_WITH_HUNKS: FileDiff = {
_links: {
lines: {
href: "http://localhost:8081/scm/api/v2/content/abc/CommitMessage.js?start={start}&end={end}",
templated: true
}
}
templated: true,
},
},
};
const TEST_CONTENT_WITH_NEW_BINARY_FILE: FileDiff = {
@@ -119,7 +119,7 @@ const TEST_CONTENT_WITH_NEW_BINARY_FILE: FileDiff = {
newEndingNewLine: true,
oldRevision: "0000000000000000000000000000000000000000",
newRevision: "86c370aae0727d628a5438f79a5cdd45752b9d99",
type: "add"
type: "add",
};
const TEST_CONTENT_WITH_NEW_TEXT_FILE: FileDiff = {
@@ -138,17 +138,16 @@ const TEST_CONTENT_WITH_NEW_TEXT_FILE: FileDiff = {
newLines: 2,
changes: [
{ content: "line 1", type: "insert", lineNumber: 1, isInsert: true },
{ content: "line 2", type: "insert", lineNumber: 2, isInsert: true }
]
}
{ content: "line 2", type: "insert", lineNumber: 2, isInsert: true },
],
},
],
_links: {
lines: {
href:
"http://localhost:8081/scm/api/v2/repositories/scm-manager/scm-editor-plugin/content/c63898d35520ee47bcc3a8291660979918715762/src/main/markdown/README.md?start={start}&end={end}",
templated: true
}
}
href: "http://localhost:8081/scm/api/v2/repositories/scm-manager/scm-editor-plugin/content/c63898d35520ee47bcc3a8291660979918715762/src/main/markdown/README.md?start={start}&end={end}",
templated: true,
},
},
};
const TEST_CONTENT_WITH_DELETED_TEXT_FILE: FileDiff = {
@@ -165,10 +164,10 @@ const TEST_CONTENT_WITH_DELETED_TEXT_FILE: FileDiff = {
content: "@@ -1 +0,0 @@",
oldStart: 1,
oldLines: 1,
changes: [{ content: "# scm-editor-plugin", type: "delete", lineNumber: 1, isDelete: true }]
}
changes: [{ content: "# scm-editor-plugin", type: "delete", lineNumber: 1, isDelete: true }],
},
],
_links: { lines: { href: "http://localhost:8081/dev/null?start={start}&end={end}", templated: true } }
_links: { lines: { href: "http://localhost:8081/dev/null?start={start}&end={end}", templated: true } },
};
const TEST_CONTENT_WITH_DELETED_LINES_AT_END: FileDiff = {
@@ -202,16 +201,16 @@ const TEST_CONTENT_WITH_DELETED_LINES_AT_END: FileDiff = {
{ content: "line", type: "delete", lineNumber: 119, isDelete: true },
{ content: "line", type: "delete", lineNumber: 120, isDelete: true },
{ content: "line", type: "delete", lineNumber: 121, isDelete: true },
{ content: "line", type: "delete", lineNumber: 122, isDelete: true }
]
}
{ content: "line", type: "delete", lineNumber: 122, isDelete: true },
],
},
],
_links: {
lines: {
href: "http://localhost:8081/scm/api/v2/content/abc/CommitMessage.js?start={start}&end={end}",
templated: true
}
}
templated: true,
},
},
};
const TEST_CONTENT_WITH_ALL_LINES_REMOVED_FROM_FILE: FileDiff = {
@@ -231,17 +230,16 @@ const TEST_CONTENT_WITH_ALL_LINES_REMOVED_FROM_FILE: FileDiff = {
changes: [
{ content: "line", type: "delete", lineNumber: 1, isDelete: true },
{ content: "line", type: "delete", lineNumber: 2, isDelete: true },
{ content: "line", type: "delete", lineNumber: 3, isDelete: true }
]
}
{ content: "line", type: "delete", lineNumber: 3, isDelete: true },
],
},
],
_links: {
lines: {
href:
"http://localhost:8081/scm/api/v2/repositories/scm-manager/scm-editor-plugin/content/b313a7690f028c77df98417c1ed6cba67e5692ec/pom.xml?start={start}&end={end}",
templated: true
}
}
href: "http://localhost:8081/scm/api/v2/repositories/scm-manager/scm-editor-plugin/content/b313a7690f028c77df98417c1ed6cba67e5692ec/pom.xml?start={start}&end={end}",
templated: true,
},
},
};
describe("with hunks the diff expander", () => {
@@ -285,7 +283,7 @@ describe("with hunks the diff expander", () => {
await diffExpander
.getHunk(1)
.expandBottom(1)
.then(file => (newFile = file));
.then((file) => (newFile = file));
expect(fetchMock.done()).toBe(true);
expect(newFile!.hunks!.length).toBe(oldHunkCount + 1);
expect(newFile!.hunks![1]).toBe(expandedHunk);
@@ -310,7 +308,7 @@ describe("with hunks the diff expander", () => {
await diffExpander
.getHunk(1)
.expandHead(5)
.then(file => (newFile = file));
.then((file) => (newFile = file));
expect(fetchMock.done()).toBe(true);
expect(newFile!.hunks!.length).toBe(oldHunkCount + 1);
expect(newFile!.hunks![0]).toBe(preceedingHunk);
@@ -339,7 +337,7 @@ describe("with hunks the diff expander", () => {
await diffExpander
.getHunk(3)
.expandBottom(10)
.then(file => (newFile = file));
.then((file) => (newFile = file));
expect(newFile!.hunks!.length).toBe(oldHunkCount + 1);
expect(newFile!.hunks![4].fullyExpanded).toBe(true);
});
@@ -352,7 +350,7 @@ describe("with hunks the diff expander", () => {
await diffExpander
.getHunk(3)
.expandBottom(-1)
.then(file => (newFile = file));
.then((file) => (newFile = file));
await fetchMock.flush(true);
expect(newFile!.hunks![4].fullyExpanded).toBe(true);
});

View File

@@ -75,7 +75,7 @@ class DiffExpander {
expandHead: (n: number, count: number) => Promise<FileDiff> = (n, count) => {
const start = this.minLineNumber(n) - Math.min(count, this.computeMaxExpandHeadRange(n)) - 1;
const end = this.minLineNumber(n) - 1;
return this.loadLines(start, end).then(lines => {
return this.loadLines(start, end).then((lines) => {
const hunk = this.file.hunks![n];
const newHunk = this.createNewHunk(
@@ -96,7 +96,7 @@ class DiffExpander {
count > 0
? start + Math.min(count, maxExpandBottomRange > 0 ? maxExpandBottomRange : Number.MAX_SAFE_INTEGER)
: -1;
return this.loadLines(start, end).then(lines => {
return this.loadLines(start, end).then((lines) => {
const hunk = this.file.hunks![n];
const newHunk: Hunk = this.createNewHunk(
@@ -116,9 +116,9 @@ class DiffExpander {
.replace("{end}", end.toString());
return apiClient
.get(lineRequestUrl)
.then(response => response.text())
.then(text => text.split("\n"))
.then(lines => (lines[lines.length - 1] === "" ? lines.slice(0, lines.length - 1) : lines));
.then((response) => response.text())
.then((text) => text.split("\n"))
.then((lines) => (lines[lines.length - 1] === "" ? lines.slice(0, lines.length - 1) : lines));
};
addHunkToFile = (newHunk: Hunk, position: number) => {
@@ -141,13 +141,13 @@ class DiffExpander {
let oldLineNumber: number = oldFirstLineNumber;
let newLineNumber: number = newFirstLineNumber;
lines.forEach(line => {
lines.forEach((line) => {
newChanges.push({
content: line,
type: "normal",
oldLineNumber,
newLineNumber,
isNormal: true
isNormal: true,
});
oldLineNumber += 1;
newLineNumber += 1;
@@ -161,7 +161,7 @@ class DiffExpander {
oldLines: lines.length,
newLines: lines.length,
expansion: true,
fullyExpanded: requestedLines < 0 || lines.length < requestedLines
fullyExpanded: requestedLines < 0 || lines.length < requestedLines,
};
};
@@ -175,13 +175,13 @@ class DiffExpander {
return lastChange.newLineNumber || lastChange.lineNumber!;
};
getHunk: (n: number) => ExpandableHunk = n => {
getHunk: (n: number) => ExpandableHunk = (n) => {
return {
maxExpandHeadRange: this.computeMaxExpandHeadRange(n),
maxExpandBottomRange: this.computeMaxExpandBottomRange(n),
expandHead: (count: number) => this.expandHead(n, count),
expandBottom: (count: number) => this.expandBottom(n, count),
hunk: this.file?.hunks![n]
hunk: this.file?.hunks![n],
};
};
}

View File

@@ -24,7 +24,7 @@
import React, { FC } from "react";
import { Color, Size } from "../styleConstants";
import Tooltip, {TooltipLocation} from "../Tooltip";
import Tooltip, { TooltipLocation } from "../Tooltip";
import Tag from "../Tag";
type Props = {

View File

@@ -49,7 +49,7 @@ function runTokenize({ id, payload }: TokenizeMessage) {
const options = {
highlight: language !== "text",
language: language,
refractor
refractor,
};
const doTokenization = (worker: Worker) => {
@@ -57,13 +57,13 @@ function runTokenize({ id, payload }: TokenizeMessage) {
const tokens = tokenize(hunks, options);
const payload = {
success: true,
tokens: tokens
tokens: tokens,
};
worker.postMessage({ id, payload });
} catch (ex) {
const payload = {
success: false,
reason: ex.message
reason: ex.message,
};
worker.postMessage({ id, payload });
}

View File

@@ -73,7 +73,7 @@ type Props = {
const TokenizedDiffView: FC<Props> = ({ file, viewType, className, children }) => {
const { tokens } = useTokenizeWorker(tokenize, {
hunks: file.hunks,
language: determineLanguage(file.language)
language: determineLanguage(file.language),
});
return (

View File

@@ -40,30 +40,30 @@ const commitCreateNewApp = {
revision: "0d8c1d328f4599b363755671afe667c7ace52bae",
author: {
name: "Arthur Dent",
mail: "arthur.dent@hitchhiker.com"
mail: "arthur.dent@hitchhiker.com",
},
description: "create new app",
when: new Date("2020-04-09T13:07:42Z")
when: new Date("2020-04-09T13:07:42Z"),
};
const commitFixedMissingImport = {
revision: "fab38559ce3ab8c388e067712b4bd7ab94b9fa9b",
author: {
name: "Tricia Marie McMillan",
mail: "trillian@hitchhiker.com"
mail: "trillian@hitchhiker.com",
},
description: "fixed missing import",
when: new Date("2020-05-10T09:18:42Z")
when: new Date("2020-05-10T09:18:42Z"),
};
const commitImplementMain = {
revision: "5203292ab2bc0c020dd22adc4d3897da4930e43f",
author: {
name: "Ford Prefect",
mail: "ford.prefect@hitchhiker.com"
mail: "ford.prefect@hitchhiker.com",
},
description: "implemented main function",
when: new Date("2020-04-12T16:29:42Z")
when: new Date("2020-04-12T16:29:42Z"),
};
const source: AnnotatedSource = {
@@ -72,44 +72,44 @@ const source: AnnotatedSource = {
{
lineNumber: 1,
code: "package main",
...commitCreateNewApp
...commitCreateNewApp,
},
{
lineNumber: 2,
code: "",
...commitCreateNewApp
...commitCreateNewApp,
},
{
lineNumber: 3,
code: 'import "fmt"',
...commitFixedMissingImport
...commitFixedMissingImport,
},
{
lineNumber: 4,
code: "",
...commitFixedMissingImport
...commitFixedMissingImport,
},
{
lineNumber: 5,
code: "func main() {",
...commitCreateNewApp
...commitCreateNewApp,
},
{
lineNumber: 6,
code: ' fmt.Println("Hello World")',
...commitImplementMain
...commitImplementMain,
},
{
lineNumber: 7,
code: "}",
...commitCreateNewApp
...commitCreateNewApp,
},
{
lineNumber: 8,
code: "",
...commitCreateNewApp
}
]
...commitCreateNewApp,
},
],
};
const markdownSource: AnnotatedSource = {
@@ -118,44 +118,44 @@ const markdownSource: AnnotatedSource = {
{
lineNumber: 1,
code: "# Title",
...commitCreateNewApp
...commitCreateNewApp,
},
{
lineNumber: 2,
code: "",
...commitCreateNewApp
...commitCreateNewApp,
},
{
lineNumber: 3,
code: "This is a short Markdown text.",
...commitFixedMissingImport
...commitFixedMissingImport,
},
{
lineNumber: 4,
code: "",
...commitFixedMissingImport
...commitFixedMissingImport,
},
{
lineNumber: 5,
code: "With **bold** and __italic__ words.",
...commitCreateNewApp
...commitCreateNewApp,
},
{
lineNumber: 6,
code: "",
...commitImplementMain
...commitImplementMain,
},
{
lineNumber: 7,
code: "> This should be a quote",
...commitCreateNewApp
...commitCreateNewApp,
},
{
lineNumber: 8,
code: "",
...commitCreateNewApp
}
]
...commitCreateNewApp,
},
],
};
const Robohash: FC = ({ children }) => {
@@ -165,8 +165,8 @@ const Robohash: FC = ({ children }) => {
};
storiesOf("Repositories/Annotate", module)
.addDecorator(storyFn => <MemoryRouter initialEntries={["/"]}>{storyFn()}</MemoryRouter>)
.addDecorator(storyFn => <Wrapper className="box">{storyFn()}</Wrapper>)
.addDecorator((storyFn) => <MemoryRouter initialEntries={["/"]}>{storyFn()}</MemoryRouter>)
.addDecorator((storyFn) => <Wrapper className="box">{storyFn()}</Wrapper>)
.add("Default", () => (
<Annotate source={source} repository={repository} baseDate={new Date("2020-04-16T09:22:42Z")} />
))

View File

@@ -115,7 +115,7 @@ const Contributors: FC<PersonsProps> = ({ persons, label, displayTextOnly }) =>
<>
{t(label)}{" "}
<AvatarList>
{persons.map(p => (
{persons.map((p) => (
<ContributorWithAvatar key={p.name} person={p} avatar={avatarFactory(p)} />
))}
</AvatarList>
@@ -125,9 +125,9 @@ const Contributors: FC<PersonsProps> = ({ persons, label, displayTextOnly }) =>
return (
<>
{t(label)}{" "}
<a title={persons.map(person => "- " + person.name).join("\n")}>
<span title={persons.map((person) => "- " + person.name).join("\n")}>
{t("changeset.contributors.more", { count: persons.length })}
</a>
</span>
</>
);
}
@@ -148,7 +148,7 @@ const ChangesetAuthor: FC<Props> = ({ changeset }) => {
const filterContributorsByType = (type: string) => {
if (changeset.contributors) {
return changeset.contributors.filter(p => p.type === type).map(contributor => contributor.person);
return changeset.contributors.filter((p) => p.type === type).map((contributor) => contributor.person);
}
return emptyListOfContributors;
};

View File

@@ -39,11 +39,11 @@ const ChangesetDescription: FC<Props> = ({ changeset, value }) => {
"changeset.description.tokens",
{
changeset,
value
value,
}
);
return <SplitAndReplace text={value} replacements={replacements.flatMap(r => r(changeset, value))} />;
return <SplitAndReplace text={value} replacements={replacements.flatMap((r) => r(changeset, value))} />;
};
export default ChangesetDescription;

View File

@@ -29,9 +29,9 @@ describe("isDiffSupported tests", () => {
const supported = isDiffSupported({
_links: {
diff: {
href: "http://diff"
}
}
href: "http://diff",
},
},
});
expect(supported).toBe(true);
@@ -41,9 +41,9 @@ describe("isDiffSupported tests", () => {
const supported = isDiffSupported({
_links: {
diffParsed: {
href: "http://diff"
}
}
href: "http://diff",
},
},
});
expect(supported).toBe(true);
@@ -51,7 +51,7 @@ describe("isDiffSupported tests", () => {
it("should return false if not diff link was provided", () => {
const supported = isDiffSupported({
_links: {}
_links: {},
});
expect(supported).toBe(false);
@@ -63,9 +63,9 @@ describe("createUrl tests", () => {
const url = createUrl({
_links: {
diff: {
href: "http://diff"
}
}
href: "http://diff",
},
},
});
expect(url).toBe("http://diff?format=GIT");
@@ -75,9 +75,9 @@ describe("createUrl tests", () => {
const url = createUrl({
_links: {
diffParsed: {
href: "http://diff-parsed"
}
}
href: "http://diff-parsed",
},
},
});
expect(url).toBe("http://diff-parsed");
@@ -87,12 +87,12 @@ describe("createUrl tests", () => {
const url = createUrl({
_links: {
diff: {
href: "http://diff"
href: "http://diff",
},
diffParsed: {
href: "http://diff-parsed"
}
}
href: "http://diff-parsed",
},
},
});
expect(url).toBe("http://diff-parsed");
@@ -101,7 +101,7 @@ describe("createUrl tests", () => {
it("should throw an error if no diff link is defined", () => {
expect(() =>
createUrl({
_links: {}
_links: {},
})
).toThrow();
});

Some files were not shown because too many files have changed in this diff Show More