I'm getting this to work if I choose a specific list to add the action to. Is there an easy way to enable this custom action on all document libraries in the whole sitecollection?
Code sample:
function createUserCustomActionList() {
var cmd = "<CommandUIExtension><CommandUIDefinitions><CommandUIDefinition Location=\"Ribbon.Documents.Manage.Controls._children\">" +
"<Button Id=\"DiaryAction.Button\" TemplateAlias=\"o1\" Command=\"DiaryCommand\" CommandType=\"General\" LabelText=\"Dela flera\" Image32by32=\"https://eolusvind.sharepoint.com/sites/intranet/_layouts/15/1033/Images/formatmap32x32.png?rev=23\"" +
" Image32by32Top=\"-271\" Image32by32Left=\"-109\" />" +
"</CommandUIDefinition></CommandUIDefinitions><CommandUIHandlers>" +
"<CommandUIHandler Command =\"DiaryCommand\" CommandAction=\"javascript:alert('Hej');\" EnabledScript=\"javascript:SP.ListOperation.Selection.getSelectedItems().length > 1;\" />" +
"</CommandUIHandlers></CommandUIExtension>";
var ctx = new SP.ClientContext.get_current();
var list = ctx.get_web().get_lists().getByTitle('Dokument');
var uca = list.get_userCustomActions();
var oUserCustomAction = uca.add();
oUserCustomAction.set_location('CommandUI.Ribbon.ListView');
oUserCustomAction.set_commandUIExtension(cmd);
oUserCustomAction.set_sequence(100);
oUserCustomAction.set_title('Dela flera');
oUserCustomAction.update();
ctx.load(list, 'Title' ,'UserCustomActions');
ctx.executeQueryAsync(function () {
alert('Custom action created for ' + list.get_title())
}, function (sender, args) {
alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
});
}
I would suggest the following approach for registering custom button in Documents libraries across site collection:
use RegistrationType set to 2(ContentType) and RegistrationId set to 0x0101 (for Document content type) to register custom action via content type
use site scope user custom action to apply changes across all site
collection
Example
var cmd = "<CommandUIExtension>" +
"<CommandUIDefinitions>" +
"<CommandUIDefinition Location=\"Ribbon.Documents.Manage.Controls._children\">" +
"<Button Id=\"ClickAction.Button\" TemplateAlias=\"o1\" Command=\"ViewCustomPropertiesCommand\" CommandType=\"General\" LabelText=\"View Custom Properties\" Image32by32=\"/_layouts/15/1033/Images/formatmap32x32.png?rev=23\" Image32by32Top=\"-1\" Image32by32Left=\"-171\" />" +
"</CommandUIDefinition></CommandUIDefinitions><CommandUIHandlers>" +
"<CommandUIHandler Command =\"ViewCustomPropertiesCommand\" CommandAction=\"javascript:console.log('View Custom Properties');\" EnabledScript=\"javascript:SP.ListOperation.Selection.getSelectedItems().length > 0;\" />" +
"</CommandUIHandlers>" +
"</CommandUIExtension>";
var ctx = new SP.ClientContext.get_current();
var customAction = ctx.get_site().get_userCustomActions().add(); //1. apply via site scope user custom action
customAction.set_location('CommandUI.Ribbon.ListView');
customAction.set_commandUIExtension(cmd);
customAction.set_sequence(112);
customAction.set_registrationType(2); //2.set to ContentType
customAction.set_registrationId("0x0101"); //2.set Document content type
//customAction.set_title('Document custom button');
customAction.update();
ctx.executeQueryAsync(function () {
console.log('Button has been registered');
}, function (sender, args) {
console.log('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
});
Related
So I have a SP Online list, that every user can submit his entries. I have a default column of "created by", where the user, that submited the entry is listed. I'd like to have 2 other columns, to get users Department and Job Title copied automatically from users account. How can I do this?
Method 1:
You can use the JSOM to set the Department/JobTitle. Because we don't sure where your user from(AD or some else )
First of all you need to load the “SP.UserProfiles.js, SP.Runtime.js and SP.js” js files on your SharePoint page, use following code snippet to load these files,
$(document).ready(function () {
var scriptbase = _spPageContextInfo.webAbsoluteUrl + "/_layouts/15/";
$.getScript(scriptbase + "SP.Runtime.js",
function () {
$.getScript(scriptbase + "SP.js",
function () {
$.getScript(scriptbase + "SP.UserProfiles.js", GetUserInformation);
});
});
});
var userProfileProperties;
function GetUserInformation() {
// Get the current client context.
var clientContext = SP.ClientContext.get_current();
//Get Instance of People Manager Class
var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);
var targetUser = "domain\\userId";
userProfileProperties = peopleManager.getPropertiesFor(targetUser);
//Execute the Query.
clientContext.load(userProfileProperties);
clientContext.executeQueryAsync(onSuccess, onFail); }
function onSuccess () {
// get user information from userProfileProperties and set to your target column.
userProfileProperties.get_userProfileProperties()['Department'];
userProfileProperties.get_userProfileProperties()['SPS-JobTitle'];
// To do: list item replace operation
}
function onFail (sender, args) {
alert("Error: " + args.get_message());
}
Reference:https://msdn.microsoft.com/en-us/library/office/jj679700.aspx
Method 2: Workflow
When user add/edit a item,we trigger the workflow to copy the user's department/JobTitle to target column
Reference for get the Department/Jobtitle.
https://sharepoint.stackexchange.com/questions/97971/get-current-user-information-and-add-to-email-action-in-workflow
I have a document library on SharePoint online with lots of columns for metadata. These columns won't fit in a single view on screen, so I want the users to first view the properties of the file before downloading them.
Is there a way to change the behavior of the SharePoint library ensure that the user views the file properties first when they click on the filename?
PS: I understand I could have used lists, but after loading about 10000 documents, I have decided to use it as a last resort. Thank you.
Custom the LinkFilename field by CSR.
Sample code:
(function () {
'use strict';
var CustomWidthCtx = {};
/**
* Initialization
*/
function init() {
CustomWidthCtx.Templates = {};
CustomWidthCtx.Templates.Fields = {
'LinkFilename': {
'View': customDisplay
}
};
// Register the custom template
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(CustomWidthCtx);
}
/**
* Rendering template
*/
function customDisplay(ctx) {
var currentVal = '';
//from the context get the current item and it's value
if (ctx != null && ctx.CurrentItem != null)
currentVal = ctx.CurrentItem[ctx.CurrentFieldSchema.Name];
var el = "<div class='ms-vb itx' id='" + ctx.CurrentItem.ID + "' app='' ctxname='ctx37'><a title='" + ctx.CurrentItem._ShortcutUrl + "' class='ms-listlink ms-draggable' aria-label='Shortcut file' onfocus='OnLink(this)' href='/Doc4/Forms/EditForm.aspx?ID=" + ctx.CurrentItem.ID + "' target='_blank' DragId='17'>" + ctx.CurrentItem.FileLeafRef + "</a></div>";
// Render the HTML5 file input in place of the OOTB
return el;
}
// Run our intiialization
init();
})();
I have a column which type is SPGroup in a list. I want to get items via SharePoint REST API, and I only need the items which SPGroup contains the current user. So what's the URL? Thank you for your advice!
You can use the $expand parameter in your REST query to include related entities of data in your query, but since the SharePoint REST service implements the OData protocol, the $filter method can only be invoked on the top level item, thus making it impossible to use on an expanded field.
Depending on how many items your list contains, I'd suggest that you either try to filter it on something other than the current user, or fetch everything and filters the result in your code instead.
A REST query would look something like this:
http://sp/_api/web/lists/getbytitle('MyList')/items?$select=Id,Title,Members/Id&$expand=Members where Members is the SPGroup to be expanded.
In each item that is returned, you will get something like
<content type="application/xml">
<m:properties>
<d:Id m:type="Edm.Int32">60</d:Id>
</m:properties>
</content>
with the Id value of the member. From this, you should be able to write some custom code to filter out only the items that contain the current logged in user.
You can still do what you're looking to do with good old fashioned SOAP with less of headache. I use this method to get Tasks assigned to a user's account or a group they're a member of.
function getAssignedToMe(){
var viewFields = '<ViewFields><FieldRef Name="ID" /><FieldRef Name="Title" /><FieldRef Name="Created" /><FieldRef Name="FileRef" />'
+'<FieldRef Name="AssignedTo" /><FieldRef Name="Status" /></ViewFields>';
// filter by AssignedTo is current user ID or assigned to the current user's group;
var camlQuery = '' +
'<Query>' +
'<Where>' +
'<And>' +
'<Or>' +
'<Membership Type="CurrentUserGroups"><FieldRef Name="AssignedTo"/></Membership>' +
'<Eq><FieldRef Name="AssignedTo"/><Value Type="Integer"><UserID/></Value></Eq>' +
'</Or>' +
'<And>' +
'<Neq><FieldRef Name="Status"/><Value Type="Text">Completed</Value></Neq>' +
'<Geq><FieldRef Name="Created" /><Value Type="DateTime"><Today OffsetDays="-60" /></Value></Geq>' +
'</And>' +
'</And>' +
'</Where>' +
'<OrderBy><FieldRef Name="Created" Ascending="TRUE"/></OrderBy>' +
'</Query>';
getListItems('/mysite', 'Tasks', viewFields, camlQuery, callback, 50);
// transform the returned XML to JSON
function callback(xmlDoc){
var data = [];
$(xmlDoc).find('*').filter(function () {
return this.nodeName.toLowerCase() == 'z:row';
}).each(function (i, el) {
// do something with the data
var id = parseInt($(el).attr('ows_ID'));
data.push({
Id: id
});
/* ... */
});
};
};
function getListItems(siteUrl, listName, viewFields, query, callback, rowLimit) {
if (rowLimit === void 0) { rowLimit = 25; }
var packet = '<?xml version="1.0" encoding="utf-8"?>' +
'<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">' +
'<soap:Body>' +
'<GetListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/">' +
'<listName>' + listName + '</listName>' +
'<query>' + query + '</query>' +
'<viewFields>' + viewFields + '</viewFields>' +
'<rowLimit>' + rowLimit + '</rowLimit>' +
'</GetListItems>' +
'</soap:Body>' +
'</soap:Envelope>';
var $jqXhr = $.ajax({
url: siteUrl + '/_vti_bin/lists.asmx',
type: 'POST',
dataType: 'xml',
data: packet,
headers: {
"SOAPAction": "http://schemas.microsoft.com/sharepoint/soap/GetListItems",
"Content-Type": "text/xml; charset=utf-8"
}
}).done(function (xmlDoc, status, error) {
callback(xmlDoc);
}).fail(function (jqXhr, status, error) {
callback(null, status + ': ' + error);
});
};
This doesn't work. Here cl is xmpp-client object of who wants to leave from group.
cl.on('online', function (userData) {
var userJid = userData.jid.user + '#' + userData.jid.domain + "/" + userData.jid.resource,
roomJid = params.typeId + params.service + userData.jid.domain + '/' + params.userName;
pres = new xmpp.Element('presence', {
from : userJid,
to : roomJid, //54d213e000e9e50c4e8e5a2b#conference.domain/nickName
type : 'unavailable',
xmlns : 'jabber:client'
});
status = cl.send(pres);
});
I have built my site based around the user management that comes with the starter site template. This works very well, except i need to modify it slightly for my use case. Let me explain:
Currently, when a new user registers, the user is created in the database, but does not let users access any pages that are secured using "WebSecurity.RequireAuthenticatedUser();" until they open and click a confirmation email....
I want to allow users access to certain parts of my site before they confirm their email, is this possible?
Should i be using a different method to WebSecurity.RequireAuthenticatedUser()?
Should i be removing the "requireEmailConfirmation" switch when creating the user??
Currently, it looks like this:
try {
bool requireEmailConfirmation = !WebMail.SmtpServer.IsEmpty();
var token = WebSecurity.CreateAccount(email, password, requireEmailConfirmation);
if (requireEmailConfirmation) {
var hostUrl = Request.Url.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped);
var confirmationUrl = hostUrl + VirtualPathUtility.ToAbsolute("~/owner/confirm?confirmationCode=" + HttpUtility.UrlEncode(token));
var details = "X-MC-MergeVars: {\"FIRSTNAME\": \"" + firstname + "\", \"LASTNAME\": \"" + lastname + "\", \"CONFIRMADDRESS\": \"" + confirmationUrl + "\"}";
var header = new[]{"X-MC-Template:registertemplate", "Reply-To:noreply#stayinflorida.co.uk", details};
WebMail.Send(
to: email,
subject: "Please confirm your account",
body: "Your confirmation code is: " + token + ". Visit " + confirmationUrl + " to activate your account.",
additionalHeaders: header
);
}
if (requireEmailConfirmation) {
// Thank the user for registering and let them know an email is on its way
Response.Redirect("~/owner/thanks");
} else {
// Navigate back to the homepage and exit
WebSecurity.Login(email, password);
Response.Redirect("~/");
}
} catch (System.Web.Security.MembershipCreateUserException e) {
ModelState.AddFormError(e.Message);
}
for pages they must be registered to use
This goes at the top
#{
if (!WebSecurity.IsAuthenticated) {
Response.Redirect("~/Account/Login?returnUrl="
+ "~/AllRaces.cshtml");
}
Layout = "~/_SiteLayout.cshtml";
Page.Title = "Upcoming";
}
For pages anyone can look at
this goes at the top
#{
Layout = "~/_SiteLayout.cshtml";
Page.Title = "Contact";
}