Reading parameters in an SDL Tridion 2011 publish dialog extension - tridion

I've built a GUI extension to 'inject' my own JavaScript into the SDL Tridion 2011 publish dialog (as explained in this post and comment: http://albertromkes.wordpress.com/2012/01/30/tridion-gui-extensions-how-to-load-a-javascript-without-showing-a-gui-element/)
I see in SDL Tridion's publish dialog (publish.js) that the publish dialog takes some parameters (not on the URL), these are passed in. For example:
var p = this.properties;
if (p.params && p.params.items && p.params.items.length > 0)
So in my JavaScript I'd like to get hold of the properties.params.items but I cannot seem to get hold of it.
My JavaScript code is inserted 'after' the publish view has loaded:
<cfg:extension target="Tridion.Web.UI.Editors.CME.Views.Popups.Publish">
<cfg:insertafter>Extensions.Resources</cfg:insertafter>
</cfg:extension>
And in my JavaScript (and in Firebug Console) I've tried to obtain the value using $display.getView().properties, but this returns a null object.
I've been using Firebug to look around the window, $display and various other objects, but cannot see a way to get to the params object.
My JavaScript looks like this:
$evt.addEventHandler($display, "start", itemsForPublish);
function itemsForPublish() {
var p = $display.getView().properties;
var items = p.params.items || [];
alert(items);
}

This should work:
function itemsForPublish() {
alert(window.dialogArguments.items);
}
In the 'Publishing.js' (and in 'Publish.js') you can see that the items to publish are send to the Popups' dialogArguments.

Related

Alfresco Object is not available in extension module in alfresco share

I am trying to override the javascript controller node-header.js of components\node-details with the extension module of alfresco share
This is my node-header.get.js
<import resource="classpath:/alfresco/templates/org/alfresco/import/alfresco-util.js">
for (var i=0; i<model.widgets.length; i++)
{
if (model.widgets[i].id == "NodeHeader")
{
if(model.widgets[i].options.nodeRef!=null)
{
var jsNode = new Alfresco.util.Node(model.widgets[i].options.nodeRef);
if(jsNode.hasAspect("custom:intranetFile")){
model.widgets[i].options.showFavourite = false;
model.widgets[i].options.showLikes = false;
}
}
}
}
I am getting this error
Error Message: 05270002 Failed to execute script
'classpath*:webscripts/custom/nodeheader/hidelikesync/node-header.get.js':
05270001 ReferenceError: "Alfresco" is not defined.
(jar:file:/C:/Alfresco/Alfresco42/tomcat/webapps/share/WEB-INF/lib/customshare.jar!/webscripts/custom/nodeheader/hidelikesync/node-header.get.js#1555)
Error lies in this line
var jsNode = new Alfresco.util.Node(model.widgets[i].options.nodeRef);
as Alfresco object is not available how can I get it?
Based on my answer yesterday on the share-extras-devel list:
Your issue is that you are mixing up your web script JS with client-side JavaScript. Alfresco.util.Node is a client-side helper class and is therefore available to client-side JS running in the web browser, but not to your web script code which runs on the server.
If you look at the source of alfresco-util.js, which you are including, you will see that there is a helper class there but it is called AlfrescoUtil.
To get some information on this given node I would suggest that you want to use the static method AlfrescoUtil.getNodeDetails() from that class, e.g.
var jsNode = AlfrescoUtil.getNodeDetails(model.widgets[i].options.nodeRef);
The structure of the jsNode object will be as per the JSON returned by the doclist-v2 webscripts, so you should be able to check for the presence of your custom aspect in the aspects array property.
If you check the source of alfresco-util.js you will see that additional parameters are also supported by getNodeDetails(). It seems to me you can also pass in an optional site name, plus some options if you wish.

Get shared pages using localized component

I'm currently working on a event handler, which will on save-event, save the latest revision date of the page and it's components into a custom database, and this is working, but i'm facing some performance issues.
Let me give you an example, for how it's working:
If a component is saved/updated (changes are made), then I want to update all pages using this component in my custom database.
Basic blueprint setup:
200 contains components
400 translation publication for components (inherent components from 200)
500 master publication for pages
600 local site publication inherent components from 400 and pages from 500)
So lets say we have component X in 200, this component is included in in a page in 500, X is localized in 400 (let us call it X(l)) and the page in 600 is NOT localized ( i.e it will use the component x(l))
So now to my question:
In my save event handler, i check what pages X(l) are included in , by using :
var filter = new UsingItemsFilter(component.Session)
{
IncludeLocalCopies = true,
ItemTypes = new[] { ItemType.Page }
};
but this will only give me references to pages from 500.
So what i then do (which feels kind of stupid) is to
create a tcm id of all pages in child publications(by looping over them) that inherent this page (now im using some psuedocodelike coding):
foreach(var 500page in foundPages)
foreach(var publication in publications){
if(subject.Session.IsExistingObject(
new TcmUri(page.Id.ItemId,page.Id.ItemType,publication.Id.ItemId)
))
{
someListThatWillContainAllChildPagesFrom500.Add(TheAboveTcmUri);
}
}
And then for each page, check the components in that page, and finally save this state to my custom database.
So the question is, is there a way by to query for all pages, that make use of the localized component, by using the TOM.NET api (no not CoreServiceClient)?
Is there a better way to find child publications of a publication, so I only need to check for pages in the childPublication?
Br Martin
The following code sample should give you the shared items of a specific local/localized item along with the item. BluePrintNodesFilter was introduced in 2013, however in earlier version BluePrintFilter should work in similar way.
SystemManager systemManager = session.SystemManager;
BluePrintNodesFilter filter = new BluePrintNodesFilter(session)
{
BaseColumns = ListBaseColumns.Id,
ForItem = page
};
IEnumerable<BluePrintNode> allNodes = systemManager.GetBluePrintNodes(filter);
IEnumerable<RepositoryLocalObject> sharedAndLocal = (from node in allNodes
where node.Item != null
where node.Item.OwningRepository.Id == page.OwningRepository.Id
select node.Item).ToArray();

