Freigeben über


Erstellen eines auf SharePoint gehosteten Project Server-Add-Ins

Von den drei Arten von Apps, die Sie für Project Online erstellen können (automatisch gehostet, vom Anbieter gehostet und SharePoint gehostet), ist die von SharePoint gehostete App die einfachste Zu erstellen und bereitzustellen. Eine von SharePoint gehostete App erfordert keine OAuth-Authentifizierung und verwendet weder Azure noch erfordert die Wartung einer lokalen Website für die vom Anbieter gehosteten Ressourcen. Die App für SharePoint 2013-Vorlage in Visual Studio ist ein praktisches Framework für die Entwicklung von Apps, die im Office Store veröffentlicht und verkauft oder in einem privaten App-Katalog in SharePoint bereitgestellt werden können.

In Project ist statusing ein Prozess, bei dem ein Teammitglied die Seite Aufgaben in Project Web App verwenden kann, um die status eines zugewiesenen Vorgangs zu übermitteln, z. B. die Anzahl der Arbeitsstunden, die an jedem Tag einer Woche mit der Arbeit an dem Vorgang verbracht wurden. Der Zuordnungsbesitzer (in der Regel der Projektmanager) kann die status genehmigen oder ablehnen. Wenn die status genehmigt wird, berechnet Project den Zeitplan neu. Die QuickStatus-App zeigt zugewiesene Aufgaben an, bei denen der Benutzer schnell den Prozentsatz der Abgeschlossenen aktualisieren und status der ausgewählten Zuweisungen zur Genehmigung übermitteln kann. Obwohl die Seite Aufgaben in Project Web App viel mehr Funktionen bietet, ist die QuickStatus-App ein Beispiel, das eine vereinfachte Benutzeroberfläche bietet.

Die QuickStatus-App ist ein Beispiel für Entwickler. es ist nicht für die Verwendung in einer Produktionsumgebung vorgesehen. Der Hauptzweck besteht darin, ein Beispiel für die App-Entwicklung für Project Online zu zeigen und nicht eine voll funktionsfähige Statusing-App zu erstellen. Einen besseren Ansatz für die Statusierung finden Sie in der Empfehlung unter Nächste Schritte.

Allgemeine Informationen zur Statusierung finden Sie unter Vorgangsstatus. Weitere Informationen zum Entwickeln von Add-Ins für SharePoint und Project Server finden Sie unter SharePoint-Add-Ins.

Voraussetzungen für das Erstellen einer App für Project Server 2013

Um relativ einfache Apps zu entwickeln, die für Project Online oder eine lokale Installation von Project Server 2013 bereitgestellt werden können, können Sie napa verwenden, das eine Onlineentwicklungsumgebung bereitstellt. Für komplexere Apps, das Ändern des Project Web App-Menübands und das einfachere Debuggen während der Entwicklung können Sie Visual Studio 2012 oder Visual Studio 2013 verwenden. Bei einer lokalen Installation können Sie beispielsweise die Entwurfsdatentabellen manuell auf Änderungen in der Project Server-Datenbank überprüfen. In diesem Artikel erfahren Sie, wie Sie die App-Entwicklung mit Visual Studio durchführen.

Für die Entwicklung von Project Server-Apps mit Visual Studio ist Folgendes erforderlich:

  • Stellen Sie sicher, dass Sie die neuesten Service Packs und Windows-Updates auf dem lokalen Entwicklungscomputer installiert haben. Als Betriebssystem kann Windows 7, Windows 8, Windows Server 2008 oder Windows Server 2012 verwendet werden.

  • Sie müssen über einen Computer verfügen, auf dem SharePoint Server 2013 und Project Server 2013 installiert sind, auf dem der Computer für die App-Isolation und das Querladen von Apps konfiguriert ist. Durch das Querladen kann Visual Studio die App vorübergehend zum Debuggen installieren. Sie können eine lokale Installation von SharePoint und Project Server verwenden. Weitere Informationen finden Sie unter Einrichten einer lokalen Entwicklungsumgebung für Apps für SharePoint.

    Hinweis

    Konfigurieren Sie für eine lokale Installation eine isolierte App-Domäne, bevor Sie einen Unternehmens-App-Katalog erstellen.

  • Bei dem Entwicklungscomputer kann es sich um einen Remotecomputer handeln, auf dem Office Developer Tools für Visual Studio 2012 installiert ist. Stellen Sie sicher, dass Sie die neueste Version installiert haben. Weitere Informationen finden Sie im Abschnitt Tools der Downloads für Apps für Office und SharePoint.

  • Vergewissern Sie sich, dass die Project Web App-instance, die Sie für Die Entwicklung und Tests verwenden, im Browser zugänglich ist.

Informationen zur Verwendung der Onlinetools finden Sie unter Einrichten einer Entwicklungsumgebung für SharePoint-Add-Ins in Microsoft 365. Eine exemplarische Vorgehensweise zum Erstellen einer einfachen App für Project Server, die die Onlinetools verwendet, finden Sie in der EPMSource-Blogreihe Erstellen Ihrer ersten Project Server-App.

Verwenden von Visual Studio zum Erstellen einer Project Server-App

Office Developer Tools für Visual Studio 2012 enthält eine Vorlage für SharePoint-Apps, die mit Project Server 2013 verwendet werden kann. Wenn Sie eine App-Lösung erstellen, enthält die Projektmappe die folgenden Dateien für Ihren benutzerdefinierten Code:

  • AppManifest.xml enthält Einstellungen für den App-Titel, den Berechtigungsanforderungsbereich und andere Eigenschaften. Prozedur 1 enthält Schritte zum Festlegen der Eigenschaften mithilfe des Manifest-Designer.

  • Default.aspx im Ordner Pages ist die Standard Seite der App. In Prozedur 2 wird gezeigt, wie HTML5-Inhalt für die QuickStatus-App hinzugefügt wird.

  • App.js im Ordner Scripts ist die primäre Datei für den benutzerdefinierten JavaScript-Code. In Prozedur 3 wird der JavaScript-Code für die QuickStatus-App erläutert.

    Wenn Sie kommerzielle Steuerelemente hinzufügen, z. B. ein jQuery-basiertes Raster oder eine Datumsauswahl, können Sie Verweise auf zusätzliche JavaScript-Dateien in der Default.aspx-Datei hinzufügen.

  • App.css im Ordner Inhalt ist die primäre Datei für benutzerdefinierte CSS3-Formatvorlagen. Prozedur 2 und Prozedur 3 enthalten Informationen zu CSS-Formatvorlagen (Cascading Stylesheets) für die QuickStatus-App . Sie können Verweise auf zusätzliche CSS-Dateien in der Default.aspx-Datei hinzufügen.

  • AppIcon.png im Ordner Bilder ist das 96 x 96-Symbol, das die App im Office Store oder im App-Katalog anzeigt.

Zum Ändern des Project Web App-Menübands können Sie eine benutzerdefinierte Menübandaktion hinzufügen. Der Abschnitt Beispielcode für die QuickStatus-App enthält den vollständigen Code für die geänderten dateien Default.aspx, App.js, App.css, Elements.xml und AppManifest.xml.

Vorgehensweise 1: So erstellen Sie ein App-Projekt in Visual Studio

  1. Führen Sie Visual Studio 2012 als Administrator aus, und klicken Sie dann auf der Startseite auf Neues Projekt .

  2. Erweitern Sie im Dialogfeld Neues Projekt die Knoten Vorlagen, Visual C# und Office/SharePoint , und wählen Sie dann Apps aus. Verwenden Sie die Standard-.NET Framework 4.5 in der Dropdownliste Zielframework oben im mittleren Bereich, und wählen Sie dann App für SharePoint 2013 aus (siehe Abbildung 1).

  3. Geben Sie im Feld Name den Namen QuickStatus ein, navigieren Sie zu dem Speicherort, an dem Sie die App speichern möchten, und wählen Sie dann OK aus.

    Abbildung 1: Erstellen einer Project Server-App in Visual Studio

    Erstellen einer Project Server-App in Visual Studio

  4. Füllen Sie im Dialogfeld Neue App für SharePoint die folgenden drei Felder aus:

    • Geben Sie im oberen Textfeld den Namen ein, den die App in Project Web App anzeigen soll. Geben Sie beispielsweise Quick Status Update ein.

    • Geben Sie für die Website, die zum Debuggen verwendet werden soll, die URL des Project Web App-instance ein. Geben Sie beispielsweise ein https://ServerName/ProjectServerName (ersetzen Sie ServerName und ProjectServerName durch Ihre eigenen Werte), und wählen Sie dann Überprüfen aus. Wenn alles gut geht, zeigt Visual Studio Die Verbindung erfolgreich an. Wenn eine Fehlermeldung angezeigt wird, stellen Sie sicher, dass die Project Web App-URL korrekt ist und dass der Project Server-Computer für die App-Isolation und das Querladen von Apps konfiguriert ist. Weitere Informationen finden Sie im Abschnitt Voraussetzungen zum Erstellen einer App für Project Server 2013 .

    • Wählen Sie in der Dropdownliste Wie möchten Sie Ihre App für SharePoint hosten ? die Option SharePoint-gehostet aus.

    Achtung

    Wenn Sie versehentlich den standardmäßigen vom Anbieter gehosteten Projekttyp auswählen, erstellt Visual Studio zwei Projekte in der Projektmappe: ein QuickStatus-Projekt und ein QuickStatusWeb-Projekt . Wenn zwei Projekte angezeigt werden, löschen Sie diese Projektmappe, und beginnen Sie erneut.

  5. Wählen Sie OK aus, um die QuickStatus-Projektmappe , das QuickStatus-Projekt und die Standarddateien zu erstellen.

  6. Öffnen Sie die Ansicht Manifest Designer (doppelklicken Sie z. B. auf die AppManifest.xml Datei). Auf der Registerkarte Allgemein sollte im Textfeld Titel der App-Name angezeigt werden, den Sie in Schritt 4 eingegeben haben. Wählen Sie die Registerkarte Berechtigungen aus, um die folgenden Berechtigungsanforderungen für die App hinzuzufügen (siehe Abbildung 2):

    • Wählen Sie in der ersten Zeile der Liste Berechtigungsanforderungen in der Spalte Bereich in der Dropdownliste Statusing aus. Wählen Sie in der Spalte Berechtigung die Option SubmitStatus aus.

    • Fügen Sie eine Zeile hinzu, in der der Bereichmehrere Projekte und die Berechtigung"Lesen" lautet.

    Abbildung 2: Festlegen des Berechtigungsumfangs für eine Statuserfassungs-App

    Festlegen des Berechtigungsbereichs für eine Status-App

