Wednesday, 14 October 2020

Update Custom Column of Task in Project Online using JSOM

 var projContext;

var projects;

var project;

var draft_project;

var tasks;

var task;

var customfields;

var ProjectId = '<guid here>'; //Guid of the Project to Be Updated


SP.SOD.executeOrDelayUntilScriptLoaded(runMyCode, "PS.js"); //Load PS.js


function runMyCode() {

 //Create the ProjectContext object

 projContext = new PS.ProjectContext('<pwa site>');


 //Project List information will be placed inside projects variable

 projects = projContext.get_projects();


 //Signal the information that is going to be loaded

 projContext.load(projects);


 //Send the request to the server

 projContext.executeQueryAsync(LoadProject, QueryFailed);

}


function LoadProject() {

 //Create variable that will hold specific project information

 project = projects.getById(ProjectId);

 projContext.load(project);

 projContext.executeQueryAsync(ProjectLoadFinished, QueryFailed);

}


function ProjectLoadFinished() {

 //The project Variable contains published information

 // alert(project.get_name());


 //In order to change the project you need to Checkout the Project

 draft_project = project.checkOut();

 GetTasks();

}


function GetTasks() {

 tasks = draft_project.get_tasks();

 projContext.load(tasks);

 projContext.executeQueryAsync(TasksLoadFinished, QueryFailed);

 //var jobUid = draft_project.update();

 //projContext.waitForQueueAsync(jobUid, 3600, PublishAndCheckIn);

}


function TasksLoadFinished() {

 task = tasks.getByGuid('<task guid>'); //GUID of Task

 projContext.load(task);

 projContext.executeQueryAsync(TaskLoadFinished, QueryFailed);

}


function TaskLoadFinished() {

 //customfields = task.get_customFields();

 //projContext.load(customfields);

 task.set_item('<custom Column internal name>', 'This is a testing method'); //set value here

 var jobUid = draft_project.update();

 projContext.waitForQueueAsync(jobUid, 3600, PublishAndCheckIn);

 //projContext.executeQueryAsync(CustomFieldsLoadFinished, QueryFailed);

}


function CustomFieldsLoadFinished() {

}


function PublishAndCheckIn(response) {

 Log("Publishing and Checkin in");

 var jobUid2 = draft_project.publish(true);

 projContext.waitForQueueAsync(jobUid2, 3600, FinalMessage);

}


function FinalMessage(response) {

 console.log(response);

}


function QueryFailed(error) {

}

});

Monday, 12 October 2020

Project Server Risks and Issues on a Project Detail Page

  <script type="text/javascript" src="/PWA/SiteAssets/jquery-1.8.3.min.js"></script>

<script type="text/javascript" src="/PWA/SiteAssets/knockout-3.1.0.js"></script>

<script type="text/javascript" src="/PWA/SiteAssets/ko.sp-1.0.min.Ex.js"></script>  

<script type="text/javascript" src="/_layouts/15/sp.runtime.debug.js"></script>

    <script type="text/javascript" src="/_layouts/15/sp.debug.js"></script>

    <script type="text/javascript" src="/_layouts/15/ps.debug.js"></script>


<script type=text/javascript>

var urlStr = unescape(window.location)

if (urlStr.toLowerCase().indexOf('projuid')>=0) {

var projUid = urlStr.substr(urlStr.indexOf("=")+1,36)

}

else {

document.write("Not available in this context. Not a Project Server Project Detail Page or project associated");

}

</script>

   

<div id="divMessage">

    <br/>

    <span id="spanMessage" style="color: #FF0000;"></span>

</div>


<style type="text/css">

.tableGrid th { width:2%; padding:4; border:1px solid; }

.tableGrid td { padding:2; border:1px solid; } 

.tableGrid tr:nth-child(even) {

background: #E5E4E2;

}

.tableGrid tr:nth-child(odd) {

background: #FFFFFF;

}

</style>


<h1>Risk Data</h1>

 <br />

   

 <div id="riskDiv">

     <table class="tableGrid">

         <thead>

             <tr>

                 <th>Risk Title</th>

                 <th>Due Date</th>

<th>Status</th>

                 <th>Cost</th>

                 <th>Probability</th>

                 <th>Impact</th>

                 <th>Assigned To</th>  

             </tr>

         </thead>

         <tbody data-bind="template: { name: 'risktable', foreach: Items }" />

     </table>

 </div> 

 <br />

