mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-09 15:05:44 +01:00
merged
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import injectSheet from "react-jss";
|
||||
import Tooltip from './Tooltip';
|
||||
import HelpIcon from './HelpIcon';
|
||||
import classNames from "classnames";
|
||||
import Tooltip from "./Tooltip";
|
||||
import HelpIcon from "./HelpIcon";
|
||||
|
||||
const styles = {
|
||||
tooltip: {
|
||||
@@ -14,21 +15,22 @@ const styles = {
|
||||
|
||||
type Props = {
|
||||
message: string,
|
||||
className?: string,
|
||||
classes: any
|
||||
}
|
||||
};
|
||||
|
||||
class Help extends React.Component<Props> {
|
||||
|
||||
render() {
|
||||
const { message, classes } = this.props;
|
||||
const { message, className, classes } = this.props;
|
||||
return (
|
||||
<Tooltip className={classes.tooltip} message={message}>
|
||||
<Tooltip
|
||||
className={classNames(classes.tooltip, className)}
|
||||
message={message}
|
||||
>
|
||||
<HelpIcon />
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default injectSheet(styles)(Help);
|
||||
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import injectSheet from "react-jss";
|
||||
import classNames from "classnames";
|
||||
import Icon from "./Icon";
|
||||
|
||||
type Props = {
|
||||
classes: any
|
||||
};
|
||||
|
||||
const styles = {
|
||||
textinfo: {
|
||||
color: "#98d8f3 !important"
|
||||
}
|
||||
textinfo: {
|
||||
color: "#98d8f3 !important"
|
||||
}
|
||||
};
|
||||
|
||||
class HelpIcon extends React.Component<Props> {
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
return <i className={classNames("fa fa-question-circle has-text-info", classes.textinfo)}></i>;
|
||||
return (
|
||||
<Icon className={classes.textinfo} name="question-circle" />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,22 +4,26 @@ import classNames from "classnames";
|
||||
|
||||
type Props = {
|
||||
title?: string,
|
||||
name: string
|
||||
}
|
||||
name: string,
|
||||
color: string,
|
||||
className?: string
|
||||
};
|
||||
|
||||
export default class Icon extends React.Component<Props> {
|
||||
static defaultProps = {
|
||||
color: "grey-light"
|
||||
};
|
||||
|
||||
render() {
|
||||
const { title, name } = this.props;
|
||||
if(title) {
|
||||
const { title, name, color, className } = this.props;
|
||||
if (title) {
|
||||
return (
|
||||
<i title={title} className={classNames("is-icon", "fas", "fa-fw", "fa-" + name)}/>
|
||||
<i
|
||||
title={title}
|
||||
className={classNames("fas", "fa-fw", "fa-" + name, `has-text-${color}`, className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<i className={classNames("is-icon", "fas", "fa-" + name)}/>
|
||||
);
|
||||
return <i className={classNames("fas", "fa-" + name, `has-text-${color}`, className)} />;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import SyntaxHighlighter from "./SyntaxHighlighter";
|
||||
import Markdown from "react-markdown/with-html";
|
||||
import {binder} from "@scm-manager/ui-extensions";
|
||||
import MarkdownHeadingRenderer from "./MarkdownHeadingRenderer";
|
||||
import { withRouter } from "react-router-dom";
|
||||
|
||||
import injectSheet from "react-jss";
|
||||
import Markdown from "react-markdown/with-html";
|
||||
import { binder } from "@scm-manager/ui-extensions";
|
||||
import SyntaxHighlighter from "./SyntaxHighlighter";
|
||||
import MarkdownHeadingRenderer from "./MarkdownHeadingRenderer";
|
||||
|
||||
type Props = {
|
||||
content: string,
|
||||
@@ -14,11 +14,34 @@ type Props = {
|
||||
enableAnchorHeadings: boolean,
|
||||
|
||||
// context props
|
||||
classes: any,
|
||||
location: any
|
||||
};
|
||||
|
||||
class MarkdownView extends React.Component<Props> {
|
||||
const styles = {
|
||||
markdown: {
|
||||
"& > .content": {
|
||||
"& > h1, h2, h3, h4, h5, h6": {
|
||||
margin: "0.5rem 0",
|
||||
fontSize: "0.9rem"
|
||||
},
|
||||
"& > h1": {
|
||||
fontWeight: "700"
|
||||
},
|
||||
"& > h2": {
|
||||
fontWeight: "600"
|
||||
},
|
||||
"& > h3, h4, h5, h6": {
|
||||
fontWeight: "500"
|
||||
},
|
||||
"& strong": {
|
||||
fontWeight: "500"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class MarkdownView extends React.Component<Props> {
|
||||
static defaultProps = {
|
||||
enableAnchorHeadings: false
|
||||
};
|
||||
@@ -45,16 +68,22 @@ class MarkdownView extends React.Component<Props> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const {content, renderers, renderContext, enableAnchorHeadings} = this.props;
|
||||
const {
|
||||
content,
|
||||
renderers,
|
||||
renderContext,
|
||||
enableAnchorHeadings,
|
||||
classes
|
||||
} = this.props;
|
||||
|
||||
const rendererFactory = binder.getExtension("markdown-renderer-factory");
|
||||
let rendererList = renderers;
|
||||
|
||||
if (rendererFactory){
|
||||
if (rendererFactory) {
|
||||
rendererList = rendererFactory(renderContext);
|
||||
}
|
||||
|
||||
if (!rendererList){
|
||||
if (!rendererList) {
|
||||
rendererList = {};
|
||||
}
|
||||
|
||||
@@ -62,12 +91,12 @@ class MarkdownView extends React.Component<Props> {
|
||||
rendererList.heading = MarkdownHeadingRenderer;
|
||||
}
|
||||
|
||||
if (!rendererList.code){
|
||||
if (!rendererList.code) {
|
||||
rendererList.code = SyntaxHighlighter;
|
||||
}
|
||||
|
||||
return (
|
||||
<div ref={el => (this.contentRef = el)}>
|
||||
<div className={classes.markdown} ref={el => (this.contentRef = el)}>
|
||||
<Markdown
|
||||
className="content"
|
||||
skipHtml={true}
|
||||
@@ -80,4 +109,4 @@ class MarkdownView extends React.Component<Props> {
|
||||
}
|
||||
}
|
||||
|
||||
export default withRouter(MarkdownView);
|
||||
export default injectSheet(styles)(withRouter(MarkdownView));
|
||||
|
||||
60
scm-ui-components/packages/ui-components/src/Tag.js
Normal file
60
scm-ui-components/packages/ui-components/src/Tag.js
Normal file
@@ -0,0 +1,60 @@
|
||||
//@flow
|
||||
import * as React from "react";
|
||||
import classNames from "classnames";
|
||||
|
||||
type Props = {
|
||||
className?: string,
|
||||
color: string,
|
||||
icon?: string,
|
||||
label: string,
|
||||
title?: string,
|
||||
onClick?: () => void,
|
||||
onRemove?: () => void
|
||||
};
|
||||
|
||||
class Tag extends React.Component<Props> {
|
||||
static defaultProps = {
|
||||
color: "light"
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
className,
|
||||
color,
|
||||
icon,
|
||||
label,
|
||||
title,
|
||||
onClick,
|
||||
onRemove
|
||||
} = this.props;
|
||||
let showIcon = null;
|
||||
if (icon) {
|
||||
showIcon = (
|
||||
<>
|
||||
<i className={classNames("fas", `fa-${icon}`)} />
|
||||
|
||||
</>
|
||||
);
|
||||
}
|
||||
let showDelete = null;
|
||||
if (onRemove) {
|
||||
showDelete = <a className="tag is-delete" onClick={onRemove} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<span
|
||||
className={classNames("tag", `is-${color}`, className)}
|
||||
title={title}
|
||||
onClick={onClick}
|
||||
>
|
||||
{showIcon}
|
||||
{label}
|
||||
</span>
|
||||
{showDelete}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Tag;
|
||||
@@ -1,11 +1,11 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import Button, { type ButtonProps } from "./Button";
|
||||
|
||||
class AddButton extends React.Component<ButtonProps> {
|
||||
render() {
|
||||
return <Button color="default" {...this.props} />;
|
||||
}
|
||||
}
|
||||
|
||||
export default AddButton;
|
||||
//@flow
|
||||
import React from "react";
|
||||
import Button, { type ButtonProps } from "./Button";
|
||||
|
||||
class AddButton extends React.Component<ButtonProps> {
|
||||
render() {
|
||||
return <Button color="default" icon="plus" {...this.props} />;
|
||||
}
|
||||
}
|
||||
|
||||
export default AddButton;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import * as React from "react";
|
||||
import classNames from "classnames";
|
||||
import { withRouter } from "react-router-dom";
|
||||
import Icon from "../Icon";
|
||||
|
||||
export type ButtonProps = {
|
||||
label?: string,
|
||||
@@ -9,10 +10,12 @@ export type ButtonProps = {
|
||||
disabled?: boolean,
|
||||
action?: (event: Event) => void,
|
||||
link?: string,
|
||||
fullWidth?: boolean,
|
||||
className?: string,
|
||||
icon?: string,
|
||||
fullWidth?: boolean,
|
||||
reducedMobile?: boolean,
|
||||
children?: React.Node,
|
||||
|
||||
|
||||
// context props
|
||||
classes: any
|
||||
};
|
||||
@@ -47,12 +50,40 @@ class Button extends React.Component<Props> {
|
||||
disabled,
|
||||
type,
|
||||
color,
|
||||
className,
|
||||
icon,
|
||||
fullWidth,
|
||||
children,
|
||||
className
|
||||
reducedMobile,
|
||||
children
|
||||
} = this.props;
|
||||
const loadingClass = loading ? "is-loading" : "";
|
||||
const fullWidthClass = fullWidth ? "is-fullwidth" : "";
|
||||
const reducedMobileClass = reducedMobile ? "is-reduced-mobile" : "";
|
||||
if (icon) {
|
||||
return (
|
||||
<button
|
||||
type={type}
|
||||
disabled={disabled}
|
||||
onClick={this.onClick}
|
||||
className={classNames(
|
||||
"button",
|
||||
"is-" + color,
|
||||
loadingClass,
|
||||
fullWidthClass,
|
||||
reducedMobileClass,
|
||||
className
|
||||
)}
|
||||
>
|
||||
<span className="icon is-medium">
|
||||
<Icon name={icon} color="inherit" />
|
||||
</span>
|
||||
<span>
|
||||
{label} {children}
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
type={type}
|
||||
@@ -69,8 +100,7 @@ class Button extends React.Component<Props> {
|
||||
{label} {children}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default withRouter(Button);
|
||||
|
||||
@@ -14,7 +14,7 @@ class ButtonAddons extends React.Component<Props> {
|
||||
const childWrapper = [];
|
||||
React.Children.forEach(children, child => {
|
||||
if (child) {
|
||||
childWrapper.push(<p className="control">{child}</p>);
|
||||
childWrapper.push(<p className="control" key={childWrapper.length}>{child}</p>);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import Button, { type ButtonProps } from "./Button";
|
||||
|
||||
class DeleteButton extends React.Component<ButtonProps> {
|
||||
render() {
|
||||
return <Button color="warning" {...this.props} />;
|
||||
return <Button color="warning" icon="times" {...this.props} />;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class DownloadButton extends React.Component<Props> {
|
||||
const { displayName, url, disabled, onClick } = this.props;
|
||||
const onClickOrDefault = !!onClick ? onClick : () => {};
|
||||
return (
|
||||
<a className="button is-large is-link" href={url} disabled={disabled} onClick={onClickOrDefault}>
|
||||
<a className="button is-link" href={url} disabled={disabled} onClick={onClickOrDefault}>
|
||||
<span className="icon is-medium">
|
||||
<i className="fas fa-arrow-circle-down" />
|
||||
</span>
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import { translate } from "react-i18next";
|
||||
import RemoveEntryOfTableButton from "../buttons/RemoveEntryOfTableButton";
|
||||
|
||||
type Props = {
|
||||
members: string[],
|
||||
t: string => string,
|
||||
memberListChanged: (string[]) => void
|
||||
};
|
||||
|
||||
type State = {};
|
||||
|
||||
class MemberNameTable extends React.Component<Props, State> {
|
||||
render() {
|
||||
const { t } = this.props;
|
||||
return (
|
||||
<div>
|
||||
<table className="table is-hoverable is-fullwidth">
|
||||
<tbody>
|
||||
{this.props.members.map(member => {
|
||||
return (
|
||||
<tr key={member}>
|
||||
<td key={member}>{member}</td>
|
||||
<td>
|
||||
<RemoveEntryOfTableButton
|
||||
entryname={member}
|
||||
removeEntry={this.removeEntry}
|
||||
disabled={false}
|
||||
label={t("remove-member-button.label")}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
removeEntry = (membername: string) => {
|
||||
const newMembers = this.props.members.filter(name => name !== membername);
|
||||
this.props.memberListChanged(newMembers);
|
||||
};
|
||||
}
|
||||
|
||||
export default translate("groups")(MemberNameTable);
|
||||
@@ -0,0 +1,37 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import { translate } from "react-i18next";
|
||||
import type { DisplayedUser } from "@scm-manager/ui-types";
|
||||
import TagGroup from "./TagGroup";
|
||||
|
||||
type Props = {
|
||||
members: string[],
|
||||
memberListChanged: (string[]) => void,
|
||||
t: string => string
|
||||
};
|
||||
|
||||
class MemberNameTagGroup extends React.Component<Props> {
|
||||
render() {
|
||||
const { members, t } = this.props;
|
||||
const membersExtended = members.map(id => {
|
||||
return { id, displayName: id, mail: "" };
|
||||
});
|
||||
return (
|
||||
<TagGroup
|
||||
items={membersExtended}
|
||||
label={t("group.members")}
|
||||
helpText={t("groupForm.help.memberHelpText")}
|
||||
onRemove={this.removeEntry}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
removeEntry = (membersExtended: DisplayedUser[]) => {
|
||||
const members = membersExtended.map(function(item) {
|
||||
return item["id"];
|
||||
});
|
||||
this.props.memberListChanged(members);
|
||||
};
|
||||
}
|
||||
|
||||
export default translate("groups")(MemberNameTagGroup);
|
||||
@@ -1,7 +1,7 @@
|
||||
// @flow
|
||||
|
||||
import React from "react";
|
||||
import {translate} from "react-i18next";
|
||||
import { translate } from "react-i18next";
|
||||
import InputField from "./InputField";
|
||||
|
||||
type State = {
|
||||
@@ -40,26 +40,28 @@ class PasswordConfirmation extends React.Component<Props, State> {
|
||||
render() {
|
||||
const { t } = this.props;
|
||||
return (
|
||||
<>
|
||||
<InputField
|
||||
label={t("password.newPassword")}
|
||||
type="password"
|
||||
onChange={this.handlePasswordChange}
|
||||
value={this.state.password ? this.state.password : ""}
|
||||
validationError={!this.state.passwordValid}
|
||||
errorMessage={t("password.passwordInvalid")}
|
||||
helpText={t("password.passwordHelpText")}
|
||||
/>
|
||||
<InputField
|
||||
label={t("password.confirmPassword")}
|
||||
type="password"
|
||||
onChange={this.handlePasswordValidationChange}
|
||||
value={this.state ? this.state.confirmedPassword : ""}
|
||||
validationError={this.state.passwordConfirmationFailed}
|
||||
errorMessage={t("password.passwordConfirmFailed")}
|
||||
helpText={t("password.passwordConfirmHelpText")}
|
||||
/>
|
||||
</>
|
||||
<div className="columns is-multiline">
|
||||
<div className="column is-half">
|
||||
<InputField
|
||||
label={t("password.newPassword")}
|
||||
type="password"
|
||||
onChange={this.handlePasswordChange}
|
||||
value={this.state.password ? this.state.password : ""}
|
||||
validationError={!this.state.passwordValid}
|
||||
errorMessage={t("password.passwordInvalid")}
|
||||
/>
|
||||
</div>
|
||||
<div className="column is-half">
|
||||
<InputField
|
||||
label={t("password.confirmPassword")}
|
||||
type="password"
|
||||
onChange={this.handlePasswordValidationChange}
|
||||
value={this.state ? this.state.confirmedPassword : ""}
|
||||
validationError={this.state.passwordConfirmationFailed}
|
||||
errorMessage={t("password.passwordConfirmFailed")}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -99,7 +101,7 @@ class PasswordConfirmation extends React.Component<Props, State> {
|
||||
};
|
||||
|
||||
isValid = () => {
|
||||
return this.state.passwordValid && !this.state.passwordConfirmationFailed
|
||||
return this.state.passwordValid && !this.state.passwordConfirmationFailed;
|
||||
};
|
||||
|
||||
propagateChange = () => {
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
//@flow
|
||||
import * as React from "react";
|
||||
import injectSheet from "react-jss";
|
||||
import type { DisplayedUser } from "@scm-manager/ui-types";
|
||||
import { Help, Tag } from "../index";
|
||||
|
||||
type Props = {
|
||||
items: DisplayedUser[],
|
||||
label: string,
|
||||
helpText?: string,
|
||||
onRemove: (DisplayedUser[]) => void,
|
||||
|
||||
// context props
|
||||
classes: Object
|
||||
};
|
||||
|
||||
const styles = {
|
||||
help: {
|
||||
position: "relative"
|
||||
}
|
||||
};
|
||||
|
||||
class TagGroup extends React.Component<Props> {
|
||||
render() {
|
||||
const { items, label, helpText, classes } = this.props;
|
||||
let help = null;
|
||||
if (helpText) {
|
||||
help = <Help className={classes.help} message={helpText} />;
|
||||
}
|
||||
return (
|
||||
<div className="field is-grouped is-grouped-multiline">
|
||||
{label && items ? (
|
||||
<div className="control">
|
||||
<strong>
|
||||
{label}
|
||||
{help}
|
||||
{items.length > 0 ? ":" : ""}
|
||||
</strong>
|
||||
</div>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
{items.map((item, key) => {
|
||||
return (
|
||||
<div className="control" key={key}>
|
||||
<div className="tags has-addons">
|
||||
<Tag
|
||||
color="info is-outlined"
|
||||
label={item.displayName}
|
||||
onRemove={() => this.removeEntry(item)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
removeEntry = item => {
|
||||
const newItems = this.props.items.filter(name => name !== item);
|
||||
this.props.onRemove(newItems);
|
||||
};
|
||||
}
|
||||
|
||||
export default injectSheet(styles)(TagGroup);
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
export { default as AddEntryToTableField } from "./AddEntryToTableField.js";
|
||||
export { default as AutocompleteAddEntryToTableField } from "./AutocompleteAddEntryToTableField.js";
|
||||
export { default as MemberNameTable } from "./MemberNameTable.js";
|
||||
export { default as TagGroup } from "./TagGroup.js";
|
||||
export { default as MemberNameTagGroup } from "./MemberNameTagGroup.js";
|
||||
export { default as Checkbox } from "./Checkbox.js";
|
||||
export { default as Radio } from "./Radio.js";
|
||||
export { default as FilterInput } from "./FilterInput.js";
|
||||
|
||||
@@ -23,6 +23,7 @@ export { default as FileSize } from "./FileSize.js";
|
||||
export { default as ProtectedRoute } from "./ProtectedRoute.js";
|
||||
export { default as Help } from "./Help";
|
||||
export { default as HelpIcon } from "./HelpIcon";
|
||||
export { default as Tag } from "./Tag";
|
||||
export { default as Tooltip } from "./Tooltip";
|
||||
// TODO do we need this? getPageFromMatch is already exported by urls
|
||||
export { getPageFromMatch } from "./urls";
|
||||
|
||||
@@ -18,7 +18,15 @@ class Modal extends React.Component<Props> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { title, closeFunction, body, footer, active, className, headColor } = this.props;
|
||||
const {
|
||||
title,
|
||||
closeFunction,
|
||||
body,
|
||||
footer,
|
||||
active,
|
||||
className,
|
||||
headColor
|
||||
} = this.props;
|
||||
|
||||
const isActive = active ? "is-active" : null;
|
||||
|
||||
@@ -31,7 +39,12 @@ class Modal extends React.Component<Props> {
|
||||
<div className={classNames("modal", className, isActive)}>
|
||||
<div className="modal-background" />
|
||||
<div className="modal-card">
|
||||
<header className={classNames("modal-card-head", `has-background-${headColor}`)}>
|
||||
<header
|
||||
className={classNames(
|
||||
"modal-card-head",
|
||||
`has-background-${headColor}`
|
||||
)}
|
||||
>
|
||||
<p className="modal-card-title is-marginless">{title}</p>
|
||||
<button
|
||||
className="delete"
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import {Change, Diff as DiffComponent, DiffObjectProps, File, getChangeKey, Hunk} from "react-diff-view";
|
||||
import {
|
||||
Change,
|
||||
Diff as DiffComponent,
|
||||
DiffObjectProps,
|
||||
File,
|
||||
getChangeKey,
|
||||
Hunk
|
||||
} from "react-diff-view";
|
||||
import injectSheets from "react-jss";
|
||||
import classNames from "classnames";
|
||||
import {translate} from "react-i18next";
|
||||
import {Button, ButtonGroup} from "../buttons";
|
||||
import { translate } from "react-i18next";
|
||||
import { Button, ButtonGroup } from "../buttons";
|
||||
import Tag from "../Tag";
|
||||
|
||||
const styles = {
|
||||
panel: {
|
||||
@@ -34,12 +42,35 @@ const styles = {
|
||||
},
|
||||
changeType: {
|
||||
marginLeft: ".75rem"
|
||||
},
|
||||
diff: {
|
||||
/* column sizing */
|
||||
"& > colgroup .diff-gutter-col": {
|
||||
width: "3.25rem"
|
||||
},
|
||||
/* prevent following content from moving down */
|
||||
"& > .diff-gutter:empty:hover::after": {
|
||||
fontSize: "0.7rem"
|
||||
},
|
||||
/* smaller font size for code */
|
||||
"& .diff-line": {
|
||||
fontSize: "0.75rem"
|
||||
},
|
||||
/* comment padding for sideBySide view */
|
||||
"&.split .diff-widget-content .is-indented-line": {
|
||||
paddingLeft: "3.25rem"
|
||||
},
|
||||
/* comment padding for combined view */
|
||||
"&.unified .diff-widget-content .is-indented-line": {
|
||||
paddingLeft: "6.5rem"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
type Props = DiffObjectProps & {
|
||||
file: File,
|
||||
collapsible: true,
|
||||
|
||||
// context props
|
||||
classes: any,
|
||||
t: string => string
|
||||
@@ -179,23 +210,21 @@ class DiffFile extends React.Component<Props, State> {
|
||||
}
|
||||
const color =
|
||||
value === "added"
|
||||
? "is-success"
|
||||
? "success is-outlined"
|
||||
: value === "deleted"
|
||||
? "is-danger"
|
||||
: "is-info";
|
||||
? "danger is-outlined"
|
||||
: "info is-outlined";
|
||||
|
||||
return (
|
||||
<span
|
||||
<Tag
|
||||
className={classNames(
|
||||
"tag",
|
||||
"is-rounded",
|
||||
"has-text-weight-normal",
|
||||
color,
|
||||
classes.changeType
|
||||
)}
|
||||
>
|
||||
{value}
|
||||
</span>
|
||||
color={color}
|
||||
label={value}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -219,15 +248,18 @@ class DiffFile extends React.Component<Props, State> {
|
||||
: null;
|
||||
icon = "fa fa-angle-down";
|
||||
body = (
|
||||
<div className="panel-block is-paddingless is-size-7">
|
||||
<div className="panel-block is-paddingless">
|
||||
{fileAnnotations}
|
||||
<DiffComponent viewType={viewType}>
|
||||
<DiffComponent
|
||||
className={classNames(viewType, classes.diff)}
|
||||
viewType={viewType}
|
||||
>
|
||||
{file.hunks.map(this.renderHunk)}
|
||||
</DiffComponent>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const collapseIcon = collapsible? <i className={icon} />: null;
|
||||
const collapseIcon = collapsible ? <i className={icon} /> : null;
|
||||
|
||||
const fileControls = fileControlFactory
|
||||
? fileControlFactory(file, this.setCollapse)
|
||||
|
||||
@@ -25,7 +25,7 @@ const styles = {
|
||||
}
|
||||
},
|
||||
avatarFigure: {
|
||||
marginTop: ".25rem",
|
||||
marginTop: ".5rem",
|
||||
marginRight: ".5rem"
|
||||
},
|
||||
avatarImage: {
|
||||
@@ -35,6 +35,9 @@ const styles = {
|
||||
metadata: {
|
||||
marginLeft: 0
|
||||
},
|
||||
authorMargin: {
|
||||
marginTop: "0.5rem"
|
||||
},
|
||||
isVcentered: {
|
||||
alignSelf: "center"
|
||||
},
|
||||
@@ -70,15 +73,6 @@ class ChangesetRow extends React.Component<Props> {
|
||||
<div className="column is-three-fifths">
|
||||
<div className="columns is-gapless">
|
||||
<div className="column is-four-fifths">
|
||||
<h4 className="has-text-weight-bold is-ellipsis-overflow">
|
||||
<ExtensionPoint
|
||||
name="changeset.description"
|
||||
props={{ changeset, value: description.title }}
|
||||
renderAll={false}
|
||||
>
|
||||
{description.title}
|
||||
</ExtensionPoint>
|
||||
</h4>
|
||||
<div className="media">
|
||||
<AvatarWrapper>
|
||||
<figure
|
||||
@@ -90,6 +84,15 @@ class ChangesetRow extends React.Component<Props> {
|
||||
</figure>
|
||||
</AvatarWrapper>
|
||||
<div className={classNames(classes.metadata, "media-right")}>
|
||||
<h4 className="has-text-weight-bold is-ellipsis-overflow">
|
||||
<ExtensionPoint
|
||||
name="changeset.description"
|
||||
props={{ changeset, value: description.title }}
|
||||
renderAll={false}
|
||||
>
|
||||
{description.title}
|
||||
</ExtensionPoint>
|
||||
</h4>
|
||||
<p className="is-hidden-touch">
|
||||
<Interpolate
|
||||
i18nKey="changeset.summary"
|
||||
@@ -104,7 +107,7 @@ class ChangesetRow extends React.Component<Props> {
|
||||
time={dateFromNow}
|
||||
/>
|
||||
</p>
|
||||
<p className="is-size-7">
|
||||
<p className={classNames("is-size-7", classes.authorMargin)}>
|
||||
<ChangesetAuthor changeset={changeset} />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -10,7 +10,7 @@ type Props = {
|
||||
class ChangesetTag extends React.Component<Props> {
|
||||
render() {
|
||||
const { tag } = this.props;
|
||||
return <ChangesetTagBase icon={"fa-tag"} label={tag.name} />;
|
||||
return <ChangesetTagBase icon="tag" label={tag.name} />;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +1,19 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import injectSheet from "react-jss";
|
||||
import classNames from "classnames";
|
||||
|
||||
const styles = {
|
||||
spacing: {
|
||||
marginRight: ".25rem"
|
||||
}
|
||||
};
|
||||
import Tag from "../../Tag";
|
||||
|
||||
type Props = {
|
||||
icon: string,
|
||||
label: string,
|
||||
|
||||
// context props
|
||||
classes: Object
|
||||
label: string
|
||||
};
|
||||
|
||||
class ChangesetTagBase extends React.Component<Props> {
|
||||
render() {
|
||||
const { icon, label, classes } = this.props;
|
||||
const { icon, label } = this.props;
|
||||
return (
|
||||
<span className={classNames("tag", "is-info")}>
|
||||
<span className={classNames("fa", icon, classes.spacing)} /> {label}
|
||||
</span>
|
||||
<Tag color="info" icon={icon} label={label} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default injectSheet(styles)(ChangesetTagBase);
|
||||
export default ChangesetTagBase;
|
||||
|
||||
@@ -1,24 +1,27 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import type { Tag } from "@scm-manager/ui-types";
|
||||
import ChangesetTagBase from "./ChangesetTagBase";
|
||||
import { translate } from "react-i18next";
|
||||
import type { Tag } from "@scm-manager/ui-types";
|
||||
import Tooltip from "../../Tooltip";
|
||||
import ChangesetTagBase from "./ChangesetTagBase";
|
||||
|
||||
type Props = {
|
||||
tags: Tag[],
|
||||
|
||||
// context props
|
||||
t: (string) => string
|
||||
t: string => string
|
||||
};
|
||||
|
||||
class ChangesetTagsCollapsed extends React.Component<Props> {
|
||||
render() {
|
||||
const { tags, t } = this.props;
|
||||
const message = tags.map((tag) => tag.name).join(", ");
|
||||
const message = tags.map(tag => tag.name).join(", ");
|
||||
return (
|
||||
<Tooltip location="top" message={message}>
|
||||
<ChangesetTagBase icon={"fa-tags"} label={ tags.length + " " + t("changeset.tags") } />
|
||||
<ChangesetTagBase
|
||||
icon="tags"
|
||||
label={tags.length + " " + t("changeset.tags")}
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user