在Sharepoint 2013中使用javascript个性化添加部分

时间:2015-10-29 07:54:01

标签: javascript sharepoint sharepoint-2013 csom personalization

我们有一位客户希望让用户更容易自定义他们的网页部分页面。因此,我们使用javascript构建一个简单的网格,用户可以从当前页面上的不同webpart区域添加,删除和移动Add In Parts(webparts和AppParts以及OOTB和自定义)。大多数功能都运行良好,但我们有两个问题似乎无法找到答案。在这种情况下,我们正在使用Farm解决方案,但我们希望它也可以与Office365一起使用。

  1. 是部分共享还是个人添加?
  2. 我们希望用户能够删除/隐藏他们不想要的添加部分,我们正在使用 SP.WebParts.WebPartDefinition.deleteWebPart()来执行此操作。这适用于用户添加到他/她的个人网站的Add In Parts,但如果您使用共享的Add In Part尝试此操作,则会出现错误。我们想知道是否共享了Add In Part,并且在这种情况下设置了hidden=true。我们似乎无法找到关于如何检查Add In Part是否共享的任何内容,然后首先尝试“deleteWebPart()”,如果它给出错误,请尝试“hidden = true”。

    1. 获取ClientWebPart(AppPart)xml
    2. 为了能够从库中向页面添加“添加部件”,您需要使用此方法中的xml:importWebPart()。对于webparts,我们可以通过检查“~siteUrl / _api / web / getCatalog(113)/ items”中的项目找到.webpart文件,但此列表中不存在AppParts。要获取我们正在使用的所有应用程序 SP.AppCatalog.getAppInstances(context,web),我们会从中获取每个应用程序名称,guid等,但不是它的xml。我们在哪里可以找到?所有人都要求相同的人建议手动导出xml并在代码中使用它,但这并不是很好。这需要是动态的,适用于所有AppParts。

      感谢您的帮助。

      致管理员:我首先在sharepoint.stackexchange.com上发布了这个问题,但我不确定是否应该在此处或那里发布有关代码的问题。如果你告诉我它应该如何,我将删除另一个。

1 个答案:

答案 0 :(得分:0)

我在我的公司找到了一些能够发挥类似功能的人,我和他们一起找到了一个令人满意的解决方案。如果将来有其他人想要做同样的事情,我会分享我是如何做到的。

问题1:添加部分共享还是个人

我无法在AddInPart上找到任何属性,如果它由用户共享或创建,所以我通过简单地加载所有共享的AddInPart并将其存储在数组中的GUID来解决这个问题。通过这样做,我可以检查我想删除的AddInPart是否在该数组中,在这种情况下采取正确的操作。我就这样做了:



var sharedWebPartGuids = new Array(); // An array containing guids from all shared webparts

function fetchSharedWebparts() {
  //get the client context
  var clientContext = new SP.ClientContext(_spPageContextInfo.webServerRelativeUrl);
  //get the current page as a file
  var oFile = clientContext.get_web().getFileByServerRelativeUrl(_spPageContextInfo.serverRequestPath);
  // Fetch all webparts that are shared
  var limitedWebPartManagerShared = oFile.getLimitedWebPartManager(SP.WebParts.PersonalizationScope.shared);
  //get the web parts on the current page
  var collWebPart = limitedWebPartManagerUser.get_webParts();
  //request the web part collection and load it from the server
  clientContext.load(collWebPart);
  clientContext.executeQueryAsync(Function.createDelegate(this, function() {
    // Go through all webparts
    for (var x = 0; x < collWebPart.get_count(); x++) {
      var webPartDef = collWebPart.get_item(x);
      sharedWebPartGuids.push(webPartDef.get_id().toString());
    }
  }), Function.createDelegate(this, function() {
    alert("failed to fetch shared webparts from page")
  }));
}
&#13;
&#13;
&#13;

问题2:获取ClientWebPart(AppPart)xml

Unfortunetley如果没有为每个应该能够添加AppPart的应用程序手动提供ProductID(GUID),我无法做到这一点。为此,我部署了一个名为 AvailableAppParts 的列表,其中包含两列; 标题 ProductId 。然后,我通过比较标题将列表中的项目与已安装的应用程序进行匹配。 GUID可以在App中的AppManifest.xml中找到,也可以将AppPart添加到页面然后将其导出。我还必须在我的代码中包含一个xml模板并替换唯一值。由于所有内容都是异步完成的,我有一个名为 initMethods 的计数器,我为每个异步方法添加,然后在它们的末尾调用 initMethodDone(),它会检查是否所有的异步方法在我向用户显示任何内容之前完成。我就这样做了:

