Added theme aware components
This commit is contained in:
parent
da1b5b0932
commit
c822d2aada
File diff suppressed because it is too large
Load Diff
|
@ -22,7 +22,7 @@
|
||||||
"@microsoft/sp-webpart-base": "1.11.0",
|
"@microsoft/sp-webpart-base": "1.11.0",
|
||||||
"@pnp/common": "1.2.6",
|
"@pnp/common": "1.2.6",
|
||||||
"@pnp/logging": "1.2.6",
|
"@pnp/logging": "1.2.6",
|
||||||
"@pnp/spfx-controls-react": "1.10.0",
|
"@pnp/spfx-controls-react": "^2.10.0",
|
||||||
"@pnp/spfx-property-controls": "1.12.0",
|
"@pnp/spfx-property-controls": "1.12.0",
|
||||||
"@types/handlebars": "4.0.39",
|
"@types/handlebars": "4.0.39",
|
||||||
"common-tags": "1.8.0",
|
"common-tags": "1.8.0",
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
"alias": "RssReaderWebPart",
|
"alias": "RssReaderWebPart",
|
||||||
"componentType": "WebPart",
|
"componentType": "WebPart",
|
||||||
|
|
||||||
|
"supportsThemeVariants": true,
|
||||||
|
|
||||||
// The "*" signifies that the version should be taken from the package.json
|
// The "*" signifies that the version should be taken from the package.json
|
||||||
"version": "*",
|
"version": "*",
|
||||||
"manifestVersion": 2,
|
"manifestVersion": 2,
|
||||||
|
|
|
@ -34,6 +34,12 @@ import {
|
||||||
MockTemplateService } from '../../services/TemplateService';
|
MockTemplateService } from '../../services/TemplateService';
|
||||||
import { FeedLayoutOption, FeedServiceOption } from '../../models';
|
import { FeedLayoutOption, FeedServiceOption } from '../../models';
|
||||||
|
|
||||||
|
import {
|
||||||
|
ThemeProvider,
|
||||||
|
ThemeChangedEventArgs,
|
||||||
|
IReadonlyTheme
|
||||||
|
} from '@microsoft/sp-component-base';
|
||||||
|
|
||||||
export interface IRssReaderWebPartProps {
|
export interface IRssReaderWebPartProps {
|
||||||
title: string;
|
title: string;
|
||||||
|
|
||||||
|
@ -72,11 +78,15 @@ export interface IRssReaderWebPartProps {
|
||||||
dateFormatLang: string;
|
dateFormatLang: string;
|
||||||
backgroundColor: string;
|
backgroundColor: string;
|
||||||
fontColor: string;
|
fontColor: string;
|
||||||
|
useThemeFontColor: boolean;
|
||||||
|
useThemeBackgroundColor: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class RssReaderWebPart extends BaseClientSideWebPart<IRssReaderWebPartProps> {
|
export default class RssReaderWebPart extends BaseClientSideWebPart<IRssReaderWebPartProps> {
|
||||||
private _templateService: BaseTemplateService;
|
private _templateService: BaseTemplateService;
|
||||||
private _propertyPage = null;
|
private _propertyPage = null;
|
||||||
|
private _themeProvider: ThemeProvider;
|
||||||
|
private _themeVariant: IReadonlyTheme | undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The template to display at render time
|
* The template to display at render time
|
||||||
|
@ -85,6 +95,15 @@ export default class RssReaderWebPart extends BaseClientSideWebPart<IRssReaderWe
|
||||||
|
|
||||||
public onInit(): Promise<void> {
|
public onInit(): Promise<void> {
|
||||||
|
|
||||||
|
// Consume the new ThemeProvider service
|
||||||
|
this._themeProvider = this.context.serviceScope.consume(ThemeProvider.serviceKey);
|
||||||
|
|
||||||
|
// If it exists, get the theme variant
|
||||||
|
this._themeVariant = this._themeProvider.tryGetTheme();
|
||||||
|
|
||||||
|
// Register a handler to be notified if the theme variant changes
|
||||||
|
this._themeProvider.themeChangedEvent.add(this, this._handleThemeChangedEvent);
|
||||||
|
|
||||||
//Initialize a redux store that uses our custom Reducer & state
|
//Initialize a redux store that uses our custom Reducer & state
|
||||||
RssHttpClientService.init(this.context);
|
RssHttpClientService.init(this.context);
|
||||||
|
|
||||||
|
@ -141,6 +160,8 @@ export default class RssReaderWebPart extends BaseClientSideWebPart<IRssReaderWe
|
||||||
|
|
||||||
backgroundColor: this.properties.backgroundColor,
|
backgroundColor: this.properties.backgroundColor,
|
||||||
fontColor: this.properties.fontColor,
|
fontColor: this.properties.fontColor,
|
||||||
|
useThemeFontColor: this.properties.useThemeFontColor,
|
||||||
|
useThemeBackgroundColor: this.properties.useThemeBackgroundColor,
|
||||||
|
|
||||||
propertyPane: this.context.propertyPane,
|
propertyPane: this.context.propertyPane,
|
||||||
|
|
||||||
|
@ -152,7 +173,9 @@ export default class RssReaderWebPart extends BaseClientSideWebPart<IRssReaderWe
|
||||||
|
|
||||||
updateProperty: (value: string) => {
|
updateProperty: (value: string) => {
|
||||||
this.properties.title = value;
|
this.properties.title = value;
|
||||||
}
|
},
|
||||||
|
|
||||||
|
themeVariant: this._themeVariant
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -516,6 +539,11 @@ export default class RssReaderWebPart extends BaseClientSideWebPart<IRssReaderWe
|
||||||
iconName: 'Precipitation',
|
iconName: 'Precipitation',
|
||||||
key: 'rssReaderFontColorField'
|
key: 'rssReaderFontColorField'
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
layoutFields.push(PropertyPaneToggle('useThemeFontColor', {
|
||||||
|
label: strings.UseThemeFontColor
|
||||||
|
}));
|
||||||
|
|
||||||
layoutFields.push(PropertyFieldColorPicker('backgroundColor', {
|
layoutFields.push(PropertyFieldColorPicker('backgroundColor', {
|
||||||
label: strings.BackgroundColorLabel,
|
label: strings.BackgroundColorLabel,
|
||||||
selectedColor: this.properties.backgroundColor,
|
selectedColor: this.properties.backgroundColor,
|
||||||
|
@ -528,6 +556,10 @@ export default class RssReaderWebPart extends BaseClientSideWebPart<IRssReaderWe
|
||||||
key: 'rssReaderBgColorField'
|
key: 'rssReaderBgColorField'
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
layoutFields.push(PropertyPaneToggle('useThemeBackgroundColor', {
|
||||||
|
label: strings.UseThemeBackgroundColor
|
||||||
|
}));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
dateFormatLang: string;
|
dateFormatLang: string;
|
||||||
*/
|
*/
|
||||||
|
@ -604,4 +636,14 @@ export default class RssReaderWebPart extends BaseClientSideWebPart<IRssReaderWe
|
||||||
|
|
||||||
this._templateContentToDisplay = templateContent;
|
this._templateContentToDisplay = templateContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the current theme variant reference and re-render.
|
||||||
|
*
|
||||||
|
* @param args The new theme
|
||||||
|
*/
|
||||||
|
private _handleThemeChangedEvent(args: ThemeChangedEventArgs): void {
|
||||||
|
this._themeVariant = args.theme;
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ import { FeedServiceOption, FeedLayoutOption } from '../../../../models';
|
||||||
|
|
||||||
import { BaseTemplateService } from '../../../../services/TemplateService';
|
import { BaseTemplateService } from '../../../../services/TemplateService';
|
||||||
|
|
||||||
|
import { IReadonlyTheme } from '@microsoft/sp-component-base';
|
||||||
|
|
||||||
export interface IRssReaderProps {
|
export interface IRssReaderProps {
|
||||||
feedUrl: string;
|
feedUrl: string;
|
||||||
feedService: FeedServiceOption;
|
feedService: FeedServiceOption;
|
||||||
|
@ -38,6 +40,8 @@ export interface IRssReaderProps {
|
||||||
|
|
||||||
backgroundColor: string;
|
backgroundColor: string;
|
||||||
fontColor: string;
|
fontColor: string;
|
||||||
|
useThemeBackgroundColor: boolean;
|
||||||
|
useThemeFontColor: boolean;
|
||||||
|
|
||||||
propertyPane?: IPropertyPaneAccessor;
|
propertyPane?: IPropertyPaneAccessor;
|
||||||
|
|
||||||
|
@ -55,4 +59,9 @@ export interface IRssReaderProps {
|
||||||
templateContent: string;
|
templateContent: string;
|
||||||
|
|
||||||
updateProperty: (value: string) => void;
|
updateProperty: (value: string) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Theme awareness
|
||||||
|
*/
|
||||||
|
themeVariant: IReadonlyTheme | undefined;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,18 +3,6 @@
|
||||||
.rssReader {
|
.rssReader {
|
||||||
.rssReaderHeader {
|
.rssReaderHeader {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.rssReaderListViewAll {
|
|
||||||
position: absolute;
|
|
||||||
top: 7px;
|
|
||||||
right: 0px;
|
|
||||||
|
|
||||||
padding: 0px;
|
|
||||||
|
|
||||||
A {
|
|
||||||
color: $ms-color-themePrimary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.rssReaderList {
|
.rssReaderList {
|
||||||
|
@ -59,7 +47,6 @@
|
||||||
|
|
||||||
.itemDate {
|
.itemDate {
|
||||||
font-size:11px;
|
font-size:11px;
|
||||||
color:$ms-color-neutralDark;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.itemContent {
|
.itemContent {
|
||||||
|
|
|
@ -24,6 +24,8 @@ import {
|
||||||
IRssReaderRequest,
|
IRssReaderRequest,
|
||||||
FeedLayoutOption } from '../../../../models';
|
FeedLayoutOption } from '../../../../models';
|
||||||
|
|
||||||
|
import { IReadonlyTheme } from '@microsoft/sp-component-base';
|
||||||
|
|
||||||
export default class RssReader extends React.Component<IRssReaderProps, IRssReaderState> {
|
export default class RssReader extends React.Component<IRssReaderProps, IRssReaderState> {
|
||||||
|
|
||||||
private viewAllLinkLabel: string = strings.DefaultFeedViewAllLinkLabel;
|
private viewAllLinkLabel: string = strings.DefaultFeedViewAllLinkLabel;
|
||||||
|
@ -51,18 +53,17 @@ export default class RssReader extends React.Component<IRssReaderProps, IRssRead
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(): React.ReactElement<IRssReaderProps> {
|
public render(): React.ReactElement<IRssReaderProps> {
|
||||||
|
const { semanticColors }: IReadonlyTheme = this.props.themeVariant;
|
||||||
return (
|
return (
|
||||||
<div className={ styles.rssReader }>
|
<div className={ styles.rssReader } style={{backgroundColor: semanticColors.bodyBackground}}>
|
||||||
<div className={styles.rssReaderHeader}>
|
<div className={styles.rssReaderHeader}>
|
||||||
<WebPartTitle displayMode={this.props.displayMode}
|
<WebPartTitle displayMode={this.props.displayMode}
|
||||||
title={this.props.title}
|
title={this.props.title}
|
||||||
updateProperty={this.props.updateProperty} />
|
updateProperty={this.props.updateProperty}
|
||||||
|
themeVariant={this.props.themeVariant}
|
||||||
{this.state.rssFeedReady && this.state.rssFeed && this.props.feedViewAllLink && this.props.feedViewAllLink.length > 0 && (
|
moreLink={this.state.rssFeedReady && this.state.rssFeed && this.props.feedViewAllLink && this.props.feedViewAllLink.length > 0 && (
|
||||||
<div className={styles.rssReaderListViewAll}>
|
<Link style={{color: semanticColors.link}} href={this.props.feedViewAllLink}>{this.viewAllLinkLabel}</Link>
|
||||||
<a href={this.props.feedViewAllLink}>{this.viewAllLinkLabel}</a>
|
)}/>
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{!this.props.feedUrl || this.props.feedUrl.length < 1 ? (
|
{!this.props.feedUrl || this.props.feedUrl.length < 1 ? (
|
||||||
|
@ -97,7 +98,7 @@ export default class RssReader extends React.Component<IRssReaderProps, IRssRead
|
||||||
className={styles.rssReaderList + (this.props.backgroundColor ? " " + styles.rssReaderListPadding : "")}
|
className={styles.rssReaderList + (this.props.backgroundColor ? " " + styles.rssReaderListPadding : "")}
|
||||||
items={this.state.rssFeed.query.results.rss}
|
items={this.state.rssFeed.query.results.rss}
|
||||||
onRenderCell={this._onRenderListRow}
|
onRenderCell={this._onRenderListRow}
|
||||||
style={this.props.backgroundColor ? {backgroundColor: this.props.backgroundColor} : {}}
|
style={this.props.useThemeBackgroundColor ? {backgroundColor: semanticColors.bodyBackground} : this.props.backgroundColor ? {backgroundColor: this.props.backgroundColor} : {}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -154,7 +155,10 @@ export default class RssReader extends React.Component<IRssReaderProps, IRssRead
|
||||||
this.props.titleLinkTarget != nextProps.titleLinkTarget ||
|
this.props.titleLinkTarget != nextProps.titleLinkTarget ||
|
||||||
this.props.dateFormat != nextProps.dateFormat ||
|
this.props.dateFormat != nextProps.dateFormat ||
|
||||||
this.props.backgroundColor != nextProps.backgroundColor ||
|
this.props.backgroundColor != nextProps.backgroundColor ||
|
||||||
this.props.fontColor != nextProps.fontColor
|
this.props.useThemeBackgroundColor != nextProps.useThemeBackgroundColor ||
|
||||||
|
this.props.useThemeFontColor != nextProps.useThemeFontColor ||
|
||||||
|
this.props.fontColor != nextProps.fontColor ||
|
||||||
|
this.props.themeVariant != nextProps.themeVariant
|
||||||
) {
|
) {
|
||||||
this.loadRssFeed();
|
this.loadRssFeed();
|
||||||
}
|
}
|
||||||
|
@ -190,6 +194,7 @@ export default class RssReader extends React.Component<IRssReaderProps, IRssRead
|
||||||
let div = document.createElement("div");
|
let div = document.createElement("div");
|
||||||
div.innerHTML = displayDesc;
|
div.innerHTML = displayDesc;
|
||||||
displayDesc = (div.textContent || div.innerText || "").replace(/\ /ig, "").trim();
|
displayDesc = (div.textContent || div.innerText || "").replace(/\ /ig, "").trim();
|
||||||
|
const { semanticColors }: IReadonlyTheme = this.props.themeVariant;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.rssReaderListItem} data-is-focusable={true}>
|
<div className={styles.rssReaderListItem} data-is-focusable={true}>
|
||||||
|
@ -197,7 +202,7 @@ export default class RssReader extends React.Component<IRssReaderProps, IRssRead
|
||||||
<Link
|
<Link
|
||||||
href={thisItem.link}
|
href={thisItem.link}
|
||||||
target={this.props.titleLinkTarget ? this.props.titleLinkTarget : "_self"}
|
target={this.props.titleLinkTarget ? this.props.titleLinkTarget : "_self"}
|
||||||
style={this.props.fontColor ? {color: this.props.fontColor} : {}}
|
style={this.props.useThemeFontColor ? {color: semanticColors.link} : this.props.fontColor ? {color: this.props.fontColor} : {}}
|
||||||
>
|
>
|
||||||
{this.decodeHtml(thisItem.title)}
|
{this.decodeHtml(thisItem.title)}
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -205,7 +210,7 @@ export default class RssReader extends React.Component<IRssReaderProps, IRssRead
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{this.props.showPubDate && (
|
{this.props.showPubDate && (
|
||||||
<div className={styles.itemDate}>
|
<div className={styles.itemDate} style={{color: semanticColors.bodySubtext}}>
|
||||||
{this.props.dateFormat && this.props.dateFormat.length > 0 ? (
|
{this.props.dateFormat && this.props.dateFormat.length > 0 ? (
|
||||||
<Moment
|
<Moment
|
||||||
format={this.props.dateFormat}
|
format={this.props.dateFormat}
|
||||||
|
@ -218,7 +223,7 @@ export default class RssReader extends React.Component<IRssReaderProps, IRssRead
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{this.props.showDesc && (
|
{this.props.showDesc && (
|
||||||
<div className={styles.itemContent}>
|
<div className={styles.itemContent} style={{color: semanticColors.bodyText}}>
|
||||||
{this.props.descCharacterLimit && (displayDesc.length > this.props.descCharacterLimit) ? (
|
{this.props.descCharacterLimit && (displayDesc.length > this.props.descCharacterLimit) ? (
|
||||||
<div>
|
<div>
|
||||||
{displayDesc.substring(0, this.props.descCharacterLimit) + '...'}
|
{displayDesc.substring(0, this.props.descCharacterLimit) + '...'}
|
||||||
|
|
|
@ -46,6 +46,8 @@ define([], function() {
|
||||||
"DateFormatLabel": "Date Format",
|
"DateFormatLabel": "Date Format",
|
||||||
"BackgroundColorLabel": "Background Color",
|
"BackgroundColorLabel": "Background Color",
|
||||||
"FontColorLabel": "Title Color",
|
"FontColorLabel": "Title Color",
|
||||||
|
"UseThemeBackgroundColor": "Use background color from theme",
|
||||||
|
"UseThemeFontColor": "Use title color from theme",
|
||||||
|
|
||||||
|
|
||||||
//feed service options
|
//feed service options
|
||||||
|
|
|
@ -42,7 +42,8 @@ declare interface IRssReaderWebPartStrings {
|
||||||
DateFormatLabel: string;
|
DateFormatLabel: string;
|
||||||
BackgroundColorLabel: string;
|
BackgroundColorLabel: string;
|
||||||
FontColorLabel: string;
|
FontColorLabel: string;
|
||||||
|
UseThemeBackgroundColor: string;
|
||||||
|
UseThemeFontColor: string;
|
||||||
|
|
||||||
|
|
||||||
//feed service options
|
//feed service options
|
||||||
|
|
Loading…
Reference in New Issue