Die QuickStatus-App ermöglicht es einem Project Web App-Benutzer, Zuweisungen für diesen Benutzer aus mehreren Projekten zu lesen, den Prozentsatz der Zuweisung abgeschlossen zu ändern und die Aktualisierung zu übermitteln. Die anderen Berechtigungsanforderungsbereiche, die in der Dropdownliste in Abbildung 2 angezeigt werden, sind für diese App nicht erforderlich. Die Berechtigungsanforderungsbereiche sind die Berechtigungen, die die App im Namen des Benutzers anfordert. Wenn der Benutzer nicht über diese Berechtigungen in Project Web App verfügt, wird die App nicht ausgeführt. Eine App kann über mehrere Berechtigungsanforderungsbereiche verfügen, einschließlich der bereiche für andere SharePoint-Berechtigungen, sollte aber nur das für die App-Funktionalität erforderliche Minimum aufweisen. Im Folgenden sind die Berechtigungsanforderungsbereiche aufgeführt, die sich auf Project Server beziehen:

  • Enterprise-Ressourcen: Resource Manager-Berechtigungen zum Lesen oder Schreiben von Informationen zu anderen Project Web App-Benutzern.

  • Mehrere Projekte: Lesen oder Schreiben in mehr als einem Projekt, in dem der Benutzer über die angeforderten Berechtigungen verfügt.

  • Project Server: Erfordert, dass der App-Benutzer über Administratorberechtigungen für Project Web App verfügt.

  • Berichterstellung: Lesen Sie den ProjectData-OData-Dienst für Project Web App (erfordert nur die Anmeldeberechtigung für Project Web App).

  • Einzelnes Projekt: Lesen oder Schreiben in ein Projekt, in dem der Benutzer über die angeforderten Berechtigungen verfügt.

  • Statuserstellung: Übermitteln Sie Aktualisierungen für status von Aufgaben, z. B. geleistete Zeiten, Abgeschlossene Prozent und neue Aufgaben.

  • Workflow: Wenn der Benutzer über die Berechtigung zum Ausführen von Project Server-Workflows verfügt, wird die App dann mit erhöhten Berechtigungen für den Workflow ausgeführt.

Weitere Informationen zu Berechtigungsanforderungsbereichen für Project Server 2013 finden Sie im Abschnitt Project Apps in Updates für Entwickler in Project 2013 und App-Berechtigungen in SharePoint 2013.

Erstellen des HTML-Inhalts für die QuickStatus-App

Bevor Sie mit dem Codieren des HTML-Inhalts beginnen, entwerfen Sie die Benutzeroberfläche und Benutzeroberfläche für die QuickStatus-App (Abbildung 3 zeigt ein Beispiel für die fertige Seite). Ein Design kann auch eine Gliederung der JavaScript-Funktionen enthalten, die mit dem HTML-Code interagieren. Allgemeine Informationen finden Sie unter UX-Design für Apps in SharePoint 2013.

Abbildung 3: Design der QuickStatus-App-Seite

Entwurf der QuickStatus-App-Seite

Die App zeigt oben den Anzeigenamen an, der den Wert des Title-Elements in AppManifest.xml.

Standardmäßig verwendet die Seite HTML5. Im Folgenden finden Sie die HTML-Standardelemente für die Standard UI-Objekte, die die QuickStatus-App im Textkörper der Seite enthält:

  • Ein Formularelement enthält alle anderen Benutzeroberflächenelemente.

  • Ein Fieldset-Element erstellt einen Container und einen Rahmen für die Tabelle der Zuordnungen. Das untergeordnete Legendenelement stellt eine Bezeichnung für den Container bereit.

  • Ein Tabellenelement enthält eine Untertitel und nur eine Tabellenüberschrift. JavaScript-Funktionen ändern die Tabelle Untertitel und fügen Zeilen für die Zuweisungen hinzu.

    Hinweis

    Zum einfachen Hinzufügen von Paging und Sortierung würde eine Produktions-App wahrscheinlich ein kommerzielles jQuery-basiertes Rastersteuerelement anstelle einer Tabelle verwenden.

    Die Tabelle enthält Spalten für den Projektnamen, den Vorgangsnamen mit einem Kontrollkästchen, die tatsächliche Arbeit, den Prozentsatz der Abgeschlossenen, die verbleibende Arbeit und den Endtermin der Zuordnung. JavaScript-Funktionen erstellen das Kontrollkästchen und das Texteingabefeld für den Prozentsatz der Fertigstellung der einzelnen Aufgaben.

  • Ein Eingabeelement für ein Textfeld legt den Prozentsatz abgeschlossen für alle ausgewählten Zuweisungen fest.

  • Ein Schaltflächenelement übermittelt die status Änderungen.

  • Ein Schaltflächenelement aktualisiert die Seite.

  • Ein Schaltflächenelement beendet die App und kehrt zur Seite Aufgaben in Project Web App zurück.

Das untere Textfeld und die Schaltflächenelemente befinden sich in div-Elementen , sodass CSS die Position und Darstellung der UI-Objekte problemlos verwalten kann. Eine JavaScript-Funktion fügt am unteren Rand der Seite einen Absatz hinzu, der Ergebnisse für Erfolg oder Fehler der status Update enthält.

Vorgehensweise 2: So erstellen Sie den HTML-Inhalt

  1. Öffnen Sie in Visual Studio die datei Default.aspx.

    Die Datei enthält zwei asp:Content-Elemente : Das -Element mit dem ContentPlaceHolderID="PlaceHolderAdditionalPageHead" -Attribut wird innerhalb der Seitenkopfzeile hinzugefügt, und das -Element mit dem ContentPlaceHolderID="PlaceHolderMain" -Attribut wird im Textkörperelement der Seite platziert.

  2. Fügen Sie im <asp:Content ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server"> Steuerelement für die Seitenkopfzeile einen Verweis auf die PS.js-Datei auf dem Project Server-Computer hinzu. Zum Testen und Debuggen können Sie PS.debug.js verwenden.

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

    Die App-Infrastruktur verwendet das /_layouts/15/ virtuelle Verzeichnis für die SharePoint-Website in IIS. Die physische Datei ist %ProgramFiles%\Common Files\Microsoft Shared\Web Server Extensions\15\TEMPLATE\LAYOUTS\PS.debug.js.

    Hinweis

    Bevor Sie die App für die Produktion bereitstellen, entfernen Sie .debug aus den Skriptverweisen, um die Leistung zu verbessern.

  3. Löschen Sie im <asp:Content ContentPlaceHolderID="PlaceHolderMain" runat="server"> Steuerelement für den Seitentext das generierte div-Element , und fügen Sie dann den HTML-Code für die UI-Objekte hinzu. Das Table-Element enthält nur eine Kopfzeile. Die Spalte Aufgabenname enthält ein Kontrollkästchen-Eingabesteuerelement. Text für das Untertitel-Element wird durch den onGetUserNameSuccess-Rückruf für die getUserInfo-Funktion in der App.js-Datei ersetzt.

    <form>
        <fieldset>
        <legend>Select assigned tasks</legend>
        <table id="assignmentsTable">
            <caption id="tableCaption">Replace caption</caption>
            <thead>
            <tr id="headerRow">
                <th>Project name</th>
                <th><input type="checkbox" id="headercheckbox" checked="checked" />Task name</th>
                <th>Actual work</th>
                <th>% complete</th>
                <th>Remaining work</th>
                <th>Due date</th>
            </tr>
            </thead>
        </table>
        </fieldset>
        <div id="inputPercentComplete" >
        Set percent complete for all selected assignments, or leave this
        <br /> field blank and set percent complete for individual assignments: 
        <input type="text" name="percentComplete" id="pctComplete" size="4"  maxlength="4" />
        </div>
        <div id="submitResult">
        <p><button id="btnSubmitUpdate" type="button" class="bottomButtons" ></button></p>
        <p id="message"></p>
        </div>
        <div id="refreshPage">
        <p><button id="btnRefresh" type="button" class="bottomButtons" >Refresh</button></p>
        </div>
        <div id="exitPage">
        <p><button id="btnExit" type="button" class="bottomButtons" >Exit</button></p>
        </div>
    </form>
    
  4. Fügen Sie in der App.css-Datei CSS-Code für die Position und Darstellung der UI-Elemente hinzu. Den vollständigen CSS-Code der QuickStatus-App finden Sie im Abschnitt Beispielcode für die QuickStatus-App .

In Prozedur 3 werden die JavaScript-Funktionen hinzugefügt, um die Zuweisungen zu lesen und die Tabellenzeilen zu erstellen sowie die Zuweisung in Prozent abgeschlossen zu ändern und zu aktualisieren. Die eigentlichen Schritte sind iterativer bei der Entwicklung einer App, bei der Sie alternativ einen Teil des HTML-Codes erstellen, verwandte Stile und JavaScript-Funktionen hinzufügen und testen, HTML-Code ändern oder hinzufügen und dann den Prozess wiederholen.

Erstellen der JavaScript-Funktionen für die QuickStatus-App

Die Visual Studio-Vorlage für eine SharePoint-App enthält die App.js-Datei, die Standardinitialisierungscode enthält, der den SharePoint-Clientkontext abruft und grundlegende Get- und Set-Aktionen für die App-Seite veranschaulicht. Der JavaScript-Namespace für die clientseitige sharePoint-SP.js-Bibliothek ist SP. Da eine Project Server-App die PS.js-Bibliothek verwendet, verwendet die App den PS-Namespace , um den Clientkontext abzurufen und auf JSOM für Project Server zuzugreifen.

JavaScript-Funktionen in der QuickStatus-App umfassen Folgendes:

  • Der Document Ready-Ereignishandler wird ausgeführt, wenn das Dokumentobjektmodell (DOM) instanziiert wird. Der ready-Ereignishandler führt die folgenden vier Schritte aus:

    1. Initialisiert die globale projContext-Variable mit dem Clientkontext für project Server JSOM und der globalen Variablen pwaWeb .

    2. Ruft die getUserInfo-Funktion auf, um die globale Variable projUser zu initialisieren.

    3. Ruft die getAssignments-Funktion auf , die angegebene Zuweisungsdaten für den Benutzer abruft.

    4. Bindet Click-Ereignishandler an das Kontrollkästchen tabellenüberschriften und an die Kontrollkästchen in jeder Zeile der Tabelle. Die Click-Ereignishandler verwalten das aktivierte Attribut der Kontrollkästchen, wenn der Benutzer ein beliebiges Kontrollkästchen in der Tabelle aktiviert oder deaktiviert.

  • Wenn die getAssignments-Funktion erfolgreich ist, wird die onGetAssignmentsSuccess-Funktion aufgerufen. Diese Funktion fügt für jede Zuweisung eine Zeile in die Tabelle ein, initialisiert die HTML-Steuerelemente in jeder Zeile und initialisiert dann die unteren Schaltflächeneigenschaften.

  • Der onClick-Ereignishandlerfür die Update-Schaltfläche ruft die updateAssignments-Funktion auf . Diese Funktion ruft den Prozentwert abgeschlossen ab, der auf jede ausgewählte Zuweisung angewendet wird. Oder wenn das Textfeld prozentvoll abgeschlossen leer ist, ruft die Funktion den prozentsatz abgeschlossen jeder ausgewählten Zuweisung in der Tabelle ab. Die updateAssignments-Funktion speichert und übermittelt dann die status Updates und schreibt eine Meldung zu den Ergebnissen am unteren Rand der Seite.

