Added support re-sizing and semantic colors
This commit is contained in:
parent
9647a8f920
commit
3b0022f214
|
@ -23,7 +23,7 @@
|
|||
}
|
||||
|
||||
.cardWrapper .dateBox {
|
||||
border-color: $ms-color-neutralTertiaryAlt;
|
||||
border-color: $ms-color-neutralLight;
|
||||
}
|
||||
|
||||
.normalCard .dateBoxContainer {
|
||||
|
@ -44,6 +44,7 @@
|
|||
.compactCard .dateBox {
|
||||
margin: auto 14px auto 0;
|
||||
min-width: 64px;
|
||||
background-color: $ms-color-white;
|
||||
}
|
||||
|
||||
[dir=rtl] .compactCard .dateBox {
|
||||
|
@ -111,7 +112,7 @@
|
|||
width: 100%;
|
||||
align-items: center;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
background-color: $ms-color-white;
|
||||
//background-color: $ms-color-white;
|
||||
border: 1px solid #eaeaea;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
|
|
|
@ -8,168 +8,186 @@ import { IEventCardProps } from ".";
|
|||
import { DateBox, DateBoxSize } from "../DateBox";
|
||||
import styles from "./EventCard.module.scss";
|
||||
import { Text } from "@microsoft/sp-core-library";
|
||||
import { IReadonlyTheme } from '@microsoft/sp-component-base';
|
||||
|
||||
/**
|
||||
* Shows an event in a document card
|
||||
*/
|
||||
export class EventCard extends React.Component<IEventCardProps, {}> {
|
||||
public render(): React.ReactElement<IEventCardProps> {
|
||||
const { isNarrow } = this.props;
|
||||
public render(): React.ReactElement<IEventCardProps> {
|
||||
const { isNarrow } = this.props;
|
||||
|
||||
if (isNarrow) {
|
||||
return this._renderNarrowCell();
|
||||
} else {
|
||||
return this._renderNormalCell();
|
||||
}
|
||||
if (isNarrow) {
|
||||
return this._renderNarrowCell();
|
||||
} else {
|
||||
return this._renderNormalCell();
|
||||
}
|
||||
}
|
||||
|
||||
private _renderNormalCell(): JSX.Element {
|
||||
const { start,
|
||||
end,
|
||||
allDay,
|
||||
title,
|
||||
url,
|
||||
category,
|
||||
// description,
|
||||
location } = this.props.event;
|
||||
const eventDate: moment.Moment = moment(start);
|
||||
const dateString: string = allDay ? eventDate.format(strings.AllDayDateFormat) : eventDate.format(strings.LocalizedTimeFormat);
|
||||
const { isEditMode } = this.props;
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
className={css(styles.cardWrapper)}
|
||||
data-is-focusable={true}
|
||||
data-is-focus-item={true}
|
||||
role="listitem"
|
||||
aria-label={Text.format(strings.EventCardWrapperArialLabel, title, `${dateString}`)}
|
||||
tabIndex={0}
|
||||
private _renderNormalCell(): JSX.Element {
|
||||
|
||||
const { start,
|
||||
end,
|
||||
allDay,
|
||||
title,
|
||||
url,
|
||||
category,
|
||||
// description,
|
||||
location } = this.props.event;
|
||||
const eventDate: moment.Moment = moment(start);
|
||||
const dateString: string = allDay ? eventDate.format(strings.AllDayDateFormat) : eventDate.format(strings.LocalizedTimeFormat);
|
||||
const { isEditMode } = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
className={css(styles.cardWrapper)}
|
||||
data-is-focusable={true}
|
||||
data-is-focus-item={true}
|
||||
role="listitem"
|
||||
aria-label={Text.format(strings.EventCardWrapperArialLabel, title, `${dateString}`)}
|
||||
tabIndex={0}
|
||||
>
|
||||
<DocumentCard
|
||||
className={css(styles.root, !isEditMode && styles.rootIsActionable, styles.normalCard)}
|
||||
type={DocumentCardType.normal}
|
||||
onClickHref={isEditMode ? null : url}
|
||||
>
|
||||
<FocusZone>
|
||||
<div className={styles.dateBoxContainer} style={{ height: 160 }}>
|
||||
<DateBox
|
||||
className={styles.dateBox}
|
||||
startDate={start}
|
||||
endDate={end}
|
||||
size={DateBoxSize.Medium}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.detailsContainer}>
|
||||
<div className={styles.category}>{category}</div>
|
||||
<div className={styles.title}>{title}</div>
|
||||
<div className={styles.datetime}>{dateString}</div>
|
||||
<div className={styles.location}>{location}</div>
|
||||
<ActionButton
|
||||
className={styles.addToMyCalendar}
|
||||
iconProps={{ iconName: "AddEvent" }}
|
||||
ariaLabel={strings.AddToCalendarAriaLabel}
|
||||
onClick={this._onAddToMyCalendar}
|
||||
>
|
||||
<DocumentCard
|
||||
className={css(styles.root, !isEditMode && styles.rootIsActionable, styles.normalCard)}
|
||||
type={DocumentCardType.normal}
|
||||
onClickHref={isEditMode ? null : url}
|
||||
>
|
||||
<FocusZone>
|
||||
<div className={styles.dateBoxContainer} style={{ height: 160 }}>
|
||||
<DateBox
|
||||
className={styles.dateBox}
|
||||
startDate={start}
|
||||
endDate={end}
|
||||
size={DateBoxSize.Medium}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.detailsContainer}>
|
||||
<div className={styles.category}>{category}</div>
|
||||
<div className={styles.title}>{title}</div>
|
||||
<div className={styles.datetime}>{dateString}</div>
|
||||
<div className={styles.location}>{location}</div>
|
||||
<ActionButton
|
||||
className={styles.addToMyCalendar}
|
||||
iconProps={{ iconName: "AddEvent" }}
|
||||
ariaLabel={strings.AddToCalendarAriaLabel}
|
||||
onClick={this._onAddToMyCalendar}
|
||||
>
|
||||
{strings.AddToCalendarButtonLabel}
|
||||
</ActionButton>
|
||||
</div>
|
||||
</FocusZone>
|
||||
</DocumentCard>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
{strings.AddToCalendarButtonLabel}
|
||||
</ActionButton>
|
||||
</div>
|
||||
</FocusZone>
|
||||
</DocumentCard>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private _renderNarrowCell(): JSX.Element {
|
||||
|
||||
const { start,
|
||||
end,
|
||||
allDay,
|
||||
title,
|
||||
url,
|
||||
// category,
|
||||
// location
|
||||
} = this.props.event;
|
||||
const eventDate: moment.Moment = moment(start);
|
||||
const dateString: string = allDay ? eventDate.format(strings.AllDayDateFormat) : eventDate.format(strings.LocalizedTimeFormat);
|
||||
|
||||
let customStyle: React.CSSProperties = {};
|
||||
if (this.props.themeVariant) {
|
||||
const { semanticColors }: IReadonlyTheme = this.props.themeVariant;
|
||||
console.log("Semantic colors", semanticColors);
|
||||
if (semanticColors && semanticColors.bodyBackground) {
|
||||
customStyle = { backgroundColor: semanticColors.bodyBackground };
|
||||
}
|
||||
console.log("Custom style", semanticColors);
|
||||
}
|
||||
|
||||
private _renderNarrowCell(): JSX.Element {
|
||||
const { start,
|
||||
end,
|
||||
allDay,
|
||||
title,
|
||||
url,
|
||||
// category,
|
||||
// location
|
||||
} = this.props.event;
|
||||
const eventDate: moment.Moment = moment(start);
|
||||
const dateString: string = allDay ? eventDate.format(strings.AllDayDateFormat) : eventDate.format(strings.LocalizedTimeFormat);
|
||||
return (
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
className={css(styles.cardWrapper, styles.compactCard, styles.root, styles.rootIsCompact)}
|
||||
style={customStyle}
|
||||
data-is-focusable={true}
|
||||
data-is-focus-item={true}
|
||||
role="listitem"
|
||||
aria-label={Text.format(strings.EventCardWrapperArialLabel, title, dateString)}
|
||||
>
|
||||
<DocumentCard
|
||||
className={css(styles.root, styles.rootIsActionable, styles.rootIsCompact)}
|
||||
type={DocumentCardType.compact}
|
||||
style={customStyle}
|
||||
onClickHref={url}
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
className={css(styles.cardWrapper, styles.compactCard, styles.root, styles.rootIsCompact)}
|
||||
data-is-focusable={true}
|
||||
data-is-focus-item={true}
|
||||
role="listitem"
|
||||
aria-label={Text.format(strings.EventCardWrapperArialLabel, title, dateString)}
|
||||
>
|
||||
<DocumentCard
|
||||
className={css(styles.root, styles.rootIsActionable, styles.rootIsCompact)}
|
||||
type={DocumentCardType.compact}
|
||||
onClickHref={url}
|
||||
>
|
||||
<div>
|
||||
<DateBox
|
||||
className={styles.dateBox}
|
||||
startDate={start}
|
||||
endDate={end}
|
||||
size={DateBoxSize.Small}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div className={styles.title}>{title}</div>
|
||||
<div className={styles.datetime}>{dateString}</div>
|
||||
</div>
|
||||
</DocumentCard>
|
||||
</div>
|
||||
<DateBox
|
||||
className={styles.dateBox}
|
||||
startDate={start}
|
||||
endDate={end}
|
||||
size={DateBoxSize.Small}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
<div>
|
||||
<div className={styles.title}>{title}</div>
|
||||
<div className={styles.datetime}>{dateString}</div>
|
||||
</div>
|
||||
</DocumentCard>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private _onAddToMyCalendar = (): void => {
|
||||
const { event } = this.props;
|
||||
|
||||
// create a calendar to hold the event
|
||||
const cal: ICS.VCALENDAR = new ICS.VCALENDAR();
|
||||
cal.addProp("VERSION", 2.0);
|
||||
cal.addProp("PRODID", "//SPFX//NONSGML v1.0//EN");
|
||||
|
||||
// create an event
|
||||
const icsEvent: ICS.VEVENT = new ICS.VEVENT();
|
||||
|
||||
// generate a unique id
|
||||
icsEvent.addProp("UID", Guid.newGuid().toString());
|
||||
|
||||
// if the event is all day, just pass the date component
|
||||
if (event.allDay) {
|
||||
icsEvent.addProp("DTSTAMP", event.start, { VALUE: "DATE" });
|
||||
icsEvent.addProp("DTSTART", event.start, { VALUE: "DATE" });
|
||||
} else {
|
||||
icsEvent.addProp("DTSTAMP", event.start, { VALUE: "DATE-TIME" });
|
||||
icsEvent.addProp("DTSTART", event.start, { VALUE: "DATE-TIME" });
|
||||
icsEvent.addProp("DTEND", event.start, { VALUE: "DATE-TIME" });
|
||||
}
|
||||
|
||||
private _onAddToMyCalendar = (): void => {
|
||||
const { event } = this.props;
|
||||
// add a title
|
||||
icsEvent.addProp("SUMMARY", event.title);
|
||||
|
||||
// create a calendar to hold the event
|
||||
const cal: ICS.VCALENDAR = new ICS.VCALENDAR();
|
||||
cal.addProp("VERSION", 2.0);
|
||||
cal.addProp("PRODID", "//SPFX//NONSGML v1.0//EN");
|
||||
|
||||
// create an event
|
||||
const icsEvent: ICS.VEVENT = new ICS.VEVENT();
|
||||
|
||||
// generate a unique id
|
||||
icsEvent.addProp("UID", Guid.newGuid().toString());
|
||||
|
||||
// if the event is all day, just pass the date component
|
||||
if (event.allDay) {
|
||||
icsEvent.addProp("DTSTAMP", event.start, { VALUE: "DATE" });
|
||||
icsEvent.addProp("DTSTART", event.start, { VALUE: "DATE" });
|
||||
} else {
|
||||
icsEvent.addProp("DTSTAMP", event.start, { VALUE: "DATE-TIME" });
|
||||
icsEvent.addProp("DTSTART", event.start, { VALUE: "DATE-TIME" });
|
||||
icsEvent.addProp("DTEND", event.start, { VALUE: "DATE-TIME" });
|
||||
}
|
||||
|
||||
// add a title
|
||||
icsEvent.addProp("SUMMARY", event.title);
|
||||
|
||||
// add a url if there is one
|
||||
if (event.url !== undefined) {
|
||||
icsEvent.addProp("URL", event.url);
|
||||
}
|
||||
|
||||
// add a description if there is one
|
||||
if (event.description !== undefined) {
|
||||
icsEvent.addProp("DESCRIPTION", event.description);
|
||||
}
|
||||
|
||||
// add a location if there is one
|
||||
if (event.location !== undefined) {
|
||||
icsEvent.addProp("LOCATION", event.location);
|
||||
}
|
||||
|
||||
// add the event to the calendar
|
||||
cal.addComponent(icsEvent);
|
||||
|
||||
// export the calendar
|
||||
// my spidey senses are telling me that there are sitaations where this isn't going to work, but none of my tests could prove it.
|
||||
// i suspect we're not encoding events properly
|
||||
window.open("data:text/calendar;charset=utf8," + encodeURIComponent(cal.toString()));
|
||||
// add a url if there is one
|
||||
if (event.url !== undefined) {
|
||||
icsEvent.addProp("URL", event.url);
|
||||
}
|
||||
|
||||
// add a description if there is one
|
||||
if (event.description !== undefined) {
|
||||
icsEvent.addProp("DESCRIPTION", event.description);
|
||||
}
|
||||
|
||||
// add a location if there is one
|
||||
if (event.location !== undefined) {
|
||||
icsEvent.addProp("LOCATION", event.location);
|
||||
}
|
||||
|
||||
// add the event to the calendar
|
||||
cal.addComponent(icsEvent);
|
||||
|
||||
// export the calendar
|
||||
// my spidey senses are telling me that there are sitaations where this isn't going to work, but none of my tests could prove it.
|
||||
// i suspect we're not encoding events properly
|
||||
window.open("data:text/calendar;charset=utf8," + encodeURIComponent(cal.toString()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import { ICalendarEvent } from "../../services/CalendarService";
|
||||
import { IReadonlyTheme } from '@microsoft/sp-component-base';
|
||||
|
||||
export interface IEventCardProps {
|
||||
isEditMode: boolean;
|
||||
event: ICalendarEvent;
|
||||
isNarrow: boolean;
|
||||
themeVariant?: IReadonlyTheme;
|
||||
}
|
||||
|
|
|
@ -4,32 +4,7 @@ import * as React from 'react';
|
|||
import Slider from 'react-slick';
|
||||
import { SPComponentLoader } from '@microsoft/sp-loader';
|
||||
import styles from "./FilmstripLayout.module.scss";
|
||||
import { useRef, useEffect, useState } from 'react';
|
||||
import useComponentSize from '@rehooks/component-size';
|
||||
|
||||
function useDebounce(value: number, delay: number) {
|
||||
// State and setters for debounced value
|
||||
const [debouncedValue, setDebouncedValue] = useState(value);
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
// Update debounced value after delay
|
||||
const handler = setTimeout(() => {
|
||||
setDebouncedValue(value);
|
||||
}, delay);
|
||||
|
||||
// Cancel the timeout if value changes (also on delay change or unmount)
|
||||
// This is how we prevent debounced value from updating if value is changed ...
|
||||
// .. within the delay period. Timeout gets cleared and restarted.
|
||||
return () => {
|
||||
clearTimeout(handler);
|
||||
};
|
||||
},
|
||||
[value, delay] // Only re-call effect if value or delay changes
|
||||
);
|
||||
|
||||
return debouncedValue;
|
||||
}
|
||||
import { useRef } from 'react';
|
||||
|
||||
function useBreakpoints(currentWidth: number, breakpoints: number[]) {
|
||||
return breakpoints.map(breakpoint => currentWidth < breakpoint);
|
||||
|
@ -39,39 +14,24 @@ function useBreakpoints(currentWidth: number, breakpoints: number[]) {
|
|||
* Filmstrip layout
|
||||
* Presents the child compoments as a slick slide
|
||||
*/
|
||||
export const FilmstripLayout = (props: { children: any; ariaLabel?: string; }) => {
|
||||
export const FilmstripLayout = (props: { children: any; clientWidth: number; ariaLabel?: string; }) => {
|
||||
let ref: React.MutableRefObject<HTMLDivElement> = useRef<HTMLDivElement>(null);
|
||||
// // the slick slider used in normal views
|
||||
let _slider: React.MutableRefObject<Slider> = useRef<Slider>(null);
|
||||
|
||||
|
||||
|
||||
let size = useComponentSize(ref);
|
||||
let { width } = size;
|
||||
|
||||
const debouncedWidth = useDebounce(width, 500);
|
||||
const [numSlides, setNumSlides] = useState(3);
|
||||
|
||||
SPComponentLoader.loadCss('https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.min.css');
|
||||
SPComponentLoader.loadCss('https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick-theme.min.css');
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
console.log("New width", debouncedWidth);
|
||||
// slick seems to have an issue with having "infinite" mode set to true and having less items than the number of slides per page
|
||||
// set infinite to true only if there are more than 3 children
|
||||
const [isSmall, isMedium] = useBreakpoints(debouncedWidth, [696, 928]);
|
||||
const [isSmall, isMedium] = useBreakpoints(props.clientWidth, [696, 928]);
|
||||
|
||||
if (isSmall) {
|
||||
setNumSlides(2);
|
||||
} else if (isMedium) {
|
||||
setNumSlides(3);
|
||||
} else {
|
||||
setNumSlides(4);
|
||||
}
|
||||
},
|
||||
[debouncedWidth] // Only re-call effect if value or delay changes
|
||||
);
|
||||
let numSlides: number = 3;
|
||||
if (isSmall) {
|
||||
numSlides = 2;
|
||||
} else if (isMedium) {
|
||||
numSlides = 3;
|
||||
} else {
|
||||
numSlides = 4;
|
||||
}
|
||||
|
||||
var isInfinite: boolean = React.Children.count(props.children) > numSlides;
|
||||
var settings: any = {
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
export interface IFilmstripLayoutProps {
|
||||
ariaLabel?: string;
|
||||
clientWidth: number;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
export interface IFilmstripLayoutState {
|
||||
numSlides: number;
|
||||
}
|
|
@ -1 +1,2 @@
|
|||
export * from "./FilmstripLayout";
|
||||
export * from "./IFilmstripLayoutProps";
|
||||
|
|
|
@ -37,9 +37,6 @@ import { ICalendarFeedSummaryProps } from "./components/CalendarFeedSummary.type
|
|||
// Support for theme variants
|
||||
import { ThemeProvider, ThemeChangedEventArgs, IReadonlyTheme, ISemanticColors } from '@microsoft/sp-component-base';
|
||||
|
||||
// this is the same width that the SharePoint events web parts use to render as narrow
|
||||
const MaxMobileWidth: number = 480;
|
||||
|
||||
/**
|
||||
* Calendar Feed Summary Web Part
|
||||
* This web part shows a summary of events, in a film-strip (for normal views) or list view (for narrow views)
|
||||
|
@ -51,7 +48,7 @@ export default class CalendarFeedSummaryWebPart extends BaseClientSideWebPart<IC
|
|||
|
||||
private _themeProvider: ThemeProvider;
|
||||
private _themeVariant: IReadonlyTheme | undefined;
|
||||
|
||||
private _clientWidth: number = undefined;
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
|
@ -104,10 +101,10 @@ export default class CalendarFeedSummaryWebPart extends BaseClientSideWebPart<IC
|
|||
* Renders the web part
|
||||
*/
|
||||
public render(): void {
|
||||
const semanticColors: Readonly<ISemanticColors> | undefined = this._themeVariant && this._themeVariant.semanticColors;
|
||||
|
||||
// see if we need to render a mobile view
|
||||
const isNarrow: boolean = this.domElement.clientWidth <= MaxMobileWidth;
|
||||
if (this._clientWidth === undefined) {
|
||||
this._clientWidth = this.domElement.clientWidth;
|
||||
}
|
||||
|
||||
// display the summary (or the configuration screen)
|
||||
const element: React.ReactElement<ICalendarFeedSummaryProps> = React.createElement(
|
||||
|
@ -117,13 +114,13 @@ export default class CalendarFeedSummaryWebPart extends BaseClientSideWebPart<IC
|
|||
displayMode: this.displayMode,
|
||||
context: this.context,
|
||||
isConfigured: this._isConfigured(),
|
||||
isNarrow: isNarrow,
|
||||
maxEvents: this.properties.maxEvents,
|
||||
provider: this._getDataProvider(),
|
||||
themeVariant: this._themeVariant,
|
||||
updateProperty: (value: string) => {
|
||||
this.properties.title = value;
|
||||
},
|
||||
clientWidth: this._clientWidth
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -277,6 +274,7 @@ export default class CalendarFeedSummaryWebPart extends BaseClientSideWebPart<IC
|
|||
* If we get resized, call the Render method so that we can switch between the narrow view and the regular view
|
||||
*/
|
||||
protected onAfterResize(newWidth: number): void {
|
||||
this._clientWidth = newWidth;
|
||||
// redraw the web part
|
||||
this.render();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { DisplayMode } from "@microsoft/sp-core-library";
|
||||
import { SPComponentLoader } from "@microsoft/sp-loader";
|
||||
import { Placeholder } from "@pnp/spfx-controls-react/lib/Placeholder";
|
||||
import { WebPartTitle } from "@pnp/spfx-controls-react/lib/WebPartTitle";
|
||||
import * as strings from "CalendarFeedSummaryWebPartStrings";
|
||||
|
@ -17,6 +16,9 @@ import { IReadonlyTheme } from '@microsoft/sp-component-base';
|
|||
// the key used when caching events
|
||||
const CacheKey: string = "calendarFeedSummary";
|
||||
|
||||
// this is the same width that the SharePoint events web parts use to render as narrow
|
||||
const MaxMobileWidth: number = 480;
|
||||
|
||||
/**
|
||||
* Displays a feed summary from a given calendar feed provider. Renders a different view for mobile/narrow web parts.
|
||||
*/
|
||||
|
@ -108,7 +110,6 @@ export default class CalendarFeedSummary extends React.Component<ICalendarFeedSu
|
|||
// put everything together in a nice little calendar view
|
||||
return (
|
||||
<div className={css(styles.calendarFeedSummary, styles.webPartChrome)} style={{backgroundColor: semanticColors.bodyBackground}}>
|
||||
|
||||
<div className={css(styles.webPartHeader, styles.headerSmMargin)}>
|
||||
<WebPartTitle displayMode={this.props.displayMode}
|
||||
title={this.props.title}
|
||||
|
@ -126,8 +127,9 @@ export default class CalendarFeedSummary extends React.Component<ICalendarFeedSu
|
|||
* Render your web part content
|
||||
*/
|
||||
private _renderContent(): JSX.Element {
|
||||
const isNarrow: boolean = this.props.clientWidth < MaxMobileWidth;
|
||||
|
||||
const {
|
||||
isNarrow,
|
||||
displayMode
|
||||
} = this.props;
|
||||
const {
|
||||
|
@ -257,11 +259,13 @@ export default class CalendarFeedSummary extends React.Component<ICalendarFeedSu
|
|||
>
|
||||
<List
|
||||
items={pagedEvents}
|
||||
onRenderCell={(item, index) => (
|
||||
onRenderCell={(item, _index) => (
|
||||
<EventCard
|
||||
isEditMode={isEditMode}
|
||||
event={item}
|
||||
isNarrow={true} />
|
||||
isNarrow={true}
|
||||
themeVariant={this.props.themeVariant}
|
||||
/>
|
||||
)} />
|
||||
{usePaging &&
|
||||
<Paging
|
||||
|
@ -293,6 +297,7 @@ export default class CalendarFeedSummary extends React.Component<ICalendarFeedSu
|
|||
<div role="application">
|
||||
<FilmstripLayout
|
||||
ariaLabel={strings.FilmStripAriaLabel}
|
||||
clientWidth={this.props.clientWidth}
|
||||
>
|
||||
{events.map((event: ICalendarEvent, index: number) => {
|
||||
return (<EventCard
|
||||
|
|
|
@ -10,6 +10,7 @@ import { IWebPartContext } from "@microsoft/sp-webpart-base";
|
|||
import { Moment } from "moment";
|
||||
import { ICalendarEvent, ICalendarService } from "../../../shared/services/CalendarService";
|
||||
import { IReadonlyTheme } from '@microsoft/sp-component-base';
|
||||
|
||||
/**
|
||||
* The props for the calendar feed summary component
|
||||
*/
|
||||
|
@ -19,10 +20,10 @@ export interface ICalendarFeedSummaryProps {
|
|||
context: IWebPartContext;
|
||||
updateProperty: (value: string) => void;
|
||||
isConfigured: boolean;
|
||||
isNarrow: boolean;
|
||||
provider: ICalendarService;
|
||||
maxEvents: number;
|
||||
themeVariant: IReadonlyTheme;
|
||||
clientWidth: number;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue