Saturday, October 16, 2021

File upload with metadata by using SPFx React framework with bootstrap - Part2


 File upload with metadata by using SPFx React framework with bootstrap - Part2.

please follow my previous Part1 post for more in details:



 

F:\SPFx\DemoReactWP

Install required

yo @microsoft/sharepoint

npm instal jquery - - save

npm install jqueryui  - - save

npm install @types/jquery  - -save-dev

npm install @types/jqueryui - -save-dev

npm install @pnp/spfx-controls-react

 

Bootstrap:

npm i react-bootstrap - -save

npm install bootstrap@4 - - save

npm install @types/bootstrap@4 - - save-dev

 

npm install url-loader --save-dev

 

SP install:

npm install @pnp/common @pnp/sp @pnp/logging @pnp/odata --save

 

Go to -> webpart.ts file

import {sp} from '@pnp/sp/presets/all'

 Add below code before the render method:

 protected async onInit(): Promise<void> {

    const _ = await super.onInit();

    sp.setup({

      spfxContext: this.context

    });

  }

 

 

 Add Style (.SCSS)

 

 .itemField {

    displayflex;

    padding5px;

.fieldLabel {

      min-width100px;

    }

  }

  

.buttonSection{

    padding-top20px;

    displayflex;

  }

.myTable{

  border1px solid #ddd;

}

.displayNone{

  displaynone;

}

.paddingTop10{

  padding-top10px

}

.tblThread{

  background#17a2b8colorwhite;

}

.tblTh{

  border1px solid #ddd;

}

 

Props.ts:

import { WebPartContext } from "@microsoft/sp-webpart-base";

export interface IMyWpProps {

  description: string;

  context:WebPartContext;  

}

  

Config.json

 "externals": {

  "jquery": {

    "path":"https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js",

      "globalName""jquery"

    },

    "bootstrap": {     

     "path""node_modules\bootstrap/dist/js/bootstrap.min.js",

      "globalName""bootstrap",

      "globalDependencies": ["jquery"]

    } 

  },

 


Component (tsx) file

import * as React from 'react';

import styles from './MyWp.module.scss';

import { IMyWpProps } from './IMyWpProps';

import { escape } from '@microsoft/sp-lodash-subset';

 

import { SPComponentLoader } from '@microsoft/sp-loader';

import * as $ from 'jquery';

import 'jqueryui';

import 'bootstrap/dist/css/bootstrap.css';

import { sp } from "@pnp/sp/presets/all";

import "@pnp/sp/webs";

import "@pnp/sp/lists";

import "@pnp/sp/items";

import { PeoplePicker, PrincipalType } from '@pnp/spfx-controls-react/lib/PeoplePicker';

import { IMyWpState } from './IMyWpState';

import { SPOps } from '../../Services/SPService';



export default class MyWp extends React.Component<IMyWpProps, IMyWpState, {}> {  

  constructor(props: IMyWpProps) {

    super(props);    

    this._spOps = new SPOps();    

    SPComponentLoader.loadCss("//code.jquery.com/ui/1.9.1/themes/smoothness/jquery-ui.css");

    SPComponentLoader.loadCss("https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css");

    //this.state={ ddlCountry:[] };

  }

 

  public _spOps: SPOps;

 

  public componentDidMount() {

    this.PageLoad();

  }

 

  public _getPeoplePickerItems = async (items: any[]) => {

    try {

      let AppprPickerItems: any[] = [];

      items.map((item) => {

        AppprPickerItems.push(item.id);

        this.setState({ ppeApproversArray: AppprPickerItems });        

      });

      // Sample code to direct excute

      if (items.length > 0) {

        this.setState({ ApproversName: items[0].text });

        this.setState({ ApproversNameId: items[0].id });

        console.log('EmployeeName -' + items[0].text);

      }

      else {      

        this.setState({ ApproversNameId: "" });

        this.setState({ ApproversName: "" });

      }

    }

    catch (ex) {

      alert(ex.message);

    }

  }

 

