I am using the following SSJS:
var author = #Author().toString();
var str = author.replace("CN=","");
var str2 = str.replace("O=","");
var str3 = str2.replace("[","");
var str4 = str3.replace("]","");
if("" == str4)
return #Name("[CN]",session.getEffectiveUserName());
else
return var4;
not the perfect way to do it, but...
Question: Why do I get all the users which edited the document in this field? I only want to show the Author of the document.
You get a list of all users because that's what #Author() returns. Here is the description of the function taken from the online help: "Returns the names of the authors of the current document."
You can use #Subset() to get the latest author:
#Subset(#Author(), -1)
and to get the original author:
#Subset(#Author(), 1)
Use #Name() to format the name. So to only show the common name part of the original author, do this:
#Name("[CN]",#Subset(#Author(), 1))
Related
So as some context, I have a dictionary which holds some custom error messages, based on the error code returned by Parse. You can see one below:
var parseErrorDict: [Int:String] = [
203: "This email address \(emailTextField.text) is already registered."
]
What I would like, is the email address that will be populated to be a different colour or to be in Bold. Is this possible?
Fairly new to Swift so please explain or help clearly :) Thanks in advance.
You want to use an attributed string to edit different parts of the string. You would first break down the string into three parts in your case, the start, middle and end. Then you can add attributes to these three parts, e.g. make the middle part (email address) red, then you can append the three parts back together again:
// The first part of the string should be mutable as parts will be appended to it
var attributedString = NSMutableAttributedString(string: "This email address ")
// Here we specify the attribute that is will be applied to the middle part
var attributes = [NSForegroundColorAttributeName: UIColor.redColor()]
var attributedStringEmail = NSAttributedString(string: "someone#somewhere.com", attributes: attributes)
// The end part
var attributedStringEnd = NSAttributedString(string: " is already registered.")
// Combine the three parts
attributedString.appendAttributedString(attributedStringEmail)
attributedString.appendAttributedString(attributedStringEnd)
// Give the label its text
label.attributedText = attributedString
I have a multivalue field called freeDaysPool which has multiple dates as strings. With the following code, the search does not return anything. If I leave that field out, the search works just fine with the two other fields. I read that I should use CONTAINS with multivalue fields but then I got query not understandable.
I've tried the back-end field as a date field and as a text field and tested all kinds of query combinations and date formats but no luck. Any help is really appreciated.
This is the search button code:
var query = new Array("");
var cTerms = 0;
// Field 1
var search01 = getComponent("searchcustomReservationField01").getValue();
if (#Contains(#Text(search01),"any city")){"";}
else {query[cTerms++] = '[customReservationField01]="' + search01 +'"'};
// Field 2
var search02 = getComponent("searchcustomReservationField02").getValue();
if (#Contains(#Text(search02),"any city")){"";}
else {query[cTerms++] = '[customReservationField02]="' + search02 + '"'};
// Date 1
var formatter = new java.text.SimpleDateFormat("d.M.yyyy");
query[cTerms++] = 'FIELD freeDaysPool = ' + formatter.format(getComponent("searchcustomDateField01").getValue());
// if query is still empty, we fill it with asterisk
if(query == "" || query == null){
query[cTerms++] = "*";
}
// make all as string
qstring = query.join(" AND ").trim();
sessionScope.searchString = qstring;
It will return query as:
[customReservationField01]="Oslo" AND [customReservationField02]="Oslo" AND FIELD freeDaysPool = 6.2.2015
AFAIK date values in formulas (and a query is a formula) have to be noted like
[06.02.2015]
to compare them. Just try to use your formular in the Notes Client to do a fulltext search. If you get results and no errors you found the correct format. That's at least the way I test queries as I'm not able to remind the syntax for years :-D
Thank you for all the help! Seems that Domino keeps the field type as date field even if you change it back to text field (noticed that from the notes FTsearch). I created completely new text field and added the days as strings in dd.MM.yyyy format. I also search them as strings and it works fine.
The changed code bit now looks like this:
// Date 1
var formatter = new java.text.SimpleDateFormat("dd.MM.yyyy");
query[cTerms++] = '[freeDays] CONTAINS "' + formatter.format(getComponent("searchcustomDateField01").getValue())+'"';
I am using #NameLookUp formula to retrieve internet address by giving a search key and it is working fine.But now i want to retrive not only the internet address but also some other properties like FirstName and LastName.
Here is the formula i am using to #Namelookup internet address by giving search string.
Vector vec=m_session.evaluate("#NameLookup([NoUpdate];\""+ userName + "\"; \"InternetAddress\")");
//username is the String variable(Search Criteria)
Can anyone please help how to retrieve multiple properties(like firstName and lastName along with InternetAddress) by evaluate the formula only once. If it cant be done using #Namelookup is there any other way..?
This is a typical example when using evaluate() to call a Formula is not a good idea.
What you want to do is to get the NotesDocument class and read values from it.
Something like this (disclaimer, I am not a Java developer):
// Open Domino Directory on specified server
Database db = session.getDatabase("YourServer/Domain", "names.nsf");
// Get a view with user name is sorted first column
View view = db.getView("($Users)");
// Get the person document for specified user
Document doc = view.getDocumentByKey(userName, true);
if (doc != null) {
// Get text values from Notes document
String emailAddress = doc.getItemValueString("InternetAddress");
String officePhone = doc.getItemValueString("OfficeNumber");
String officeAddress = doc.getItemValueString("OfficeStreetAddress");
}
I believe this would be faster than multiple lookups using evaluate(), and you also have the added benefit of full error handling, and all being native code.
#NameLookup only returns the value of one item per call.
Assuming your goal is to only have one Evaluate statement, you could chain the calls together and return an array of values in a certain order:
Vector vec=m_session.evaluate("FirstName := #NameLookup([NoUpdate];\""+ userName + "\"; \"FirstName\"); LastName:= #NameLookup([NoUpdate];\""+ userName + "\"; \"LastName\"); InternetAddress :=#NameLookup([NoUpdate];\""+ userName + "\"; \"InternetAddress\"); FirstName:LastName:InternetAddress");
Or possibly:
String firstName = m_session.evaluate("#NameLookup([NoUpdate];\""+ userName + "\"; \"FirstName\")");
String lastName = m_session.evaluate("#NameLookup([NoUpdate];\""+ userName + "\"; \"LastName\")");
String internetAddress = m_session.evaluate("#NameLookup([NoUpdate];\""+ userName + "\"; \"InternetAddress\")");
And then add those three strings in any order into your Vector.
Another approach is to use the DirectoryNavigator class. I believe it's been available since Notes/Domino 8.5 (perhaps even before that). DirectoryNavigator uses some of the same core logic as #NameLookup, so it should perform well.
Here's some sample code. I haven't tested this exact code, but I adapted it from production code that does a similar lookup:
String firstName = null;
String lastName = null;
String inetAddress = null;
Vector<String> lookupItems = new Vector<String>();
lookupItems.addElement("FirstName");
lookupItems.addElement("LastName");
lookupItems.addElement("InternetAddress");
Vector<String> vName = new Vector<String>();
vName.addElement(userName);
Directory dir = session.getDirectory();
DirectoryNavigator dirNav = dir.lookupNames("($Users)", vName, lookupItems, true);
if( dirNav != null && dirNav.getCurrentMatches() != 0 ) {
// Digest the results of the lookup
Vector<String> value = null;
value = dirNav.getFirstItemValue();
firstName = value.elementAt(0);
value = dirNav.getNextItemValue();
lastName = value.elementAt(0);
value = dirNav.getNextItemValue();
inetAddress = value.elementAt(0);
}
Recently I've started using Apache CMIS and read the official documentation and examples. I haven't noticed anything about paging query results.
There is an example showing how to list folder items, setting maxItemsPerPage using operationContext, but it seems that operationContext can be used inside getChilder method:
int maxItemsPerPage = 5;
int skipCount = 10;
CmisObject object = session.getObject(session.createObjectId(folderId));
Folder folder = (Folder) object;
OperationContext operationContext = session.createOperationContext();
operationContext.setMaxItemsPerPage(maxItemsPerPage);
ItemIterable<CmisObject> children = folder.getChildren(operationContext);
ItemIterable<CmisObject> page = children.skipTo(skipCount).getPage();
This is ok when it comes to listing u folder. But my case is about getting results from custom search query. The basic approach is:
String myType = "my:documentType";
ObjectType type = session.getTypeDefinition(myType);
PropertyDefinition<?> objectIdPropDef = type.getPropertyDefinitions().get(PropertyIds.OBJECT_ID);
String objectIdQueryName = objectIdPropDef.getQueryName();
String queryString = "SELECT " + objectIdQueryName + " FROM " + type.getQueryName();
ItemIterable<QueryResult> results = session.query(queryString, false);
for (QueryResult qResult : results) {
String objectId = qResult.getPropertyValueByQueryName(objectIdQueryName);
Document doc = (Document) session.getObject(session.createObjectId(objectId));
}
This approach will retrieve all documents in a queryResult, but I would like to include startIndex and limit. The idea would be to type something like this:
ItemIterable<QueryResult> results = session.query(queryString, false).skipTo(startIndex).getPage(limit);
I'm not sure about this part: getPage(limit). Is this right approach for paging? Also I would like to retrieve Total Number of Items, so I could know how to set up the max items in grid where my items will be shown. There is a method, but something strange is written in docs, like sometimes the repository can't be aware of max items. This is that method:
results.getTotalNumItems();
I have tried something like:
SELECT COUNT(*)...
but that didn't do the trick :)
Please, could you give me some advice how to do a proper paging from a query result?
Thanks in advance.
Query returns the same ItemIterable that getChildren returns, so you can page a result set returned by a query just like you can page a result set returned by getChildren.
Suppose you have a result page that shows 20 items on the page. Consider this snippet which I am running in the Groovy Console in the OpenCMIS Workbench against a folder with 149 files named testN.txt:
int PAGE_NUM = 1
int PAGE_SIZE = 20
String queryString = "SELECT cmis:name FROM cmis:document where cmis:name like 'test%.txt'"
ItemIterable<QueryResult> results = session.query(queryString, false, operationContext).skipTo(PAGE_NUM * PAGE_SIZE).getPage(PAGE_SIZE)
println "Total items:" + results.getTotalNumItems()
for (QueryResult result : results) {
println result.getPropertyValueByQueryName("cmis:name")
}
println results.getHasMoreItems()
When you run it with PAGE_NUM = 1, you'll get 20 results and the last println statement will return true. Also note that the first println will print 149, the total number of documents that match the search query, but as you point out, not all servers know how to return that.
If you re-run this with PAGE_NUM = 7, you'll get 9 results and the last println returns false because you are at the end of the list.
If you want to see a working search page that leverages OpenCMIS and plain servlets and JSP pages, take a look at the SearchServlet class in The Blend, a sample web app that comes with the book CMIS & Apache Chemistry in Action.
I have a plugin where i am creating a new case and I want to send an email out as it is created including its ticketnumber. I have attempted just to call this in the plugin but it is coming back saying that it is not present in the dictionary. I know this field is populated using CRM's own autonumbering so what i'm guessing is happening is that my plugin is firing and creating the case but then i'm trying to use this field before the autonumber has completed.
So is there a way that i can get my plugin to "wait" until this field is available and then use it?
Thanks
EDIT: Code below:
string emailBody = entity.Attributes["description"].ToString();
int bodyLength = emailBody.Length;
int textStart = emailBody.IndexOf(">") + 1;
int newLength = bodyLength - (textStart + 7);
string description = emailBody.Substring(textStart, newLength);
//create complaint
Entity complaint = new Entity("incident");
complaint["description"] = description;
complaint["ts_case_type"] = 717750001;
complaint["ts_registration_datetime"] = DateTime.Now;
complaint["ownerid"] = Owner;
complaint["customerid"] = Organisation;
Service.Create(complaint);
As a side I would suggest sending the email with a workflow if possible, it will be far easier to maintain in the long run and quicker to implement in the short.
In any case to answer your question, from what you have here you need to update your code to retrieve the ticketnumber once you have created the incident. You can do this with a Retrieve message.
For example:
//Create the complaint
Entity complaint = new Entity("incident");
//This is the information that is being sent to the server,
//it will not be updated by CRM with any additional information post creation
complaint["description"] = description;
complaint["ts_case_type"] = 717750001;
complaint["ts_registration_datetime"] = DateTime.Now;
complaint["ownerid"] = Owner;
complaint["customerid"] = Organisation;
//Capture the id of the complaint, we will need this in a moment
Guid complaintId = Service.Create(complaint);
//complaint["ticketnumber"] <-- The server does not populate this information in your object
//Retrieve the ticketnumber from the incident we just created
Entity complaintRetrieved = service.Retrieve("incident", complaintId, new ColumnSet("ticketnumber"));
//Get the ticketnumber
String ticketNumber = (String)complaintRetrieved.Attributes["ticketnumber"];
Like James said in comment, if you just want to send email with some case properties, it is best to do that with workflow (on case create).
In your plugin, ID is generated, and you can get it with:
entity.Attributes["ticketnumber"]