writing a library class properly

This is my very first library class that i am writing and i feel like i need to load up on that topic but cannot find the best sources. I have a web forms project that uploads a pdf and creates a qrcode for it and places it in the document. I need to create a library but don't know where to start or the exact structure. Every method it's own subclass in the library class? or can i have them all in one and what is a professional way of going about this.
This is party of my web forms application that i need to create a library for:
void UpdateStudentSubmissionGrid()
{
var usr = StudentListStep2.SelectedItem as User;
var lib = AssignmentListStep2.SelectedItem as Library;
if (usr == null || lib == null) return;
using (var dc = new DocMgmtDataContext())
{
var subs =
(from doc in dc.Documents
where doc.OwnedByUserID == usr.ID && doc.LibraryID == lib.ID
select new {DocID = doc.ID, Assignment = doc.Library.Name, Submitted = doc.UploadDT})
.OrderByDescending(c => c.Submitted)
.ToList();
StudentSubmissionGrid.DataSource = subs;
}
}
How do i start with this method?
By the looks of things you are using this function for a single webpage. You can call that function from any event i.e. user hits submit button. On the. Click the button and it will create a onclick event. Call the code from inside there UpdateStudentSubmissionGrid(); Just make sure the function is not nested inside another event or function. Webforms is already a class, you are just placing a function within the class.

SDL Tridion GetListKeywords using Anquilla Framework