Verfahren 3. So erstellen Sie die JavaScript-Funktionen

  1. Öffnen Sie in Visual Studio die App.js-Datei, und löschen Sie dann den gesamten Inhalt der Datei.

  2. Fügen Sie die globalen Variablen und den Document Ready-Ereignishandler hinzu. Auf das Dokumentobjekt wird mithilfe einer jQuery-Funktion zugegriffen.

    Der Click-Ereignishandler für die Tabellenüberschrift legt den aktivierten Status der Zeilenkontrollkästchen fest. Wenn alle Zeilenkontrollkästchen aktiviert oder alle deaktiviert sind, legt der Click-Ereignishandler für die Zeilenkontrollkästchen den aktivierten Status des Kopfzeilen-Kontrollkästchens fest. Die Click-Ereignishandler legen auch die Ergebnismeldung am unteren Rand der Seite auf eine leere Zeichenfolge fest.

     var projContext;
     var pwaWeb;
     var projUser;
     // This code runs when the DOM is ready and creates a ProjectContext object.
     // The ProjectContext object is required to use the JSOM for Project Server.
     $(document).ready(function () {
         projContext = PS.ProjectContext.get_current();
         pwaWeb = projContext.get_web();
         getUserInfo();
         getAssignments();
         // Bind a click event handler to the table header check box, which sets the row check boxes
         // to the checked state of the header check box, and sets the results message to an empty string.
         $('#headercheckbox').live('click', function (event) {
             $('input:checkbox:not(#headercheckbox)').attr('checked', this.checked);
             $get("message").innerText = "";
         });
         // Bind a click event handler to the row check boxes. If any row check box is cleared, clear
         // the header check box. If all of the row check boxes are selected, select the header check box.
         $('input:checkbox:not(#headercheckbox)').live('click', function (event) {
             var isChecked = true;
             $('input:checkbox:not(#headercheckbox)').each(function () {
                 if (this.checked == false) isChecked = false;
                 $get("message").innerText = "";
             });
             $("#headercheckbox").attr('checked', isChecked);
         });
     });
    
  3. Fügen Sie die getUserInfo-Funktion hinzu, die onGetUserNameSuccess aufruft , wenn die Abfrage erfolgreich ist. Die onGetUserNameSuccess-Funktion ersetzt den Inhalt des Untertitel Absatzes durch eine Tabelle Untertitel, die den Benutzernamen enthält.

         // Get information about the current user.
         function getUserInfo() {
             projUser = pwaWeb.get_currentUser();
             projContext.load(projUser);
             projContext.executeQueryAsync(onGetUserNameSuccess,
                 // Anonymous function to execute if getUserInfo fails.
                 function (sender, args) {
                     alert('Failed to get user name. Error: ' + args.get_message());
             });
         } 
         // This function is executed if the getUserInfo call is successful.
         function onGetUserNameSuccess() {
             var prefaceInfo = 'Assignments for ' + projUser.get_title();
             $('#tableCaption').text(prefaceInfo);
         }
    
  4. Fügen Sie die getAssignments-Funktion hinzu, die onGetAssignmentsSuccess aufruft (siehe Schritt 5), wenn die Zuweisungsabfrage erfolgreich ist. Die Option Include schränkt die Abfrage so ein, dass nur die angegebenen Felder zurückgegeben werden.

     // Get the collection of assignments for the current user.
     function getAssignments() {
         assignments = PS.EnterpriseResource.getSelf(projContext).get_assignments();
         // Register the request that you want to run on the server. The optional "Include" parameter 
         // requests only the specified properties for each assignment in the collection.
         projContext.load(assignments,
             'Include(Project, Name, ActualWork, ActualWorkMilliseconds, PercentComplete, RemainingWork, Finish, Task)');
         // Run the request on the server.
         projContext.executeQueryAsync(onGetAssignmentsSuccess,
             // Anonymous function to execute if getAssignments fails.
             function (sender, args) {
                 alert('Failed to get assignments. Error: ' + args.get_message());
             });
     }
    
  5. Fügen Sie die onGetAssignmentsSuccess-Funktion hinzu, die der Tabelle eine Zeile für jede Zuweisung hinzufügt. Die Variable prevProjName wird verwendet, um zu bestimmen, ob eine Zeile für ein anderes Projekt ist. Wenn ja, wird der Projektname fett formatiert angezeigt. Andernfalls wird der Projektname auf eine leere Zeichenfolge festgelegt.

    Hinweis

    Das JSOM enthält keine TimeSpan-Eigenschaften , die das CSOM enthält, z. B. ActualWorkTimeSpan. Stattdessen verwendet das JSOM Eigenschaften für die Anzahl von Millisekunden, z. B . den PS. StatusAssignment.actualWorkMilliseconds-Eigenschaft . Die Methode zum Abrufen dieser Eigenschaft ist get_actualWorkMilliseconds, die einen ganzzahligen Wert zurückgibt. > Die get_actualWork-Methode gibt eine Zeichenfolge wie "3h" zurück. Sie können beide Werte in der QuickStatus-App verwenden, aber anders anzeigen. Die Zuweisungsabfrage enthält beide Eigenschaften, sodass Sie den Wert während des Debuggens testen können. Wenn Sie die variable actualWork entfernen, können Sie auch die ActualWork-Eigenschaft in der Zuweisungsabfrage entfernen.

    Schließlich initialisiert die onGetAssignmentsSuccess-Funktion die Schaltfläche Aktualisieren und die Schaltfläche Aktualisieren mit Click-Ereignishandlern. Der Textwert der Schaltfläche Aktualisieren kann auch im HTML-Code festgelegt werden.

         // Get the enumerator, iterate through the assignment collection, 
         // and add each assignment to the table.
         function onGetAssignmentsSuccess(sender, args) {
             if (assignments.get_count() > 0) {
                 var assignmentsEnumerator = assignments.getEnumerator();
                 var projName = "";
                 var prevProjName = "3D2A8045-4920-4B31-B3E7-9D0C5195FC70"; // Any unique name.
                 var taskNum = 0;
                 var chkTask = "";
                 var txtPctComplete = "";
                 // Constants for creating input controls in the table.
                 var INPUTCHK = '<input type="checkbox" class="chkTask" checked="checked" id="chk';
                 var LBLCHK = '<label for="chk';
                 var INPUTTXT = '<input type="text" size="4"  maxlength="4" class="txtPctComplete" id="txt';
                 while (assignmentsEnumerator.moveNext()) {
                     var statusAssignment = assignmentsEnumerator.get_current();
                     projName = statusAssignment.get_project().get_name();
                     // Get an integer, such as 3600000.
                     var actualWorkMilliseconds = statusAssignment.get_actualWorkMilliseconds(); 
                     // Get a string, such as "1h". Not used here.
                     var actualWork = statusAssignment.get_actualWork();
                     if (projName === prevProjName) {
                         projName = "";
                     }
                     prevProjName = statusAssignment.get_project().get_name();
                     // Create a row for the assignment information.
                     var row = assignmentsTable.insertRow();
                     taskNum++;
                     // Create an HTML string with a check box and task name label, for example:
                     // <input type="checkbox" class="chkTask" checked="checked" id="chk1" /> <label for="chk1">Task 1</label>
                     chkTask = INPUTCHK + taskNum + '" /> ' + LBLCHK + taskNum + '">' 
                         + statusAssignment.get_name() + '</label>';
                     txtPctComplete = INPUTTXT + taskNum + '" />';
                     // Insert cells for the assignment properties.
                     row.insertCell().innerHTML = '<strong>' + projName + '</strong>';
                     row.insertCell().innerHTML = chkTask;
                     row.insertCell().innerText = actualWorkMilliseconds / 3600000 + 'h';
                     row.insertCell().innerHTML = txtPctComplete;
                     row.insertCell().innerText = statusAssignment.get_remainingWork();
                     row.insertCell().innerText = statusAssignment.get_finish();
                     // Initialize the percent complete cell.
                     $get("txt" + taskNum).innerText = statusAssignment.get_percentComplete() + '%'
                 }
             }
             else {
                 $('p#message').attr('style', 'color: #0f3fdb');     // Blue text.
                 $get("message").innerText = projUser.get_title() + ' has no assignments'
             }
             // Initialize the button properties.
             $get("btnSubmitUpdate").onclick = function() { updateAssignments(); };
             $get("btnSubmitUpdate").innerText = 'Update';
             $get('btnRefresh').onclick = function () { window.location.reload(true); };
             $get('btnExit').onclick = function () { exitToPwa(); };
         }
    
  6. Fügen Sie den Click-Ereignishandler updateAssignments für die Schaltfläche Aktualisieren hinzu. Wenn der Benutzer einen Wert für den Prozentsatz der Fertigstellung einer Aufgabe ändert oder einen Wert im Textfeld percentComplete hinzufügt, kann der Wert in verschiedenen Formaten eingegeben werden, z. B. "60", "60%" oder "60 %". Die getNumericValue-Methode gibt den numerischen Wert des Eingabetexts zurück.

    Hinweis

    In einer App, die für die Verwendung in der Produktion konzipiert ist, sollten Eingabewerte für numerische Informationen die Feldvalidierung und zusätzliche Fehlerüberprüfung enthalten.

    Das UpdateAssignments-Beispiel enthält einige grundlegende Fehlerüberprüfungen und zeigt Informationen im Meldungsabsatz am unteren Rand der Seite an – grün, wenn die Updateabfrage erfolgreich ist, und rot, wenn ein Eingabefehler vorliegt oder die Updateabfrage nicht erfolgreich ist.

    Vor der Verwendung der submitAllStatusUpdates-Methode muss die App die Updates mithilfe des PS auf dem Server speichern . StatusAssignmentCollection.update-Methode .

         // Update all checked assignments. If the bottom percent complete field is blank,
         // use the value in the % complete field of each selected row in the table.
         function updateAssignments() {
             // Get percent complete from the bottom text box.
             var pctCompleteMain = getNumericValue($('#pctComplete').val()).trim();
             var pctComplete = pctCompleteMain;
             var assignmentsEnumerator = assignments.getEnumerator();
             var taskNum = 0;
             var taskRow = "";
             var indexPercent = "";
             var doSubmit = true;
             while (assignmentsEnumerator.moveNext()) {
                 var pctCompleteRow = "";
                 taskRow = "chk" + ++taskNum;
                 if ($get(taskRow).checked) {
                     var statusAssignment = assignmentsEnumerator.get_current();
                     if (pctCompleteMain === "") {
                         // Get percent complete from the text box field in the table row.
                         pctCompleteRow = getNumericValue($('#txt' + taskNum).val());
                         pctComplete = pctCompleteRow;
                     }
                     // If both percent complete fields are empty, show an error.
                     if (pctCompleteMain === "" && pctCompleteRow === "") {
                         $('p#message').attr('style', 'color: #e11500');     // Red text.
                         $get("message").innerHTML =
                             '<b>Error:</b> Both <i>Percent complete</i> fields are empty, in row '
                             + taskNum
                             + ' and in the bottom textbox.<br/>One of those fields must have a valid percent.'
                             + '<p>Please refresh the page and try again.</p>';
                         doSubmit = false;
                         taskNum = 0;
                         break;
                     }
                     if (doSubmit) statusAssignment.set_percentComplete(pctComplete);
                 }
             } 
             // Save and submit the assignment updates.
             if (doSubmit) {
                 assignments.update();
                 assignments.submitAllStatusUpdates();
                 projContext.executeQueryAsync(function (source, args) {
                     $('p#message').attr('style', 'color: #0faa0d');     // Green text.
                     $get("message").innerText = 'Assignments have been updated.';
                 }, function (source, args) {
                     $('p#message').attr('style', 'color: #e11500');     // Red text.
                     $get("message").innerText = 'Error updating assignments: ' + args.get_message();
                 });
             }
         }
         // Get the numeric part for percent complete, from a string. For example, with "20 %", return "20".
         function getNumericValue(pctComplete) {
             pctComplete = pctComplete.trim();
             pctComplete = pctComplete.replace(/ /g, "");    // Remove interior spaces.
             indexPercent = pctComplete.indexOf('%', 0);
             if (indexPercent > -1) pctComplete = pctComplete.substring(0, indexPercent);
             return pctComplete;
         }
    
  7. Fügen Sie die ExitToPwa-Funktion hinzu, die den Abfragezeichenfolgenparameter SPHostUrl für die URL der Project Web App-Hostwebsite verwendet. Um zurück zur Seite Aufgaben zu navigieren, fügen Sie an die URL an "/Tasks.aspx" . Beispielsweise würde die SpHostUrl-Variable auf https://ServerName/ProjectServerName/Tasks.aspxfestgelegt werden.

    Die getQueryStringParameter-Funktion teilt die URL der QuickStatus-Seite auf, um den angegebenen Parameter in den URL-Optionen zu extrahieren und zurückzugeben. Es folgt ein Beispiel für das Dokument. URL-Wert für das QuickStatus-Dokument (alle in einer Zeile):

     https://app-ef98082fa37e3c.servername.officeapps.selfhost.corp.microsoft.com/pwa/
         QuickStatus/Pages/Default.aspx
         ?SPHostUrl=https%3A%2F%2Fsphvm%2D85178%2Fpwa
         &SPLanguage=en%2DUS
         &SPClientTag=1
         &SPProductNumber=15%2E0%2E4420%2E1022
         &SPAppWebUrl=https%3A%2F%2Fapp%2Def98082fa37e3c%2Eservername
             %2Eofficeapps%2Eselfhost%2Ecorp%2Emicrosoft%2Ecom%2Fpwa%2FQuickStatus
    

    Für die vorherige URL gibt die getQueryStringParameter-Funktion den SpHostUrl-Abfragezeichenfolgenwert zurück. https://ServerName/pwa

         // Exit the QuickStatus page and go back to the Tasks page in Project Web App.
         function exitToPwa() {
             // Get the SharePoint host URL, which is the top page of PWA, and add the Tasks page.
             var spHostUrl = decodeURIComponent(getQueryStringParameter('SPHostUrl'))
                             + "/Tasks.aspx";
             // Set the top window for the QuickStatus IFrame to the Tasks page.
             window.top.location.href = spHostUrl;
         }
         // Get a specified query string parameter from the {StandardTokens} URL option string.
         function getQueryStringParameter(urlParameterKey) {
             var docUrl = document.URL;
             var params = docUrl.split('?')[1].split('&');
             for (var i = 0; i < params.length; i++) {
                 var theParam = params[i].split('=');
                 if (theParam[0] == urlParameterKey)
                     return decodeURIComponent(theParam[1]);
             }
         }
    

