ScheduleView.js 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291
  1. /*
  2. * Licensed Materials - Property of IBM
  3. *
  4. * IBM Cognos Products: SHARE
  5. *
  6. * (C) Copyright IBM Corp. 2015, 2020
  7. *
  8. * US Government Users Restricted Rights - Use, duplication or disclosure
  9. * restricted by GSA ADP Schedule Contract with IBM Corp.
  10. */
  11. define([
  12. 'bi/glass/app/ContentView',
  13. 'bi/schedule/app/appControler',
  14. 'jquery',
  15. 'bi/commons/utils/Utils',
  16. 'bi/sharecommon/utils/translator',
  17. 'q',
  18. 'bi/sharecommon/utils/simpledoT',
  19. 'text!bi/schedule/templates/ScheduleView.html',
  20. 'underscore',
  21. 'moment-timezone',
  22. 'bi/schedule/views/DateTimeRangeCadencePickerView',
  23. 'bi/schedule/views/DailyCadencePickerView',
  24. 'bi/schedule/views/WeeklyCadencePickerView',
  25. 'bi/schedule/views/MonthlyCadencePickerView',
  26. 'bi/schedule/views/YearlyCadencePickerView',
  27. 'bi/schedule/views/TriggerCadencePickerView',
  28. 'bi/schedule/views/FormatPickerView',
  29. 'bi/schedule/views/ScheduleDeliveryPickerView',
  30. 'bi/commons/ui/properties/DropDown',
  31. 'bi/commons/ui/properties/CheckBox',
  32. 'ca_portal/features/mypreferences/MyPreferences',
  33. 'bi/schedule/views/PdfOptionsView',
  34. 'bi/commons/ui/properties/PropertyUIControl',
  35. 'bi/content_apps/utils/ContentStoreObject',
  36. 'bi/commons/ui/dialogs/ConfirmationDialog',
  37. 'bi/content_apps/utils/C10Utils',
  38. 'caglass/ajax/CAAuthentication',
  39. 'bi/content_apps/authoring/AuthoringHelper'
  40. ],
  41. function(View,
  42. controler,
  43. $,
  44. Utils,
  45. t,
  46. Q,
  47. dot,
  48. template,
  49. _,
  50. moment,
  51. DateTimeRangeCadencePicker,
  52. DailyCadencePicker,
  53. WeeklyCadencePicker,
  54. MonthlyCadencePicker,
  55. YearlyCadencePicker,
  56. TriggerCadencePicker,
  57. FormatPicker,
  58. ScheduleDeliveryPicker,
  59. DropDown,
  60. CheckBox,
  61. MyPreferences,
  62. PdfOptionsView,
  63. PropertyUIControl,
  64. ContentStoreObject,
  65. ConfirmationDialog,
  66. C10Utils, CAAuthentication, AuthoringHelper) {
  67. 'use strict';
  68. var __CHILD_SLIDEOUT_STANDARD_WIDTH = '350px';
  69. var scheduleView = View.extend({
  70. /**
  71. * @constructor options can contain:
  72. *
  73. * objectInformation: The CM object being scheduled,
  74. * onCreateOrUpdateCallback: callback to call once a schedule is created or updated
  75. * canBurst: whether this report is burstable,
  76. * glassContext: the glass context
  77. */
  78. init: function(options) {
  79. scheduleView.inherited('init', this, arguments);
  80. this.showOptions = true;
  81. this.defaultLocale = options.glassContext.services.userProfile.preferences.contentLocale || 'en-us';
  82. this.options = {
  83. delivery: {
  84. save: {
  85. notify: false
  86. }
  87. },
  88. outputLocale: [this.defaultLocale],
  89. pdf:{},
  90. burst:false,
  91. outputFormat: []
  92. };
  93. this.options.outputFormat.push( this._getDefaultOutputFormat());
  94. _.extend(this, options);
  95. // set defaults
  96. this.currentRenderedCadenceType = 'weekly';
  97. this.outputLocale = [this.defaultLocale];
  98. this.msgs = [];
  99. this.warningMessage = null;
  100. this.parameterValues = [];
  101. //Place holder for parameter values set on the report properties
  102. this.reportParameterValues = [];
  103. this.scheduleTypeSelector = null;
  104. this.uniqueId = _.uniqueId('id_');
  105. this.readOnly = false;
  106. this.deliveryPicker = null;
  107. this.outputFormatPicker = null;
  108. this.pdfOptionsView = null;
  109. this.timezone = this.glassContext.services.userProfile.preferences.timeZoneID;
  110. this.canBurst = this.canBurst && this.glassContext.hasCapability('canUseBursting');
  111. this.showPDFOption = this.glassContext.hasCapability('canGeneratePDFOutput') &&
  112. this.objectInformation.type !== 'interactiveReport' &&
  113. this.objectInformation.type !== 'powerPlay8Report' &&
  114. this.objectInformation.type !== 'powerPlay8ReportView';
  115. // Predefine this to cache data of the existing schedule on the initial render
  116. this.initScheduleDescriptor = {
  117. reportId: null,
  118. reportType: null,
  119. scheduleInfo: {
  120. active: null,
  121. startDate: null,
  122. endDate: null,
  123. endType: null,
  124. timezone: null,
  125. weekly: null,
  126. everyNPeriods: null,
  127. type: null
  128. },
  129. options: {
  130. outputFormat: null,
  131. delivery: null,
  132. outputLocale: null,
  133. pdf: null,
  134. burst: null
  135. },
  136. parameters: null
  137. };
  138. this.showOptions = this._supportsOptions();
  139. },
  140. _supportsOptions: function() {
  141. var objWithNoOptions = ['dataSet2','agentDefinition', 'agentDefinitionView', 'jobDefinition', 'jupyterNotebook'];
  142. return objWithNoOptions.indexOf(this.objectInformation.type) === -1;
  143. },
  144. _openClassicView:function(){
  145. var scheduleDescriptor = this._prepareScheduleDescriptor();
  146. this._confirmChanges(function() {
  147. if (_.isEqual(scheduleDescriptor, this.initDesc)){
  148. this.setDone();
  149. this.slideout.hide();
  150. if (this.slideout.parent) {
  151. this.slideout.parent.hide();
  152. }
  153. C10Utils.openC10Morphlet('portal/schedule/report.xts', this.objectInfo.type, this.objectInfo.id);
  154. } else {
  155. this._createOrUpdateScheduleRoutine(scheduleDescriptor).then(
  156. function(){
  157. this.slideout.hide();
  158. if (this.slideout.parent) {
  159. this.slideout.parent.hide();
  160. }
  161. C10Utils.openC10Morphlet('portal/schedule/report.xts', this.objectInfo.type, this.objectInfo.id);
  162. }.bind(this)
  163. );
  164. }
  165. }.bind(this), function(){}, t.translate('schedule_update_confirm'), t.translate('schedule_update_save_before_classicview'), scheduleDescriptor);
  166. },
  167. setFocus: function() {
  168. this.$el.focus();
  169. },
  170. _confirmChanges: function(okFunc, cancelFunc, messageTitle, messageText, scheduleDescriptor) {
  171. if ((scheduleDescriptor) && (_.isEqual(scheduleDescriptor, this.initDesc))) {
  172. okFunc();
  173. return;
  174. }
  175. var updateDialog = new ConfirmationDialog('warning', messageTitle, messageText);
  176. updateDialog.confirm(okFunc, cancelFunc);
  177. },
  178. _hasRestrictedFormats: function () {
  179. var formats = this.outputFormatPicker && this.outputFormatPicker.getOutputFormats() || [];
  180. for(var index=0; index < formats.length;index += 1) {
  181. if (!AuthoringHelper.userCanGenerateFormat(this.glassContext, formats[index])){
  182. return true;
  183. }
  184. }
  185. return false;
  186. },
  187. _resetRestrictedFormats: function(scheduleDescriptor) {
  188. var updatedList = _.reject(scheduleDescriptor.options.outputFormat, function(aFormat) {return !AuthoringHelper.userCanGenerateFormat(this.glassContext, aFormat);}.bind(this));
  189. if (updatedList.length === 0) {
  190. updatedList.push('HTML');
  191. }
  192. scheduleDescriptor.options.outputFormat = updatedList;
  193. },
  194. _handleUpdate: function() {
  195. return this._closeOpenChildren()
  196. .then(function() {
  197. this.setWorking();
  198. this.hideWarningMessage();
  199. var scheduleDescriptor = this._prepareScheduleDescriptor();
  200. this.initDesc = scheduleDescriptor;
  201. if ( this.validate(scheduleDescriptor) ) {
  202. // Create a new schedule
  203. if (!this.descriptor) {
  204. return this._createOrUpdateScheduleRoutine(scheduleDescriptor);
  205. // Update an existing schedule
  206. } else {
  207. var timeZoneChanged = this._hasOnlyTimezoneBeenChanged(this.initScheduleDescriptor, scheduleDescriptor);
  208. var hasResctictedFormats = this._hasRestrictedFormats();
  209. var message = '';
  210. if (timeZoneChanged && hasResctictedFormats) {
  211. message = t.translate('schedule_update_restricted_formats_timezone_confirm_message');
  212. } else if (timeZoneChanged){
  213. message = t.translate('schedule_update_timezone_difference_confirm_message');
  214. } else if (hasResctictedFormats) {
  215. message = t.translate('schedule_update_restricted_formats_confirm_message');
  216. }
  217. if (message.length > 0) {
  218. return this._confirmChanges(function() {
  219. if (hasResctictedFormats) {
  220. this._resetRestrictedFormats(scheduleDescriptor);
  221. }
  222. this._createOrUpdateScheduleRoutine(scheduleDescriptor);
  223. }.bind(this), this.setDone.bind(this), t.translate('schedule_update_confirm'), message);
  224. } else {
  225. return this._createOrUpdateScheduleRoutine(scheduleDescriptor);
  226. }
  227. }
  228. } else {
  229. this.showWarningMessage();
  230. this.setDone();
  231. return Promise.resolve();
  232. }
  233. }.bind(this));
  234. //.done(function(){return Promise.resolve()});
  235. },
  236. _setEvents: function () {
  237. this.$el.find('.classicViewLink').on('primaryaction', this._openClassicView.bind(this));
  238. this.$el.find('.schedule_primary_button').on('clicktap', this._handleUpdate.bind(this));
  239. this.$el.find('.schedule_language_picker').on('clicktap', function() {
  240. this._closeOpenChildren().then(function() {
  241. this.glassContext.appController.showSlideOut({
  242. 'parent': this.slideout,
  243. 'overlay': false,
  244. 'width': __CHILD_SLIDEOUT_STANDARD_WIDTH,
  245. 'label': t.translate('schedule_language_picker_name'),
  246. 'content': {
  247. 'module': 'bi/content_apps/common/ui/LanguagePickerView',
  248. 'glassContext': this.glassContext,
  249. 'supportedContentLocales': this.supportedContentLocales,
  250. 'enabledLanguages': this.outputLocale,
  251. 'closeCallback': function(data) {
  252. this.outputLocale = data;
  253. var languageLabel = t.translate('schedule_no_languages_label');
  254. var labelArray = [];
  255. for(var i = 0; i < this.outputLocale.length; i++) {
  256. labelArray.push(this.supportedContentLocales[this.outputLocale[i]]);
  257. }
  258. languageLabel = labelArray.join(', ');
  259. this.$el.find('.output_language_list').text(languageLabel);
  260. this.$el.find('.output_language_list').attr('title', languageLabel);
  261. }.bind(this)
  262. }
  263. });
  264. }.bind(this)).done();
  265. }.bind(this));
  266. var cancelChanges = function() {
  267. this.close();
  268. }.bind(this);
  269. this.$el.find('.schedule_secondary_button').on('clicktap', cancelChanges);
  270. },
  271. _prepareScheduleDescriptor: function() {
  272. var reportId = this.objectInformation.id;
  273. var reportType = this.objectInformation.type;
  274. var active = this.isEditMode? this.objectInformation.descriptor.scheduleInfo.active : true;
  275. var outputFormats = this.options.outputFormat;
  276. if(this.outputFormatPicker !== null) {
  277. outputFormats = this.outputFormatPicker.getOutputFormats();
  278. }
  279. var scheduleInfo = {
  280. active: active,
  281. timezone: this.timezone
  282. };
  283. // grab datetimerangecadencePicker schedinfo
  284. scheduleInfo = this.datetimeRangeCadencePicker.toDescriptor(scheduleInfo);
  285. // grab cadencePicker info
  286. scheduleInfo = this.cadencePicker.toDescriptor(scheduleInfo);
  287. // DELIVERY
  288. var deliveryOptions = this.options.delivery;
  289. if(this.deliveryPicker !== null) {
  290. deliveryOptions = this.deliveryPicker.getDeliveryOptions();
  291. }
  292. // Languages/ Output Locale
  293. var outputLocale = this.outputLocale || this.options.outputLocale;
  294. // PDF Options
  295. var pdfOptions = this.pdfOptionsView ? this.pdfOptionsView.getOptions() : this.options.pdf;
  296. // Burst
  297. var burst = this._getBurstValue();
  298. // note: do not send a schedule name. Causes problems with triggers.
  299. var scheduleDescriptor = _.extend({}, {
  300. reportId: reportId,
  301. reportType: reportType,
  302. scheduleInfo: scheduleInfo,
  303. options: {
  304. outputFormat: outputFormats,
  305. delivery: deliveryOptions,
  306. outputLocale: outputLocale,
  307. pdf: pdfOptions,
  308. burst: burst
  309. },
  310. parameters: this.parameterValues
  311. });
  312. if ((this.objectInformation.type === 'agentDefinition') || (this.objectInformation.type === 'agentDefinitionView')) {
  313. delete scheduleDescriptor.options ;
  314. }
  315. return scheduleDescriptor;
  316. },
  317. _hasOnlyTimezoneBeenChanged: function(scheduleDescriptorOld, scheduleDescriptorNew) {
  318. var status = false;
  319. var oldCopy = $.extend(true, {}, scheduleDescriptorOld);
  320. var newCopy = $.extend(true, {}, scheduleDescriptorNew);
  321. var oldTimezone = oldCopy.scheduleInfo.timezone;
  322. var newTimezone = newCopy.scheduleInfo.timezone;
  323. if (oldTimezone !== newTimezone) {
  324. // Undefine these properties in order to compare schedule descriptors
  325. delete oldCopy.scheduleInfo.timezone;
  326. delete newCopy.scheduleInfo.timezone;
  327. // remove endDate if indefinite
  328. if(oldCopy.scheduleInfo.endType === 'indefinite') {
  329. delete oldCopy.scheduleInfo.endDate;
  330. }
  331. if(newCopy.scheduleInfo.endType === 'indefinite') {
  332. delete newCopy.scheduleInfo.endDate;
  333. }
  334. status = _.isEqual(oldCopy, newCopy);
  335. }
  336. return status;
  337. },
  338. _closeOpenChildren: function() {
  339. var deferred = Q.defer();
  340. // Close any open open child slideouts
  341. if (this.slideout && this.slideout.hasOpenChild()) {
  342. var openChild = this.slideout.child;
  343. openChild.hide().then(function() {
  344. deferred.resolve();
  345. }).done();
  346. } else {
  347. deferred.resolve();
  348. }
  349. return deferred.promise;
  350. },
  351. _getOutputFormat: function(options) {
  352. var outputFormat = '';
  353. try {
  354. for (var i = 0; i < options.length; i++) {
  355. if (options[i].name === 'outputFormat') {
  356. // expect output format option value to be a MobX ObservableArray
  357. outputFormat = options[i].value.join(',');
  358. break;
  359. }
  360. }
  361. } catch(e) {
  362. // return outputFormat as empty string
  363. }
  364. return outputFormat;
  365. },
  366. _createOrUpdateSchedule: function(scheduleDescriptor) {
  367. var _self = this;
  368. // scheduleDescriptor should not include options when scheduling a job
  369. if (_self.objectInformation && _self.objectInformation.type && _self.objectInformation.type === 'jobDefinition' && scheduleDescriptor.options )
  370. delete scheduleDescriptor.options;
  371. return controler.createSchedule(scheduleDescriptor, _self.glassContext).then(function(resp) {
  372. // Not all schedulable objects have delivery options
  373. var cloudOpts = this.deliveryPicker === null ? {} : this.deliveryPicker.getCloudOptions();
  374. if (!resp) {
  375. resp = {};
  376. }
  377. return controler.updateSaveToCloudOptions(resp.id, cloudOpts, this.glassContext).then(function(){
  378. // call callback if specified
  379. if(_self.onCreateOrUpdateCallback && typeof(_self.onCreateOrUpdateCallback)==='function') {
  380. _self.onCreateOrUpdateCallback();
  381. }
  382. var message;
  383. var trackingOpts = {
  384. objectType: this.objectInformation.type,
  385. object: this.objectInformation.id,
  386. 'custom.outputFormat': this._getOutputFormat(this.objectInformation.outputFormat)
  387. };
  388. if(_self.isEditMode) {
  389. trackingOpts.type = 'Updated Object';
  390. trackingOpts.action = 'scheduleEdited';
  391. trackingOpts.milestoneName = 'scheduleEdited_' + this.objectInformation.type;
  392. message = t.translate('sch_update_success_msg');
  393. } else {
  394. trackingOpts.type = 'Created Object';
  395. trackingOpts.action = 'scheduleCreated';
  396. trackingOpts.milestoneName = 'scheduleCreated_' + this.objectInformation.type;
  397. message = t.translate('sch_create_success_msg');
  398. }
  399. var instrumentor = this.glassContext.getCoreSvc('.Instrumentation');
  400. if ((instrumentor) && (instrumentor.track)) {
  401. instrumentor.track(trackingOpts);
  402. }
  403. _self.glassContext.appController.showToast(message, {
  404. 'newestOnTop' : true,
  405. 'preventDuplicates' : false,
  406. 'timeOut': 6000,
  407. 'extendedTimeOut': 1000
  408. });
  409. _self.setDone();
  410. _self.close();
  411. return Promise.resolve();
  412. }.bind(this));
  413. }.bind(this)).fail(function () {
  414. _self.setDone();
  415. });
  416. },
  417. _getFormatFromObject: function() {
  418. if ((this.objectInformation) && (this.objectInformation.options)) {
  419. var formatOpt = _.find(this.objectInformation.options, function(opt){return opt.name === 'outputFormat';});
  420. if (formatOpt) {
  421. var objectDefaultFormat;
  422. if ((typeof formatOpt.value).toLocaleLowerCase() === 'string') {
  423. objectDefaultFormat = formatOpt.value;
  424. } else {
  425. objectDefaultFormat = formatOpt.value[0];
  426. }
  427. if (!AuthoringHelper.userCanGenerateFormat(this.glassContext, objectDefaultFormat)) {
  428. objectDefaultFormat = 'HTML';
  429. }
  430. return objectDefaultFormat;
  431. } else {
  432. return undefined;
  433. }
  434. }
  435. return undefined;
  436. },
  437. _getDefaultOutputFormat: function() {
  438. var formatFromObject = this._getFormatFromObject();
  439. var formatFromPreferences = this.glassContext.services.userProfile.preferences.format;
  440. if (formatFromObject) {
  441. return formatFromObject;
  442. }
  443. if ((formatFromPreferences) && (AuthoringHelper.userCanGenerateFormat(this.glassContext, formatFromPreferences)) ){
  444. return formatFromPreferences;
  445. }
  446. return 'HTML';
  447. },
  448. _createOrUpdateScheduleRoutine: function(scheduleDescriptor) {
  449. return controler.getUserCredential(this.glassContext).then(function () {
  450. return this._createOrUpdateSchedule(scheduleDescriptor);
  451. }.bind(this)).fail(function () {
  452. // Credentials need to be renewed
  453. this.glassContext.appController.showToast(t.translate('sub_credentials_expired_msg'), {
  454. 'type': 'warning',
  455. 'preventDuplicates': true,
  456. 'btnLabel': t.translate('sub_renew_credentials_button'),
  457. 'callback': function () {
  458. this._caAuthentication = new CAAuthentication();
  459. return this._caAuthentication.storeCredentials(this.glassContext).then(function () {
  460. this._createOrUpdateSchedule(scheduleDescriptor);
  461. }.bind(this)).fail(function (error) {
  462. if (error && error.displayObjects) {
  463. this._myPreferences = new MyPreferences({ glassContext: this.glassContext });
  464. return this._myPreferences.openCreateCredentialDialog(error.displayObjects).then(function () {
  465. this._createOrUpdateSchedule(scheduleDescriptor);
  466. }.bind(this)).fail(function () {
  467. this.setDone();
  468. }.bind(this));
  469. }
  470. }.bind(this)).fail(function () {
  471. this.setDone();
  472. }.bind(this));
  473. }.bind(this)
  474. });
  475. }.bind(this));
  476. },
  477. /**
  478. * Render the new schedule view
  479. *
  480. */
  481. render: function() {
  482. var deferred = Q.defer();
  483. this.descriptor = this.objectInformation.descriptor;
  484. this.isEditMode = typeof(this.descriptor) !== 'undefined';
  485. this.readOnly = this.isEditMode && this.objectInformation.hasPermission && !this.objectInformation.hasPermission.write && this.objectInformation.hasPermission.read;
  486. var htmlGenerator = dot.simpleTemplate(template);
  487. var objectInformation = this.objectInformation || {};
  488. var canBurst = this.canBurst || false;
  489. var showPDFOption = this.showPDFOption;
  490. objectInformation.defaultName = this.objectInformation.defaultName || '';
  491. this.canShowPrompt = !(C10Utils.isPowerPlay(this.objectInformation.type));
  492. if (this.canShowPrompt){
  493. // For display render the prompt picker
  494. // to indicate there are parameter values from report properties available for this schedule but will not be part of the schedule unless user set values by editing
  495. this.reportParameterValues = this.objectInformation.parameters || [];
  496. }
  497. var capableSchedType = this.getScheduleType();
  498. var title = this.isEditMode ? t.translate('schedule_panel_title_update_text') : t.translate('schedule_panel_title_text');
  499. var attributes = {
  500. canShowClassic: this._supportsOptions(),
  501. asset_name: _.escape(objectInformation.defaultName),
  502. schedule_panel_back: t.translate('schedule_panel_back_text'),
  503. schedule_panel_title: title,
  504. schedule_type_label: t.translate('schedule_type_label'),
  505. schedule_output_label: t.translate('schedule_output_label'),
  506. schedule_delivery_label: t.translate('schedule_delivery_label'),
  507. schedule_prompts_label: t.translate('schedule_prompts_label'),
  508. schedule_select_text: t.translate('schedule_select_text'),
  509. schedule_create_btn: this.isEditMode ? t.translate('schedule_update_btn_label') : t.translate('schedule_create_btn_label'),
  510. schedule_cancel_btn: t.translate('schedule_cancel_btn_label'),
  511. schedule_period: t.translate('schedule_period'),
  512. uniqueid: this.uniqueId,
  513. output_format_select_text: t.translate('output_format_select_text'),
  514. showOptions: this.showOptions,
  515. showPDFOption: showPDFOption,
  516. canBurst: canBurst,
  517. schedule_languages_label: t.translate('schedule_languages_label'),
  518. schedule_pdf_options_label: t.translate('schedule_pdf_options_label'),
  519. schedule_classic_view_label: t.translate('classicViewLink'),
  520. canShowPrompt: this.canShowPrompt
  521. };
  522. attributes.schedule_controls_description = t.translate('schedule_controls_description', {
  523. action1: attributes.schedule_create_btn,
  524. action2: attributes.schedule_cancel_btn
  525. });
  526. var items = [{
  527. 'type': 'Banner',
  528. 'centerLabel': true,
  529. 'backButton': this.slideout.overlay,
  530. 'value': title
  531. },
  532. {
  533. 'type': 'SectionLabel',
  534. 'label': t.translate('schedule_period')
  535. }];
  536. if(this.showOptions) {
  537. items.push({
  538. 'type': 'SectionLabel',
  539. 'label': t.translate('schedule_options')
  540. });
  541. }
  542. this._propertyUIControl = new PropertyUIControl({
  543. 'glassContext': this.glassContext,
  544. 'el': this.$el,
  545. 'closeCallback': this.close.bind(this),
  546. 'items': items
  547. });
  548. this._propertyUIControl.render().then(function() {
  549. // load the complete template
  550. var $content = $(htmlGenerator(attributes));
  551. // point this.$el to the content section of the slideout, below the header
  552. this.$el = this.$el.find('.propertiesUIControlPageView');
  553. // add each of the three sections, to the correct place
  554. // add type section to above the first divider ('Period')
  555. this.$el.prepend($content.find('.schedule_type_section'));
  556. // add period section to below the first divider ('Period')
  557. $content.find('.schedule_period_section').insertAfter(this.$el.find('.sectionLabel:first'));
  558. // add options section to below the second divider ('Options')
  559. this.$el.append($content.find('.schedule_options_section'));
  560. // add the progress overlay div
  561. this.$el.append($content.find('.progress-overlay'));
  562. this.$el.addClass('new_schedule_slideout');
  563. return this.renderDateTimeRangeCadencePicker();
  564. }.bind(this)).then(function() {
  565. this.renderCadencePicker(capableSchedType);
  566. if(this.showOptions) {
  567. this.renderOutputFormatPicker();
  568. this.renderPromptRow();
  569. this.renderDeliveryPicker();
  570. if (showPDFOption) {
  571. this.renderPdfOptionsView();
  572. }
  573. this.setLanguageLabel();
  574. // checkbox for burst
  575. if(canBurst) {
  576. this.renderBurstCheckBox();
  577. }
  578. }
  579. //selector
  580. this._renderTypeSelector(capableSchedType);
  581. if ( this.isEditMode ) {
  582. this.currentRenderedCadenceType = capableSchedType;
  583. this.scheduleTypeSelector.getHTMLControl().val(this.currentRenderedCadenceType);
  584. }
  585. this._setIcons();
  586. // in update mode the permissions are passed
  587. if ( this.readOnly ) {
  588. // Update buttons
  589. this.$el.find('.schedule_primary_button').prop('disabled', true);
  590. this.$el.find('.schedule_secondary_button').prop('disabled', true);
  591. // Language picker
  592. this.$el.find('.schedule_language_option_toggler').prop('disabled', true);
  593. // Pdf option picker
  594. this.$el.find('.schedule_pdf_option_toggler').prop('disabled', true);
  595. // All input fields including all pickers
  596. this.$el.find('input').prop('disabled', true);
  597. }
  598. // Cache data of the existing schedule
  599. this._saveExistingScheduleInitialState();
  600. this._setEvents();
  601. this.initDesc = this._prepareScheduleDescriptor();
  602. deferred.resolve();
  603. }.bind(this));
  604. return deferred.promise;
  605. },
  606. setLanguageLabel: function() {
  607. if ((this.objectInformation.descriptor) && (this.objectInformation.descriptor.options.outputLocale)) {
  608. this.outputLocale = this.objectInformation.descriptor.options.outputLocale;
  609. }
  610. this.glassContext.services.config.getContentLocales().then(function(contentLocales) {
  611. this.supportedContentLocales = contentLocales;
  612. if ((this.objectInformation.descriptor) && (this.objectInformation.descriptor.options.outputLocale) ){
  613. this.outputLocale = this.objectInformation.descriptor.options.outputLocale;
  614. }
  615. var languageLabel = t.translate('schedule_no_languages_label');
  616. if(this.isEditMode) {
  617. if((this.objectInformation.descriptor) && (this.objectInformation.descriptor.options.outputLocale) ){
  618. var languageList = [];
  619. for(var i = 0; i < this.outputLocale.length; i++) {
  620. languageList.push(contentLocales[this.outputLocale[i]]);
  621. }
  622. if(languageList.length > 0) {
  623. languageLabel = languageList.join(', ');
  624. } else {
  625. languageLabel = contentLocales[this.defaultLocale];
  626. }
  627. }
  628. } else {
  629. languageLabel = contentLocales[this.defaultLocale];
  630. }
  631. this.$el.find('.output_language_list').text(languageLabel);
  632. this.$el.find('.output_language_list').attr('title', languageLabel);
  633. }.bind(this)).done();
  634. },
  635. shouldShowMobile: function() {
  636. var mobileTypes = ['interactiveReport', 'report', 'query', 'analysis'];
  637. return ((mobileTypes.indexOf(this.objectInformation.type) !== -1) || ((this.objectInformation.type === 'reportView') && (mobileTypes.indexOf(this.objectInformation.base[0].type) !== -1)));
  638. },
  639. renderDeliveryPicker: function() {
  640. var deliveryOptions = {};
  641. var name = this.objectInformation.defaultName;
  642. if(this.isEditMode) {
  643. if(this.objectInformation.descriptor.options.delivery) {
  644. deliveryOptions = this.objectInformation.descriptor.options.delivery;
  645. }
  646. }
  647. try {
  648. this.deliveryPicker = new ScheduleDeliveryPicker({
  649. $el: this.$el.find('.schedule_delivery_picker'),
  650. $toggler: this.$el.find('.schedule_delivery_picker'),
  651. $activeOptionsContainer: this.$el.find('.delivery_list'),
  652. reportName: name,
  653. deliveryOptions: deliveryOptions,
  654. rawOptions: this.objectInformation.rawOptions,
  655. isEditMode: this.isEditMode,
  656. glassContext: this.glassContext,
  657. slideoutparent: this.slideout,
  658. hasPermission: this.objectInformation.hasPermission,
  659. showMobile: this.shouldShowMobile(),
  660. enableAdvancedSettings: true,
  661. allowRecipients: function() { return !this._getBurstValue(); }.bind(this)
  662. });
  663. this.deliveryPicker.render();
  664. } catch(e) {
  665. console.log('There was an error initializing the DeliveryPicker.', e);
  666. }
  667. },
  668. renderPdfOptionsView: function() {
  669. var _self = this;
  670. var pdfOptions = {};
  671. if(this.isEditMode) {
  672. if(this.objectInformation.descriptor.options.pdf) {
  673. pdfOptions = this.objectInformation.descriptor.options.pdf;
  674. }
  675. }
  676. this.pdfOptionsView = new PdfOptionsView({
  677. glassContext: _self.glassContext,
  678. $toggler: _self.$el.find('.schedule_pdf_options_picker'),
  679. parentSlideout: _self.slideout,
  680. pdfOptions: pdfOptions
  681. });
  682. this.pdfOptionsView.render();
  683. },
  684. _saveExistingScheduleInitialState: function() {
  685. // Cache data of the existing schedule
  686. if (this.isEditMode) {
  687. this.initScheduleDescriptor = this._prepareScheduleDescriptor();
  688. // restore original timezone
  689. this.initScheduleDescriptor.scheduleInfo.timezone = this.descriptor.scheduleInfo.timezone;
  690. }
  691. },
  692. _renderTypeSelector: function(schType) {
  693. var schOptions = [];
  694. if (this.glassContext.hasCapability('canUseSchedulingByDay')) {
  695. schOptions.push({
  696. 'label': t.translate('daily_label'),
  697. 'value': 'daily',
  698. 'selected': (schType == 'daily')?true:false
  699. });
  700. }
  701. if (this.glassContext.hasCapability('canUseSchedulingByWeek')) {
  702. schOptions.push({
  703. 'label': t.translate('weekly_label'),
  704. 'value': 'weekly',
  705. 'selected': (schType == 'weekly')?true:false
  706. });
  707. }
  708. if (this.glassContext.hasCapability('canUseSchedulingByMonth')) {
  709. schOptions.push({
  710. 'label': t.translate('monthly_label'),
  711. 'value': 'monthly',
  712. 'selected': (schType == 'monthly')?true:false
  713. });
  714. }
  715. if (this.glassContext.hasCapability('canUseSchedulingByYear')) {
  716. schOptions.push({
  717. 'label': t.translate('yearly_label'),
  718. 'value': 'yearly',
  719. 'selected': (schType == 'yearly')?true:false
  720. });
  721. }
  722. if (this.glassContext.hasCapability('canUseSchedulingByTrigger')) {
  723. schOptions.push({
  724. 'label': t.translate('trigger_label'),
  725. 'value': 'trigger',
  726. 'selected': (schType == 'trigger')?true:false
  727. });
  728. }
  729. if (schOptions.length === 0) {
  730. // Should not happen. Use default
  731. schOptions.push({
  732. 'label': t.translate(schType + '_label'),
  733. 'value': schType,
  734. 'selected': true
  735. });
  736. }
  737. var scheduleId = 'schedule_type_' + this.uniqueId;
  738. var scheduleName = 'schedule_type_option';
  739. //var scheduleDescribedBy = 'schedule_type_describedby_'+this.uniqueId;
  740. this.scheduleTypeSelector = new DropDown({
  741. 'id': scheduleId,
  742. 'el': this.$el.find('#schedule_type_selector_container_' + this.uniqueId),
  743. 'label': t.translate('schedule_type_label'),
  744. 'name' : scheduleName,
  745. 'responsive': false,
  746. 'onChange': function(name, value){this._toggleCadenceView(name, value);}.bind(this),
  747. 'options': schOptions,
  748. 'readOnly': this.readOnly,
  749. 'ariaLabel': t.translate('schedule_type_aria_label'),
  750. 'ariaDescribedby': t.translate('schedule_type_description')
  751. });
  752. this.scheduleTypeSelector.doRender();
  753. },
  754. _toggleCadenceView: function(name, scheduleType) {
  755. // Handle change for different type of cadence view in the schedule pane
  756. var $cadence = this.$el.find('.schedule_cadence_picker');
  757. if (scheduleType != this.currentRenderedCadenceType) {
  758. this.currentRenderedCadenceType = scheduleType;
  759. $cadence.empty();
  760. this.renderCadencePicker(scheduleType);
  761. }
  762. },
  763. renderDateTimeRangeCadencePicker: function() {
  764. this.datetimeRangeCadencePicker = new DateTimeRangeCadencePicker({
  765. $el: this.$el.find('.schedule_datetime_range_picker'),
  766. objectInformation: {
  767. descriptor: this.objectInformation.descriptor
  768. },
  769. glassContext: this.glassContext
  770. });
  771. return this.datetimeRangeCadencePicker.render();
  772. },
  773. renderCadencePicker: function(type) {
  774. var $cadence = this.$el.find('.schedule_cadence_picker');
  775. switch(type) {
  776. case 'daily':
  777. this.cadencePicker = new DailyCadencePicker({
  778. $el: $cadence,
  779. objectInformation: {
  780. descriptor: this.objectInformation.descriptor,
  781. showDailyInterval: true
  782. },
  783. glassContext: this.glassContext,
  784. hasPermission: this.objectInformation.hasPermission
  785. });
  786. break;
  787. case 'weekly':
  788. this.cadencePicker = new WeeklyCadencePicker({
  789. $el: $cadence,
  790. objectInformation: {
  791. descriptor: this.objectInformation.descriptor,
  792. showRunEvery: true,
  793. showDailyInterval: true
  794. },
  795. glassContext: this.glassContext,
  796. hasPermission: this.objectInformation.hasPermission
  797. });
  798. break;
  799. case 'monthly':
  800. this.cadencePicker = new MonthlyCadencePicker({
  801. $el: $cadence,
  802. objectInformation: {
  803. descriptor: this.objectInformation.descriptor,
  804. showDailyInterval: true
  805. },
  806. glassContext: this.glassContext,
  807. hasPermission: this.objectInformation.hasPermission
  808. });
  809. break;
  810. case 'yearly':
  811. this.cadencePicker = new YearlyCadencePicker({
  812. $el: $cadence,
  813. objectInformation: {
  814. descriptor: this.objectInformation.descriptor,
  815. showDailyInterval: true
  816. },
  817. glassContext: this.glassContext,
  818. hasPermission: this.objectInformation.hasPermission
  819. });
  820. break;
  821. case 'trigger':
  822. this.cadencePicker = new TriggerCadencePicker({
  823. $el: $cadence,
  824. objectInformation: {
  825. descriptor: this.objectInformation.descriptor
  826. },
  827. glassContext: this.glassContext
  828. });
  829. break;
  830. default:
  831. console.log('Wrong cadence type.');
  832. }
  833. if (this.cadencePicker) {
  834. this.cadencePicker.render();
  835. }
  836. },
  837. renderOutputFormatPicker: function() {
  838. //var _self = this;
  839. var formats = this.options.outputFormat;
  840. if(this.isEditMode) {
  841. if(this.objectInformation.descriptor.options.outputFormat) {
  842. formats = this.objectInformation.descriptor.options.outputFormat.slice();
  843. }
  844. }
  845. try {
  846. /*
  847. We show all of the formats when it is not an interactive report or it is not a report view of an interactive report.
  848. Otherwise only html format shows
  849. */
  850. var showHtmlOnly = this.objectInformation.type === 'interactiveReport' ||
  851. this.objectInformation.type === 'reportView' &&
  852. this.objectInformation.base &&
  853. this.objectInformation.base[0] &&
  854. this.objectInformation.base[0].type &&
  855. this.objectInformation.base[0].type === 'interactiveReport';
  856. var showPdfOnly = this.objectInformation.type === 'powerPlay8Report' || this.objectInformation.type === 'powerPlay8ReportView';
  857. this.outputFormatPicker = new FormatPicker({
  858. $el: this.$el.find('.output_format_list'),
  859. $toggler: this.$el.find('.schedule_output_format_picker'),
  860. outputFormats: showPdfOnly ? this._getOutputFormatsForPowerPlayObjects(formats): formats.slice(),
  861. hasPermission: this.objectInformation.hasPermission,
  862. showHTML: !showPdfOnly,
  863. showPDF: (!showHtmlOnly) && this.glassContext.hasCapability('canGeneratePDFOutput'),
  864. showExcel: (!showHtmlOnly) && (!showPdfOnly) && this.glassContext.hasCapability('canGenerateXLSOutput'),
  865. showCSV: (!showHtmlOnly) && (!showPdfOnly) && this.glassContext.hasCapability('canGenerateCSVOutput'),
  866. showXML: (!showHtmlOnly) && (!showPdfOnly) && this.glassContext.hasCapability('canGenerateXMLOutput'),
  867. glassContext: this.glassContext,
  868. slideoutparent: this.slideout,
  869. overlay: false
  870. });
  871. this.outputFormatPicker.render();
  872. } catch(e) {
  873. console.log('There was an error initializing the FormatPicker.', e);
  874. }
  875. },
  876. _getOutputFormatsForPowerPlayObjects: function (formats) {
  877. if (!this.objectInformation.options) {
  878. return ['PDF'];
  879. } else {
  880. return formats.slice();
  881. }
  882. },
  883. _renderPromptRowForReport: function() {
  884. var _self = this;
  885. // content_apps.PromptValuesView uses 'objectInfo' instead of 'objectInformation'
  886. this.objectInfo = this.objectInformation;
  887. if(this.isEditMode) {
  888. if(this.descriptor.parameters) {
  889. this.parameterValues = this.descriptor.parameters;
  890. }
  891. }
  892. var hasScheduleParameterValues = this.parameterValues.length > 0;
  893. var displayParameterValues = hasScheduleParameterValues?this.parameterValues:this.reportParameterValues;
  894. this.$el.find('.prompt_picker_target').on('clicktap', function() {
  895. _self._closeOpenChildren().then(function() {
  896. _self.glassContext.appController.showSlideOut({
  897. 'position': _self.slideout ? null : 'right',
  898. 'parent': _self.slideout,
  899. 'width': '350',
  900. 'enableTabLooping': true,
  901. 'label': t.translate('schedule_prompt_picker_name'),
  902. 'content': {
  903. 'module': 'bi/content_apps/PromptValuesView',
  904. 'parentView': _self,
  905. 'glassContext': _self.glassContext,
  906. 'promptDisplayValues': ContentStoreObject.getPromptsDisplayValues(displayParameterValues),
  907. 'parameters': _self.parameterValues,
  908. 'hasPermission': _self.objectInformation.hasPermission,
  909. 'clearCallback': _self._updatePromptValueLabelCB.bind(_self),
  910. 'editCallback': _self._updatePromptValueLabelCB.bind(_self)
  911. }
  912. });
  913. }).done();
  914. });
  915. // Always show user specifically set parameter values first if any
  916. this._updatePromptValueLabel( displayParameterValues, !hasScheduleParameterValues);
  917. },
  918. renderPromptRow: function() {
  919. if (this.canShowPrompt){
  920. return this._renderPromptRowForReport();
  921. }
  922. },
  923. _updatePromptValueLabelCB: function(prompts) {
  924. // Set the parameter values associated with this schedule after user edit callback
  925. // Or reset the parameterValues to empty on Clear callback
  926. this.parameterValues = prompts? prompts:[];
  927. var $promptValueLabel = this.$el.find('.currentPromptValues');
  928. $promptValueLabel.text(this._getPromptValueLabel(this.parameterValues));
  929. },
  930. // On Render
  931. _updatePromptValueLabel: function(prompts, reportPrompts) {
  932. var $promptValueLabel = this.$el.find('.currentPromptValues');
  933. $promptValueLabel.text(this._getPromptValueLabel(prompts, reportPrompts));
  934. },
  935. _getPromptValueLabel: function(prompts, reportPrompts) {
  936. var label = t.translate('schedule_prompt_value_label_default');
  937. var prefix = reportPrompts?'report':'schedule';
  938. if (prompts && prompts.length > 0) {
  939. if(prompts.length == 1) {
  940. label = t.translate(prefix + '_prompt_value_label_single');
  941. } else {
  942. label = t.translate(prefix + '_prompt_value_label_multiple', {
  943. 'number': prompts.length
  944. });
  945. }
  946. }
  947. return label;
  948. },
  949. renderBurstCheckBox: function() {
  950. var burst = false;
  951. if(this.objectInformation && this.objectInformation.descriptor &&
  952. this.objectInformation.descriptor.options && this.objectInformation.descriptor.options.burst) {
  953. burst = this.objectInformation.descriptor.options.burst || false;
  954. }
  955. this.burstCheckbox = new CheckBox({
  956. 'id': 'schedule_burst_checkbox_' + this.uniqueId,
  957. 'el': this.$el.find('.schedule_burst_option_container'),
  958. 'name': 'schedule_burst_report',
  959. 'label': t.translate('schedule_burst_label'),
  960. 'ariaLabel': t.translate('schedule_burst_label'),
  961. 'checked': burst,
  962. 'controlOnLeft': true,
  963. 'onChange': function() {return;}
  964. });
  965. this.burstCheckbox.doRender();
  966. },
  967. close: function() {
  968. // Close off this pane
  969. this.slideout.hide();
  970. // temporary solution before glass overlay is ready
  971. $('.flyoutPane .pane-child').css('z-index', '-1');
  972. },
  973. /**
  974. * mark as in progress
  975. */
  976. setWorking: function() {
  977. this.$overlay = this.$el.find('.progress-overlay');
  978. this.$overlay.show();
  979. },
  980. /**
  981. * Show the view if hidden
  982. */
  983. setDone: function() {
  984. if(!this.$overlay) return;
  985. this.$overlay.hide();
  986. },
  987. _setIcons: function() {
  988. var icons = this.$el.find('.common_schedule_icon');
  989. for(var i = 0; i < icons.length; i++) {
  990. var $icon = $(icons[i]);
  991. Utils.setIcon($icon, 'common-' + $icon.data('icon'), t.translate('svg_expand_icon'));
  992. }
  993. },
  994. getScheduleType: function() {
  995. var capabilityType = this.getCapabilityScheduleType();
  996. if ( this.isEditMode ) {
  997. switch ( this.descriptor.scheduleInfo.type ) {
  998. case 'daily':
  999. case 'dailyWithIntradayRecurrence':
  1000. return 'daily';
  1001. case 'monthlyRelative':
  1002. case 'monthlyAbsolute':
  1003. case 'monthlyRelativeWithIntradayRecurrence':
  1004. case 'monthlyAbsoluteWithIntradayRecurrence':
  1005. return 'monthly';
  1006. case 'yearlyRelative':
  1007. case 'yearlyAbsolute':
  1008. case 'yearlyRelativeWithIntradayRecurrence':
  1009. case 'yearlyAbsoluteWithIntradayRecurrence':
  1010. return 'yearly';
  1011. case 'trigger':
  1012. return 'trigger';
  1013. default:
  1014. return 'weekly';
  1015. }
  1016. } else {
  1017. return capabilityType;
  1018. }
  1019. },
  1020. getCapabilityScheduleType: function() {
  1021. // Return the proper type according to capabilities for creating new
  1022. // default to "weekly" whenever possible
  1023. if ( this.glassContext.hasCapability('canUseSchedulingByWeek') ) {
  1024. return 'weekly';
  1025. }else {
  1026. if ( this.glassContext.hasCapability('canUseSchedulingByDay') ) {
  1027. return 'daily';
  1028. }else if (this.glassContext.hasCapability('canUseSchedulingByMonth')) {
  1029. return 'monthly';
  1030. }else if (this.glassContext.hasCapability('canUseSchedulingByYear')) {
  1031. return 'yearly';
  1032. } else if (this.glassContext.hasCapability('canUseSchedulingByTrigger')) {
  1033. return 'trigger';
  1034. }
  1035. }
  1036. return 'weekly';
  1037. },
  1038. validate: function() {
  1039. this.msgs = [];
  1040. this.msgs = this.datetimeRangeCadencePicker.validate(this.msgs);
  1041. if ( this.msgs.length > 0 ) {
  1042. return false;
  1043. }
  1044. this.msgs = this.cadencePicker.validate(this.msgs);
  1045. if ( this.msgs.length > 0 ) {
  1046. return false;
  1047. }
  1048. // Burst
  1049. var burst = this._getBurstValue();
  1050. // Check delivery Options
  1051. if(this.deliveryPicker) {
  1052. var deliveryOptions = this.deliveryPicker.getDeliveryOptions();
  1053. var $deliveryListDiv = this.$el.find('.delivery_list');
  1054. $deliveryListDiv.removeAttr('aria-invalid aria-describedby');
  1055. if (!burst) {
  1056. if (deliveryOptions.email) {
  1057. deliveryOptions.email.to = deliveryOptions.email.to? deliveryOptions.email.to : [];
  1058. deliveryOptions.email.cc = deliveryOptions.email.cc? deliveryOptions.email.cc : [];
  1059. deliveryOptions.email.bcc = deliveryOptions.email.bcc? deliveryOptions.email.bcc : [];
  1060. if(deliveryOptions.email.to.length === 0 && deliveryOptions.email.cc.length === 0 && deliveryOptions.email.bcc.length === 0) {
  1061. this.msgs.push(t.translate('schedule_delivery_no_email_recipients_error'));
  1062. $deliveryListDiv.attr({
  1063. 'aria-invalid': 'true',
  1064. 'aria-describedby': this.msgs[0]
  1065. });
  1066. return false;
  1067. }
  1068. if (!deliveryOptions.email.emailAsAttachment && !deliveryOptions.email.emailAsURL) {
  1069. this.msgs.push(t.translate('schedule_delivery_email_require_include'));
  1070. $deliveryListDiv.attr({
  1071. 'aria-invalid': 'true',
  1072. 'aria-describedby': this.msgs[0]
  1073. });
  1074. return false;
  1075. }
  1076. }
  1077. if (deliveryOptions.mobile) {
  1078. if(typeof deliveryOptions.mobile.to === 'undefined' || deliveryOptions.mobile.to.length === 0) {
  1079. this.msgs.push(t.translate('schedule_delivery_no_mobile_recipients_error'));
  1080. $deliveryListDiv.attr({
  1081. 'aria-invalid': 'true',
  1082. 'aria-describedby': this.msgs[0]
  1083. });
  1084. return false;
  1085. }
  1086. }
  1087. }
  1088. if(deliveryOptions.print && $.trim(deliveryOptions.print.name) === '') {
  1089. this.msgs.push(t.translate('schedule_delivery_printer_empty_error'));
  1090. $deliveryListDiv.attr({
  1091. 'aria-invalid': 'true',
  1092. 'aria-describedby': this.msgs[0]
  1093. });
  1094. return false;
  1095. }
  1096. if(deliveryOptions.archive && $.trim(deliveryOptions.archive.filenameStub) === '') {
  1097. this.msgs.push(t.translate('schedule_delivery_archive_name_empty_error'));
  1098. $deliveryListDiv.attr({
  1099. 'aria-invalid': 'true',
  1100. 'aria-describedby': this.msgs[0]
  1101. });
  1102. return false;
  1103. }
  1104. }
  1105. return this.msgs.length === 0;
  1106. },
  1107. /**
  1108. * Show warning message for invalid time/date/form input by user
  1109. */
  1110. showWarningMessage: function() {
  1111. this.warningMessage = this.$el.find('.invalid_input_warning_message');
  1112. if (!this.warningMessage) {
  1113. return;
  1114. }else {
  1115. this.warningMessage.text(this.msgs[0]);
  1116. }
  1117. this.warningMessage.show();
  1118. },
  1119. /**
  1120. * Hide the warning message
  1121. */
  1122. hideWarningMessage: function() {
  1123. if (!this.warningMessage) return;
  1124. this.warningMessage.hide();
  1125. },
  1126. /** If this is a burst-enabled report, get whether or not to burst.
  1127. * @return Whether the user wants this report bursted or not.
  1128. * Returns false if the report cannot be bursted.
  1129. */
  1130. _getBurstValue: function() {
  1131. var burst = false;
  1132. if(this.canBurst && typeof this.burstCheckbox !== 'undefined') {
  1133. burst = this.burstCheckbox.isChecked();
  1134. }
  1135. return burst;
  1136. }
  1137. });
  1138. return scheduleView;
  1139. });