<h1>Issue Data</h1>

 <br />

 <div id="issueDiv">

     <table class="tableGrid">

         <thead>

             <tr>

                 <th>Issue Title</th>

                 <th>Due Date</th>

<th>Status</th>

                 <th>Priority</th>

<th>Assigned To</th>

                 <th>Modified By</th>  

             </tr>

         </thead>

         <tbody data-bind="template: { name: 'issuetable', foreach: Items }" />

     </table>

 </div> 


<script type="text/javascript">


    var projects;

    SP.SOD.executeOrDelayUntilScriptLoaded(GetProjects, "PS.js");


    function GetProjects() {


        var projContext = PS.ProjectContext.get_current();


        projects = projContext.get_projects();


        projContext.load(projects, 'Include(Name, Id, ProjectSiteUrl)');


        projContext.executeQueryAsync(onQuerySucceeded, onQueryFailed);

    }

    function onQuerySucceeded(sender, args) {


        var projectEnumerator = projects.getEnumerator();

var proj;

        while (projectEnumerator.moveNext()) {

            var project = projectEnumerator.get_current();


if (project.get_id() == projUid) {

                  proj = project;

}

}

            projSiteUrl = proj.get_projectSiteUrl();


ko.applyBindings(new KoSpModal1(), riskDiv);                                     

            ko.applyBindings(new KoSpModal2(), issueDiv);

    }

    function onQueryFailed(sender, args) {

        $get("spanMessage").innerText = 'Request failed: ' + args.get_message();

    }

</script>


 <script type="text/html" id="risktable">

     <tr>

         <td data-bind="text:Title"></td>

         <td data-bind="spDate:DueDate,defaultValue:' NA'"></td>

<td data-bind="spChoice:Status"></td>

         <td data-bind="spNumber:Cost,dataFormat:'£0.00',defaultValue:'£0.00'"></td>

         <td data-bind="spNumber:Probability,dataFormat:'0.00 %',defaultValue:'0.00 %'"align="center"></td>

         <td data-bind="spNumber:Impact,dataFormat:'0.00'"align="center"></td>

         <td data-bind="spUser:AssignedTo"></td>

     </tr>

 </script>

 <script type="text/javascript">

     function KoSpModal1() {

         var self = this;

self.Items = ko.observableArray([]);

         $.getJSON(projSiteUrl + "/_vti_bin/listdata.svc/Risks?$expand=Status,AssignedTo&$select=Title,DueDate,Status,Cost,Probability,Impact,AssignedTo",

             function (data) {

                 if (data.d.results) {

                     self.Items(ko.toJS(data.d.results));

                 }

             }

       )

     }

 </script>

  <script type="text/html" id="issuetable">

     <tr>

         <td data-bind="text:Title"></td>

         <td data-bind="spDate:DueDate,defaultValue:' NA'"></td>

<td data-bind="spChoice:Status"></td>

         <td data-bind="spChoice:Priority"></td>

<td data-bind="spUser:AssignedTo"></td>

         <td data-bind="spUser:ModifiedBy"></td>

     </tr>

 </script>

 <script type="text/javascript">

     function KoSpModal2() {

         var self = this;

         self.Items = ko.observableArray([]);

         $.getJSON(projSiteUrl + "/_vti_bin/listdata.svc/Issues?$expand=Status,Priority,AssignedTo,ModifiedBy&$select=Title,DueDate,Status,Priority,AssignedTo,ModifiedBy",

             function (data) {

                 if (data.d.results) {

                     self.Items(ko.toJS(data.d.results));

                 }

             }

       )

     }

 </script>

Use SharePoint people pickers on Project Server or Online PDPs

 


//Set the following to be an array of fields you would like to change into a people-picker

var targetFields = ['Project Sponsor'];

//var targetFields = ['Field 1', 'Field 2'];


//safely load JQuery

if (typeof jQuery == 'undefined') {

    var s = document.createElement("script");

    s.src = '//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js';

    if (s.addEventListener) {

        s.addEventListener("load", function () { myJQueryCode() }, false);

    } else if (s.readyState) {

        s.onreadystatechange = function () { myJQueryCode() };

    }

    document.getElementsByTagName('head')[0].appendChild(s);

} else {

    myJQueryCode();

}


