Initial Commit (#183)

This commit is contained in:
David Hartman 2017-05-06 11:42:34 -04:00 committed by Vesa Juvonen
parent d3bf47845b
commit ef0c9f7f7c
30 changed files with 702 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

32
samples/bootstrap-slider/.gitignore vendored Normal file
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": "bootstrap-slider",
"framework": "none",
"version": "1.0.0",
"libraryId": "aea96b80-92f9-49e4-9f29-34acc9990af5"
}
}

View File

@ -0,0 +1,51 @@
## Bootstrap Slider Built with jQueryr v1.x and Boostrap v3.x
## Summary
Sample bootstrap slider which pulls the slides from a list inside the SharePoint site. The list is automatically deployed once the app is installed in the SharePoint site.
![First Slider Image](./assets/slider_image_1.png)
![Second Slider Image](./assets/slider_image_2.png)
![Deployed List](./assets/List.png)
## Used SharePoint Framework Version
![drop](https://img.shields.io/badge/drop-ga-green.svg)
## Applies to
* [SharePoint Framework Developer GA](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)
--------|---------
bootstrap-slider|David Hartman ([Slalom](https://slalom.com))
## Version History
Version|Date|Comments
-------|----|--------
1.0|April 25th, 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.**
---
## Configuration Bliss
- clone this repo
- in write-manifests.json
- fill in the correct CDN path
- in the command line run:
- `npm i`
- `gulp bundle --ship`
- `gulp package-solution --ship`
- in your SharePoint Online tenant app store install the app
- add your assets to the specified path in the write-manifests.json
- the assets are found in the **temp/deploy** folder
- add the app to your SharePoint Online site
- When the app is finished installing you should see a **SPFx List** in the **Site Contents** of the site
![Deployed List](./assets/List.png)
- Add items to the **SPFx List** inorder for slides to display in the webpart

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 960 KiB

View File

@ -0,0 +1,22 @@
{
"entries": [
{
"entry": "./lib/webparts/slider/SliderWebPart.js",
"manifest": "./src/webparts/slider/SliderWebPart.manifest.json",
"outputPath": "./dist/slider.bundle.js"
}
],
"externals": {
"jquery": {
"path": "https://code.jquery.com/jquery-1.12.4.js",
"globalName": "jquery"
},
"bootstrap": {
"path": "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js",
"globalName": "bootstrap"
}
},
"localizedResources": {
"sliderStrings": "webparts/slider/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": "bootstrap-slider",
"accessKey": "<!-- ACCESS KEY -->"
}

View File

@ -0,0 +1,26 @@
{
"solution": {
"name": "bootstrap-slider-client-side-solution",
"id": "aea96b80-92f9-49e4-9f29-34acc9990af5",
"version": "1.0.0.2",
"features": [
{
"title": "slider-assets",
"description": "deploy slider assets to site",
"id": "1de84ad0-f79e-478d-84f4-231eca43385f",
"version": "1.0.0.2",
"assets": {
"elementManifests": [
"elements.xml"
],
"elementFiles": [
"schema.xml"
]
}
}
]
},
"paths": {
"zippedPackage": "solution/bootstrap-slider.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,46 @@
{
// 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,
"prefer-const": true
}
}
}

View File

@ -0,0 +1,3 @@
{
"cdnBasePath": "https://dhartman.sharepoint.com/sites/PnPSlider/SiteAssets/"
}

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": "bootstrap-slider",
"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"
},
"devDependencies": {
"@microsoft/sp-build-web": "~1.0.0",
"@microsoft/sp-module-interfaces": "~1.0.0",
"@microsoft/sp-webpart-workbench": "~1.0.0",
"@types/bootstrap": "3.3.33",
"@types/chai": ">=3.4.34 <3.6.0",
"@types/jquery": "1.10.31",
"@types/mocha": ">=2.2.33 <2.6.0",
"gulp": "~3.9.1"
},
"scripts": {
"build": "gulp bundle",
"clean": "gulp clean",
"test": "gulp test"
}
}

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Field ID="{3246929A-5ECA-4E1E-BC8F-4ED878F3A33E}"
Name="SPFxSliderImage"
DisplayName="Slider Image"
Type="Image"
RichText="TRUE"
RichTextMode="FullHtml"
Group="SPFx Slider"/>
<Field ID="{CEEFD3D4-212F-48D7-AA8F-B9A23A7C0FF6}"
Name="SPFxOrder"
DisplayName="Order"
Type="Number"
Group="SPFx Slider" />
<ContentType ID="0x01009FAF6E59182F44F6AABD475FDC8F8836"
Name="Slider"
Group="SPFx Content Types"
Description="Sample content type from web part solution">
<FieldRefs>
<FieldRef ID="{3246929A-5ECA-4E1E-BC8F-4ED878F3A33E}" />
<FieldRef ID="{CEEFD3D4-212F-48D7-AA8F-B9A23A7C0FF6}" />
</FieldRefs>
</ContentType>
<ListInstance
CustomSchema="schema.xml"
FeatureId="00bfea71-de22-43b2-a848-c05709900100"
Title="SPFx List"
Description="SPFx List"
TemplateType="100"
Url="Lists/SPFxList">
</ListInstance>
</Elements>

View File

@ -0,0 +1,31 @@
<List xmlns:ows="Microsoft SharePoint" Title="Basic List" EnableContentTypes="TRUE" FolderCreation="FALSE" Direction="$Resources:Direction;" Url="Lists/Basic List" BaseType="0" xmlns="http://schemas.microsoft.com/sharepoint/">
<MetaData>
<ContentTypes>
<ContentTypeRef ID="0x01009FAF6E59182F44F6AABD475FDC8F8836" />
</ContentTypes>
<Fields></Fields>
<Views>
<View BaseViewID="1" Type="HTML" WebPartZoneID="Main" DisplayName="$Resources:core,objectiv_schema_mwsidcamlidC24;" DefaultView="TRUE" MobileView="TRUE" MobileDefaultView="TRUE" SetupPath="pages\viewpage.aspx" ImageUrl="/_layouts/images/generic.png" Url="AllItems.aspx">
<XslLink Default="TRUE">main.xsl</XslLink>
<JSLink>clienttemplates.js</JSLink>
<RowLimit Paged="TRUE">30</RowLimit>
<Toolbar Type="Standard" />
<ViewFields>
<FieldRef Name="LinkTitle"></FieldRef>
<FieldRef Name="SPFxSliderImage"></FieldRef>
<FieldRef Name="SPFxOrder"></FieldRef>
</ViewFields>
<Query>
<OrderBy>
<FieldRef Name="ID" />
</OrderBy>
</Query>
</View>
</Views>
<Forms>
<Form Type="DisplayForm" Url="DispForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
<Form Type="EditForm" Url="EditForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
<Form Type="NewForm" Url="NewForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
</Forms>
</MetaData>
</List>

View File

@ -0,0 +1,3 @@
export interface ISliderWebPartProps {
description: string;
}

View File

@ -0,0 +1,52 @@
.helloWorld {
.container {
max-width: 700px;
margin: 0px auto;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
}
.row {
padding: 20px;
}
.listItem {
max-width: 715px;
margin: 5px auto 5px auto;
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
}
.button {
// Our button
text-decoration: none;
height: 32px;
// Primary Button
min-width: 80px;
background-color: #0078d7;
border-color: #0078d7;
color: #ffffff;
// Basic Button
outline: transparent;
position: relative;
font-family: "Segoe UI WestEuropean","Segoe UI",-apple-system,BlinkMacSystemFont,Roboto,"Helvetica Neue",sans-serif;
-webkit-font-smoothing: antialiased;
font-size: 14px;
font-weight: 400;
border-width: 0;
text-align: center;
cursor: pointer;
display: inline-block;
padding: 0 16px;
.label {
font-weight: 600;
font-size: 14px;
height: 32px;
line-height: 32px;
margin: 0 4px;
vertical-align: top;
display: inline-block;
}
}
}

View File

@ -0,0 +1,20 @@
{
"$schema": "../../../node_modules/@microsoft/sp-module-interfaces/lib/manifestSchemas/jsonSchemas/clientSideComponentManifestSchema.json",
"id": "e7d6a43a-8292-426f-bd64-f65ec47dc91b",
"alias": "SliderWebPart",
"componentType": "WebPart",
"version": "0.0.3",
"manifestVersion": 2,
"preconfiguredEntries": [{
"groupId": "e7d6a43a-8292-426f-bd64-f65ec47dc91b",
"group": { "default": "Under Development" },
"title": { "default": "Slider" },
"description": { "default": "Slider description" },
"officeFabricIconFontName": "Page",
"properties": {
"description": "Slider"
}
}]
}

View File

@ -0,0 +1,228 @@
import { Version } from '@microsoft/sp-core-library';
import {
BaseClientSideWebPart,
IPropertyPaneConfiguration,
PropertyPaneTextField,
IWebPartContext
} from '@microsoft/sp-webpart-base';
import { SPComponentLoader } from '@microsoft/sp-loader';
import { SPHttpClient, SPHttpClientResponse } from '@microsoft/sp-http';
import { escape } from '@microsoft/sp-lodash-subset';
import styles from './Slider.module.scss';
import * as strings from 'sliderStrings';
import { ISliderWebPartProps } from './ISliderWebPartProps';
import 'jquery';
import 'bootstrap';
export interface ISlides{
value: ISlide[];
}
export interface ISlide {
ID: number;
Title: string;
}
export interface ISlideItem {
SPFxSliderImage: string;
}
export interface IItemGuid {
value: string;
}
export interface slides {
Title: string;
Url: string;
}
export default class SliderWebPart extends BaseClientSideWebPart<ISliderWebPartProps> {
private _slides: slides[] = [];
public constructor(context: IWebPartContext) {
super();
SPComponentLoader.loadCss("https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css");
}
public render(): void {
/*
this.domElement.innerHTML = `
<div class="${styles.helloWorld}">
<div class="${styles.container}">
<div class="ms-Grid-row ms-bgColor-themeDark ms-fontColor-white ${styles.row}">
<div class="ms-Grid-col ms-u-lg10 ms-u-xl8 ms-u-xlPush2 ms-u-lgPush1">
<span class="ms-font-xl ms-fontColor-white">Welcome to SharePoint!</span>
<p class="ms-font-l ms-fontColor-white">Customize SharePoint experiences using Web Parts.</p>
<p class="ms-font-l ms-fontColor-white">${escape(this.properties.description)}</p>
<a href="https://aka.ms/spfx" class="${styles.button}">
<span class="${styles.label}">Learn more</span>
</a>
</div>
</div>
</div>
</div>`;*/
this._getSlides()
.then((response: ISlides): void => {
// get slider images
response.value.forEach((slide: ISlide): void => {
this._getImage(slide.ID)
.then((data: ISlideItem): void => {
// get the image out of the FieldValuesAsHtml
let div = document.createElement('div');
div.innerHTML = data.SPFxSliderImage;
let img: HTMLImageElement = div.firstChild as HTMLImageElement;
// need to do string split inorder to make the url relative
const imgUrl: string = img.src.split(this.context.pageContext.web.serverRelativeUrl)[1];
const item: slides = {
Title: slide.Title,
Url: `${this.context.pageContext.web.absoluteUrl}/_layouts/15/getpreview.ashx?resolution=2&path=${this.context.pageContext.web.serverRelativeUrl}${imgUrl}&clientType=modernWebPart`
};
this._slides.push(item);
})
.then((): void => {
this.domElement.innerHTML = `
<div class="container">
<div id="myCarousel" class="carousel slide" data-ride="carousel">
<!-- Indicators -->
<ol class="carousel-indicators"></ol>
<!-- Wrapper For Slides -->
<div class="carousel-inner" role="listbox"></div>
<!-- Side Controls -->
<a class="carousel-control left" href="#myCarousel" data-slide="prev"></a>
<a class="carousel-control right" href="#myCarousel" data-slide="next"></a>
</div>
</div>`;
// add carousel items to domElement
if (this._slides.length > 0){
this._slides.forEach((item: slides, index: number): void =>{
jQuery('.carousel-indicators', this.domElement).append(this._itemCarouselIndicators(index));
jQuery('.carousel-inner', this.domElement).append(this._itemSlideWrapper(item, index));
});
}
// initialize the slider
jQuery('#myCarousel').carousel({
interval: 7000
});
});
//console.log(img.src);
});
});
}
public onInit<T>(): Promise<T> {
// get slider items
/*this._getSlides()
.then((response: ISlides): void => {
// get slider images
response.value.forEach((slide: ISlide): void => {
this._getImage(slide.ID)
.then((data: ISlideItem): void => {
// get the image out of the FieldValuesAsHtml
let div = document.createElement('div');
div.innerHTML = data.SPFxSliderImage;
let img: HTMLImageElement = div.firstChild as HTMLImageElement;
// need to do string split inorder to make the url relative
this._getImageUrl(img.src.split(this.context.pageContext.web.serverRelativeUrl)[1])
.then((imgGuid: string) => {
const item: slides = {
Title: slide.Title,
Url: `${this.context.pageContext.web.absoluteUrl}/_layouts/15/getpreview.ashx?
resolution=4&guidSite=${this.context.pageContext.site.id}
&guidWeb=${this.context.pageContext.web.id}
&guidFile=${imgGuid}
&clientType=modernWebPart`
};
this._slides.push(item);
});
//console.log(img.src);
});
});
});*/
return Promise.resolve();
}
protected get dataVersion(): Version {
return Version.parse('1.0');
}
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
return {
pages: [
{
header: {
description: strings.PropertyPaneDescription
},
groups: [
{
groupName: strings.BasicGroupName,
groupFields: [
PropertyPaneTextField('description', {
label: strings.DescriptionFieldLabel
})
]
}
]
}
]
};
}
private _getSlides(): Promise<ISlides> {
return this.context.spHttpClient.get(`${this.context.pageContext.web.absoluteUrl}/_api/web/lists/getByTitle('SPFx List')/items?$orderBy=SPFxOrder asc`,
SPHttpClient.configurations.v1)
.then((response: SPHttpClientResponse) => {
return response.json();
});
}
private _getImage(id: number): Promise<ISlideItem>{
return this.context.spHttpClient.get(`${this.context.pageContext.web.absoluteUrl}/_api/web/lists/getByTitle('SPFx List')/items('${id}')/FieldValuesAsHtml`,
SPHttpClient.configurations.v1)
.then((response: SPHttpClientResponse) => {
return response.json();
});
}
private _getImageUrl(url: string): Promise<string> {
return this.context.spHttpClient.get(`${this.context.pageContext.web.absoluteUrl}/_api/web/GetFileByServerRelativeUrl('${this.context.pageContext.web.serverRelativeUrl}${url}')/ListItemAllFields/ServerRelatveUrl`,
SPHttpClient.configurations.v1)
.then((response: SPHttpClientResponse) => {
return response.json();
})
.then((item: IItemGuid) => {
return item.value;
});
}
private _itemCarouselIndicators(index: number): string {
if (index == 0){
return `<li data-target="#myCarousel" data-slide-to="${index}" class="active"></li>`;
}
else {
return `<li data-target="#myCarousel" data-slide-to="${index}" class=""></li>`;
}
}
private _itemSlideWrapper(item: slides, index: number): string {
if (index == 0){
return `
<div class="item active">
<img src="${item.Url}" class="img-responsive">
</div>`;
}
else {
return `
<div class="item">
<img src="${item.Url}" class="img-responsive">
</div>`;
}
}
}

View File

@ -0,0 +1,7 @@
define([], function() {
return {
"PropertyPaneDescription": "Description",
"BasicGroupName": "Group Name",
"DescriptionFieldLabel": "Description Field"
}
});

View File

@ -0,0 +1,10 @@
declare interface ISliderStrings {
PropertyPaneDescription: string;
BasicGroupName: string;
DescriptionFieldLabel: string;
}
declare module 'sliderStrings' {
const strings: ISliderStrings;
export = strings;
}

View File

@ -0,0 +1,9 @@
/// <reference types="mocha" />
import { assert } from 'chai';
describe('SliderWebPart', () => {
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" />