Wenn Sie die QuickStatus-App an diesem Punkt veröffentlichen und zu Project Web App hinzufügen, kann die App auf der Seite Websiteinhalte ausgeführt werden, aber sie ist für Benutzer nicht einfach verfügbar. Damit Benutzer die App finden und ausführen können, können Sie dem Menüband auf der Seite Aufgaben eine Entsprechende Schaltfläche hinzufügen. Prozedur 4 zeigt, wie eine benutzerdefinierte Menübandaktion hinzugefügt wird.

Hinzufügen einer benutzerdefinierten Menübandaktion

Menübandregisterkarten, Gruppen und Steuerelemente für Project Web App werden in der pwaribbon.xml-Datei angegeben, die [Program Files]\Common Files\Microsoft Shared\Web Server Extensions\15\TEMPLATE\FEATURES\PWARibbon\listtemplates im Verzeichnis auf dem Computer mit Project Server installiert ist. Um benutzerdefinierte Aktionen für das Project Web App-Menüband zu entwerfen, enthält der Project 2013 SDK-Download eine Kopie von pwaribbon.xml.

Project Web App verwendet verschiedene Menübanddefinitionen für die Seite Aufgaben, je nachdem, ob die Project Web App-instance den Einzeleintragsmodus verwendet, mit dem Benutzer Werte für die Arbeitszeittabelle und die Vorgangs-status eingeben können. Wenn Sie über Administratorberechtigungen für Project Web App verfügen, wählen Sie zum Bestimmen des Eingabemodus PWA-Einstellungen im Dropdownmenü einstellungen in der oberen rechten Ecke der Seite aus. Wählen Sie auf der Seite PWA-Einstellungen die Option Arbeitszeittabelleneinstellungen und Standardwerte aus, und sehen Sie sich dann das Kontrollkästchen Einzeleintragsmodus am unteren Rand der Seite an.

Wenn der Einzeleintragsmodus deaktiviert ist, wird das Menüband auf der Seite Aufgaben durch den Bereich "Meine Arbeit" in pwaribbon.xml definiert:

   <!-- REGION My Work Ribbon-->
   <CustomAction
      Id="Ribbon.ContextualTabs.MyWork"
      . . .

Wenn der Einzeleintragsmodus aktiviert ist, wird das Menüband der Seite Aufgaben durch den Bereich "Gebundener Modus" in pwaribbon.xml definiert:

   <!-- REGION Tied Mode Ribbon-->
   <CustomAction
      Id="Ribbon.ContextualTabs.TiedMode"
      . . .

Obwohl die Gruppen und Steuerelemente in den einzelnen Regionen ähnlich aussehen, kann ein Steuerelement für den gebundenen Modus eine andere Funktion als dasselbe Steuerelement für den nicht gebundenen Modus aufrufen. In Prozedur 4 wird gezeigt, wie Sie ein Schaltflächensteuerelement für die QuickStatus-App hinzufügen, wenn der Einzeleingabemodus deaktiviert ist (das Kontrollkästchen Einzeleingabemodus ist deaktiviert).

Hinweis

Allgemeine Informationen zum Hinzufügen benutzerdefinierter Aktionen zu einem Menüband oder einem Menü in einer SharePoint-Anwendung finden Sie unter Erstellen benutzerdefinierter Aktionen zum Bereitstellen mit Apps für SharePoint.

