Calendar alternative view (#4254)

* Introduce a new view that shows all upcoming scheduled events

* remove log

* Fix unused component import that was breaking the build

* minor fix of inline style to className

* Correct PR comments

* Correct PR comments - move assignment inside className

* Alter some css colors - fix css issue that was putting the add-to-calendar button out of the box on screen resolutions more than 2000px width

* more PR comments fix - dark theme alignment
This commit is contained in:
Nikos Kontakis 2020-12-24 09:36:35 +02:00 committed by GitHub
parent a63ff78ab2
commit 6aec1ee17c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 148 additions and 13 deletions

View File

@ -3,7 +3,7 @@
import type { EntryInfo } from './types';
import React, { useMemo, useRef } from 'react';
import React, { useCallback, useMemo, useRef } from 'react';
import styled from 'styled-components';
import { Button } from '@polkadot/react-components';
@ -21,6 +21,7 @@ interface Props {
scheduled: EntryInfo[];
setNextDay: () => void;
setPrevDay: () => void;
setView: (v: boolean) => void;
}
const HOURS = ((): number[] => {
@ -33,7 +34,7 @@ const HOURS = ((): number[] => {
return hours;
})();
function Day ({ className, date, hasNextDay, now, scheduled, setNextDay, setPrevDay }: Props): React.ReactElement<Props> {
function Day ({ className, date, hasNextDay, now, scheduled, setNextDay, setPrevDay, setView }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const monthRef = useRef(MONTHS.map((m) => t(m)));
@ -47,10 +48,21 @@ function Day ({ className, date, hasNextDay, now, scheduled, setNextDay, setPrev
[date, now]
);
const viewSetter = useCallback(() => (
<Button
className='all-events-button'
icon={'list'}
onClick={() => setView(true)}
/>
), [setView]);
return (
<div className={className}>
<h1>
<div className='highlight--color'>{date.getDate()} {monthRef.current[date.getMonth()]} {date.getFullYear()} {isToday && <DayTime />}</div>
<div className='highlight--color'>
{viewSetter()}
{date.getDate()} {monthRef.current[date.getMonth()]} {date.getFullYear()} {isToday && <DayTime />}
</div>
<Button.Group>
<Button
icon='chevron-left'

View File

@ -14,9 +14,12 @@ import { dateCalendarFormat } from './util';
interface Props {
className?: string;
showAllEvents?: boolean;
item: EntryInfoTyped;
}
const options = { day: 'numeric', month: 'long', weekday: 'long', year: 'numeric' };
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function assertUnreachable (x: never): never {
throw new Error('We cannot get here');
@ -52,7 +55,7 @@ function exportCalendar (date: Date, description: string): void {
window.URL.revokeObjectURL(anchor.href);
}
function DayItem ({ className, item: { date, info, type } }: Props): React.ReactElement<Props> {
function DayItem ({ className, item: { date, info, type }, showAllEvents }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const [description, setDescription] = useState<string>('');
@ -156,11 +159,14 @@ function DayItem ({ className, item: { date, info, type } }: Props): React.React
return (
<div className={className}>
{showAllEvents &&
<div className='itemDate'>{date.toLocaleString(undefined, options)}</div>
}
<div className='itemTime'>{date.toLocaleTimeString().split(':').slice(0, 2).join(':')}</div>
{desc}
{date && (
<Button
className='exportCal'
className={showAllEvents ? 'exportCal exportCal-allEvents' : 'exportCal'}
icon='calendar-plus'
onClick={_exportCal}
/>
@ -190,6 +196,16 @@ export default React.memo(styled(DayItem)`
}
}
.exportCal-allEvents {
right: 3.5rem;
}
.itemDate {
padding: 0 0.375rem;
border-radius: 0.25rem;
width: 17rem;
}
.itemTime {
background: #999;
padding: 0 0.375rem;

View File

@ -0,0 +1,73 @@
// Copyright 2017-2020 @polkadot/app-calendar authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { ThemeProps } from '@polkadot/react-components/types';
import type { EntryInfo } from './types';
import React, { useCallback, useMemo } from 'react';
import styled from 'styled-components';
import { Button } from '@polkadot/react-components';
import DayItem from './DayItem';
interface Props {
className?: string;
scheduled: EntryInfo[];
setView: (v: boolean) => void;
}
function UpcomingEvents ({ className, scheduled, setView }: Props): React.ReactElement<Props> {
const sched = useMemo(
() => scheduled.sort((a, b) => a.dateTime - b.dateTime),
[scheduled]
);
const viewSetter = useCallback(() => (
<Button
className='all-events-button'
icon={'calendar'}
onClick={() => setView(false)}
/>
), [setView]);
return (
<div className={className}>
<h1>
<div className='highlight--color'>
{viewSetter()}
Upcoming Events
</div>
</h1>
<ul className='allEventsWrapper'>
{sched.map((item, index): React.ReactNode => {
return (
<DayItem
className={'all-events-rows'}
item={item}
key={index}
showAllEvents
/>
);
})}
</ul>
</div>
);
}
export default React.memo(styled(UpcomingEvents)(({ theme }: ThemeProps) => `
flex: 0;
max-width: max-content;
.all-events-rows {
padding: 10px 0;
font-size: 13px;
&:nth-child(odd) {
background: ${theme.bgTable};
}
}
.allEventsWrapper {
padding-inline-start: 10px;
}
`));

View File

@ -12,6 +12,7 @@ import { Tabs } from '@polkadot/react-components';
import Day from './Day';
import Month from './Month';
import { useTranslation } from './translate';
import UpcomingEvents from './UpcomingEvents';
import useScheduled from './useScheduled';
import { getDateState, nextMonth, prevMonth } from './util';
@ -27,6 +28,7 @@ function CalendarApp ({ basePath, className }: Props): React.ReactElement<Props>
const scheduled = useScheduled();
const [now, setNow] = useState(new Date());
const [dateState, setDateState] = useState(getDateState(now, now));
const [allEventsView, setAllEventsView] = useState(false);
const itemsRef = useRef([{
isRoot: true,
@ -108,6 +110,11 @@ function CalendarApp ({ basePath, className }: Props): React.ReactElement<Props>
[]
);
const _setAllEventsView = useCallback(
(v) => setAllEventsView(v),
[]
);
return (
<main className={className}>
<header>
@ -127,14 +134,28 @@ function CalendarApp ({ basePath, className }: Props): React.ReactElement<Props>
setPrevMonth={_prevMonth}
state={dateState}
/>
<Day
date={dateState.dateSelected}
hasNextDay={hasNextDay}
now={now}
scheduled={scheduled}
setNextDay={_nextDay}
setPrevDay={_prevDay}
/>
<div className='wrapper-style'>
{allEventsView
? (
<UpcomingEvents
className='upcoming-events'
scheduled={scheduled}
setView={_setAllEventsView}
/>
)
: (
<Day
date={dateState.dateSelected}
hasNextDay={hasNextDay}
now={now}
scheduled={scheduled}
setNextDay={_nextDay}
setPrevDay={_prevDay}
setView={_setAllEventsView}
/>
)
}
</div>
</div>
</main>
);
@ -146,6 +167,15 @@ export default React.memo(styled(CalendarApp)(({ theme }: ThemeProps) => `
display: flex;
flex-wrap: nowrap;
.wrapper-style {
flex: 1;
.upcoming-events {
position: relative;
max-width: 100%;
}
}
> div {
background-color: ${theme.bgTable};
border: 1px solid ${theme.borderTable};
@ -166,6 +196,10 @@ export default React.memo(styled(CalendarApp)(({ theme }: ThemeProps) => `
justify-content: space-between;
padding: 0.5rem 0.5rem 0 1rem;
.all-events-button {
margin-right: 1rem;
}
.ui--Button {
font-size: 1rem;
}