Skip to content

Commit

Permalink
Refactored Calendar component to remove dependency of primereact. (#2592
Browse files Browse the repository at this point in the history


* Refactored Calendar component to remove dependency of primereact.

* Modified according to pr review

* Modified according to pr review

* Add unit tests

* Upgrade unit tests for node environment

* Support all languages

* use useTranslation get current language

* update UI & useMemo Strategy

* update UI

* table cell align center

* add focus control

* update focus control

* fix unit test

* not move focus when outside the table
  • Loading branch information
mortoys authored Mar 25, 2023
1 parent b3db62a commit 9e559cb
Show file tree
Hide file tree
Showing 11 changed files with 849 additions and 161 deletions.
1 change: 0 additions & 1 deletion packages/neuron-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
"immer": "9.0.16",
"jsqr": "1.4.0",
"office-ui-fabric-react": "7.199.6",
"primereact": "8.7.1",
"qr.js": "0.0.0",
"react": "17.0.2",
"react-dom": "17.0.2",
Expand Down
2 changes: 2 additions & 0 deletions packages/neuron-ui/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,8 @@
"tag": "D"
},
"timezone": "Time Zone",
"previous-month": "previous month",
"next-month": "next month",
"start-tomorrow": "Selected time should start from tomorrow."
},
"sign-and-verify": {
Expand Down
2 changes: 2 additions & 0 deletions packages/neuron-ui/src/locales/zh-tw.json
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,8 @@
"tag": "十二月"
},
"timezone": "時區",
"previous-month": "上個月",
"next-month": "下個月",
"start-tomorrow": "所選時間不能早於明天。"
},
"sign-and-verify": {
Expand Down
2 changes: 2 additions & 0 deletions packages/neuron-ui/src/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,8 @@
"tag": "十二月"
},
"timezone": "时区",
"previous-month": "上个月",
"next-month": "下个月",
"start-tomorrow": "所选时间不能早于明天。"
},
"sign-and-verify": {
Expand Down
154 changes: 154 additions & 0 deletions packages/neuron-ui/src/tests/calendar/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import {
isDayInRange,
isMonthInRange,
isYearInRange,
isDateEqual,
getMonthCalendar,
getLocalMonthNames,
getLocalMonthShortNames,
getLocalWeekNames,
} from '../../widgets/Calendar/utils'

describe('Check day in range', () => {
it('check no restrictions', () => {
expect(isDayInRange(new Date(2023, 1, 1), {})).toBe(true)
})
it('check minDate', () => {
expect(isDayInRange(new Date(2023, 1, 1), { minDate: new Date(2023, 1, 1) })).toBe(true)
expect(isDayInRange(new Date(2023, 1, 1), { minDate: new Date(2023, 1, 1, 12) })).toBe(true)
expect(isDayInRange(new Date(2023, 1, 1), { minDate: new Date(2023, 1, 2) })).toBe(false)
})
it('check maxDate', () => {
expect(isDayInRange(new Date(2023, 1, 2), { maxDate: new Date(2023, 1, 2) })).toBe(true)
expect(isDayInRange(new Date(2023, 1, 2), { maxDate: new Date(2023, 1, 1) })).toBe(false)
expect(isDayInRange(new Date(2023, 1, 2), { maxDate: new Date(2023, 1, 1, 12) })).toBe(false)
})
})

describe('Check month in range', () => {
it('check no restrictions', () => {
expect(isMonthInRange(2023, 1, {})).toBe(true)
})
it('check minDate', () => {
expect(isMonthInRange(2023, 1, { minDate: new Date(2023, 1, 1) })).toBe(false)
expect(isMonthInRange(2023, 1, { minDate: new Date(2023, 0, 31) })).toBe(true)
})
it('check maxDate', () => {
expect(isMonthInRange(2023, 2, { maxDate: new Date(2023, 1, 1) })).toBe(true)
expect(isMonthInRange(2023, 2, { maxDate: new Date(2023, 0, 31) })).toBe(false)
})
})

describe('Check year in range', () => {
it('check no restrictions', () => {
expect(isYearInRange(2023, {})).toBe(true)
})
it('check minDate', () => {
expect(isYearInRange(2023, { minDate: new Date(2023, 1, 1) })).toBe(true)
expect(isYearInRange(2023, { minDate: new Date(2024, 1, 1) })).toBe(false)
expect(isYearInRange(2023, { minDate: new Date(2022, 1, 1) })).toBe(true)
})
it('check maxDate', () => {
expect(isYearInRange(2023, { maxDate: new Date(2023, 1, 1) })).toBe(true)
expect(isYearInRange(2023, { maxDate: new Date(2024, 1, 1) })).toBe(true)
expect(isYearInRange(2023, { maxDate: new Date(2022, 1, 1) })).toBe(false)
})
})

describe('Check date equal', () => {
it('undefined in one side', () => {
expect(isDateEqual(new Date(2023, 2, 1), undefined)).toBe(false)
expect(isDateEqual(undefined, new Date(2023, 2, 1))).toBe(false)
})
it('check date equal', () => {
expect(isDateEqual(new Date(2023, 2, 1), new Date(2023, 2, 1))).toBe(true)
})
it('check date equal ignore time', () => {
expect(isDateEqual(new Date(2023, 2, 1, 12), new Date(2023, 2, 1, 18))).toBe(true)
})
})

describe('Generate monthly calendar data', () => {
it('Test month calendar output', () => {
expect(getMonthCalendar(2023, 1).map(week => week.map(date => `${date.year}/${date.month}/${date.date}`))).toEqual([
['2023/1/1', '2023/1/2', '2023/1/3', '2023/1/4', '2023/1/5', '2023/1/6', '2023/1/7'],
['2023/1/8', '2023/1/9', '2023/1/10', '2023/1/11', '2023/1/12', '2023/1/13', '2023/1/14'],
['2023/1/15', '2023/1/16', '2023/1/17', '2023/1/18', '2023/1/19', '2023/1/20', '2023/1/21'],
['2023/1/22', '2023/1/23', '2023/1/24', '2023/1/25', '2023/1/26', '2023/1/27', '2023/1/28'],
['2023/1/29', '2023/1/30', '2023/1/31', '2023/2/1', '2023/2/2', '2023/2/3', '2023/2/4'],
['2023/2/5', '2023/2/6', '2023/2/7', '2023/2/8', '2023/2/9', '2023/2/10', '2023/2/11'],
])
})

it('Test month canlendar with specified start weekday', () => {
expect(
getMonthCalendar(2023, 1, 1).map(week => week.map(date => `${date.year}/${date.month}/${date.date}`))
).toEqual([
['2022/12/26', '2022/12/27', '2022/12/28', '2022/12/29', '2022/12/30', '2022/12/31', '2023/1/1'],
['2023/1/2', '2023/1/3', '2023/1/4', '2023/1/5', '2023/1/6', '2023/1/7', '2023/1/8'],
['2023/1/9', '2023/1/10', '2023/1/11', '2023/1/12', '2023/1/13', '2023/1/14', '2023/1/15'],
['2023/1/16', '2023/1/17', '2023/1/18', '2023/1/19', '2023/1/20', '2023/1/21', '2023/1/22'],
['2023/1/23', '2023/1/24', '2023/1/25', '2023/1/26', '2023/1/27', '2023/1/28', '2023/1/29'],
['2023/1/30', '2023/1/31', '2023/2/1', '2023/2/2', '2023/2/3', '2023/2/4', '2023/2/5'],
])
})
})

describe('Get Local Month Short Names', () => {
it('Chinese', () => {
const names = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
expect(getLocalMonthShortNames('zh')).toEqual(names)
})

it('English', () => {
const names = ['Jan.', 'Feb.', 'Mar.', 'Apr.', 'May.', 'Jun.', 'Jul.', 'Aug.', 'Sep.', 'Oct.', 'Nov.', 'Dec.']
expect(getLocalMonthShortNames('en')).toEqual(names)
})
})

describe('Get Local Month Names', () => {
it('Chinese', () => {
const names = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月']
expect(getLocalMonthNames('zh')).toEqual(names)
})

it('English', () => {
const names = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
]
expect(getLocalMonthNames('en')).toEqual(names)
})
})

