无依赖简单易用的Dynamics 365公共视图克隆工具
本人微信公众号:微软动态CRM专家罗勇 ,回复279或者20180818可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!我的网站是 www.luoyong.me 。
Dynamics 365 Customer Engagement 新建实体后会自动建立一些公共视图,默认情况下,我们会修改实体的默认公共视图,让他显示更多的列和合适的排序和筛选。但是很多人会觉得比较耗时去修改其他的视图,如果不修改,用户切换到其他视图,默认只有两三列,变化比较大,用户体验不大好。
那么问题来了,有没有工具可以克隆公共视图呢?当然在克隆的时候保留目标视图的筛选条件,我今天就开发了一个这样的无依赖简单易用的工具,就是一个HTML Web资源,为了方便使用没有引用第三方JavaScript类库。
可以选择实体,选择一个源视图,一次克隆到这个实体的一个或者多个公共视图。
代码如下,可以看到Web API功能很强大了,查询元数据,执行操作,比如发布实体等以前做不了的操作都不在话下了,赞。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dynamics 365公共视图克隆工具_罗勇原创_www.luoyong.me</title>
<script src="../../../ClientGlobalContext.js.aspx" type="text/javascript"></script>
<script type="text/javascript">
var clientUrl = "";
var savedQueries;
var targetEntityName = "";
function initPage() {
if (typeof GetGlobalContext != "undefined") {
crmclientcontext = GetGlobalContext();
} else {
throw new Error("引入ClientGlobalContext.js.aspx失败,请检查!");
}
clientUrl = crmclientcontext.getClientUrl() + "/api/data/v8.2/";
var req = new XMLHttpRequest();
req.open("GET", encodeURI(clientUrl + "EntityDefinitions?$select=LogicalName&$filter=IsCustomizable/Value eq true"), false);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.onreadystatechange = function () {
if (this.readyState == 4 /* complete */) {
req.onreadystatechange = null;
if (this.status == 200) {
var responseJson = JSON.parse(this.responseText);
var targetEntitySelect= document.getElementById("TargetEntity");
if (responseJson.value.length >= 1) {
var recordCount = responseJson.value.length;
for (var i = 0; i < recordCount; i++) {
var option = document.createElement('option');
option.text = option.value = responseJson.value[i].LogicalName;
targetEntitySelect.add(option, 0);
}
}
}
else {
errorCallback(JSON.parse(this.responseText));
}
}
};
req.send();
} function targetEntityOnChange() {
var targetEntitySelect = document.getElementById("TargetEntity");
targetEntityName = targetEntitySelect.options[targetEntitySelect.selectedIndex].value;
if (targetEntityName != "nothing") {
var req = new XMLHttpRequest();
req.open("GET", encodeURI(clientUrl + "savedqueries?$select=name,savedqueryid,layoutxml,fetchxml,isdefault,querytype&$filter=returnedtypecode eq '" + targetEntityName + "' and createdon ne null&$orderby=name asc"), false);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.onreadystatechange = function () {
if (this.readyState == 4 /* complete */) {
req.onreadystatechange = null;
if (this.status == 200) {
var responseJson = JSON.parse(this.responseText);
var sourceSavedQuerySelect = document.getElementById("SourceSavedQuery");
var targetSavedQueryFieldset = document.getElementById("TargetSavedQuery");
sourceSavedQuerySelect.options.length = 0;
while (targetSavedQueryFieldset.firstChild) {
targetSavedQueryFieldset.removeChild(targetSavedQueryFieldset.firstChild);
}
savedQueries = responseJson.value;
if (responseJson.value.length >= 1) {
var recordCount = responseJson.value.length;
for (var i = 0; i < recordCount; i++) {
var option = document.createElement('option');
option.value = responseJson.value[i].savedqueryid;
option.text = responseJson.value[i].name;
if (responseJson.value[i].isdefault == true && responseJson.value[i].querytype == 0) {
option.selected = true;
}
sourceSavedQuerySelect.add(option, 0); var checkbox = document.createElement('input');
checkbox.type = "checkbox";
checkbox.name = "savedquerygroup";
checkbox.value = responseJson.value[i].savedqueryid;
checkbox.id = "savedquery" + i;
var label = document.createElement('label');
label.htmlFor = "savedquery" + i;
label.appendChild(document.createTextNode(responseJson.value[i].name));
targetSavedQueryFieldset.appendChild(checkbox);
targetSavedQueryFieldset.appendChild(label);
}
}
}
else {
errorCallback(JSON.parse(this.responseText));
}
}
};
req.send();
}
} function getSaveQueryObj(savedQueryId) {
var returnVal = {};
var recordCount = savedQueries.length;
for (var i = 0; i < recordCount; i++) {
if (savedQueries[i].savedqueryid == savedQueryId) {
returnVal.fetchxml = savedQueries[i].fetchxml;
returnVal.layoutxml = savedQueries[i].layoutxml;
returnVal.savedqueryid = savedQueries[i].savedqueryid;
returnVal.name = savedQueries[i].name;
}
}
return returnVal;
} function Copy() {
var sourceSavedQuerySelect = document.getElementById("SourceSavedQuery");
var sourceSavedQueryId = sourceSavedQuerySelect.options[sourceSavedQuerySelect.selectedIndex].value;
var sourceFetchXml = getSaveQueryObj(sourceSavedQueryId).fetchxml;
var sourceFetchXmlBeforeFilter = "";
var sourceFetchXmlAfterFilter = "";
var sourceFetchXmlFilterStart = sourceFetchXml.indexOf('<filter');
var sourceFetchXmlFilterEnd = sourceFetchXml.lastIndexOf('</filter>');
if (sourceFetchXmlFilterStart >= 0) {
sourceFetchXmlBeforeFilter = sourceFetchXml.substring(0, sourceFetchXmlFilterStart);
sourceFetchXmlAfterFilter = sourceFetchXml.substring(sourceFetchXmlFilterEnd + 9);
}
else {
sourceFetchXmlBeforeFilter = sourceFetchXml;
}
//console.log("source savedquery id=" + sourceSavedQueryId);
//console.log("source savedquery name=" + getSaveQueryObj(sourceSavedQueryId).name);
//console.log("source savedquery fetchxml=" + getSaveQueryObj(sourceSavedQueryId).fetchxml);
//console.log("sourceFetchXmlBeforeFilter=" + sourceFetchXmlBeforeFilter);
//console.log("sourceFetchXmlAfterFilter=" + sourceFetchXmlAfterFilter);
//console.log("source savedquery layoutxml=" + getSaveQueryObj(sourceSavedQueryId).layoutxml);
var selectedTargetSavedQueries = document.forms['myForm'].elements['savedquerygroup'];
var j = 0;
for (var i = 0, len = selectedTargetSavedQueries.length; i < len; i++) {
if (selectedTargetSavedQueries[i].checked) {
//console.log("target savedquery id=" + selectedTargetSavedQueries[i].value);
//console.log("target savedquery name=" + getSaveQueryObj(selectedTargetSavedQueries[i].value).name);
//console.log("target savedquery fetchxml=" + getSaveQueryObj(selectedTargetSavedQueries[i].value).fetchxml);
var targetFetchXml = getSaveQueryObj(selectedTargetSavedQueries[i].value).fetchxml;
var targetFetchXmlFilter = "";
var targetFetchXmlFilterStart = targetFetchXml.indexOf('<filter');
var targetFetchXmlFilterEnd = targetFetchXml.lastIndexOf('</filter>');
if (targetFetchXmlFilterStart >= 0) {
targetFetchXmlFilter = targetFetchXml.substring(targetFetchXmlFilterStart, targetFetchXmlFilterEnd + 9);
}
//console.log("targetFetchXmlFilter=" + targetFetchXmlFilter);
//console.log("new fetchxml=" + sourceFetchXmlBeforeFilter + targetFetchXmlFilter + sourceFetchXmlAfterFilter);
//console.log("target savedquery layoutxml=" + getSaveQueryObj(selectedTargetSavedQueries[i].value).layoutxml); var updateObj = {};
updateObj.fetchxml = sourceFetchXmlBeforeFilter + targetFetchXmlFilter + sourceFetchXmlAfterFilter;
updateObj.layoutxml = getSaveQueryObj(sourceSavedQueryId).layoutxml;
var req = new XMLHttpRequest();
req.open("PATCH", encodeURI(clientUrl + "savedqueries" + "(" + selectedTargetSavedQueries[i].value + ")"), false);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.onreadystatechange = function () {
if (this.readyState == 4 /* complete */) {
req.onreadystatechange = null;
if (this.status == 204) {
j++;
}
else {
errorCallback(JSON.parse(this.responseText));
}
}
};
req.send(JSON.stringify(updateObj));
}
}
Xrm.Utility.alertDialog("成功克隆到" + j + "个视图!");
} function CopyAndPublish() {
Copy();
var pulishObj = {};
pulishObj.ParameterXml = "<importexportxml><entities><entity>" + targetEntityName + "</entity></entities></importexportxml>";
var req = new XMLHttpRequest();
req.open("POST", encodeURI(clientUrl + "PublishXml"), true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.onreadystatechange = function () {
if (this.readyState == 4 /* complete */) {
req.onreadystatechange = null;
if (this.status == 204) {
Xrm.Utility.alertDialog("发布实体【" + targetEntityName + "】成功,去看看效果吧!");
}
else {
errorCallback(JSON.parse(this.responseText));
}
}
};
req.send(JSON.stringify(pulishObj));
} function errorCallback(errorJson) {
console.log(errorJson);
if (typeof errorJson.error.message === "string") {
Xrm.Utility.alertDialog("执行FetchXml出错!" + errorJson.error.message);
}
else {
Xrm.Utility.alertDialog("执行FetchXml出错,请查看console中的输出信息!");
}
}
</script>
</head>
<body onload="initPage()">
<h3>罗勇原创的Dynamics 365公共视图克隆工具_会保留目标视图的筛选条件</h3>
<p>请选择实体: <select id="TargetEntity" onchange="targetEntityOnChange()"><option value="nothing">请选择</option></select></p>
<p>请选择源视图:<select id="SourceSavedQuery"><option value="nothing">请选择</option></select></p>
<form id="myForm" action="#" method="post">
<fieldset id="TargetSavedQuery">
<legend>请选择目标视图</legend>
</fieldset>
</form>
<p><button id="copy" onclick="Copy()">仅复制不发布</button> <button id="copyandpublish" onclick="CopyAndPublish()">复制并且发布</button></p>
</body>
</html>
打开初始界面如下:
我选择一个实体后,源视图会默认为该实体的默认公共视图,当然你可以修改,可以选择一个或者多个目标视图,如下:
我这这里选择复制到两个公共视图。下面有有两个按钮,分别为【仅复制不发布】和【复制并且发布】,前面的按钮仅仅更改,不发布,可以等到一定的量后一起发布,而且发布我们知道也是会锁数据库的,会造成Dynamics 365的卡顿,所以不一定修改后经常发布。若需要复制后立即发布的话点击第二个按钮【复制并且发布】,我这里点击这个按钮,会提示两次,分别如下:
发布后刷新看看效果,目标视图的列和排序和源视图一样了,但是筛选是保留源视图本身的,搞定。
无依赖简单易用的Dynamics 365公共视图克隆工具的更多相关文章
- 无依赖简单易用的Dynamics 365实体记录数计数器并能计算出FetchXml返回的记录数
本人微信公众号:微软动态CRM专家罗勇 ,回复278或者20180812可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!我的网站是 www.luoyong.me . 我们 ...
- 输入输出无依赖型函数的GroovySpock单测模板的自动生成工具(上)
目标 在<使用Groovy+Spock轻松写出更简洁的单测> 一文中,讲解了如何使用 Groovy + Spock 写出简洁易懂的单测. 对于相对简单的无外部服务依赖型函数,通常可以使用 ...
- Dynamics 365 POA表记录的查询
微软动态CRM专家罗勇 ,回复313或者20190311可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!我的网站是 www.luoyong.me . PrincipalO ...
- Dynamics 365出现数据加密错误怎么办?
本人微信公众号:微软动态CRM专家罗勇 ,回复290或者20181227可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!我的网站是 www.luoyong.me . Dy ...
- 为Dynamics 365写一个简单程序实现解决方案一键迁移
关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复258或者20170627可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...
- 工作中经常用到github上优秀、实用、轻量级、无依赖的插件和库
原文收录在我的 GitHub博客 (https://github.com/jawil/blog) ,喜欢的可以关注最新动态,大家一起多交流学习,共同进步,以学习者的身份写博客,记录点滴. 按照格式推荐 ...
- 工作中经常用到 github 上优秀、实用、轻量级、无依赖的插件和库
原文收录在 GitHub博客 ( https://github.com/jawil/blog ) ,喜欢的可以关注最新动态,大家一起多交流学习,共同进步,以学习者的身份写博客,记录点滴. 由于gith ...
- DataAccess通用数据库访问类,简单易用,功能强悍
以下是我编写的DataAccess通用数据库访问类,简单易用,支持:内联式创建多个参数.支持多事务提交.支持参数复用.支持更换数据库类型,希望能帮到大家,若需支持查出来后转换成实体,可以自行扩展dat ...
- Dynamics 365 Online-Relevance Search
区别于Quick Find,以及Full-Text Quick Find,Dynamics 365 Online有了一个特有的Search功能:Relevance Search.至于为什么是Onlin ...
随机推荐
- ArrayList源码理解
ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存. ArrayList不是线程安全的,只能用在单线程环境下,多线程环境下可以考虑用Col ...
- JVM,Tomcat与OSGi类加载机制比较
首先一个思维导图来看下Tomcat的类加载机制和JVM类加载机制的过程 类加载 在JVM中并不是一次性把所有的文件都加载到,而是一步一步的,按照需要来加载. 比如JVM启动时,会通过不同的类加载器加载 ...
- 官方JwPlayer去水印步骤
在前端播放视频,现在用html5的video标签已经是一个不错的选择,不过有时候还是需要用StrobeMediaPlayback.JWPlayer这一类的flash播放器,JWPlayer的免费版本带 ...
- 超有料丨小白如何成功逆袭为年薪30万的Web安全工程师
今天的文章是一篇超实用的学习指南,尤其是对于即将毕业的学生,新入职场的菜鸟,对Web安全感兴趣的小白,真的非常nice,希望大家能够好好阅读,真的可以让你少走很多弯路,至少年薪30万so easy! ...
- [Swift]LeetCode730. 统计不同回文子字符串 | Count Different Palindromic Subsequences
Given a string S, find the number of different non-empty palindromic subsequences in S, and return t ...
- [Swift]LeetCode909. 蛇梯棋 | Snakes and Ladders
On an N x N board, the numbers from 1 to N*N are written boustrophedonically starting from the botto ...
- 非对称加密技术里面,最近出现了一种奇葩的密钥生成技术,iFace人脸密钥技术
要说到非对称加密技术啊,得先说说对称加密技术 什么是对称加密技术 对称加密采用了对称密码编码技术,它的特点是文件加密和解密使用相同的密钥加密. 也就是密钥也可以用作解密密钥,这种方法在密码学中叫做对称 ...
- war包部署到腾讯云中报404的排错经历
项目完成了部分功能,需要把项目放到公网上,方便演示讨论.本来以为挺简单的,直接将war包放到腾讯云服务器tomcat中,结果报错404,第一次碰到这种情况,于是想办法解决,花了一天的时间,终于解决了问 ...
- python预编译函数compile,exec,eval
funcname = "func" func = "def %s():\n" % funcname funccontent = 'print "hel ...
- php的四个fetch语句
先给一个表 man: |---------------| |-name--|-age--| |--AA---|--aa---| |--BB---|--bb---| |--CC---|--cc---| ...