Adding a List Item to a Project Detail Page in Gallery format

Occasional Contributor

I created a new custom list in Sharepoint and set it to gallery view, so I can see each list item as a card with Choice Pills styling. I have attached a picture of one of the list items. I want to be able to present this list item (as is) in a Project Details Page using a web part.

1) Is this possible? If so, how?
2) Which webpart would I use to achieve this?
3) Are there other web parts that are available to download from Microsoft that may allow me to do what I am envisioning?

Thank you in advance.

5 Replies

Hello @John Passaro ,

Where is the list hosted?

Out of the box you can surface lists from the PWA site collection in pages in PWA such as PDPs using the List found in the Apps Category as seen below - I have a list called "Test List" in my root PWA site:

PaulMather_0-1634242770192.png

 

Please note, as this list is central and not project specific and the PDPs are shared pages between projects, this list will appear on for all Projects - see example below:

"Pauls Test Project":

PaulMather_1-1634242969855.png

"Pauls Test Project 2":

PaulMather_2-1634243005600.png

That is the out of the box option for surfacing a list on a PDP.

 

Regarding other web parts to download - there is a SharePoint store. From the Site Contents page in PWA, click New --> App

PaulMather_3-1634243169598.png

 

Click From SharePoint Store:

PaulMather_4-1634243239232.png

Some of those Apps might include App parts (webparts). I'm not sure if there is anything in the store that will give you what you need, but have a browse to see what you can find. 

Paul

Thanks, Paul. My list was created at the project level and I just can't seem to find a webpart that will allow me to see the Gallery view Card in the PDP. I'm assuming the only way for me to show the list as a webpart is to create it from the root site for all projects? That is not what I'm looking for. I wanted to create the project health list for each project and show it in their respective PDP. Thank you.

Hello @John Passaro ,

There wont be a webpart for the classic PDPs to show the gallery view on a modern list - I think you'd need to build (code) that yourself.

Will this central list on the root site contain items for each project? Out of the box you wont be able to filter the list items for the current project on that PDP, the list view will show all items in the list view used. Where the list is a central list on the root site or a list on the project site, you will need a custom solution to display the filtered / specific content for that project on the PDP. These blog posts might help:

https://pwmather.wordpress.com/2015/05/12/projectonline-projectserver-2013-access-sharepoint-lists-o...

https://pwmather.wordpress.com/2014/04/11/want-to-see-risks-and-issues-on-a-projectonline-projectser... 

The code isn't available on the download link anymore but I can share it here if needed (it will need updating / testing / making suitable for production use as it is very old - it might not event work anymore!)

Paul

Anything you can share would be greatly appreciated. I will also look at the links you provided. Thank you very much.

Hello @John Passaro ,

Please see the code samples below (these will need testing / changing / making suitable for production etc.) These were written many many years ago and might no loner work:

Showing lists from the Project sites on PDPs in an iframe:

</style>
	
<script type="text/javascript">

$(document).ready(function () {
getProjectUID();
});

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

//get project UID from the URL
function getProjectUID(){
	var urlStr = unescape(window.location)
	if (urlStr.toLowerCase().indexOf('projuid')>=0) {
	projUid = urlStr.substr(urlStr.indexOf("=")+1,36) 
		}
	else {
		$("#messages").html("Not available in this context. Not a Project Server Project Detail Page or project associated");
		$("#buttons").hide();
		}
}

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();
		showRisks();
}
function onQueryFailed(sender, args) {
	$get("spanMessage").innerText = 'Request failed: ' + args.get_message();
}	
	
function showRisks() {
    $("#issueDiv").hide();
    $("#riskDiv").show();
	$("#riskTable").html('<object width="950" height="800" data= "'+projSiteUrl+'/Lists/Risks/AllItems.aspx?isdlg=1"/>');	
    $("#riskBtn").addClass("selectedBtn").removeClass("deselectedBtn");
    $("#issueBtn").removeClass("selectedBtn");
}

function showIssues() {
    $("#riskDiv").hide();
    $("#issueDiv").show();
	$("#issueTable").html('<object width="950" height="800" data= "'+projSiteUrl+'/Lists/Issues/AllItems.aspx?isdlg=1"/>');
    $("#riskBtn").removeClass("selectedBtn");
    $("#issueBtn").addClass("selectedBtn").removeClass("deselectedBtn");
}
</script>

You will need to ensure jQuery etc. are loaded on the page too. You then just need the HTML and CSS to such as:

<div id="divMessage">
    <br/>
    <span id="spanMessage" style="color: #FF0000;"></span>
</div>
<p id="messages"></p>
	
<div id="buttons">
    <button type='button' id="riskBtn" class='deselectedBtn' onclick="showRisks()" >Display Risks</button>
    <button type='button' id="issueBtn" class='deselectedBtn' onclick="showIssues()">Display Issues</button>
</div>	

<div id="riskDiv" style="display:none">
	<h1>Risk List</h1>
	<div id="riskTable"></div>
</div> 

<div id="issueDiv" style="display:none">
	<h1>Issue List</h1>
    <div id="issueTable"></div>
</div>

<style type="text/css">
.selectedBtn {
	background-color: grey;
	color: white;
	text-decoration: underline;
}
.deselectedBtn {
	background-color: white;
	color: black;
	text-decoration: none;
}
</style>

The other example calls the SharePoint API's (the list svc - I'd change that to use the newer _api/web/ API) and puts the data into a table on the page - this is very old so definitely needs some work / rewriting:

<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");
}
   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>

Then the HTML / CSS:

<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> 

This example uses jQuery, knockout-3.1.0.js and ko.sp-1.0.min.Ex.js so these will need to be loaded - but I'd really recommend not using this example code - it is very old but I've added it here to give you some ideas.

 

Both of these are just samples (very old samples!) to give you some ideas - they are provided as is with no warranties etc. 

Hope that helps

Paul