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:
parent
a63ff78ab2
commit
6aec1ee17c
@ -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'
|
||||
|
||||
@ -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;
|
||||
|
||||
73
packages/page-calendar/src/UpcomingEvents.tsx
Normal file
73
packages/page-calendar/src/UpcomingEvents.tsx
Normal 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;
|
||||
}
|
||||
`));
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user