I'm writing a GUI extension and using the Anquilla framework to get a list of Keywords within a Category. I'm obtaining an XML document for the list of keywords then working with that document within my extension.
My problem is that the returned XML doesn't contain the Keyword's 'Description' value. I have the Title and Key etc.
My original code looks like this:
var category = $models.getItem("CATEGORYTCMID:);
var list = category.getListKeywords();
list.getXml();
A typical node returned is this:
<tcm:Item ID="tcm:4-1749-1024"
Type="1024" Title="rate_one" Lock="0" IsRoot="true"
Modified="2012-12-17T23:01:59" FromPub="010 Schema"
Key="rate_one_value" IsAbstract="false"
CategoryTitle="TagSelector"
CategoryID="tcm:4-469-512" Icon="T1024L0P0"
Allow="268560384" Deny="96" IsNew="false"
Managed="1024"/></tcm:ListKeywords>
So I've tried using a Filter to give me additional column information:
var filter = new Tridion.ContentManager.ListFilter();
filter.columns = Tridion.Constants.ColumnFilter.EXTENDED;
var list = category.getListKeywords(filter);
Unfortunately this only gives the additional XML attributes:
IsShared="true" IsLocalized="false"
I'd really like the description value to be part of this XML without having to create a Keyword object from the XML. Is such a thing possible?
cough any ideas? cough
I'm afraid you'll have to load the Keyword itself to get the Description.
It's not used in any lists, so it's not returned in the XML.
You could always create a List Extender to add this information to the list, but try to be smart about it since this extender will execute everytime a GetList is called.
Won't save you from having to open every keyword in the list, but you'll be doing it server-side (with Core Service/NetTcp for instance) which will probably be easier and faster than opening each keyword with Anguilla.
In this instance I only need the one keyword, so I simply get it from the CMS. Getting an object in Anguilla is a bit weird, here's the code:
In your main code area:
var selectedKy = $models.getItem("TcmUriOfKeywordHere");
if (selectedKy.isLoaded()) {
p.selectedKy = selectedKy;
this.onselectedKyLoaded();
} else {
$evt.addEventHandler(selectedKy, "load", this.onselectedKyLoaded);
selectedKy.load();
}
It's worth noting how I store the keyword in the properties of the item, so I can obtain it in the onselectedKyLoaded function
The function called once the item is loaded
ContentBloom.ExampleGuiExtension.prototype.onselectedKyLoaded = function (event) {
var p = this.properties;
var selectedDescription = p.selectedKy.getDescription();
// do what you need to do with the description :)
};
I resolved this, thanks to the answer here: https://stackoverflow.com/a/12805939/1221032 - Cheers Nuno :)

FileReference.load() does not as excepted

I used Flash player 10, and Flex SDK 3.4. The code as followings:
// Following comes callbacks
function imageLoadOpenCallback(evt:Event):void
{
trace("in--open");
}
function imageLoadCompleteCallback(evt:Event):void
{
trace("in--load");
var fr:FileReference = evt.target as FileReference;
trace(fr.data);
}
function imageLoadErrorCallback(evt:IOErrorEvent):void
{
trace("in--ioerror");
}
function imageSelectCancelCallback(evt:Event):void
{
trace("in cancel");
}
function imageSelectCallback(evt:Event):void
{
trace("in -- select");
for (var i:int=0; i<frl.fileList.length; i++)
{
frl.fileList[i].addEventListener(Event.OPEN, imageLoadOpenCallback);
frl.fileList[i].addEventListener(Event.COMPLETE, imageLoadCompleteCallback);
frl.fileList[i].addEventListener(IOErrorEvent.IO_ERROR, imageLoadErrorCallback);
frl.fileList[i].load();
trace(frl.fileList[i]);
trace(frl.fileList[i].creationDate);
trace(frl.fileList[i].creator);
trace(frl.fileList[i].data);
trace(frl.fileList[i].name);
}
}
// Following comes UI handlers
function onAddPictures():void
{
var imageFilter:FileFilter = new FileFilter("Images", "*.jpg;*.png");
frl.addEventListener(Event.SELECT, imageSelectCallback);
frl.addEventListener(Event.CANCEL, imageSelectCancelCallback);
frl.browse([imageFilter]);
}
Only the imageSelectCancelCallback handler get called when I select some files in the dialog. But no load/open/io_error handler get called at all. I have Google some code example, in which it used FileReference instead of FileReferenceList. I don't know the reason, could you please help me?
In Air the fileReference objects in fileReferenceList do not fire the complete event when doing fileList[i].load(). In a Flex project it works fine. Adobe has not responded to bug reports on this appropriately.
Make sure in your compiler settings for flex, that you have at least 10.0.0 for "Use a specific version".
The main reason to use FileReferenceList instead of FileReference would be if you need to upload multiple files at once. If you only want to allow uploading one file at once, simply use FileReference.
Some clarification: imageSelectCallback(), and NOT imageSelectCancelCallback(), should get called when you select some files in the file browser AND click OK. imageSelectCancelCallback() is only called when you click Cancel.
Other than that, I never used the load() API, but I did use the upload(URLRequest) API. I am not sure what's your use case, but if you need to upload an image to a server, you should use the upload() method.
Speaking of upload events, I experienced some reliability issues when listening to Event.COMPLETE events, so I actually got better results listening to DataEvent.UPLOAD_COMPLETE_DATA.

Resources