Prozedur 4. So fügen Sie der Seite Aufgaben eine benutzerdefinierte Menübandaktion hinzu

  1. Untersuchen Sie das Menüband auf der Seite Aufgaben in Project Web App. Wählen Sie im Menüband die Registerkarte AUFGABEN aus, und planen Sie, wie sie geändert werden soll. Es gibt sieben Gruppen, z. B . Übermitteln, Aufgaben und Zeitraum. Die Gruppe Senden verfügt über zwei Steuerelemente: die Schaltfläche Speichern und das Dropdownmenü Sendestatus . Sie können ein Steuerelement an einer beliebigen Stelle in einer Gruppe hinzufügen, eine Gruppe mit einem neuen Steuerelement an einer beliebigen Stelle auf der Registerkarte AUFGABEN hinzufügen oder eine weitere Menübandregisterkarte mit benutzerdefinierten Gruppen und Steuerelementen hinzufügen. In diesem Beispiel fügen wir der Gruppe Senden eine dritte Schaltfläche hinzu, in der die Schaltfläche die URL der QuickStatus-App aufruft.

  2. Klicken Sie im bereich Projektmappen-Explorer in Visual Studio mit der rechten Maustaste auf das Projekt QuickStatus, und fügen Sie dann ein neues Element hinzu. Wählen Sie im Dialogfeld Neues Element hinzufügen die Option Benutzerdefinierte Menübandaktion aus (siehe Abbildung 4). Nennen Sie beispielsweise die benutzerdefinierte Aktion RibbonQuickStatusAction, und wählen Sie dann Hinzufügen aus.

    Abbildung 4: Hinzufügen einer benutzerdefinierten Menübandaktion

    Hinzufügen einer benutzerdefinierten Menübandaktion

  3. Lassen Sie auf der ersten Seite des Assistenten zum Erstellen einer benutzerdefinierten Aktion für das Menüband die Option Hostweb ausgewählt, wählen Sie in der Dropdownliste für den benutzerdefinierten Aktionsbereich keine aus, und wählen Sie dann Weiter aus (siehe Abbildung 5). Die Elemente in den Dropdownlisten sind für SharePoint und nicht für Project Server relevant. Wir ersetzen den Großteil des generierten XML-Codes für die benutzerdefinierte Aktion, sodass er für Project Server gilt.

    Abbildung 5: Festlegen von Eigenschaften für die benutzerdefinierte Menübandaktion

    Angeben von Eigenschaften für die benutzerdefinierte Menübandaktion

  4. Übernehmen Sie auf der nächsten Seite des Assistenten zum Erstellen einer benutzerdefinierten Aktion für das Menüband alle Standardwerte für die Einstellungen, und wählen Sie dann Fertig stellen aus (siehe Abbildung 6). Visual Studio erstellt den Ordner RibbonQuickStatusAction , der eine Elements.xml Datei enthält.

    Abbildung 6 Festlegen der Einstellungen für ein Schaltflächensteuerelement

    Angeben der Einstellungen für ein Schaltflächensteuerelement

  5. Ändern Sie den generierten Standardcode in der Elements.xml-Datei für die benutzerdefinierte Menübandaktion. Es folgt der XML-Standardcode:

     <?xml version="1.0" encoding="utf-8"?>
     <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
         <CustomAction Id="21ea3aaf-79e5-4aac-9479-8eef14b4d9df.RibbonQuickStatusAction"
                     Location="CommandUI.Ribbon"
                     Sequence="10001"
                     Title="Invoke &apos;RibbonQuickStatusAction&apos; action">
         <CommandUIExtension>
             <!-- 
             Update the UI definitions below with the controls and the command actions
             that you want to enable for the custom action.
             -->
             <CommandUIDefinitions>
             <CommandUIDefinition Location="Ribbon.ListItem.Actions.Controls._children">
                 <Button Id="Ribbon.ListItem.Actions.RibbonQuickStatusActionButton"
                         Alt="Request RibbonQuickStatusAction"
                         Sequence="100"
                         Command="Invoke_RibbonQuickStatusActionButtonRequest"
                         LabelText="Request RibbonQuickStatusAction"
                         TemplateAlias="o1"
                         Image32by32="_layouts/15/images/placeholder32x32.png"
                         Image16by16="_layouts/15/images/placeholder16x16.png" />
             </CommandUIDefinition>
             </CommandUIDefinitions>
             <CommandUIHandlers>
             <CommandUIHandler Command="Invoke_RibbonQuickStatusActionButtonRequest"
                                 CommandAction="~appWebUrl/Pages/Default.aspx"/>
             </CommandUIHandlers>
         </CommandUIExtension >
         </CustomAction>
     </Elements>
    
    1. Löschen Sie im CustomAction-Element das Sequence-Attribut und das Title-Attribut .

    2. Um der Gruppe Submit ein Steuerelement hinzuzufügen, suchen Sie die erste Gruppe in der Ribbon.ContextualTabs.MyWork.Home.Groups Auflistung in der pwaribbon.xml Datei, die das Element ist, das beginnt, <Group Id="Ribbon.ContextualTabs.MyWork.Home.Page" Command="PageGroup" Sequence="10" Title="$Resources:pwafeatures,PAGE_PDP_CM_SUBMIT". Um der Gruppe Submit ein untergeordnetes Steuerelement hinzuzufügen, zeigt der folgende Code das richtige Location-Attribut des CommandUIDefinition-Elements in der Elements.xml-Datei an:

        <CommandUIDefinitions>
          <CommandUIDefinition Location="Ribbon.ContextualTabs.MyWork.Home.Page.Controls._children">
             . . .
          </CommandUIDefinition>
        </CommandUIDefinitions>
      
    3. Ändern Sie die Attributwerte des untergeordneten Button-Elements wie folgt:

           <Button Id="Ribbon.ContextualTabs.MyWork.Home.Page.QuickStatus"
                   Alt="Quick Status app"
                   Sequence="30"
                   Command="Invoke_QuickStatus"
                   LabelText="Quick Status"
                   TemplateAlias="o1"
                   Image16by16="_layouts/15/1033/images/ps16x16.png" 
                   Image16by16Left="-80"
                   Image16by16Top="-144"
                   Image32by32="_layouts/15/1033/images/ps32x32.png" 
                   Image32by32Left="-32"
                   Image32by32Top="-288" 
                   ToolTipTitle="QuickStatus"
                   ToolTipDescription="Run the QuickStatus app" />
      
      • Um die Schaltfläche zum dritten Steuerelement in der Gruppe zu machen, kann das Sequence-Attribut eine beliebige Zahl sein, die höher ist als der Sequence="20" Wert des vorhandenen Send Status-Steuerelements (bei dem es sich um ein FlyoutAnchor-Element in pwaribbon.xml handelt). Gemäß der Konvention sind 10, 20, 30, …die Sequenznummern von Gruppen und Steuerelementen , wodurch Elemente an Zwischenpositionen eingefügt werden können.

      • Das Command-Attribut gibt den Befehl an, der im CommandUIHandler-Element ausgeführt werden soll (siehe den folgenden Schritt 5.d). Sie können den Befehlsnamen vereinfachen, um es dem nächsten Entwickler zu erleichtern. Beispielsweise Command="Invoke_QuickStatus" ist einfacher zu lesen als Command="Invoke_RibbonQuickStatusActionButtonRequest".

      • Die Bildattribute geben das 16 x 16-Pixel-Symbol und das 32 x 32-Pixel-Symbol für das Schaltflächensteuerelement an. Gibt in der Standarddatei Image32by32="_layouts/15/images/placeholder32x32.png" Elements.xml einen orangefarbenen Punkt an. Sie können Symbole aus den Imagezuordnungsdateien (ps16x16.png und ps32x32.png) extrahieren, die [Program Files]\Common Files\Microsoft Shared\Web Server Extensions\15\TEMPLATE\LAYOUTS\1033\IMAGES im Verzeichnis auf dem Computer installiert sind, auf dem Project Server ausgeführt wird. Beispielsweise befindet sich das 32 x 32-Pixel-Symbol in der zweiten Symbolspalte von links und die zehnte Zeile unten vom oberen Rand der ps32x32.png Bildzuordnung (der obere Rand des Symbols befindet sich nach dem Ende der neunten Zeile; 9 Zeilen x 32 Pixel/Zeile = 288 Pixel).

      • Um eine QuickInfo für das Schaltflächensteuerelement anzuzeigen, fügen Sie das ToolTipTitle-Attribut und das ToolTipDescription-Attribut hinzu.

    4. Ändern Sie die Attribute des CommandUIHandler-Elements . Stellen Sie beispielsweise sicher, dass das Command-Attribut mit dem Command-Attributwert für das Button-Element übereinstimmt. Für das CommandAction-Attribut~appWebUrl ist ein Platzhalter für die URL der QuickStatus-Webseite . Wenn die Menübandschaltfläche die QuickStatus-App aufruft, wird das {StandardTokens} -Token durch URL-Optionen ersetzt, die SPHostUrl, SPLanguage, SPClientTag, SPProductNumber und SPAppWebUrl enthalten.

          <CommandUIHandlers>
              <CommandUIHandler Command="Invoke_QuickStatus"
                                CommandAction="~appWebUrl/Pages/Default.aspx?{StandardTokens}"/>
          </CommandUIHandlers>
      
  6. Öffnen Sie in Projektmappen-Explorer den Feature1.feature-Designer, und verschieben Sie das Element RibbonQuickStatusAction aus dem Bereich Elemente im Bereich Projektmappe in die Elemente im Featurebereich. Wenn Sie dann den Package.package-Designer öffnen, befindet sich das Element RibbonQuickStatusAction im Bereich Elemente im Bereich Paket .

Wenn Sie die App entwickeln und eine Menübandschaltfläche hinzufügen, testen Sie die App normalerweise und legen Haltepunkte im JavaScript-Code für das Debuggen fest. Wenn Sie F5 drücken, um das Debuggen zu starten, kompiliert Visual Studio die App, stellt sie auf der Website bereit, die in der Website-URL-Eigenschaft des QuickStatus-Projekts angegeben ist, und zeigt eine Seite an, auf der Sie gefragt werden, ob Sie der App vertrauen. Wenn Sie fortfahren und dann die QuickStatus-App beenden, kehrt sie zur Seite Aufgaben in Project Web App zurück.

Hinweis

Abbildung 7 zeigt, dass die Schaltfläche Schnellstatus auf der Registerkarte AUFGABEN des Menübands deaktiviert ist. Nach vielen Debugbereitstellungen mit Visual Studio können benutzerdefinierte Menübandsteuerelemente blockiert werden, wenn Sie die veröffentlichte App auf demselben Testserver debuggen oder bereitstellen. Um die Schaltfläche zu aktivieren, löschen Sie das Element RibbonQuickStatusAction in Visual Studio, und erstellen Sie dann eine neue Menübandaktion mit einem anderen Namen und einer anderen ID. Wenn das Problem dadurch nicht behoben wird, versuchen Sie, die App aus dem Project Web App-Test instance zu entfernen, und erstellen Sie die App dann mit einer anderen App-ID neu.

Abbildung 7: Anzeigen der QuickInfo der deaktivierten Schaltfläche "Schnellstatus"

Anzeigen der QuickInfo der deaktivierten Schaltfläche

In Prozedur 5 wird gezeigt, wie Sie die QuickStatus-App bereitstellen und installieren. In Prozedur 6 werden einige zusätzliche Schritte zum Testen der App nach der Installation gezeigt.

Bereitstellen der QuickStatus-App

Es gibt mehrere Möglichkeiten, eine App in einer SharePoint-Webanwendung wie Project Web App bereitzustellen. Welche Bereitstellung Sie verwenden, hängt davon ab, ob Sie die App in einem privaten SharePoint-Katalog oder im öffentlichen Office Store veröffentlichen möchten und ob SharePoint lokal installiert ist oder ein Onlinemandant ist. In Prozedur 5 wird gezeigt, wie Die QuickStatus-App in einer lokalen Installation in einem privaten App-Katalog bereitgestellt wird. Weitere Informationen finden Sie unter Installieren und Verwalten von Apps für SharePoint 2013 und Veröffentlichen von Apps für SharePoint.

Hinweis

Das Hinzufügen einer App zu einem SharePoint-Katalog erfordert SharePoint-Administratorberechtigungen.

