Web: Components: added calendar locale, function onChange, base styles, date format and new file calendar helper.
This commit is contained in:
parent
3827beaa1e
commit
222cf080d8
@ -0,0 +1,50 @@
|
|||||||
|
// Calendar builder for a month in the specified year
|
||||||
|
// Returns an array of the calendar dates.
|
||||||
|
// Each calendar date is represented as an array => [YYYY, MM, DD]
|
||||||
|
|
||||||
|
export default (month = THIS_MONTH, year = THIS_YEAR) => {
|
||||||
|
|
||||||
|
// Get number of days in the month and the month's first day
|
||||||
|
|
||||||
|
const monthDays = getMonthDays(month, year);
|
||||||
|
const monthFirstDay = getMonthFirstDay(month, year);
|
||||||
|
|
||||||
|
// Get number of days to be displayed from previous and next months
|
||||||
|
// These ensure a total of 42 days (6 weeks) displayed on the calendar
|
||||||
|
|
||||||
|
const daysFromPrevMonth = monthFirstDay - 1;
|
||||||
|
const daysFromNextMonth = (CALENDAR_WEEKS * 7) - (daysFromPrevMonth + monthDays);
|
||||||
|
|
||||||
|
// Get the previous and next months and years
|
||||||
|
|
||||||
|
const { month: prevMonth, year: prevMonthYear } = getPreviousMonth(month, year);
|
||||||
|
const { month: nextMonth, year: nextMonthYear } = getNextMonth(month, year);
|
||||||
|
|
||||||
|
// Get number of days in previous month
|
||||||
|
const prevMonthDays = getMonthDays(prevMonth, prevMonthYear);
|
||||||
|
|
||||||
|
// Builds dates to be displayed from previous month
|
||||||
|
|
||||||
|
const prevMonthDates = [...new Array(daysFromPrevMonth)].map((n, index) => {
|
||||||
|
const day = index + 1 + (prevMonthDays - daysFromPrevMonth);
|
||||||
|
return [ prevMonthYear, zeroPad(prevMonth, 2), zeroPad(day, 2) ];
|
||||||
|
});
|
||||||
|
|
||||||
|
// Builds dates to be displayed from current month
|
||||||
|
|
||||||
|
const thisMonthDates = [...new Array(monthDays)].map((n, index) => {
|
||||||
|
const day = index + 1;
|
||||||
|
return [year, zeroPad(month, 2), zeroPad(day, 2)];
|
||||||
|
});
|
||||||
|
|
||||||
|
// Builds dates to be displayed from next month
|
||||||
|
|
||||||
|
const nextMonthDates = [...new Array(daysFromNextMonth)].map((n, index) => {
|
||||||
|
const day = index + 1;
|
||||||
|
return [nextMonthYear, zeroPad(nextMonth, 2), zeroPad(day, 2)];
|
||||||
|
});
|
||||||
|
|
||||||
|
// Combines all dates from previous, current and next months
|
||||||
|
return [ ...prevMonthDates, ...thisMonthDates, ...nextMonthDates ];
|
||||||
|
|
||||||
|
}
|
168
web/ASC.Web.Components/src/components/calendar/index.js
Normal file
168
web/ASC.Web.Components/src/components/calendar/index.js
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import styled, { css } from 'styled-components';
|
||||||
|
import DatePicker, { registerLocale } from "react-datepicker";
|
||||||
|
import ComboBox from '../combobox';
|
||||||
|
import "react-datepicker/dist/react-datepicker.css";
|
||||||
|
import enGB from 'date-fns/locale/en-GB';
|
||||||
|
import calendar, { isDate, isSameDay, isSameMonth, getDateISO, getNextMonth, getPreviousMonth, WEEK_DAYS, CALENDAR_MONTHS } from "./helper-calendar";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const DataSelector = styled.div`
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
|
const CalendarContainer = styled.div`
|
||||||
|
width:500px;
|
||||||
|
height:500px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const DaysStyle = css`
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border-radius: 16px;
|
||||||
|
text-align: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
|
||||||
|
const CalendarStyle = styled.div`
|
||||||
|
|
||||||
|
.react-datepicker__month-container {
|
||||||
|
font-size: 13px;
|
||||||
|
font-family: Open Sans;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__header {
|
||||||
|
background-color: #fff;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__month {
|
||||||
|
margin-top: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__week {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day-name {
|
||||||
|
width: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day-names {
|
||||||
|
display: block;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day {
|
||||||
|
line-height: 2.5em;
|
||||||
|
color: #333;
|
||||||
|
${DaysStyle}
|
||||||
|
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-radius: 16px;
|
||||||
|
|
||||||
|
background-color: #ED7309;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker__day--selected {
|
||||||
|
${DaysStyle}
|
||||||
|
background-color: #F8F9F9;
|
||||||
|
}
|
||||||
|
|
||||||
|
react-datepicker__time-name {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
registerLocale('en-GB', enGB);
|
||||||
|
|
||||||
|
class Calendar extends Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
startDate: props.startDate
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
options = [
|
||||||
|
{ key: 0, label: '25 per page' },
|
||||||
|
{ key: 1, label: '50 per page', },
|
||||||
|
{ key: 2, label: '100 per page' }];
|
||||||
|
|
||||||
|
handleChange(date) {
|
||||||
|
this.setState({ startDate: date });
|
||||||
|
this.props.onChange && this.props.onChange(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
render() {
|
||||||
|
//console.log('RENDER');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CalendarContainer>
|
||||||
|
<DataSelector>
|
||||||
|
<ComboBox isDisabled={this.props.disabled} options={this.options} />
|
||||||
|
<ComboBox isDisabled={this.props.disabled} options={this.options} />
|
||||||
|
</DataSelector>
|
||||||
|
|
||||||
|
<CalendarStyle>
|
||||||
|
|
||||||
|
<DatePicker
|
||||||
|
inline
|
||||||
|
selected={this.state.startDate}
|
||||||
|
onChange={this.handleChange.bind(this)}
|
||||||
|
dateFormat={this.props.dateFormat}
|
||||||
|
disabled={this.props.disabled}
|
||||||
|
locale="en-GB"
|
||||||
|
renderCustomHeader={() => { }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</CalendarStyle>
|
||||||
|
|
||||||
|
</CalendarContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Calendar.propTypes = {
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
startDate: PropTypes.instanceOf(Date),
|
||||||
|
dateFormat: PropTypes.string,
|
||||||
|
themeColor: PropTypes.color
|
||||||
|
}
|
||||||
|
|
||||||
|
Calendar.defaultProps = {
|
||||||
|
startDate: new Date(),
|
||||||
|
dateFormat: "dd.MM.yyyy",
|
||||||
|
themeColor: '#ED7309'
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Calendar;
|
||||||
|
|
||||||
|
/*
|
||||||
|
const DataSelector2 = styled.div`
|
||||||
|
background: #eee;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
padding: 10px;
|
||||||
|
float: left;
|
||||||
|
width: 23.5%;
|
||||||
|
margin-right: 2%;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
`;
|
||||||
|
*/
|
@ -41,4 +41,5 @@ export { default as Textarea } from './components/textarea'
|
|||||||
export { default as ToggleButton } from './components/toggle-button'
|
export { default as ToggleButton } from './components/toggle-button'
|
||||||
export { default as LinkWithDropdown } from './components/link-with-dropdown'
|
export { default as LinkWithDropdown } from './components/link-with-dropdown'
|
||||||
export { default as TabContainer } from './components/tabs-container'
|
export { default as TabContainer } from './components/tabs-container'
|
||||||
export { default as DropDownProfileItem } from './components/drop-down-profile-item'
|
export { default as DropDownProfileItem } from './components/drop-down-profile-item'
|
||||||
|
export { default as Calendar } from './components/calendar'
|
29
web/ASC.Web.Storybook/stories/input/calendar/README.md
Normal file
29
web/ASC.Web.Storybook/stories/input/calendar/README.md
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# DateInput
|
||||||
|
|
||||||
|
#### Description
|
||||||
|
|
||||||
|
Custom date input
|
||||||
|
|
||||||
|
#### Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { DateInput } from 'asc-web-components';
|
||||||
|
|
||||||
|
<DateInput selected={new Date()} dateFormat="dd.MM.yyyy" onChange={date => {}}/>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Properties
|
||||||
|
|
||||||
|
https://reactdatepicker.com/
|
||||||
|
|
||||||
|
| Props | Type | Required | Values | Default | Description |
|
||||||
|
| ------------ | -------- | :------: | ------ | ------- | --------------------------------------- |
|
||||||
|
| `id` | `string` | - | - | - | Used as HTML `id` property |
|
||||||
|
| `name` | `string` | - | - | - | Used as HTML `name` property |
|
||||||
|
| `disabled` | `bool` | - | - | - | Used as HTML `disabled` property |
|
||||||
|
| `readOnly` | `bool` | - | - | - | Used as HTML `readOnly` property |
|
||||||
|
| `selected` | `date` | - | - | - | Selected date value |
|
||||||
|
| `onChange` | `func` | - | - | - | OnChange event |
|
||||||
|
| `dateFormat` | `string` | - | - | - | Date format string |
|
||||||
|
| `hasError` | `bool` | - | - | - | Indicates the input field has an error |
|
||||||
|
| `hasWarning` | `bool` | - | - | - | Indicates the input field has a warning |
|
@ -0,0 +1,60 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { storiesOf } from '@storybook/react';
|
||||||
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import { DateValue } from 'react-values'
|
||||||
|
import { withKnobs, boolean, text, color, select } from '@storybook/addon-knobs/react';
|
||||||
|
import withReadme from 'storybook-readme/with-readme';
|
||||||
|
import Readme from './README.md';
|
||||||
|
import { Calendar } from 'asc-web-components';
|
||||||
|
import Section from '../../../.storybook/decorators/section';
|
||||||
|
import { object } from '@storybook/addon-knobs/dist/deprecated';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
storiesOf('Components|Input', module)
|
||||||
|
.addDecorator(withKnobs)
|
||||||
|
.addDecorator(withReadme(Readme))
|
||||||
|
.add('calendar', () => (
|
||||||
|
<Section>
|
||||||
|
<Calendar
|
||||||
|
onChange={date => {
|
||||||
|
action('onChange')(date);
|
||||||
|
}}
|
||||||
|
dateFormat={text('dateFormat', 'dd.MM.yyyy')}
|
||||||
|
startDate = {new Date()}
|
||||||
|
disabled={boolean('disabled', false)}
|
||||||
|
themeColor={color('themeColor', '#ED7309')}
|
||||||
|
|
||||||
|
|
||||||
|
/>
|
||||||
|
</Section>
|
||||||
|
));
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
|
||||||
|
const sizeOptions = ['base', 'medium', 'big'];
|
||||||
|
size={select('size', sizeOptions, 'big')}
|
||||||
|
|
||||||
|
<Section>
|
||||||
|
<DateValue>
|
||||||
|
{({ value, set }) => (
|
||||||
|
<DateInput
|
||||||
|
id={text('id', '')}
|
||||||
|
name={text('name', '')}
|
||||||
|
disabled={boolean('disabled', false)}
|
||||||
|
readOnly={boolean('readOnly', false)}
|
||||||
|
selected={value}
|
||||||
|
onChange={date => {
|
||||||
|
action('onChange')(date);
|
||||||
|
set(date);
|
||||||
|
}}
|
||||||
|
dateFormat={text('dateFormat', 'dd.MM.yyyy')}
|
||||||
|
hasError={boolean('hasError', false)}
|
||||||
|
hasWarning={boolean('hasWarning', false)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</DateValue>
|
||||||
|
</Section>
|
||||||
|
*/
|
Loading…
Reference in New Issue
Block a user