  public render(): React.ReactElement<IMyWpProps> {

 

    return (

      <div className="container-fluid">

        <div className="row">

          <div className="col-sm">

            <label>

              <h3>Document Upload using SPFx -React</h3>

            </label>

          </div>

        </div>

        <div className="row">

          <div className="col-sm">

            <label>File Upload:</label>

            <input id="fileuploader" type="file" className="form-control" />

          </div>

          <div className="col-sm">

          </div>

        </div>

        <div className="row">

          <div className="col-sm">

            <label>Project Code:</label>

            <select id="projectcode" className="form-control">

              <option>-- select project code --</option>

              <option>001</option>

              <option>002</option>

              <option>003</option>

              <option>004</option>

              <option>005</option>

            </select>

          </div>

          <div className="col-sm">

            <label>Project Title:</label>

            <input type="text" id="projecttitle" className="form-control" />

          </div>

          <div className="col-sm">

            <label>Document Type:</label>

            <select id="documenttype" className="form-control">

              <option>-- select document --</option>

              <option>Type1</option>

              <option>Type2</option>

              <option>Type3</option>

              <option>Type4</option>

              <option>Type5</option>

            </select>

          </div>

 

        </div>

        <div className="row">

          <div className="col-sm">

            <label>Requestor:</label>

            <select id="originator" className="form-control">

              <option>-- select requestor --</option>

              <option>Sample1</option>

              <option>Sample2</option>

              <option>Sample3</option>

              <option>Sample4</option>

              <option>Sample5</option>

            </select>

          </div>

          <div className="col-sm">

            <label>Valid From:</label>

            <input type="text" id="validfrom" className="form-control" />

          </div>

          <div className="col-sm">

            <label>Valid Till:</label>

            <input type="text" id="validto" className="form-control" />

          </div>

        </div>

 

        <div className="row">

 

          <div className="col-sm">

            <label>Currency:</label>

            <select id="currency" className="form-control">

              <option>-- select currency --</option>

              <option>AED</option>

              <option>SAD</option>

              <option>INR</option>

              <option>USD</option>

              <option>QAR</option>

            </select>

          </div>

 

          <div className="col-sm">

            <label>Amount:</label>

            <input type="text" id="amount" className="form-control" />

          </div>

          <div className="col-sm">

            <label>Approvers name </label>

            <PeoplePicker

              context={this.props.context}

              personSelectionLimit={3}

              required={false}

              onChange={this._getPeoplePickerItems}

              //defaultSelectedUsers={[this.state.ppeApproversArray ? this.state.ppeApproversArray[] : ""]}

              showHiddenInUI={false}

              principalTypes={[PrincipalType.User]}

              resolveDelay={1000}

              ensureUser={true}

            />

          </div>

 

        </div>

 

        <div className="row">

          <br />

        </div>

 

        <div className="row">

          <div className="col-sm">

            <input type="button" id="btnsave" value="Save" className="btn-danger form-control" /></div>

          <div className="col-sm">

            <input type="button" id="btncancel" value="Cancel" className="btn-info form-control" /></div>

          <div className="col-sm"></div>

        </div>

        <div className="row">

          <br />

        </div>

        <div className="row" >

          <div className="col-sm">

            <label id="itemId" />

            <table className={styles.myTable}>

              <thead className={styles.tblThread}>

                <tr>

                  <th className={styles.tblTh}>Type</th>

                  <th className={styles.tblTh}>Project Code</th>

                  <th className={styles.tblTh}>Project Title</th>

                  <th className={styles.tblTh}>Document Type</th>

                  <th className={styles.tblTh}>Requestor</th>

                  <th className={styles.tblTh}>Amount</th>

                  <th className={styles.tblTh}>Actions</th>

                </tr>

              </thead>

              <tbody id="expirydocuments"></tbody>

            </table>

          </div>

        </div>

      </div>

    );

  }

 

 

  public PageLoad(): Promise<string> {

    try {

      return new Promise<string>(async (resolve, reject) => {

        $("#validfrom").datepicker();

        $("#validto").datepicker();

        $("#btnsave").click(f => {

          let itemId = $("#itemId").val();

          if (itemId == "" || itemId == null) {

            this.AddUpdate("Add", "");

          }

          else { this.AddUpdate("Update", itemId); }

        });

        $("#btncancel").click(f => {

          $("#itemId").val("");

          this.ClearControl();

        });

        this.BindData();

        resolve('Loaded succesfully');

      });

    }

    catch (ex) {

      alert(ex.message);

    }

  }

 

