123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625 |
- /*
- *+------------------------------------------------------------------------+
- *| Licensed Materials - Property of IBM
- *| IBM Cognos Products: Viewer
- *| (C) Copyright IBM Corp. 2001, 2013
- *|
- *| US Government Users Restricted Rights - Use, duplication or
- *| disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
- *|
- *+------------------------------------------------------------------------+
- */
- dojo.provide("viewer.AnnotationHelper");
- dojo.declare("viewer.AnnotationHelper", null, {
- m_loadAnnotationsDfd : null,
- //This records if any annotation is returned on the first getAnnotation call. if none is returned, we want to skip getAnnotation call.
- //default value is true. responseHandler of getAnnotations update this flag accordingly.
- //If a user select 'reset' action, this flag reset to 'true' so that we issue getAnnotation call.
- m_bCallGetAnnotations : true,
- m_bAnnotationsEnabled : null,
- constructor : function(iWidget) {
- this.m_viewerIWidget = iWidget;
- this.m_bCallGetAnnotations = true;
- this.m_bAnnotationsEnabled = null;
- },
- getAnnotationStore : function() {
- return this.m_viewerIWidget.getAnnotationStore();
- },
- setCallGetAnnotations : function(flag) {
- this.m_bCallGetAnnotations = flag;
- },
- isEnabled : function() {
- if(this.m_bAnnotationsEnabled === null) {
- this.m_bAnnotationsEnabled = this.m_viewerIWidget.getViewerObject().bBuxAnnotationsAvailable;
- }
- return this.m_bAnnotationsEnabled;
- },
- refreshAnnotationData : function() {
- if(this.m_loadAnnotationsDfd) {
- return null;
- }
- this.m_loadAnnotationsDfd = new dojo.Deferred();
- this.fetchAnnotationData();
- return this.m_loadAnnotationsDfd;
- },
- /**
- * Sends a request to the server for the latest annotation data
- */
- fetchAnnotationData : function() {
- var viewerIWidget = this.m_viewerIWidget;
- if (!this.m_bCallGetAnnotations || !this.isEnabled()) { //stop proceede if the flag is false
- return;
- }
- dojo.when(viewerIWidget.getWidgetStoreID(),
- dojo.hitch(this, function(widgetStoreID) {
- if(!widgetStoreID) {
- return;
- }
- this.m_viewerIWidget.getLoadManager().runWhenHasViewer(
- dojo.hitch(this, this._fetchAnnotationData, widgetStoreID)
- );
- })
- );
- },
- _fetchAnnotationData: function(widgetStoreID) {
- var cognosViewer = this.m_viewerIWidget.getViewerObject();
- var selCon = cognosViewer.getSelectionController();
- var metadata = selCon.getCCDManager().m_md;
- if(!metadata) {
- metadata = {};
- }
- metadata = dojo.toJson(metadata);
- var contextData = selCon.getCCDManager().m_cd;
- if(!contextData) {
- contextData = {};
- }
- contextData = dojo.toJson(contextData);
- var callbacks = {"complete":{}, "fault": {}};
- callbacks.complete["object"] = this;
- callbacks.complete["method"] = this.fetchAnnotationDataResponse;
- callbacks.fault["object"] = this;
- callbacks.fault["method"] = this.fetchAnnotationDataResponseFault;
- var asynchRequest = new AsynchJSONDispatcherEntry(cognosViewer);
- asynchRequest.setCallbacks(callbacks);
- asynchRequest.addFormField("widgetStoreID", widgetStoreID);
- asynchRequest.addFormField("ui.action", "getAnnotations");
- asynchRequest.addFormField("cv.metatdata", metadata);
- asynchRequest.addFormField("cv.context", contextData);
- // Need to bypass the queue for this request since it's a background request and
- // we don't want other requests (actions) to get dropped from the queue
- asynchRequest.sendRequest();
- },
- fetchAnnotationDataResponseFault: function(oAsynchResponse) {
- this.m_bCallGetAnnotations = false;
- var oFaultDialog = new FaultDialog(this.m_viewerIWidget.getViewerObject());
- var oSoapFault = oAsynchResponse.getSoapFault();
- var sErrorCode = null;
- var nException = XMLHelper_FindChildByTagName(oSoapFault, "exception", true);
- if(nException) {
- var nErrorCode = XMLHelper_FindChildByTagName(nException, "errorCode", false);
- if(nErrorCode) {
- sErrorCode = XMLHelper_GetText(nErrorCode);
- }
- }
- if(sErrorCode === "0") {
- var sMessage = null;
- var nMessage = XMLHelper_FindChildByTagName(nException, "message", false);
- if(nMessage) {
- var nMessageString = XMLHelper_FindChildByTagName(nMessage, "messageString", true);
- if(nMessageString) {
- sMessage = XMLHelper_GetText(nMessageString, false);
- }
- }
- if(sMessage) {
- var rErrorCode = /ANS-GEN-(\d{2,4})/;
- var aMatches = rErrorCode.exec(sMessage);
- if(aMatches && aMatches.length && aMatches.length > 1) {
- var sAnsErrorCode = aMatches[1];
- if(sAnsErrorCode === "0075") {
- //Parent deleted - i.e. widget has been deleted.
- oFaultDialog.setErrorMessage(RV_RES.IDS_ANNOTATION_WIDGET_DELETED_ERROR);
- }
- }
- }
- }
- //Delete all annotations (they're no longer valid).
- this._cleanupPreviousAnnotations();
- this.getAnnotationStore().clear();
- oFaultDialog.show(oSoapFault);
- if(this.m_loadAnnotationsDfd) {
- this.m_loadAnnotationsDfd.errback();
- this.m_loadAnnotationsDfd = null;
- }
- },
- fetchAnnotationDataResponse : function(asynchJSONResponse) {
- var editContentAction = window["CVEditContentActionInstance"];
- var jsonResult = asynchJSONResponse.getResult();
- //Prevent subsequent queries for annotations only if the report
- //has no annotations at all (i.e. jsonResult is null, not empty).
- this.m_bCallGetAnnotations = this.m_bCallGetAnnotations && jsonResult !== null;
- if (jsonResult===null) {
- jsonResult = [];
- }
- var viewerObject = this.m_viewerIWidget.getViewerObject();
- viewerObject.envParams["cv.annotationData"] = jsonResult;
- this._cleanupPreviousAnnotations();
- if (jsonResult.length > 0) {
- if (this.getAnnotationStore()) {
- var annotationArray = this._generateMatchedAnnotationsFromViewerObject();
- this.getAnnotationStore().load(annotationArray);
- this.displayCommentIndicators();
- }
- }
- if(this.m_loadAnnotationsDfd) {
- this.m_loadAnnotationsDfd.callback();
- this.m_loadAnnotationsDfd = null;
- }
- },
- /*
- * destroy all commentViewer widget for previous annotations
- */
- _cleanupPreviousAnnotations : function () {
- var store = this.getAnnotationStore();
- if (store) {
- var annotations = store.getAll();
- //clean up all annotations
- for (var contextId in annotations) {
- var commentId = this.m_viewerIWidget.getWidgetId() + "_" + contextId + "_comment";
- var commentViewer = dijit.byId(commentId);
- if (typeof commentViewer != "undefined" && commentViewer != null) {
- commentViewer.destroy();
- delete commentViewer;
- }
- store.clear(contextId);
- }
- }
- },
- /*
- * Returns array of annotations. Ctx of an annotation is updated with the explicit ctx value of the report cell the annotation is on.
- * In order to update ctx value, it does the following.
- *
- * - remove any OR (|) operator in ctxValue
- * - find a matching report cell and take ctx value of it
- *
- */
- _generateMatchedAnnotationsFromViewerObject : function () {
- var viewerObject = this.m_viewerIWidget.getViewerObject();
- var annotationData = [];
- if (viewerObject && viewerObject.envParams && viewerObject.envParams["cv.annotationData"]) {
- annotationData = eval(viewerObject.envParams["cv.annotationData"]);
- }
- var annotationListWithUniqueCTX = this._generateAnnotationListWithoutORoperator(annotationData);
- return this._updateAnnotationCtxWithMatchedCellCtx(annotationListWithUniqueCTX, viewerObject);
- },
- /*
- * ctx of an annotation may have 'OR' operator.
- * for example, 9:3|4:*
- * It means that annotated cell's ctx could be either 9:3:* or 9:4:*
- *
- * This function removes 'OR' operator and make two annotations with one of each possible ctx value.
- *
- */
- _generateAnnotationListWithoutORoperator : function(annotationData) {
- var annotationListWithUniqueCTX = [];
- for (var i=0, len=annotationData.length; i<len; i++ ) {
- var anno = annotationData[i];
- if(anno.ctx) { //cell level annotation
- var oneOrMoreAnno = bux.AnnotationHelper.generateCTXList(anno.ctx);
- for(var j=0, jLen=oneOrMoreAnno.length; j<jLen; j++) {
- var newAnno = {
- ann:anno.ann, // serviceId
- lmt:anno.lmt, // modified date/time
- lmtf:anno.lmtf, // modified date/time (formatted)
- ctx:anno.ctx,
- desc:anno.desc, // text
- fd:anno.fd, //filter data
- layoutElementId:anno.layoutElementId,
- owner:anno.owner, //owner name string
- ownerSearchPath:anno.ownerSearchPath,
- pv:anno.pv, //prompt param values
- rdi:anno.rdi,
- sd:anno.sd, //sliders data
- version:anno.version || 1
- };
- newAnno.ctx = oneOrMoreAnno[j];
- annotationListWithUniqueCTX.splice(0,0, newAnno);
- }
- } else {//widget level annotation
- annotationListWithUniqueCTX.splice(0,0, anno);
- }
- }
- return annotationListWithUniqueCTX;
- },
- /*
- * Finds the report cell of an annotations, and update ctx of annotation with the cell's ctx
- * Returns array of annotations which all has explicit ctx value
- *
- * In order to that, it does the following
- *
- * first, creates AnnotationCTXLookup object, and
- * calls populateCtxDetailsForAllAnnotations to load ctx details for all Ids in annotation ctx
- *
- * then, for each annotation
- *
- * - queries dom nodes with ctx attirbute, report cells, if hasn't
- * - if ctx of an annotation is not present, it is a widget level. put it in the return array
- * - calls isAnnotatedCell function of AnnotationCTXLookup with annotation and each cell's ctx value.
- * - only if the function return true,
- * updates ctx of annotation with the ctx value of the cell. and put it in the return array
- *
- */
- _updateAnnotationCtxWithMatchedCellCtx : function (newAnnotationListWithUniqueCTX, viewerObject) {
- var processedAnnotationList = [];
- var ctxLookup = new AnnotationCTXLookup(this.m_viewerIWidget.getViewerObject().getSelectionController().getCCDManager());
- ctxLookup.populateCtxDetailsForAllAnnotations(newAnnotationListWithUniqueCTX);
- var nodes = [];
- for(var i=0, len=newAnnotationListWithUniqueCTX.length; i<len; i++) {
- var anno = newAnnotationListWithUniqueCTX[i];
- if (anno.ctx) {
- if (nodes.length === 0) {
- //query now. we need it for cell level handling
- nodes = dojo.query('[ctx]', this.m_viewerIWidget.iContext.getRootElement());
- }
- for (var j = 0, jLen = nodes.length; j < jLen; j++) {
- var cellCtxValue = nodes[j].getAttribute('ctx'); // get ctx attributes from node
- if (ctxLookup.isAnnotatedCell(anno, cellCtxValue)) {
- anno.ctx = cellCtxValue;
- processedAnnotationList.splice(0,0, anno);
- break;
- }
- }
- } else {
- processedAnnotationList.splice(0,0, anno);
- }
- }
- return processedAnnotationList;
- },
- displayCommentIndicators : function () {
- var store = this.getAnnotationStore();
- var commentedCells = store.getAll();
- for (var cell in commentedCells)
- {
- var indicator = new bux.AnnotationIndicator({annotationStore: store, context: cell, iWidgetContainer: this.m_viewerIWidget, dir: this.m_viewerIWidget.getViewerObject().getDirection()});
- indicator.addExistingCommentToCell();
- }
- },
- /**
- * Runs the placement logic on each annotation indicator again,
- * incase the positions where they should be have changed.
- */
- repositionCommentIndicators : function() {
- var store = this.getAnnotationStore();
- var annotations = store.getAll();
- for (var id in annotations) {
- var annotation = annotations[id];
- var ctx = annotation[0].getContext();
- var indicatorId = store.getIndicatorWidgetId(ctx);
- if (indicatorId!==null) {
- var indicator = dijit.byId(indicatorId);
- indicator.addToPage();
- }
- }
- },
- promptForSave : function(yesOkFunc) {
- dojo["require"]("bux.dialogs.InformationDialog"); //@lazyload
- var saveConfirmationDialog = new bux.dialogs.InformationDialog({
- title: RV_RES.IDS_JS_COMMENT_DLG_TITLE,
- sMainMessage: RV_RES.IDS_JS_COMMENT_DLG_MESSAGE,
- sDescription: RV_RES.IDS_JS_COMMENT_DLG_DETAILS,
- sInfoIconClass: 'bux-informationDialog-warning-icon',
- buttons : ['YES','NO'],
- yesOKHandler : yesOkFunc
- });
- saveConfirmationDialog.startup();
- saveConfirmationDialog.show();
- },
- addComment : function (ctxId, cellValue) {
- if (this.m_viewerIWidget.isSaveNecessary()) {
- this.promptForSave( dojo.hitch(this, this.onCommentSaveAcknowledge, ctxId, cellValue) );
- } else {
- this.addNewComment(ctxId, cellValue);
- }
- },
- editComment : function (ctxId) {
- var comment = bux.getComment(this.m_viewerIWidget.iContext, this.getAnnotationStore().getEffectiveIds(ctxId));
- if (comment && comment.edit)
- {
- comment.edit();
- }
- },
- deleteComment : function (ctxId) {
- this.getAnnotationStore().deleteOneComment(ctxId);
- /* THE following function should be added as a callback function of the deleteOneComment above.
- * The deleteOneComment function must be modified to return the deferred object.
- * Commenting this logic for now because BUX streamlining work is in progress.
- *
- this.m_bCallGetAnnotations = this.annotationStore.hasAnnotation();
- */
- },
- addNewComment : function(ctxId, cellValue) {
- //If cellValue is undefined or null, don't prepopulate flyout
- this.addAsNewComment(ctxId, (cellValue == null) ? "" : (cellValue + ' - '));
- },
- addAsNewComment : function(ctxId, text) {
- var indicator = null;
- var contextId = (ctxId===null)? this.getAnnotationStore().WIDGET_CONTEXT: ctxId;
- var indicatorId = this.getAnnotationStore().getIndicatorWidgetId(contextId);
- if (indicatorId!=null) {
- indicator = dijit.byId(indicatorId);
- }
- if (indicator==null) {
- dojo["require"]("bux.AnnotationIndicator"); //@lazyload
- indicator = new bux.AnnotationIndicator({
- annotationStore: this.getAnnotationStore(),
- context: contextId,
- iWidgetContainer: this.m_viewerIWidget,
- dir: this.m_viewerIWidget.getViewerObject().getDirection()
- });
- window.setTimeout(function () { indicator.addNewCommentToCell(text); },0);
- } else {
- window.setTimeout(function () { indicator.comment.editNewComment(contextId, text); },0);
- }
- },
- onCommentSaveAcknowledge : function(ctxId, cellValue) {
- this.m_viewerIWidget._pendingContextId = ctxId;
- this.m_viewerIWidget._pendingCellValue = cellValue;
- this.m_viewerIWidget.fireEvent('com.ibm.bux.widget.action', null, {action: 'canvas.save'});
- },
- addWidgetComment : function () {
- if (this.m_viewerIWidget.isSaveNecessary()) {
- this.promptForSave( dojo.hitch(this, this.onCommentSaveAcknowledge, null, this.m_viewerIWidget.getDisplayName()) );
- } else {
- this.addNewComment(null, this.m_viewerIWidget.getDisplayName());
- }
- },
- editWidgetComment : function () {
- var comment = bux.getComment(this.m_viewerIWidget.iContext, [this.getAnnotationStore().WIDGET_CONTEXT]);
- if (comment && comment.edit)
- {
- comment.edit();
- }
- },
- deleteWidgetComment : function () {
- this.deleteComment(this.getAnnotationStore().WIDGET_CONTEXT);
- },
- commitComment : function(annotation) {
- //If it has never been loaded, it's a brand new comment
- if (annotation.getContext() !== this.getAnnotationStore().WIDGET_CONTEXT) {
- return this.commitCellComment(annotation);
- }
- else {
- return this.commitWidgetComment(annotation, this.getAnnotationStore());
- }
- },
- /**
- * @return a deferred which will be resolved when the request to the server
- * to commit a cell comment returns.
- */
- commitCellComment : function(annotation) {
- //Fire off a request to Viewer to commit the annotation
- //Note: Edit requests go directly to the annotation service and not through Viewer,
- //so they are not dealt with here
- var deferred = new dojo.Deferred();
- var cognosViewer = this.m_viewerIWidget.getViewerObject();
- var callbacks = {
- customArguments:[annotation, deferred],
- "complete": {"object": this, "method": this.handleCellCommentSaveResponse},
- "fault": {"object": this, "method": this.handleCellCommentSaveErrorResponse},
- "error": {"object": this, "method": this.handleCellCommentSaveServerErrorResponse}
- };
- var asynchRequest = new AsynchJSONDispatcherEntry(cognosViewer);
- asynchRequest.setCallbacks( callbacks );
- this.preparePostForCommitCellComment( asynchRequest, annotation ).then(
- function() {
- cognosViewer.dispatchRequest(asynchRequest);
- }
- );
- return deferred;
- },
- /**
- * @return a deferred which will be resolved when all form fields are added to the request
- */
- preparePostForCommitCellComment : function(asynchRequest, annotation) {
- var dfd = new dojo.Deferred();
- dojo.when(this.m_viewerIWidget.getWidgetStoreID(),
- dojo.hitch(this, function(widgetStoreID) {
- var viewerObject = this.m_viewerIWidget.getViewerObject();
- var selCon = viewerObject.getSelectionController();
- asynchRequest.addFormField("widgetStoreID", widgetStoreID);
- asynchRequest.addFormField("ui.action", "commentSave");
- asynchRequest.addFormField("cv.metatdata", dojo.toJson(selCon.getCCDManager().m_md));
- asynchRequest.addFormField("cv.context", dojo.toJson(selCon.getCCDManager().m_cd));
- asynchRequest.addFormField("cv.commentId", annotation.getContext());
- asynchRequest.addFormField("cv.commentDesc", xml_encode(annotation.getDescription()));
- var lid = selCon.getAllSelectedObjects()[0].getLayoutElementId();
- if (lid) {
- //The "lid" attribute is composed of layout ID + namespacePrefix + widget identifier.
- //We only want the layout ID, so remove the rest.
- lid = lid.replace(this.m_viewerIWidget.getViewerId(), "");
- annotation.setParentId(lid);
- asynchRequest.addFormField("cv.commentLayoutId", annotation.getParentId());
- var annInfoBar = new AnnotationInfoBar(viewerObject, lid);
- var filterContext = annInfoBar.createFilterContext();
- if (filterContext!=null) {
- annotation.setFilterContext(filterContext);
- if (filterContext.getPromptsJSON()) {
- asynchRequest.addFormField("cv.filterContext_prompts", dojo.toJson(filterContext.getPromptsJSON()));
- }
- if (filterContext.getFilterJSON()) {
- asynchRequest.addFormField("cv.filterContext_filter", dojo.toJson(filterContext.getFilterJSON()));
- }
- if (filterContext.getSlidersJSON()) {
- asynchRequest.addFormField("cv.filterContext_sliders", dojo.toJson(filterContext.getSlidersJSON()));
- }
- }
- }
- dfd.callback();
- })
- );
- return dfd;
- },
- /**
- * @return a deferred that resolves when the server responds to new annotation request
- */
- commitWidgetComment : function(annotation) {
- dojo["require"]("bux.Services"); //@lazyload
- var serviceURL = bux.Services.getGateway() + "/annotationService/creation";
- var contentObj = {};
- contentObj["annotationName"] = annotation.getName();
- if (contentObj["annotationName"] == null) {
- //This parameter is necessary to the API -- the call will fail without it
- contentObj["annotationName"] = "";
- }
- contentObj["annotationDescription"] = annotation.getDescription();
- var dfd = new dojo.Deferred();
- dojo.when(this.m_viewerIWidget.getWidgetStoreID(),
- dojo.hitch(this, function(widgetStoreID) {
- contentObj["annotationParentID"] = widgetStoreID;
- bux.xhrPost({
- url: serviceURL,
- sync: true,
- content: contentObj
- }).then(
- /*callback*/ dojo.hitch( this, function (response) {
- this.handleCommentSaveDone(response, annotation, this.getAnnotationStore(), this.m_viewerIWidget);
- annotation.loadDetails();
- dfd.callback();
- })
- );
- })
- );
- return dfd;
- },
- handleCellCommentSaveResponse : function(asynchJSONResponse, annotation, deferred)
- {
- var responseObject = asynchJSONResponse.getJSONResponseObject();
- if (responseObject) {
- var jsonResult = responseObject.json;
- if (jsonResult) {
- var result = this.handleCommentSaveDone(jsonResult, annotation, this.getAnnotationStore(), this.m_viewerIWidget);
- if (typeof result != 'Error') {
- annotation.loadDetails();
- }
- }
- }
- deferred.callback(asynchJSONResponse);
- },
- handleCellCommentSaveErrorResponse: function(asynchJSONError, annotation, deferred) {
- deferred.errback(new Error(asynchJSONError.getSoapFaultDetailMessageString()));
- },
- handleCellCommentSaveServerErrorResponse: function(error, annotation, deferred) {
- var errorObject = new Error(error.xmlHttp.statusText);
- //Include the server error response code so the user can diagnose his web server
- errorObject.xhr = error.xmlHttp;
- deferred.errback(errorObject);
- },
- //TODO: we shouldn't need to pass viewerWidget to this function, we could simply use this.m_viewerIWidget to get the widget
- handleCommentSaveDone : function(response, annotation, store, viewerWidget) {
- var xmlDom = XMLBuilderLoadXMLFromString(response);
- if (xmlDom) {
- var responseNode = xmlDom.firstChild;
- var annotationNode = XMLHelper_FindChildByTagName(responseNode, "annotation", false);
- if (annotationNode) {
- var annotationIdNode = XMLHelper_FindChildByTagName(annotationNode, "id", false);
- if (annotationIdNode) {
- var annotationId = XMLHelper_GetText(annotationIdNode);
- annotation.setServiceId(annotationId);
- annotation.setIWidgetContainer(viewerWidget);
- store.setWidgetContainer(viewerWidget);
- this.setCallGetAnnotations(true);
- return response;
- }
- }
- }
- return new Error(response.toString());
- }
- });
|