merge with upstream

This commit is contained in:
Florian Scholdei
2019-09-23 10:58:52 +02:00
60 changed files with 2771 additions and 775 deletions

View File

@@ -1,10 +1,9 @@
//@flow
import React from "react";
import { Link } from "react-router-dom";
import type { Branch, Repository } from "@scm-manager/ui-types";
import {Link} from "react-router-dom";
import type {Branch, Repository} from "@scm-manager/ui-types";
import injectSheet from "react-jss";
import { ExtensionPoint, binder } from "@scm-manager/ui-extensions";
import {ButtonGroup} from "./buttons";
import {binder, ExtensionPoint} from "@scm-manager/ui-extensions";
import classNames from "classnames";
type Props = {
@@ -64,33 +63,48 @@ class Breadcrumb extends React.Component<Props> {
}
render() {
const { classes, baseUrl, branch, defaultBranch, branches, revision, path, repository } = this.props;
const {
classes,
baseUrl,
branch,
defaultBranch,
branches,
revision,
path,
repository
} = this.props;
return (
<>
<div className={classes.flexRow}>
<nav className={classNames(classes.flexStart, "breadcrumb sources-breadcrumb")} aria-label="breadcrumbs">
<nav
className={classNames(
classes.flexStart,
"breadcrumb sources-breadcrumb"
)}
aria-label="breadcrumbs"
>
<ul>{this.renderPath()}</ul>
</nav>
{
binder.hasExtension("repos.sources.actionbar") &&
{binder.hasExtension("repos.sources.actionbar") && (
<div className={classes.buttonGroup}>
<ButtonGroup>
<ExtensionPoint
name="repos.sources.actionbar"
props={{
baseUrl,
branch: branch ? branch : defaultBranch,
path,
isBranchUrl: branches &&
branches.filter(b => b.name.replace("/", "%2F") === revision).length > 0,
repository
}}
renderAll={true}
/>
</ButtonGroup>
<ExtensionPoint
name="repos.sources.actionbar"
props={{
baseUrl,
branch: branch ? branch : defaultBranch,
path,
isBranchUrl:
branches &&
branches.filter(
b => b.name.replace("/", "%2F") === revision
).length > 0,
repository
}}
renderAll={true}
/>
</div>
}
)}
</div>
<hr className={classes.noMargin} />
</>

View File

@@ -48,6 +48,7 @@ type Props = {
footerRight: React.Node,
link?: string,
action?: () => void,
className?: string,
// context props
classes: any
@@ -72,13 +73,14 @@ class CardColumn extends React.Component<Props> {
contentRight,
footerLeft,
footerRight,
classes
classes,
className
} = this.props;
const link = this.createLink();
return (
<>
{link}
<article className={classNames("media", classes.inner)}>
<article className={classNames("media", className, classes.inner)}>
<figure className={classNames(classes.centerImage, "media-left")}>
{avatar}
</figure>

View File

@@ -8,12 +8,17 @@ type Props = {
body: any,
footer?: any,
active: boolean,
className?: string
className?: string,
headColor: string
};
class Modal extends React.Component<Props> {
static defaultProps = {
headColor: "light"
};
render() {
const { title, closeFunction, body, footer, active, className } = this.props;
const { title, closeFunction, body, footer, active, className, headColor } = this.props;
const isActive = active ? "is-active" : null;
@@ -26,7 +31,7 @@ class Modal extends React.Component<Props> {
<div className={classNames("modal", className, isActive)}>
<div className="modal-background" />
<div className="modal-card">
<header className="modal-card-head">
<header className={classNames("modal-card-head", `has-background-${headColor}`)}>
<p className="modal-card-title is-marginless">{title}</p>
<button
className="delete"

View File

@@ -46,6 +46,10 @@ const styles = {
diff: {
"& > colgroup .diff-gutter-col": {
width: "3.25rem"
},
/* prevent following content from moving down */
"& > .diff-gutter:empty:hover::after": {
fontSize: "0.7rem"
}
}
};
@@ -191,7 +195,7 @@ class DiffFile extends React.Component<Props, State> {
value = file.type;
}
const color =
value === "added" ? "outline-success" : value === "deleted" ? "outline-danger" : "outline-info";
value === "added" ? "success is-outlined" : value === "deleted" ? "danger is-outlined" : "info is-outlined";
return (
<Tag

View File

@@ -5,7 +5,7 @@ export const isNameValid = (name: string) => {
return nameRegex.test(name);
};
const mailRegex = /^[ -~]+@[A-Za-z0-9][\w\-.]*\.[A-Za-z0-9][A-Za-z0-9-]+$/;
const mailRegex = /^[ -~]+@[A-Za-z0-9][\w\-.]*\.[A-Za-z0-9][A-Za-z0-9-]+$/;
export const isMailValid = (mail: string) => {
return mailRegex.test(mail);
@@ -14,3 +14,9 @@ export const isMailValid = (mail: string) => {
export const isNumberValid = (number: string) => {
return !isNaN(number);
};
const pathRegex = /^((?!\/{2,}).)*$/;
export const isPathValid = (path: string) => {
return pathRegex.test(path);
};

View File

@@ -2,102 +2,117 @@
import * as validator from "./validation";
describe("test name validation", () => {
it("should return false", () => {
// invalid names taken from ValidationUtilTest.java
const invalidNames = [
"@test",
" test 123",
" test 123 ",
"test 123 ",
"test/123",
"test%123",
"test:123",
"t ",
" t",
" t ",
"",
// invalid names taken from ValidationUtilTest.java
const invalidNames = [
"@test",
" test 123",
" test 123 ",
"test 123 ",
"test/123",
"test%123",
"test:123",
"t ",
" t",
" t ",
"",
" invalid_name",
"another%one",
"!!!",
"!_!"
];
for (let name of invalidNames) {
" invalid_name",
"another%one",
"!!!",
"!_!"
];
for (let name of invalidNames) {
it(`should return false for '${name}'`, () => {
expect(validator.isNameValid(name)).toBe(false);
}
});
});
}
it("should return true", () => {
// valid names taken from ValidationUtilTest.java
const validNames = [
"test",
"test.git",
"Test123.git",
"Test123-git",
"Test_user-123.git",
"test@scm-manager.de",
"test123",
"tt",
"t",
"valid_name",
"another1",
"stillValid",
"this.one_as-well",
"and@this"
];
for (let name of validNames) {
// valid names taken from ValidationUtilTest.java
const validNames = [
"test",
"test.git",
"Test123.git",
"Test123-git",
"Test_user-123.git",
"test@scm-manager.de",
"test123",
"tt",
"t",
"valid_name",
"another1",
"stillValid",
"this.one_as-well",
"and@this"
];
for (let name of validNames) {
it(`should return true for '${name}'`, () => {
expect(validator.isNameValid(name)).toBe(true);
}
});
});
}
});
describe("test mail validation", () => {
it("should return false", () => {
// invalid taken from ValidationUtilTest.java
const invalid = [
"ostfalia.de",
"@ostfalia.de",
"s.sdorra@",
"s.sdorra@ostfalia",
"s.sdorra@ ostfalia.de",
"s.sdorra@[ostfalia.de"
];
for (let mail of invalid) {
// invalid taken from ValidationUtilTest.java
const invalid = [
"ostfalia.de",
"@ostfalia.de",
"s.sdorra@",
"s.sdorra@ostfalia",
"s.sdorra@ ostfalia.de",
"s.sdorra@[ostfalia.de"
];
for (let mail of invalid) {
it(`should return false for '${mail}'`, () => {
expect(validator.isMailValid(mail)).toBe(false);
}
});
});
}
it("should return true", () => {
// valid taken from ValidationUtilTest.java
const valid = [
"s.sdorra@ostfalia.de",
"sdorra@ostfalia.de",
"s.sdorra@hbk-bs.de",
"s.sdorra@gmail.com",
"s.sdorra@t.co",
"s.sdorra@ucla.college",
"s.sdorra@example.xn--p1ai",
"s.sdorra@scm.solutions",
"s'sdorra@scm.solutions",
"\"S Sdorra\"@scm.solutions"
];
for (let mail of valid) {
// valid taken from ValidationUtilTest.java
const valid = [
"s.sdorra@ostfalia.de",
"sdorra@ostfalia.de",
"s.sdorra@hbk-bs.de",
"s.sdorra@gmail.com",
"s.sdorra@t.co",
"s.sdorra@ucla.college",
"s.sdorra@example.xn--p1ai",
"s.sdorra@scm.solutions",
"s'sdorra@scm.solutions",
"\"S Sdorra\"@scm.solutions"
];
for (let mail of valid) {
it(`should return true for '${mail}'`, () => {
expect(validator.isMailValid(mail)).toBe(true);
}
});
});
}
});
describe("test number validation", () => {
it("should return false", () => {
const invalid = ["1a", "35gu", "dj6", "45,5", "test"];
for (let number of invalid) {
expect(validator.isNumberValid(number)).toBe(false);
}
});
it("should return true", () => {
const valid = ["1", "35", "2", "235", "34.4"];
for (let number of valid) {
const invalid = ["1a", "35gu", "dj6", "45,5", "test"];
for (let number of invalid) {
it(`should return false for '${number}'`, () => {
expect(validator.isNumberValid(number)).toBe(false);
});
}
const valid = ["1", "35", "2", "235", "34.4"];
for (let number of valid) {
it(`should return true for '${number}'`, () => {
expect(validator.isNumberValid(number)).toBe(true);
}
});
});
}
});
describe("test path validation", () => {
const invalid = ["//", "some//path", "end//"];
for (let path of invalid) {
it(`should return false for '${path}'`, () => {
expect(validator.isPathValid(path)).toBe(false);
});
}
const valid = ["", "/", "dir", "some/path", "end/"];
for (let path of valid) {
it(`should return true for '${path}'`, () => {
expect(validator.isPathValid(path)).toBe(true);
});
}
});