Prozedur 5. So stellen Sie die QuickStatus-App bereit

  1. Speichern Sie alle Dateien in Visual Studio, klicken Sie dann im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt QuickStatus, und wählen Sie Veröffentlichen aus.

  2. Da die QuickStatus-App von SharePoint gehostet wird, gibt es nur sehr wenige Optionen für die Veröffentlichung (siehe Abbildung 8). Wählen Sie im Dialogfeld Apps für Office und SharePoint veröffentlichen die Option Fertig stellen aus.

    Abbildung 8: Veröffentlichen der QuickStatus-App

    Verwenden des Veröffentlichungs-Assistenten

  3. Kopieren Sie die QuickStatus.app-Datei aus dem ~\QuickStatus\bin\Debug\app.publish\1.0.0.0 Verzeichnis in ein geeignetes Verzeichnis auf dem lokalen Computer (oder auf den SharePoint-Computer für eine lokale Installation).

  4. Wählen Sie in der SharePoint-Zentraladministration im Schnellstart die Option Apps und dann App-Katalog verwalten aus.

  5. Wenn kein App-Katalog vorhanden ist, erstellen Sie eine Websitesammlung für den App-Katalog, indem Sie dem Abschnitt Konfigurieren der App-Katalogwebsite für eine Webanwendung unter Verwalten des App-Katalogs in SharePoint 2013 folgen.

    Wenn ein App-Katalog vorhanden ist, navigieren Sie zur Website-URL auf der Seite App-Katalog verwalten. In den folgenden Schritten ist https://ServerName/sites/TestAppsdie App-Katalogwebsite beispielsweise .

  6. Wählen Sie auf der Seite App-Katalog im Schnellstart die Option Apps für SharePoint aus. Wählen Sie auf der Seite Apps für SharePoint auf der Registerkarte DATEIEN des Menübands Dokument hochladen aus.

  7. Suchen Sie im Dialogfeld Dokument hinzufügen nach der QuickStatus.app Datei, fügen Sie Kommentare für die Version hinzu, und wählen Sie dann OK aus.

  8. Wenn Sie eine App hinzufügen, können Sie auch lokale Informationen für die App-Beschreibung, das Symbol und andere Informationen hinzufügen. Fügen Sie im Dialogfeld Apps für SharePoint – QuickStatus.app die Informationen hinzu, die Sie für die App in der SharePoint-Websitesammlung anzeigen möchten. Fügen Sie beispielsweise die folgenden Informationen hinzu:

    1. Feld "Kurze Beschreibung ": Geben Sie Schnellstatus-Test-App ein.

    2. Beschreibungsfeld : Geben Sie Test-App ein, um den Prozentsatz abgeschlossen für Vorgänge in mehreren Projekten zu aktualisieren.

    3. Symbol-URL-Felder : Fügen Sie den Websiteressourcen für den App-Katalog ein Bild mit 96 x 96 Pixeln für das App-Symbol hinzu. Navigieren Sie beispielsweise zu https://ServerName/sites/TestApps, wählen Sie im Dropdownmenü Einstellungen die Option Websiteinhalte aus, wählen Sie Websiteobjekte aus, und fügen Sie dann das quickStatusApp.png Bild hinzu. Klicken Sie mit der rechten Maustaste auf das Element quickStatusApp , wählen Sie Eigenschaften aus, und kopieren Sie dann den Wert Adresse (URL) im Dialogfeld Eigenschaften . Kopieren Sie https://ServerName/sites/TestApps/SiteAssets/QuickStatusApp.pngz. B. , und fügen Sie dann den Wert in das Feld Symbol-URL-Webadresse ein. Geben Sie eine Beschreibung für das Symbol ein, z. B. (wie in Abbildung 9), geben Sie QuickStatus-App-Symbol ein. Testen Sie, dass die URL gültig ist.

      Abbildung 9: Hinzufügen einer Symbol-URL für die QuickStatus-App

      Festlegen von Eigenschaften in SharePoint für die App

    4. Kategoriefeld : Wählen Sie eine vorhandene Kategorie aus, oder geben Sie Einen eigenen Wert an. Geben Sie beispielsweise Statusing ein.

      Hinweis

      Eine Kategorie mit dem Namen Statusing dient nur zu Testzwecken. Eine typische Kategorie für Project Server-Apps ist Project Management.

    5. Feld "Herausgebername ": Geben Sie den Namen des Herausgebers ein. Geben Sie in diesem Beispiel Project SDK ein.

    6. Aktiviertes Feld: Aktivieren Sie das Kontrollkästchen Aktiviert , um die App für Project Web App-Websiteadministratoren für die Installation sichtbar zu machen.

    7. Zusätzliche Felder sind optional. Sie können beispielsweise eine Support-URL und mehrere Hilfebilder für die Seite mit den App-Details hinzufügen. In Abbildung 9 enthalten die Felder für Bild-URL 1 die URL für einen Screenshot der App und eine Beschreibung des Screenshots.

    8. Wählen Sie im Dialogfeld Apps für SharePoint – QuickStatus.appdie Option Speichern aus. In Abbildung 9 ist das Element Schnelle Statusaktualisierung in der App für SharePoint-Bibliothek zur Bearbeitung ausgecheckt. Auf der Registerkarte BEARBEITEN des Menübands des Dialogfelds würden Sie daher Check In auswählen, um den Vorgang abzuschließen (siehe Abbildung 10).

      Abbildung 10: Die QuickStatus-App wird der Bibliothek Apps für SharePoint hinzugefügt.

      Die QuickStatus-App wird sharePoint hinzugefügt.

  9. Wählen Sie in Project Web App im Dropdownmenü Einstellungen die Option App hinzufügen aus. Wählen Sie auf der Seite Ihre Apps im Schnellstart die Option Aus Ihrer Organisation und dann App-Details für die App Quick Status Update aus. Abbildung 11 zeigt die Detailseite mit dem App-Symbol, dem Screenshot und anderen Informationen, die Sie im vorherigen Schritt hinzugefügt haben.

    Abbildung 11: Verwenden der Seite "Details zur schnellen Statusaktualisierung" in Project Web App

    Hinzufügen der QuickStatus-App zu Project Web App

  10. Wählen Sie auf der Seite Details zur schnellen Statusaktualisierung die Option IT hinzufügen aus. Project Web App zeigt ein Dialogfeld an, in dem die Vorgänge aufgelistet sind, die die QuickStatus-App ausführen kann (siehe Abbildung 12). Die Liste der Vorgänge wird von den AppPermissionRequest-Elementen in der AppManifest.xml-Datei abgeleitet.

    Abbildung 12. Überprüfen, ob Sie der App "Schnellstatus" vertrauen

    Überprüfen der Vertrauensstellung für die QuickStatus-App

  11. Wählen Sie im Dialogfeld Schnelle Statusaktualisierung die Option Vertrauen aus. Die App wird der Seite "Project Web App-Websiteinhalte" hinzugefügt (siehe Abbildung 13).

    Abbildung 13. Anzeigen der App "Schnellstatus" auf der Seite "Websiteinhalte"

    Anzeigen der QuickStatus-App in Websiteinhalten

Auf der Seite Websiteinhalte können Sie das Symbol Schnelle Statusaktualisierung auswählen, um die App auszuführen.

Hinweis

Wählen Sie für zusätzliche Befehle, die Informationen zur App bereitstellen, auf der Seite Websiteinhalte die Region aus, die den Namen der Schnellen Statusaktualisierung und die Auslassungspunkte (...) enthält. Sie können die Seite Info für die App überprüfen, die Seite App-Details anzeigen, die Informationen zu App-Fehlern enthält, die Seite mit den App-Berechtigungen überprüfen oder die App aus Project Web App entfernen.

Auf der Seite Aufgaben in Project Web App (siehe Abbildung 14) sollte die Schaltfläche QuickStatus im Menüband aktiviert sein. Wenn die Schaltfläche Schnellstatus deaktiviert ist, probieren Sie die im Hinweis für Abbildung 7 beschriebenen Aktionen aus.

Abbildung 14. Starten der QuickStatus-App von der Registerkarte "TASKS"

Starten der QuickStatus-App über die Registerkarte AUFGABEN

In Prozedur 6 werden einige Tests gezeigt, die mit der QuickStatus-App durchgeführt werden müssen.

Testen der QuickStatus-App

Jeder Vorgang, den ein Benutzer in der QuickStatus-App ausprobieren kann, sollte in einer Testinstallation von Project Server getestet werden, bevor die App auf einem Produktionsserver oder auf einem Produktionsmandanten von Project Online bereitgestellt wird. Mit einer Testinstallation können Sie Zuweisungen für Benutzer ändern und löschen, ohne dass sich dies auf die tatsächlichen Projekte auswirkt. An den Tests sollten auch mehrere Benutzer beteiligt sein, die über unterschiedliche Berechtigungssätze verfügen, z. B. Administrator, Projektmanager und Teammitglied. Gründliche Tests können Änderungen aufdecken, die in der App vorgenommen werden sollten, die während der Entwicklung in Tests nicht offensichtlich waren. Prozedur 6 listet mehrere Tests für die QuickStatus-App auf, enthält jedoch keine vollständige Reihe von Tests.

