Commit bfadcd29 by Torkel Ödegaard Committed by GitHub

Merge branch 'master' into page-layout-component

parents 1dfabf49 9ecfc39b
...@@ -38,7 +38,7 @@ Name | Description ...@@ -38,7 +38,7 @@ Name | Description
### IAM Roles ### IAM Roles
Currently all access to CloudWatch is done server side by the Grafana backend using the official AWS SDK. If you grafana Currently all access to CloudWatch is done server side by the Grafana backend using the official AWS SDK. If your Grafana
server is running on AWS you can use IAM Roles and authentication will be handled automatically. server is running on AWS you can use IAM Roles and authentication will be handled automatically.
Checkout AWS docs on [IAM Roles](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html) Checkout AWS docs on [IAM Roles](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html)
......
import React from 'react';
import { shallow } from 'enzyme';
import { FormField, Props } from './FormField';
const setup = (propOverrides?: object) => {
const props: Props = {
label: 'Test',
labelWidth: 11,
value: 10,
onChange: jest.fn(),
};
Object.assign(props, propOverrides);
return shallow(<FormField {...props} />);
};
describe('Render', () => {
it('should render component', () => {
const wrapper = setup();
expect(wrapper).toMatchSnapshot();
});
});
import React, { InputHTMLAttributes, FunctionComponent } from 'react';
import { FormLabel } from '..';
export interface Props extends InputHTMLAttributes<HTMLInputElement> {
label: string;
labelWidth?: number;
inputWidth?: number;
}
const defaultProps = {
labelWidth: 6,
inputWidth: 12,
};
const FormField: FunctionComponent<Props> = ({ label, labelWidth, inputWidth, ...inputProps }) => {
return (
<div className="form-field">
<FormLabel width={labelWidth}>{label}</FormLabel>
<input type="text" className={`gf-form-input width-${inputWidth}`} {...inputProps} />
</div>
);
};
FormField.defaultProps = defaultProps;
export { FormField };
.form-field {
margin-bottom: $gf-form-margin;
display: flex;
flex-direction: row;
align-items: center;
text-align: left;
position: relative;
&--grow {
flex-grow: 1;
}
}
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Render should render component 1`] = `
<div
className="form-field"
>
<Component
width={11}
>
Test
</Component>
<input
className="gf-form-input width-12"
onChange={[MockFunction]}
type="text"
value={10}
/>
</div>
`;
import React, { SFC, ReactNode } from 'react'; import React, { FunctionComponent, ReactNode } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { Tooltip } from '..';
interface Props { interface Props {
children: ReactNode; children: ReactNode;
htmlFor?: string;
className?: string; className?: string;
htmlFor?: string;
isFocused?: boolean; isFocused?: boolean;
isInvalid?: boolean; isInvalid?: boolean;
tooltip?: string;
width?: number;
} }
export const GfFormLabel: SFC<Props> = ({ children, isFocused, isInvalid, className, htmlFor, ...rest }) => { export const FormLabel: FunctionComponent<Props> = ({
const classes = classNames('gf-form-label', className, { children,
isFocused,
isInvalid,
className,
htmlFor,
tooltip,
width,
...rest
}) => {
const classes = classNames(`gf-form-label width-${width ? width : '10'}`, className, {
'gf-form-label--is-focused': isFocused, 'gf-form-label--is-focused': isFocused,
'gf-form-label--is-invalid': isInvalid, 'gf-form-label--is-invalid': isInvalid,
}); });
...@@ -18,6 +30,13 @@ export const GfFormLabel: SFC<Props> = ({ children, isFocused, isInvalid, classN ...@@ -18,6 +30,13 @@ export const GfFormLabel: SFC<Props> = ({ children, isFocused, isInvalid, classN
return ( return (
<label className={classes} {...rest} htmlFor={htmlFor}> <label className={classes} {...rest} htmlFor={htmlFor}>
{children} {children}
{tooltip && (
<Tooltip placement="auto" content={tooltip}>
<div className="gf-form-help-icon--right-normal">
<i className="gicon gicon-question gicon--has-hover" />
</div>
</Tooltip>
)}
</label> </label>
); );
}; };
import React, { SFC, ReactNode } from 'react';
import { Tooltip } from '../Tooltip/Tooltip';
interface Props {
tooltip?: string;
for?: string;
children: ReactNode;
width?: number;
className?: string;
}
export const Label: SFC<Props> = props => {
return (
<span className={`gf-form-label width-${props.width ? props.width : '10'}`}>
<span>{props.children}</span>
{props.tooltip && (
<Tooltip placement="auto" content={props.tooltip}>
<div className="gf-form-help-icon--right-normal">
<i className="gicon gicon-question gicon--has-hover" />
</div>
</Tooltip>
)}
</span>
);
};
...@@ -16,7 +16,7 @@ import SelectOptionGroup from './SelectOptionGroup'; ...@@ -16,7 +16,7 @@ import SelectOptionGroup from './SelectOptionGroup';
import IndicatorsContainer from './IndicatorsContainer'; import IndicatorsContainer from './IndicatorsContainer';
import NoOptionsMessage from './NoOptionsMessage'; import NoOptionsMessage from './NoOptionsMessage';
import resetSelectStyles from './resetSelectStyles'; import resetSelectStyles from './resetSelectStyles';
import { CustomScrollbar } from '@grafana/ui'; import { CustomScrollbar } from '..';
export interface SelectOptionItem { export interface SelectOptionItem {
label?: string; label?: string;
......
...@@ -102,6 +102,7 @@ $select-input-bg-disabled: $input-bg-disabled; ...@@ -102,6 +102,7 @@ $select-input-bg-disabled: $input-bg-disabled;
.gf-form-select-box__value-container { .gf-form-select-box__value-container {
display: table-cell; display: table-cell;
padding: 6px 10px; padding: 6px 10px;
vertical-align: middle;
> div { > div {
display: inline-block; display: inline-block;
} }
......
import React, { PureComponent } from 'react'; import React, { ChangeEvent, PureComponent } from 'react';
import { MappingType, ValueMapping } from '../../types/panel'; import { MappingType, ValueMapping } from '../../types';
import { Label } from '../Label/Label'; import { FormField, FormLabel, Select } from '..';
import { Select } from '../Select/Select';
export interface Props { export interface Props {
valueMapping: ValueMapping; valueMapping: ValueMapping;
...@@ -32,19 +31,19 @@ export default class MappingRow extends PureComponent<Props, State> { ...@@ -32,19 +31,19 @@ export default class MappingRow extends PureComponent<Props, State> {
this.state = { ...props.valueMapping }; this.state = { ...props.valueMapping };
} }
onMappingValueChange = (event: React.ChangeEvent<HTMLInputElement>) => { onMappingValueChange = (event: ChangeEvent<HTMLInputElement>) => {
this.setState({ value: event.target.value }); this.setState({ value: event.target.value });
}; };
onMappingFromChange = (event: React.ChangeEvent<HTMLInputElement>) => { onMappingFromChange = (event: ChangeEvent<HTMLInputElement>) => {
this.setState({ from: event.target.value }); this.setState({ from: event.target.value });
}; };
onMappingToChange = (event: React.ChangeEvent<HTMLInputElement>) => { onMappingToChange = (event: ChangeEvent<HTMLInputElement>) => {
this.setState({ to: event.target.value }); this.setState({ to: event.target.value });
}; };
onMappingTextChange = (event: React.ChangeEvent<HTMLInputElement>) => { onMappingTextChange = (event: ChangeEvent<HTMLInputElement>) => {
this.setState({ text: event.target.value }); this.setState({ text: event.target.value });
}; };
...@@ -62,30 +61,28 @@ export default class MappingRow extends PureComponent<Props, State> { ...@@ -62,30 +61,28 @@ export default class MappingRow extends PureComponent<Props, State> {
if (type === MappingType.RangeToText) { if (type === MappingType.RangeToText) {
return ( return (
<> <>
<div className="gf-form"> <FormField
<Label width={4}>From</Label> label="From"
<input labelWidth={4}
className="gf-form-input width-8" inputWidth={8}
value={from} onBlur={this.updateMapping}
onBlur={this.updateMapping} onChange={this.onMappingFromChange}
onChange={this.onMappingFromChange} value={from}
/> />
</div> <FormField
<div className="gf-form"> label="To"
<Label width={4}>To</Label> labelWidth={4}
inputWidth={8}
onBlur={this.updateMapping}
onChange={this.onMappingToChange}
value={to}
/>
<div className="gf-form gf-form--grow">
<FormLabel width={4}>Text</FormLabel>
<input <input
className="gf-form-input width-8" className="gf-form-input"
value={to}
onBlur={this.updateMapping} onBlur={this.updateMapping}
onChange={this.onMappingToChange}
/>
</div>
<div className="gf-form">
<Label width={4}>Text</Label>
<input
className="gf-form-input width-10"
value={text} value={text}
onBlur={this.updateMapping}
onChange={this.onMappingTextChange} onChange={this.onMappingTextChange}
/> />
</div> </div>
...@@ -95,17 +92,16 @@ export default class MappingRow extends PureComponent<Props, State> { ...@@ -95,17 +92,16 @@ export default class MappingRow extends PureComponent<Props, State> {
return ( return (
<> <>
<div className="gf-form"> <FormField
<Label width={4}>Value</Label> label="Value"
<input labelWidth={4}
className="gf-form-input width-8" onBlur={this.updateMapping}
onBlur={this.updateMapping} onChange={this.onMappingValueChange}
onChange={this.onMappingValueChange} value={value}
value={value} inputWidth={8}
/> />
</div>
<div className="gf-form gf-form--grow"> <div className="gf-form gf-form--grow">
<Label width={4}>Text</Label> <FormLabel width={4}>Text</FormLabel>
<input <input
className="gf-form-input" className="gf-form-input"
onBlur={this.updateMapping} onBlur={this.updateMapping}
...@@ -123,7 +119,7 @@ export default class MappingRow extends PureComponent<Props, State> { ...@@ -123,7 +119,7 @@ export default class MappingRow extends PureComponent<Props, State> {
return ( return (
<div className="gf-form-inline"> <div className="gf-form-inline">
<div className="gf-form"> <div className="gf-form">
<Label width={5}>Type</Label> <FormLabel width={5}>Type</FormLabel>
<Select <Select
placeholder="Choose type" placeholder="Choose type"
isSearchable={false} isSearchable={false}
......
...@@ -7,3 +7,4 @@ ...@@ -7,3 +7,4 @@
@import 'PanelOptionsGrid/PanelOptionsGrid'; @import 'PanelOptionsGrid/PanelOptionsGrid';
@import 'ColorPicker/ColorPicker'; @import 'ColorPicker/ColorPicker';
@import 'ValueMappingsEditor/ValueMappingsEditor'; @import 'ValueMappingsEditor/ValueMappingsEditor';
@import "FormField/FormField";
...@@ -2,7 +2,6 @@ export { DeleteButton } from './DeleteButton/DeleteButton'; ...@@ -2,7 +2,6 @@ export { DeleteButton } from './DeleteButton/DeleteButton';
export { Tooltip } from './Tooltip/Tooltip'; export { Tooltip } from './Tooltip/Tooltip';
export { Portal } from './Portal/Portal'; export { Portal } from './Portal/Portal';
export { CustomScrollbar } from './CustomScrollbar/CustomScrollbar'; export { CustomScrollbar } from './CustomScrollbar/CustomScrollbar';
export { Label } from './Label/Label';
// Select // Select
export { Select, AsyncSelect, SelectOptionItem } from './Select/Select'; export { Select, AsyncSelect, SelectOptionItem } from './Select/Select';
...@@ -10,12 +9,15 @@ export { IndicatorsContainer } from './Select/IndicatorsContainer'; ...@@ -10,12 +9,15 @@ export { IndicatorsContainer } from './Select/IndicatorsContainer';
export { NoOptionsMessage } from './Select/NoOptionsMessage'; export { NoOptionsMessage } from './Select/NoOptionsMessage';
export { default as resetSelectStyles } from './Select/resetSelectStyles'; export { default as resetSelectStyles } from './Select/resetSelectStyles';
// Forms
export { FormLabel } from './FormLabel/FormLabel';
export { FormField } from './FormField/FormField';
export { LoadingPlaceholder } from './LoadingPlaceholder/LoadingPlaceholder'; export { LoadingPlaceholder } from './LoadingPlaceholder/LoadingPlaceholder';
export { ColorPicker } from './ColorPicker/ColorPicker'; export { ColorPicker } from './ColorPicker/ColorPicker';
export { SeriesColorPickerPopover } from './ColorPicker/SeriesColorPickerPopover'; export { SeriesColorPickerPopover } from './ColorPicker/SeriesColorPickerPopover';
export { SeriesColorPicker } from './ColorPicker/SeriesColorPicker'; export { SeriesColorPicker } from './ColorPicker/SeriesColorPicker';
export { ThresholdsEditor } from './ThresholdsEditor/ThresholdsEditor'; export { ThresholdsEditor } from './ThresholdsEditor/ThresholdsEditor';
export { GfFormLabel } from './GfFormLabel/GfFormLabel';
export { Graph } from './Graph/Graph'; export { Graph } from './Graph/Graph';
export { PanelOptionsGroup } from './PanelOptionsGroup/PanelOptionsGroup'; export { PanelOptionsGroup } from './PanelOptionsGroup/PanelOptionsGroup';
export { PanelOptionsGrid } from './PanelOptionsGrid/PanelOptionsGrid'; export { PanelOptionsGrid } from './PanelOptionsGrid/PanelOptionsGrid';
......
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import { Select, Label } from '@grafana/ui';
import { FormLabel, Select } from '@grafana/ui';
import { getBackendSrv, BackendSrv } from 'app/core/services/backend_srv'; import { getBackendSrv, BackendSrv } from 'app/core/services/backend_srv';
import { DashboardSearchHit } from 'app/types'; import { DashboardSearchHit } from 'app/types';
...@@ -99,12 +99,12 @@ export class SharedPreferences extends PureComponent<Props, State> { ...@@ -99,12 +99,12 @@ export class SharedPreferences extends PureComponent<Props, State> {
/> />
</div> </div>
<div className="gf-form"> <div className="gf-form">
<Label <FormLabel
width={11} width={11}
tooltip="Not finding dashboard you want? Star it first, then it should appear in this select box." tooltip="Not finding dashboard you want? Star it first, then it should appear in this select box."
> >
Home Dashboard Home Dashboard
</Label> </FormLabel>
<Select <Select
value={dashboards.find(dashboard => dashboard.id === homeDashboardId)} value={dashboards.find(dashboard => dashboard.id === homeDashboardId)}
getOptionValue={i => i.id} getOptionValue={i => i.id}
......
...@@ -10,7 +10,7 @@ import { Input } from 'app/core/components/Form'; ...@@ -10,7 +10,7 @@ import { Input } from 'app/core/components/Form';
import { EventsWithValidation } from 'app/core/components/Form/Input'; import { EventsWithValidation } from 'app/core/components/Form/Input';
import { InputStatus } from 'app/core/components/Form/Input'; import { InputStatus } from 'app/core/components/Form/Input';
import DataSourceOption from './DataSourceOption'; import DataSourceOption from './DataSourceOption';
import { GfFormLabel } from '@grafana/ui'; import { FormLabel } from '@grafana/ui';
// Types // Types
import { PanelModel } from '../panel_model'; import { PanelModel } from '../panel_model';
...@@ -164,7 +164,7 @@ export class QueryOptions extends PureComponent<Props, State> { ...@@ -164,7 +164,7 @@ export class QueryOptions extends PureComponent<Props, State> {
{this.renderOptions()} {this.renderOptions()}
<div className="gf-form"> <div className="gf-form">
<GfFormLabel>Relative time</GfFormLabel> <FormLabel>Relative time</FormLabel>
<Input <Input
type="text" type="text"
className="width-6" className="width-6"
......
import React, { FC } from 'react'; import React, { FC } from 'react';
import { Label } from '@grafana/ui'; import { FormLabel } from '@grafana/ui';
import { Switch } from '../../../core/components/Switch/Switch'; import { Switch } from '../../../core/components/Switch/Switch';
export interface Props { export interface Props {
...@@ -15,14 +14,14 @@ const BasicSettings: FC<Props> = ({ dataSourceName, isDefault, onDefaultChange, ...@@ -15,14 +14,14 @@ const BasicSettings: FC<Props> = ({ dataSourceName, isDefault, onDefaultChange,
<div className="gf-form-group"> <div className="gf-form-group">
<div className="gf-form-inline"> <div className="gf-form-inline">
<div className="gf-form max-width-30" style={{ marginRight: '3px' }}> <div className="gf-form max-width-30" style={{ marginRight: '3px' }}>
<Label <FormLabel
tooltip={ tooltip={
'The name is used when you select the data source in panels. The Default data source is ' + 'The name is used when you select the data source in panels. The Default data source is ' +
'preselected in new panels.' 'preselected in new panels.'
} }
> >
Name Name
</Label> </FormLabel>
<input <input
className="gf-form-input max-width-23" className="gf-form-input max-width-23"
type="text" type="text"
......
import React from 'react'; import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Label } from '@grafana/ui'; import { FormLabel } from '@grafana/ui';
import { SharedPreferences } from 'app/core/components/SharedPreferences/SharedPreferences'; import { SharedPreferences } from 'app/core/components/SharedPreferences/SharedPreferences';
import { updateTeam } from './state/actions'; import { updateTeam } from './state/actions';
...@@ -51,7 +51,7 @@ export class TeamSettings extends React.Component<Props, State> { ...@@ -51,7 +51,7 @@ export class TeamSettings extends React.Component<Props, State> {
<h3 className="page-sub-heading">Team Settings</h3> <h3 className="page-sub-heading">Team Settings</h3>
<form name="teamDetailsForm" className="gf-form-group" onSubmit={this.onUpdate}> <form name="teamDetailsForm" className="gf-form-group" onSubmit={this.onUpdate}>
<div className="gf-form max-width-30"> <div className="gf-form max-width-30">
<Label>Name</Label> <FormLabel>Name</FormLabel>
<input <input
type="text" type="text"
required required
...@@ -62,9 +62,9 @@ export class TeamSettings extends React.Component<Props, State> { ...@@ -62,9 +62,9 @@ export class TeamSettings extends React.Component<Props, State> {
</div> </div>
<div className="gf-form max-width-30"> <div className="gf-form max-width-30">
<Label tooltip="This is optional and is primarily used to set the team profile avatar (via gravatar service)"> <FormLabel tooltip="This is optional and is primarily used to set the team profile avatar (via gravatar service)">
Email Email
</Label> </FormLabel>
<input <input
type="email" type="email"
className="gf-form-input max-width-22" className="gf-form-input max-width-22"
......
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import { PanelOptionsProps, PanelOptionsGroup, Label } from '@grafana/ui'; import { FormField, PanelOptionsProps, PanelOptionsGroup } from '@grafana/ui';
import { Switch } from 'app/core/components/Switch/Switch'; import { Switch } from 'app/core/components/Switch/Switch';
import { GaugeOptions } from './types'; import { GaugeOptions } from './types';
...@@ -21,14 +21,8 @@ export default class GaugeOptionsEditor extends PureComponent<PanelOptionsProps< ...@@ -21,14 +21,8 @@ export default class GaugeOptionsEditor extends PureComponent<PanelOptionsProps<
return ( return (
<PanelOptionsGroup title="Gauge"> <PanelOptionsGroup title="Gauge">
<div className="gf-form"> <FormField label="Min value" labelWidth={8} onChange={this.onMinValueChange} value={minValue} />
<Label width={8}>Min value</Label> <FormField label="Max value" labelWidth={8} onChange={this.onMaxValueChange} value={maxValue} />
<input type="text" className="gf-form-input width-12" onChange={this.onMinValueChange} value={minValue} />
</div>
<div className="gf-form">
<Label width={8}>Max value</Label>
<input type="text" className="gf-form-input width-12" onChange={this.onMaxValueChange} value={maxValue} />
</div>
<Switch <Switch
label="Show labels" label="Show labels"
labelClass="width-8" labelClass="width-8"
......
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import { PanelOptionsProps, PanelOptionsGroup, Label, Select } from '@grafana/ui'; import { FormField, FormLabel, PanelOptionsProps, PanelOptionsGroup, Select } from '@grafana/ui';
import UnitPicker from 'app/core/components/Select/UnitPicker'; import UnitPicker from 'app/core/components/Select/UnitPicker';
import { GaugeOptions } from './types'; import { GaugeOptions } from './types';
...@@ -41,7 +40,7 @@ export default class ValueOptions extends PureComponent<PanelOptionsProps<GaugeO ...@@ -41,7 +40,7 @@ export default class ValueOptions extends PureComponent<PanelOptionsProps<GaugeO
return ( return (
<PanelOptionsGroup title="Value"> <PanelOptionsGroup title="Value">
<div className="gf-form"> <div className="gf-form">
<Label width={labelWidth}>Stat</Label> <FormLabel width={labelWidth}>Stat</FormLabel>
<Select <Select
width={12} width={12}
options={statOptions} options={statOptions}
...@@ -50,27 +49,19 @@ export default class ValueOptions extends PureComponent<PanelOptionsProps<GaugeO ...@@ -50,27 +49,19 @@ export default class ValueOptions extends PureComponent<PanelOptionsProps<GaugeO
/> />
</div> </div>
<div className="gf-form"> <div className="gf-form">
<Label width={labelWidth}>Unit</Label> <FormLabel width={labelWidth}>Unit</FormLabel>
<UnitPicker defaultValue={unit} onChange={this.onUnitChange} /> <UnitPicker defaultValue={unit} onChange={this.onUnitChange} />
</div> </div>
<div className="gf-form"> <FormField
<Label width={labelWidth}>Decimals</Label> label="Decimals"
<input labelWidth={labelWidth}
className="gf-form-input width-12" placeholder="auto"
type="number" onChange={this.onDecimalChange}
placeholder="auto" value={decimals || ''}
value={decimals || ''} type="number"
onChange={this.onDecimalChange} />
/> <FormField label="Prefix" labelWidth={labelWidth} onChange={this.onPrefixChange} value={prefix || ''} />
</div> <FormField label="Suffix" labelWidth={labelWidth} onChange={this.onSuffixChange} value={suffix || ''} />
<div className="gf-form">
<Label width={labelWidth}>Prefix</Label>
<input className="gf-form-input width-12" type="text" value={prefix || ''} onChange={this.onPrefixChange} />
</div>
<div className="gf-form">
<Label width={labelWidth}>Suffix</Label>
<input className="gf-form-input width-12" type="text" value={suffix || ''} onChange={this.onSuffixChange} />
</div>
</PanelOptionsGroup> </PanelOptionsGroup>
); );
} }
......
...@@ -8,8 +8,6 @@ RUN git clone https://github.com/aptly-dev/aptly $GOPATH/src/github.com/aptly-de ...@@ -8,8 +8,6 @@ RUN git clone https://github.com/aptly-dev/aptly $GOPATH/src/github.com/aptly-de
FROM circleci/python:2.7-stretch FROM circleci/python:2.7-stretch
ENV PATH=$PATH:/opt/google-cloud-sdk/bin
USER root USER root
RUN pip install awscli && \ RUN pip install awscli && \
...@@ -18,7 +16,9 @@ RUN pip install awscli && \ ...@@ -18,7 +16,9 @@ RUN pip install awscli && \
apt update && \ apt update && \
apt install -y createrepo expect && \ apt install -y createrepo expect && \
apt-get autoremove -y && \ apt-get autoremove -y && \
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/* && \
ln -s /opt/google-cloud-sdk/bin/gsutil /usr/bin/gsutil && \
ln -s /opt/google-cloud-sdk/bin/gcloud /usr/bin/gcloud
COPY --from=0 /go/bin/aptly /usr/local/bin/aptly COPY --from=0 /go/bin/aptly /usr/local/bin/aptly
......
#!/bin/bash #!/bin/bash
_version="1.1.0" _version="1.2.0"
_tag="grafana/grafana-ci-deploy:${_version}" _tag="grafana/grafana-ci-deploy:${_version}"
docker build -t $_tag . docker build -t $_tag .
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment