From 879f9ddd96b701387d15bfc7d36296e7d82f3905 Mon Sep 17 00:00:00 2001 From: Sudharsan K <10280385+sudharsank@users.noreply.github.com> Date: Fri, 10 Jul 2020 12:53:17 +0800 Subject: [PATCH] Configured few properties and also added the codetour for solution walkthrough --- .../.tours/extension-walkthrough.tour | 155 ++++++++++++++++++ .../config/package-solution.json | 7 +- .../sharepoint/assets/ClientSideInstance.xml | 4 +- .../sharepoint/assets/elements.xml | 4 +- .../src/extensions/globalAlerts/Alerts.tsx | 9 +- .../globalAlerts/GlobalAlerts.module.scss | 6 +- ...lAlertsApplicationCustomizer.manifest.json | 6 - .../GlobalAlertsApplicationCustomizer.ts | 74 +++++---- 8 files changed, 213 insertions(+), 52 deletions(-) create mode 100644 samples/js-application-alert-message/.tours/extension-walkthrough.tour diff --git a/samples/js-application-alert-message/.tours/extension-walkthrough.tour b/samples/js-application-alert-message/.tours/extension-walkthrough.tour new file mode 100644 index 000000000..51f31066f --- /dev/null +++ b/samples/js-application-alert-message/.tours/extension-walkthrough.tour @@ -0,0 +1,155 @@ +{ + "title": "Extension Walkthrough", + "steps": [ + { + "file": "src/extensions/globalAlerts/GlobalAlertsApplicationCustomizer.ts", + "line": 24, + "description": "Property declaration\n1. **animationType** - Property to hold the animation to be played for the alerts. Default is set to be '**_bounceInRight_**', if there is no property defined.\n2. **animationDelay** - Delay to be used between multiple alerts. Default is set to be '**_5000ms_**', if there is no property defined.\n3. **alertBackgoundColor** - Background color for the alert container. Default is set to be '**_Red_**' if there is no property defined.\n4. **textColor** - Text color based on the background color. Default is set to be '**_White_**', if there is no property defined.", + "selection": { + "start": { + "line": 21, + "character": 5 + }, + "end": { + "line": 24, + "character": 23 + } + } + }, + { + "file": "src/extensions/globalAlerts/GlobalAlertsApplicationCustomizer.ts", + "line": 53, + "description": "Render Placeholder method to render the actual alert component once the Placeholder is available in the page. We are also passing all the properties to the alert component where the actual alert fetching and redering is maintained.", + "selection": { + "start": { + "line": 31, + "character": 5 + }, + "end": { + "line": 53, + "character": 6 + } + } + }, + { + "file": "src/extensions/globalAlerts/GlobalAlertsApplicationCustomizer.ts", + "line": 59, + "description": "Setting up the **_spfxcontext_** for the **PnP** library. Since we get all the alerts from SharePoint list using the **PnP** library.", + "selection": { + "start": { + "line": 59, + "character": 9 + }, + "end": { + "line": 59, + "character": 32 + } + } + }, + { + "file": "src/extensions/globalAlerts/GlobalAlertsApplicationCustomizer.ts", + "line": 61, + "description": "Make sure the placeholders are rendered in the page and after rendering the default placeholders, we have to call our custom render method to apply the customization.\n\n**_Note_**: Without this line, the extension will not work properly. Sometimes the extension will load and sometimes not.", + "selection": { + "start": { + "line": 61, + "character": 9 + }, + "end": { + "line": 61, + "character": 91 + } + } + }, + { + "file": "src/extensions/globalAlerts/Alerts.tsx", + "line": 6, + "description": "Using **selective imports** from **PnP** library to reduce the package size.", + "selection": { + "start": { + "line": 4, + "character": 1 + }, + "end": { + "line": 6, + "character": 24 + } + } + }, + { + "file": "src/extensions/globalAlerts/Alerts.tsx", + "line": 55, + "description": "Defining the **background color** and the **forecolor** of the text based on the properties defined.", + "selection": { + "start": { + "line": 54, + "character": 5 + }, + "end": { + "line": 55, + "character": 73 + } + } + }, + { + "file": "src/extensions/globalAlerts/Alerts.tsx", + "line": 74, + "description": "Animation method to trigger the animation using **Morphext.js** and **Animate.css**.", + "selection": { + "start": { + "line": 58, + "character": 5 + }, + "end": { + "line": 74, + "character": 7 + } + } + }, + { + "file": "src/extensions/globalAlerts/Alerts.tsx", + "line": 86, + "description": "Method to hide the **Top Placeholder** if there is no alert to display.", + "selection": { + "start": { + "line": 75, + "character": 5 + }, + "end": { + "line": 86, + "character": 7 + } + } + }, + { + "file": "src/extensions/globalAlerts/Alerts.tsx", + "line": 97, + "description": "Method to get the active and non-expired alerts from the SharePoint list.", + "selection": { + "start": { + "line": 87, + "character": 5 + }, + "end": { + "line": 97, + "character": 7 + } + } + }, + { + "file": "sharepoint/assets/elements.xml", + "line": 8, + "description": "Custom properties defined. Pre-allocated height for the top placeholder is defined to reduce the page flick when the extension is deployed. For more details, please [click here](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/extensions/overview-extensions).", + "selection": { + "start": { + "line": 7, + "character": 9 + }, + "end": { + "line": 8, + "character": 98 + } + } + } + ] +} \ No newline at end of file diff --git a/samples/js-application-alert-message/config/package-solution.json b/samples/js-application-alert-message/config/package-solution.json index 08d31c4b9..37f058a57 100644 --- a/samples/js-application-alert-message/config/package-solution.json +++ b/samples/js-application-alert-message/config/package-solution.json @@ -1,15 +1,16 @@ { "$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json", "solution": { - "name": "js-application-alert-message-client-side-solution", + "name": "js-application-alert-message", + "title": "Alert Message Extn", "id": "e06a3f71-616c-495d-9ce9-ece921d8f58d", "version": "1.0.0.0", "includeClientSideAssets": true, "isDomainIsolated": false, "features": [ { - "title": "Application Extension - Deployment of custom action.", - "description": "Deploys a custom action with ClientSideComponentId association", + "title": "Alert Message", + "description": "Custom extension to display alert message on the top placeholder.", "id": "15a67329-5278-4d3e-be53-6fdc6ccfc689", "version": "1.0.0.0", "assets": { diff --git a/samples/js-application-alert-message/sharepoint/assets/ClientSideInstance.xml b/samples/js-application-alert-message/sharepoint/assets/ClientSideInstance.xml index b4a7e071e..13914bcb7 100644 --- a/samples/js-application-alert-message/sharepoint/assets/ClientSideInstance.xml +++ b/samples/js-application-alert-message/sharepoint/assets/ClientSideInstance.xml @@ -4,7 +4,7 @@ Title="GlobalAlerts" Location="ClientSideExtension.ApplicationCustomizer" ComponentId="6ba4b6c1-ee22-421f-97d9-d2bad0a4cc57" - Properties="{"testMessage":"Test message"}" - HostProperties="{"preAllocatedApplicationCustomizerTopHeight":"50"}"> + Properties="{"animationType":"bounceInRight","animationDelay":"3000","alertBackgroundColor":"blue"}" + HostProperties="{"preAllocatedApplicationCustomizerTopHeight":"35"}"> \ No newline at end of file diff --git a/samples/js-application-alert-message/sharepoint/assets/elements.xml b/samples/js-application-alert-message/sharepoint/assets/elements.xml index a922cdafb..28d32d9c9 100644 --- a/samples/js-application-alert-message/sharepoint/assets/elements.xml +++ b/samples/js-application-alert-message/sharepoint/assets/elements.xml @@ -4,7 +4,7 @@ Title="GlobalAlerts" Location="ClientSideExtension.ApplicationCustomizer" ClientSideComponentId="6ba4b6c1-ee22-421f-97d9-d2bad0a4cc57" - ClientSideComponentProperties="{"testMessage":"Test message"}" - HostProperties="{"preAllocatedApplicationCustomizerTopHeight":"50"}"> + ClientSideComponentProperties="{"animationType":"bounceInRight","animationDelay":"3000","alertBackgroundColor":"blue"}" + HostProperties="{"preAllocatedApplicationCustomizerTopHeight":"35"}"> \ No newline at end of file diff --git a/samples/js-application-alert-message/src/extensions/globalAlerts/Alerts.tsx b/samples/js-application-alert-message/src/extensions/globalAlerts/Alerts.tsx index 332c2925b..e7a1ac0c2 100644 --- a/samples/js-application-alert-message/src/extensions/globalAlerts/Alerts.tsx +++ b/samples/js-application-alert-message/src/extensions/globalAlerts/Alerts.tsx @@ -45,9 +45,14 @@ const Qry_Alert = ` export interface IAlertsProps { animationType: string; + animationDelay: number; + alertBackgroundColor: string; + textColor: string; } export default function (props: IAlertsProps) { + let bgColor: string = props.alertBackgroundColor ? props.alertBackgroundColor : 'red'; + let textColor: string = props.textColor ? props.textColor : 'white'; const [alerts, setAlerts] = React.useState(''); const [showAlerts, setShowAlerts] = React.useState(false); const _startAlertAnimation = () => { @@ -58,7 +63,7 @@ export default function (props: IAlertsProps) { // An array of phrases to rotate are created based on this separator. Change it if you wish to separate the phrases differently (e.g. So Simple | Very Doge | Much Wow | Such Cool). separator: "~", // The delay between the changing of each phrase in milliseconds. - speed: 5000, + speed: props.animationDelay ? props.animationDelay : 5000, complete: () => { // Called after the entrance animation is executed. jQuery("#alertMessage").find(".morphext").css("display", "inline-block"); @@ -96,7 +101,7 @@ export default function (props: IAlertsProps) { return ( <> {alerts.length > 0 && -
+
{showAlerts && {alerts} } diff --git a/samples/js-application-alert-message/src/extensions/globalAlerts/GlobalAlerts.module.scss b/samples/js-application-alert-message/src/extensions/globalAlerts/GlobalAlerts.module.scss index 034ad5d38..aeec26660 100644 --- a/samples/js-application-alert-message/src/extensions/globalAlerts/GlobalAlerts.module.scss +++ b/samples/js-application-alert-message/src/extensions/globalAlerts/GlobalAlerts.module.scss @@ -1,9 +1,7 @@ .alertContainer { - height: 30px; + height: 35px; padding-left: 20px; - background-color: red; - color: white; - padding-top: 3px; + padding-top: 4px; font-weight: bold; &.animated { display: inline-block; diff --git a/samples/js-application-alert-message/src/extensions/globalAlerts/GlobalAlertsApplicationCustomizer.manifest.json b/samples/js-application-alert-message/src/extensions/globalAlerts/GlobalAlertsApplicationCustomizer.manifest.json index 4b3742215..a6b17e6ad 100644 --- a/samples/js-application-alert-message/src/extensions/globalAlerts/GlobalAlertsApplicationCustomizer.manifest.json +++ b/samples/js-application-alert-message/src/extensions/globalAlerts/GlobalAlertsApplicationCustomizer.manifest.json @@ -5,13 +5,7 @@ "alias": "GlobalAlertsApplicationCustomizer", "componentType": "Extension", "extensionType": "ApplicationCustomizer", - - // The "*" signifies that the version should be taken from the package.json "version": "*", "manifestVersion": 2, - - // If true, the component can only be installed on sites where Custom Script is allowed. - // Components that allow authors to embed arbitrary script code should set this to true. - // https://support.office.com/en-us/article/Turn-scripting-capabilities-on-or-off-1f2c515f-5d7e-448a-9fd7-835da935584f "requiresCustomScript": false } diff --git a/samples/js-application-alert-message/src/extensions/globalAlerts/GlobalAlertsApplicationCustomizer.ts b/samples/js-application-alert-message/src/extensions/globalAlerts/GlobalAlertsApplicationCustomizer.ts index e801ba1fe..f5ecfb415 100644 --- a/samples/js-application-alert-message/src/extensions/globalAlerts/GlobalAlertsApplicationCustomizer.ts +++ b/samples/js-application-alert-message/src/extensions/globalAlerts/GlobalAlertsApplicationCustomizer.ts @@ -3,7 +3,7 @@ import * as ReactDOM from 'react-dom'; import { override } from '@microsoft/decorators'; import { Log } from '@microsoft/sp-core-library'; import { - BaseApplicationCustomizer, PlaceholderName, PlaceholderContent + BaseApplicationCustomizer, PlaceholderName, PlaceholderContent } from '@microsoft/sp-application-base'; import * as strings from 'GlobalAlertsApplicationCustomizerStrings'; import { sp } from "@pnp/sp"; @@ -17,40 +17,48 @@ const LOG_SOURCE: string = 'GlobalAlertsApplicationCustomizer'; * You can define an interface to describe it. */ export interface IGlobalAlertsApplicationCustomizerProperties { - // This is an example; replace with your own property - animationType: string; + // This is an example; replace with your own property + animationType: string; + animationDelay: number; + alertBackgroundColor: string; + textColor: string; } /** A Custom Action which can be run during execution of a Client Side Application */ export default class GlobalAlertsApplicationCustomizer - extends BaseApplicationCustomizer { - private _topPlaceholder: PlaceholderContent | undefined; - private _renderPlaceHolders(): void { - // Handling the top placeholder - if (!this._topPlaceholder) { - this._topPlaceholder = this.context.placeholderProvider.tryCreateContent( - PlaceholderName.Top, - { onDispose: this._onDispose } - ); - // The extension should not assume that the expected placeholder is available. - if (!this._topPlaceholder) { - console.error("The expected placeholder (Top) was not found."); - return; - } - if (this._topPlaceholder.domElement) { - const elem: React.ReactElement = React.createElement(Alerts, { animationType: this.properties.animationType }); - ReactDOM.render(elem, this._topPlaceholder.domElement); - } - } - } - private _onDispose(): void { - console.log('[GlobalAlertApplicationCustomizer._onDispose] Disposed custom top placeholders.'); - } - @override - public onInit(): Promise { - sp.setup(this.context); - // Wait for the placeholders to be created (or handle them being changed) and then render. - this.context.placeholderProvider.changedEvent.add(this, this._renderPlaceHolders); - return Promise.resolve(); - } + extends BaseApplicationCustomizer { + private _topPlaceholder: PlaceholderContent | undefined; + private _renderPlaceHolders(): void { + // Handling the top placeholder + if (!this._topPlaceholder) { + this._topPlaceholder = this.context.placeholderProvider.tryCreateContent( + PlaceholderName.Top, + { onDispose: this._onDispose } + ); + // The extension should not assume that the expected placeholder is available. + if (!this._topPlaceholder) { + console.error("The expected placeholder (Top) was not found."); + return; + } + if (this._topPlaceholder.domElement) { + const elem: React.ReactElement = React.createElement(Alerts, { + animationType: this.properties.animationType, + animationDelay: this.properties.animationDelay, + alertBackgroundColor: this.properties.alertBackgroundColor, + textColor: this.properties.textColor + }); + ReactDOM.render(elem, this._topPlaceholder.domElement); + } + } + } + private _onDispose(): void { + console.log('[GlobalAlertApplicationCustomizer._onDispose] Disposed custom top placeholders.'); + } + @override + public onInit(): Promise { + sp.setup(this.context); + // Wait for the placeholders to be created (or handle them being changed) and then render. + this.context.placeholderProvider.changedEvent.add(this, this._renderPlaceHolders); + return Promise.resolve(); + } }