function myJQueryCode() {

    $(document).ready(function () {

        var scriptRoot = _spPageContextInfo.siteAbsoluteUrl + '/_layouts/15/';


        $.when(

                $.getScript(scriptRoot + "clienttemplates.js"),

                $.getScript(scriptRoot + "clientforms.js"),

                $.getScript(scriptRoot + "clientpeoplepicker.js"),

                $.getScript(scriptRoot + "autofill.js")

            )

            .done(function () {

                window.console && console.log('Scripts loaded');

                renderPeoplePickers();

            })

            .fail(function (message) {

                window.console && console.error('Loading scripts failed: ' + message);

            });

    });

}


function renderPeoplePickers() {

    for (fieldIndex = 0; fieldIndex < targetFields.length; fieldIndex++) {

        $("input[type='text'][title='" + targetFields[fieldIndex] + "']").each(function () {

            this.style.color = "green";

            renderPeoplePicker(this);

            window.console && console.log('PeoplePicker rendered: ' + targetFields[fieldIndex]);

        });

    }

}


function renderPeoplePicker(targetInput) {

    var divPeoplePicker = document.createElement('div');

    var idPeoplePicker = targetInput.id + '_PeoplePicker';

    var targetValue = $(targetInput).attr('value');


    divPeoplePicker.id = idPeoplePicker;

    $(targetInput).parent().append(divPeoplePicker);


    initializePeoplePicker(idPeoplePicker);

    var newPeoplePicker = this.SPClientPeoplePicker.SPClientPeoplePickerDict[idPeoplePicker + '_TopSpan'];

    $(targetInput).hide();


    if (typeof targetValue !== "undefined") {

        newPeoplePicker.AddUnresolvedUser({

            Key: targetValue,

            DisplayText: targetValue

        }, true);

    }


    newPeoplePicker.OnControlResolvedUserChanged = function () {

        if (this.TotalUserCount > 0) {

            //we have a resolved user

            var resolvedUser = this.GetAllUserInfo()[0];


            //Set the underlying field value

            $('input#' + (this.TopLevelElementId.split("_PeoplePicker_TopSpan")[0])).attr('value', resolvedUser.DisplayText);


            //If value has changed then mark the PDP dirty to enable save

            //Thankyou to Martin Laukkanen (nearbaseline.com) for this fix!

            if ($('input#' + (this.TopLevelElementId.split("_PeoplePicker_TopSpan")[0])).attr('origvalue') !== $('input#' + (this.TopLevelElementId.split("_PeoplePicker_TopSpan")[0])).attr('value')) {

                WPDPParts[0].IsDirty = true;

            }

        } else {

            //we have nothing - so clear out the target field

            $('input#' + (this.TopLevelElementId.split("_PeoplePicker_TopSpan")[0])).attr('value', '');

        }

    }


}


// Render and initialize the client-side People Picker.

function initializePeoplePicker(peoplePickerElementId, defaultValue) {


    var users;

    if ((defaultValue != undefined) && (defaultValue != "")) {

        users = new Array(1);

        var defaultUser = new Object();

        defaultUser.AutoFillDisplayText = defaultValue;

        defaultUser.AutoFillKey = defaultValue;

        //defaultUser.Description = user.get_email();

        defaultUser.DisplayText = defaultValue;

        defaultUser.EntityType = "User";

        defaultUser.IsResolved = false;

        defaultUser.Key = defaultValue;

        defaultUser.Resolved = false;

        users[0] = defaultUser;

    } else {

        users = null;

    }


    // Create a schema to store picker properties, and set the properties.

    var schema = {};

    schema['PrincipalAccountType'] = 'User';

    //schema['PrincipalAccountType'] = 'User,DL,SecGroup,SPGroup';

    schema['SearchPrincipalSource'] = 15;

    schema['ResolvePrincipalSource'] = 15;

    schema['AllowMultipleValues'] = false;

    schema['MaximumEntitySuggestions'] = 50;

    schema['Width'] = '360px';


    // Render and initialize the picker. 

    // Pass the ID of the DOM element that contains the picker, an array of initial

    // PickerEntity objects to set the picker value, and a schema that defines

    // picker properties.

    this.SPClientPeoplePicker_InitStandaloneControlWrapper(peoplePickerElementId, users, schema);

}