describe('Get Local Week Names', () => {
it('Chinese', () => {
const names = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
expect(getLocalWeekNames('zh')).toEqual(names)
})

it('English', () => {
const names = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
expect(getLocalWeekNames('en')).toEqual(names)
})

it('Traditional Chinese', () => {
const names = ['週日', '週一', '週二', '週三', '週四', '週五', '週六']
expect(getLocalWeekNames('zh-TW')).toEqual(names)
})

it('Japanese', () => {
const names = ['日', '月', '火', '水', '木', '金', '土']
expect(getLocalWeekNames('ja')).toEqual(names)
})
})
130 changes: 130 additions & 0 deletions packages/neuron-ui/src/widgets/Calendar/calendar.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
@import '../../styles/mixin.scss';

.srOnly {
position: absolute;
top: -10000px;
left: -10000px;
}

@mixin button {
@include medium-text;
appearance: none;
cursor: pointer;
font-size: 0.75rem;
line-height: 1rem;
font-weight: 500;
padding: 7px 7px;
border: none;
border-radius: 2px;
margin: 0;
box-sizing: border-box;
border-radius: 2px;
background-color: transparent;
min-width: 0;
&:hover, &:focus {
@include semi-bold-text;
background-color: #efefef;
}
&[disabled] {
cursor: not-allowed;
opacity: 0.5;
box-shadow: none !important;
pointer-events: none;
&:hover {
background-color: transparent;
}
}
}

.calendar {
.calOptions {
width: 100%;
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
list-style-type: none;
list-style: none;
padding: 0;

li {
flex-grow: 1;
}

button {
@include button;
width: 100px;
&[aria-checked="true"] {
background-color: var(--nervos-green);
color: white;
}
}
}
}

.calendarHeader {
display: flex;
justify-content: space-between;
border-bottom: 1px solid #eee;
margin-top: 10px;
margin-bottom: 10px;

.calPrev, .calNext {
@include button;
width: 30px;
}
.calPrev {
order: 1;

&::before {
content: '<';
}
}
.calNext {
order: 3;

&::before {
content: '>';
}
}

.calTitle {
order: 2;
margin: 0;
font-size: 0;

button {
@include button;
@include semi-bold-text;
height: 100%;
min-width: 100px;
margin-right: 10px;
}
}
}

.calendarTable {
width: 100%;

td {
text-align: center;
}

.calTableHeader {
@include semi-bold-text;
font-size: 13px;
}

.calDateItem {
@include button;
width: 30px;
height: 30px;
border-radius: 50%;
&[aria-current="date"] {
color: var(--nervos-green);
}
&[aria-pressed="true"] {
background-color: var(--nervos-green);
color: white;
}
}
}
Loading

1 comment on commit 9e559cb

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Packaging for test is done in 4517012464

Please sign in to comment.