&#13;
&#13;
var webpartsFromGallery = new Array(); // An array where I store an object for each AppPart
// The xml template:
var appPartXml = '<webParts><webPart xmlns="http://schemas.microsoft.com/WebPart/v3"><metaData><type name="Microsoft.SharePoint.WebPartPages.ClientWebPart, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" /><importErrorMessage>Cannot import this Web Part.</importErrorMessage> </metaData><data><properties><property name="TitleIconImageUrl" type="string" /><property name="Direction" type="direction">NotSet</property><property name="ExportMode" type="exportmode">NonSensitiveData</property><property name="HelpUrl" type="string" /><property name="Hidden" type="bool">False</property><property name="Description" type="string">AppPart Description</property><property name="FeatureId" type="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">{FeatureId}</property><property name="Title" type="string">{Title}</property><property name="AllowHide" type="bool">True</property><property name="ProductWebId" type="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">{ProductWebId}</property><property name="AllowZoneChange" type="bool">True</property><property name="TitleUrl" type="string" /><property name="ChromeType" type="chrometype">Default</property><property name="AllowConnect" type="bool">True</property><property name="Width" type="unit" /><property name="Height" type="unit" /><property name="WebPartName" type="string">AppPart</property><property name="HelpMode" type="helpmode">Navigate</property><property name="AllowEdit" type="bool">True</property><property name="AllowMinimize" type="bool">True</property><property name="ProductId" type="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">{ProductId}</property><property name="AllowClose" type="bool">True</property><property name="ChromeState" type="chromestate">Normal</property></properties></data></webPart></webParts>';

function fetchAppPartsFromGallery() {
  initMethods++;
  var ctx = SP.ClientContext.get_current();
  var web = ctx.get_web();
  // Fetch all installed Apps on this site (SPWeb)
  var appInstances = SP.AppCatalog.getAppInstances(ctx, web);
  ctx.load(appInstances);
  ctx.executeQueryAsync(
    function() {
      if (appInstances.get_count() == 0) {
        // No apps found, stop here
        return;
      }
      // Iterate through the app instances and store them in a map
      // Also create a filter string
      var map = new Object();
      var filterString = "";
      for (var i = 0; i < appInstances.get_count(); i++) {
        var instance = appInstances.getItemAtIndex(i);
        var title = instance.get_title();
        map[title] = instance;

        // Append filter
        if (filterString.length > 0) {
          filterString += "or";
        }
        filterString += "(Title+eq+'" + title + "')";
      }
      if (filterString.length > 0) {
        filterString = "?$filter=" + filterString;
      }

      // Fetch available apps from my list
      $.ajax({
        url: siteApiUrl + "/web/lists/getbytitle('AvailableAppParts')/items" + filterString,
        type: "GET",
        headers: {
          "accept": "application/json;odata=verbose",
        },
        success: function(data) {
          // Go through all returned apps and build the xml for each one
          var results = data.d.results;
          for (var i = 0; i < results.length; i++) {
            var listItem = results[i];
            var title = listItem.Title;
            var productId = listItem.ProductId;

            var appInstance = map[title];
            if (!appInstance) {
              console.log("Could not find app with title '" + title + "'");
              continue;
            }
            var instanceId = appInstance.get_id();
            var webId = appInstance.get_webId();
            var featureId = calculateFeatureIdFromProductId(productId);

            // This is the values we have to replace with our unique ones
            var xml = appPartXml.replace(/{Title}/g, title);
            xml = xml.replace(/{ProductId}/g, productId);
            xml = xml.replace(/{ProductWebId}/g, webId);
            xml = xml.replace(/{FeatureId}/g, featureId);

            webpartsFromGallery.push({
              id: instanceId,
              title: title,
              xml: xml
            });
          }

          function calculateFeatureIdFromProductId(productID) {
            // Calculate featureId since it is always one hexadecimal value higher than productId
            var lastIndex = productID.lastIndexOf('-');
            var lastNumber = productID.substring(lastIndex + 12);
            // We are using hexadecimal numbers therefor using parseInt(..., 16) and toString(16)
            var increment = parseInt(lastNumber, 16) + 1;
            var incrementHex = increment.toString(16);
            var featureID = productID.substring(0, lastIndex + 12) + incrementHex;
            return featureID;
          }

          initMethodDone();
        },
        error: function(error) {
          alert(JSON.stringify(error));

          initMethodDone();
        }

      });
    },
    function(sender, args) {
      console.log(JSON.stringify(args));

      initMethodDone();
    });
}
&#13;
&#13;
&#13;