Js advanced commenting (#1131)
* Advanced comment box sample * Typo error Updated the SharePoint generator version info. Co-authored-by: Mikael Svenson <miksvenson@gmail.com> Co-authored-by: Laura Kokkarinen <41330990+LauraKokkarinen@users.noreply.github.com>
This commit is contained in:
parent
4242412984
commit
8acf36979f
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"@microsoft/generator-sharepoint": {
|
||||
"isCreatingSolution": true,
|
||||
"environment": "spo",
|
||||
"version": "1.9.1",
|
||||
"libraryName": "modern-page-comments",
|
||||
"libraryId": "cfa8dbcf-b32d-4de0-a6ba-af486007c2f2",
|
||||
"packageManager": "npm",
|
||||
"isDomainIsolated": false,
|
||||
"componentType": "webpart"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
# Advanced Comments Box
|
||||
|
||||
## Summary
|
||||
> This component is developed for the advanced usage of commenting the page or article etc. **_Page Comments_** lists will be created to store the comments. Following are some of the features of this component.
|
||||
* Can be used in the modern page with the existing comments disabled.
|
||||
* Classification of comments by **_Popular_**, **_Newest_**, **_Oldest_** and **_Attachments_**
|
||||
* Ability to refer files as a comment.
|
||||
* **_Edit_**, **_Reply_** (nested comments), **_Like_** & **_Delete_** options are available based on the configuration.
|
||||
* **_Hashtag_** & **_Ping Users_** are also available.
|
||||
* **_Document Preview_** is also available for all office documents and videos based on the configuration.
|
||||
* Display of **_New_** icon for the current day comments.
|
||||
|
||||
## Properties
|
||||
|
||||
1. **_DateTime_** format on when the comments were added or modified
|
||||
|
||||
2. **_Profile Picture_** style, whether it has to be rounded or square
|
||||
|
||||
3. Enable or Disable **_Navigation_** whether to display the comments classification
|
||||
|
||||
4. Enable or disable **_Attachments_**. Following properties are required when attachments are enabled.
|
||||
|
||||
* **_Library_** to store the files uploaded.
|
||||
* Allowed **_File Formats_** in the comments box.
|
||||
* Maximum **_File Size_** allowed.
|
||||
|
||||
5. **_Ping Users_** will allow to mention the users. The users are pulled from the **Site Users**.
|
||||
|
||||
6. **_Edit_** comments can be enabled or disabled to allow the users to edit the comments. Files added can be deleted not edited.
|
||||
* **_Delete_** option can be enabled or disabled to allow the users to delete the comments. Comments with no-replies are allowed to delete. Delete is allowed only if Edit is allowed.
|
||||
|
||||
7. **_Upvoting_** of comments to like or dislike the comments.
|
||||
|
||||
8. **_Hashtags_**
|
||||
|
||||
9. **_Document Preview_** can be enabled or disabled for the office files and videos.
|
||||
|
||||
|
||||
## Preview
|
||||
![Advanced-Comments-Box](./assets/Advanced-Comments-Box.gif)
|
||||
|
||||
## Used SharePoint Framework Version
|
||||
![drop](https://img.shields.io/badge/version-GA-green.svg)
|
||||
|
||||
## Applies to
|
||||
|
||||
* [SharePoint Framework](https:/dev.office.com/sharepoint)
|
||||
* [Office 365 tenant](https://dev.office.com/sharepoint/docs/spfx/set-up-your-development-environment)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
> **@microsoft/generator-sharepoint - 1.9.1**
|
||||
|
||||
## Solution
|
||||
|
||||
Solution|Author(s)
|
||||
--------|---------
|
||||
SPFxPageComments | Sudharsan K.([@sudharsank](https://twitter.com/sudharsank), [Know More](http://windowssharepointserver.blogspot.com/))
|
||||
|
||||
## Version history
|
||||
|
||||
Version|Date|Comments
|
||||
-------|----|--------
|
||||
1.0.0.0|Feb 05 2020|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`
|
||||
- `gulp bundle --ship && gulp package-solution --ship`
|
||||
- Add the .sppkg file to the app catalog and add the **Page Comments** web part to the page.
|
||||
|
||||
## Features
|
||||
- Used [SharePoint Framework Property Controls](https://sharepoint.github.io/sp-dev-fx-property-controls/) to create the property pane controls(Text, ListPicker, Toggle) with callout.
|
||||
- Used [PnP](https://pnp.github.io/pnpjs/) for communication with SharePoint.
|
||||
- Used [jquery-comments](https://viima.github.io/jquery-comments/) for comments control with some customization.
|
||||
- Used [Moment.js](https://momentjs.com/) for datetime formatting.
|
||||
|
||||
#### Local Mode
|
||||
This solution doesn't work on local mode.
|
||||
|
||||
#### SharePoint Mode
|
||||
If you want to try on a real environment, open:
|
||||
[O365 Workbench](https://your-domain.sharepoint.com/_layouts/15/workbench.aspx)
|
Binary file not shown.
After Width: | Height: | Size: 7.9 MiB |
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
|
||||
"version": "2.0",
|
||||
"bundles": {
|
||||
"page-comments-web-part": {
|
||||
"components": [
|
||||
{
|
||||
"entrypoint": "./lib/webparts/pageComments/PageCommentsWebPart.js",
|
||||
"manifest": "./src/webparts/pageComments/PageCommentsWebPart.manifest.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"externals": {
|
||||
"jquery": {
|
||||
"path": "node_modules/jquery/dist/jquery.min.js",
|
||||
"globalName": "jQuery"
|
||||
},
|
||||
"textcomplete": {
|
||||
"path": "https://cdnjs.cloudflare.com/ajax/libs/jquery.textcomplete/1.8.0/jquery.textcomplete.js",
|
||||
"globalName": "jQuery",
|
||||
"globalDependencies": [
|
||||
"jquery"
|
||||
]
|
||||
}
|
||||
},
|
||||
"localizedResources": {
|
||||
"PageCommentsWebPartStrings": "lib/webparts/pageComments/loc/{locale}.js",
|
||||
"PropertyControlStrings": "node_modules/@pnp/spfx-property-controls/lib/loc/{locale}.js"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/copy-assets.schema.json",
|
||||
"deployCdnPath": "temp/deploy"
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/deploy-azure-storage.schema.json",
|
||||
"workingDir": "./temp/deploy/",
|
||||
"account": "<!-- STORAGE ACCOUNT NAME -->",
|
||||
"container": "modern-page-comments",
|
||||
"accessKey": "<!-- ACCESS KEY -->"
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
|
||||
"solution": {
|
||||
"name": "Advanced Comments Box",
|
||||
"id": "cfa8dbcf-b32d-4de0-a6ba-af486007c2f2",
|
||||
"version": "1.1.0.2",
|
||||
"includeClientSideAssets": true,
|
||||
"isDomainIsolated": false
|
||||
},
|
||||
"paths": {
|
||||
"zippedPackage": "solution/advanced-comments-box.sppkg"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/core-build/serve.schema.json",
|
||||
"port": 4321,
|
||||
"https": true,
|
||||
"initialPage": "https://localhost:5432/workbench",
|
||||
"api": {
|
||||
"port": 5432,
|
||||
"entryPath": "node_modules/@microsoft/sp-webpart-workbench/lib/api/"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/write-manifests.schema.json",
|
||||
"cdnBasePath": "<!-- PATH TO CDN -->"
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const gulp = require('gulp');
|
||||
const build = require('@microsoft/sp-build-web');
|
||||
build.addSuppression(`Warning - [sass] The local CSS class 'ms-Grid' is not camelCase and will not be type-safe.`);
|
||||
|
||||
build.initialize(gulp);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"name": "modern-page-comments",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"main": "lib/index.js",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "gulp bundle",
|
||||
"clean": "gulp clean",
|
||||
"test": "gulp test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@microsoft/sp-core-library": "1.9.1",
|
||||
"@microsoft/sp-lodash-subset": "1.9.1",
|
||||
"@microsoft/sp-office-ui-fabric-core": "1.9.1",
|
||||
"@microsoft/sp-webpart-base": "1.9.1",
|
||||
"@pnp/sp": "^2.0.0",
|
||||
"@pnp/spfx-property-controls": "1.16.0",
|
||||
"@types/es6-promise": "0.0.33",
|
||||
"@types/jquery": "^2.0.54",
|
||||
"@types/webpack-env": "1.13.1",
|
||||
"jquery": "^2.2.4",
|
||||
"moment": "^2.24.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/sp-build-web": "1.9.1",
|
||||
"@microsoft/sp-tslint-rules": "1.9.1",
|
||||
"@microsoft/sp-module-interfaces": "1.9.1",
|
||||
"@microsoft/sp-webpart-workbench": "1.9.1",
|
||||
"@microsoft/rush-stack-compiler-2.9": "0.7.16",
|
||||
"gulp": "~3.9.1",
|
||||
"@types/chai": "3.4.34",
|
||||
"@types/mocha": "2.2.38",
|
||||
"ajv": "~5.2.2"
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
// A file is required to be in the root of the /src directory by the TypeScript compiler
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json",
|
||||
"id": "7520fa3d-1f05-4d78-bf7f-91627d9b64d3",
|
||||
"alias": "PageCommentsWebPart",
|
||||
"componentType": "WebPart",
|
||||
"version": "*",
|
||||
"manifestVersion": 2,
|
||||
"requiresCustomScript": false,
|
||||
"supportedHosts": ["SharePointWebPart"],
|
||||
|
||||
"preconfiguredEntries": [{
|
||||
"groupId": "5c03119e-3074-46fd-976b-c60198311f70",
|
||||
"group": { "default": "Other" },
|
||||
"title": { "default": "Advanced Comments" },
|
||||
"description": { "default": "Comments with advanced features for modern pages" },
|
||||
"officeFabricIconFontName": "FileComment",
|
||||
"properties": {
|
||||
"datetimeFormat":"DD/MM/YYYY",
|
||||
"enableNavigation": true,
|
||||
"enableReplying": true,
|
||||
"enableEditing": false,
|
||||
"enableUpvoting": true,
|
||||
"enableDeleting": false,
|
||||
"enableAttachments": false,
|
||||
"enableHashtags": false,
|
||||
"enablePinging": false,
|
||||
"enableDocumentPreview": false,
|
||||
"roundProfilePictures": true,
|
||||
"attachmentFileFormats": "audio/*,image/*,video/*,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx",
|
||||
"attachmentFileSize": 2
|
||||
}
|
||||
}]
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
@import '~@microsoft/sp-office-ui-fabric-core/dist/sass/SPFabricCore.scss';
|
||||
|
||||
.pageComments {
|
||||
.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 {
|
||||
@include ms-Grid-row;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.column {
|
||||
@include ms-Grid-col;
|
||||
@include ms-lg10;
|
||||
@include ms-xl8;
|
||||
@include ms-xlPush2;
|
||||
@include ms-lgPush1;
|
||||
}
|
||||
|
||||
.title {
|
||||
@include ms-font-xl;
|
||||
@include ms-fontColor-white;
|
||||
}
|
||||
|
||||
.subTitle {
|
||||
@include ms-font-l;
|
||||
@include ms-fontColor-white;
|
||||
}
|
||||
|
||||
.description {
|
||||
@include ms-font-l;
|
||||
@include ms-fontColor-white;
|
||||
}
|
||||
}
|
||||
.errorMessage {
|
||||
margin: 10px;
|
||||
border: 1px solid red;
|
||||
padding: 10px;
|
||||
background-color: #ead9d9;
|
||||
font-weight: 600;
|
||||
}
|
|
@ -0,0 +1,374 @@
|
|||
import * as React from 'react';
|
||||
import { Version } from '@microsoft/sp-core-library';
|
||||
import {
|
||||
BaseClientSideWebPart,
|
||||
IPropertyPaneConfiguration,
|
||||
PropertyPaneTextField
|
||||
} from '@microsoft/sp-webpart-base';
|
||||
import { SPComponentLoader } from '@microsoft/sp-loader';
|
||||
import { CalloutTriggers } from '@pnp/spfx-property-controls/lib/PropertyFieldHeader';
|
||||
import { PropertyFieldSliderWithCallout } from '@pnp/spfx-property-controls/lib/PropertyFieldSliderWithCallout';
|
||||
import { PropertyFieldToggleWithCallout } from '@pnp/spfx-property-controls/lib/PropertyFieldToggleWithCallout';
|
||||
import { PropertyFieldListPicker, PropertyFieldListPickerOrderBy } from '@pnp/spfx-property-controls/lib/PropertyFieldListPicker';
|
||||
import * as _ from "lodash";
|
||||
import * as moment from 'moment';
|
||||
|
||||
import styles from './PageCommentsWebPart.module.scss';
|
||||
import * as strings from 'PageCommentsWebPartStrings';
|
||||
|
||||
import * as $ from 'jquery';
|
||||
require('textcomplete');
|
||||
import { sp } from '@pnp/sp';
|
||||
import SPHelper from './SPHelper';
|
||||
require('./css/jquery-comments.css');
|
||||
|
||||
export interface IPageCommentsWebPartProps {
|
||||
enableNavigation: boolean;
|
||||
enableReplying: boolean;
|
||||
enableAttachments: boolean;
|
||||
enableEditing: boolean;
|
||||
enableUpvoting: boolean;
|
||||
enableDeleting: boolean;
|
||||
enableDeletingCommentWithReplies: boolean;
|
||||
enableHashtags: boolean;
|
||||
enablePinging: boolean;
|
||||
enableDocumentPreview: boolean;
|
||||
roundProfilePictures: boolean;
|
||||
datetimeFormat: string;
|
||||
attachmentFileFormats: string;
|
||||
attachmentFileSize: number;
|
||||
docLib: string;
|
||||
}
|
||||
|
||||
export default class PageCommentsWebPart extends BaseClientSideWebPart<IPageCommentsWebPartProps> {
|
||||
|
||||
private helper: SPHelper = null;
|
||||
private currentUserInfo: any = null;
|
||||
private siteUsers: any[] = [];
|
||||
private pageurl: string = '';
|
||||
private postAttachmentPath: string = '';
|
||||
private pageFolderExists: boolean = false;
|
||||
|
||||
protected async onInit(): Promise<void> {
|
||||
await super.onInit();
|
||||
sp.setup(this.context);
|
||||
}
|
||||
|
||||
public constructor() {
|
||||
super();
|
||||
SPComponentLoader.loadCss("https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css");
|
||||
}
|
||||
|
||||
public render(): void {
|
||||
if (this.properties.enableAttachments && (this.properties.docLib === null || undefined === this.properties.docLib ||
|
||||
this.properties.docLib.toLocaleUpperCase() === "NO_LIST_SELECTED")) {
|
||||
this.domElement.innerHTML = `
|
||||
<div class="${styles.errorMessage}"><i class="fa fa-times-circle" aria-hidden="true"></i> ${strings.NoAttachmentRepoMsg}</div>
|
||||
`;
|
||||
} else {
|
||||
this.context.statusRenderer.displayLoadingIndicator(this.domElement, strings.LoadingMsg, 0);
|
||||
this.checkAndCreateList();
|
||||
}
|
||||
}
|
||||
|
||||
private async checkAndCreateList() {
|
||||
if (this.properties.enableAttachments) {
|
||||
this.helper = new SPHelper(this.properties.docLib);
|
||||
} else {
|
||||
this.helper = new SPHelper();
|
||||
}
|
||||
await this.helper.checkListExists();
|
||||
this.initializeComments();
|
||||
}
|
||||
|
||||
private initializeComments = async () => {
|
||||
this.context.statusRenderer.clearLoadingIndicator(this.domElement);
|
||||
this.domElement.innerHTML = `
|
||||
<div class="${ styles.pageComments}">
|
||||
<div class="${ styles.container}">
|
||||
<div class="${ styles.row}">
|
||||
<div id="page-comments"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
var self = this;
|
||||
if (this.properties.enableAttachments) {
|
||||
await this.helper.getDocLibInfo();
|
||||
this.postAttachmentPath = await this.helper.getPostAttachmentFilePath(this.pageurl);
|
||||
this.pageFolderExists = await this.helper.checkForPageFolder(this.postAttachmentPath);
|
||||
}
|
||||
this.pageurl = this.context.pageContext.legacyPageContext.serverRequestPath;
|
||||
this.currentUserInfo = await this.helper.getCurrentUserInfo();
|
||||
this.siteUsers = await this.helper.getSiteUsers(self.currentUserInfo.ID);
|
||||
require(['jquery', './js/jquery-comments.min'], (jQuery, comments) => {
|
||||
jQuery('#page-comments').comments({
|
||||
profilePictureURL: self.currentUserInfo.Picture,
|
||||
currentUserId: self.currentUserInfo.ID,
|
||||
maxRepliesVisible: 3,
|
||||
textareaRows: 1,
|
||||
textareaRowsOnFocus: 2,
|
||||
textareaMaxRows: 5,
|
||||
highlightColor: '#b5121b',
|
||||
attachmentFileFormats: self.properties.attachmentFileFormats !== undefined ? self.properties.attachmentFileFormats : 'audio/*,image/*,video/*,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx',
|
||||
attachmentFileSize: self.properties.attachmentFileSize !== undefined ? self.properties.attachmentFileSize : 5,
|
||||
siteURL: self.context.pageContext.legacyPageContext.webServerRelativeUrl,
|
||||
enableNavigation: self.properties.enableNavigation !== undefined ? self.properties.enableNavigation : true,
|
||||
enableReplying: self.properties.enableReplying !== undefined ? self.properties.enableReplying : true,
|
||||
enableEditing: self.properties.enableEditing !== undefined ? self.properties.enableEditing : false,
|
||||
enableUpvoting: self.properties.enableUpvoting !== undefined ? self.properties.enableUpvoting : true,
|
||||
enableDeleting: self.properties.enableDeleting !== undefined ? self.properties.enableDeleting : false,
|
||||
enableAttachments: self.properties.enableAttachments !== undefined ? self.properties.enableAttachments : false,
|
||||
enableHashtags: self.properties.enableHashtags !== undefined ? self.properties.enableHashtags : false,
|
||||
enablePinging: self.properties.enablePinging !== undefined ? self.properties.enablePinging : false,
|
||||
enableDocumentPreview: self.properties.enableDocumentPreview !== undefined ? self.properties.enableDocumentPreview : false,
|
||||
roundProfilePictures: self.properties.roundProfilePictures !== undefined ? self.properties.roundProfilePictures : true,
|
||||
timeFormatter: (time) => {
|
||||
try {
|
||||
if (self.properties.datetimeFormat) {
|
||||
return moment(time).format(self.properties.datetimeFormat);
|
||||
} else return moment(time).format(self.properties.datetimeFormat);
|
||||
} catch (err) {
|
||||
return moment(time).format("DD/MM/YYYY hh:mm:ss A");
|
||||
}
|
||||
},
|
||||
getComments: async (success, error) => {
|
||||
let commentsArray = await self.helper.getPostComments(self.pageurl, self.currentUserInfo);
|
||||
if (commentsArray.length > 0) {
|
||||
var fil = _.filter(commentsArray, (o) => { return moment(o.created).format("DD/MM/YYYY") === moment().format("DD/MM/YYYY"); });
|
||||
fil.map((comment) => {
|
||||
_.set(comment, 'is_new', true);
|
||||
});
|
||||
fil = _.filter(commentsArray, (o) => { return o.userid == self.currentUserInfo.ID; });
|
||||
fil.map((comment) => {
|
||||
_.set(comment, 'created_by_current_user', true);
|
||||
});
|
||||
}
|
||||
success(commentsArray);
|
||||
},
|
||||
postComment: async (commentJson, success, error) => {
|
||||
commentJson.fullname = self.currentUserInfo.DisplayName;
|
||||
commentJson.userid = self.currentUserInfo.ID;
|
||||
commentJson = self.saveComment(commentJson);
|
||||
await self.helper.postComment(self.pageurl, commentJson, self.currentUserInfo);
|
||||
if (moment(commentJson.created).format("DD/MM/YYYY") === moment().format("DD/MM/YYYY")) _.set(commentJson, 'is_new', true);
|
||||
_.set(commentJson, 'created_by_current_user', true);
|
||||
success(commentJson);
|
||||
},
|
||||
searchUsers: async (term, success, error) => {
|
||||
let res = [];
|
||||
if (self.siteUsers.length <= 0) self.siteUsers = await self.helper.getSiteUsers(self.currentUserInfo.ID);
|
||||
res = _.chain(self.siteUsers).filter((o) => { return o.fullname.toLowerCase().indexOf(term) >= 0 || o.email.toLowerCase().indexOf(term) >= 0; }).take(10).value();
|
||||
success(res);
|
||||
},
|
||||
upvoteComment: async (commentJSON, success, error) => {
|
||||
await self.helper.voteComment(self.pageurl, commentJSON, self.currentUserInfo);
|
||||
success(commentJSON);
|
||||
},
|
||||
deleteComment: async (commentJSON, success, error) => {
|
||||
await self.helper.deleteComment(self.pageurl, commentJSON);
|
||||
success();
|
||||
},
|
||||
putComment: async (commentJSON, success, error) => {
|
||||
commentJSON = self.saveComment(commentJSON);
|
||||
await self.helper.editComments(self.pageurl, commentJSON);
|
||||
success(commentJSON);
|
||||
},
|
||||
uploadAttachments: async (commentArray, success, error) => {
|
||||
let res = await self.helper.postAttachments(commentArray, self.pageFolderExists, self.postAttachmentPath);
|
||||
_.merge(res[0], { userid: self.currentUserInfo.ID, fullname: self.currentUserInfo.DisplayName });
|
||||
await self.helper.postComment(self.pageurl, res[0], self.currentUserInfo);
|
||||
if (moment(res[0].created).format("DD/MM/YYYY") === moment().format("DD/MM/YYYY")) _.set(res[0], 'is_new', true);
|
||||
_.set(res[0], 'created_by_current_user', true);
|
||||
success(res);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private saveComment = (data) => {
|
||||
// Convert pings to human readable format
|
||||
$(Object.keys(data.pings)).each((index, userId) => {
|
||||
var fullname = data.pings[`${userId}`];
|
||||
var pingText = '@' + fullname;
|
||||
data.content = data.content.replace(new RegExp('@' + userId, 'g'), pingText);
|
||||
});
|
||||
return data;
|
||||
}
|
||||
|
||||
private checkForDocumentLibrary = (value: string): string => {
|
||||
if (value === null || value.trim().length === 0 || value.toLocaleUpperCase() === "NO_LIST_SELECTED") {
|
||||
return strings.AttachmentRepoPropValMsg;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
protected get disableReactivePropertyChanges(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected get dataVersion(): Version {
|
||||
return Version.parse('1.0');
|
||||
}
|
||||
|
||||
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
|
||||
return {
|
||||
pages: [
|
||||
{
|
||||
header: {
|
||||
description: strings.PropertyPaneDescription
|
||||
},
|
||||
groups: [
|
||||
{
|
||||
groupName: strings.BasicGroupName,
|
||||
groupFields: [
|
||||
PropertyPaneTextField('datetimeFormat', {
|
||||
label: strings.DateTimeFormatLabel,
|
||||
description: strings.DateTimeFormatDescription,
|
||||
multiline: false,
|
||||
resizable: false,
|
||||
value: this.properties.datetimeFormat
|
||||
}),
|
||||
PropertyFieldToggleWithCallout('roundProfilePictures', {
|
||||
calloutTrigger: CalloutTriggers.Hover,
|
||||
key: 'roundProfilePicturesFieldId',
|
||||
label: strings.RoundProfilePicLabel,
|
||||
calloutContent: React.createElement('p', {}, strings.RoundProfilePicDescription),
|
||||
onText: 'Enable',
|
||||
offText: 'Disable',
|
||||
checked: this.properties.roundProfilePictures !== undefined ? this.properties.roundProfilePictures : true
|
||||
}),
|
||||
PropertyFieldToggleWithCallout('enableNavigation', {
|
||||
calloutTrigger: CalloutTriggers.Hover,
|
||||
key: 'enableNavigationFieldId',
|
||||
label: strings.NavigationLabel,
|
||||
calloutContent: React.createElement('p', {}, strings.NavigationDescription),
|
||||
onText: 'Enable',
|
||||
offText: 'Disable',
|
||||
checked: this.properties.enableNavigation !== undefined ? this.properties.enableNavigation : true
|
||||
}),
|
||||
PropertyFieldToggleWithCallout('enableAttachments', {
|
||||
calloutTrigger: CalloutTriggers.Hover,
|
||||
key: 'enableAttachmentsFieldId',
|
||||
label: strings.AttachmentLabel,
|
||||
calloutContent: React.createElement('p', {}, strings.AttachmentDescription),
|
||||
onText: 'Enable',
|
||||
offText: 'Disable',
|
||||
checked: this.properties.enableAttachments !== undefined ? this.properties.enableAttachments : false
|
||||
}),
|
||||
PropertyFieldListPicker('docLib', {
|
||||
label: strings.AttachmentRepoLabel,
|
||||
selectedList: this.properties.docLib,
|
||||
includeHidden: false,
|
||||
orderBy: PropertyFieldListPickerOrderBy.Title,
|
||||
onPropertyChange: this.onPropertyPaneFieldChanged.bind(this),
|
||||
properties: this.properties,
|
||||
context: this.context,
|
||||
onGetErrorMessage: this.checkForDocumentLibrary.bind(this),
|
||||
deferredValidationTime: 0,
|
||||
key: 'docLibFieldId',
|
||||
baseTemplate: 101,
|
||||
disabled: !this.properties.enableAttachments
|
||||
}),
|
||||
PropertyPaneTextField('attachmentFileFormats', {
|
||||
label: strings.AttachmentFileFormatLabel,
|
||||
description: strings.AttachmentFileFormatDescription,
|
||||
multiline: false,
|
||||
resizable: false,
|
||||
value: this.properties.attachmentFileFormats,
|
||||
disabled: !this.properties.enableAttachments
|
||||
}),
|
||||
PropertyFieldSliderWithCallout('attachmentFileSize', {
|
||||
calloutContent: React.createElement('div', {}, strings.AttachmentFileSizeDescription),
|
||||
calloutTrigger: CalloutTriggers.Hover,
|
||||
calloutWidth: 200,
|
||||
key: 'attachmentFileSizeFieldId',
|
||||
label: strings.AttachmentFileSizeLabel,
|
||||
max: 10,
|
||||
min: 1,
|
||||
step: 1,
|
||||
showValue: true,
|
||||
value: this.properties.attachmentFileSize,
|
||||
disabled: !this.properties.enableAttachments
|
||||
}),
|
||||
PropertyFieldToggleWithCallout('enablePinging', {
|
||||
calloutTrigger: CalloutTriggers.Hover,
|
||||
key: 'enablePingingFieldId',
|
||||
label: strings.PingLabel,
|
||||
calloutContent: React.createElement('p', {}, strings.PingDescription),
|
||||
onText: 'Enable',
|
||||
offText: 'Disable',
|
||||
checked: this.properties.enablePinging !== undefined ? this.properties.enablePinging : false
|
||||
}),
|
||||
PropertyFieldToggleWithCallout('enableEditing', {
|
||||
calloutTrigger: CalloutTriggers.Hover,
|
||||
key: 'enableEditingFieldId',
|
||||
label: strings.EditingLabel,
|
||||
calloutContent: React.createElement('p', {}, strings.EditingDescription),
|
||||
onText: 'Enable',
|
||||
offText: 'Disable',
|
||||
checked: this.properties.enableEditing !== undefined ? this.properties.enableEditing : false
|
||||
}),
|
||||
PropertyFieldToggleWithCallout('enableDeleting', {
|
||||
calloutTrigger: CalloutTriggers.Hover,
|
||||
key: 'enableDeletingFieldId',
|
||||
label: strings.DeleteLabel,
|
||||
calloutContent: React.createElement('p', {}, strings.DeleteDescription),
|
||||
onText: 'Enable',
|
||||
offText: 'Disable',
|
||||
checked: this.properties.enableDeleting !== undefined ? this.properties.enableDeleting : false,
|
||||
disabled: !this.properties.enableEditing
|
||||
}),
|
||||
// PropertyFieldToggleWithCallout('enableDeletingCommentWithReplies', {
|
||||
// calloutTrigger: CalloutTriggers.Hover,
|
||||
// key: 'enableDeletingCommentWithRepliesFieldId',
|
||||
// label: strings.DeleteRepliesLabel,
|
||||
// calloutContent: React.createElement('p', {}, strings.DeleteRepliesDescription),
|
||||
// onText: 'Enable',
|
||||
// offText: 'Disable',
|
||||
// checked: this.properties.enableDeletingCommentWithReplies,
|
||||
// disabled: !this.properties.enableEditing
|
||||
// }),
|
||||
PropertyFieldToggleWithCallout('enableUpvoting', {
|
||||
calloutTrigger: CalloutTriggers.Hover,
|
||||
key: 'enableUpvotingFieldId',
|
||||
label: strings.UpVotingLabel,
|
||||
calloutContent: React.createElement('p', {}, strings.UpVotingDescription),
|
||||
onText: 'Enable',
|
||||
offText: 'Disable',
|
||||
checked: this.properties.enableUpvoting !== undefined ? this.properties.enableUpvoting : true
|
||||
}),
|
||||
PropertyFieldToggleWithCallout('enableReplying', {
|
||||
calloutTrigger: CalloutTriggers.Hover,
|
||||
key: 'enableReplyingFieldId',
|
||||
label: strings.ReplyLabel,
|
||||
calloutContent: React.createElement('p', {}, strings.ReplyDescription),
|
||||
onText: 'Enable',
|
||||
offText: 'Disable',
|
||||
checked: this.properties.enableReplying !== undefined ? this.properties.enableReplying : true
|
||||
}),
|
||||
PropertyFieldToggleWithCallout('enableHashtags', {
|
||||
calloutTrigger: CalloutTriggers.Hover,
|
||||
key: 'enableHashtagsFieldId',
|
||||
label: strings.HashtagsLabel,
|
||||
calloutContent: React.createElement('p', {}, strings.HashtagsDescription),
|
||||
onText: 'Enable',
|
||||
offText: 'Disable',
|
||||
checked: this.properties.enableHashtags !== undefined ? this.properties.enableHashtags : false
|
||||
}),
|
||||
PropertyFieldToggleWithCallout('enableDocumentPreview', {
|
||||
calloutTrigger: CalloutTriggers.Hover,
|
||||
key: 'enableDocumentPreviewFieldId',
|
||||
label: strings.DocumentPreviewLabel,
|
||||
calloutContent: React.createElement('p', {}, strings.DocumentPreviewDescription),
|
||||
onText: 'Enable',
|
||||
offText: 'Disable',
|
||||
checked: this.properties.enableDocumentPreview !== undefined ? this.properties.enableDocumentPreview : false
|
||||
}),
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,281 @@
|
|||
import { sp } from "@pnp/sp";
|
||||
import "@pnp/sp/webs";
|
||||
import "@pnp/sp/lists/web";
|
||||
import "@pnp/sp/folders/web";
|
||||
import "@pnp/sp/files/folder";
|
||||
import "@pnp/sp/items/list";
|
||||
import "@pnp/sp/fields/list";
|
||||
import "@pnp/sp/views/list";
|
||||
import "@pnp/sp/site-users/web";
|
||||
import { IList } from "@pnp/sp/lists";
|
||||
import * as _ from "lodash";
|
||||
|
||||
export default class SPHelper {
|
||||
private lst_pageComments: string = '';
|
||||
private lst_pageDocuments: string = '';
|
||||
private lst_docListName: string = '';
|
||||
private _list: IList = null;
|
||||
private _doclist: IList = null;
|
||||
private cqPostDocs: string = `<View>
|
||||
<Query>
|
||||
<Where>
|
||||
<And>
|
||||
<Eq>
|
||||
<FieldRef Name='FSObjType' />
|
||||
<Value Type='Text'>1</Value>
|
||||
</Eq>
|
||||
<Eq>
|
||||
<FieldRef Name='FileRef' />
|
||||
<Value Type='Text'>{{FilePath}}</Value>
|
||||
</Eq>
|
||||
</And>
|
||||
</Where>
|
||||
<ViewFields><FieldRef Name="ID" /></ViewFields>
|
||||
</Query>
|
||||
</View>`;
|
||||
|
||||
public constructor(lstDocLib?: string) {
|
||||
this.lst_pageComments = "Page Comments";
|
||||
this._list = sp.web.lists.getByTitle(this.lst_pageComments);
|
||||
if (lstDocLib) {
|
||||
this.lst_pageDocuments = lstDocLib;
|
||||
}
|
||||
}
|
||||
|
||||
public getDocLibInfo = async () => {
|
||||
this._doclist = sp.web.lists.getById(this.lst_pageDocuments);
|
||||
let listInfo: any = await this._doclist.select('Title').get();
|
||||
this.lst_docListName = listInfo.Title;
|
||||
}
|
||||
|
||||
public queryList = async (query, $list: IList) => {
|
||||
return await $list.getItemsByCAMLQuery(query);
|
||||
}
|
||||
|
||||
public getCurrentUserInfo = async () => {
|
||||
let currentUserInfo = await sp.web.currentUser.get();
|
||||
return ({
|
||||
ID: currentUserInfo.Id,
|
||||
Email: currentUserInfo.Email,
|
||||
LoginName: currentUserInfo.LoginName,
|
||||
DisplayName: currentUserInfo.Title,
|
||||
Picture: '/_layouts/15/userphoto.aspx?size=S&username=' + currentUserInfo.UserPrincipalName,
|
||||
});
|
||||
}
|
||||
|
||||
public getSiteUsers = async (currentUserId: number) => {
|
||||
let resusers = await sp.web.siteUsers.filter('IsHiddenInUI eq false and PrincipalType eq 1').get();
|
||||
_.remove(resusers, (o) => { return o.Id == currentUserId || o.Email == ""; });
|
||||
let userResults = [];
|
||||
resusers.map((user) => {
|
||||
userResults.push({
|
||||
id: user.Id,
|
||||
fullname: user.Title,
|
||||
email: user.Email,
|
||||
profile_picture_url: '/_layouts/15/userphoto.aspx?size=S&username=' + user.UserPrincipalName
|
||||
});
|
||||
});
|
||||
return userResults;
|
||||
}
|
||||
|
||||
public getPostAttachmentFilePath = async (pageUrl) => {
|
||||
let pageName = pageUrl.split('/')[pageUrl.split('/').length - 1].split('.').slice(0, -1).join('.');
|
||||
let res = await sp.web.select('ServerRelativeUrl').get();
|
||||
let doclistName = (this.lst_docListName.toLowerCase() === 'documents') ? "Shared Documents" : this.lst_docListName;
|
||||
return res.ServerRelativeUrl + "/" + doclistName + "/" + pageName;
|
||||
}
|
||||
|
||||
public checkForPageFolder = async (postAttachmentPath) => {
|
||||
let xml = this.cqPostDocs.replace('{{FilePath}}', postAttachmentPath);
|
||||
let q = {
|
||||
ViewXml: xml
|
||||
};
|
||||
let res = await this.queryList(q, this._doclist);
|
||||
if (res.length > 0) return true; else return false;
|
||||
}
|
||||
|
||||
public getPostComments = async (pageurl, currentUserInfo) => {
|
||||
let pagecomments = await this._list.items.select('Comments', 'Likes', 'FieldValuesAsText/Comments', 'FieldValuesAsText/Likes')
|
||||
.filter(`PageURL eq '${pageurl}'`).expand('FieldValuesAsText').get();
|
||||
if (pagecomments.length > 0) {
|
||||
var tempComments = pagecomments[0].FieldValuesAsText.Comments;
|
||||
var tempLikes = pagecomments[0].FieldValuesAsText.Likes;
|
||||
if (tempLikes != undefined && tempLikes != null && tempLikes !== "") tempLikes = JSON.parse(tempLikes);
|
||||
else tempLikes = [];
|
||||
if (tempComments != undefined && tempComments != null && tempComments !== "") {
|
||||
var jsonComments = JSON.parse(tempComments);
|
||||
if (tempLikes.length > 0) {
|
||||
tempLikes.map((liked) => {
|
||||
var fil = _.find(jsonComments, (o) => { return o.id == liked.commentID; });
|
||||
if (fil !== undefined && fil !== null) {
|
||||
fil.upvote_count = liked.userVote.length;
|
||||
var cufil = _.find(liked.userVote, (o) => { return o.userid == currentUserInfo.ID; });
|
||||
if (cufil !== undefined && cufil !== null) fil.user_has_upvoted = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
return jsonComments;
|
||||
} else return [];
|
||||
} else return [];
|
||||
}
|
||||
|
||||
public getComment = async (pageurl) => {
|
||||
let pagecomments = await this._list.items.select('Comments', 'FieldValuesAsText/Comments')
|
||||
.filter(`PageURL eq '${pageurl}'`).expand('FieldValuesAsText').get();
|
||||
if (pagecomments.length > 0) return pagecomments[0].FieldValuesAsText.Comments;
|
||||
else return null;
|
||||
}
|
||||
|
||||
public addComment = async (pageUrl, comments) => {
|
||||
let pageName = pageUrl.split('/')[pageUrl.split('/').length - 1];
|
||||
let commentsToAdd = await sp.web.lists.getByTitle(this.lst_pageComments).items.add({
|
||||
Title: pageName,
|
||||
PageURL: pageUrl,
|
||||
Comments: JSON.stringify(comments)
|
||||
});
|
||||
return commentsToAdd;
|
||||
}
|
||||
|
||||
public updateComment = async (pageurl, comments) => {
|
||||
let pageComment = await this._list.items.select('ID', 'PageURL').filter(`PageURL eq '${pageurl}'`).get();
|
||||
if (comments.length > 0) {
|
||||
if (pageComment.length > 0) {
|
||||
let pageCommentsToUpdate = await this._list.items.getById(pageComment[0].ID).update({
|
||||
Comments: JSON.stringify(comments)
|
||||
});
|
||||
return pageCommentsToUpdate;
|
||||
}
|
||||
} else {
|
||||
return await this._list.items.getById(pageComment[0].ID).delete();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public postComment = async (pageurl, commentJson, currentUserInfo) => {
|
||||
commentJson.created_by_current_user = false;
|
||||
let comments = await this.getPostComments(pageurl, currentUserInfo);
|
||||
if (comments.length > 0) {
|
||||
comments.push(commentJson);
|
||||
let updateComments = await this.updateComment(pageurl, comments);
|
||||
return updateComments;
|
||||
} else {
|
||||
comments.push(commentJson);
|
||||
let addComments = await this.addComment(pageurl, comments);
|
||||
return addComments;
|
||||
}
|
||||
}
|
||||
|
||||
public addVoteForComment = async (pageurl, commentJson, currentUserInfo) => {
|
||||
var tempLikes = [];
|
||||
tempLikes.push({
|
||||
commentID: commentJson.id,
|
||||
userVote: [{ userid: currentUserInfo.ID, name: currentUserInfo.DisplayName }]
|
||||
});
|
||||
let pageComment = await this._list.items.select('ID').filter(`PageURL eq '${pageurl}'`).get();
|
||||
if (pageComment.length > 0) {
|
||||
return await this._list.items.getById(pageComment[0].ID).update({ Likes: JSON.stringify(tempLikes) });
|
||||
}
|
||||
}
|
||||
|
||||
public updateVoteForComment = async (pageurl, jsonLikes) => {
|
||||
let pageComment = await this._list.items.select('ID').filter(`PageURL eq '${pageurl}'`).get();
|
||||
if (pageComment.length > 0) {
|
||||
return await this._list.items.getById(pageComment[0].ID).update({ Likes: JSON.stringify(jsonLikes) });
|
||||
}
|
||||
}
|
||||
|
||||
public voteComment = async (pageurl, commentJson, currentUserInfo) => {
|
||||
let res = await this._list.items.select('Likes', 'FieldValuesAsText/Likes').filter(`PageURL eq '${pageurl}'`).expand('FieldValuesAsText').get();
|
||||
if (res.length > 0) {
|
||||
var tempLikes = res[0].FieldValuesAsText.Likes;
|
||||
if (tempLikes != undefined && tempLikes != null && tempLikes !== "") {
|
||||
// Likes already exits so update the item
|
||||
var jsonLikes = JSON.parse(tempLikes);
|
||||
var userAlreadyVoted = _.find(jsonLikes, (o) => { return o.commentID == commentJson.id && _.find(o.userVote, (oo) => { return oo.userid == currentUserInfo.ID; }); });
|
||||
var userPresent = (userAlreadyVoted === undefined || userAlreadyVoted == null) ? false : true;
|
||||
var fil = _.find(jsonLikes, (o) => { return o.commentID == commentJson.id; });
|
||||
if (fil !== undefined && fil !== null) {
|
||||
// Found likes for the comment id
|
||||
if (commentJson.user_has_upvoted) {
|
||||
if (!userPresent) fil.userVote = _.concat(fil.userVote, { userid: currentUserInfo.ID, name: currentUserInfo.DisplayName });
|
||||
} else {
|
||||
if (userPresent) {
|
||||
if (fil !== undefined && fil !== null) _.remove(fil.userVote, (o) => { return o['userid'] == currentUserInfo.ID; });
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No likes found for the comment id
|
||||
jsonLikes.push({ commentID: commentJson.id, userVote: [{ userid: currentUserInfo.ID, name: currentUserInfo.DisplayName }] });
|
||||
}
|
||||
return await this.updateVoteForComment(pageurl, jsonLikes);
|
||||
} else {
|
||||
// Likes doesn't exists so add new
|
||||
if (commentJson.user_has_upvoted) return await this.addVoteForComment(pageurl, commentJson, currentUserInfo);
|
||||
}
|
||||
} else {
|
||||
return commentJson;
|
||||
}
|
||||
}
|
||||
|
||||
public deleteComment = async (pageurl, commentJson) => {
|
||||
let comments = await this.getComment(pageurl);
|
||||
if (comments !== undefined && comments !== null) {
|
||||
var jsonComments = JSON.parse(comments);
|
||||
_.remove(jsonComments, (o) => { return o['id'] == commentJson.id; });
|
||||
return await this.updateComment(pageurl, jsonComments);
|
||||
}
|
||||
}
|
||||
|
||||
public editComments = async (pageurl, commentJson) => {
|
||||
let comment = await this.getComment(pageurl);
|
||||
if (comment !== undefined && comment !== null) {
|
||||
var jsonComments = JSON.parse(comment);
|
||||
var match = _.find(jsonComments, (o) => { return o.id == commentJson.id; });
|
||||
if (match) _.merge(match, { pings: commentJson.pings, content: commentJson.content, modified: commentJson.modified });
|
||||
return await this.updateComment(pageurl, jsonComments);
|
||||
}
|
||||
}
|
||||
|
||||
public createFolder = async (folderPath) => {
|
||||
return await sp.web.folders.add(folderPath);
|
||||
}
|
||||
|
||||
public uploadFileToFolder = async (folderpath, fileinfo) => {
|
||||
return await sp.web.getFolderByServerRelativeUrl(folderpath).files.add(fileinfo.name, fileinfo.content, true);
|
||||
}
|
||||
|
||||
public postAttachments = async (commentArray: any[], pageFolderExists, postAttachmentPath): Promise<any> => {
|
||||
var self = this;
|
||||
return new Promise(async (resolve, reject) => {
|
||||
if (!pageFolderExists) await this.createFolder(postAttachmentPath);
|
||||
var reader = new FileReader();
|
||||
reader.onload = async () => {
|
||||
var contentBuffer = reader.result;
|
||||
let uploadedFile = await self.uploadFileToFolder(postAttachmentPath, { name: commentArray[0].file.name, content: contentBuffer });
|
||||
_.set(commentArray[0], 'file_id', uploadedFile.data.UniqueId);
|
||||
_.set(commentArray[0], 'file_url', postAttachmentPath + "/" + commentArray[0].file.name);
|
||||
resolve(commentArray);
|
||||
};
|
||||
await reader.readAsArrayBuffer(commentArray[0].file);
|
||||
});
|
||||
}
|
||||
|
||||
public checkListExists = async (): Promise<boolean> => {
|
||||
return new Promise<boolean>(async (res, rej) => {
|
||||
sp.web.lists.getByTitle(this.lst_pageComments).get().then((listExists) => {
|
||||
res(true);
|
||||
}).catch(async err => {
|
||||
let listExists = await (await sp.web.lists.ensure(this.lst_pageComments)).list;
|
||||
await listExists.fields.addText('PageURL', 255, { Required: true, Description: '' });
|
||||
await listExists.fields.addMultilineText('Comments', 6, false, false, false, false, { Required: true, Description: '' });
|
||||
await listExists.fields.addMultilineText('Likes', 6, false, false, false, false, { Required: false, Description: '' });
|
||||
let allItemsView = await listExists.views.getByTitle('All Items');
|
||||
await allItemsView.fields.add('PageURL');
|
||||
await allItemsView.fields.add('Comments');
|
||||
await allItemsView.fields.add('Likes');
|
||||
res(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,789 @@
|
|||
/*jquery-comments.js 1.4.0
|
||||
|
||||
(c) 2017 Joona Tykkyläinen, Viima Solutions Oy
|
||||
jquery-comments may be freely distributed under the MIT license.
|
||||
For all details and documentation:
|
||||
http://viima.github.io/jquery-comments/*/
|
||||
|
||||
.jquery-comments * {
|
||||
box-sizing: border-box;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.jquery-comments a[href] {
|
||||
color: #2793e6;
|
||||
text-decoration: none;
|
||||
font-size: 13px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.jquery-comments a[href]:hover {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
.jquery-comments a[href]:visited {
|
||||
text-decoration: none;
|
||||
color: #2793e6;
|
||||
}
|
||||
|
||||
.jquery-comments .textarea, .jquery-comments input, .jquery-comments button {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
-ms-appearance: none;
|
||||
appearance: none;
|
||||
|
||||
vertical-align: top;
|
||||
border-radius: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
background: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.jquery-comments button {
|
||||
vertical-align: inherit;
|
||||
}
|
||||
|
||||
.jquery-comments .tag {
|
||||
color: inherit;
|
||||
font-size: 0.9em;
|
||||
line-height: 1.2em;
|
||||
background: #ddd;
|
||||
border: 1px solid #ccc;
|
||||
padding: 0.1em 0.3em;
|
||||
cursor: pointer;
|
||||
font-weight: normal;
|
||||
border-radius: 1em;
|
||||
transition: all 0.2s linear;
|
||||
}
|
||||
|
||||
.jquery-comments .tag:hover {
|
||||
text-decoration: none;
|
||||
background-color: #d8edf8;
|
||||
border-color: #2793e6;
|
||||
}
|
||||
|
||||
.jquery-comments [contentEditable=true]:empty:not(:focus):before{
|
||||
content:attr(data-placeholder);
|
||||
color: #CCC;
|
||||
position: inherit;
|
||||
}
|
||||
|
||||
.jquery-comments i.fa {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.jquery-comments i.fa.image:before {
|
||||
content: "";
|
||||
}
|
||||
|
||||
.jquery-comments .spinner {
|
||||
font-size: 2em;
|
||||
text-align: center;
|
||||
padding: 0.5em;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.jquery-comments ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.jquery-comments .profile-picture {
|
||||
float: left;
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
max-width: 50px;
|
||||
max-height: 50px;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
}
|
||||
|
||||
.jquery-comments i.profile-picture {
|
||||
font-size: 3.4em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.jquery-comments .profile-picture.round {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.jquery-comments .commenting-field.main{
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
|
||||
.jquery-comments .commenting-field.main .profile-picture {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.jquery-comments .textarea-wrapper {
|
||||
overflow: hidden;
|
||||
padding-left: 15px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.jquery-comments .textarea-wrapper:before {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
border: 5px solid #D5D5D5;
|
||||
left: 5px;
|
||||
top: 0;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
box-sizing: border-box;
|
||||
border-bottom-color: rgba(0, 0, 0, 0);
|
||||
border-left-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.jquery-comments .textarea-wrapper:after {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
border: 7px solid #FFF;
|
||||
left: 7px;
|
||||
top: 1px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
box-sizing: border-box;
|
||||
border-bottom-color: rgba(0, 0, 0, 0);
|
||||
border-left-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.jquery-comments .textarea-wrapper .inline-button {
|
||||
cursor: pointer;
|
||||
right: 0;
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
border: .5em solid rgba(0,0,0,0);
|
||||
box-sizing: content-box;
|
||||
font-size: inherit;
|
||||
overflow: hidden;
|
||||
opacity: 0.5;
|
||||
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.jquery-comments .textarea-wrapper .inline-button:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.jquery-comments:not(.mobile) .commenting-field-scrollable .textarea-wrapper .inline-button {
|
||||
margin-right: 15px; /* Because of scrollbar */
|
||||
}
|
||||
|
||||
.jquery-comments .textarea-wrapper .upload.inline-button i {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
.jquery-comments .textarea-wrapper .upload input {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
min-width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.jquery-comments .textarea-wrapper .close {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
}
|
||||
|
||||
.jquery-comments .textarea-wrapper .close span {
|
||||
background: #999;
|
||||
width: 25%;
|
||||
left: 37.5%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
-ms-transform: rotate(45deg);
|
||||
-webkit-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.jquery-comments .textarea-wrapper .close .right {
|
||||
-ms-transform: rotate(-45deg);
|
||||
-webkit-transform: rotate(-45deg);
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.jquery-comments .textarea-wrapper .textarea {
|
||||
margin: 0;
|
||||
outline: 0;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
cursor: text;
|
||||
|
||||
border: 1px solid #CCC;;
|
||||
background: #FFF;
|
||||
font-size: 1em;
|
||||
line-height: 1.45em;
|
||||
padding: .25em .8em;
|
||||
padding-right: 2em;
|
||||
}
|
||||
|
||||
.jquery-comments:not(.mobile) .commenting-field-scrollable .textarea-wrapper .textarea {
|
||||
padding-right: calc(2em + 15px); /* Because of scrollbar */
|
||||
}
|
||||
|
||||
.jquery-comments .textarea-wrapper .control-row > span {
|
||||
float: right;
|
||||
|
||||
color: #FFF;
|
||||
padding: 0 1em;
|
||||
font-size: 1em;
|
||||
line-height: 1.6em;
|
||||
margin-top: .4em;
|
||||
border: 1px solid rgba(0, 0, 0, 0);
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
.jquery-comments .textarea-wrapper .control-row > span:not(:first-child) {
|
||||
margin-right: .5em;
|
||||
}
|
||||
|
||||
.jquery-comments .textarea-wrapper .control-row > span.enabled {
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.jquery-comments .textarea-wrapper .control-row > span:not(.enabled) {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.jquery-comments .textarea-wrapper .control-row > span.enabled:hover {
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
.jquery-comments .textarea-wrapper .control-row > span.upload {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background-color: #999;
|
||||
}
|
||||
|
||||
.jquery-comments ul.navigation {
|
||||
clear: both;
|
||||
|
||||
color: #CCC;
|
||||
border-bottom: 2px solid #CCC;
|
||||
line-height: 2em;
|
||||
font-size: 1em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.jquery-comments ul.navigation .navigation-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.jquery-comments ul.navigation li {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
padding: 0 1em;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.jquery-comments ul.navigation li.active,
|
||||
.jquery-comments ul.navigation li:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.jquery-comments ul.navigation li.active:after {
|
||||
content: " ";
|
||||
display: block;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
background: #000;
|
||||
position: absolute;
|
||||
bottom: -2px;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.jquery-comments ul.navigation li[data-sort-key="attachments"] {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.jquery-comments ul.navigation li[data-sort-key="attachments"] i {
|
||||
margin-right: 0.25em;
|
||||
}
|
||||
|
||||
.jquery-comments ul.navigation .navigation-wrapper.responsive {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
.jquery-comments ul.navigation .navigation-wrapper {
|
||||
display: none;
|
||||
}
|
||||
.jquery-comments ul.navigation .navigation-wrapper.responsive {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
.jquery-comments.responsive ul.navigation .navigation-wrapper {
|
||||
display: none;
|
||||
}
|
||||
.jquery-comments.responsive ul.navigation .navigation-wrapper.responsive {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.jquery-comments ul.navigation .navigation-wrapper.responsive li.title {
|
||||
padding: 0 1.5em;
|
||||
}
|
||||
|
||||
.jquery-comments ul.navigation .navigation-wrapper.responsive li.title header:after {
|
||||
display: inline-block;
|
||||
content: "";
|
||||
border-left: 0.3em solid rgba(0, 0, 0, 0) !important;
|
||||
border-right: 0.3em solid rgba(0, 0, 0, 0) !important;
|
||||
border-top: 0.4em solid #CCC;
|
||||
margin-left: 0.5em;
|
||||
position: relative;
|
||||
top: -0.1em;
|
||||
}
|
||||
|
||||
.jquery-comments ul.navigation .navigation-wrapper.responsive li.title.active header:after,
|
||||
.jquery-comments ul.navigation .navigation-wrapper.responsive li.title:hover header:after {
|
||||
border-top-color: #000;
|
||||
}
|
||||
|
||||
.jquery-comments ul.dropdown {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background: #FFF;
|
||||
z-index: 99;
|
||||
line-height: 1.2em;
|
||||
|
||||
border: 1px solid #CCC;
|
||||
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
|
||||
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
|
||||
-moz-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
|
||||
-ms-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
|
||||
}
|
||||
|
||||
.jquery-comments ul.dropdown.autocomplete {
|
||||
margin-top: 0.25em;
|
||||
}
|
||||
|
||||
.jquery-comments ul.dropdown li {
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
clear: both;
|
||||
padding: 0.6em;
|
||||
font-weight: normal;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.jquery-comments ul.dropdown li.active {
|
||||
background: #EEE;
|
||||
}
|
||||
|
||||
.jquery-comments ul.dropdown li a {
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.jquery-comments ul.dropdown li .profile-picture {
|
||||
float: left;
|
||||
width: 2.4em;
|
||||
height: 2.4em;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
.jquery-comments ul.dropdown li .details {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.jquery-comments ul.dropdown li .name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.jquery-comments ul.dropdown li .details.no-email {
|
||||
line-height: 2.4em;
|
||||
}
|
||||
|
||||
.jquery-comments ul.dropdown li .email {
|
||||
color: #999;
|
||||
font-size: 0.95em;
|
||||
margin-top: 0.1em;
|
||||
}
|
||||
|
||||
.jquery-comments ul.navigation .navigation-wrapper.responsive ul.dropdown {
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.jquery-comments ul.navigation .navigation-wrapper.responsive ul.dropdown li {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.jquery-comments ul.navigation .navigation-wrapper.responsive ul.dropdown li.active {
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
.jquery-comments ul.navigation .navigation-wrapper.responsive ul.dropdown li:hover:not(.active) {
|
||||
background: #F5F5F5;
|
||||
}
|
||||
|
||||
.jquery-comments ul.navigation .navigation-wrapper.responsive ul.dropdown li:after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jquery-comments .no-data {
|
||||
display: none;
|
||||
margin: 1em;
|
||||
text-align: center;
|
||||
font-size: 1.5em;
|
||||
color: #CCC;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main:empty ~ .no-comments {
|
||||
display: inherit;
|
||||
}
|
||||
|
||||
.jquery-comments ul#attachment-list:empty ~ .no-attachments {
|
||||
display: inherit;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .comment-wrapper,
|
||||
.jquery-comments ul.main li.toggle-all,
|
||||
.jquery-comments ul.main li.comment .commenting-field {
|
||||
padding: .5em;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .comment-wrapper {
|
||||
border-top: 1px solid #DDD;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main > li.comment:first-child > .comment-wrapper {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .comment-wrapper > .profile-picture {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment time {
|
||||
float: right;
|
||||
line-height: 1.4em;
|
||||
margin-left: .5em;
|
||||
font-size: 0.8em;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .name {
|
||||
line-height: 1.4em;
|
||||
font-weight: bold;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .name a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .name .reply-to {
|
||||
color: #999;
|
||||
font-size: .8em;
|
||||
font-weight: normal;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .name .reply-to i {
|
||||
margin-left: .5em;
|
||||
margin-right: .25em;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .name .new {
|
||||
margin-left: .5em;
|
||||
background: #2793e6;
|
||||
font-size: 0.8em;
|
||||
padding: 0.2em 0.5em;
|
||||
color: #fff;
|
||||
font-weight: normal;
|
||||
border-radius: 1em;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .wrapper{
|
||||
line-height: 1.4em;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.jquery-comments.mobile ul.main li.comment .child-comments li.comment .wrapper{
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
|
||||
/* Content */
|
||||
.jquery-comments ul.main li.comment .wrapper .content {
|
||||
white-space: pre-line;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .wrapper .content a.attachment i {
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .wrapper .content a.attachment > * {
|
||||
max-width: 100%;
|
||||
max-height: 300px;
|
||||
width: auto;
|
||||
height: auto;
|
||||
margin-top: .25em;
|
||||
margin-bottom: .25em;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .wrapper .content time.edited {
|
||||
float: inherit;
|
||||
margin: 0;
|
||||
font-size: .9em;
|
||||
font-style: italic;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .wrapper .content time.edited:before {
|
||||
content: " - ";
|
||||
}
|
||||
|
||||
|
||||
/* Actions */
|
||||
.jquery-comments.mobile ul.main li.comment .actions {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .actions > * {
|
||||
color: #999;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .actions .action {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
line-height: 1.5em;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .actions .action:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .actions .action.upvote {
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .actions .action.upvote .upvote-count {
|
||||
margin-right: .5em;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .actions .action.upvote .upvote-count:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .actions .action.upvote i {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .actions .action:not(.upvote):hover,
|
||||
.jquery-comments ul.main li.comment .actions .action.upvote:not(.highlight-font) i:hover {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .actions .action.delete {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .actions .action.delete.enabled {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.jquery-comments ul#attachment-list li.comment .actions .action:not(.delete) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jquery-comments ul#attachment-list li.comment .actions .action.delete {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.jquery-comments ul#attachment-list li.comment .actions .separator {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/* Child comments */
|
||||
.jquery-comments ul.main li.comment .child-comments > *:before { /* Margin for second level content */
|
||||
content: "";
|
||||
height: 1px;
|
||||
float: left;
|
||||
|
||||
width: calc(3.6em + .5em); /* Profile picture width plus margin */
|
||||
max-width: calc(50px + .5em); /* Profile picture max width plus margin */
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .child-comments .profile-picture {
|
||||
width: 2.4rem;
|
||||
height: 2.4rem;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .child-comments i.profile-picture {
|
||||
font-size: 2.4em;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .child-comments li.toggle-all {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .child-comments li.toggle-all span:first-child {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .child-comments li.toggle-all span:first-child:hover {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .child-comments li.toggle-all .caret {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 0;
|
||||
height: 0;
|
||||
|
||||
margin-left: .5em;
|
||||
border: .3em solid;
|
||||
margin-top: .35em;
|
||||
|
||||
border-left-color: rgba(0, 0, 0, 0);
|
||||
border-bottom-color: rgba(0, 0, 0, 0);
|
||||
border-right-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .child-comments li.toggle-all .caret.up {
|
||||
border-top-color: rgba(0, 0, 0, 0);
|
||||
border-bottom-color: inherit;
|
||||
margin-top: -.2em;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .child-comments .togglable-reply {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment .child-comments .visible {
|
||||
display: inherit;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Editing comment */
|
||||
.jquery-comments ul.main li.comment.edit > .comment-wrapper > *:not(.commenting-field) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jquery-comments ul.main li.comment.edit > .comment-wrapper .commenting-field {
|
||||
padding: 0 !important; /* Parent element has the padding */
|
||||
}
|
||||
|
||||
/* Drag & drop attachments */
|
||||
.jquery-comments.drag-ongoing {
|
||||
overflow-y: hidden !important;
|
||||
}
|
||||
|
||||
.jquery-comments .droppable-overlay {
|
||||
display: table;
|
||||
position: fixed;
|
||||
z-index: 99;
|
||||
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0,0,0,0.3)
|
||||
}
|
||||
|
||||
.jquery-comments .droppable-overlay .droppable-container {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.jquery-comments .droppable-overlay .droppable-container .droppable {
|
||||
background: #FFF;
|
||||
color: #CCC;
|
||||
padding: 6em;
|
||||
}
|
||||
|
||||
.jquery-comments .droppable-overlay .droppable-container .droppable.drag-over {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.jquery-comments .droppable-overlay .droppable-container .droppable i {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
/* Read-only mode */
|
||||
.jquery-comments.read-only .commenting-field {
|
||||
display: none;
|
||||
}
|
||||
.jquery-comments.read-only .actions {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.displayctrl {
|
||||
display: '' !important;
|
||||
}
|
||||
.hidectrl {
|
||||
display: none !important;
|
||||
}
|
||||
.greenColor {
|
||||
color: green;
|
||||
}
|
||||
.blueColor {
|
||||
color: blue;
|
||||
}
|
||||
.redColor {
|
||||
color: red;
|
||||
}
|
||||
.yellowColor {
|
||||
color: yellow;
|
||||
}
|
||||
.jquery-comments .msgContainer {
|
||||
margin-top: 5px;
|
||||
display: inline-block;
|
||||
}
|
||||
.jquery-comments .errorMsg {
|
||||
background: #f3c4c4;
|
||||
}
|
||||
.jquery-comments .msgAlert {
|
||||
padding: 10px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
width: 100%;
|
||||
}
|
2473
samples/js-advanced-commenting/src/webparts/pageComments/js/jquery-comments.js
vendored
Normal file
2473
samples/js-advanced-commenting/src/webparts/pageComments/js/jquery-comments.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
samples/js-advanced-commenting/src/webparts/pageComments/js/jquery-comments.min.js
vendored
Normal file
1
samples/js-advanced-commenting/src/webparts/pageComments/js/jquery-comments.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,38 @@
|
|||
define([], function () {
|
||||
return {
|
||||
"PropertyPaneDescription": "",
|
||||
"BasicGroupName": "Settings",
|
||||
DateTimeFormatLabel: "Datetime format",
|
||||
DateTimeFormatDescription: "Please use the moment datetime format option.",
|
||||
RoundProfilePicLabel: "Profile Picture rounded",
|
||||
RoundProfilePicDescription: "Enable to display the user profile picture as rounded.",
|
||||
NavigationLabel: "Navigation",
|
||||
NavigationDescription: "Tabs like Newest, Oldest, Popular & Attachments will be displayed.",
|
||||
AttachmentLabel: "Attachments",
|
||||
AttachmentDescription: "Allow the users to upload files.",
|
||||
PingLabel: "Ping users",
|
||||
PingDescription: "Allow users to ping other users in the comments.",
|
||||
EditingLabel: "Edit Comments",
|
||||
EditingDescription: "Allow the users to edit their own comments.",
|
||||
UpVotingLabel: "Upvoting of comments",
|
||||
UpVotingDescription: "Allow the users to upvote the comments.",
|
||||
ReplyLabel: "Reply to comments",
|
||||
ReplyDescription: "Allow the users to reply to the comments.",
|
||||
DeleteLabel: "Delete own comments",
|
||||
DeleteDescription: "Allow the users to delete their own comments.",
|
||||
DeleteRepliesLabel: "Delete own comments with replies",
|
||||
DeleteRepliesDescription: "Allow the users to delete their own comments with replies.",
|
||||
HashtagsLabel: "Hashtags",
|
||||
HashtagsDescription: "Allow the users to use hashtags.",
|
||||
DocumentPreviewLabel: "Document Preview",
|
||||
DocumentPreviewDescription: "Allow the users to view few of the document formats inline.",
|
||||
AttachmentFileFormatLabel: "Allowed Files",
|
||||
AttachmentFileFormatDescription: "Allowed files to attach. Please enter file extensions separated by ,",
|
||||
AttachmentFileSizeLabel: "Max File Size",
|
||||
AttachmentFileSizeDescription: "Maximum file size(MB) allowed to attach.",
|
||||
AttachmentRepoLabel: "Select a libary",
|
||||
AttachmentRepoPropValMsg: "Please choose the document library",
|
||||
NoAttachmentRepoMsg: "Please select the document library to store the attachments.",
|
||||
LoadingMsg: "Please wait..."
|
||||
}
|
||||
});
|
|
@ -0,0 +1,42 @@
|
|||
declare interface IPageCommentsWebPartStrings {
|
||||
PropertyPaneDescription: string;
|
||||
BasicGroupName: string;
|
||||
|
||||
DateTimeFormatLabel: string;
|
||||
DateTimeFormatDescription: string;
|
||||
RoundProfilePicLabel: string;
|
||||
RoundProfilePicDescription: string;
|
||||
NavigationLabel: string;
|
||||
NavigationDescription: string;
|
||||
AttachmentLabel: string;
|
||||
AttachmentDescription: string;
|
||||
PingLabel: string;
|
||||
PingDescription: string;
|
||||
EditingLabel: string;
|
||||
EditingDescription: string;
|
||||
UpVotingLabel: string;
|
||||
UpVotingDescription: string;
|
||||
ReplyLabel: string;
|
||||
ReplyDescription: string;
|
||||
DeleteLabel: string;
|
||||
DeleteDescription: string;
|
||||
DeleteRepliesLabel: string;
|
||||
DeleteRepliesDescription: string;
|
||||
HashtagsLabel: string;
|
||||
HashtagsDescription: string;
|
||||
DocumentPreviewLabel: string;
|
||||
DocumentPreviewDescription: string;
|
||||
AttachmentFileFormatLabel: string;
|
||||
AttachmentFileFormatDescription: string;
|
||||
AttachmentFileSizeLabel: string;
|
||||
AttachmentFileSizeDescription: string;
|
||||
AttachmentRepoLabel: string;
|
||||
AttachmentRepoPropValMsg: string;
|
||||
NoAttachmentRepoMsg: string;
|
||||
LoadingMsg: string;
|
||||
}
|
||||
|
||||
declare module 'PageCommentsWebPartStrings' {
|
||||
const strings: IPageCommentsWebPartStrings;
|
||||
export = strings;
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"extends": "./node_modules/@microsoft/rush-stack-compiler-2.9/includes/tsconfig-web.json",
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"jsx": "react",
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
"experimentalDecorators": true,
|
||||
"skipLibCheck": true,
|
||||
"outDir": "lib",
|
||||
"inlineSources": false,
|
||||
"strictNullChecks": false,
|
||||
"noUnusedLocals": false,
|
||||
"typeRoots": [
|
||||
"./node_modules/@types",
|
||||
"./node_modules/@microsoft"
|
||||
],
|
||||
"types": [
|
||||
"es6-promise",
|
||||
"webpack-env"
|
||||
],
|
||||
"lib": [
|
||||
"es5",
|
||||
"dom",
|
||||
"es2015.collection"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"lib"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"extends": "@microsoft/sp-tslint-rules/base-tslint.json",
|
||||
"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-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-use-before-declare": true,
|
||||
"no-with-statement": true,
|
||||
"semicolon": true,
|
||||
"trailing-comma": false,
|
||||
"typedef": false,
|
||||
"typedef-whitespace": false,
|
||||
"use-named-parameter": true,
|
||||
"variable-name": false,
|
||||
"whitespace": false
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue