Added spfx sample for Employee Spotlight webpart (#244)

Added the sample webpart code to display the Employee Spotlight details
from a configured list using javascript and SharePoint framework
This commit is contained in:
Ravi Kumar Bomma 2017-07-21 23:28:04 +05:30 committed by Vesa Juvonen
parent db3a0653a2
commit 5c8f6a644d
28 changed files with 977 additions and 0 deletions

View File

@ -0,0 +1,25 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true
[*]
# change these settings to your own preference
indent_style = space
indent_size = 2
# we recommend you to keep these unchanged
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[{package,bower}.json]
indent_style = space
indent_size = 2

View File

@ -0,0 +1 @@
* text=auto

View File

@ -0,0 +1,32 @@
# Logs
logs
*.log
npm-debug.log*
# Dependency directories
node_modules
# Build generated files
dist
lib
solution
temp
*.sppkg
# Coverage directory used by tools like istanbul
coverage
# OSX
.DS_Store
# Visual Studio files
.ntvs_analysis.dat
.vs
bin
obj
# Resx Generated Code
*.resx.ts
# Styles Generated Code
*.scss.ts

View File

@ -0,0 +1,14 @@
# Folders
.vscode
coverage
node_modules
sharepoint
src
temp
# Files
*.csproj
.git*
.yo-rc.json
gulpfile.js
tsconfig.json

View File

@ -0,0 +1,8 @@
{
"@microsoft/generator-sharepoint": {
"libraryName": "js-employee-spotlight",
"framework": "none",
"version": "1.0.2",
"libraryId": "d57c7f34-22d4-45b5-9c26-441ef9fef48a"
}
}

View File

@ -0,0 +1,79 @@
# Display Employee Spotlight JavaScript Client-Side Web Part
## Summary
Simple Web Part that demonstrates the use of SharePoint Framework for show casing Employee Spotlight. The web part pulls data from a configured list and User Profile service.
The properties pane for this web part has 5 canscading dropdowns.
- A drop down list of sites(webs) in the current site collection.
- A drop down list of list titles in the selected site(web).
- 3 drop downs with list of field names from selected list, which includes
* Name(Person or Group Column).
* Splotlight Description (Multiline - Enriched text Column).
* Expiry date for Spotlight event (DateTime Column with Date only option).
- The properties pane also has options for following slider effects.
* Background color - A color picker to choose Slider background color
* Font color - A color picker to choose Slider font color
* Set Auto slide - A switch to enable/disable auto slide for slider
* Slider Speed - A Slider control to select slider speed from 0sec - 7sec with 0.5sec as a step.
![Screeshot of the Employee Spotlight web part options](./assets/Employee-spotlight-options.png).
Once the user selects all the configuration details, the web part displays the spotlight details from the configured list.
![Screeshot of the Employee Spotlight web part](./assets/Employee-spotlight-priview.png).
> Data is displayed only when hosted in SharePoint. No mock data included at this point for local testing.
## Used SharePoint Framework Version
![drop](https://img.shields.io/badge/drop-GA-green.svg)
## Applies to
* [SharePoint Framework Developer](http://dev.office.com/sharepoint/docs/spfx/sharepoint-framework-overview)
* [Office 365 developer tenant](http://dev.office.com/sharepoint/docs/spfx/set-up-your-developer-tenant)
## Solution
Solution|Author(s)
--------|---------
js-employee-spotlight| SPS (Strategic Products and Services)
## Version history
Version|Date|Comments
-------|----|--------
1.0|June 12, 2017|Initial release
## Disclaimer
**THIS CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
---
## Minimal Path to Awesome
- Clone this repository
- in the command line run:
- `npm install`
- `tsd install`
- `gulp serve`
- `Open the workbench on your Office 365 Developer tenant`
- Basic functionality can be tested locally, data is only shown when used in context of SharePoint
## Features
The js-employee-spotlight web part displays the content of the list specified in the web part properties pane, The list should have the 3 mandatory fields.
This Web Part illustrates the following concepts on top of the SharePoint Framework:
* Using a dynamic drop down box in the web part properties pane to display cascading dropdowns, which contains
- the titles webs in current sitecollection
- titles of the lists in the selected web
- fields of a selected list
* Use of a third party control(sp-client-custom-fields) for selecting webpart foregroud and background colors.
* Use of switch, slider controls to configure slider speed and auto scrolling.
* Using a javascript slider.
* Fetching the user details from User Profile service like user designation, user profile image.
* Logging.
* Rendering error messages.

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

View File

@ -0,0 +1,14 @@
{
"entries": [{
"entry": "./lib/webparts/employeeSpotlight/EmployeeSpotlightWebPart.js",
"manifest": "./src/webparts/employeeSpotlight/EmployeeSpotlightWebPart.manifest.json",
"outputPath": "./dist/employee-spotlight.bundle.js"
}],
"externals": {
"sp-client-custom-fields": "node_modules/sp-client-custom-fields/dist/sp-client-custom-fields.bundle.js"
},
"localizedResources": {
"sp-client-custom-fields/strings": "../node_modules/sp-client-custom-fields/lib/loc/{locale}.js",
"employeeSpotlightStrings": "webparts/employeeSpotlight/loc/{locale}.js"
}
}

View File

@ -0,0 +1,3 @@
{
"deployCdnPath": "temp/deploy"
}

View File

@ -0,0 +1,6 @@
{
"workingDir": "./temp/deploy/",
"account": "<!-- STORAGE ACCOUNT NAME -->",
"container": "js-employee-spotlight",
"accessKey": "<!-- ACCESS KEY -->"
}

View File

@ -0,0 +1,10 @@
{
"solution": {
"name": "Employee Spotlight-v1",
"id": "d57c7f34-22d4-45b5-9c26-441ef9fef482",
"version": "2.0.0.0"
},
"paths": {
"zippedPackage": "solution/EmployeeSpotlight-v1.sppkg"
}
}

View File

@ -0,0 +1,9 @@
{
"port": 4321,
"initialPage": "https://localhost:5432/workbench",
"https": true,
"api": {
"port": 5432,
"entryPath": "node_modules/@microsoft/sp-webpart-workbench/lib/api/"
}
}

View File

@ -0,0 +1,45 @@
{
// Display errors as warnings
"displayAsWarning": true,
// The TSLint task may have been configured with several custom lint rules
// before this config file is read (for example lint rules from the tslint-microsoft-contrib
// project). If true, this flag will deactivate any of these rules.
"removeExistingRules": true,
// When true, the TSLint task is configured with some default TSLint "rules.":
"useDefaultConfigAsBase": false,
// Since removeExistingRules=true and useDefaultConfigAsBase=false, there will be no lint rules
// which are active, other than the list of rules below.
"lintConfig": {
// Opt-in to Lint rules which help to eliminate bugs in JavaScript
"rules": {
"class-name": false,
"export-name": false,
"forin": false,
"label-position": false,
"member-access": true,
"no-arg": false,
"no-console": false,
"no-construct": false,
"no-duplicate-case": true,
"no-duplicate-variable": true,
"no-eval": false,
"no-function-expression": true,
"no-internal-module": true,
"no-shadowed-variable": true,
"no-switch-case-fall-through": true,
"no-unnecessary-semicolons": true,
"no-unused-expression": true,
"no-unused-imports": true,
"no-use-before-declare": true,
"no-with-statement": true,
"semicolon": true,
"trailing-comma": false,
"typedef": false,
"typedef-whitespace": false,
"use-named-parameter": true,
"valid-typeof": true,
"variable-name": false,
"whitespace": false
}
}
}

View File

@ -0,0 +1,3 @@
{
"cdnBasePath": ""
}

View File

@ -0,0 +1,6 @@
'use strict';
const gulp = require('gulp');
const build = require('@microsoft/sp-build-web');
build.initialize(gulp);

View File

@ -0,0 +1,29 @@
{
"name": "js-employee-spotlight",
"version": "0.0.1",
"private": true,
"engines": {
"node": ">=0.10.0"
},
"dependencies": {
"@microsoft/sp-client-base": "~1.0.0",
"@microsoft/sp-core-library": "~1.0.0",
"@microsoft/sp-webpart-base": "~1.0.0",
"@types/webpack-env": ">=1.12.1 <1.14.0",
"sp-client-custom-fields": "^1.3.4"
},
"devDependencies": {
"@microsoft/sp-build-web": "~1.0.1",
"@microsoft/sp-module-interfaces": "~1.0.0",
"@microsoft/sp-webpart-workbench": "~1.0.0",
"@types/chai": ">=3.4.34 <3.6.0",
"@types/mocha": ">=2.2.33 <2.6.0",
"gulp": "~3.9.1",
"gulp-util": "^3.0.8"
},
"scripts": {
"build": "gulp bundle",
"clean": "gulp clean",
"test": "gulp test"
}
}

View File

@ -0,0 +1,82 @@
* {
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box!important;
}
* {
box-sizing: border-box
}
/* Slideshow container */
.containers {
max-width: 1000px;
min-width: 350px;
min-height: 160px;
position: relative;
margin: auto;
overflow: hidden;
}
.mySlides {
display: none;
transition: 1s all ease-in-out;
-webkit-animation: slideIn 1s forwards;
-moz-animation: slideIn 1s forwards;
animation: slideIn 1s forwards;
}
/* Next & previous buttons */
.prev{
left:0;
border-radius: 0 3px 3px 0;
}
.prev,
.next {
cursor: pointer;
position: absolute;
top: 50%;
width: auto;
margin-top: -22px;
padding: 8px;
color: white;
font-weight: bold;
font-size: 18px;
transition: 0.6s all ease;
}
/* Position the "next button" to the right */
.next {
right: 0;
border-radius: 3px 0 0 3px;
}
/* On hover, add a black background color with a little bit see-through */
.prev:hover,
.next:hover {
background-color: rgba(0, 0, 0, 0.8);
}
@-webkit-keyframes slideIn {
0% {
transform: translateX(0);
}
100% {
transform: translateX(900px);
}
}
@-moz-keyframes slideIn {
0% {
transform: translateX(0);
}
100% {
transform: translateX(900px);
}
}
@keyframes slideIn {
0% {
transform: translateX(-900px);
}
100% {
transform: translateX(0);
}
}

View File

@ -0,0 +1,23 @@
{
"$schema": "../../../node_modules/@microsoft/sp-module-interfaces/lib/manifestSchemas/jsonSchemas/clientSideComponentManifestSchema.json",
"id": "54d10877-595f-464d-81f0-19fb840c766f",
"alias": "EmployeeSpotlightWebPart",
"componentType": "WebPart",
"version": "0.0.1",
"manifestVersion": 2,
"preconfiguredEntries": [{
"groupId": "54d10877-595f-464d-81f0-19fb840c766f",
"group": { "default": "SPFx Webparts" },
"title": { "default": "Employee Spotlight" },
"description": { "default": "This webpart shows the employee spotlight information." },
"officeFabricIconFontName": "Page",
"properties": {
"description": "Employee Spotlight",
"spotlightBGColor": "#3f0d3e",
"spotlightFontColor": "#ffffff",
"enabledSpotlightAutoPlay": true
}
}]
}

View File

@ -0,0 +1,467 @@
/**
* @file
* Spotlight Web Part with SharePoint Framework
* Author: SPS-COM
* Copyright (c) 2017
*/
import { Version } from '@microsoft/sp-core-library';
import {
BaseClientSideWebPart,
IPropertyPaneConfiguration,
IPropertyPaneDropdownOption,
PropertyPaneDropdown,
PropertyPaneToggle,
PropertyPaneSlider
} from '@microsoft/sp-webpart-base';
import { SPComponentLoader } from '@microsoft/sp-loader';
import { SPHttpClient } from '@microsoft/sp-http';
import {
Environment,
EnvironmentType
} from '@microsoft/sp-core-library';
import { PropertyFieldColorPickerMini } from 'sp-client-custom-fields/lib/PropertyFieldColorPickerMini';
import * as jQuery from 'jquery';
import * as _ from "lodash";
import styles from './EmployeeSpotlight.module.scss';
import * as strings from 'employeeSpotlightStrings';
import { IEmployeeSpotlightWebPartProps } from './IEmployeeSpotlightWebPartProps';
import { SliderHelper } from './Helper';
/**
* An interface to hold the key and value.
*/
export interface ResponceDetails {
title: string;
id: string;
}
/**
* An interface to hold the ResponceDetails collection.
*/
export interface ResponceCollection {
value: ResponceDetails[];
}
/**
* An interface to hold the SpotlightDetails.
*/
export interface SpotlightDetails {
userDisplayName: string;
userEmail: string;
userProfilePic: string;
description: string;
designation?: string;
}
/**
* A class that contains spotlight webpart operations and corresponding properties to hold the data.
*/
export default class EmployeeSpotlightWebPart extends BaseClientSideWebPart<IEmployeeSpotlightWebPartProps> {
private spotlightListFieldOptions: IPropertyPaneDropdownOption[] = [];
private spotlightListOptions: IPropertyPaneDropdownOption[] = [];
private siteOptions: IPropertyPaneDropdownOption[] = [];
private defaultProfileImageUrl: string = "/_layouts/15/userphoto.aspx?size=L";
private helper: SliderHelper = new SliderHelper();
private sliderControl: any = null;
/**
* Constructor of SpotlightWebpart class.
*/
public constructor() {
super();
SPComponentLoader.loadScript('https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js', { globalExportsName: 'jQuery' });
// Next button functionality
jQuery(document).on("click", "." + styles.next, (event) => {
event.preventDefault(); //prevent default action of <a>
this.helper.moveSlides(1);
});
// Previous button functionality
jQuery(document).on("click", "." + styles.prev, (event) => {
event.preventDefault(); //prevent default action of <a>
this.helper.moveSlides(-1);
});
// start and stop slider on hover
jQuery(document).ready(() => {
jQuery(document).on('mouseenter', '.' + styles.containers, () => {
if (this.properties.enabledSpotlightAutoPlay)
clearInterval(this.sliderControl);
}).on('mouseleave', '.' + styles.containers, () => {
var carouselSpeed: number = this.properties.spotlightSliderSpeed * 1000;
if (carouselSpeed && this.properties.enabledSpotlightAutoPlay)
this.sliderControl = setInterval(this.helper.startAutoPlay, carouselSpeed);
});
});
}
/**
* A starting point for application.
*/
public render(): void {
this.domElement.innerHTML = `<div id="spListContainer" />`;
this._renderSpotlightTemplateAsync();
this._renderSpotlightDataAsync();
}
/**
* Builds the spotlight details collection with necessary details.
*/
private _renderSpotlightTemplateAsync(): void {
if (Environment.type == EnvironmentType.SharePoint || Environment.type == EnvironmentType.ClassicSharePoint) {
this._getSiteCollectionRootWeb().then((response) => {
this.properties.spotlightSiteCollectionURL = response['Url'];
});
if (this.properties.spotlightSiteURL && this.properties.spotlightListName && this.properties.spotlightEmployeeEmailColumn && this.properties.spotlightDescriptionColumn) {
let spotlightDataCollection: SpotlightDetails[] = [];
this._getSpotlightListData(this.properties.spotlightSiteURL, this.properties.spotlightListName, this.properties.spotlightEmployeeExpirationDateColumn, this.properties.spotlightEmployeeEmailColumn, this.properties.spotlightDescriptionColumn)
.then((listDataResponse) => {
var spotlightListData = listDataResponse.value;
if (spotlightListData) {
debugger;
for (var key in listDataResponse.value) {
var email = listDataResponse.value[key][this.properties.spotlightEmployeeEmailColumn]["EMail"];
var id = listDataResponse.value[key]["ID"];
this._getUserImage(email)
.then((response) => {
spotlightListData.forEach((item: ResponceDetails) => {
let userSpotlightDetails: SpotlightDetails = { userDisplayName: "", userEmail: "", userProfilePic: "", description: "" };
if (item[this.properties.spotlightEmployeeEmailColumn]["EMail"] == response["Email"]) {
var userName = item[this.properties.spotlightEmployeeEmailColumn];
var description = item[this.properties.spotlightDescriptionColumn];
var userDescription = "";
try {
userDescription = $(description).text();
}
catch (err) {
userDescription = description;
}
if (userDescription.length > 140) {
var displayFormUrl = this.properties.spotlightSiteURL + '/Lists/' + this.properties.spotlightListName + '/DispForm.aspx?ID=' + id;
userDescription = userDescription.substring(0, 140) + `&nbsp; <a href="${displayFormUrl}">ReadMore...</a>`;
}
var displayName = response["DisplayName"];
var designationProperty = _.filter(response["UserProfileProperties"], { Key: "SPS-JobTitle" })[0];
var designation = designationProperty["Value"] ? designationProperty["Value"] : "";
// uses default image if user image not exist
var profilePicture = response["PictureUrl"] != null && response["PictureUrl"] != undefined ? (<string>response["PictureUrl"]).replace("MThumb", "LThumb") : this.defaultProfileImageUrl;
// var profilePicture = response["PictureUrl"] != null && response["PictureUrl"] != undefined ? (<string>response["PictureUrl"]) : this.defaultProfileImageUrl;
profilePicture = '/_layouts/15/userphoto.aspx?accountname=' + displayName + '&size=M&url=' + profilePicture.split("?")[0];
userSpotlightDetails = {
userDisplayName: response["DisplayName"],
userEmail: response["Email"],
userProfilePic: profilePicture,
description: userDescription,
designation: designation
};
spotlightDataCollection.push(userSpotlightDetails);
}
});
this._addSpotlightTemplateContent(spotlightDataCollection);
if (this.sliderControl == null && this.properties && this.properties.enabledSpotlightAutoPlay) {
setTimeout(this.helper.moveSlides(), 2000);
this.sliderControl = setInterval(this.helper.startAutoPlay, this.properties.spotlightSliderSpeed * 1000);
}
});
}
}
});
}
}
}
/**
* Renders the webpart html with the given spotlight details collection.
* @param spotlightDetails - a collection of spotlight details.
*/
private _addSpotlightTemplateContent(spotlightDetails: SpotlightDetails[]): void {
this.domElement.innerHTML = '';
var innerContent: string = '';
for (let i: number = 0; i < spotlightDetails.length; i++) {
innerContent += `
<div class="${styles.mySlides}">
<div style="width:100%;">
<div style="width:36%;float:left;padding:10% 0;">
<img style="border-radius:50%;width: 90px;" src="${spotlightDetails[i].userProfilePic}" />
</div>
<div style="width:60%;float:left;text-align:left;">
<h5 style="margin-bottom:0; text-transform: uppercase;text-align:center;">${spotlightDetails[i].userDisplayName}</h5>
<h6 style="text-align:center;">${spotlightDetails[i].designation}</h6>
<p>${spotlightDetails[i].description}</p>
</div>
</div>
</div>`;
}
this.domElement.innerHTML +=
`<div class="${styles.containers}" id="slideshow" style="background-color: ${this.properties.spotlightBGColor}; cursor:pointer; width: 100%!important; padding: 5px;border-radius: 15px;box-shadow: rgba(0,0,0,0.25) 0 0 20px 0;text-align:center;color:${this.properties.spotlightFontColor};">
` + innerContent + `
<a class="${styles.prev}">&#10094;</a>
<a class="${styles.next}">&#10095;</a>
</div>`;
}
/**
* A generic utility function to execute the rest api call and return the corresponding result as a promise.
* @param url - The string containing api url.
*/
private _callAPI(url: string): Promise<ResponceCollection> {
return this.context.spHttpClient.get(url, SPHttpClient.configurations.v1).then((response) => {
return response.json();
});
}
/**
* Returns a promise that returns user image url and name.
* @param email - The string containing user email id.
*/
private _getUserImage(email: string): Promise<ResponceCollection> {
return this._callAPI(this.properties.spotlightSiteCollectionURL + "/_api/SP.UserProfiles.PeopleManager/GetPropertiesFor(accountName=@v)?@v='i:0%23.f|membership|" + email + "'");
}
/**
* Returns a promise that returns sitecollection rootweb url.
*/
private _getSiteCollectionRootWeb(): Promise<ResponceCollection> {
return this._callAPI(this.context.pageContext.web.absoluteUrl + `/_api/Site/RootWeb?$select=Title,Url`);
}
/**
* Returns a promise that returns all the subsite names from the given sitecollection.
* @param spotlightSiteCollectionURL - The string containing user email id.
*/
private _getAllSubsites(spotlightSiteCollectionURL: string): Promise<ResponceCollection> {
return this._callAPI(spotlightSiteCollectionURL + `/_api/web/webs?$select=Title,Url`);
}
/**
* Returns a promise that returns all the list names in corresponding site.
* @param siteUrl - The string containing site url.
*/
private _getAllLists(siteUrl: string): Promise<ResponceCollection> {
if (siteUrl != "" && siteUrl != undefined) {
return this._callAPI(siteUrl + `/_api/web/lists?$orderby=Id desc&$filter=Hidden eq false and BaseTemplate eq 100`);
}
}
/**
* Returns a promise that returns spotlight list field names.
* @param siteUrl - The string containing site url.
* @param spotlightListName - The string containing spotlight list name.
*/
private _getSpotlightListFields(siteUrl: string, spotlightListName: string): Promise<ResponceCollection> {
if (siteUrl != "" && spotlightListName != "" && siteUrl != undefined && spotlightListName != undefined) {
return this._callAPI(siteUrl + `/_api/web/lists/GetByTitle('${spotlightListName}')/Fields?$orderby=Id desc&$filter=Hidden eq false and ReadOnlyField eq false`);
}
}
/**
* Loads all the subsites in the current sitecollection and initiates the corresponding dropdown values loading.
*/
private _renderSpotlightDataAsync(): void {
this._getSiteCollectionRootWeb()
.then((response) => {
this.properties.spotlightSiteCollectionURL = response['Url'];
this._getAllSubsites(response['Url'])
.then((sitesResponse) => {
this.siteOptions = this._getDropDownCollection(sitesResponse, 'Url', 'Title');
this.context.propertyPane.refresh();
if (this.properties.spotlightSiteURL != "") {
this._loadAllListsDropDown(this.properties.spotlightSiteURL);
}
if (this.properties.spotlightListName != "") {
this._loadSpotlightListFieldsDropDown(this.properties.spotlightSiteURL, this.properties.spotlightListName);
}
});
});
}
/**
* Loads all the list names in the selected site for spotlight list dropdown.
* @param siteUrl - The string containing site url.
*/
private _loadAllListsDropDown(siteUrl: string): void {
this._getAllLists(siteUrl)
.then((response) => {
this.spotlightListOptions = this._getDropDownCollection(response, 'Title', 'Title');
this.context.propertyPane.refresh();
});
}
/**
* Loads the spotlight list fields for fields dropdown.
* @param siteUrl - The string containing site url.
* @param spotlightListName - The string containing spotlight list name.
*/
private _loadSpotlightListFieldsDropDown(siteUrl: string, spotlightListName: string): void {
this._getSpotlightListFields(siteUrl, spotlightListName)
.then((response) => {
this.spotlightListFieldOptions = this._getDropDownCollection(response, 'Title', 'Title');
this.context.propertyPane.refresh();
});
}
/**
* Returns the dropdown key and values collection.
* @param response - The collection containing keys and values.
* @param key - The string containing key.
* @param text - The string containing value.
*/
private _getDropDownCollection(response: ResponceCollection, key: string, text: string): IPropertyPaneDropdownOption[] {
var dropdownOptions: IPropertyPaneDropdownOption[] = [];
if (key == 'Url')
dropdownOptions.push({ key: this.context.pageContext.web.absoluteUrl, text: 'This Site' });
for (var itemKey in response.value) {
dropdownOptions.push({ key: response.value[itemKey][key], text: response.value[itemKey][text] });
}
return dropdownOptions;
}
/**
* Returns a promise that returns spotlight list items.
* @param siteUrl - The string containing site url.
* @param spotlightListName - The string containing spotlight list name.
*/
private _getSpotlightListData(siteUrl: string, spotlightListName: string, expiryDateColumn: string, emailColumn: string, descriptionColumn: string): Promise<ResponceCollection> {
if (siteUrl != "" && spotlightListName != "") {
var today: Date = new Date();
var dd: any = today.getDate();
var mm: any = today.getMonth() + 1; //January is 0!
var yyyy: any = today.getFullYear();
dd = (dd < 10) ? '0' + dd : dd;
mm = (mm < 10) ? '0' + mm : mm;
var dateString: string = `${yyyy}-${mm}-${dd}`;
emailColumn = emailColumn.replace(" ", "_x0020_");
descriptionColumn = descriptionColumn.replace(" ", "_x0020_");
expiryDateColumn = expiryDateColumn.replace(" ", "_x0020_");
return this._callAPI(siteUrl + `/_api/web/lists/GetByTitle('${spotlightListName}')/items?$select=ID,${descriptionColumn},${emailColumn}/EMail&$expand=${emailColumn}/Id&$orderby=Id desc&$filter=${expiryDateColumn} ge '${dateString}'`);
}
}
/**
* Validates the Property pane fields for null checks
* @param value - The string value of the field to be validated.
*/
private _validateFiledValue(value: string): string {
var validationMessage: string = '';
if (value === null || value.trim().length === 0) {
validationMessage = 'Please select a value';
}
return validationMessage;
}
protected get dataVersion(): Version {
return Version.parse('1.0');
}
/**
* Builds the Propertypane with specific configurations.
*/
protected onPropertyPaneConfigurationStart(): void {
// Stops execution, if the list values already exists
if (this.spotlightListOptions.length > 0) return;
// Calls function to append the list names to dropdown
this._renderSpotlightTemplateAsync();
}
/**
* Triggers foreach Property pane value update and loads the corresponding details.
* @param propertyPath - The string containing property path.
* @param oldValue - The string containing old value of property.
* @param newValue - The string containing new value of property.
*/
protected onPropertyPaneFieldChanged(propertyPath: string, oldValue: any, newValue: any): void {
switch (propertyPath) {
case "spotlightSiteURL":
this.properties.spotlightListName = "";
this._loadAllListsDropDown(this.properties.spotlightSiteURL);
break;
case "spotlightListName":
this.properties.spotlightEmployeeEmailColumn = "";
this.properties.spotlightDescriptionColumn = "";
this._loadSpotlightListFieldsDropDown(this.properties.spotlightSiteURL, this.properties.spotlightListName);
break;
default:
break;
}
}
/**
* Retuns the property pane configuration.
*/
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
return {
pages: [
{
groups: [
{
groupName: strings.propertyPaneHeading,
groupFields: [
PropertyPaneDropdown('spotlightSiteURL', {
label: strings.selectSiteLableMessage,
options: this.siteOptions,
selectedKey: this._validateFiledValue.bind(this)
}),
PropertyPaneDropdown('spotlightListName', {
label: strings.selectListLableMessage,
options: this.spotlightListOptions,
selectedKey: this._validateFiledValue.bind(this)
}),
PropertyPaneDropdown('spotlightEmployeeEmailColumn', {
label: strings.employeeEmailcolumnLableMessage,
options: this.spotlightListFieldOptions,
selectedKey: this._validateFiledValue.bind(this)
}),
PropertyPaneDropdown('spotlightDescriptionColumn', {
label: strings.descriptioncolumnLableMessage,
options: this.spotlightListFieldOptions,
selectedKey: this._validateFiledValue.bind(this)
}),
PropertyPaneDropdown('spotlightEmployeeExpirationDateColumn', {
label: strings.expirationDateColumnLableMessage,
options: this.spotlightListFieldOptions,
selectedKey: this._validateFiledValue.bind(this)
})
]
},
{
groupName: strings.effectsGroupName,
groupFields: [
PropertyFieldColorPickerMini('spotlightBGColor', {
label: strings.spotlightBGColorLableMessage,
initialColor: this.properties.spotlightBGColor,
disabled: false,
onPropertyChange: this.onPropertyPaneFieldChanged.bind(this),
properties: this.properties,
onGetErrorMessage: null,
deferredValidationTime: 0,
key: 'spotlightBGColorFieldId'
}),
PropertyFieldColorPickerMini('spotlightFontColor', {
label: strings.spotlightFontColorLableMessage,
initialColor: this.properties.spotlightFontColor,
disabled: false,
onPropertyChange: this.onPropertyPaneFieldChanged.bind(this),
properties: this.properties,
onGetErrorMessage: null,
deferredValidationTime: 0,
key: 'spotlightFontColorFieldId'
}),
PropertyPaneToggle('enabledSpotlightAutoPlay', {
label: strings.enableAutoSlideLableMessage
}),
PropertyPaneSlider('spotlightSliderSpeed', {
label: strings.carouselSpeedLableMessage,
min: 0,
max: 7,
value: 3,
showValue: true,
step: 0.5
})
]
}
]
}
]
};
}
}

View File

@ -0,0 +1,42 @@
import styles from './EmployeeSpotlight.module.scss';
export class SliderHelper {
public static slideIndex: number = 0;
// /**
// * Constructor of helper class.
// */
public constructor() {
SliderHelper.slideIndex = 0;
}
/**
* auto play slider
*/
public startAutoPlay(): void {
var slides = <HTMLScriptElement[]><any>document.getElementsByClassName(styles.mySlides);
debugger;
if (slides.length > 0) {
for (var i: number = 0; i < slides.length; i++) {
slides[i].style.display = SliderHelper.slideIndex == i ? "block" : "none";
}
SliderHelper.slideIndex = (++SliderHelper.slideIndex) >= slides.length ? 0 : SliderHelper.slideIndex;
}
}
/**
* move slide
* @param n - slide index.
*/
public moveSlides(n: number = 0): boolean {
SliderHelper.slideIndex += n;
var slides = (<HTMLScriptElement[]><any>document.getElementsByClassName(styles.mySlides));
if (slides.length > 0) {
if (SliderHelper.slideIndex >= slides.length) { SliderHelper.slideIndex = 0; }
if (SliderHelper.slideIndex < 0) { SliderHelper.slideIndex = slides.length - 1; }
for (var i: number = 0; i < slides.length; i++) {
slides[i].style.display = SliderHelper.slideIndex == i ? "block" : "none";
}
}
return true;
}
}

View File

@ -0,0 +1,13 @@
export interface IEmployeeSpotlightWebPartProps {
description: string;
spotlightSiteCollectionURL: string;
spotlightSiteURL: string;
spotlightListName: string;
spotlightEmployeeEmailColumn: string;
spotlightEmployeeExpirationDateColumn: string;
spotlightBGColor:string;
spotlightFontColor:string;
spotlightDescriptionColumn: string;
spotlightSliderSpeed: number;
enabledSpotlightAutoPlay: boolean;
}

View File

@ -0,0 +1,15 @@
define([], function() {
return {
"propertyPaneHeading": "Spotlight Configuration",
"selectSiteLableMessage": "Select Site",
"selectListLableMessage": "Select List Name",
"employeeEmailcolumnLableMessage": "Select Employee Name column",
"descriptioncolumnLableMessage": "Select Description column",
"expirationDateColumnLableMessage": "Select ExpiryDate column",
"effectsGroupName": "Slider Effects",
"spotlightBGColorLableMessage": "Background Color",
"spotlightFontColorLableMessage": "Font Color",
"enableAutoSlideLableMessage": "Enable auto slide",
"carouselSpeedLableMessage": "Slider speed(in seconds)"
}
});

View File

@ -0,0 +1,18 @@
declare interface IEmployeeSpotlightStrings {
propertyPaneHeading: string;
selectSiteLableMessage: string;
selectListLableMessage: string;
employeeEmailcolumnLableMessage: string;
descriptioncolumnLableMessage: string;
expirationDateColumnLableMessage: string;
effectsGroupName: string;
spotlightBGColorLableMessage:string;
spotlightFontColorLableMessage:string;
enableAutoSlideLableMessage: string;
carouselSpeedLableMessage: string;
}
declare module 'employeeSpotlightStrings' {
const strings: IEmployeeSpotlightStrings;
export = strings;
}

View File

@ -0,0 +1,9 @@
/// <reference types="mocha" />
import { assert } from 'chai';
describe('EmployeeSpotlightWebPart', () => {
it('should do something', () => {
assert.ok(true);
});
});

View File

@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "es5",
"forceConsistentCasingInFileNames": true,
"module": "commonjs",
"jsx": "react",
"declaration": true,
"sourceMap": true,
"types": [
"es6-promise",
"es6-collections",
"webpack-env"
]
}
}

View File

@ -0,0 +1,8 @@
// Type definitions for Microsoft ODSP projects
// Project: ODSP
/* Global definition for UNIT_TEST builds
Code that is wrapped inside an if(UNIT_TEST) {...}
block will not be included in the final bundle when the
--ship flag is specified */
declare const UNIT_TEST: boolean;

View File

@ -0,0 +1 @@
/// <reference path="@ms/odsp.d.ts" />