Verfahren 6. So testen Sie die QuickStatus-App

  1. Führen Sie die QuickStatus-App aus, bei der der Benutzer keine Zuweisungen hat. Die App sollte unten auf der Seite eine blaue Meldung anzeigen, z. B. Benutzername hat keine Zuweisungen.

    Wählen Sie Aktualisieren aus, und die Meldung ändert sich an eine grüne Zuweisung wurde aktualisiert.

    Hinweis

    Das App-Verhalten sollte so geändert werden, dass die Schaltfläche Aktualisieren deaktiviert wird, wenn keine Zuweisungen vorhanden sind.

  2. Führen Sie die App aus, bei der der Benutzer mehrere Zuweisungen in mehreren verschiedenen Projekten hat und einige Zuweisungen nicht abgeschlossen sind. Beachten Sie das Aussehen der App, und führen Sie aktionen wie folgt aus (siehe Abbildung 15):

    1. Die onGetAssignmentsSuccess-Funktion erstellt eine Zeile in der Tabelle für jede Zuweisung für den aktuellen Benutzer. Der Projektname wird nur einmal fett formatiert für die erste Aufgabe in jedem Projekt angezeigt.

    2. Deaktivieren Sie das Kontrollkästchen in der Spaltenüberschrift Vorgangsname . Der Click-Ereignishandler der Tabellenkopfzeile löscht alle anderen Kontrollkästchen in den Aufgabenzeilen.

    3. Wählen Sie alle Aufgaben aus. Der Click-Ereignishandler für jede Zeile bestimmt, ob alle Zeilen ausgewählt sind, und wenn ja, wählt die Spaltenüberschrift Taskname aus.

    4. Deaktivieren Sie alle Kontrollkästchen erneut, und wählen Sie dann eine Aufgabe aus, die noch etwas Arbeit hat. Abbildung 15 zeigt z. B., dass die oberste Aufgabe T1 20 % verbleibende Arbeit hat.

    5. Geben Sie im Textfeld Prozent abgeschlossen festlegen den Wert 80 ein, und wählen Sie dann Aktualisieren aus. Am unteren Rand der Seite sollte eine grüne Meldung angezeigt werden: Zuweisungen wurden aktualisiert.

      Abbildung 15. Aktualisieren einer Zuweisung in der QuickStatus-App

      Aktualisieren einer Aufgabe in der QuickStatus-App

  3. Wählen Sie Aktualisieren aus (siehe Abbildung 16). Alle Vorgänge werden erneut ausgewählt, und die oberste Aufgabe zeigt 80 % abgeschlossen an.

    Abbildung 16. Aktualisieren der Seite "Schnelle Statusaktualisierung"

    Aktualisieren der QuickStatus-Seite

  4. Deaktivieren Sie alle Kontrollkästchen, und wählen Sie dann eine andere Aufgabe aus. Wählen Sie z. B . Neue Aufgabe aus PWA aus. Lassen Sie das Textfeld Prozent abgeschlossen festlegen leer, löschen Sie den gesamten Text in der Spalte % abgeschlossen für die ausgewählte Aufgabe, und wählen Sie dann Aktualisieren aus. Da beide Textfelder leer sind, zeigt die App eine rote Fehlermeldung an (siehe Abbildung 17).

    Abbildung 17. Testen der Fehlermeldung

    Testen der Fehlermeldung

  5. Aktualisieren Sie die vorherige Aufgabe auf 80 % abgeschlossen, und wählen Sie dann Beenden aus. Die exitToPwa-Funktion ändert den Speicherort des Browserfensters in die Seite Aufgaben in der SharePoint-Hostanwendung (d. a. die URL ändert sich in <https://ServerName/pwa/Tasks.aspx>). Abbildung 18 zeigt, dass der T1-Vorgang und der Vorgang Neuer Vorgang aus PWA jeweils zu 80 % abgeschlossen sind.

    Abbildung 18. Überprüfen, ob die Vorgänge in Project Web App aktualisiert werden

    Überprüfen der aktualisierten Vorgänge in Project Web App

  6. Bevor die aktualisierte status in Project Professional 2013 angezeigt wird, müssen die Änderungen zur Genehmigung eingereicht und dann vom Projektmanager genehmigt werden.

Das Testen zeigt mehrere andere Änderungen, die in der QuickStatus-App vorgenommen werden sollten, um die Benutzerfreundlichkeit zu verbessern. Zum Beispiel:

  • Es sollten zusätzliche Fehlerüberprüfungen und die Überprüfung von Textfeldwerten erfolgen. Derzeit kann ein Benutzer einen nicht numerischen Oder einen negativen Wert für %abgeschlossen eingeben, was zu einer unfreundlichen Fehlermeldung führt. Bei einem negativen Wert lautet die Fehlermeldung z. B . Fehler beim Aktualisieren von Zuweisungen: PJClientCallableException: StatusingSetDataValueInvalid.

  • Die Fehlermeldung für leere Textfelder kann das Projekt und die Aufgabe zusätzlich zur Zeilennummer auflisten.

  • Die Erfolgsmeldung könnte eine Liste der aktualisierten Aufgaben enthalten. Oder wenn die updateAssignments-Funktion erfolgreich ist, kann sie eine automatische Seitenaktualisierung durchführen und aktualisierte Aufgaben oder Prozentsätze in einer anderen Farbe und fett formatierten Schriftart anzeigen.

  • Um eine sehr große Tabelle zu vermeiden, sollte die Zuordnungstabelle auf Vorgänge beschränkt sein, die weniger als 100 % abgeschlossen sind. Oder fügen Sie eine Option hinzu, um alle Aufgaben anzuzeigen. Dieses Problem könnte auch durch die Verwendung eines jQuery-basierten Rasters anstelle einer Tabelle gelöst werden, in dem Sie problemlos Filterung und Raster paging implementieren können.

  • Da die QuickStatus-App keine status übermittelt, ist das Symbol Schnellstatus auf der Registerkarte AUFGABEN des Menübands logischer als das erste Symbol in der Gruppe Aufgaben und nicht das letzte Symbol in der Gruppe Senden.

  • Da die onGetAssignmentsSuccess-Funktion den BtnSubmitUpdate-Schaltflächentext initialisiert, die anderen Textwerte der Schaltfläche jedoch in HTML initialisiert werden, bleibt die Seite in einem teilweise initialisierten Zustand, während die getAssignments-Funktion ausgeführt wird. Schaltflächen auf der Seite würden konsistenter aussehen, wenn die Textwerte alle in HTML initialisiert würden.

Am wichtigsten ist, dass der Ansatz, den die QuickStatus-App verwendet, bei dem sie sich für Zuweisungen in Prozent abgeschlossen ändert, in einer Produktions-App überarbeitet werden sollte. Weitere Informationen finden Sie im Abschnitt Nächste Schritte .

Beispielcode für die QuickStatus-App

Default.aspx Datei

Der folgende Code befindet sich in der Pages\Default.aspx Datei des QuickStatus-Projekts :

    <%-- The following lines are ASP.NET directives needed when using SharePoint components --%>
    <%@ Page Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage, Microsoft.SharePoint, Version=15.0.0.0, 
    Culture=neutral, PublicKeyToken=71e9bce111e9429c" MasterPageFile="~masterurl/default.master" Language="C#" %>
    <%@ Register TagPrefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=15.0.0.0, 
    Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
    <%@ Register TagPrefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=15.0.0.0, 
    Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
    <%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=15.0.0.0, 
    Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
    <%-- The markup and script in the following Content element will be placed in the <head> of the page.
        For production deployment, change the .debug.js JavaScript references to .js. --%>
    <asp:Content ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">
    <script type="text/javascript" src="../Scripts/jquery-1.7.1.min.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>
    <!-- CSS styles -->
    <link rel="Stylesheet" type="text/css" href="../Content/App.css" />
    <!-- Add your JavaScript to the following file -->
    <script type="text/javascript" src="../Scripts/App.js"></script>
    </asp:Content>
    <%-- The markup and script in the following Content element will be placed in the <body> of the page --%>
    <asp:Content ContentPlaceHolderID="PlaceHolderMain" runat="server">
    <form>
        <fieldset>
        <legend>Select assigned tasks</legend>
        <table id="assignmentsTable">
            <caption id="tableCaption">Replace caption</caption>
            <thead>
            <tr id="headerRow">
                <th>Project name</th>
                <th><input type="checkbox" id="headercheckbox" checked="checked" />Task name</th>
                <th>Actual work</th>
                <th>% complete</th>
                <th>Remaining work</th>
                <th>Due date</th>
            </tr>
            </thead>
        </table>
        </fieldset>
        <div id="inputPercentComplete" >
        Set percent complete for all selected assignments, or leave this
        <br /> field blank and set percent complete for individual assignments: 
        <input type="text" name="percentComplete" id="pctComplete" size="4"  maxlength="4" />
        </div>
        <div id="submitResult">
        <p><button id="btnSubmitUpdate" type="button" class="bottomButtons" ></button></p>
        <p id="message"></p>
        </div>
        <div id="refreshPage">
        <p><button id="btnRefresh" type="button" class="bottomButtons" >Refresh</button></p>
        </div>
    <div id="exitPage">
        <p><button id="btnExit" type="button" class="bottomButtons" >Exit</button></p>
    </div>
    </form>
    </asp:Content>

datei App.js

Der folgende Code befindet sich in der Scripts\App.js Datei des QuickStatus-Projekts :

    var projContext;
    var pwaWeb;
    var projUser;
    // This code runs when the DOM is ready and creates a ProjectContext object.
    // The ProjectContext object is required to use the JSOM for Project Server.
    $(document).ready(function () {
        projContext = PS.ProjectContext.get_current();
        pwaWeb = projContext.get_web();
        getUserInfo();
        getAssignments();
        // Bind a click event handler to the table header check box, which sets the row check boxes
        // to the selected state of the header check box, and sets the results message to an empty string.
        $('#headercheckbox').live('click', function (event) {
            $('input:checkbox:not(#headercheckbox)').attr('checked', this.checked);
            $get("message").innerText = "";
        });
        // Bind a click event handler to the row check boxes. If any row check box is cleared, clear
        // the header check box. If all of the row check boxes are selected, select the header check box.
        $('input:checkbox:not(#headercheckbox)').live('click', function (event) {
            var isChecked = true;
            $('input:checkbox:not(#headercheckbox)').each(function () {
                if (this.checked == false) isChecked = false;
                $get("message").innerText = "";
            });
            $("#headercheckbox").attr('checked', isChecked);
        });
    });
    // Get information about the current user.
    function getUserInfo() {
        projUser = pwaWeb.get_currentUser();
        projContext.load(projUser);
        projContext.executeQueryAsync(onGetUserNameSuccess,
            // Anonymous function to execute if getUserInfo fails.
            function (sender, args) {
                alert('Failed to get user name. Error: ' + args.get_message());
        });
    }
    // This function is executed if the getUserInfo call is successful.
    // Replace the contents of the 'caption' paragraph with the project user name.
    function onGetUserNameSuccess() {
        var prefaceInfo = 'Assignments for ' + projUser.get_title();
        $('#tableCaption').text(prefaceInfo);
    }
    // Get the collection of assignments for the current user.
    function getAssignments() {
        assignments = PS.EnterpriseResource.getSelf(projContext).get_assignments();
        // Register the request that you want to run on the server. The optional "Include" parameter 
        // requests only the specified properties for each assignment in the collection.
        projContext.load(assignments,
            'Include(Project, Name, ActualWork, ActualWorkMilliseconds, PercentComplete, RemainingWork, Finish, Task)');
        // Run the request on the server.
        projContext.executeQueryAsync(onGetAssignmentsSuccess,
            // Anonymous function to execute if getAssignments fails.
            function (sender, args) {
                alert('Failed to get assignments. Error: ' + args.get_message());
            });
    }
    // Get the enumerator, iterate through the assignment collection, 
    // and add each assignment to the table.
    function onGetAssignmentsSuccess(sender, args) {
        if (assignments.get_count() > 0) {
            var assignmentsEnumerator = assignments.getEnumerator();
            var projName = "";
            var prevProjName = "3D2A8045-4920-4B31-B3E7-9D0C5195FC70"; // Any unique name.
            var taskNum = 0;
            var chkTask = "";
            var txtPctComplete = "";
            // Constants for creating input controls in the table.
            var INPUTCHK = '<input type="checkbox" class="chkTask" checked="checked" id="chk';
            var LBLCHK = '<label for="chk';
            var INPUTTXT = '<input type="text" size="4"  maxlength="4" class="txtPctComplete" id="txt';
            while (assignmentsEnumerator.moveNext()) {
                var statusAssignment = assignmentsEnumerator.get_current();
                projName = statusAssignment.get_project().get_name();
                // Get an integer value for the number of milliseconds of actual work, such as 3600000.
                var actualWorkMilliseconds = statusAssignment.get_actualWorkMilliseconds();
                // Get a string value for the assignment actual work, such as "1h". Not used here.
                var actualWork = statusAssignment.get_actualWork();                         
                if (projName === prevProjName) {
                    projName = "";
                }
                prevProjName = statusAssignment.get_project().get_name();
                // Create a row for the assignment information.
                var row = assignmentsTable.insertRow();
                taskNum++;
                // Create an HTML string with a check box and task name label, for example:
                //     <input type="checkbox" class="chkTask" checked="checked" id="chk1" /> 
                //     <label for="chk1">Task 1</label>
                chkTask = INPUTCHK + taskNum + '" /> ' + LBLCHK + taskNum + '">'
                    + statusAssignment.get_name() + '</label>';
                txtPctComplete = INPUTTXT + taskNum + '" />';
                // Insert cells for the assignment properties.
                row.insertCell().innerHTML = '<strong>' + projName + '</strong>';
                row.insertCell().innerHTML = chkTask;
                row.insertCell().innerText = actualWorkMilliseconds / 3600000 + 'h';
                row.insertCell().innerHTML = txtPctComplete;
                row.insertCell().innerText = statusAssignment.get_remainingWork();
                row.insertCell().innerText = statusAssignment.get_finish();
                // Initialize the percent complete cell.
                $get("txt" + taskNum).innerText = statusAssignment.get_percentComplete() + '%'
            }
        }
        else {
            $('p#message').attr('style', 'color: #0f3fdb');     // Blue text.
            $get("message").innerText = projUser.get_title() + ' has no assignments'
        }
        // Initialize the button properties.
        $get("btnSubmitUpdate").onclick = function() { updateAssignments(); };
        $get("btnSubmitUpdate").innerText = 'Update';
        $get('btnRefresh').onclick = function () { window.location.reload(true); };
        $get('btnExit').onclick = function () { exitToPwa(); };
    }
    // Update all selected assignments. If the bottom percent complete field is blank,
    // use the value in the % complete field of each selected row in the table.
    function updateAssignments() {
        // Get percent complete from the bottom text box.
        var pctCompleteMain = getNumericValue($('#pctComplete').val()).trim();
        var pctComplete = pctCompleteMain;
        var assignmentsEnumerator = assignments.getEnumerator();
        var taskNum = 0;
        var taskRow = "";
        var indexPercent = "";
        var doSubmit = true;
        while (assignmentsEnumerator.moveNext()) {
            var pctCompleteRow = "";
            taskRow = "chk" + ++taskNum;
            if ($get(taskRow).checked) {
                var statusAssignment = assignmentsEnumerator.get_current();
                if (pctCompleteMain === "") {
                    // Get percent complete from the text box field in the table row.
                    pctCompleteRow = getNumericValue($('#txt' + taskNum).val());
                    pctComplete = pctCompleteRow;
                }
                // If both percent complete fields are empty, show an error.
                if (pctCompleteMain === "" && pctCompleteRow === "") {
                    $('p#message').attr('style', 'color: #e11500');     // Red text.
                    $get("message").innerHTML =
                        '<b>Error:</b> Both <i>Percent complete</i> fields are empty, in row '
                        + taskNum
                        + ' and in the bottom textbox.<br/>One of those fields must have a valid percent.'
                        + '<p>Please refresh the page and try again.</p>';
                    doSubmit = false;
                    taskNum = 0;
                    break;
                }
                if (doSubmit) statusAssignment.set_percentComplete(pctComplete);
            }
        } 
        // Save and submit the assignment updates.
        if (doSubmit) {
            assignments.update();
            assignments.submitAllStatusUpdates();
            projContext.executeQueryAsync(function (source, args) {
                $('p#message').attr('style', 'color: #0faa0d');     // Green text.
                $get("message").innerText = 'Assignments have been updated.';
            }, function (source, args) {
                $('p#message').attr('style', 'color: #e11500');     // Red text.
                $get("message").innerText = 'Error updating assignments: ' + args.get_message();
            });
        }
    }
    // Get the numeric part for percent complete, from a string. 
    // For example, with "20 %", return "20".
    function getNumericValue(pctComplete) {
        pctComplete = pctComplete.trim();
        pctComplete = pctComplete.replace(/ /g, "");    // Remove interior spaces.
        indexPercent = pctComplete.indexOf('%', 0);
        if (indexPercent > -1) pctComplete = pctComplete.substring(0, indexPercent);
        return pctComplete;
    }
    // Exit the QuickStatus page and go back to the Tasks page in Project Web App.
    function exitToPwa() {
        // Get the SharePoint host URL, which is the top page of PWA, and add the Tasks page.
        var spHostUrl = decodeURIComponent(getQueryStringParameter('SPHostUrl'))
                        + "/Tasks.aspx";
        // Set the top window for the QuickStatus IFrame to the Tasks page.
        window.top.location.href = spHostUrl;
    }
    // Get a specified query string parameter from the {StandardTokens} URL option string.
    function getQueryStringParameter(urlParameterKey) {
        var docUrl = document.URL;
        var params = docUrl.split('?')[1].split('&');
        for (var i = 0; i < params.length; i++) {
            var theParam = params[i].split('=');
            if (theParam[0] == urlParameterKey)
                return decodeURIComponent(theParam[1]);
        }
    }

App.css-Datei

Der folgende CSS-Code befindet sich in der Content\App.css Datei des QuickStatus-Projekts :

    /* Custom styles for the QuickStatus app. */
    /*============= Table elements ========================================*/
    table {
        width: 90%;
    }
    caption {
        font-size: 16px;
        padding-bottom: 5px;
        font-weight: bold;
        color: gray;
    }
    table th {
        background-color: gray;
        color: white;
    }
    table td, th {
        width: auto;
        text-align: left;
        padding: 2px;
        border: solid 1px whitesmoke;
        color: gray;
    }
    /*=== Class for check boxes added to rows 
    */
    .chkTask {
        width: 12px;
        height: 12px;
        color: gray;
    }
    /*========== DIV id for the Percent Complete text box ================*/
    #inputPercentComplete {
        position: fixed;
        top: auto;
        height: auto;
        padding-top: 20px;
        margin-left: 30px;
    }
    /*========== DIV id for the Submit Result button ====================*/
    #submitResult {
        position: fixed;
        top: auto;
        height: auto;
        padding-top: 60px;
    }
    /*========== DIV id for the Refresh Page button ====================*/
    #refreshPage {
        position: fixed;
        top: auto;
        height: auto;
        padding-top: 60px;
        margin-left: 120px;
    }
    /*========== DIV id for the Exit Page button ====================*/
    #exitPage {
        position: fixed;
        top: auto;
        height: auto;
        padding-top: 60px;
        margin-left: 240px;
    }
    /*========== Class for the buttons at the bottom of the page =======*/
    .bottomButtons {
        color: gray;
        font-weight: bold; 
        font-size: 12px; 
        border-color: darkgreen;
        border-width: thin;
    }