  public getItemName(itemid: number): Promise<string> {

    try {

      let filName: string = "";

      return new Promise<string>((resolve, reject) => {

        sp.web.lists.getByTitle("DocumentExpiry").items.getById(itemid).select('File_x0020_Type')

          .get().then(item => {

            console.log('File_x0020_Type' + item.File_x0020_Type);

            filName = item.File_x0020_Type;

            resolve(filName);

            debugger;

          });

 

      });

    } catch (ex) {

      alert('Error - getItemName --' + ex.message);

    }

  }

  public BindData = async () => {

    let i:number =0;

    sp.web.lists.getByTitle("DocumentExpiry").items.getAll().then(items => {

      $("#expirydocuments").html("");  

      items.forEach(item => {

        let filename: string = "";

        this.getItemName(item.Id).then((data: any) => {

          filename = data;

          i++;

          let htmlContent = `

          <tr>

          <td style="border: 1px solid #ddd;"><img src="/_layouts/15/images/ic${filename}.png" /></td>

          <td style="border: 1px solid #ddd;">${item.ProjectCode}</td>

          <td style="border: 1px solid #ddd;">${item.ProjectTitle == null ? '' : item.ProjectTitle}</td>

          <td style="border: 1px solid #ddd;">${item.DocumentType}</td>

          <td style="border: 1px solid #ddd;">${item.Originator}</td>            

          <td style="border: 1px solid #ddd;">${item.Amount == null ? '' : item.Amount} ${item.Currency}</td>

         

          <td style="border: 1px solid #ddd;">

            <input id="edit_${item.Id}" class="edit" type="button" value="Edit">

            <input type="button" id="btndelete_${item.Id}" class="btndelete" value="Delete" > </td>';

            </tr>`;

          $("#expirydocuments").append(htmlContent);

          if(items.length == i){          

            this.EventBinding();

          }        

        });      

      });    

    });

  }

 

  public EventBinding = async () => {

    try {

      $(".btndelete").click(w => {

        let itemId = Number(w.delegateTarget.id.split("_")[1]);

        if (confirm("Are you sure,you want to delete this item?")) {

          this.DeleteItem(itemId);

        }

      });

 

      $(".edit").click(w => {

        let itemId = Number(w.delegateTarget.id.split("_")[1]);

        this.LoadItemDetails(itemId);

      });

    }

    catch (ex) {

      alert(ex.message);

    }

  }

  public LoadItemDetails = async (itemid: number) => {

    sp.web.lists.getByTitle("DocumentExpiry").items.getById(itemid).get().then(item => {

      $("#itemId").val(item.Id);

      $("#projectcode").val(item.ProjectCode);

      $("#projecttitle").val(item.ProjectTitle = null ? '' : item.ProjectTitle);

      $("#documenttype").val(item.DocumentType);

      $("#originator").val(item.Originator);

      $("#validfrom").val(item.ValidFrom = null ? '' :

        $.datepicker.formatDate('mm/dd/yy', new Date(item.ValidFrom)));

      $("#validto").val(item.ValidTill = null ? '' :

        $.datepicker.formatDate('mm/dd/yy', new Date(item.ValidTill)));

      $("#currency").val(item.Currency);

      $("#amount").val(item.Amount = null ? '' : item.Amount);

    });

  }

 

  public DeleteItem = async (itemid: number) => {

    sp.web.lists.getByTitle("DocumentExpiry").items.getById(itemid).delete().then(res => {

      alert("Item Deleted.");

      this.BindData();

    }).catch(error => { console.log(error); });

  }

