Skip to content

Commit 43a6fa9

Browse files
committed
large refactor; reorganize and add new features
1 parent 1afb8eb commit 43a6fa9

File tree

13 files changed

+539
-295
lines changed

13 files changed

+539
-295
lines changed

src/webparts/wordPressRssFeed/WordPressRssFeedWebPart.ts

Lines changed: 103 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import * as React from "react";
22
import * as ReactDom from "react-dom";
33
import { Version } from "@microsoft/sp-core-library";
44
import { PropertyPaneTagCategoryPicker } from "./controls/TagCategoryPicker/PropertyPaneTagCategoryPicker";
5-
65
import {
76
type IPropertyPaneConfiguration,
87
PropertyPaneDropdown,
@@ -13,32 +12,26 @@ import { BaseClientSideWebPart } from "@microsoft/sp-webpart-base";
1312
import { IReadonlyTheme } from "@microsoft/sp-component-base";
1413
import WordPressRssFeed from "./components/WordPressRssFeed";
1514
import { ITagOrCategory, IWordPressRssFeedWebPartProps } from "./interfaces";
16-
import { DEFAULTS, defaultSettings } from "./defaults";
15+
import { defaultDisplaySettings, defaultFeedRequestSettings } from "./defaults";
1716
import { filterJoinOperators, layouts } from "./dropdownOptions";
1817
import { PropertyPaneWordPressUrlField } from "./controls/WordPressUrlField/PropertyPaneWordPressUrlField";
1918
import { validateUrl } from "./util";
2019
import { PropertyPaneNumericTextField } from "./controls/NumericTextField/PropertyPaneNumericTextField";
21-
2220
export default class WordPressRssFeedWebPart extends BaseClientSideWebPart<IWordPressRssFeedWebPartProps> {
2321
// store data that you need to fetch asynchronously within
2422
// configuration panel as private variables, and load them
2523
// onInit.
2624
private _tagOptions: { key: number; text: string }[] = [];
2725
private _categoryOptions: { key: number; text: string }[] = [];
2826
private _siteName: string = "";
29-
3027
public render(): void {
3128
const element: React.ReactElement<IWordPressRssFeedWebPartProps> = React.createElement(WordPressRssFeed, {
32-
title: this.properties.title,
33-
description: this.properties.description,
34-
readMoreLink: this.properties.readMoreLink,
35-
feedSettings: this.properties.feedSettings,
29+
displaySettings: this.properties.displaySettings,
30+
feedFilterSettings: this.properties.feedFilterSettings,
3631
url: this.properties.url,
3732
});
38-
3933
ReactDom.render(element, this.domElement);
4034
}
41-
4235
private loadSiteDataFromURL: () => Promise<void> = async () => {
4336
const apiBase = this.properties.url;
4437
const [general, tags, categories] = await Promise.all([
@@ -51,168 +44,197 @@ export default class WordPressRssFeedWebPart extends BaseClientSideWebPart<IWord
5144
this._categoryOptions = categories.map((cat: ITagOrCategory) => ({ key: cat.id, text: cat.name }));
5245
return Promise.resolve();
5346
};
54-
5547
protected onInit(): Promise<void> {
5648
// initialize values to defaults if database instance has nothing stored
57-
5849
if (!this.properties.url) {
59-
this.properties.url = DEFAULTS.siteUrl;
50+
this.properties.url = "";
6051
}
61-
if (!this.properties.feedSettings) {
62-
this.properties.feedSettings = defaultSettings;
52+
if (!this.properties.feedFilterSettings) {
53+
this.properties.feedFilterSettings = defaultFeedRequestSettings;
6354
}
64-
if (!this.properties.title) {
65-
this.properties.title = DEFAULTS.title;
55+
if (!this.properties.displaySettings) {
56+
this.properties.displaySettings = defaultDisplaySettings;
6657
}
67-
if (!this.properties.description) {
68-
this.properties.description = DEFAULTS.description;
69-
}
70-
if (!this.properties.readMoreLink) {
71-
this.properties.readMoreLink = DEFAULTS.readMoreLink;
72-
}
73-
7458
if (validateUrl(this.properties.url)) {
7559
this.loadSiteDataFromURL().catch((e) => console.error(e));
7660
}
7761
return super.onInit();
7862
}
79-
8063
protected onThemeChanged(currentTheme: IReadonlyTheme | undefined): void {
8164
if (!currentTheme) {
8265
return;
8366
}
8467
const { semanticColors } = currentTheme;
85-
8668
if (semanticColors) {
8769
this.domElement.style.setProperty("--bodyText", semanticColors.bodyText || null);
8870
this.domElement.style.setProperty("--link", semanticColors.link || null);
8971
this.domElement.style.setProperty("--linkHovered", semanticColors.linkHovered || null);
9072
}
9173
}
92-
9374
protected onDispose(): void {
9475
ReactDom.unmountComponentAtNode(this.domElement);
9576
}
96-
9777
protected get dataVersion(): Version {
9878
return Version.parse("1.0");
9979
}
100-
10180
public getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
10281
return {
10382
pages: [
10483
{
10584
header: { description: "Configure your WordPress feed" },
10685
groups: [
10786
{
108-
groupName: "Feed Basics",
87+
groupName: "WordPress Site Connection",
10988
groupFields: [
110-
PropertyPaneTextField("title", {
89+
new PropertyPaneWordPressUrlField("url", {
90+
label: "WordPress Site URL",
91+
key: "url",
92+
value: this.properties.url,
93+
siteName: this._siteName,
94+
onChange: (s: string) => {
95+
this.properties.url = s;
96+
this.context.propertyPane.refresh();
97+
},
98+
siteFetchHandler: async () => {
99+
await this.loadSiteDataFromURL()
100+
.then(() => {
101+
this.context.propertyPane.refresh();
102+
this.render();
103+
})
104+
.catch((e) => console.error(e));
105+
},
106+
}),
107+
],
108+
},
109+
{
110+
groupName: "Display Settings",
111+
groupFields: [
112+
PropertyPaneTextField("displaySettings.title", {
111113
label: "Feed Title",
112-
value: this.properties.title,
114+
value: this.properties.displaySettings.title,
113115
}),
114-
PropertyPaneTextField("description", {
116+
PropertyPaneTextField("displaySettings.description", {
115117
label: "Feed Description",
116118
multiline: true,
117-
value: this.properties.description,
119+
value: this.properties.displaySettings.description,
118120
}),
119-
PropertyPaneToggle("readMoreLink.include", {
121+
PropertyPaneToggle("displaySettings.readMoreLink.include", {
120122
label: "Include Link Below Feed?",
121-
checked: this.properties.readMoreLink.include,
123+
checked: this.properties.displaySettings.readMoreLink.include,
122124
}),
123-
PropertyPaneTextField("readMoreLink.linkText", {
125+
PropertyPaneTextField("displaySettings.readMoreLink.linkText", {
124126
label: "Link Text",
125-
disabled: !this.properties.readMoreLink.include,
126-
value: this.properties.readMoreLink.linkText,
127+
disabled: !this.properties.displaySettings.readMoreLink.include,
128+
value: this.properties.displaySettings.readMoreLink.linkText,
127129
}),
128-
PropertyPaneTextField("readMoreLink.linkUrl", {
130+
PropertyPaneTextField("displaySettings.readMoreLink.linkUrl", {
129131
label: "Link URL",
130-
disabled: !this.properties.readMoreLink.include,
131-
value: this.properties.readMoreLink.linkUrl,
132+
disabled: !this.properties.displaySettings.readMoreLink.include,
133+
value: this.properties.displaySettings.readMoreLink.linkUrl,
132134
}),
133-
PropertyPaneToggle("readMoreLink.linkNewTab", {
135+
PropertyPaneToggle("displaySettings.readMoreLink.linkNewTab", {
134136
label: "Open link in new tab",
135-
checked: this.properties.readMoreLink.linkNewTab,
137+
checked: this.properties.displaySettings.readMoreLink.linkNewTab,
136138
}),
137-
new PropertyPaneWordPressUrlField("url", {
138-
label: "WordPress Site URL",
139-
key: "url",
140-
value: this.properties.url,
141-
siteName: this._siteName,
139+
PropertyPaneToggle("displaySettings.showAuthor", {
140+
label: "Show Author on Posts",
141+
checked: this.properties.displaySettings.showAuthor,
142+
}),
143+
PropertyPaneToggle("displaySettings.showMedia", {
144+
label: "Show Media / Thumbnail (if available)",
145+
checked: this.properties.displaySettings.showMedia,
146+
}),
147+
PropertyPaneDropdown("displaySettings.layoutType", {
148+
label: "Feed Layout",
149+
options: layouts,
150+
selectedKey: this.properties.displaySettings.layoutType,
151+
}),
152+
new PropertyPaneNumericTextField("displaySettings.itemsPerPage", {
153+
label: "Pagination - Items Per Page (set equal to Number of Posts for no pagination)",
154+
min: 1,
155+
max: 100, // obviously the real limit will be the number of posts in the feed
156+
key: "displaySettings.itemsPerPage",
157+
value: this.properties.displaySettings.itemsPerPage.toString(),
142158
onChange: (s: string) => {
143-
this.properties.url = s;
159+
this.properties.displaySettings.itemsPerPage = parseInt(s);
144160
this.context.propertyPane.refresh();
161+
this.render();
145162
},
146-
siteFetchHandler: async () => {
147-
await this.loadSiteDataFromURL()
148-
.then(() => this.context.propertyPane.refresh())
149-
.catch((e) => console.error(e));
163+
}),
164+
new PropertyPaneNumericTextField("displaySettings.excerptLength", {
165+
label: "Excerpt Preview Length (set to 0 to hide excerpt)",
166+
min: 0,
167+
max: 300,
168+
key: "displaySettings.excerptLength",
169+
value: this.properties.displaySettings.excerptLength.toString(),
170+
onChange: (s: string) => {
171+
this.properties.displaySettings.excerptLength = parseInt(s);
172+
this.context.propertyPane.refresh();
173+
this.render();
150174
},
151175
}),
152176
],
153177
},
154-
155178
{
156-
groupName: "Feed Settings",
179+
groupName: "Feed Filter Settings",
157180
groupFields: [
158-
new PropertyPaneNumericTextField("feedSettings.numPosts", {
181+
new PropertyPaneNumericTextField("feedFilterSettings.numPosts", {
159182
label: "Number of Posts",
160-
key: "feedSettings.numPosts",
161-
value: this.properties.feedSettings.numPosts.toString(),
183+
min: 1,
184+
max: 50,
185+
key: "feedFilterSettings.numPosts",
186+
value: this.properties.feedFilterSettings.numPosts.toString(),
162187
onChange: (s: string) => {
163-
this.properties.feedSettings.numPosts = parseInt(s);
188+
this.properties.feedFilterSettings.numPosts = parseInt(s);
164189
this.context.propertyPane.refresh();
165190
this.render();
166191
},
167192
}),
168-
new PropertyPaneNumericTextField("feedSettings.pastDays", {
193+
new PropertyPaneNumericTextField("feedFilterSettings.pastDays", {
169194
label: "Past Days",
170-
key: "feedSettings.pastDays",
171-
value: this.properties.feedSettings.pastDays.toString(),
195+
min: 1,
196+
max: 3650, // 10 years seems sufficient :)
197+
key: "feedFilterSettings.pastDays",
198+
value: this.properties.feedFilterSettings.pastDays.toString(),
172199
onChange: (s: string) => {
173-
this.properties.feedSettings.pastDays = parseInt(s);
200+
this.properties.feedFilterSettings.pastDays = parseInt(s);
174201
this.context.propertyPane.refresh();
175202
this.render();
176203
},
177204
}),
178205
// Tag/category filtering would require dynamic loading,
179206
// which SPFX doesn't support directly in the property pane.
180207
// I am using a customPropertyPaneField for this if needed.
181-
new PropertyPaneTagCategoryPicker("feedSettings.tagIds", {
208+
new PropertyPaneTagCategoryPicker("feedFilterSettings.tagIds", {
182209
label: "Select Tags",
183-
key: "feedSettings.tagIds",
184-
selectedKeys: this.properties.feedSettings.tagIds || [],
210+
key: "feedFilterSettings.tagIds",
211+
selectedKeys: this.properties.feedFilterSettings.tagIds || [],
185212
options: this._tagOptions,
186213
onChange: (newTagIds: number[]) => {
187-
this.properties.feedSettings.tagIds = newTagIds;
214+
this.properties.feedFilterSettings.tagIds = newTagIds;
188215
this.context.propertyPane.refresh();
189216
this.render();
190217
},
191218
}),
192-
new PropertyPaneTagCategoryPicker("feedSettings.categoryIds", {
219+
new PropertyPaneTagCategoryPicker("feedFilterSettings.categoryIds", {
193220
label: "Select Categories",
194-
key: "feedSettings.categoryIds",
195-
selectedKeys: this.properties.feedSettings.categoryIds || [],
221+
key: "feedFilterSettings.categoryIds",
222+
selectedKeys: this.properties.feedFilterSettings.categoryIds || [],
196223
options: this._categoryOptions,
197224
onChange: (newCategoryIds: number[]) => {
198-
this.properties.feedSettings.categoryIds = newCategoryIds;
225+
this.properties.feedFilterSettings.categoryIds = newCategoryIds;
199226
this.context.propertyPane.refresh();
200227
this.render();
201228
},
202229
}),
203-
PropertyPaneTextField("feedSettings.postPattern", {
230+
PropertyPaneTextField("feedFilterSettings.postPattern", {
204231
label: "Post Pattern (Wildcard OK)",
205-
value: this.properties.feedSettings.postPattern,
232+
value: this.properties.feedFilterSettings.postPattern,
206233
}),
207-
PropertyPaneDropdown("feedSettings.filterJoinOperator", {
234+
PropertyPaneDropdown("feedFilterSettings.filterJoinOperator", {
208235
label: "Join Operator",
209236
options: filterJoinOperators,
210-
selectedKey: this.properties.feedSettings.filterJoinOperator,
211-
}),
212-
PropertyPaneDropdown("feedSettings.layoutType", {
213-
label: "Feed Layout",
214-
options: layouts,
215-
selectedKey: this.properties.feedSettings.layoutType,
237+
selectedKey: this.properties.feedFilterSettings.filterJoinOperator,
216238
}),
217239
],
218240
},

src/webparts/wordPressRssFeed/components/FeedRender.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,21 @@ import styles from "./WordPressRssFeed.module.scss";
66
import { readMoreLinkNotEmpty } from "../util";
77
import ReadMoreLink from "./ReadMoreLink";
88

9-
const FeedRender: React.FC<IFeedRenderProps> = ({ title, description, readMoreLink, url, posts, layoutType }) => {
9+
const FeedRender: React.FC<IFeedRenderProps> = ({ posts, displaySettings }) => {
1010
return (
1111
<div>
12-
{title.trim() !== "" && <h1 className={styles.feedTitle}>{title}</h1>}
13-
{description.trim() !== "" && <p className={styles.feedDescription}>{description}</p>}
12+
{displaySettings?.title?.trim() !== "" && <h1 className={styles.feedTitle}>{displaySettings.title}</h1>}
13+
{displaySettings.description?.trim() !== "" && (
14+
<p className={styles.feedDescription}>{displaySettings.description}</p>
15+
)}
1416
{!posts || posts.length === 0 ? (
1517
<Alert type={"warning"} msg={MESSAGES.WARNING.noPostsToDisplay} />
1618
) : (
17-
<PostsLayout url={url} posts={posts} layoutType={layoutType} />
19+
<PostsLayout posts={posts} displaySettings={displaySettings} />
20+
)}
21+
{displaySettings.readMoreLink.include && readMoreLinkNotEmpty(displaySettings.readMoreLink) && (
22+
<ReadMoreLink {...displaySettings.readMoreLink} />
1823
)}
19-
{readMoreLink.include && readMoreLinkNotEmpty(readMoreLink) && <ReadMoreLink {...readMoreLink} />}
2024
</div>
2125
);
2226
};

0 commit comments

Comments
 (0)