Elements.xml Datei für das Menüband

Die folgende XML-Definition für die hinzugefügte Schaltfläche auf der Registerkarte AUFGABEN im Menüband befindet sich in der RibbonQuickStatusAction\Elements.xml Datei des QuickStatus-Projekts :

    <?xml version="1.0" encoding="utf-8"?>
    <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
    <CustomAction Id="21ea3aaf-79e5-4aac-9479-8eef14b4d9df.RibbonQuickStatusAction"
                    Location="CommandUI.Ribbon">
        <CommandUIExtension>
        <!-- 
        Add a button that invokes the QuickStatus app. The Quick Status button is displayed as  
        the third control in the Page group (the group title is "Submit").
        -->
        <CommandUIDefinitions>
            <CommandUIDefinition Location="Ribbon.ContextualTabs.MyWork.Home.Page.Controls._children">
            <Button Id="Ribbon.ContextualTabs.MyWork.Home.Page.QuickStatus"
                    Alt="Quick Status app"
                    Sequence="30"
                    Command="Invokae_QuickStatus"
                    LabelText="Quick Status"
                    TemplateAlias="o1"
                    Image16by16="_layouts/15/1033/images/ps16x16.png" 
                    Image16by16Left="-80"
                    Image16by16Top="-144"
                    Image32by32="_layouts/15/1033/images/ps32x32.png" 
                    Image32by32Left="-32"
                    Image32by32Top="-288" 
                    ToolTipTitle="Quick Status"
                    ToolTipDescription="Run the QuickStatus app" />
            </CommandUIDefinition>
        </CommandUIDefinitions>
        <CommandUIHandlers>
            <CommandUIHandler Command="Invoke_QuickStatus"
                            CommandAction="~appWebUrl/Pages/Default.aspx?{StandardTokens}"/>
        </CommandUIHandlers>
        </CommandUIExtension >
    </CustomAction>
    </Elements>

Die Datei "AppManifest.xml"

Im Folgenden finden Sie den XML-Code für das App-Manifest des QuickStatus-Projekts, das die beiden Berechtigungsanforderungsbereiche enthält, die zum Aktualisieren der Zuweisung des App-Benutzers status in mehreren Projekten erforderlich sind:

    <?xml version="1.0" encoding="utf-8" ?>
    <!--Created:cb85b80c-f585-40ff-8bfc-12ff4d0e34a9-->
    <App xmlns="http://schemas.microsoft.com/sharepoint/2012/app/manifest"
        Name="QuickStatus"
        ProductID="{bbc497e7-1221-4d7b-a0ae-141a99546008}"
        Version="1.0.0.0"
        SharePointMinVersion="15.0.0.0"
    >
    <Properties>
        <Title>Quick Status Update</Title>
        <StartPage>~appWebUrl/Pages/Default.aspx?{StandardTokens}</StartPage>
    </Properties>
    <AppPrincipal>
        <Internal />
    </AppPrincipal>
    <AppPermissionRequests>
        <AppPermissionRequest Scope="https://sharepoint/projectserver/statusing" Right="SubmitStatus" />
        <AppPermissionRequest Scope="https://sharepoint/projectserver/projects" Right="Read" />
    </AppPermissionRequests>
    </App>

datei AppIcon.png

Die vollständige Visual Studio-Projektmappe für die QuickStatus-App enthält eine benutzerdefinierte AppIcon.png-Datei. Die Projektmappe wird im Project 2013 SDK-Download enthalten sein.

Nächste Schritte

Die QuickStatus-App ist ein relativ einfaches Beispiel für das Schreiben von Apps, die unter Project Server 2013 und Project Online installiert werden können. Im Abschnitt Testen der QuickStatus-App werden mehrere Verbesserungen aufgeführt, die für eine bessere Benutzerfreundlichkeit vorgenommen werden können. Die QuickStatus-App verwendet JavaScript-Funktionen, um Zuweisungen status für Project Web App zu aktualisieren. Das Ändern des Prozentsatzes der abgeschlossenen Zuordnung ist jedoch keine empfohlene Projektmanagementmethode. Ein anderer Ansatz besteht darin, den tatsächlichen Anfangstermin und die verbleibende Dauer der zugewiesenen Aufgaben zu aktualisieren. Eine Erläuterung der Probleme finden Sie unter Update Better im MPUG-Newsletter.

Siehe auch