  private AddUpdate(commandType: string, itemid: any): void {

    let projectCode = $("#projectcode").val();

    let projectTitle = $("#projecttitle").val();

    let documentType = $("#documenttype").val();

    let originator = $("#originator").val();

    let vF: any = $("#validfrom").val();

    let vT: any = $("#validto").val();

    let validFrom = new Date(vF);

    let validTill = new Date(vT);

    let currency = $("#currency").val();

    let amount = $("#amount").val();

 

    if (commandType == "Add") {    

      try {

        let file = (document.querySelector("#fileuploader") as HTMLInputElement).files[0];

        //upload small file in document library  

        console.log('RK Url' + this.props.context.pageContext.site.serverRelativeUrl);

        sp.web.getFolderByServerRelativeUrl(this.props.context.pageContext.site.serverRelativeUrl + "/DocumentExpiry").files

          .add(file.name, file, true).then(f => {

            // use below to update the properties of document

            f.file.getItem().then(item => {

              item.update({

                ProjectCode: projectCode,

                ProjectTitle: projectTitle,

                DocumentType: documentType,

                Originator: originator,

                ValidFrom: validFrom,

                ValidTill: validTill,

                Currency: currency,

                Amount: amount,

                ApproversNameId: { results: this.state.ppeApproversArray }

              }).then(f => {

                alert("File uploaded successfully"); $("#itemId").val("");

                this.BindData();

                this.ClearControl();

              }).catch(error => {

                console.log(error);

              });

            });

          });

      }

      catch (ex) {

        alert(ex.message);

      }    

    }

    else {

      try {

        sp.web.lists.getByTitle("DocumentExpiry").items.getById(itemid).update({

          ProjectCode: projectCode,

          ProjectTitle: projectTitle,

          DocumentType: documentType,

          Originator: originator,

          ValidFrom: validFrom,

          ValidTill: validTill,

          Currency: currency,

          Amount: amount,

          ApproversNameId: { results: this.state.ppeApproversArray }

        }).then(item => {

          alert("Item Updated successfully");

          $("#itemId").val("");

          this.BindData();

          this.ClearControl();

        }).catch(error => { console.log(error); });

      }

      catch (ex) {

        alert(ex.message);

      }

    }

  }

 

  public ClearControl = async () => {

    $("#projecttitle").val('');

    $("#validfrom").val('');

    $("#validto").val('');

    $("#amount").val('');

    $('#projectcode').val("-- select project code --");

    $('#documenttype').val("-- select document --");

    $('#originator').val("-- select requestor --");

    $('#currency').val("-- select currency --");

  } 

}

 



Ts File:

import * as React from 'react';

import * as ReactDom from 'react-dom';

import { Version } from '@microsoft/sp-core-library';

import {

  IPropertyPaneConfiguration,

  PropertyPaneTextField

} from '@microsoft/sp-property-pane';

import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';

 

import * as strings from 'MyWpWebPartStrings';

import MyWp from './components/MyWp';

import { IMyWpProps } from './components/IMyWpProps';

import {sp} from '@pnp/sp/presets/all'; 

export interface IMyWpWebPartProps {

  description: string;

}

 

export default class MyWpWebPart extends BaseClientSideWebPart<IMyWpWebPartProps> { 

  protected async onInit(): Promise<void> {

    const _ = await super.onInit();

    sp.setup({

      spfxContext: this.context

    });

  }

 

  public render(): void {

    const element: React.ReactElement<IMyWpProps> = React.createElement(

      MyWp,

      {

        description: this.properties.description,

        context:this.context

      }

    ); 

    ReactDom.render(element, this.domElement);

  }

 

  protected onDispose(): void {

    ReactDom.unmountComponentAtNode(this.domElement);

  }

 

  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

                })

              ]

            }

          ]

        }

      ]

    };

  }

}

 

Props File:

import { WebPartContext } from "@microsoft/sp-webpart-base"; 

export interface IMyWpProps {

  description: string;

  context:WebPartContext;  

}

 

SPOperations/Service File:

 


import { WebPartContext } from '@microsoft/sp-webpart-base';

import { sp } from '@pnp/sp/presets/all';

import { error } from 'jquery';

import { IDropdownOption } from 'office-ui-fabric-react'; 

export class SPOps { 

   public getDropdown(context: WebPartContext): Promise<IDropdownOption[]> {

      return new Promise<IDropdownOption[]>((resolve, reject) => {

         let countryTemp:IDropdownOption[] = [];

         sp.web.lists.getByTitle('DocumentExpiry').fields.getByInternalNameOrTitle('Country')

         .select('Country,ID').get().then((items:any)=>{          

            items.map((item:any)=>{

               countryTemp.push({key:item.Title,text:item.Title});

               resolve(countryTemp);

            });

         });

      });

   }

 

   public DeletItem(itemID: number): Promise<string> {

      try {

         return new Promise<string>(async (resolve, reject) => {              sp.web.lists.getByTitle('DocumentExpiry').items.getById(itemID).delete().then(() => {

               resolve('Item Deleted ' + itemID + ' Succesfully');

            }, (error: any): void => { reject("Error occured " + error); }

            ); 

         });

      }

      catch (ex) {       

      }

   }

 

}