From a09bd47bfd866871f1cf7362b6c1b03fecc0bdd3 Mon Sep 17 00:00:00 2001 From: Geoffrey Kwan Date: Mon, 21 May 2018 14:43:41 -0700 Subject: [PATCH 1/8] Authoring Tool: Added a "Valid JSON" and "Invalid JSON" message when authoring the project JSON. --- .../authoringTool/authoringToolController.es6 | 5 + .../authoringTool/authoringToolController.js | 6 ++ .../authoringToolController.js.map | 2 +- .../components/shared/toolbar/toolbar.es6 | 5 + .../components/shared/toolbar/toolbar.js | 5 +- .../components/shared/toolbar/toolbar.js.map | 2 +- .../wise5/authoringTool/i18n/i18n_en.json | 4 +- .../wise5/authoringTool/project/project.html | 4 +- .../project/projectController.es6 | 78 +++++++++++++++- .../project/projectController.js | 91 ++++++++++++++++++- .../project/projectController.js.map | 2 +- 11 files changed, 190 insertions(+), 14 deletions(-) diff --git a/src/main/webapp/wise5/authoringTool/authoringToolController.es6 b/src/main/webapp/wise5/authoringTool/authoringToolController.es6 index 4f027362c9..f2a03c1645 100644 --- a/src/main/webapp/wise5/authoringTool/authoringToolController.es6 +++ b/src/main/webapp/wise5/authoringTool/authoringToolController.es6 @@ -266,6 +266,11 @@ class AuthoringToolController { } else { this.projectTitle = null; } + this.turnOffJSONValidMessage(); + } + + turnOffJSONValidMessage() { + this.$rootScope.$broadcast('setIsJSONValid', { isJSONValid: null }); } /** diff --git a/src/main/webapp/wise5/authoringTool/authoringToolController.js b/src/main/webapp/wise5/authoringTool/authoringToolController.js index 17da20da6b..43229ce03d 100644 --- a/src/main/webapp/wise5/authoringTool/authoringToolController.js +++ b/src/main/webapp/wise5/authoringTool/authoringToolController.js @@ -252,6 +252,12 @@ var AuthoringToolController = function () { } else { this.projectTitle = null; } + this.turnOffJSONValidMessage(); + } + }, { + key: 'turnOffJSONValidMessage', + value: function turnOffJSONValidMessage() { + this.$rootScope.$broadcast('setIsJSONValid', { isJSONValid: null }); } /** diff --git a/src/main/webapp/wise5/authoringTool/authoringToolController.js.map b/src/main/webapp/wise5/authoringTool/authoringToolController.js.map index ee9ef40ad6..9f039190b1 100644 --- a/src/main/webapp/wise5/authoringTool/authoringToolController.js.map +++ b/src/main/webapp/wise5/authoringTool/authoringToolController.js.map @@ -1 +1 @@ -{"version":3,"sources":["authoringToolController.es6"],"names":["AuthoringToolController","$anchorScroll","$filter","$location","$mdDialog","$rootScope","$scope","$state","$timeout","ConfigService","ProjectService","SessionService","TeacherDataService","$translate","numberProject","isMenuOpen","views","id","name","label","icon","type","showToolbar","active","logoPath","getThemePath","processUI","$on","event","toState","toParams","fromState","fromParams","confirm","parent","angular","element","document","body","title","content","ariaLabel","ok","cancel","show","then","renewSession","forceLogOut","ev","alert","textContent","targetEvent","setGlobalMessage","Date","getTime","params","stateParams","isPopup","projectId","nodeId","componentId","target","targetObject","templateUrl","controller","controllerAs","$stateParams","clickOutsideToClose","escapeToClose","saveEvent","current","showStepTools","$current","view","currentViewName","getProjectId","runId","getRunId","projectTitle","getProjectTitle","url","mouseMoved","notifyAuthorProjectEnd","wiseBaseURL","getWISEBaseURL","window","location","message","time","globalMessage","text","$broadcast","eventName","category","context","componentType","data","$inject"],"mappings":"AAAA;;;;;;;;;;IAEMA,uB;AAEJ,mCACIC,aADJ,EAEIC,OAFJ,EAGIC,SAHJ,EAIIC,SAJJ,EAKIC,UALJ,EAMIC,MANJ,EAOIC,MAPJ,EAQIC,QARJ,EASIC,aATJ,EAUIC,cAVJ,EAWIC,cAXJ,EAYIC,kBAZJ,EAYwB;AAAA;;AAAA;;AACtB,SAAKX,aAAL,GAAqBA,aAArB;AACA,SAAKC,OAAL,GAAeA,OAAf;AACA,SAAKC,SAAL,GAAiBA,SAAjB;AACA,SAAKC,SAAL,GAAiBA,SAAjB;AACA,SAAKC,UAAL,GAAkBA,UAAlB;AACA,SAAKC,MAAL,GAAcA,MAAd;AACA,SAAKC,MAAL,GAAcA,MAAd;AACA,SAAKC,QAAL,GAAgBA,QAAhB;AACA,SAAKK,UAAL,GAAkB,KAAKX,OAAL,CAAa,WAAb,CAAlB;AACA,SAAKO,aAAL,GAAqBA,aAArB;AACA,SAAKC,cAAL,GAAsBA,cAAtB;AACA,SAAKC,cAAL,GAAsBA,cAAtB;AACA,SAAKC,kBAAL,GAA0BA,kBAA1B;;AAEA,SAAKE,aAAL,GAAqB,IAArB,CAfsB,CAeK;AAC3B,SAAKC,UAAL,GAAkB,KAAlB;;AAEA;AACA,SAAKC,KAAL,GAAa;AACX,sBAAgB;AACdC,YAAI,mBADU;AAEdC,cAAM,KAAKL,UAAL,CAAgB,aAAhB,CAFQ;AAGdM,eAAO,KAAKN,UAAL,CAAgB,aAAhB,CAHO;AAIdO,cAAM,MAJQ;AAKdC,cAAM,SALQ;AAMdC,qBAAa,IANC;AAOdC,gBAAQ;AAPM,OADL;AAUX,+BAAyB;AACvBN,YAAI,gBADmB;AAEvBC,cAAM,KAAKL,UAAL,CAAgB,kBAAhB,CAFiB;AAGvBM,eAAO,KAAKN,UAAL,CAAgB,kBAAhB,CAHgB;AAIvBO,cAAM,MAJiB;AAKvBC,cAAM,SALiB;AAMvBC,qBAAa,IANU;AAOvBC,gBAAQ;AAPe,OAVd;AAmBX,4BAAsB;AACpBN,YAAI,aADgB;AAEpBC,cAAM,KAAKL,UAAL,CAAgB,aAAhB,CAFc;AAGpBM,eAAO,KAAKN,UAAL,CAAgB,aAAhB,CAHa;AAIpBO,cAAM,aAJc;AAKpBC,cAAM,SALc;AAMpBC,qBAAa,IANO;AAOpBC,gBAAQ;AAPY,OAnBX;AA4BX,2BAAqB;AACnBN,YAAI,YADe;AAEnBC,cAAM,KAAKL,UAAL,CAAgB,cAAhB,CAFa;AAGnBM,eAAO,KAAKN,UAAL,CAAgB,cAAhB,CAHY;AAInBO,cAAM,MAJa;AAKnBC,cAAM,SALa;AAMnBC,qBAAa,IANM;AAOnBC,gBAAQ;AAPW,OA5BV;AAqCX,mBAAa;AACXN,YAAI,mBADO;AAEXC,cAAM,KAAKL,UAAL,CAAgB,cAAhB,CAFK;AAGXM,eAAO,KAAKN,UAAL,CAAgB,cAAhB,CAHI;AAIXO,cAAM,SAJK;AAKXC,cAAM,SALK;AAMXC,qBAAa,KANF;AAOXC,gBAAQ;AAPG,OArCF;AA8CX,2BAAqB;AACnBL,cAAM,EADa;AAEnBC,eAAO,EAFY;AAGnBC,cAAM,EAHa;AAInBC,cAAM,WAJa;AAKnBC,qBAAa,IALM;AAMnBC,gBAAQ;AANW,OA9CV;AAsDX,sCAAgC;AAC9BL,cAAM,EADwB;AAE9BC,eAAO,EAFuB;AAG9BC,cAAM,EAHwB;AAI9BC,cAAM,WAJwB;AAK9BC,qBAAa,IALiB;AAM9BC,gBAAQ;AANsB,OAtDrB;AA8DX,oCAA8B;AAC5BL,cAAM,EADsB;AAE5BC,eAAO,EAFqB;AAG5BC,cAAM,EAHsB;AAI5BC,cAAM,WAJsB;AAK5BC,qBAAa,IALe;AAM5BC,gBAAQ;AANoB;AA9DnB,KAAb;;AAwEA,SAAKC,QAAL,GAAgB,KAAKd,cAAL,CAAoBe,YAApB,KAAqC,8BAArD;AACA,SAAKC,SAAL;;AAEA;AACA,SAAKpB,MAAL,CAAYqB,GAAZ,CAAgB,qBAAhB,EACI,UAACC,KAAD,EAAQC,OAAR,EAAiBC,QAAjB,EAA2BC,SAA3B,EAAsCC,UAAtC,EAAqD;AACvD,YAAKjB,UAAL,GAAkB,KAAlB;AACA,YAAKW,SAAL;AACD,KAJD;;AAMApB,WAAOqB,GAAP,CAAW,oBAAX,EAAiC,YAAM;AACrC,UAAIM,UAAU,MAAK7B,SAAL,CAAe6B,OAAf,GACTC,MADS,CACFC,QAAQC,OAAR,CAAgBC,SAASC,IAAzB,CADE,EAETC,KAFS,CAEH,MAAK1B,UAAL,CAAgB,gBAAhB,CAFG,EAGT2B,OAHS,CAGD,MAAK3B,UAAL,CAAgB,mBAAhB,CAHC,EAIT4B,SAJS,CAIC,MAAK5B,UAAL,CAAgB,gBAAhB,CAJD,EAKT6B,EALS,CAKN,MAAK7B,UAAL,CAAgB,KAAhB,CALM,EAMT8B,MANS,CAMF,MAAK9B,UAAL,CAAgB,IAAhB,CANE,CAAd;AAOA,YAAKT,SAAL,CAAewC,IAAf,CAAoBX,OAApB,EAA6BY,IAA7B,CAAkC,YAAM;AACtC,cAAKlC,cAAL,CAAoBmC,YAApB;AACD,OAFD,EAEG,YAAM;AACP,cAAKnC,cAAL,CAAoBoC,WAApB;AACD,OAJD;AAKD,KAbD;;AAeA;AACA,SAAKzC,MAAL,CAAYqB,GAAZ,CAAgB,mBAAhB,EAAqC,UAACqB,EAAD,EAAQ;AAC3C,UAAIC,QAAQ,MAAK7C,SAAL,CAAe6B,OAAf,GACPC,MADO,CACAC,QAAQC,OAAR,CAAgBC,SAASC,IAAzB,CADA,EAEPC,KAFO,CAED,MAAK1B,UAAL,CAAgB,cAAhB,CAFC,EAGPqC,WAHO,CAGK,MAAKrC,UAAL,CAAgB,kCAAhB,CAHL,EAIP4B,SAJO,CAIG,MAAK5B,UAAL,CAAgB,cAAhB,CAJH,EAKPsC,WALO,CAKKH,EALL,EAMPN,EANO,CAMJ,MAAK7B,UAAL,CAAgB,IAAhB,CANI,CAAZ;;AAQA,YAAKT,SAAL,CAAewC,IAAf,CAAoBK,KAApB,EAA2BJ,IAA3B,CAAgC,YAAM;AACpC;AACD,OAFD,EAEG,YAAM;AACP;AACD,OAJD;AAKD,KAdD;;AAgBA;;;;;AAKA,SAAKvC,MAAL,CAAYqB,GAAZ,CAAgB,eAAhB,EAAiC,YAAM;AACrC,YAAKyB,gBAAL,CAAsB,MAAKvC,UAAL,CAAgB,QAAhB,CAAtB,EAAiD,IAAjD;AACD,KAFD;;AAIA;;;;AAIA,SAAKP,MAAL,CAAYqB,GAAZ,CAAgB,cAAhB,EAAgC,YAAM;;AAEpC;;;;;;;AAOA,YAAKnB,QAAL,CAAc,YAAM;AAClB,cAAK4C,gBAAL,CAAsB,MAAKvC,UAAL,CAAgB,OAAhB,CAAtB,EAAgD,IAAIwC,IAAJ,GAAWC,OAAX,EAAhD;AACD,OAFD,EAEG,GAFH;AAGD,KAZD;;AAcA;;;;AAIA,SAAKhD,MAAL,CAAYqB,GAAZ,CAAgB,kBAAhB,EAAoC,UAACC,KAAD,EAAQ2B,MAAR,EAAmB;AACrD;AACA,UAAMC,cAAc;AAChBC,iBAASF,OAAOE,OADA;AAEhBC,mBAAWH,OAAOG,SAFF;AAGhBC,gBAAQJ,OAAOI,MAHC;AAIhBC,qBAAaL,OAAOK,WAJJ;AAKhBC,gBAAQN,OAAOM,MALC;AAMhBC,sBAAcP,OAAOO;AANL,OAApB;;AASA;AACA,YAAK1D,SAAL,CAAewC,IAAf,CAAoB;AAChBmB,qBAAa,sCADG;AAEhBC,oBAAY,wBAFI;AAGhBC,sBAAc,wBAHE;AAIhBC,sBAAcV,WAJE;AAKhBW,6BAAqB,IALL;AAMhBC,uBAAe;AANC,OAApB;AAQD,KApBD;;AAsBA;;;;AAIA,SAAK9D,MAAL,CAAYqB,GAAZ,CAAgB,qBAAhB,EAAuC,UAACC,KAAD,EAAQ2B,MAAR,EAAmB;AACxD;AACA,UAAMC,cAAc;AAChBE,mBAAWH,OAAOG,SADF;AAEhBC,gBAAQJ,OAAOI,MAFC;AAGhBC,qBAAaL,OAAOK,WAHJ;AAIhBC,gBAAQN,OAAOM;AAJC,OAApB;;AAOA;AACA,YAAKzD,SAAL,CAAewC,IAAf,CAAoB;AAChBmB,qBAAa,qDADG;AAEhBC,oBAAY,6BAFI;AAGhBC,sBAAc,6BAHE;AAIhBC,sBAAcV,WAJE;AAKhBW,6BAAqB,IALL;AAMhBC,uBAAe;AANC,OAApB;AAQD,KAlBD;;AAoBA,SAAK/D,UAAL,CAAgBsB,GAAhB,CAAoB,qBAApB,EACI,UAACC,KAAD,EAAQC,OAAR,EAAiBC,QAAjB,EAA2BC,SAA3B,EAAsCC,UAAtC,EAAqD;AACvD,UAAIH,WAAW,IAAX,IAAmBA,QAAQX,IAAR,IAAgB,WAAvC,EAAoD;AAClD,cAAKmD,SAAL,CAAe,mBAAf,EAAoC,YAApC;AACD;AACF,KALD;;AAOA,QAAI,KAAK9D,MAAL,CAAY+D,OAAZ,CAAoBpD,IAApB,IAA4B,WAAhC,EAA6C;AAC3C,WAAKmD,SAAL,CAAe,mBAAf,EAAoC,YAApC;AACD;AACF;;AAED;;;;;;;;gCAIY;AACV;AACA,WAAKpE,aAAL,CAAmB,KAAnB;;AAEA;AACA,WAAKsE,aAAL,GAAqB,KAAKhE,MAAL,CAAYiE,QAAZ,CAAqBtD,IAArB,KAA8B,cAA9B,IACjB,KAAKX,MAAL,CAAYiE,QAAZ,CAAqBtD,IAArB,KAA8B,mBADb,IAEjB,KAAKX,MAAL,CAAYiE,QAAZ,CAAqBtD,IAArB,KAA8B,8BAFb,IAGnB,KAAKX,MAAL,CAAYiE,QAAZ,CAAqBtD,IAArB,KAA8B,4BAHhC;AAIA,UAAMuD,OAAO,KAAKzD,KAAL,CAAW,KAAKT,MAAL,CAAYiE,QAAZ,CAAqBtD,IAAhC,CAAb;AACA,UAAIuD,IAAJ,EAAU;AACR,aAAKC,eAAL,GAAuBD,KAAKvD,IAA5B;AACA,aAAKI,WAAL,GAAmBmD,KAAKnD,WAAxB;AACD,OAHD,MAGO;AACL,aAAKoD,eAAL,GAAuB,EAAvB;AACA,aAAKpD,WAAL,GAAmB,KAAnB;AACD;;AAED,WAAKoC,SAAL,GAAiB,KAAKjD,aAAL,CAAmBkE,YAAnB,EAAjB;AACA,WAAKC,KAAL,GAAa,KAAKnE,aAAL,CAAmBoE,QAAnB,EAAb;;AAEA,UAAI,KAAKnB,SAAT,EAAoB;AAClB,aAAKoB,YAAL,GAAoB,KAAKpE,cAAL,CAAoBqE,eAApB,EAApB;AACD,OAFD,MAEO;AACL,aAAKD,YAAL,GAAoB,IAApB;AACD;AACF;;AAED;;;;;;qCAGiB;AACf,WAAK3E,SAAL,CAAe6E,GAAf,CAAmB,SAAnB;AACD;;AAED;;;;;;iCAGa;AACX,WAAKjE,UAAL,GAAkB,CAAC,KAAKA,UAAxB;AACD;;AAED;;;;;;iCAGa;AACX,WAAKJ,cAAL,CAAoBsE,UAApB;AACD;;;2BAEM;AAAA;;AACL,WAAKvE,cAAL,CAAoBwE,sBAApB,GAA6CrC,IAA7C,CAAkD,YAAM;AACtD,YAAIsC,cAAc,OAAK1E,aAAL,CAAmB2E,cAAnB,EAAlB;AACAC,eAAOC,QAAP,GAAkBH,cAAc,UAAhC;AACD,OAHD;AAID;;AAED;;;;;;;;qCAKiBI,O,EAASC,I,EAAM;AAC9B,UAAMC,gBAAgB;AACpBC,cAAMH,OADc;AAEpBC,cAAMA;AAFc,OAAtB;AAIA,WAAKnF,UAAL,CAAgBsF,UAAhB,CAA2B,kBAA3B,EAA+C,EAAEF,eAAeA,aAAjB,EAA/C;AACD;;;;;AAED;;;;;;8BAMUG,S,EAAWC,Q,EAAU;AAC7B,UAAIC,UAAU,eAAd;AACA,UAAInC,SAAS,IAAb;AACA,UAAIC,cAAc,IAAlB;AACA,UAAImC,gBAAgB,IAApB;AACA,UAAIC,OAAO,EAAX;;AAEA,WAAKpF,kBAAL,CAAwByD,SAAxB,CAAkCyB,OAAlC,EAA2CnC,MAA3C,EAAmDC,WAAnD,EACImC,aADJ,EACmBF,QADnB,EAC6BD,SAD7B,EACwCI,IADxC;AAED;;;;;;AAGHhG,wBAAwBiG,OAAxB,GAAkC,CAChC,eADgC,EAEhC,SAFgC,EAGhC,WAHgC,EAIhC,WAJgC,EAKhC,YALgC,EAMhC,QANgC,EAOhC,QAPgC,EAQhC,UARgC,EAShC,eATgC,EAUhC,gBAVgC,EAWhC,gBAXgC,EAYhC,oBAZgC,EAahC,QAbgC,CAAlC;;kBAgBejG,uB","file":"authoringToolController.js","sourcesContent":["'use strict';\n\nclass AuthoringToolController {\n\n constructor(\n $anchorScroll,\n $filter,\n $location,\n $mdDialog,\n $rootScope,\n $scope,\n $state,\n $timeout,\n ConfigService,\n ProjectService,\n SessionService,\n TeacherDataService) {\n this.$anchorScroll = $anchorScroll;\n this.$filter = $filter;\n this.$location = $location;\n this.$mdDialog = $mdDialog;\n this.$rootScope = $rootScope;\n this.$scope = $scope;\n this.$state = $state;\n this.$timeout = $timeout;\n this.$translate = this.$filter('translate');\n this.ConfigService = ConfigService;\n this.ProjectService = ProjectService;\n this.SessionService = SessionService;\n this.TeacherDataService = TeacherDataService;\n\n this.numberProject = true; // TODO: make dynamic or remove\n this.isMenuOpen = false;\n\n // ui-views and their corresponding names, labels, and icons\n this.views = {\n 'root.project': {\n id: 'projectHomeButton',\n name: this.$translate('projectHome'),\n label: this.$translate('projectHome'),\n icon: 'home',\n type: 'primary',\n showToolbar: true,\n active: true\n },\n 'root.project.notebook': {\n id: 'notebookButton',\n name: this.$translate('notebookSettings'),\n label: this.$translate('notebookSettings'),\n icon: 'book',\n type: 'primary',\n showToolbar: true,\n active: true\n },\n 'root.project.asset': {\n id: 'assetButton',\n name: this.$translate('fileManager'),\n label: this.$translate('fileManager'),\n icon: 'attach_file',\n type: 'primary',\n showToolbar: true,\n active: true\n },\n 'root.project.info': {\n id: 'infoButton',\n name: this.$translate('PROJECT_INFO'),\n label: this.$translate('PROJECT_INFO'),\n icon: 'info',\n type: 'primary',\n showToolbar: true,\n active: true\n },\n 'root.main': {\n id: 'projectListButton',\n name: this.$translate('projectsList'),\n label: this.$translate('projectsList'),\n icon: 'reorder',\n type: 'primary',\n showToolbar: false,\n active: true\n },\n 'root.project.node': {\n name: '',\n label: '',\n icon: '',\n type: 'secondary',\n showToolbar: true,\n active: false\n },\n 'root.project.nodeConstraints': {\n name: '',\n label: '',\n icon: '',\n type: 'secondary',\n showToolbar: true,\n active: false\n },\n 'root.project.nodeEditPaths': {\n name: '',\n label: '',\n icon: '',\n type: 'secondary',\n showToolbar: true,\n active: false\n },\n };\n\n this.logoPath = this.ProjectService.getThemePath() + '/images/WISE-logo-ffffff.svg';\n this.processUI();\n\n // listen for state change events and close the menu\n this.$scope.$on('$stateChangeSuccess',\n (event, toState, toParams, fromState, fromParams) => {\n this.isMenuOpen = false;\n this.processUI();\n });\n\n $scope.$on('showSessionWarning', () => {\n let confirm = this.$mdDialog.confirm()\n .parent(angular.element(document.body))\n .title(this.$translate('sessionTimeout'))\n .content(this.$translate('autoLogoutMessage'))\n .ariaLabel(this.$translate('sessionTimeout'))\n .ok(this.$translate('yes'))\n .cancel(this.$translate('no'));\n this.$mdDialog.show(confirm).then(() => {\n this.SessionService.renewSession();\n }, () => {\n this.SessionService.forceLogOut();\n });\n });\n\n // alert user when they're inactive for a long time\n this.$scope.$on('showRequestLogout', (ev) => {\n let alert = this.$mdDialog.confirm()\n .parent(angular.element(document.body))\n .title(this.$translate('serverUpdate'))\n .textContent(this.$translate('serverUpdateRequestLogoutMessage'))\n .ariaLabel(this.$translate('serverUpdate'))\n .targetEvent(ev)\n .ok(this.$translate('ok'));\n\n this.$mdDialog.show(alert).then(() => {\n // do nothing\n }, () => {\n // do nothing\n });\n });\n\n /*\n * Listen for the savingProject event which means the authoring tool\n * is in the process of saving the project and display this information\n * globally.\n */\n this.$scope.$on('savingProject', () => {\n this.setGlobalMessage(this.$translate('saving'), null);\n });\n\n /*\n * Listen for the projectSaved event which means the project has just\n * been saved to the server\n */\n this.$scope.$on('projectSaved', () => {\n\n /*\n * Wait half a second before changing the message to 'Saved' so that\n * the 'Saving...' message stays up long enough for the author to\n * see that the project is saving. If we don't perform this wait,\n * it will always say 'Saved' and authors may wonder whether the\n * project ever gets saved.\n */\n this.$timeout(() => {\n this.setGlobalMessage(this.$translate('SAVED'), new Date().getTime());\n }, 500);\n });\n\n /*\n * Open the asset chooser to let the author insert an asset into the\n * specified target\n */\n this.$scope.$on('openAssetChooser', (event, params) => {\n // create the params for opening the asset chooser\n const stateParams = {\n isPopup: params.isPopup,\n projectId: params.projectId,\n nodeId: params.nodeId,\n componentId: params.componentId,\n target: params.target,\n targetObject: params.targetObject\n };\n\n // open the dialog that will display the assets for the user to choose\n this.$mdDialog.show({\n templateUrl: 'wise5/authoringTool/asset/asset.html',\n controller: 'ProjectAssetController',\n controllerAs: 'projectAssetController',\n $stateParams: stateParams,\n clickOutsideToClose: true,\n escapeToClose: true\n });\n });\n\n /*\n * Open the asset chooser to let the author insert an WISE Link into the\n * specified target\n */\n this.$scope.$on('openWISELinkChooser', (event, params) => {\n // create the params for opening the WISE Link authoring popup\n const stateParams = {\n projectId: params.projectId,\n nodeId: params.nodeId,\n componentId: params.componentId,\n target: params.target\n };\n\n // open the WISE Link authoring popup\n this.$mdDialog.show({\n templateUrl: 'wise5/authoringTool/wiseLink/wiseLinkAuthoring.html',\n controller: 'WISELinkAuthoringController',\n controllerAs: 'wiseLinkAuthoringController',\n $stateParams: stateParams,\n clickOutsideToClose: true,\n escapeToClose: true\n });\n });\n\n this.$rootScope.$on('$stateChangeSuccess',\n (event, toState, toParams, fromState, fromParams) => {\n if (toState != null && toState.name == 'root.main') {\n this.saveEvent('projectListViewed', 'Navigation');\n }\n });\n\n if (this.$state.current.name == 'root.main') {\n this.saveEvent('projectListViewed', 'Navigation');\n }\n }\n\n /**\n * Update UI items based on state, show or hide relevant menus and toolbars\n * TODO: remove/rework this and put items in their own ui states?\n */\n processUI() {\n // scroll to the top of the page\n this.$anchorScroll('top');\n\n // set current view and whether to show the toolbars and step tools\n this.showStepTools = this.$state.$current.name === 'root.project' ||\n this.$state.$current.name === 'root.project.node' ||\n this.$state.$current.name === 'root.project.nodeConstraints' ||\n this.$state.$current.name === 'root.project.nodeEditPaths';\n const view = this.views[this.$state.$current.name];\n if (view) {\n this.currentViewName = view.name;\n this.showToolbar = view.showToolbar;\n } else {\n this.currentViewName = '';\n this.showToolbar = false;\n }\n\n this.projectId = this.ConfigService.getProjectId();\n this.runId = this.ConfigService.getRunId();\n\n if (this.projectId) {\n this.projectTitle = this.ProjectService.getProjectTitle();\n } else {\n this.projectTitle = null;\n }\n }\n\n /**\n * Navigate the user to the My Projects page in the Authoring Tool\n */\n goToMyProjects() {\n this.$location.url('/author');\n }\n\n /**\n * Toggle the authoring tool main menu\n */\n toggleMenu() {\n this.isMenuOpen = !this.isMenuOpen;\n }\n\n /**\n * Notify Session to renew when user moves the mouse\n */\n mouseMoved() {\n this.SessionService.mouseMoved();\n }\n\n exit() {\n this.ProjectService.notifyAuthorProjectEnd().then(() => {\n let wiseBaseURL = this.ConfigService.getWISEBaseURL();\n window.location = wiseBaseURL + '/teacher';\n });\n }\n\n /**\n * Set the global message at the top right\n * @param message the message to display\n * @param time the time to display\n */\n setGlobalMessage(message, time) {\n const globalMessage = {\n text: message,\n time: time\n };\n this.$rootScope.$broadcast('setGlobalMessage', { globalMessage: globalMessage });\n };\n\n /**\n * Save an Authoring Tool event\n * @param eventName the name of the event\n * @param category the category of the event\n * example 'Navigation' or 'Authoring'\n */\n saveEvent(eventName, category) {\n let context = 'AuthoringTool';\n let nodeId = null;\n let componentId = null;\n let componentType = null;\n let data = {};\n\n this.TeacherDataService.saveEvent(context, nodeId, componentId,\n componentType, category, eventName, data);\n }\n}\n\nAuthoringToolController.$inject = [\n '$anchorScroll',\n '$filter',\n '$location',\n '$mdDialog',\n '$rootScope',\n '$scope',\n '$state',\n '$timeout',\n 'ConfigService',\n 'ProjectService',\n 'SessionService',\n 'TeacherDataService',\n 'moment'\n];\n\nexport default AuthoringToolController;\n"]} \ No newline at end of file +{"version":3,"sources":["authoringToolController.es6"],"names":["AuthoringToolController","$anchorScroll","$filter","$location","$mdDialog","$rootScope","$scope","$state","$timeout","ConfigService","ProjectService","SessionService","TeacherDataService","$translate","numberProject","isMenuOpen","views","id","name","label","icon","type","showToolbar","active","logoPath","getThemePath","processUI","$on","event","toState","toParams","fromState","fromParams","confirm","parent","angular","element","document","body","title","content","ariaLabel","ok","cancel","show","then","renewSession","forceLogOut","ev","alert","textContent","targetEvent","setGlobalMessage","Date","getTime","params","stateParams","isPopup","projectId","nodeId","componentId","target","targetObject","templateUrl","controller","controllerAs","$stateParams","clickOutsideToClose","escapeToClose","saveEvent","current","showStepTools","$current","view","currentViewName","getProjectId","runId","getRunId","projectTitle","getProjectTitle","turnOffJSONValidMessage","$broadcast","isJSONValid","url","mouseMoved","notifyAuthorProjectEnd","wiseBaseURL","getWISEBaseURL","window","location","message","time","globalMessage","text","eventName","category","context","componentType","data","$inject"],"mappings":"AAAA;;;;;;;;;;IAEMA,uB;AAEJ,mCACIC,aADJ,EAEIC,OAFJ,EAGIC,SAHJ,EAIIC,SAJJ,EAKIC,UALJ,EAMIC,MANJ,EAOIC,MAPJ,EAQIC,QARJ,EASIC,aATJ,EAUIC,cAVJ,EAWIC,cAXJ,EAYIC,kBAZJ,EAYwB;AAAA;;AAAA;;AACtB,SAAKX,aAAL,GAAqBA,aAArB;AACA,SAAKC,OAAL,GAAeA,OAAf;AACA,SAAKC,SAAL,GAAiBA,SAAjB;AACA,SAAKC,SAAL,GAAiBA,SAAjB;AACA,SAAKC,UAAL,GAAkBA,UAAlB;AACA,SAAKC,MAAL,GAAcA,MAAd;AACA,SAAKC,MAAL,GAAcA,MAAd;AACA,SAAKC,QAAL,GAAgBA,QAAhB;AACA,SAAKK,UAAL,GAAkB,KAAKX,OAAL,CAAa,WAAb,CAAlB;AACA,SAAKO,aAAL,GAAqBA,aAArB;AACA,SAAKC,cAAL,GAAsBA,cAAtB;AACA,SAAKC,cAAL,GAAsBA,cAAtB;AACA,SAAKC,kBAAL,GAA0BA,kBAA1B;;AAEA,SAAKE,aAAL,GAAqB,IAArB,CAfsB,CAeK;AAC3B,SAAKC,UAAL,GAAkB,KAAlB;;AAEA;AACA,SAAKC,KAAL,GAAa;AACX,sBAAgB;AACdC,YAAI,mBADU;AAEdC,cAAM,KAAKL,UAAL,CAAgB,aAAhB,CAFQ;AAGdM,eAAO,KAAKN,UAAL,CAAgB,aAAhB,CAHO;AAIdO,cAAM,MAJQ;AAKdC,cAAM,SALQ;AAMdC,qBAAa,IANC;AAOdC,gBAAQ;AAPM,OADL;AAUX,+BAAyB;AACvBN,YAAI,gBADmB;AAEvBC,cAAM,KAAKL,UAAL,CAAgB,kBAAhB,CAFiB;AAGvBM,eAAO,KAAKN,UAAL,CAAgB,kBAAhB,CAHgB;AAIvBO,cAAM,MAJiB;AAKvBC,cAAM,SALiB;AAMvBC,qBAAa,IANU;AAOvBC,gBAAQ;AAPe,OAVd;AAmBX,4BAAsB;AACpBN,YAAI,aADgB;AAEpBC,cAAM,KAAKL,UAAL,CAAgB,aAAhB,CAFc;AAGpBM,eAAO,KAAKN,UAAL,CAAgB,aAAhB,CAHa;AAIpBO,cAAM,aAJc;AAKpBC,cAAM,SALc;AAMpBC,qBAAa,IANO;AAOpBC,gBAAQ;AAPY,OAnBX;AA4BX,2BAAqB;AACnBN,YAAI,YADe;AAEnBC,cAAM,KAAKL,UAAL,CAAgB,cAAhB,CAFa;AAGnBM,eAAO,KAAKN,UAAL,CAAgB,cAAhB,CAHY;AAInBO,cAAM,MAJa;AAKnBC,cAAM,SALa;AAMnBC,qBAAa,IANM;AAOnBC,gBAAQ;AAPW,OA5BV;AAqCX,mBAAa;AACXN,YAAI,mBADO;AAEXC,cAAM,KAAKL,UAAL,CAAgB,cAAhB,CAFK;AAGXM,eAAO,KAAKN,UAAL,CAAgB,cAAhB,CAHI;AAIXO,cAAM,SAJK;AAKXC,cAAM,SALK;AAMXC,qBAAa,KANF;AAOXC,gBAAQ;AAPG,OArCF;AA8CX,2BAAqB;AACnBL,cAAM,EADa;AAEnBC,eAAO,EAFY;AAGnBC,cAAM,EAHa;AAInBC,cAAM,WAJa;AAKnBC,qBAAa,IALM;AAMnBC,gBAAQ;AANW,OA9CV;AAsDX,sCAAgC;AAC9BL,cAAM,EADwB;AAE9BC,eAAO,EAFuB;AAG9BC,cAAM,EAHwB;AAI9BC,cAAM,WAJwB;AAK9BC,qBAAa,IALiB;AAM9BC,gBAAQ;AANsB,OAtDrB;AA8DX,oCAA8B;AAC5BL,cAAM,EADsB;AAE5BC,eAAO,EAFqB;AAG5BC,cAAM,EAHsB;AAI5BC,cAAM,WAJsB;AAK5BC,qBAAa,IALe;AAM5BC,gBAAQ;AANoB;AA9DnB,KAAb;;AAwEA,SAAKC,QAAL,GAAgB,KAAKd,cAAL,CAAoBe,YAApB,KAAqC,8BAArD;AACA,SAAKC,SAAL;;AAEA;AACA,SAAKpB,MAAL,CAAYqB,GAAZ,CAAgB,qBAAhB,EACI,UAACC,KAAD,EAAQC,OAAR,EAAiBC,QAAjB,EAA2BC,SAA3B,EAAsCC,UAAtC,EAAqD;AACvD,YAAKjB,UAAL,GAAkB,KAAlB;AACA,YAAKW,SAAL;AACD,KAJD;;AAMApB,WAAOqB,GAAP,CAAW,oBAAX,EAAiC,YAAM;AACrC,UAAIM,UAAU,MAAK7B,SAAL,CAAe6B,OAAf,GACTC,MADS,CACFC,QAAQC,OAAR,CAAgBC,SAASC,IAAzB,CADE,EAETC,KAFS,CAEH,MAAK1B,UAAL,CAAgB,gBAAhB,CAFG,EAGT2B,OAHS,CAGD,MAAK3B,UAAL,CAAgB,mBAAhB,CAHC,EAIT4B,SAJS,CAIC,MAAK5B,UAAL,CAAgB,gBAAhB,CAJD,EAKT6B,EALS,CAKN,MAAK7B,UAAL,CAAgB,KAAhB,CALM,EAMT8B,MANS,CAMF,MAAK9B,UAAL,CAAgB,IAAhB,CANE,CAAd;AAOA,YAAKT,SAAL,CAAewC,IAAf,CAAoBX,OAApB,EAA6BY,IAA7B,CAAkC,YAAM;AACtC,cAAKlC,cAAL,CAAoBmC,YAApB;AACD,OAFD,EAEG,YAAM;AACP,cAAKnC,cAAL,CAAoBoC,WAApB;AACD,OAJD;AAKD,KAbD;;AAeA;AACA,SAAKzC,MAAL,CAAYqB,GAAZ,CAAgB,mBAAhB,EAAqC,UAACqB,EAAD,EAAQ;AAC3C,UAAIC,QAAQ,MAAK7C,SAAL,CAAe6B,OAAf,GACPC,MADO,CACAC,QAAQC,OAAR,CAAgBC,SAASC,IAAzB,CADA,EAEPC,KAFO,CAED,MAAK1B,UAAL,CAAgB,cAAhB,CAFC,EAGPqC,WAHO,CAGK,MAAKrC,UAAL,CAAgB,kCAAhB,CAHL,EAIP4B,SAJO,CAIG,MAAK5B,UAAL,CAAgB,cAAhB,CAJH,EAKPsC,WALO,CAKKH,EALL,EAMPN,EANO,CAMJ,MAAK7B,UAAL,CAAgB,IAAhB,CANI,CAAZ;;AAQA,YAAKT,SAAL,CAAewC,IAAf,CAAoBK,KAApB,EAA2BJ,IAA3B,CAAgC,YAAM;AACpC;AACD,OAFD,EAEG,YAAM;AACP;AACD,OAJD;AAKD,KAdD;;AAgBA;;;;;AAKA,SAAKvC,MAAL,CAAYqB,GAAZ,CAAgB,eAAhB,EAAiC,YAAM;AACrC,YAAKyB,gBAAL,CAAsB,MAAKvC,UAAL,CAAgB,QAAhB,CAAtB,EAAiD,IAAjD;AACD,KAFD;;AAIA;;;;AAIA,SAAKP,MAAL,CAAYqB,GAAZ,CAAgB,cAAhB,EAAgC,YAAM;;AAEpC;;;;;;;AAOA,YAAKnB,QAAL,CAAc,YAAM;AAClB,cAAK4C,gBAAL,CAAsB,MAAKvC,UAAL,CAAgB,OAAhB,CAAtB,EAAgD,IAAIwC,IAAJ,GAAWC,OAAX,EAAhD;AACD,OAFD,EAEG,GAFH;AAGD,KAZD;;AAcA;;;;AAIA,SAAKhD,MAAL,CAAYqB,GAAZ,CAAgB,kBAAhB,EAAoC,UAACC,KAAD,EAAQ2B,MAAR,EAAmB;AACrD;AACA,UAAMC,cAAc;AAChBC,iBAASF,OAAOE,OADA;AAEhBC,mBAAWH,OAAOG,SAFF;AAGhBC,gBAAQJ,OAAOI,MAHC;AAIhBC,qBAAaL,OAAOK,WAJJ;AAKhBC,gBAAQN,OAAOM,MALC;AAMhBC,sBAAcP,OAAOO;AANL,OAApB;;AASA;AACA,YAAK1D,SAAL,CAAewC,IAAf,CAAoB;AAChBmB,qBAAa,sCADG;AAEhBC,oBAAY,wBAFI;AAGhBC,sBAAc,wBAHE;AAIhBC,sBAAcV,WAJE;AAKhBW,6BAAqB,IALL;AAMhBC,uBAAe;AANC,OAApB;AAQD,KApBD;;AAsBA;;;;AAIA,SAAK9D,MAAL,CAAYqB,GAAZ,CAAgB,qBAAhB,EAAuC,UAACC,KAAD,EAAQ2B,MAAR,EAAmB;AACxD;AACA,UAAMC,cAAc;AAChBE,mBAAWH,OAAOG,SADF;AAEhBC,gBAAQJ,OAAOI,MAFC;AAGhBC,qBAAaL,OAAOK,WAHJ;AAIhBC,gBAAQN,OAAOM;AAJC,OAApB;;AAOA;AACA,YAAKzD,SAAL,CAAewC,IAAf,CAAoB;AAChBmB,qBAAa,qDADG;AAEhBC,oBAAY,6BAFI;AAGhBC,sBAAc,6BAHE;AAIhBC,sBAAcV,WAJE;AAKhBW,6BAAqB,IALL;AAMhBC,uBAAe;AANC,OAApB;AAQD,KAlBD;;AAoBA,SAAK/D,UAAL,CAAgBsB,GAAhB,CAAoB,qBAApB,EACI,UAACC,KAAD,EAAQC,OAAR,EAAiBC,QAAjB,EAA2BC,SAA3B,EAAsCC,UAAtC,EAAqD;AACvD,UAAIH,WAAW,IAAX,IAAmBA,QAAQX,IAAR,IAAgB,WAAvC,EAAoD;AAClD,cAAKmD,SAAL,CAAe,mBAAf,EAAoC,YAApC;AACD;AACF,KALD;;AAOA,QAAI,KAAK9D,MAAL,CAAY+D,OAAZ,CAAoBpD,IAApB,IAA4B,WAAhC,EAA6C;AAC3C,WAAKmD,SAAL,CAAe,mBAAf,EAAoC,YAApC;AACD;AACF;;AAED;;;;;;;;gCAIY;AACV;AACA,WAAKpE,aAAL,CAAmB,KAAnB;;AAEA;AACA,WAAKsE,aAAL,GAAqB,KAAKhE,MAAL,CAAYiE,QAAZ,CAAqBtD,IAArB,KAA8B,cAA9B,IACjB,KAAKX,MAAL,CAAYiE,QAAZ,CAAqBtD,IAArB,KAA8B,mBADb,IAEjB,KAAKX,MAAL,CAAYiE,QAAZ,CAAqBtD,IAArB,KAA8B,8BAFb,IAGnB,KAAKX,MAAL,CAAYiE,QAAZ,CAAqBtD,IAArB,KAA8B,4BAHhC;AAIA,UAAMuD,OAAO,KAAKzD,KAAL,CAAW,KAAKT,MAAL,CAAYiE,QAAZ,CAAqBtD,IAAhC,CAAb;AACA,UAAIuD,IAAJ,EAAU;AACR,aAAKC,eAAL,GAAuBD,KAAKvD,IAA5B;AACA,aAAKI,WAAL,GAAmBmD,KAAKnD,WAAxB;AACD,OAHD,MAGO;AACL,aAAKoD,eAAL,GAAuB,EAAvB;AACA,aAAKpD,WAAL,GAAmB,KAAnB;AACD;;AAED,WAAKoC,SAAL,GAAiB,KAAKjD,aAAL,CAAmBkE,YAAnB,EAAjB;AACA,WAAKC,KAAL,GAAa,KAAKnE,aAAL,CAAmBoE,QAAnB,EAAb;;AAEA,UAAI,KAAKnB,SAAT,EAAoB;AAClB,aAAKoB,YAAL,GAAoB,KAAKpE,cAAL,CAAoBqE,eAApB,EAApB;AACD,OAFD,MAEO;AACL,aAAKD,YAAL,GAAoB,IAApB;AACD;AACD,WAAKE,uBAAL;AACD;;;8CAEyB;AACxB,WAAK3E,UAAL,CAAgB4E,UAAhB,CAA2B,gBAA3B,EAA6C,EAAEC,aAAa,IAAf,EAA7C;AACD;;AAED;;;;;;qCAGiB;AACf,WAAK/E,SAAL,CAAegF,GAAf,CAAmB,SAAnB;AACD;;AAED;;;;;;iCAGa;AACX,WAAKpE,UAAL,GAAkB,CAAC,KAAKA,UAAxB;AACD;;AAED;;;;;;iCAGa;AACX,WAAKJ,cAAL,CAAoByE,UAApB;AACD;;;2BAEM;AAAA;;AACL,WAAK1E,cAAL,CAAoB2E,sBAApB,GAA6CxC,IAA7C,CAAkD,YAAM;AACtD,YAAIyC,cAAc,OAAK7E,aAAL,CAAmB8E,cAAnB,EAAlB;AACAC,eAAOC,QAAP,GAAkBH,cAAc,UAAhC;AACD,OAHD;AAID;;AAED;;;;;;;;qCAKiBI,O,EAASC,I,EAAM;AAC9B,UAAMC,gBAAgB;AACpBC,cAAMH,OADc;AAEpBC,cAAMA;AAFc,OAAtB;AAIA,WAAKtF,UAAL,CAAgB4E,UAAhB,CAA2B,kBAA3B,EAA+C,EAAEW,eAAeA,aAAjB,EAA/C;AACD;;;;;AAED;;;;;;8BAMUE,S,EAAWC,Q,EAAU;AAC7B,UAAIC,UAAU,eAAd;AACA,UAAIrC,SAAS,IAAb;AACA,UAAIC,cAAc,IAAlB;AACA,UAAIqC,gBAAgB,IAApB;AACA,UAAIC,OAAO,EAAX;;AAEA,WAAKtF,kBAAL,CAAwByD,SAAxB,CAAkC2B,OAAlC,EAA2CrC,MAA3C,EAAmDC,WAAnD,EACIqC,aADJ,EACmBF,QADnB,EAC6BD,SAD7B,EACwCI,IADxC;AAED;;;;;;AAGHlG,wBAAwBmG,OAAxB,GAAkC,CAChC,eADgC,EAEhC,SAFgC,EAGhC,WAHgC,EAIhC,WAJgC,EAKhC,YALgC,EAMhC,QANgC,EAOhC,QAPgC,EAQhC,UARgC,EAShC,eATgC,EAUhC,gBAVgC,EAWhC,gBAXgC,EAYhC,oBAZgC,EAahC,QAbgC,CAAlC;;kBAgBenG,uB","file":"authoringToolController.js","sourcesContent":["'use strict';\n\nclass AuthoringToolController {\n\n constructor(\n $anchorScroll,\n $filter,\n $location,\n $mdDialog,\n $rootScope,\n $scope,\n $state,\n $timeout,\n ConfigService,\n ProjectService,\n SessionService,\n TeacherDataService) {\n this.$anchorScroll = $anchorScroll;\n this.$filter = $filter;\n this.$location = $location;\n this.$mdDialog = $mdDialog;\n this.$rootScope = $rootScope;\n this.$scope = $scope;\n this.$state = $state;\n this.$timeout = $timeout;\n this.$translate = this.$filter('translate');\n this.ConfigService = ConfigService;\n this.ProjectService = ProjectService;\n this.SessionService = SessionService;\n this.TeacherDataService = TeacherDataService;\n\n this.numberProject = true; // TODO: make dynamic or remove\n this.isMenuOpen = false;\n\n // ui-views and their corresponding names, labels, and icons\n this.views = {\n 'root.project': {\n id: 'projectHomeButton',\n name: this.$translate('projectHome'),\n label: this.$translate('projectHome'),\n icon: 'home',\n type: 'primary',\n showToolbar: true,\n active: true\n },\n 'root.project.notebook': {\n id: 'notebookButton',\n name: this.$translate('notebookSettings'),\n label: this.$translate('notebookSettings'),\n icon: 'book',\n type: 'primary',\n showToolbar: true,\n active: true\n },\n 'root.project.asset': {\n id: 'assetButton',\n name: this.$translate('fileManager'),\n label: this.$translate('fileManager'),\n icon: 'attach_file',\n type: 'primary',\n showToolbar: true,\n active: true\n },\n 'root.project.info': {\n id: 'infoButton',\n name: this.$translate('PROJECT_INFO'),\n label: this.$translate('PROJECT_INFO'),\n icon: 'info',\n type: 'primary',\n showToolbar: true,\n active: true\n },\n 'root.main': {\n id: 'projectListButton',\n name: this.$translate('projectsList'),\n label: this.$translate('projectsList'),\n icon: 'reorder',\n type: 'primary',\n showToolbar: false,\n active: true\n },\n 'root.project.node': {\n name: '',\n label: '',\n icon: '',\n type: 'secondary',\n showToolbar: true,\n active: false\n },\n 'root.project.nodeConstraints': {\n name: '',\n label: '',\n icon: '',\n type: 'secondary',\n showToolbar: true,\n active: false\n },\n 'root.project.nodeEditPaths': {\n name: '',\n label: '',\n icon: '',\n type: 'secondary',\n showToolbar: true,\n active: false\n },\n };\n\n this.logoPath = this.ProjectService.getThemePath() + '/images/WISE-logo-ffffff.svg';\n this.processUI();\n\n // listen for state change events and close the menu\n this.$scope.$on('$stateChangeSuccess',\n (event, toState, toParams, fromState, fromParams) => {\n this.isMenuOpen = false;\n this.processUI();\n });\n\n $scope.$on('showSessionWarning', () => {\n let confirm = this.$mdDialog.confirm()\n .parent(angular.element(document.body))\n .title(this.$translate('sessionTimeout'))\n .content(this.$translate('autoLogoutMessage'))\n .ariaLabel(this.$translate('sessionTimeout'))\n .ok(this.$translate('yes'))\n .cancel(this.$translate('no'));\n this.$mdDialog.show(confirm).then(() => {\n this.SessionService.renewSession();\n }, () => {\n this.SessionService.forceLogOut();\n });\n });\n\n // alert user when they're inactive for a long time\n this.$scope.$on('showRequestLogout', (ev) => {\n let alert = this.$mdDialog.confirm()\n .parent(angular.element(document.body))\n .title(this.$translate('serverUpdate'))\n .textContent(this.$translate('serverUpdateRequestLogoutMessage'))\n .ariaLabel(this.$translate('serverUpdate'))\n .targetEvent(ev)\n .ok(this.$translate('ok'));\n\n this.$mdDialog.show(alert).then(() => {\n // do nothing\n }, () => {\n // do nothing\n });\n });\n\n /*\n * Listen for the savingProject event which means the authoring tool\n * is in the process of saving the project and display this information\n * globally.\n */\n this.$scope.$on('savingProject', () => {\n this.setGlobalMessage(this.$translate('saving'), null);\n });\n\n /*\n * Listen for the projectSaved event which means the project has just\n * been saved to the server\n */\n this.$scope.$on('projectSaved', () => {\n\n /*\n * Wait half a second before changing the message to 'Saved' so that\n * the 'Saving...' message stays up long enough for the author to\n * see that the project is saving. If we don't perform this wait,\n * it will always say 'Saved' and authors may wonder whether the\n * project ever gets saved.\n */\n this.$timeout(() => {\n this.setGlobalMessage(this.$translate('SAVED'), new Date().getTime());\n }, 500);\n });\n\n /*\n * Open the asset chooser to let the author insert an asset into the\n * specified target\n */\n this.$scope.$on('openAssetChooser', (event, params) => {\n // create the params for opening the asset chooser\n const stateParams = {\n isPopup: params.isPopup,\n projectId: params.projectId,\n nodeId: params.nodeId,\n componentId: params.componentId,\n target: params.target,\n targetObject: params.targetObject\n };\n\n // open the dialog that will display the assets for the user to choose\n this.$mdDialog.show({\n templateUrl: 'wise5/authoringTool/asset/asset.html',\n controller: 'ProjectAssetController',\n controllerAs: 'projectAssetController',\n $stateParams: stateParams,\n clickOutsideToClose: true,\n escapeToClose: true\n });\n });\n\n /*\n * Open the asset chooser to let the author insert an WISE Link into the\n * specified target\n */\n this.$scope.$on('openWISELinkChooser', (event, params) => {\n // create the params for opening the WISE Link authoring popup\n const stateParams = {\n projectId: params.projectId,\n nodeId: params.nodeId,\n componentId: params.componentId,\n target: params.target\n };\n\n // open the WISE Link authoring popup\n this.$mdDialog.show({\n templateUrl: 'wise5/authoringTool/wiseLink/wiseLinkAuthoring.html',\n controller: 'WISELinkAuthoringController',\n controllerAs: 'wiseLinkAuthoringController',\n $stateParams: stateParams,\n clickOutsideToClose: true,\n escapeToClose: true\n });\n });\n\n this.$rootScope.$on('$stateChangeSuccess',\n (event, toState, toParams, fromState, fromParams) => {\n if (toState != null && toState.name == 'root.main') {\n this.saveEvent('projectListViewed', 'Navigation');\n }\n });\n\n if (this.$state.current.name == 'root.main') {\n this.saveEvent('projectListViewed', 'Navigation');\n }\n }\n\n /**\n * Update UI items based on state, show or hide relevant menus and toolbars\n * TODO: remove/rework this and put items in their own ui states?\n */\n processUI() {\n // scroll to the top of the page\n this.$anchorScroll('top');\n\n // set current view and whether to show the toolbars and step tools\n this.showStepTools = this.$state.$current.name === 'root.project' ||\n this.$state.$current.name === 'root.project.node' ||\n this.$state.$current.name === 'root.project.nodeConstraints' ||\n this.$state.$current.name === 'root.project.nodeEditPaths';\n const view = this.views[this.$state.$current.name];\n if (view) {\n this.currentViewName = view.name;\n this.showToolbar = view.showToolbar;\n } else {\n this.currentViewName = '';\n this.showToolbar = false;\n }\n\n this.projectId = this.ConfigService.getProjectId();\n this.runId = this.ConfigService.getRunId();\n\n if (this.projectId) {\n this.projectTitle = this.ProjectService.getProjectTitle();\n } else {\n this.projectTitle = null;\n }\n this.turnOffJSONValidMessage();\n }\n\n turnOffJSONValidMessage() {\n this.$rootScope.$broadcast('setIsJSONValid', { isJSONValid: null });\n }\n\n /**\n * Navigate the user to the My Projects page in the Authoring Tool\n */\n goToMyProjects() {\n this.$location.url('/author');\n }\n\n /**\n * Toggle the authoring tool main menu\n */\n toggleMenu() {\n this.isMenuOpen = !this.isMenuOpen;\n }\n\n /**\n * Notify Session to renew when user moves the mouse\n */\n mouseMoved() {\n this.SessionService.mouseMoved();\n }\n\n exit() {\n this.ProjectService.notifyAuthorProjectEnd().then(() => {\n let wiseBaseURL = this.ConfigService.getWISEBaseURL();\n window.location = wiseBaseURL + '/teacher';\n });\n }\n\n /**\n * Set the global message at the top right\n * @param message the message to display\n * @param time the time to display\n */\n setGlobalMessage(message, time) {\n const globalMessage = {\n text: message,\n time: time\n };\n this.$rootScope.$broadcast('setGlobalMessage', { globalMessage: globalMessage });\n };\n\n /**\n * Save an Authoring Tool event\n * @param eventName the name of the event\n * @param category the category of the event\n * example 'Navigation' or 'Authoring'\n */\n saveEvent(eventName, category) {\n let context = 'AuthoringTool';\n let nodeId = null;\n let componentId = null;\n let componentType = null;\n let data = {};\n\n this.TeacherDataService.saveEvent(context, nodeId, componentId,\n componentType, category, eventName, data);\n }\n}\n\nAuthoringToolController.$inject = [\n '$anchorScroll',\n '$filter',\n '$location',\n '$mdDialog',\n '$rootScope',\n '$scope',\n '$state',\n '$timeout',\n 'ConfigService',\n 'ProjectService',\n 'SessionService',\n 'TeacherDataService',\n 'moment'\n];\n\nexport default AuthoringToolController;\n"]} \ No newline at end of file diff --git a/src/main/webapp/wise5/authoringTool/components/shared/toolbar/toolbar.es6 b/src/main/webapp/wise5/authoringTool/components/shared/toolbar/toolbar.es6 index 245f5b0d6c..39d3dd2b4a 100644 --- a/src/main/webapp/wise5/authoringTool/components/shared/toolbar/toolbar.es6 +++ b/src/main/webapp/wise5/authoringTool/components/shared/toolbar/toolbar.es6 @@ -11,6 +11,9 @@ class ToolbarController { } this.globalMessage = params.globalMessage; }); + this.$rootScope.$on('setIsJSONValid', (event, params) => { + this.isJSONValid = params.isJSONValid; + }); } toggleMenu() { @@ -39,6 +42,8 @@ const Toolbar = { {{ $ctrl.viewName }}
+ {{ 'jsonValid' | translate }} + {{ 'jsonInvalid' | translate }}
\n
\n \n menu \n \n {{ $ctrl.viewName }}\n \n
\n
\n \n \n
\n \n {{$ctrl.globalMessage.text}}\n \n \n {{ $ctrl.globalMessage.time | amDateFormat:\'ddd, MMM D YYYY, h:mm a\' }}\n \n \n \n \n
\n ' + template: '\n
\n \n menu \n \n {{ $ctrl.viewName }}\n \n
\n {{ \'jsonValid\' | translate }}\n {{ \'jsonInvalid\' | translate }}\n
\n \n \n
\n \n {{$ctrl.globalMessage.text}}\n \n \n {{ $ctrl.globalMessage.time | amDateFormat:\'ddd, MMM D YYYY, h:mm a\' }}\n \n \n \n \n
\n
' }; exports.default = Toolbar; diff --git a/src/main/webapp/wise5/authoringTool/components/shared/toolbar/toolbar.js.map b/src/main/webapp/wise5/authoringTool/components/shared/toolbar/toolbar.js.map index 6d243a773e..ea58b7861e 100644 --- a/src/main/webapp/wise5/authoringTool/components/shared/toolbar/toolbar.js.map +++ b/src/main/webapp/wise5/authoringTool/components/shared/toolbar/toolbar.js.map @@ -1 +1 @@ -{"version":3,"sources":["toolbar.es6"],"names":["ToolbarController","$rootScope","$on","event","params","globalMessage","time","isProgressIndicatorVisible","onMenuToggle","$inject","Toolbar","bindings","numberProject","showStepTools","viewName","controller","template"],"mappings":"AAAA;;;;;;;;;;IAEMA,iB;AACJ,6BAAYC,UAAZ,EAAwB;AAAA;;AAAA;;AACtB,SAAKA,UAAL,GAAkBA,UAAlB;AACA,SAAKA,UAAL,CAAgBC,GAAhB,CAAoB,kBAApB,EAAwC,UAACC,KAAD,EAAQC,MAAR,EAAmB;AACzD,UAAIA,OAAOC,aAAP,CAAqBC,IAArB,KAA8B,IAAlC,EAAwC;AACtC,cAAKC,0BAAL,GAAkC,IAAlC;AACD,OAFD,MAEO;AACL,cAAKA,0BAAL,GAAkC,KAAlC;AACD;AACD,YAAKF,aAAL,GAAqBD,OAAOC,aAA5B;AACD,KAPD;AAQD;;;;iCAEY;AACX,WAAKG,YAAL;AACD;;;;;;AAGHR,kBAAkBS,OAAlB,GAA4B,CAC1B,YAD0B,CAA5B;;AAIA,IAAMC,UAAU;AACdC,YAAU;AACRC,mBAAe,GADP;AAERC,mBAAe,GAFP;AAGRC,cAAU,GAHF;AAIRN,kBAAc;AAJN,GADI;AAOdO,cAAYf,iBAPE;AAQdgB;AARc,CAAhB;;kBAwCeN,O","file":"toolbar.js","sourcesContent":["\"use strict\";\n\nclass ToolbarController {\n constructor($rootScope) {\n this.$rootScope = $rootScope;\n this.$rootScope.$on('setGlobalMessage', (event, params) => {\n if (params.globalMessage.time === null) {\n this.isProgressIndicatorVisible = true;\n } else {\n this.isProgressIndicatorVisible = false;\n }\n this.globalMessage = params.globalMessage;\n });\n }\n\n toggleMenu() {\n this.onMenuToggle();\n }\n}\n\nToolbarController.$inject = [\n '$rootScope'\n];\n\nconst Toolbar = {\n bindings: {\n numberProject: '<',\n showStepTools: '<',\n viewName: '<',\n onMenuToggle: '&'\n },\n controller: ToolbarController,\n template:\n `\n
\n \n menu \n \n {{ $ctrl.viewName }}\n \n
\n
\n \n \n
\n \n {{$ctrl.globalMessage.text}}\n \n \n {{ $ctrl.globalMessage.time | amDateFormat:'ddd, MMM D YYYY, h:mm a' }}\n \n \n \n \n
\n
`\n};\n\nexport default Toolbar;\n"]} \ No newline at end of file +{"version":3,"sources":["toolbar.es6"],"names":["ToolbarController","$rootScope","$on","event","params","globalMessage","time","isProgressIndicatorVisible","isJSONValid","onMenuToggle","$inject","Toolbar","bindings","numberProject","showStepTools","viewName","controller","template"],"mappings":"AAAA;;;;;;;;;;IAEMA,iB;AACJ,6BAAYC,UAAZ,EAAwB;AAAA;;AAAA;;AACtB,SAAKA,UAAL,GAAkBA,UAAlB;AACA,SAAKA,UAAL,CAAgBC,GAAhB,CAAoB,kBAApB,EAAwC,UAACC,KAAD,EAAQC,MAAR,EAAmB;AACzD,UAAIA,OAAOC,aAAP,CAAqBC,IAArB,KAA8B,IAAlC,EAAwC;AACtC,cAAKC,0BAAL,GAAkC,IAAlC;AACD,OAFD,MAEO;AACL,cAAKA,0BAAL,GAAkC,KAAlC;AACD;AACD,YAAKF,aAAL,GAAqBD,OAAOC,aAA5B;AACD,KAPD;AAQA,SAAKJ,UAAL,CAAgBC,GAAhB,CAAoB,gBAApB,EAAsC,UAACC,KAAD,EAAQC,MAAR,EAAmB;AACvD,YAAKI,WAAL,GAAmBJ,OAAOI,WAA1B;AACD,KAFD;AAGD;;;;iCAEY;AACX,WAAKC,YAAL;AACD;;;;;;AAGHT,kBAAkBU,OAAlB,GAA4B,CAC1B,YAD0B,CAA5B;;AAIA,IAAMC,UAAU;AACdC,YAAU;AACRC,mBAAe,GADP;AAERC,mBAAe,GAFP;AAGRC,cAAU,GAHF;AAIRN,kBAAc;AAJN,GADI;AAOdO,cAAYhB,iBAPE;AAQdiB;AARc,CAAhB;;kBA0CeN,O","file":"toolbar.js","sourcesContent":["\"use strict\";\n\nclass ToolbarController {\n constructor($rootScope) {\n this.$rootScope = $rootScope;\n this.$rootScope.$on('setGlobalMessage', (event, params) => {\n if (params.globalMessage.time === null) {\n this.isProgressIndicatorVisible = true;\n } else {\n this.isProgressIndicatorVisible = false;\n }\n this.globalMessage = params.globalMessage;\n });\n this.$rootScope.$on('setIsJSONValid', (event, params) => {\n this.isJSONValid = params.isJSONValid;\n });\n }\n\n toggleMenu() {\n this.onMenuToggle();\n }\n}\n\nToolbarController.$inject = [\n '$rootScope'\n];\n\nconst Toolbar = {\n bindings: {\n numberProject: '<',\n showStepTools: '<',\n viewName: '<',\n onMenuToggle: '&'\n },\n controller: ToolbarController,\n template:\n `\n
\n \n menu \n \n {{ $ctrl.viewName }}\n \n
\n {{ 'jsonValid' | translate }}\n {{ 'jsonInvalid' | translate }}\n
\n \n \n
\n \n {{$ctrl.globalMessage.text}}\n \n \n {{ $ctrl.globalMessage.time | amDateFormat:'ddd, MMM D YYYY, h:mm a' }}\n \n \n \n \n
\n
`\n};\n\nexport default Toolbar;\n"]} \ No newline at end of file diff --git a/src/main/webapp/wise5/authoringTool/i18n/i18n_en.json b/src/main/webapp/wise5/authoringTool/i18n/i18n_en.json index 0b46b22844..6de25c8e86 100644 --- a/src/main/webapp/wise5/authoringTool/i18n/i18n_en.json +++ b/src/main/webapp/wise5/authoringTool/i18n/i18n_en.json @@ -160,6 +160,8 @@ "isVisitable": "Is Visitable", "isVisited": "Is Visited", "json": "JSON", + "jsonInvalid": "JSON Invalid", + "jsonValid": "JSON Valid", "labelLink": "Label (Link)", "labelPlural": "Label (Plural)", "labelSingular": "Label (Singular)", @@ -224,6 +226,7 @@ "projectCreatedOn": "Project created on ", "projectHome": "Project Home", "projectJSON": "Project JSON", + "projectJSONInvalidErrorMessage": "The project JSON is invalid. Invalid JSON will not be saved.\nClick \"OK\" to revert back to the last valid JSON.\nClick \"Cancel\" to keep the invalid JSON open so you can fix it.", "projectsList": "Projects List", "projectStyles": "Project Styles", "projectStructure": "Project Structure", @@ -240,7 +243,6 @@ "requireTextOnEveryNote": "Require students to write text on every note", "requiredNumberOfWords": "Required Number of Words", "requiredSubmitCount": "Required Submit Count", - "saveErrorAdvancedAuthoring": "Error saving advanced authoring, possibly due to malformed JSON content. Check that your JSON is valid. Your changes have not been saved.", "saving": "Saving...", "scoresParens": "Score(s)", "scriptFilename": "Script Filename", diff --git a/src/main/webapp/wise5/authoringTool/project/project.html b/src/main/webapp/wise5/authoringTool/project/project.html index 454b050555..e83830a03e 100644 --- a/src/main/webapp/wise5/authoringTool/project/project.html +++ b/src/main/webapp/wise5/authoringTool/project/project.html @@ -394,8 +394,8 @@
+ ng-change='projectController.autoSaveProjectJSONString()' + ng-model-options='{ debounce: 1000 }'>
diff --git a/src/main/webapp/wise5/authoringTool/project/projectController.es6 b/src/main/webapp/wise5/authoringTool/project/projectController.es6 index 4c90aa2461..1d1fadfe77 100644 --- a/src/main/webapp/wise5/authoringTool/project/projectController.es6 +++ b/src/main/webapp/wise5/authoringTool/project/projectController.es6 @@ -1135,17 +1135,86 @@ class ProjectController { * The show JSON button was clicked */ showJSONClicked() { - this.showJSONAuthoring = !this.showJSONAuthoring; if (this.showJSONAuthoring) { + // we were showing the JSON view and the author now wants to hide it + if (this.isJSONValid()) { + this.toggleJSONAuthoringView(); + this.hideValidJSONMessage(); + } else { + let answer = confirm(this.$translate('projectJSONInvalidErrorMessage')); + if (answer) { + // the author wants to revert back to the last valid JSON + this.toggleJSONAuthoringView(); + this.hideValidJSONMessage(); + } + } + } else { + // we were not showing the JSON view and now the author wants to show it + this.toggleJSONAuthoringView(); this.projectJSONString = angular.toJson(this.ProjectService.project, 4); + this.showValidJSONMessage(); + } + } + + isJSONValid() { + try { + angular.fromJson(this.projectJSONString); + return true; + } catch(e) { + return false; + } + } + + toggleJSONAuthoringView() { + this.showJSONAuthoring = !this.showJSONAuthoring; + } + + showValidJSONMessage() { + this.setIsJSONValidMessage(true); + } + + showInvalidJSONMessage() { + this.setIsJSONValidMessage(false); + } + + hideValidJSONMessage() { + this.setIsJSONValidMessage(null); + } + + /** + * Show the message in the toolbar that says "JSON Valid" or "JSON Invalid". + * @param isJSONValid + * true if we want to show "JSON Valid" + * false if we want to show "JSON Invalid" + * null if we don't want to show anything + */ + setIsJSONValidMessage(isJSONValid) { + this.$rootScope.$broadcast('setIsJSONValid', { isJSONValid: isJSONValid }); + } + + /** + * Save the project JSON to the server. + * @return {boolean} + * True if the JSON is valid. + * False if the JSON is invalid. + */ + autoSaveProjectJSONString() { + try { + this.saveProjectJSON(this.projectJSONString); + this.showValidJSONMessage(); + return true; + } catch(e) { + this.showInvalidJSONMessage(); + return false; } } /** * Save the project JSON string to the server + * @param projectJSONString */ - saveProjectJSONString() { - let project = angular.fromJson(this.projectJSONString); + saveProjectJSON(projectJSONString) { + let project = angular.fromJson(projectJSONString); this.ProjectService.setProject(project); let scriptFilename = this.ProjectService.getProjectScriptFilename(); if (scriptFilename != null) { @@ -1300,6 +1369,9 @@ class ProjectController { // if the advanced view is shown, do not show the project view this.projectMode = !this.advancedMode; } + if (!this.showJSONAuthoring) { + this.hideValidJSONMessage(); + } } /** diff --git a/src/main/webapp/wise5/authoringTool/project/projectController.js b/src/main/webapp/wise5/authoringTool/project/projectController.js index 1646dc01cd..7365c92a1d 100644 --- a/src/main/webapp/wise5/authoringTool/project/projectController.js +++ b/src/main/webapp/wise5/authoringTool/project/projectController.js @@ -1394,20 +1394,100 @@ var ProjectController = function () { }, { key: 'showJSONClicked', value: function showJSONClicked() { - this.showJSONAuthoring = !this.showJSONAuthoring; if (this.showJSONAuthoring) { + // we were showing the JSON view and the author now wants to hide it + if (this.isJSONValid()) { + this.toggleJSONAuthoringView(); + this.hideValidJSONMessage(); + } else { + var answer = confirm(this.$translate('projectJSONInvalidErrorMessage')); + if (answer) { + // the author wants to revert back to the last valid JSON + this.toggleJSONAuthoringView(); + this.hideValidJSONMessage(); + } + } + } else { + // we were not showing the JSON view and now the author wants to show it + this.toggleJSONAuthoringView(); this.projectJSONString = angular.toJson(this.ProjectService.project, 4); + this.showValidJSONMessage(); + } + } + }, { + key: 'isJSONValid', + value: function isJSONValid() { + try { + angular.fromJson(this.projectJSONString); + return true; + } catch (e) { + return false; + } + } + }, { + key: 'toggleJSONAuthoringView', + value: function toggleJSONAuthoringView() { + this.showJSONAuthoring = !this.showJSONAuthoring; + } + }, { + key: 'showValidJSONMessage', + value: function showValidJSONMessage() { + this.setIsJSONValidMessage(true); + } + }, { + key: 'showInvalidJSONMessage', + value: function showInvalidJSONMessage() { + this.setIsJSONValidMessage(false); + } + }, { + key: 'hideValidJSONMessage', + value: function hideValidJSONMessage() { + this.setIsJSONValidMessage(null); + } + + /** + * Show the message in the toolbar that says "JSON Valid" or "JSON Invalid". + * @param isJSONValid + * true if we want to show "JSON Valid" + * false if we want to show "JSON Invalid" + * null if we don't want to show anything + */ + + }, { + key: 'setIsJSONValidMessage', + value: function setIsJSONValidMessage(isJSONValid) { + this.$rootScope.$broadcast('setIsJSONValid', { isJSONValid: isJSONValid }); + } + + /** + * Save the project JSON to the server. + * @return {boolean} + * True if the JSON is valid. + * False if the JSON is invalid. + */ + + }, { + key: 'autoSaveProjectJSONString', + value: function autoSaveProjectJSONString() { + try { + this.saveProjectJSON(this.projectJSONString); + this.showValidJSONMessage(); + return true; + } catch (e) { + this.showInvalidJSONMessage(); + return false; } } /** * Save the project JSON string to the server + * @param projectJSONString */ }, { - key: 'saveProjectJSONString', - value: function saveProjectJSONString() { - var project = angular.fromJson(this.projectJSONString); + key: 'saveProjectJSON', + value: function saveProjectJSON(projectJSONString) { + var project = angular.fromJson(projectJSONString); this.ProjectService.setProject(project); var scriptFilename = this.ProjectService.getProjectScriptFilename(); if (scriptFilename != null) { @@ -1577,6 +1657,9 @@ var ProjectController = function () { // if the advanced view is shown, do not show the project view this.projectMode = !this.advancedMode; } + if (!this.showJSONAuthoring) { + this.hideValidJSONMessage(); + } } /** diff --git a/src/main/webapp/wise5/authoringTool/project/projectController.js.map b/src/main/webapp/wise5/authoringTool/project/projectController.js.map index 34d720c397..52fe90a46e 100644 --- a/src/main/webapp/wise5/authoringTool/project/projectController.js.map +++ b/src/main/webapp/wise5/authoringTool/project/projectController.js.map @@ -1 +1 @@ -{"version":3,"sources":["projectController.es6"],"names":["ProjectController","$anchorScroll","$filter","$interval","$mdDialog","$q","$rootScope","$scope","$state","$stateParams","$timeout","AuthorWebSocketService","ConfigService","ProjectAssetService","ProjectService","TeacherDataService","UtilService","$translate","projectId","runId","getRunId","items","idToOrder","nodeIds","getFlattenedProjectAsNodeIds","showCreateGroup","showCreateNode","projectTitle","getProjectTitle","inactiveGroupNodes","getInactiveGroupNodes","inactiveStepNodes","getInactiveStepNodes","inactiveNodes","getInactiveNodes","idToNode","getIdToNode","projectScriptFilename","getProjectScriptFilename","currentAuthorsMessage","projectMode","showImportView","importMode","editProjectRubricMode","advancedMode","showJSONAuthoring","stepNodeSelected","activityNodeSelected","stepBackgroundColors","setCurrentNode","metadata","getProjectMetadata","notifyAuthorProjectBegin","summernoteRubricId","summernoteRubricHTML","replaceAssetPaths","getProjectRubric","insertAssetToolTipText","insertAssetButton","createInsertAssetButton","summernoteRubricOptions","toolbar","height","disableDragAndDrop","buttons","projectURL","window","location","origin","getConfigParam","$on","event","args","currentAuthorsUsernames","myUserName","getMyUserName","splice","indexOf","length","currentAuthors","join","notifyAuthorProjectEnd","assetItem","fileName","assetFileName","target","summernoteElement","$","fullAssetPath","getProjectAssetsDirectoryPath","isImage","summernote","isVideo","videoElement","document","createElement","controls","innerHTML","projectScriptFilenameChanged","hide","toState","toParams","fromState","fromParams","stateName","name","saveEvent","refreshProject","scrollToBottomOfPage","previewProjectEventData","constraints","open","go","commitMessage","saveProject","then","commitHistoryArray","commitHistory","val","error","alert","href","getWISEBaseURL","nodeId","getNodePositionById","getComponentsByNodeId","componentId","getPossibleTransitionCriteria","getNodeTitleByNodeId","isGroupNode","unselectAllItems","endCurrentNodeAndSetCurrentNodeByNodeId","nodeToAdd","createGroup","createGroupTitle","insertGroupMode","createMode","createNode","createNodeTitle","insertNodeMode","handleCreateModeInsert","moveMode","handleMoveModeInsert","copyMode","handleCopyModeInsert","importSelectedNodes","moveTo","createNodeInside","createNodeAfter","newNodes","newNode","temporarilyHighlightNewNodes","checkPotentialStartNodeIdChangeThenSaveProject","nodeCreatedEventData","id","getNodePositionAndTitleByNodeId","selectedNodeIds","getSelectedNodeIds","movedNodes","selectedNodeId","node","push","moveNodesInside","moveNodesAfter","firstNewNode","n","toTitle","nodeMovedEventData","activitiesMoved","stepsMoved","copiedNodes","copyNodesInside","copyNodesAfter","toNodeId","nodeCopiedEventData","activitiesCopied","stepsCopied","nodeIdToInsertInsideOrAfter","selectedNodes","getSelectedNodesToImport","selectedNodeTitles","getSelectedNodeTitlesToImport","toProjectId","fromProjectId","importProjectId","performImport","doScrollToNewNodes","stepsImported","selectedNode","selectedNodeTitle","stepImported","parseInt","fromNodeId","fromTitle","stepsImportedEventData","copyNodes","toggleView","importProjectIdToOrder","importProjectItems","importMyProjectId","importLibraryProjectId","importProject","showProjectHome","retrieveProjectAssets","selectedItemTypes","getSelectedItemTypes","confirmMessage","numItems","confirm","deletedStartNodeId","activityDeleted","stepDeleted","stepsDeleted","activitiesDeleted","getNodeById","tempNode","title","isStartNodeId","stepsInActivityDeleted","ids","stepNodeId","stepTitle","stepObject","deleteNode","updateStartNodeId","activitiesDeletedEventData","stepDeletedEventData","angular","forEach","value","key","checked","inactiveNode","nodeType","type","inactiveNodeType","focus","newStartNodeId","startGroupId","getStartGroupId","done","startId","isApplicationNode","setStartNodeId","resolve","reject","firstLeafNodeId","getFirstLeafNodeId","currentStartNodeId","getStartNodeId","checkPotentialStartNodeIdChange","parseProject","setProjectTitle","myProjectsList","getAuthorableProjects","libraryProjectsList","getLibraryProjects","showImportProject","retrieveProjectById","projectJSON","nodeOrderOfProject","getNodeOrderOfProject","nodes","previewProjectURL","previewStepURL","item","projectJSONString","toJson","project","fromJson","setProject","scriptFilename","html","removeAbsoluteAssetPaths","insertWISELinks","setProjectRubric","isNodeInAnyBranchPath","setProjectScriptFilename","openAssetChooserParams","popup","$broadcast","view","scrollToTopOfPage","animate","scrollTop","prop","temporarilyHighlightElement","firstNodeElementAdded","eventName","category","data","context","componentType","stepNumber","color","branchPathLetter","getBranchPathLetter","letterASCIICode","charCodeAt","branchPathNumber","textArea","body","appendChild","select","execCommand","removeChild","count","getParentGroup","isBranchPoint","getNumberOfBranchPaths","getBranchCriteriaDescription","nodeHasConstraint","getConstraintsOnNode","constraintDescriptions","c","constraint","description","getConstraintDescription","nodeHasRubric","$inject"],"mappings":"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","file":"projectController.js","sourcesContent":["'use strict';\n\nclass ProjectController {\n\n constructor(\n $anchorScroll,\n $filter,\n $interval,\n $mdDialog,\n $q,\n $rootScope,\n $scope,\n $state,\n $stateParams,\n $timeout,\n AuthorWebSocketService,\n ConfigService,\n ProjectAssetService,\n ProjectService,\n TeacherDataService,\n UtilService) {\n this.$anchorScroll = $anchorScroll;\n this.$filter = $filter;\n this.$interval = $interval;\n this.$mdDialog = $mdDialog;\n this.$q = $q;\n this.$rootScope = $rootScope;\n this.$scope = $scope;\n this.$state = $state;\n this.$stateParams = $stateParams;\n this.$timeout = $timeout;\n this.$translate = this.$filter('translate');\n this.AuthorWebSocketService = AuthorWebSocketService;\n this.ConfigService = ConfigService;\n this.ProjectAssetService = ProjectAssetService;\n this.ProjectService = ProjectService;\n this.TeacherDataService = TeacherDataService;\n this.UtilService = UtilService;\n\n this.projectId = this.$stateParams.projectId;\n this.runId = this.ConfigService.getRunId();\n this.items = this.ProjectService.idToOrder;\n this.nodeIds = this.ProjectService.getFlattenedProjectAsNodeIds();\n this.showCreateGroup = false;\n this.showCreateNode = false;\n this.projectTitle = this.ProjectService.getProjectTitle();\n this.inactiveGroupNodes = this.ProjectService.getInactiveGroupNodes();\n this.inactiveStepNodes = this.ProjectService.getInactiveStepNodes();\n this.inactiveNodes = this.ProjectService.getInactiveNodes();\n this.idToNode = this.ProjectService.getIdToNode();\n this.projectScriptFilename = this.ProjectService.getProjectScriptFilename();\n this.currentAuthorsMessage = '';\n this.projectMode = true;\n this.showCreateGroup = false;\n this.showCreateNode = false;\n this.showImportView = false;\n this.importMode = false;\n this.editProjectRubricMode = false;\n this.advancedMode = false;\n this.showJSONAuthoring = false;\n\n // whether there are any step nodes checked\n this.stepNodeSelected = false;\n\n // whether there are any activity nodes checked\n this.activityNodeSelected = false;\n\n /*\n * The colors for the branch path steps. The colors are from\n * http://colorbrewer2.org/\n * http://colorbrewer2.org/export/colorbrewer.js\n * The colors chosen are from the 'qualitative', 'Set2'.\n */\n this.stepBackgroundColors = ['#66c2a5','#fc8d62','#8da0cb','#e78ac3',\n '#a6d854','#ffd92f','#e5c494','#b3b3b3'];\n\n // start by opening the project, with no node being authored\n this.TeacherDataService.setCurrentNode(null);\n\n this.metadata = this.ProjectService.getProjectMetadata();\n this.ProjectService.notifyAuthorProjectBegin(this.projectId);\n this.summernoteRubricId = 'summernoteRubric_' + this.projectId;\n this.summernoteRubricHTML = this.ProjectService\n .replaceAssetPaths(this.ProjectService.getProjectRubric());\n\n let insertAssetToolTipText = this.$translate('INSERT_ASSET');\n let insertAssetButton = this.UtilService.createInsertAssetButton(this,\n this.projectId, null, null, 'rubric', insertAssetToolTipText);\n\n // options to display in the summernote tool\n this.summernoteRubricOptions = {\n toolbar: [\n ['style', ['style']],\n ['font', ['bold', 'underline', 'clear']],\n ['fontname', ['fontname']],\n ['fontsize', ['fontsize']],\n ['color', ['color']],\n ['para', ['ul', 'ol', 'paragraph']],\n ['table', ['table']],\n ['insert', ['link', 'video']],\n ['view', ['fullscreen', 'codeview', 'help']],\n ['customButton', ['insertAssetButton']]\n ],\n height: 300,\n disableDragAndDrop: true,\n buttons: {\n 'insertAssetButton': insertAssetButton\n }\n };\n\n this.projectURL = window.location.origin + this.ConfigService.getConfigParam('projectURL');\n\n this.$scope.$on('currentAuthorsReceived', (event, args) => {\n let currentAuthorsUsernames = args.currentAuthorsUsernames;\n let myUserName = this.ConfigService.getMyUserName();\n currentAuthorsUsernames\n .splice(currentAuthorsUsernames.indexOf(myUserName), 1);\n if (currentAuthorsUsernames.length > 0) {\n this.currentAuthorsMessage = this.$translate('concurrentAuthorsWarning',\n { currentAuthors: currentAuthorsUsernames.join(', ') });\n } else {\n this.currentAuthorsMessage = '';\n }\n });\n\n this.$scope.$on('$destroy', () => {\n this.ProjectService.notifyAuthorProjectEnd(this.projectId);\n });\n\n /*\n * Listen for the assetSelected event which occurs when the author\n * selects an asset from the choose asset popup to add to project rubric\n * or choosing the script file.\n */\n this.$scope.$on('assetSelected', (event, args) => {\n if (args != null && args.projectId == this.projectId &&\n args.assetItem != null && args.assetItem.fileName != null) {\n let assetFileName = args.assetItem.fileName;\n if (args.target === 'rubric') {\n let summernoteElement = $('#summernoteRubric_' + this.projectId);\n let fullAssetPath =\n this.ConfigService.getProjectAssetsDirectoryPath() +\n '/' + assetFileName;\n if (this.UtilService.isImage(assetFileName)) {\n /*\n * move the cursor back to its position when the asset chooser\n * popup was clicked\n */\n summernoteElement.summernote('editor.restoreRange');\n summernoteElement.summernote('editor.focus');\n summernoteElement.summernote(\n 'insertImage', fullAssetPath, assetFileName);\n } else if (this.UtilService.isVideo(assetFileName)) {\n /*\n * move the cursor back to its position when the asset chooser\n * popup was clicked\n */\n summernoteElement.summernote('editor.restoreRange');\n summernoteElement.summernote('editor.focus');\n let videoElement = document.createElement('video');\n videoElement.controls = 'true';\n videoElement.innerHTML =\n '';\n summernoteElement.summernote('insertNode', videoElement);\n }\n } else if (args.target === 'scriptFilename') {\n this.projectScriptFilename = assetFileName;\n this.projectScriptFilenameChanged();\n }\n }\n this.$mdDialog.hide();\n });\n\n this.$rootScope.$on('$stateChangeSuccess',\n (event, toState, toParams, fromState, fromParams) => {\n if (toState != null) {\n let stateName = toState.name;\n if (stateName == 'root.project') {\n this.saveEvent('projectHomeViewOpened', 'Navigation');\n } else if (stateName == 'root.project.node') {\n } else if (stateName == 'root.project.asset') {\n this.saveEvent('assetsViewOpened', 'Navigation');\n } else if (stateName == 'root.project.info') {\n this.saveEvent('projectInfoViewOpened', 'Navigation');\n } else if (stateName == 'root.project.notebook') {\n this.saveEvent('notebookViewOpened', 'Navigation');\n }\n }\n });\n\n this.$rootScope.$on('projectSaved', () => {\n //this.saveEvent('projectSaved', 'Authoring');\n });\n\n /*\n * Listen for the event to parse the project. This is so other\n * controllers can trigger parsing the project in this controller.\n */\n this.$rootScope.$on('parseProject', () => {\n this.refreshProject();\n });\n\n this.$rootScope.$on('scrollToBottom', () => {\n this.scrollToBottomOfPage();\n });\n\n this.saveEvent('projectOpened', 'Navigation');\n };\n\n /**\n * Launch the project in preview mode in a new tab\n */\n previewProject() {\n let previewProjectEventData = { constraints: true };\n this.saveEvent('projectPreviewed', 'Navigation', previewProjectEventData);\n window.open(this.ConfigService.getConfigParam('previewProjectURL'));\n };\n\n /**\n * Launch the project in preview mode without constraints in a new tab\n */\n previewProjectWithoutConstraints() {\n let previewProjectEventData = { constraints: false };\n this.saveEvent('projectPreviewed', 'Navigation', previewProjectEventData);\n window.open(this.ConfigService.getConfigParam('previewProjectURL') +\n '?constraints=false');\n };\n\n viewProjectAssets() {\n this.$state.go('root.project.asset', {projectId: this.projectId});\n };\n\n viewProjectHistory() {\n this.$state.go('root.project.history', {projectId: this.projectId});\n };\n\n viewNotebookSettings() {\n this.$state.go('root.project.notebook', {projectId: this.projectId});\n }\n\n saveProject() {\n let commitMessage = 'Made changes to the project.';\n try {\n // if projectJSONString is bad json,\n // an exception will be thrown and it will not save.\n this.ProjectService.saveProject(commitMessage)\n .then((commitHistoryArray) => {\n this.commitHistory = commitHistoryArray;\n $('#commitMessageInput').val('');\n });\n } catch (error) {\n // TODO: i18n\n alert('Invalid JSON. Please check syntax. Aborting save.');\n return;\n }\n };\n\n /**\n * Make a request to download this project as a zip file\n */\n downloadProject() {\n window.location.href = this.ConfigService.getWISEBaseURL()\n + '/project/export/' + this.projectId;\n }\n\n /**\n * Close authoring for the current project and bring user back to main AT page\n */\n closeProject() {\n this.$state.go('root.main');\n };\n\n /**\n * Get the node position\n * @param nodeId the node id\n * @returns the node position\n */\n getNodePositionById(nodeId) {\n return this.ProjectService.getNodePositionById(nodeId);\n };\n\n /**\n * Get the components that are in the specified node id.\n * @param nodeId the node id\n * @returns components in the node\n */\n getComponentsByNodeId(nodeId) {\n return this.ProjectService.getComponentsByNodeId(nodeId);\n }\n\n /**\n * Returns a list of possible criteria for the specified node and component\n * @param nodeId the node id\n * @param componentId the component id in the node\n */\n getPossibleTransitionCriteria(nodeId, componentId) {\n return this.ProjectService\n .getPossibleTransitionCriteria(nodeId, componentId);\n }\n\n /**\n * Get the node title for a node\n * @param nodeId the node id\n * @returns the node title\n */\n getNodeTitleByNodeId(nodeId) {\n return this.ProjectService.getNodeTitleByNodeId(nodeId);\n };\n\n /**\n * Check if a node id is for a group\n * @param nodeId\n * @returns whether the node is a group node\n */\n isGroupNode(nodeId) {\n return this.ProjectService.isGroupNode(nodeId);\n };\n\n /**\n * A node was clicked so we will go to the node authoring view\n * @param nodeId\n */\n nodeClicked(nodeId) {\n this.unselectAllItems();\n this.TeacherDataService\n .endCurrentNodeAndSetCurrentNodeByNodeId(this.nodeId);\n this.$state\n .go('root.project.node', {projectId: this.projectId, nodeId: nodeId});\n };\n\n /**\n * The constraint icon on a step in the project view was clicked.\n * We will open the constraint view for the step.\n * @param nodeId The node id of the step.\n */\n constraintIconClicked(nodeId) {\n this.TeacherDataService\n .endCurrentNodeAndSetCurrentNodeByNodeId(nodeId);\n this.$state\n .go('root.project.nodeConstraints', {projectId: this.projectId, nodeId: nodeId});\n }\n\n /**\n * The branch icon on a step in the project view was clicked.\n * We will open the transitions view for the step.\n * @param nodeId The node id of the step.\n */\n branchIconClicked(nodeId) {\n this.TeacherDataService\n .endCurrentNodeAndSetCurrentNodeByNodeId(nodeId);\n this.$state\n .go('root.project.nodeEditPaths', {projectId: this.projectId, nodeId: nodeId});\n }\n\n /**\n * Create a new group (activity)\n */\n createGroup() {\n /*\n * set the group into this variable to hold it temporarily while the\n * author decides where to place it\n */\n this.nodeToAdd = this.ProjectService.createGroup(this.createGroupTitle);\n\n this.showCreateGroup = false;\n this.createGroupTitle = '';\n this.insertGroupMode = true;\n this.createMode = true;\n }\n\n /**\n * Create a new node (step)\n */\n createNode() {\n /*\n * set the node into this variable to hold it temporarily while the\n * author decides where to place it\n */\n this.nodeToAdd = this.ProjectService.createNode(this.createNodeTitle);\n\n this.showCreateNode = false;\n this.createNodeTitle = '';\n this.insertNodeMode = true;\n this.createMode = true;\n }\n\n /**\n * Insert the node(s) inside\n * @param nodeId the node id of the group that we will insert into\n */\n insertInside(nodeId) {\n // TODO check that we are inserting into a group\n if (this.createMode) {\n this.handleCreateModeInsert(nodeId, 'inside');\n } else if (this.moveMode) {\n this.handleMoveModeInsert(nodeId, 'inside');\n } else if (this.copyMode) {\n this.handleCopyModeInsert(nodeId, 'inside');\n } else if (this.importMode) {\n this.importSelectedNodes(nodeId);\n }\n }\n\n /**\n * Insert the node(s) after\n * @param nodeId the node id of the node we will insert after\n */\n insertAfter(nodeId) {\n if (this.createMode) {\n this.handleCreateModeInsert(nodeId, 'after');\n } else if (this.moveMode) {\n this.handleMoveModeInsert(nodeId, 'after');\n } else if (this.copyMode) {\n this.handleCopyModeInsert(nodeId, 'after');\n } else if (this.importMode) {\n this.importSelectedNodes(nodeId);\n }\n }\n\n /**\n * Create a node and then insert it in the specified location\n * @param nodeId insert the new node inside or after this node id\n * @param moveTo whether to insert 'inside' or 'after' the nodeId parameter\n */\n handleCreateModeInsert(nodeId, moveTo) {\n if (moveTo === 'inside') {\n this.ProjectService.createNodeInside(this.nodeToAdd, nodeId);\n } else if (moveTo === 'after') {\n this.ProjectService.createNodeAfter(this.nodeToAdd, nodeId);\n } else {\n // an unspecified moveTo was provided\n return;\n }\n\n let newNodes = [this.nodeToAdd];\n let newNode = this.nodeToAdd;\n\n /*\n * clear this variable that we used to hold the node we inserted.\n * since we have inserted the node we don't need a handle to it\n * anymore\n */\n this.nodeToAdd = null;\n\n this.createMode = false;\n this.insertGroupMode = false;\n this.insertNodeMode = false;\n this.temporarilyHighlightNewNodes(newNodes);\n\n this.checkPotentialStartNodeIdChangeThenSaveProject().then(() => {\n if (newNode != null) {\n let nodeCreatedEventData = {\n 'nodeId': newNode.id,\n 'title': this.ProjectService\n .getNodePositionAndTitleByNodeId(newNode.id)\n };\n\n if (this.ProjectService.isGroupNode(newNode.id)) {\n this.saveEvent('activityCreated', 'Authoring', nodeCreatedEventData);\n } else {\n this.saveEvent('stepCreated', 'Authoring', nodeCreatedEventData);\n }\n }\n });\n }\n\n /**\n * Move a node and insert it in the specified location\n * @param nodeId insert the new node inside or after this node id\n * @param moveTo whether to insert 'inside' or 'after' the nodeId parameter\n */\n handleMoveModeInsert(nodeId, moveTo) {\n let selectedNodeIds = this.getSelectedNodeIds();\n if (selectedNodeIds != null && selectedNodeIds.indexOf(nodeId) != -1) {\n /*\n * the user is trying to insert the selected node ids after\n * itself so we will not allow that\n */\n if (selectedNodeIds.length == 1) {\n alert(this\n .$translate('youAreNotAllowedToInsertTheSelectedItemAfterItself'));\n } else if (selectedNodeIds.length > 1) {\n alert(this\n .$translate('youAreNotAllowedToInsertTheSelectedItemsAfterItself'));\n }\n } else {\n let movedNodes = [];\n for (let selectedNodeId of selectedNodeIds) {\n let node = {\n 'nodeId': selectedNodeId,\n 'fromTitle': this.ProjectService\n .getNodePositionAndTitleByNodeId(selectedNodeId)\n };\n movedNodes.push(node);\n }\n\n let newNodes = [];\n if (moveTo === 'inside') {\n newNodes = this.ProjectService.moveNodesInside(selectedNodeIds, nodeId);\n } else if (moveTo === 'after') {\n newNodes = this.ProjectService.moveNodesAfter(selectedNodeIds, nodeId);\n } else {\n // an unspecified moveTo was provided\n return;\n }\n\n this.moveMode = false;\n this.insertGroupMode = false;\n this.insertNodeMode = false;\n this.temporarilyHighlightNewNodes(newNodes);\n this.checkPotentialStartNodeIdChangeThenSaveProject().then(() => {\n if (newNodes != null && newNodes.length > 0) {\n let firstNewNode = newNodes[0];\n if (firstNewNode != null && firstNewNode.id != null) {\n for (let n = 0; n < movedNodes.length; n++) {\n let node = movedNodes[n];\n let newNode = newNodes[n];\n if (node != null && newNode != null) {\n node.toTitle = this.ProjectService\n .getNodePositionAndTitleByNodeId(newNode.id);\n }\n }\n\n if (this.ProjectService.isGroupNode(firstNewNode.id)) {\n let nodeMovedEventData = { activitiesMoved: movedNodes };\n this.saveEvent('activityMoved', 'Authoring', nodeMovedEventData);\n } else {\n let nodeMovedEventData = { stepsMoved: movedNodes };\n this.saveEvent('stepMoved', 'Authoring', nodeMovedEventData);\n }\n }\n }\n });\n }\n }\n\n /**\n * Copy a node and insert it in the specified location\n * @param nodeId insert the new node inside or after this node id\n * @param moveTo whether to insert 'inside' or 'after' the nodeId parameter\n */\n handleCopyModeInsert(nodeId, moveTo) {\n let copiedNodes = [];\n let selectedNodeIds = this.getSelectedNodeIds();\n for (let selectedNodeId of selectedNodeIds) {\n let node = {\n 'fromNodeId': selectedNodeId,\n 'fromTitle': this.ProjectService\n .getNodePositionAndTitleByNodeId(selectedNodeId)\n };\n copiedNodes.push(node);\n }\n\n let newNodes = [];\n if (moveTo === 'inside') {\n newNodes = this.ProjectService.copyNodesInside(selectedNodeIds, nodeId);\n } else if (moveTo === 'after') {\n newNodes = this.ProjectService.copyNodesAfter(selectedNodeIds, nodeId);\n } else {\n // an unspecified moveTo was provided\n return;\n }\n\n this.copyMode = false;\n this.insertGroupMode = false;\n this.insertNodeMode = false;\n this.temporarilyHighlightNewNodes(newNodes);\n this.checkPotentialStartNodeIdChangeThenSaveProject().then(() => {\n if (newNodes != null && newNodes.length > 0) {\n let firstNewNode = newNodes[0];\n if (firstNewNode != null && firstNewNode.id != null) {\n for (let n = 0; n < copiedNodes.length; n++) {\n let node = copiedNodes[n];\n let newNode = newNodes[n];\n if (node != null && newNode != null) {\n node.toNodeId = newNode.id;\n node.toTitle = this.ProjectService\n .getNodePositionAndTitleByNodeId(newNode.id);\n }\n }\n\n if (this.ProjectService.isGroupNode(firstNewNode.id)) {\n let nodeCopiedEventData = { activitiesCopied: copiedNodes };\n this.saveEvent('activityCopied', 'Authoring', nodeCopiedEventData);\n } else {\n let nodeCopiedEventData = { stepsCopied: copiedNodes };\n this.saveEvent('stepCopied', 'Authoring', nodeCopiedEventData);\n }\n }\n }\n });\n }\n\n /**\n * Import the selected steps and draw attention to them by highlighting them\n * and scrolling to them.\n * @param nodeIdToInsertInsideOrAfter If this is a group, we will make the\n * new step the first step in the group. If this is a step, we will place\n * the new step after it.\n */\n importSelectedNodes(nodeIdToInsertInsideOrAfter) {\n let selectedNodes = this.getSelectedNodesToImport();\n let selectedNodeTitles = this.getSelectedNodeTitlesToImport();\n let toProjectId = this.ConfigService.getConfigParam('projectId');\n let fromProjectId = this.importProjectId;\n\n this.performImport(nodeIdToInsertInsideOrAfter).then((newNodes) => {\n this.checkPotentialStartNodeIdChangeThenSaveProject().then(() => {\n let doScrollToNewNodes = true;\n this.temporarilyHighlightNewNodes(newNodes, doScrollToNewNodes);\n\n let stepsImported = [];\n for (let n = 0; n < selectedNodes.length; n++) {\n let selectedNode = selectedNodes[n];\n let selectedNodeTitle = selectedNodeTitles[n];\n let newNode = newNodes[n];\n\n let stepImported = {\n fromProjectId: parseInt(fromProjectId),\n fromNodeId: selectedNode.id,\n fromTitle: selectedNodeTitle,\n toNodeId: newNode.id,\n toTitle: this.ProjectService\n .getNodePositionAndTitleByNodeId(newNode.id)\n };\n stepsImported.push(stepImported);\n }\n\n let stepsImportedEventData = { 'stepsImported': stepsImported };\n this.saveEvent('stepImported', 'Authoring', stepsImportedEventData);\n });\n });\n }\n\n /**\n * Import the step and place it in the chosen location\n * @param nodeIdToInsertInsideOrAfter If this is a group, we will make the\n * new step the first step in the group. If this is a step, we will place\n * the new step after it.\n */\n performImport(nodeIdToInsertInsideOrAfter) {\n let selectedNodes = this.getSelectedNodesToImport();\n let toProjectId = this.ConfigService.getConfigParam('projectId');\n let fromProjectId = this.importProjectId;\n\n return this.ProjectService.copyNodes(selectedNodes, fromProjectId,\n toProjectId, nodeIdToInsertInsideOrAfter).then((newNodes) => {\n this.refreshProject();\n this.insertNodeMode = false;\n this.toggleView('project');\n\n this.importProjectIdToOrder = {};\n this.importProjectItems = [];\n this.importMyProjectId = null;\n this.importLibraryProjectId = null;\n this.importProjectId = null;\n this.importProject = null;\n\n /*\n * go back to the project view and\n * refresh the project assets in case any of the imported\n * steps also imported assets\n */\n this.showProjectHome();\n this.ProjectAssetService.retrieveProjectAssets();\n return newNodes;\n });\n }\n\n /**\n * Turn on copy mode\n */\n copy() {\n // make sure there is at least one item selected\n let selectedNodeIds = this.getSelectedNodeIds();\n if (selectedNodeIds == null || selectedNodeIds.length == 0) {\n alert(this.$translate('pleaseSelectAnItemToCopyAndThenClickTheCopyButtonAgain'));\n } else {\n let selectedItemTypes = this.getSelectedItemTypes();\n if (selectedItemTypes.length === 1 && selectedItemTypes[0] === 'node') {\n this.insertNodeMode = true;\n this.copyMode = true;\n } else if (selectedItemTypes.length === 1 && selectedItemTypes[0] === 'group') {\n alert(this.$translate('youCannotCopyActivitiesAtThisTime'));\n }\n }\n }\n\n /**\n * Turn on move mode\n * TODO refactor. too many nesting. Rename function to \"turnOnMoveMode\"?\n */\n move() {\n // make sure there is at least one item selected\n let selectedNodeIds = this.getSelectedNodeIds();\n if (selectedNodeIds == null || selectedNodeIds.length == 0) {\n alert(this.$translate('pleaseSelectAnItemToMoveAndThenClickTheMoveButtonAgain'));\n } else {\n let selectedItemTypes = this.getSelectedItemTypes();\n if (selectedItemTypes.length === 1 && selectedItemTypes[0] === 'node') {\n this.insertNodeMode = true;\n this.moveMode = true;\n } else if (selectedItemTypes.length === 1 && selectedItemTypes[0] === 'group') {\n this.insertGroupMode = true;\n this.moveMode = true;\n }\n }\n }\n\n /**\n * Delete the selected nodes after asking user for confirmation\n * TODO refactor too many nesting\n */\n delete() {\n let selectedNodeIds = this.getSelectedNodeIds();\n if (selectedNodeIds == null || selectedNodeIds.length == 0) {\n alert(this.$translate('pleaseSelectAnItemToDeleteAndThenClickTheDeleteButtonAgain'));\n } else {\n let confirmMessage = '';\n if (selectedNodeIds.length == 1) {\n confirmMessage = this.$translate('areYouSureYouWantToDeleteTheSelectedItem');\n } else if (selectedNodeIds.length > 1) {\n confirmMessage = this.$translate('areYouSureYouWantToDeleteTheXSelectedItems',\n { numItems: selectedNodeIds.length });\n }\n if (confirm(confirmMessage)) {\n let deletedStartNodeId = false;\n let activityDeleted = false;\n let stepDeleted = false;\n let stepsDeleted = [];\n let activitiesDeleted = [];\n for (let nodeId of selectedNodeIds) {\n let node = this.ProjectService.getNodeById(nodeId);\n let tempNode = {};\n\n if (node != null) {\n tempNode.nodeId = node.id;\n tempNode.title =\n this.ProjectService.getNodePositionAndTitleByNodeId(node.id);\n }\n\n if (this.ProjectService.isStartNodeId(nodeId)) {\n deletedStartNodeId = true;\n }\n\n if (this.ProjectService.isGroupNode(nodeId)) {\n activityDeleted = true;\n let stepsInActivityDeleted = [];\n for (let stepNodeId of node.ids) {\n let stepTitle = this.ProjectService\n .getNodePositionAndTitleByNodeId(stepNodeId);\n\n // create an object with the step id and title\n let stepObject = {\n 'nodeId': stepNodeId,\n 'title': stepTitle\n };\n stepsInActivityDeleted.push(stepObject);\n }\n tempNode.stepsInActivityDeleted = stepsInActivityDeleted;\n activitiesDeleted.push(tempNode);\n } else {\n stepDeleted = true;\n stepsDeleted.push(tempNode);\n }\n this.ProjectService.deleteNode(nodeId);\n }\n\n if (deletedStartNodeId) {\n this.updateStartNodeId();\n }\n\n if (activityDeleted) {\n let activitiesDeletedEventData = {\n 'activitiesDeleted': activitiesDeleted\n };\n this.saveEvent('activityDeleted', 'Authoring',\n activitiesDeletedEventData);\n }\n\n if (stepDeleted) {\n let stepDeletedEventData = {\n 'stepsDeleted': stepsDeleted\n };\n this.saveEvent('stepDeleted', 'Authoring', stepDeletedEventData);\n }\n\n this.ProjectService.saveProject();\n this.refreshProject();\n }\n }\n }\n\n /**\n * Get the ids of the selected nodes, both active and inactive.\n * @returns an array of node ids that are selected\n */\n getSelectedNodeIds() {\n let selectedNodeIds = [];\n angular.forEach(this.items, function(value, key) {\n if (value.checked) {\n selectedNodeIds.push(key);\n }\n }, selectedNodeIds);\n\n if (this.inactiveNodes != null) {\n for (let inactiveNode of this.inactiveNodes) {\n if (inactiveNode != null && inactiveNode.checked) {\n selectedNodeIds.push(inactiveNode.id);\n }\n }\n }\n return selectedNodeIds;\n }\n\n /**\n * Get the distinct types of the selected items, both active and inactive.\n * @returns an array of item types. possible items are group or node.\n */\n getSelectedItemTypes() {\n let selectedItemTypes = [];\n\n angular.forEach(this.items, function(value, key) {\n if (value.checked) {\n let node = this.ProjectService.getNodeById(key);\n if (node != null) {\n let nodeType = node.type;\n if (selectedItemTypes.indexOf(nodeType) == -1) {\n selectedItemTypes.push(nodeType);\n }\n }\n }\n }, this);\n\n if (this.inactiveNodes != null) {\n for (let inactiveNode of this.inactiveNodes) {\n if (inactiveNode != null && inactiveNode.checked) {\n let inactiveNodeType = inactiveNode.type;\n if (selectedItemTypes.indexOf(inactiveNodeType) == -1) {\n selectedItemTypes.push(inactiveNodeType);\n }\n }\n }\n }\n\n return selectedItemTypes;\n }\n\n unselectAllItems() {\n angular.forEach(this.items, function(value, key) {\n value.checked = false;\n });\n angular.forEach(this.inactiveGroupNodes, function(value, key) {\n value.checked = false;\n });\n angular.forEach(this.inactiveStepNodes, function(value, key) {\n value.checked = false;\n });\n this.stepNodeSelected = false;\n this.activityNodeSelected = false;\n }\n\n /**\n * Toggle the create group input\n */\n creatNewActivityClicked() {\n this.createGroupTitle = '';\n this.toggleView('createGroup');\n if (this.showCreateGroup) {\n this.$timeout(() => {\n $('#createGroupTitle').focus();\n });\n }\n }\n\n /**\n * Toggle the create node input\n */\n createNewStepClicked() {\n this.createNodeTitle = '';\n this.toggleView('createNode');\n if (this.showCreateNode) {\n this.$timeout(() => {\n $('#createNodeTitle').focus();\n });\n }\n }\n\n /**\n * Cancel the move mode\n */\n cancelMove() {\n this.insertGroupMode = false;\n this.insertNodeMode = false;\n this.nodeToAdd = null;\n this.createMode = false;\n this.moveMode = false;\n this.copyMode = false;\n this.importMode = false;\n this.unselectAllItems();\n }\n\n /**\n * Update the start node id by traversing start ids until a\n * node id is found.\n */\n updateStartNodeId() {\n let newStartNodeId = null;\n let startGroupId = this.ProjectService.getStartGroupId();\n let node = this.ProjectService.getNodeById(startGroupId);\n let done = false;\n\n // recursively traverse the start ids\n while (!done) {\n if (node == null) {\n // base case in case something went wrong\n done = true;\n } else if (this.ProjectService.isGroupNode(node.id)) {\n // the node is a group node so we will get its start node\n node = this.ProjectService.getNodeById(node.startId);\n } else if (this.ProjectService.isApplicationNode(node.id)) {\n // the node is a step node so we have found the new start node id\n newStartNodeId = node.id;\n done = true;\n } else {\n // base case in case something went wrong\n done = true;\n }\n }\n\n if (newStartNodeId) {\n this.ProjectService.setStartNodeId(newStartNodeId);\n }\n }\n\n /**\n * Check if the start node id for the project could potentially\n * change.\n */\n checkPotentialStartNodeIdChange() {\n return this.$q((resolve, reject) => {\n let firstLeafNodeId = this.ProjectService.getFirstLeafNodeId();\n if (firstLeafNodeId == null) {\n // there are no steps in the project\n // set the start node id to empty string\n this.ProjectService.setStartNodeId('');\n resolve();\n } else {\n // we have found a leaf node\n let currentStartNodeId = this.ProjectService.getStartNodeId();\n if (currentStartNodeId != firstLeafNodeId) {\n // update the start node id\n this.ProjectService.setStartNodeId(firstLeafNodeId);\n resolve();\n } else {\n resolve();\n }\n }\n });\n }\n\n /**\n * Check if the start node id has changed and then save the project\n */\n checkPotentialStartNodeIdChangeThenSaveProject() {\n return this.checkPotentialStartNodeIdChange().then(() => {\n this.ProjectService.saveProject();\n this.refreshProject();\n });\n }\n\n /**\n * Recalculates step numbering\n */\n refreshProject() {\n /*\n * Use a timeout before we refresh the project in order to allow the\n * spinning progress indicator to show up before the browser starts\n * blocking/freezing.\n */\n this.$timeout(() => {\n this.ProjectService.parseProject();\n this.items = this.ProjectService.idToOrder;\n this.inactiveGroupNodes = this.ProjectService.getInactiveGroupNodes();\n this.inactiveStepNodes = this.ProjectService.getInactiveStepNodes();\n this.inactiveNodes = this.ProjectService.getInactiveNodes();\n this.idToNode = this.ProjectService.getIdToNode();\n this.unselectAllItems();\n });\n }\n\n /**\n * The project title changed so we will update the project title in the\n * project service and save the project\n */\n projectTitleChanged() {\n this.ProjectService.setProjectTitle(this.projectTitle);\n this.ProjectService.saveProject();\n }\n\n /**\n * Toggle the import view and populate the project drop downs if necessary\n */\n importStepClicked() {\n this.toggleView('importStep');\n\n if (this.importMode) {\n if (this.myProjectsList == null) {\n this.myProjectsList = this.ConfigService.getAuthorableProjects();\n }\n\n if (this.libraryProjectsList == null) {\n this.ConfigService.getLibraryProjects().then((libraryProjectsList) => {\n this.libraryProjectsList = libraryProjectsList;\n });\n }\n }\n }\n\n /**\n * The author has chosen an authorable project to import from\n * @param importProjectId the project id to import from\n */\n showMyImportProject(importProjectId) {\n this.importLibraryProjectId = null;\n this.showImportProject(importProjectId);\n }\n\n /**\n * The author has chosen a library project to import from\n * @param importProjectId the project id to import from\n */\n showLibraryImportProject(importProjectId) {\n this.importMyProjectId = null;\n this.showImportProject(importProjectId);\n }\n\n /**\n * Show the project we want to import steps from\n * @param importProjectId the import project id\n */\n showImportProject(importProjectId) {\n this.importProjectId = importProjectId;\n if (this.importProjectId == null) {\n // clear all the import project values\n this.importProjectIdToOrder = {};\n this.importProjectItems = [];\n this.importMyProjectId = null;\n this.importLibraryProjectId = null;\n this.importProjectId = null;\n this.importProject = null;\n } else {\n this.ProjectService.retrieveProjectById(this.importProjectId)\n .then((projectJSON) => {\n this.importProject = projectJSON;\n const nodeOrderOfProject = this.ProjectService\n .getNodeOrderOfProject(this.importProject);\n this.importProjectIdToOrder = nodeOrderOfProject.idToOrder;\n this.importProjectItems = nodeOrderOfProject.nodes;\n });\n }\n }\n\n /**\n * Preview the import project in a new tab\n */\n previewImportProject() {\n if (this.importProject != null) {\n window.open(this.importProject.previewProjectURL);\n }\n }\n\n /**\n * Preview the import step in a new tab\n * @param node\n */\n previewImportNode(node) {\n if (node != null) {\n const nodeId = node.id;\n const previewProjectURL = this.importProject.previewProjectURL;\n const previewStepURL = previewProjectURL + '#/vle/' + nodeId;\n window.open(previewStepURL);\n }\n }\n\n /**\n * Import the selected steps\n */\n importSteps() {\n let selectedNodes = this.getSelectedNodesToImport();\n if (selectedNodes == null || selectedNodes.length == 0) {\n // TODO i18n\n alert('Please select a step to import.');\n } else {\n /*\n * hide the import view because we want to go back to the\n * project view so that the author can choose where to place\n * the new steps\n */\n this.showImportView = false;\n this.insertNodeMode = true;\n this.projectMode = true;\n }\n }\n\n /**\n * Get the selected nodes to import\n * @return an array of selected nodes\n */\n getSelectedNodesToImport() {\n let selectedNodes = [];\n for (let item of this.importProjectItems) {\n if (item.checked) {\n selectedNodes.push(item.node);\n }\n }\n return selectedNodes;\n }\n\n /**\n * Show the view to edit the project rubric\n */\n editProjectRubricClicked() {\n this.toggleView('rubric');\n }\n\n /**\n * Show the advanced authoring view\n */\n advancedClicked() {\n this.toggleView('advanced');\n }\n\n /**\n * The show JSON button was clicked\n */\n showJSONClicked() {\n this.showJSONAuthoring = !this.showJSONAuthoring;\n if (this.showJSONAuthoring) {\n this.projectJSONString = angular.toJson(this.ProjectService.project, 4);\n }\n }\n\n /**\n * Save the project JSON string to the server\n */\n saveProjectJSONString() {\n let project = angular.fromJson(this.projectJSONString);\n this.ProjectService.setProject(project);\n let scriptFilename = this.ProjectService.getProjectScriptFilename();\n if (scriptFilename != null) {\n this.projectScriptFilename = scriptFilename;\n }\n this.checkPotentialStartNodeIdChangeThenSaveProject();\n }\n\n /**\n * The author has changed the rubric, so save the changes\n */\n summernoteRubricHTMLChanged() {\n let html = this.summernoteRubricHTML;\n\n /*\n * remove the absolute asset paths\n * e.g.\n * \n * will be changed to\n * \n */\n html = this.ConfigService.removeAbsoluteAssetPaths(html);\n\n /*\n * replace and \";\n } else {\n // default to creating a link that represents the wiselink\n newElement = \"\" + linkText + \"\";\n }\n\n if (newElement != null) {\n // replace the wiselink with the new element\n html = html.replace(wiseLinkHTML, newElement);\n }\n\n // find the next match\n wiseLinkRegExMatchResult = wiseLinkRegEx.exec(html);\n }\n return html;\n }\n\n /**\n * Create a custom summernote button that inserts a WISE asset into\n * summernote\n * @param controller the controller that is creating the button\n * e.g. openResponseController\n * @param nodeId the node id of the component that is creating the button\n * @param componentId the component id of the component that is creating the button\n * @param target the target element in the component to insert the asset into\n * e.g. 'prompt' or 'rubricSummernoteId'\n * @param tooltip the tooltip text for the custom button\n * @return custom summernote button\n */\n createInsertAssetButton(controller, projectId, nodeId, componentId, target, tooltip) {\n const thisRootScope = this.$rootScope;\n\n const InsertAssetButton = function(context) {\n const ui = $.summernote.ui;\n\n const button = ui.button({\n contents: '',\n tooltip: tooltip,\n click: function () {\n // remember the position of the cursor\n context.invoke('editor.saveRange');\n\n // create the params for opening the asset chooser\n const params = {};\n params.isPopup = true;\n\n if (projectId != null) {\n params.projectId = projectId;\n }\n\n if (nodeId != null) {\n params.nodeId = nodeId;\n }\n\n if (componentId != null) {\n params.componentId = componentId;\n }\n\n params.target = target;\n\n // display the asset chooser\n thisRootScope.$broadcast('openAssetChooser', params);\n }\n });\n return button.render(); // return button as jquery object\n };\n return InsertAssetButton;\n }\n\n /**\n * Create a custom summernote button that inserts a WISE link into\n * summernote\n * @param controller the controller that is creating the WISE link\n * e.g. openResponseController\n * @param nodeId the node id of the component that is creating the WISE link\n * @param componentId the component id of the component that is creating the WISE link\n * @param target the target element in the component to insert the WISE link into\n * e.g. 'prompt' or 'rubricSummernoteId'\n * @param tooltip the tooltip text for the custom button\n * @return custom summernote button\n */\n createInsertWISELinkButton(controller, projectId, nodeId, componentId, target, tooltip) {\n const thisRootScope = this.$rootScope;\n\n const InsertWISELinkButton = function(context) {\n const ui = $.summernote.ui;\n\n const button = ui.button({\n contents: '',\n tooltip: tooltip,\n click: function () {\n // remember the position of the cursor\n context.invoke('editor.saveRange');\n\n // create the params for opening the WISE Link chooser\n const params = {};\n\n if (projectId != null) {\n params.projectId = projectId;\n }\n\n if (nodeId != null) {\n params.nodeId = nodeId;\n }\n\n if (componentId != null) {\n params.componentId = componentId;\n }\n\n params.target = target;\n\n // display the WISE Link authoring popup\n thisRootScope.$broadcast('openWISELinkChooser', params);\n }\n });\n return button.render(); // return button as jquery object\n };\n return InsertWISELinkButton;\n }\n\n /**\n * Remove html tags from the string. Also remove new lines.\n * @param html an html string\n * @return text without html tags\n */\n removeHTMLTags(html) {\n let text = '';\n if (html != null) {\n // remove tags\n text = html.replace(/<\\/?[^>]+(>|$)/g, \" \");\n text = text.replace(/\\n/g, \" \");\n text = text.replace(/\\r/g, \" \");\n }\n return text;\n }\n\n /**\n * Check if a string ends with a specific string\n * @param subjectString the main string\n * @param searchString the potential end of the string\n * @param position (optional) the position to start searching\n * @return whether the subjectString ends with the searchString\n */\n endsWith(subjectString, searchString, position) {\n if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {\n position = subjectString.length;\n }\n position -= searchString.length;\n const lastIndex = subjectString.lastIndexOf(searchString, position);\n return lastIndex !== -1 && lastIndex === position;\n }\n\n /**\n * Sort the objects by server save time\n * @param object1 an object\n * @param object2 an object\n * @return -1 if object1 server save time comes before object2 server save time\n * 1 if object1 server save time comes after object2 server save time\n * 0 if object1 server save time is equal to object2 server save time\n */\n sortByServerSaveTime(object1, object2) {\n if (object1.serverSaveTime < object2.serverSaveTime) {\n return -1;\n } else if (object1.serverSaveTime > object2.serverSaveTime) {\n return 1;\n } else {\n return 0;\n }\n }\n\n /**\n * Convert milliseconds since the epoch to a pretty printed date time\n * @param milliseconds the milliseconds since the epoch\n * @return a string containing the pretty printed date time\n * example\n * Wed Apr 06 2016 9:05:38 AM\n */\n convertMillisecondsToFormattedDateTime(milliseconds) {\n const date = new Date(milliseconds);\n if (date != null) {\n return date.toDateString() + \" \" + date.toLocaleTimeString();\n }\n return \"\";\n }\n\n /**\n * Get the label for the given component type\n * @param componentType string\n * @return string label for the component type\n */\n getComponentTypeLabel(componentType) {\n /*\n * check if we have already obtained the label for this component type\n * before\n */\n let label = this.componentTypeToLabel[componentType];\n\n if (label == null) {\n let componentService = this.$injector.get(componentType + 'Service');\n if (componentService != null && componentService.getComponentTypeLabel != null) {\n label = componentService.getComponentTypeLabel();\n this.componentTypeToLabel[componentType] = label;\n }\n }\n\n if (label == null) {\n /*\n * we were unable to find the label so we will just use the\n * component type as the label\n */\n label = componentType;\n }\n return label;\n }\n\n /**\n * Check if two arrays contain the same values. This is commonly used to\n * check if two arrays of ids contain the same values. The order of the\n * elements is not compared, only the actual values. This means the elements\n * can be in different orders but still contain the same values.\n * Example:\n * array1=['1234567890', 'abcdefghij']\n * array2=['abcdefghij', '1234567890']\n * If these two arrays are passed in as the two arguments, this function\n * will return true.\n * Note: This may only work if the elements are strings, numbers or\n * booleans. If the elements are objects, this function may or may not work.\n * @param array1 an array of strings, numbers, or booleans\n * @param array2 an array of strings, numbers, or booleans\n * @return whether the arrays contain the same values\n */\n arraysContainSameValues(array1, array2) {\n if (array1 != null && array2 != null) {\n const array1Copy = this.makeCopyOfJSONObject(array1);\n array1Copy.sort();\n\n const array2Copy = this.makeCopyOfJSONObject(array2);\n array2Copy.sort();\n\n if (angular.toJson(array1Copy) == angular.toJson(array2Copy)) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Whether there are any connected components\n * @param componentContent the component content\n * @return whether there are any connected components\n */\n hasConnectedComponent(componentContent) {\n if (componentContent != null) {\n const connectedComponents = componentContent.connectedComponents;\n if (connectedComponents != null && connectedComponents.length > 0) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @param componentContent The component content.\n * @return Whether there are any connected components with a field we always\n * want to read or write.\n */\n hasConnectedComponentAlwaysField(componentContent) {\n if (componentContent != null) {\n const connectedComponents = componentContent.connectedComponents;\n if (connectedComponents != null && connectedComponents.length > 0) {\n for (let connectedComponent of connectedComponents) {\n if (connectedComponent.fields != null) {\n for (let field of connectedComponent.fields) {\n if (field.when == \"always\") {\n return true;\n }\n }\n }\n }\n }\n }\n return false;\n }\n\n /**\n * Whether this component shows work from a connected component\n * @param componentContent the component content\n * @return whether this component shows work from a connected component\n */\n hasShowWorkConnectedComponent(componentContent) {\n if (componentContent != null) {\n const connectedComponents = componentContent.connectedComponents;\n if (connectedComponents != null) {\n for (let connectedComponent of connectedComponents) {\n if (connectedComponent != null) {\n if (connectedComponent.type == 'showWork') {\n return true;\n }\n }\n }\n }\n }\n return false;\n }\n\n /**\n * Whether this component imports work from a connected component\n * @param componentContent the component content\n * @return whether this component imports work from a connected component\n */\n hasImportWorkConnectedComponent(componentContent) {\n if (componentContent != null) {\n const connectedComponents = componentContent.connectedComponents;\n if (connectedComponents != null) {\n for (let connectedComponent of connectedComponents) {\n if (connectedComponent != null) {\n if (connectedComponent.type == 'importWork') {\n return true;\n }\n }\n }\n }\n }\n return false;\n }\n\n /**\n * Check if an array has any non null elements.\n * @param arrayToCheck An array which may have null and non null elements.\n * @return True if the array has at least one non null element.\n * False if the array has all null elements.\n */\n arrayHasNonNullElement(arrayToCheck) {\n for (let element of arrayToCheck) {\n if (element != null) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Takes a string and breaks it up into multiple lines so that the length of\n * each line does not exceed a certain number of characters. This code was\n * found on stackoverflow.\n * https://stackoverflow.com/questions/14484787/wrap-text-in-javascript\n * @param str The string to break up.\n * @param maxWidth The max width of a line.\n * @return A string that has been broken up into multiple lines using \\n.\n */\n wordWrap(str, maxWidth) {\n if (str.length <= maxWidth) {\n return str;\n }\n let newLineStr = \"\\n\";\n let done = false;\n let res = '';\n do {\n let found = false;\n // Inserts new line at first whitespace of the line\n for (let i = maxWidth - 1; i >= 0; i--) {\n if (this.testWhite(str.charAt(i))) {\n res = res + [str.slice(0, i), newLineStr].join('');\n str = str.slice(i + 1);\n found = true;\n break;\n }\n }\n // Inserts new line at maxWidth position, the word is too long to wrap\n if (!found) {\n res += [str.slice(0, maxWidth), newLineStr].join('');\n str = str.slice(maxWidth);\n }\n\n if (str.length < maxWidth)\n done = true;\n } while (!done);\n\n return res + str;\n }\n\n /**\n * Helper function for wordWrap().\n * @param x A single character string.\n * @return Whether the single character is a whitespace character.\n */\n testWhite(x) {\n let white = new RegExp(/^\\s$/);\n return white.test(x.charAt(0));\n };\n\n /**\n * Get the number of words in the string.\n * @param str The string.\n * @return The number of words in the string.\n */\n wordCount(str) {\n return str.trim().split(/\\s+/).length;\n }\n\n /**\n * Check if there is a 'nodeEntered' event in the array of events.\n * @param events An array of events.\n * @return Whether there is a 'nodeEntered' event in the array of events.\n */\n hasNodeEnteredEvent(events) {\n for (let event of events) {\n if (event.event == 'nodeEntered') {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Determine whether the component has been authored to import work.\n * @param componentContent The component content.\n * @return Whether to import work in this component.\n */\n hasImportWorkConnectedComponent(componentContent) {\n return this.hasXConnectedComponent(componentContent, 'importWork');\n }\n\n /**\n * Determine whether the component has been authored to show work.\n * @param componentContent The component content.\n * @return Whether to show work in this component.\n */\n hasShowWorkConnectedComponent(componentContent) {\n return this.hasXConnectedComponent(componentContent, 'showWork');\n }\n\n /**\n * Determine whether the component has been authored to show classmate work.\n * @param componentContent The component content.\n * @return Whether to show classmate work in this component.\n */\n hasShowClassmateWorkConnectedComponent(componentContent) {\n return this.hasXConnectedComponent(componentContent, 'showClassmateWork');\n }\n\n /**\n * Determine whether the component has a connected component of the given type.\n * @param componentContent The component content.\n * @param connectedComponentType The connected component type.\n * @return Whether the component has a connected component of the given type.\n */\n hasXConnectedComponent(componentContent, connectedComponentType) {\n if (componentContent.connectedComponents != null) {\n let connectedComponents = componentContent.connectedComponents;\n // loop through all the connected components\n for (let connectedComponent of connectedComponents) {\n if (connectedComponent.type == connectedComponentType) {\n // the connected component is the type we're looking for\n return true;\n }\n }\n }\n return false;\n }\n\n /**\n * Temporarily highlight an element in the DOM.\n * @param id The id of the element.\n * @param duration The number of milliseconds to keep the element highlighted.\n */\n temporarilyHighlightElement(id, duration = 1000) {\n let element = $('#' + id);\n let originalBackgroundColor = element.css('backgroundColor');\n element.css('background-color', '#FFFF9C');\n\n /*\n * Use a timeout before starting to transition back to\n * the original background color. For some reason the\n * element won't get highlighted in the first place\n * unless this timeout is used.\n */\n this.$timeout(() => {\n // slowly fade back to the original background color\n element.css({\n 'transition': 'background-color 2s ease-in-out',\n 'background-color': originalBackgroundColor\n });\n\n /*\n * remove these styling fields after we perform\n * the fade otherwise the regular mouseover\n * background color change will not work\n */\n this.$timeout(() => {\n element.css({\n 'transition': '',\n 'background-color': ''\n });\n }, 2000);\n }, duration);\n }\n\n /**\n * Render the component state and then generate an image from it.\n * @param componentState The component state to render.\n * @return A promise that will return an image.\n */\n generateImageFromComponentState(componentState) {\n let deferred = this.$q.defer();\n this.$mdDialog.show({\n template: `\n
\n
\n {{ \"importingWork\" | translate }}...\n
\n
\n \n
\n \n `,\n locals: {\n nodeId: componentState.nodeId,\n componentId: componentState.componentId,\n componentState: componentState\n },\n controller: DialogController\n });\n function DialogController($scope, $mdDialog, nodeId, componentId, componentState) {\n $scope.nodeId = nodeId;\n $scope.componentId = componentId;\n $scope.componentState = componentState;\n $scope.closeDialog = function() {\n $mdDialog.hide();\n }\n }\n DialogController.$inject = ['$scope', '$mdDialog', 'nodeId', 'componentId', 'componentState'];\n // wait for the component in the dialog to finish rendering\n let doneRenderingComponentListener = this.$rootScope.$on('doneRenderingComponent', (event, args) => {\n if (componentState.nodeId == args.nodeId && componentState.componentId == args.componentId) {\n this.$timeout(() => {\n this.generateImageFromComponentStateHelper(componentState).then((image) => {\n /*\n * Destroy the listener otherwise this block of code will be called every time\n * doneRenderingComponent is fired in the future.\n */\n doneRenderingComponentListener();\n this.$timeout.cancel(destroyDoneRenderingComponentListenerTimeout);\n deferred.resolve(image);\n });\n }, 1000);\n }\n });\n /*\n * Set a timeout to destroy the listener in case there is an error creating the image and\n * we don't get to destroying it above.\n */\n let destroyDoneRenderingComponentListenerTimeout = this.$timeout(() => {\n // destroy the listener\n doneRenderingComponentListener();\n }, 10000);\n return deferred.promise;\n }\n\n /**\n * The component state has been rendered in the DOM and now we want to create an image\n * from it.\n * @param componentState The component state that has been rendered.\n * @return A promise that will return an image.\n */\n generateImageFromComponentStateHelper(componentState) {\n let deferred = this.$q.defer();\n let componentService = this.$injector.get(componentState.componentType + 'Service');\n componentService.generateImageFromRenderedComponentState(componentState).then((image) => {\n deferred.resolve(image);\n this.$mdDialog.hide();\n });\n return deferred.promise;\n }\n\n /**\n * Get the connected component associated with the component state.\n * @param componentContent The component content.\n * @param componentState The component state.\n * @return A connected component object or null.\n */\n getConnectedComponentByComponentState(componentContent, componentState) {\n let nodeId = componentState.nodeId;\n let componentId = componentState.componentId;\n let connectedComponents = componentContent.connectedComponents;\n for (let connectedComponent of connectedComponents) {\n if (connectedComponent.nodeId == nodeId && connectedComponent.componentId == componentId) {\n return connectedComponent;\n }\n }\n return null;\n }\n}\n\n// Get the last element of the array\nif (!Array.prototype.last) {\n Array.prototype.last = function() {\n return this[this.length - 1];\n };\n}\n\nUtilService.$inject = [\n '$filter',\n '$injector',\n '$mdDialog',\n '$q',\n '$rootScope',\n '$timeout'\n];\n\nexport default UtilService;\n"]} \ No newline at end of file +{"version":3,"sources":["utilService.es6"],"names":["UtilService","$filter","$injector","$mdDialog","$q","$rootScope","$timeout","componentTypeToLabel","$translate","length","CHARS","key","a","Math","floor","random","str","isNaN","Number","jsonObject","jsonObjectString","angular","toJson","fromJson","img_b64","blob","dataURItoBlob","now","Date","getTime","filename","encodeURIComponent","pngFile","File","lastModified","type","dataURI","byteString","split","indexOf","atob","unescape","mimeString","ia","Uint8Array","i","charCodeAt","Blob","imageElement","imageObject","canvas","document","createElement","width","naturalWidth","height","naturalHeight","ctx","getContext","drawImage","dataURL","toDataURL","getImageObjectFromBase64String","fileName","imageExtensionsRegEx","RegExp","lowerCaseFileName","toLowerCase","matchResult","match","videoExtensionsRegEx","html","insertWISELinkAnchors","insertWISELinkButtons","wiseLinkRegEx","wiseLinkRegExMatchResult","exec","anchorHTML","anchorText","nodeId","getWISELinkNodeId","componentIdAttr","componentId","getWISELinkComponentId","wiselinkHtml","replace","buttonHTML","buttonText","nodeIdRegEx","nodeIdRegExResult","componentIdRegEx","componentIdRegExResult","typeRegEx","typeRegExResult","linkTextRegEx","linkTextRegExResult","replaceWISELinksHelper","regex","wiseLinkHTML","componentHTML","getWISELinkType","linkText","getWISELinkLinkText","newElement","controller","projectId","target","tooltip","thisRootScope","InsertAssetButton","context","ui","$","summernote","button","contents","click","invoke","params","isPopup","$broadcast","render","InsertWISELinkButton","text","subjectString","searchString","position","isFinite","lastIndex","lastIndexOf","object1","object2","serverSaveTime","milliseconds","date","toDateString","toLocaleTimeString","componentType","label","componentService","get","getComponentTypeLabel","array1","array2","array1Copy","makeCopyOfJSONObject","sort","array2Copy","componentContent","connectedComponents","connectedComponent","fields","field","when","arrayToCheck","element","maxWidth","newLineStr","done","res","found","testWhite","charAt","slice","join","x","white","test","trim","events","event","hasXConnectedComponent","connectedComponentType","id","duration","originalBackgroundColor","css","componentState","deferred","defer","show","template","locals","DialogController","$scope","closeDialog","hide","$inject","doneRenderingComponentListener","$on","args","generateImageFromComponentStateHelper","then","image","cancel","destroyDoneRenderingComponentListenerTimeout","resolve","promise","generateImageFromRenderedComponentState","setIsJSONValidMessage","isJSONValid","Array","prototype","last"],"mappings":"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","file":"utilService.js","sourcesContent":["'use strict';\n\nclass UtilService {\n constructor(\n $filter,\n $injector,\n $mdDialog,\n $q,\n $rootScope,\n $timeout) {\n this.$filter = $filter;\n this.$injector = $injector;\n this.$mdDialog = $mdDialog;\n this.$q = $q;\n this.$rootScope = $rootScope;\n this.$timeout = $timeout;\n this.componentTypeToLabel = {};\n this.$translate = this.$filter('translate');\n }\n\n /**\n * Generates and returns a random key of the given length if\n * specified. If length is not specified, returns a key 10\n * characters in length.\n */\n generateKey(length) {\n this.CHARS = [\"a\",\"b\",\"c\",\"d\",\"e\",\"f\",\"g\",\"h\",\"i\",\"j\",\"k\",\"l\",\"m\",\n \"n\",\"o\",\"p\",\"q\",\"r\", \"s\",\"t\",\"u\",\"v\",\"w\",\"x\",\"y\",\"z\",\n \"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\"];\n\n if (!length) {\n length = 10;\n }\n\n let key = '';\n for (let a = 0; a < length; a++) {\n key += this.CHARS[Math.floor(Math.random() * (this.CHARS.length - 1))];\n }\n\n return key;\n };\n\n /**\n * Try to convert a string to a number\n * @param str the string to convert\n * @returns a number if we were able to convert the string to a number.\n * if we couldn't convert the string to a number we will just return the string.\n */\n convertStringToNumber(str) {\n if (str != null && str != '' && !isNaN(Number(str))) {\n return Number(str);\n }\n return str;\n };\n\n /**\n * Create a copy of a JSON object\n * @param jsonObject the JSON object to get a copy of\n * @return a copy of the JSON object that was passed in\n */\n makeCopyOfJSONObject(jsonObject) {\n if (jsonObject != null) {\n const jsonObjectString = angular.toJson(jsonObject);\n return angular.fromJson(jsonObjectString);\n }\n return null;\n };\n\n /**\n * Get the image object\n * @params img_b64 the base64 image string\n * @returns an image object\n */\n getImageObjectFromBase64String(img_b64) {\n // create a blob from the base64 image string\n const blob = this.dataURItoBlob(img_b64);\n\n const now = new Date().getTime();\n const filename = encodeURIComponent('picture_' + now + '.png');\n const pngFile = new File([blob], filename, {\n lastModified: now, // optional - default = now\n type: 'image/png' // optional - default = ''\n });\n return pngFile;\n }\n\n /**\n * Convert base64/URLEncoded data component to raw binary data held in a string\n * @param dataURI base64/URLEncoded data\n * @returns a Blob object\n */\n dataURItoBlob(dataURI) {\n let byteString;\n if (dataURI.split(',')[0].indexOf('base64') >= 0)\n byteString = atob(dataURI.split(',')[1]);\n else\n byteString = unescape(dataURI.split(',')[1]);\n\n // separate out the mime component\n const mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];\n\n // write the bytes of the string to a typed array\n const ia = new Uint8Array(byteString.length);\n for (let i = 0; i < byteString.length; i++) {\n ia[i] = byteString.charCodeAt(i);\n }\n return new Blob([ia], {type:mimeString});\n };\n\n /**\n * Get an image object from an image element\n * @param imageElement an image element ()\n * @returns an image object\n */\n getImageObjectFromImageElement(imageElement) {\n let imageObject = null;\n if (imageElement != null) {\n // create a canvas element that we will use to generate a base64 string\n const canvas = document.createElement(\"canvas\");\n\n // set the width and height of the canvas to match the image dimensions\n canvas.width = imageElement.naturalWidth;\n canvas.height = imageElement.naturalHeight;\n\n // draw the image onto the canvas\n const ctx = canvas.getContext(\"2d\");\n ctx.drawImage(imageElement, 0, 0);\n\n const dataURL = canvas.toDataURL(\"image/png\");\n imageObject = this.getImageObjectFromBase64String(dataURL);\n }\n return imageObject;\n }\n\n /**\n * Check if the asset is an image\n * @param fileName the file name of the asset\n * @return whether the asset is an image or not\n */\n isImage(fileName) {\n if (fileName != null) {\n const imageExtensionsRegEx =\n new RegExp('.*\\.(png|jpg|jpeg|bmp|gif|tiff|svg)');\n const lowerCaseFileName = fileName.toLowerCase();\n const matchResult = lowerCaseFileName.match(imageExtensionsRegEx);\n\n if (matchResult != null) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Check if the asset is a video\n * @param fileName the file name of the asset\n * @return whether the asset is a video or not\n */\n isVideo(fileName) {\n if (fileName != null) {\n const videoExtensionsRegEx =\n new RegExp('.*\\.(mp4|mpg|mpeg|m4v|m2v|avi|gifv|mov|qt)');\n const lowerCaseFileName = fileName.toLowerCase();\n const matchResult = lowerCaseFileName.match(videoExtensionsRegEx);\n\n if (matchResult != null) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Replace and \";\n } else {\n // default to creating a link that represents the wiselink\n newElement = \"\" + linkText + \"\";\n }\n\n if (newElement != null) {\n // replace the wiselink with the new element\n html = html.replace(wiseLinkHTML, newElement);\n }\n\n // find the next match\n wiseLinkRegExMatchResult = wiseLinkRegEx.exec(html);\n }\n return html;\n }\n\n /**\n * Create a custom summernote button that inserts a WISE asset into\n * summernote\n * @param controller the controller that is creating the button\n * e.g. openResponseController\n * @param nodeId the node id of the component that is creating the button\n * @param componentId the component id of the component that is creating the button\n * @param target the target element in the component to insert the asset into\n * e.g. 'prompt' or 'rubricSummernoteId'\n * @param tooltip the tooltip text for the custom button\n * @return custom summernote button\n */\n createInsertAssetButton(controller, projectId, nodeId, componentId, target, tooltip) {\n const thisRootScope = this.$rootScope;\n\n const InsertAssetButton = function(context) {\n const ui = $.summernote.ui;\n\n const button = ui.button({\n contents: '',\n tooltip: tooltip,\n click: function () {\n // remember the position of the cursor\n context.invoke('editor.saveRange');\n\n // create the params for opening the asset chooser\n const params = {};\n params.isPopup = true;\n\n if (projectId != null) {\n params.projectId = projectId;\n }\n\n if (nodeId != null) {\n params.nodeId = nodeId;\n }\n\n if (componentId != null) {\n params.componentId = componentId;\n }\n\n params.target = target;\n\n // display the asset chooser\n thisRootScope.$broadcast('openAssetChooser', params);\n }\n });\n return button.render(); // return button as jquery object\n };\n return InsertAssetButton;\n }\n\n /**\n * Create a custom summernote button that inserts a WISE link into\n * summernote\n * @param controller the controller that is creating the WISE link\n * e.g. openResponseController\n * @param nodeId the node id of the component that is creating the WISE link\n * @param componentId the component id of the component that is creating the WISE link\n * @param target the target element in the component to insert the WISE link into\n * e.g. 'prompt' or 'rubricSummernoteId'\n * @param tooltip the tooltip text for the custom button\n * @return custom summernote button\n */\n createInsertWISELinkButton(controller, projectId, nodeId, componentId, target, tooltip) {\n const thisRootScope = this.$rootScope;\n\n const InsertWISELinkButton = function(context) {\n const ui = $.summernote.ui;\n\n const button = ui.button({\n contents: '',\n tooltip: tooltip,\n click: function () {\n // remember the position of the cursor\n context.invoke('editor.saveRange');\n\n // create the params for opening the WISE Link chooser\n const params = {};\n\n if (projectId != null) {\n params.projectId = projectId;\n }\n\n if (nodeId != null) {\n params.nodeId = nodeId;\n }\n\n if (componentId != null) {\n params.componentId = componentId;\n }\n\n params.target = target;\n\n // display the WISE Link authoring popup\n thisRootScope.$broadcast('openWISELinkChooser', params);\n }\n });\n return button.render(); // return button as jquery object\n };\n return InsertWISELinkButton;\n }\n\n /**\n * Remove html tags from the string. Also remove new lines.\n * @param html an html string\n * @return text without html tags\n */\n removeHTMLTags(html) {\n let text = '';\n if (html != null) {\n // remove tags\n text = html.replace(/<\\/?[^>]+(>|$)/g, \" \");\n text = text.replace(/\\n/g, \" \");\n text = text.replace(/\\r/g, \" \");\n }\n return text;\n }\n\n /**\n * Check if a string ends with a specific string\n * @param subjectString the main string\n * @param searchString the potential end of the string\n * @param position (optional) the position to start searching\n * @return whether the subjectString ends with the searchString\n */\n endsWith(subjectString, searchString, position) {\n if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {\n position = subjectString.length;\n }\n position -= searchString.length;\n const lastIndex = subjectString.lastIndexOf(searchString, position);\n return lastIndex !== -1 && lastIndex === position;\n }\n\n /**\n * Sort the objects by server save time\n * @param object1 an object\n * @param object2 an object\n * @return -1 if object1 server save time comes before object2 server save time\n * 1 if object1 server save time comes after object2 server save time\n * 0 if object1 server save time is equal to object2 server save time\n */\n sortByServerSaveTime(object1, object2) {\n if (object1.serverSaveTime < object2.serverSaveTime) {\n return -1;\n } else if (object1.serverSaveTime > object2.serverSaveTime) {\n return 1;\n } else {\n return 0;\n }\n }\n\n /**\n * Convert milliseconds since the epoch to a pretty printed date time\n * @param milliseconds the milliseconds since the epoch\n * @return a string containing the pretty printed date time\n * example\n * Wed Apr 06 2016 9:05:38 AM\n */\n convertMillisecondsToFormattedDateTime(milliseconds) {\n const date = new Date(milliseconds);\n if (date != null) {\n return date.toDateString() + \" \" + date.toLocaleTimeString();\n }\n return \"\";\n }\n\n /**\n * Get the label for the given component type\n * @param componentType string\n * @return string label for the component type\n */\n getComponentTypeLabel(componentType) {\n /*\n * check if we have already obtained the label for this component type\n * before\n */\n let label = this.componentTypeToLabel[componentType];\n\n if (label == null) {\n let componentService = this.$injector.get(componentType + 'Service');\n if (componentService != null && componentService.getComponentTypeLabel != null) {\n label = componentService.getComponentTypeLabel();\n this.componentTypeToLabel[componentType] = label;\n }\n }\n\n if (label == null) {\n /*\n * we were unable to find the label so we will just use the\n * component type as the label\n */\n label = componentType;\n }\n return label;\n }\n\n /**\n * Check if two arrays contain the same values. This is commonly used to\n * check if two arrays of ids contain the same values. The order of the\n * elements is not compared, only the actual values. This means the elements\n * can be in different orders but still contain the same values.\n * Example:\n * array1=['1234567890', 'abcdefghij']\n * array2=['abcdefghij', '1234567890']\n * If these two arrays are passed in as the two arguments, this function\n * will return true.\n * Note: This may only work if the elements are strings, numbers or\n * booleans. If the elements are objects, this function may or may not work.\n * @param array1 an array of strings, numbers, or booleans\n * @param array2 an array of strings, numbers, or booleans\n * @return whether the arrays contain the same values\n */\n arraysContainSameValues(array1, array2) {\n if (array1 != null && array2 != null) {\n const array1Copy = this.makeCopyOfJSONObject(array1);\n array1Copy.sort();\n\n const array2Copy = this.makeCopyOfJSONObject(array2);\n array2Copy.sort();\n\n if (angular.toJson(array1Copy) == angular.toJson(array2Copy)) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Whether there are any connected components\n * @param componentContent the component content\n * @return whether there are any connected components\n */\n hasConnectedComponent(componentContent) {\n if (componentContent != null) {\n const connectedComponents = componentContent.connectedComponents;\n if (connectedComponents != null && connectedComponents.length > 0) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * @param componentContent The component content.\n * @return Whether there are any connected components with a field we always\n * want to read or write.\n */\n hasConnectedComponentAlwaysField(componentContent) {\n if (componentContent != null) {\n const connectedComponents = componentContent.connectedComponents;\n if (connectedComponents != null && connectedComponents.length > 0) {\n for (let connectedComponent of connectedComponents) {\n if (connectedComponent.fields != null) {\n for (let field of connectedComponent.fields) {\n if (field.when == \"always\") {\n return true;\n }\n }\n }\n }\n }\n }\n return false;\n }\n\n /**\n * Whether this component shows work from a connected component\n * @param componentContent the component content\n * @return whether this component shows work from a connected component\n */\n hasShowWorkConnectedComponent(componentContent) {\n if (componentContent != null) {\n const connectedComponents = componentContent.connectedComponents;\n if (connectedComponents != null) {\n for (let connectedComponent of connectedComponents) {\n if (connectedComponent != null) {\n if (connectedComponent.type == 'showWork') {\n return true;\n }\n }\n }\n }\n }\n return false;\n }\n\n /**\n * Whether this component imports work from a connected component\n * @param componentContent the component content\n * @return whether this component imports work from a connected component\n */\n hasImportWorkConnectedComponent(componentContent) {\n if (componentContent != null) {\n const connectedComponents = componentContent.connectedComponents;\n if (connectedComponents != null) {\n for (let connectedComponent of connectedComponents) {\n if (connectedComponent != null) {\n if (connectedComponent.type == 'importWork') {\n return true;\n }\n }\n }\n }\n }\n return false;\n }\n\n /**\n * Check if an array has any non null elements.\n * @param arrayToCheck An array which may have null and non null elements.\n * @return True if the array has at least one non null element.\n * False if the array has all null elements.\n */\n arrayHasNonNullElement(arrayToCheck) {\n for (let element of arrayToCheck) {\n if (element != null) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Takes a string and breaks it up into multiple lines so that the length of\n * each line does not exceed a certain number of characters. This code was\n * found on stackoverflow.\n * https://stackoverflow.com/questions/14484787/wrap-text-in-javascript\n * @param str The string to break up.\n * @param maxWidth The max width of a line.\n * @return A string that has been broken up into multiple lines using \\n.\n */\n wordWrap(str, maxWidth) {\n if (str.length <= maxWidth) {\n return str;\n }\n let newLineStr = \"\\n\";\n let done = false;\n let res = '';\n do {\n let found = false;\n // Inserts new line at first whitespace of the line\n for (let i = maxWidth - 1; i >= 0; i--) {\n if (this.testWhite(str.charAt(i))) {\n res = res + [str.slice(0, i), newLineStr].join('');\n str = str.slice(i + 1);\n found = true;\n break;\n }\n }\n // Inserts new line at maxWidth position, the word is too long to wrap\n if (!found) {\n res += [str.slice(0, maxWidth), newLineStr].join('');\n str = str.slice(maxWidth);\n }\n\n if (str.length < maxWidth)\n done = true;\n } while (!done);\n\n return res + str;\n }\n\n /**\n * Helper function for wordWrap().\n * @param x A single character string.\n * @return Whether the single character is a whitespace character.\n */\n testWhite(x) {\n let white = new RegExp(/^\\s$/);\n return white.test(x.charAt(0));\n };\n\n /**\n * Get the number of words in the string.\n * @param str The string.\n * @return The number of words in the string.\n */\n wordCount(str) {\n return str.trim().split(/\\s+/).length;\n }\n\n /**\n * Check if there is a 'nodeEntered' event in the array of events.\n * @param events An array of events.\n * @return Whether there is a 'nodeEntered' event in the array of events.\n */\n hasNodeEnteredEvent(events) {\n for (let event of events) {\n if (event.event == 'nodeEntered') {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Determine whether the component has been authored to import work.\n * @param componentContent The component content.\n * @return Whether to import work in this component.\n */\n hasImportWorkConnectedComponent(componentContent) {\n return this.hasXConnectedComponent(componentContent, 'importWork');\n }\n\n /**\n * Determine whether the component has been authored to show work.\n * @param componentContent The component content.\n * @return Whether to show work in this component.\n */\n hasShowWorkConnectedComponent(componentContent) {\n return this.hasXConnectedComponent(componentContent, 'showWork');\n }\n\n /**\n * Determine whether the component has been authored to show classmate work.\n * @param componentContent The component content.\n * @return Whether to show classmate work in this component.\n */\n hasShowClassmateWorkConnectedComponent(componentContent) {\n return this.hasXConnectedComponent(componentContent, 'showClassmateWork');\n }\n\n /**\n * Determine whether the component has a connected component of the given type.\n * @param componentContent The component content.\n * @param connectedComponentType The connected component type.\n * @return Whether the component has a connected component of the given type.\n */\n hasXConnectedComponent(componentContent, connectedComponentType) {\n if (componentContent.connectedComponents != null) {\n let connectedComponents = componentContent.connectedComponents;\n // loop through all the connected components\n for (let connectedComponent of connectedComponents) {\n if (connectedComponent.type == connectedComponentType) {\n // the connected component is the type we're looking for\n return true;\n }\n }\n }\n return false;\n }\n\n /**\n * Temporarily highlight an element in the DOM.\n * @param id The id of the element.\n * @param duration The number of milliseconds to keep the element highlighted.\n */\n temporarilyHighlightElement(id, duration = 1000) {\n let element = $('#' + id);\n let originalBackgroundColor = element.css('backgroundColor');\n element.css('background-color', '#FFFF9C');\n\n /*\n * Use a timeout before starting to transition back to\n * the original background color. For some reason the\n * element won't get highlighted in the first place\n * unless this timeout is used.\n */\n this.$timeout(() => {\n // slowly fade back to the original background color\n element.css({\n 'transition': 'background-color 2s ease-in-out',\n 'background-color': originalBackgroundColor\n });\n\n /*\n * remove these styling fields after we perform\n * the fade otherwise the regular mouseover\n * background color change will not work\n */\n this.$timeout(() => {\n element.css({\n 'transition': '',\n 'background-color': ''\n });\n }, 2000);\n }, duration);\n }\n\n /**\n * Render the component state and then generate an image from it.\n * @param componentState The component state to render.\n * @return A promise that will return an image.\n */\n generateImageFromComponentState(componentState) {\n let deferred = this.$q.defer();\n this.$mdDialog.show({\n template: `\n
\n
\n {{ \"importingWork\" | translate }}...\n
\n
\n \n
\n \n `,\n locals: {\n nodeId: componentState.nodeId,\n componentId: componentState.componentId,\n componentState: componentState\n },\n controller: DialogController\n });\n function DialogController($scope, $mdDialog, nodeId, componentId, componentState) {\n $scope.nodeId = nodeId;\n $scope.componentId = componentId;\n $scope.componentState = componentState;\n $scope.closeDialog = function() {\n $mdDialog.hide();\n }\n }\n DialogController.$inject = ['$scope', '$mdDialog', 'nodeId', 'componentId', 'componentState'];\n // wait for the component in the dialog to finish rendering\n let doneRenderingComponentListener = this.$rootScope.$on('doneRenderingComponent', (event, args) => {\n if (componentState.nodeId == args.nodeId && componentState.componentId == args.componentId) {\n this.$timeout(() => {\n this.generateImageFromComponentStateHelper(componentState).then((image) => {\n /*\n * Destroy the listener otherwise this block of code will be called every time\n * doneRenderingComponent is fired in the future.\n */\n doneRenderingComponentListener();\n this.$timeout.cancel(destroyDoneRenderingComponentListenerTimeout);\n deferred.resolve(image);\n });\n }, 1000);\n }\n });\n /*\n * Set a timeout to destroy the listener in case there is an error creating the image and\n * we don't get to destroying it above.\n */\n let destroyDoneRenderingComponentListenerTimeout = this.$timeout(() => {\n // destroy the listener\n doneRenderingComponentListener();\n }, 10000);\n return deferred.promise;\n }\n\n /**\n * The component state has been rendered in the DOM and now we want to create an image\n * from it.\n * @param componentState The component state that has been rendered.\n * @return A promise that will return an image.\n */\n generateImageFromComponentStateHelper(componentState) {\n let deferred = this.$q.defer();\n let componentService = this.$injector.get(componentState.componentType + 'Service');\n componentService.generateImageFromRenderedComponentState(componentState).then((image) => {\n deferred.resolve(image);\n this.$mdDialog.hide();\n });\n return deferred.promise;\n }\n\n /**\n * Get the connected component associated with the component state.\n * @param componentContent The component content.\n * @param componentState The component state.\n * @return A connected component object or null.\n */\n getConnectedComponentByComponentState(componentContent, componentState) {\n let nodeId = componentState.nodeId;\n let componentId = componentState.componentId;\n let connectedComponents = componentContent.connectedComponents;\n for (let connectedComponent of connectedComponents) {\n if (connectedComponent.nodeId == nodeId && connectedComponent.componentId == componentId) {\n return connectedComponent;\n }\n }\n return null;\n }\n\n showJSONValidMessage() {\n this.setIsJSONValidMessage(true);\n }\n\n showJSONInvalidMessage() {\n this.setIsJSONValidMessage(false);\n }\n\n hideJSONValidMessage() {\n this.setIsJSONValidMessage(null);\n }\n\n /**\n * Show the message in the toolbar that says \"JSON Valid\" or \"JSON Invalid\".\n * @param isJSONValid\n * true if we want to show \"JSON Valid\"\n * false if we want to show \"JSON Invalid\"\n * null if we don't want to show anything\n */\n setIsJSONValidMessage(isJSONValid) {\n this.$rootScope.$broadcast('setIsJSONValid', { isJSONValid: isJSONValid });\n }\n}\n\n// Get the last element of the array\nif (!Array.prototype.last) {\n Array.prototype.last = function() {\n return this[this.length - 1];\n };\n}\n\nUtilService.$inject = [\n '$filter',\n '$injector',\n '$mdDialog',\n '$q',\n '$rootScope',\n '$timeout'\n];\n\nexport default UtilService;\n"]} \ No newline at end of file From 613ddae48453fe99b2a0e1e4fe3b91563121440b Mon Sep 17 00:00:00 2001 From: Geoffrey Kwan Date: Mon, 21 May 2018 16:09:02 -0700 Subject: [PATCH 4/8] Authoring Tool: Updated the autoSaveProjectJSONString() function to not return anything because we never use the return value. --- .../wise5/authoringTool/project/projectController.es6 | 7 +------ .../wise5/authoringTool/project/projectController.js | 7 +------ .../wise5/authoringTool/project/projectController.js.map | 2 +- 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/main/webapp/wise5/authoringTool/project/projectController.es6 b/src/main/webapp/wise5/authoringTool/project/projectController.es6 index 9d6743e961..97672e914b 100644 --- a/src/main/webapp/wise5/authoringTool/project/projectController.es6 +++ b/src/main/webapp/wise5/authoringTool/project/projectController.es6 @@ -1170,19 +1170,14 @@ class ProjectController { } /** - * Save the project JSON to the server. - * @return {boolean} - * True if the JSON is valid. - * False if the JSON is invalid. + * Save the project JSON to the server if the JSON is valid. */ autoSaveProjectJSONString() { try { this.saveProjectJSON(this.projectJSONString); this.UtilService.showJSONValidMessage(); - return true; } catch(e) { this.UtilService.showJSONInvalidMessage(); - return false; } } diff --git a/src/main/webapp/wise5/authoringTool/project/projectController.js b/src/main/webapp/wise5/authoringTool/project/projectController.js index 9e1b6c1ec3..a80bb1e7ec 100644 --- a/src/main/webapp/wise5/authoringTool/project/projectController.js +++ b/src/main/webapp/wise5/authoringTool/project/projectController.js @@ -1431,10 +1431,7 @@ var ProjectController = function () { } /** - * Save the project JSON to the server. - * @return {boolean} - * True if the JSON is valid. - * False if the JSON is invalid. + * Save the project JSON to the server if the JSON is valid. */ }, { @@ -1443,10 +1440,8 @@ var ProjectController = function () { try { this.saveProjectJSON(this.projectJSONString); this.UtilService.showJSONValidMessage(); - return true; } catch (e) { this.UtilService.showJSONInvalidMessage(); - return false; } } diff --git a/src/main/webapp/wise5/authoringTool/project/projectController.js.map b/src/main/webapp/wise5/authoringTool/project/projectController.js.map index d0527dc152..74ed73303e 100644 --- a/src/main/webapp/wise5/authoringTool/project/projectController.js.map +++ b/src/main/webapp/wise5/authoringTool/project/projectController.js.map @@ -1 +1 @@ -{"version":3,"sources":["projectController.es6"],"names":["ProjectController","$anchorScroll","$filter","$interval","$mdDialog","$q","$rootScope","$scope","$state","$stateParams","$timeout","AuthorWebSocketService","ConfigService","ProjectAssetService","ProjectService","TeacherDataService","UtilService","$translate","projectId","runId","getRunId","items","idToOrder","nodeIds","getFlattenedProjectAsNodeIds","showCreateGroup","showCreateNode","projectTitle","getProjectTitle","inactiveGroupNodes","getInactiveGroupNodes","inactiveStepNodes","getInactiveStepNodes","inactiveNodes","getInactiveNodes","idToNode","getIdToNode","projectScriptFilename","getProjectScriptFilename","currentAuthorsMessage","projectMode","showImportView","importMode","editProjectRubricMode","advancedMode","showJSONAuthoring","stepNodeSelected","activityNodeSelected","stepBackgroundColors","setCurrentNode","metadata","getProjectMetadata","notifyAuthorProjectBegin","summernoteRubricId","summernoteRubricHTML","replaceAssetPaths","getProjectRubric","insertAssetToolTipText","insertAssetButton","createInsertAssetButton","summernoteRubricOptions","toolbar","height","disableDragAndDrop","buttons","projectURL","window","location","origin","getConfigParam","$on","event","args","currentAuthorsUsernames","myUserName","getMyUserName","splice","indexOf","length","currentAuthors","join","notifyAuthorProjectEnd","assetItem","fileName","assetFileName","target","summernoteElement","$","fullAssetPath","getProjectAssetsDirectoryPath","isImage","summernote","isVideo","videoElement","document","createElement","controls","innerHTML","projectScriptFilenameChanged","hide","toState","toParams","fromState","fromParams","stateName","name","saveEvent","refreshProject","scrollToBottomOfPage","previewProjectEventData","constraints","open","go","commitMessage","saveProject","then","commitHistoryArray","commitHistory","val","error","alert","href","getWISEBaseURL","nodeId","getNodePositionById","getComponentsByNodeId","componentId","getPossibleTransitionCriteria","getNodeTitleByNodeId","isGroupNode","unselectAllItems","endCurrentNodeAndSetCurrentNodeByNodeId","nodeToAdd","createGroup","createGroupTitle","insertGroupMode","createMode","createNode","createNodeTitle","insertNodeMode","handleCreateModeInsert","moveMode","handleMoveModeInsert","copyMode","handleCopyModeInsert","importSelectedNodes","moveTo","createNodeInside","createNodeAfter","newNodes","newNode","temporarilyHighlightNewNodes","checkPotentialStartNodeIdChangeThenSaveProject","nodeCreatedEventData","id","getNodePositionAndTitleByNodeId","selectedNodeIds","getSelectedNodeIds","movedNodes","selectedNodeId","node","push","moveNodesInside","moveNodesAfter","firstNewNode","n","toTitle","nodeMovedEventData","activitiesMoved","stepsMoved","copiedNodes","copyNodesInside","copyNodesAfter","toNodeId","nodeCopiedEventData","activitiesCopied","stepsCopied","nodeIdToInsertInsideOrAfter","selectedNodes","getSelectedNodesToImport","selectedNodeTitles","getSelectedNodeTitlesToImport","toProjectId","fromProjectId","importProjectId","performImport","doScrollToNewNodes","stepsImported","selectedNode","selectedNodeTitle","stepImported","parseInt","fromNodeId","fromTitle","stepsImportedEventData","copyNodes","toggleView","importProjectIdToOrder","importProjectItems","importMyProjectId","importLibraryProjectId","importProject","showProjectHome","retrieveProjectAssets","selectedItemTypes","getSelectedItemTypes","confirmMessage","numItems","confirm","deletedStartNodeId","activityDeleted","stepDeleted","stepsDeleted","activitiesDeleted","getNodeById","tempNode","title","isStartNodeId","stepsInActivityDeleted","ids","stepNodeId","stepTitle","stepObject","deleteNode","updateStartNodeId","activitiesDeletedEventData","stepDeletedEventData","angular","forEach","value","key","checked","inactiveNode","nodeType","type","inactiveNodeType","focus","newStartNodeId","startGroupId","getStartGroupId","done","startId","isApplicationNode","setStartNodeId","resolve","reject","firstLeafNodeId","getFirstLeafNodeId","currentStartNodeId","getStartNodeId","checkPotentialStartNodeIdChange","parseProject","setProjectTitle","myProjectsList","getAuthorableProjects","libraryProjectsList","getLibraryProjects","showImportProject","retrieveProjectById","projectJSON","nodeOrderOfProject","getNodeOrderOfProject","nodes","previewProjectURL","previewStepURL","item","isJSONValid","toggleJSONAuthoringView","hideJSONValidMessage","answer","projectJSONString","toJson","project","showJSONValidMessage","fromJson","e","saveProjectJSON","showJSONInvalidMessage","setProject","scriptFilename","html","removeAbsoluteAssetPaths","insertWISELinks","setProjectRubric","isNodeInAnyBranchPath","setProjectScriptFilename","openAssetChooserParams","popup","$broadcast","view","scrollToTopOfPage","animate","scrollTop","prop","temporarilyHighlightElement","firstNodeElementAdded","eventName","category","data","context","componentType","stepNumber","color","branchPathLetter","getBranchPathLetter","letterASCIICode","charCodeAt","branchPathNumber","textArea","body","appendChild","select","execCommand","removeChild","count","getParentGroup","isBranchPoint","getNumberOfBranchPaths","getBranchCriteriaDescription","nodeHasConstraint","getConstraintsOnNode","constraintDescriptions","c","constraint","description","getConstraintDescription","nodeHasRubric","$inject"],"mappings":"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","file":"projectController.js","sourcesContent":["'use strict';\n\nclass ProjectController {\n\n constructor(\n $anchorScroll,\n $filter,\n $interval,\n $mdDialog,\n $q,\n $rootScope,\n $scope,\n $state,\n $stateParams,\n $timeout,\n AuthorWebSocketService,\n ConfigService,\n ProjectAssetService,\n ProjectService,\n TeacherDataService,\n UtilService) {\n this.$anchorScroll = $anchorScroll;\n this.$filter = $filter;\n this.$interval = $interval;\n this.$mdDialog = $mdDialog;\n this.$q = $q;\n this.$rootScope = $rootScope;\n this.$scope = $scope;\n this.$state = $state;\n this.$stateParams = $stateParams;\n this.$timeout = $timeout;\n this.$translate = this.$filter('translate');\n this.AuthorWebSocketService = AuthorWebSocketService;\n this.ConfigService = ConfigService;\n this.ProjectAssetService = ProjectAssetService;\n this.ProjectService = ProjectService;\n this.TeacherDataService = TeacherDataService;\n this.UtilService = UtilService;\n\n this.projectId = this.$stateParams.projectId;\n this.runId = this.ConfigService.getRunId();\n this.items = this.ProjectService.idToOrder;\n this.nodeIds = this.ProjectService.getFlattenedProjectAsNodeIds();\n this.showCreateGroup = false;\n this.showCreateNode = false;\n this.projectTitle = this.ProjectService.getProjectTitle();\n this.inactiveGroupNodes = this.ProjectService.getInactiveGroupNodes();\n this.inactiveStepNodes = this.ProjectService.getInactiveStepNodes();\n this.inactiveNodes = this.ProjectService.getInactiveNodes();\n this.idToNode = this.ProjectService.getIdToNode();\n this.projectScriptFilename = this.ProjectService.getProjectScriptFilename();\n this.currentAuthorsMessage = '';\n this.projectMode = true;\n this.showCreateGroup = false;\n this.showCreateNode = false;\n this.showImportView = false;\n this.importMode = false;\n this.editProjectRubricMode = false;\n this.advancedMode = false;\n this.showJSONAuthoring = false;\n\n // whether there are any step nodes checked\n this.stepNodeSelected = false;\n\n // whether there are any activity nodes checked\n this.activityNodeSelected = false;\n\n /*\n * The colors for the branch path steps. The colors are from\n * http://colorbrewer2.org/\n * http://colorbrewer2.org/export/colorbrewer.js\n * The colors chosen are from the 'qualitative', 'Set2'.\n */\n this.stepBackgroundColors = ['#66c2a5','#fc8d62','#8da0cb','#e78ac3',\n '#a6d854','#ffd92f','#e5c494','#b3b3b3'];\n\n // start by opening the project, with no node being authored\n this.TeacherDataService.setCurrentNode(null);\n\n this.metadata = this.ProjectService.getProjectMetadata();\n this.ProjectService.notifyAuthorProjectBegin(this.projectId);\n this.summernoteRubricId = 'summernoteRubric_' + this.projectId;\n this.summernoteRubricHTML = this.ProjectService\n .replaceAssetPaths(this.ProjectService.getProjectRubric());\n\n let insertAssetToolTipText = this.$translate('INSERT_ASSET');\n let insertAssetButton = this.UtilService.createInsertAssetButton(this,\n this.projectId, null, null, 'rubric', insertAssetToolTipText);\n\n // options to display in the summernote tool\n this.summernoteRubricOptions = {\n toolbar: [\n ['style', ['style']],\n ['font', ['bold', 'underline', 'clear']],\n ['fontname', ['fontname']],\n ['fontsize', ['fontsize']],\n ['color', ['color']],\n ['para', ['ul', 'ol', 'paragraph']],\n ['table', ['table']],\n ['insert', ['link', 'video']],\n ['view', ['fullscreen', 'codeview', 'help']],\n ['customButton', ['insertAssetButton']]\n ],\n height: 300,\n disableDragAndDrop: true,\n buttons: {\n 'insertAssetButton': insertAssetButton\n }\n };\n\n this.projectURL = window.location.origin + this.ConfigService.getConfigParam('projectURL');\n\n this.$scope.$on('currentAuthorsReceived', (event, args) => {\n let currentAuthorsUsernames = args.currentAuthorsUsernames;\n let myUserName = this.ConfigService.getMyUserName();\n currentAuthorsUsernames\n .splice(currentAuthorsUsernames.indexOf(myUserName), 1);\n if (currentAuthorsUsernames.length > 0) {\n this.currentAuthorsMessage = this.$translate('concurrentAuthorsWarning',\n { currentAuthors: currentAuthorsUsernames.join(', ') });\n } else {\n this.currentAuthorsMessage = '';\n }\n });\n\n this.$scope.$on('$destroy', () => {\n this.ProjectService.notifyAuthorProjectEnd(this.projectId);\n });\n\n /*\n * Listen for the assetSelected event which occurs when the author\n * selects an asset from the choose asset popup to add to project rubric\n * or choosing the script file.\n */\n this.$scope.$on('assetSelected', (event, args) => {\n if (args != null && args.projectId == this.projectId &&\n args.assetItem != null && args.assetItem.fileName != null) {\n let assetFileName = args.assetItem.fileName;\n if (args.target === 'rubric') {\n let summernoteElement = $('#summernoteRubric_' + this.projectId);\n let fullAssetPath =\n this.ConfigService.getProjectAssetsDirectoryPath() +\n '/' + assetFileName;\n if (this.UtilService.isImage(assetFileName)) {\n /*\n * move the cursor back to its position when the asset chooser\n * popup was clicked\n */\n summernoteElement.summernote('editor.restoreRange');\n summernoteElement.summernote('editor.focus');\n summernoteElement.summernote(\n 'insertImage', fullAssetPath, assetFileName);\n } else if (this.UtilService.isVideo(assetFileName)) {\n /*\n * move the cursor back to its position when the asset chooser\n * popup was clicked\n */\n summernoteElement.summernote('editor.restoreRange');\n summernoteElement.summernote('editor.focus');\n let videoElement = document.createElement('video');\n videoElement.controls = 'true';\n videoElement.innerHTML =\n '';\n summernoteElement.summernote('insertNode', videoElement);\n }\n } else if (args.target === 'scriptFilename') {\n this.projectScriptFilename = assetFileName;\n this.projectScriptFilenameChanged();\n }\n }\n this.$mdDialog.hide();\n });\n\n this.$rootScope.$on('$stateChangeSuccess',\n (event, toState, toParams, fromState, fromParams) => {\n if (toState != null) {\n let stateName = toState.name;\n if (stateName == 'root.project') {\n this.saveEvent('projectHomeViewOpened', 'Navigation');\n } else if (stateName == 'root.project.node') {\n } else if (stateName == 'root.project.asset') {\n this.saveEvent('assetsViewOpened', 'Navigation');\n } else if (stateName == 'root.project.info') {\n this.saveEvent('projectInfoViewOpened', 'Navigation');\n } else if (stateName == 'root.project.notebook') {\n this.saveEvent('notebookViewOpened', 'Navigation');\n }\n }\n });\n\n this.$rootScope.$on('projectSaved', () => {\n //this.saveEvent('projectSaved', 'Authoring');\n });\n\n /*\n * Listen for the event to parse the project. This is so other\n * controllers can trigger parsing the project in this controller.\n */\n this.$rootScope.$on('parseProject', () => {\n this.refreshProject();\n });\n\n this.$rootScope.$on('scrollToBottom', () => {\n this.scrollToBottomOfPage();\n });\n\n this.saveEvent('projectOpened', 'Navigation');\n };\n\n /**\n * Launch the project in preview mode in a new tab\n */\n previewProject() {\n let previewProjectEventData = { constraints: true };\n this.saveEvent('projectPreviewed', 'Navigation', previewProjectEventData);\n window.open(this.ConfigService.getConfigParam('previewProjectURL'));\n };\n\n /**\n * Launch the project in preview mode without constraints in a new tab\n */\n previewProjectWithoutConstraints() {\n let previewProjectEventData = { constraints: false };\n this.saveEvent('projectPreviewed', 'Navigation', previewProjectEventData);\n window.open(this.ConfigService.getConfigParam('previewProjectURL') +\n '?constraints=false');\n };\n\n viewProjectAssets() {\n this.$state.go('root.project.asset', {projectId: this.projectId});\n };\n\n viewProjectHistory() {\n this.$state.go('root.project.history', {projectId: this.projectId});\n };\n\n viewNotebookSettings() {\n this.$state.go('root.project.notebook', {projectId: this.projectId});\n }\n\n saveProject() {\n let commitMessage = 'Made changes to the project.';\n try {\n // if projectJSONString is bad json,\n // an exception will be thrown and it will not save.\n this.ProjectService.saveProject(commitMessage)\n .then((commitHistoryArray) => {\n this.commitHistory = commitHistoryArray;\n $('#commitMessageInput').val('');\n });\n } catch (error) {\n // TODO: i18n\n alert('Invalid JSON. Please check syntax. Aborting save.');\n return;\n }\n };\n\n /**\n * Make a request to download this project as a zip file\n */\n downloadProject() {\n window.location.href = this.ConfigService.getWISEBaseURL()\n + '/project/export/' + this.projectId;\n }\n\n /**\n * Close authoring for the current project and bring user back to main AT page\n */\n closeProject() {\n this.$state.go('root.main');\n };\n\n /**\n * Get the node position\n * @param nodeId the node id\n * @returns the node position\n */\n getNodePositionById(nodeId) {\n return this.ProjectService.getNodePositionById(nodeId);\n };\n\n /**\n * Get the components that are in the specified node id.\n * @param nodeId the node id\n * @returns components in the node\n */\n getComponentsByNodeId(nodeId) {\n return this.ProjectService.getComponentsByNodeId(nodeId);\n }\n\n /**\n * Returns a list of possible criteria for the specified node and component\n * @param nodeId the node id\n * @param componentId the component id in the node\n */\n getPossibleTransitionCriteria(nodeId, componentId) {\n return this.ProjectService\n .getPossibleTransitionCriteria(nodeId, componentId);\n }\n\n /**\n * Get the node title for a node\n * @param nodeId the node id\n * @returns the node title\n */\n getNodeTitleByNodeId(nodeId) {\n return this.ProjectService.getNodeTitleByNodeId(nodeId);\n };\n\n /**\n * Check if a node id is for a group\n * @param nodeId\n * @returns whether the node is a group node\n */\n isGroupNode(nodeId) {\n return this.ProjectService.isGroupNode(nodeId);\n };\n\n /**\n * A node was clicked so we will go to the node authoring view\n * @param nodeId\n */\n nodeClicked(nodeId) {\n this.unselectAllItems();\n this.TeacherDataService\n .endCurrentNodeAndSetCurrentNodeByNodeId(this.nodeId);\n this.$state\n .go('root.project.node', {projectId: this.projectId, nodeId: nodeId});\n };\n\n /**\n * The constraint icon on a step in the project view was clicked.\n * We will open the constraint view for the step.\n * @param nodeId The node id of the step.\n */\n constraintIconClicked(nodeId) {\n this.TeacherDataService\n .endCurrentNodeAndSetCurrentNodeByNodeId(nodeId);\n this.$state\n .go('root.project.nodeConstraints', {projectId: this.projectId, nodeId: nodeId});\n }\n\n /**\n * The branch icon on a step in the project view was clicked.\n * We will open the transitions view for the step.\n * @param nodeId The node id of the step.\n */\n branchIconClicked(nodeId) {\n this.TeacherDataService\n .endCurrentNodeAndSetCurrentNodeByNodeId(nodeId);\n this.$state\n .go('root.project.nodeEditPaths', {projectId: this.projectId, nodeId: nodeId});\n }\n\n /**\n * Create a new group (activity)\n */\n createGroup() {\n /*\n * set the group into this variable to hold it temporarily while the\n * author decides where to place it\n */\n this.nodeToAdd = this.ProjectService.createGroup(this.createGroupTitle);\n\n this.showCreateGroup = false;\n this.createGroupTitle = '';\n this.insertGroupMode = true;\n this.createMode = true;\n }\n\n /**\n * Create a new node (step)\n */\n createNode() {\n /*\n * set the node into this variable to hold it temporarily while the\n * author decides where to place it\n */\n this.nodeToAdd = this.ProjectService.createNode(this.createNodeTitle);\n\n this.showCreateNode = false;\n this.createNodeTitle = '';\n this.insertNodeMode = true;\n this.createMode = true;\n }\n\n /**\n * Insert the node(s) inside\n * @param nodeId the node id of the group that we will insert into\n */\n insertInside(nodeId) {\n // TODO check that we are inserting into a group\n if (this.createMode) {\n this.handleCreateModeInsert(nodeId, 'inside');\n } else if (this.moveMode) {\n this.handleMoveModeInsert(nodeId, 'inside');\n } else if (this.copyMode) {\n this.handleCopyModeInsert(nodeId, 'inside');\n } else if (this.importMode) {\n this.importSelectedNodes(nodeId);\n }\n }\n\n /**\n * Insert the node(s) after\n * @param nodeId the node id of the node we will insert after\n */\n insertAfter(nodeId) {\n if (this.createMode) {\n this.handleCreateModeInsert(nodeId, 'after');\n } else if (this.moveMode) {\n this.handleMoveModeInsert(nodeId, 'after');\n } else if (this.copyMode) {\n this.handleCopyModeInsert(nodeId, 'after');\n } else if (this.importMode) {\n this.importSelectedNodes(nodeId);\n }\n }\n\n /**\n * Create a node and then insert it in the specified location\n * @param nodeId insert the new node inside or after this node id\n * @param moveTo whether to insert 'inside' or 'after' the nodeId parameter\n */\n handleCreateModeInsert(nodeId, moveTo) {\n if (moveTo === 'inside') {\n this.ProjectService.createNodeInside(this.nodeToAdd, nodeId);\n } else if (moveTo === 'after') {\n this.ProjectService.createNodeAfter(this.nodeToAdd, nodeId);\n } else {\n // an unspecified moveTo was provided\n return;\n }\n\n let newNodes = [this.nodeToAdd];\n let newNode = this.nodeToAdd;\n\n /*\n * clear this variable that we used to hold the node we inserted.\n * since we have inserted the node we don't need a handle to it\n * anymore\n */\n this.nodeToAdd = null;\n\n this.createMode = false;\n this.insertGroupMode = false;\n this.insertNodeMode = false;\n this.temporarilyHighlightNewNodes(newNodes);\n\n this.checkPotentialStartNodeIdChangeThenSaveProject().then(() => {\n if (newNode != null) {\n let nodeCreatedEventData = {\n 'nodeId': newNode.id,\n 'title': this.ProjectService\n .getNodePositionAndTitleByNodeId(newNode.id)\n };\n\n if (this.ProjectService.isGroupNode(newNode.id)) {\n this.saveEvent('activityCreated', 'Authoring', nodeCreatedEventData);\n } else {\n this.saveEvent('stepCreated', 'Authoring', nodeCreatedEventData);\n }\n }\n });\n }\n\n /**\n * Move a node and insert it in the specified location\n * @param nodeId insert the new node inside or after this node id\n * @param moveTo whether to insert 'inside' or 'after' the nodeId parameter\n */\n handleMoveModeInsert(nodeId, moveTo) {\n let selectedNodeIds = this.getSelectedNodeIds();\n if (selectedNodeIds != null && selectedNodeIds.indexOf(nodeId) != -1) {\n /*\n * the user is trying to insert the selected node ids after\n * itself so we will not allow that\n */\n if (selectedNodeIds.length == 1) {\n alert(this\n .$translate('youAreNotAllowedToInsertTheSelectedItemAfterItself'));\n } else if (selectedNodeIds.length > 1) {\n alert(this\n .$translate('youAreNotAllowedToInsertTheSelectedItemsAfterItself'));\n }\n } else {\n let movedNodes = [];\n for (let selectedNodeId of selectedNodeIds) {\n let node = {\n 'nodeId': selectedNodeId,\n 'fromTitle': this.ProjectService\n .getNodePositionAndTitleByNodeId(selectedNodeId)\n };\n movedNodes.push(node);\n }\n\n let newNodes = [];\n if (moveTo === 'inside') {\n newNodes = this.ProjectService.moveNodesInside(selectedNodeIds, nodeId);\n } else if (moveTo === 'after') {\n newNodes = this.ProjectService.moveNodesAfter(selectedNodeIds, nodeId);\n } else {\n // an unspecified moveTo was provided\n return;\n }\n\n this.moveMode = false;\n this.insertGroupMode = false;\n this.insertNodeMode = false;\n this.temporarilyHighlightNewNodes(newNodes);\n this.checkPotentialStartNodeIdChangeThenSaveProject().then(() => {\n if (newNodes != null && newNodes.length > 0) {\n let firstNewNode = newNodes[0];\n if (firstNewNode != null && firstNewNode.id != null) {\n for (let n = 0; n < movedNodes.length; n++) {\n let node = movedNodes[n];\n let newNode = newNodes[n];\n if (node != null && newNode != null) {\n node.toTitle = this.ProjectService\n .getNodePositionAndTitleByNodeId(newNode.id);\n }\n }\n\n if (this.ProjectService.isGroupNode(firstNewNode.id)) {\n let nodeMovedEventData = { activitiesMoved: movedNodes };\n this.saveEvent('activityMoved', 'Authoring', nodeMovedEventData);\n } else {\n let nodeMovedEventData = { stepsMoved: movedNodes };\n this.saveEvent('stepMoved', 'Authoring', nodeMovedEventData);\n }\n }\n }\n });\n }\n }\n\n /**\n * Copy a node and insert it in the specified location\n * @param nodeId insert the new node inside or after this node id\n * @param moveTo whether to insert 'inside' or 'after' the nodeId parameter\n */\n handleCopyModeInsert(nodeId, moveTo) {\n let copiedNodes = [];\n let selectedNodeIds = this.getSelectedNodeIds();\n for (let selectedNodeId of selectedNodeIds) {\n let node = {\n 'fromNodeId': selectedNodeId,\n 'fromTitle': this.ProjectService\n .getNodePositionAndTitleByNodeId(selectedNodeId)\n };\n copiedNodes.push(node);\n }\n\n let newNodes = [];\n if (moveTo === 'inside') {\n newNodes = this.ProjectService.copyNodesInside(selectedNodeIds, nodeId);\n } else if (moveTo === 'after') {\n newNodes = this.ProjectService.copyNodesAfter(selectedNodeIds, nodeId);\n } else {\n // an unspecified moveTo was provided\n return;\n }\n\n this.copyMode = false;\n this.insertGroupMode = false;\n this.insertNodeMode = false;\n this.temporarilyHighlightNewNodes(newNodes);\n this.checkPotentialStartNodeIdChangeThenSaveProject().then(() => {\n if (newNodes != null && newNodes.length > 0) {\n let firstNewNode = newNodes[0];\n if (firstNewNode != null && firstNewNode.id != null) {\n for (let n = 0; n < copiedNodes.length; n++) {\n let node = copiedNodes[n];\n let newNode = newNodes[n];\n if (node != null && newNode != null) {\n node.toNodeId = newNode.id;\n node.toTitle = this.ProjectService\n .getNodePositionAndTitleByNodeId(newNode.id);\n }\n }\n\n if (this.ProjectService.isGroupNode(firstNewNode.id)) {\n let nodeCopiedEventData = { activitiesCopied: copiedNodes };\n this.saveEvent('activityCopied', 'Authoring', nodeCopiedEventData);\n } else {\n let nodeCopiedEventData = { stepsCopied: copiedNodes };\n this.saveEvent('stepCopied', 'Authoring', nodeCopiedEventData);\n }\n }\n }\n });\n }\n\n /**\n * Import the selected steps and draw attention to them by highlighting them\n * and scrolling to them.\n * @param nodeIdToInsertInsideOrAfter If this is a group, we will make the\n * new step the first step in the group. If this is a step, we will place\n * the new step after it.\n */\n importSelectedNodes(nodeIdToInsertInsideOrAfter) {\n let selectedNodes = this.getSelectedNodesToImport();\n let selectedNodeTitles = this.getSelectedNodeTitlesToImport();\n let toProjectId = this.ConfigService.getConfigParam('projectId');\n let fromProjectId = this.importProjectId;\n\n this.performImport(nodeIdToInsertInsideOrAfter).then((newNodes) => {\n this.checkPotentialStartNodeIdChangeThenSaveProject().then(() => {\n let doScrollToNewNodes = true;\n this.temporarilyHighlightNewNodes(newNodes, doScrollToNewNodes);\n\n let stepsImported = [];\n for (let n = 0; n < selectedNodes.length; n++) {\n let selectedNode = selectedNodes[n];\n let selectedNodeTitle = selectedNodeTitles[n];\n let newNode = newNodes[n];\n\n let stepImported = {\n fromProjectId: parseInt(fromProjectId),\n fromNodeId: selectedNode.id,\n fromTitle: selectedNodeTitle,\n toNodeId: newNode.id,\n toTitle: this.ProjectService\n .getNodePositionAndTitleByNodeId(newNode.id)\n };\n stepsImported.push(stepImported);\n }\n\n let stepsImportedEventData = { 'stepsImported': stepsImported };\n this.saveEvent('stepImported', 'Authoring', stepsImportedEventData);\n });\n });\n }\n\n /**\n * Import the step and place it in the chosen location\n * @param nodeIdToInsertInsideOrAfter If this is a group, we will make the\n * new step the first step in the group. If this is a step, we will place\n * the new step after it.\n */\n performImport(nodeIdToInsertInsideOrAfter) {\n let selectedNodes = this.getSelectedNodesToImport();\n let toProjectId = this.ConfigService.getConfigParam('projectId');\n let fromProjectId = this.importProjectId;\n\n return this.ProjectService.copyNodes(selectedNodes, fromProjectId,\n toProjectId, nodeIdToInsertInsideOrAfter).then((newNodes) => {\n this.refreshProject();\n this.insertNodeMode = false;\n this.toggleView('project');\n\n this.importProjectIdToOrder = {};\n this.importProjectItems = [];\n this.importMyProjectId = null;\n this.importLibraryProjectId = null;\n this.importProjectId = null;\n this.importProject = null;\n\n /*\n * go back to the project view and\n * refresh the project assets in case any of the imported\n * steps also imported assets\n */\n this.showProjectHome();\n this.ProjectAssetService.retrieveProjectAssets();\n return newNodes;\n });\n }\n\n /**\n * Turn on copy mode\n */\n copy() {\n // make sure there is at least one item selected\n let selectedNodeIds = this.getSelectedNodeIds();\n if (selectedNodeIds == null || selectedNodeIds.length == 0) {\n alert(this.$translate('pleaseSelectAnItemToCopyAndThenClickTheCopyButtonAgain'));\n } else {\n let selectedItemTypes = this.getSelectedItemTypes();\n if (selectedItemTypes.length === 1 && selectedItemTypes[0] === 'node') {\n this.insertNodeMode = true;\n this.copyMode = true;\n } else if (selectedItemTypes.length === 1 && selectedItemTypes[0] === 'group') {\n alert(this.$translate('youCannotCopyActivitiesAtThisTime'));\n }\n }\n }\n\n /**\n * Turn on move mode\n * TODO refactor. too many nesting. Rename function to \"turnOnMoveMode\"?\n */\n move() {\n // make sure there is at least one item selected\n let selectedNodeIds = this.getSelectedNodeIds();\n if (selectedNodeIds == null || selectedNodeIds.length == 0) {\n alert(this.$translate('pleaseSelectAnItemToMoveAndThenClickTheMoveButtonAgain'));\n } else {\n let selectedItemTypes = this.getSelectedItemTypes();\n if (selectedItemTypes.length === 1 && selectedItemTypes[0] === 'node') {\n this.insertNodeMode = true;\n this.moveMode = true;\n } else if (selectedItemTypes.length === 1 && selectedItemTypes[0] === 'group') {\n this.insertGroupMode = true;\n this.moveMode = true;\n }\n }\n }\n\n /**\n * Delete the selected nodes after asking user for confirmation\n * TODO refactor too many nesting\n */\n delete() {\n let selectedNodeIds = this.getSelectedNodeIds();\n if (selectedNodeIds == null || selectedNodeIds.length == 0) {\n alert(this.$translate('pleaseSelectAnItemToDeleteAndThenClickTheDeleteButtonAgain'));\n } else {\n let confirmMessage = '';\n if (selectedNodeIds.length == 1) {\n confirmMessage = this.$translate('areYouSureYouWantToDeleteTheSelectedItem');\n } else if (selectedNodeIds.length > 1) {\n confirmMessage = this.$translate('areYouSureYouWantToDeleteTheXSelectedItems',\n { numItems: selectedNodeIds.length });\n }\n if (confirm(confirmMessage)) {\n let deletedStartNodeId = false;\n let activityDeleted = false;\n let stepDeleted = false;\n let stepsDeleted = [];\n let activitiesDeleted = [];\n for (let nodeId of selectedNodeIds) {\n let node = this.ProjectService.getNodeById(nodeId);\n let tempNode = {};\n\n if (node != null) {\n tempNode.nodeId = node.id;\n tempNode.title =\n this.ProjectService.getNodePositionAndTitleByNodeId(node.id);\n }\n\n if (this.ProjectService.isStartNodeId(nodeId)) {\n deletedStartNodeId = true;\n }\n\n if (this.ProjectService.isGroupNode(nodeId)) {\n activityDeleted = true;\n let stepsInActivityDeleted = [];\n for (let stepNodeId of node.ids) {\n let stepTitle = this.ProjectService\n .getNodePositionAndTitleByNodeId(stepNodeId);\n\n // create an object with the step id and title\n let stepObject = {\n 'nodeId': stepNodeId,\n 'title': stepTitle\n };\n stepsInActivityDeleted.push(stepObject);\n }\n tempNode.stepsInActivityDeleted = stepsInActivityDeleted;\n activitiesDeleted.push(tempNode);\n } else {\n stepDeleted = true;\n stepsDeleted.push(tempNode);\n }\n this.ProjectService.deleteNode(nodeId);\n }\n\n if (deletedStartNodeId) {\n this.updateStartNodeId();\n }\n\n if (activityDeleted) {\n let activitiesDeletedEventData = {\n 'activitiesDeleted': activitiesDeleted\n };\n this.saveEvent('activityDeleted', 'Authoring',\n activitiesDeletedEventData);\n }\n\n if (stepDeleted) {\n let stepDeletedEventData = {\n 'stepsDeleted': stepsDeleted\n };\n this.saveEvent('stepDeleted', 'Authoring', stepDeletedEventData);\n }\n\n this.ProjectService.saveProject();\n this.refreshProject();\n }\n }\n }\n\n /**\n * Get the ids of the selected nodes, both active and inactive.\n * @returns an array of node ids that are selected\n */\n getSelectedNodeIds() {\n let selectedNodeIds = [];\n angular.forEach(this.items, function(value, key) {\n if (value.checked) {\n selectedNodeIds.push(key);\n }\n }, selectedNodeIds);\n\n if (this.inactiveNodes != null) {\n for (let inactiveNode of this.inactiveNodes) {\n if (inactiveNode != null && inactiveNode.checked) {\n selectedNodeIds.push(inactiveNode.id);\n }\n }\n }\n return selectedNodeIds;\n }\n\n /**\n * Get the distinct types of the selected items, both active and inactive.\n * @returns an array of item types. possible items are group or node.\n */\n getSelectedItemTypes() {\n let selectedItemTypes = [];\n\n angular.forEach(this.items, function(value, key) {\n if (value.checked) {\n let node = this.ProjectService.getNodeById(key);\n if (node != null) {\n let nodeType = node.type;\n if (selectedItemTypes.indexOf(nodeType) == -1) {\n selectedItemTypes.push(nodeType);\n }\n }\n }\n }, this);\n\n if (this.inactiveNodes != null) {\n for (let inactiveNode of this.inactiveNodes) {\n if (inactiveNode != null && inactiveNode.checked) {\n let inactiveNodeType = inactiveNode.type;\n if (selectedItemTypes.indexOf(inactiveNodeType) == -1) {\n selectedItemTypes.push(inactiveNodeType);\n }\n }\n }\n }\n\n return selectedItemTypes;\n }\n\n unselectAllItems() {\n angular.forEach(this.items, function(value, key) {\n value.checked = false;\n });\n angular.forEach(this.inactiveGroupNodes, function(value, key) {\n value.checked = false;\n });\n angular.forEach(this.inactiveStepNodes, function(value, key) {\n value.checked = false;\n });\n this.stepNodeSelected = false;\n this.activityNodeSelected = false;\n }\n\n /**\n * Toggle the create group input\n */\n creatNewActivityClicked() {\n this.createGroupTitle = '';\n this.toggleView('createGroup');\n if (this.showCreateGroup) {\n this.$timeout(() => {\n $('#createGroupTitle').focus();\n });\n }\n }\n\n /**\n * Toggle the create node input\n */\n createNewStepClicked() {\n this.createNodeTitle = '';\n this.toggleView('createNode');\n if (this.showCreateNode) {\n this.$timeout(() => {\n $('#createNodeTitle').focus();\n });\n }\n }\n\n /**\n * Cancel the move mode\n */\n cancelMove() {\n this.insertGroupMode = false;\n this.insertNodeMode = false;\n this.nodeToAdd = null;\n this.createMode = false;\n this.moveMode = false;\n this.copyMode = false;\n this.importMode = false;\n this.unselectAllItems();\n }\n\n /**\n * Update the start node id by traversing start ids until a\n * node id is found.\n */\n updateStartNodeId() {\n let newStartNodeId = null;\n let startGroupId = this.ProjectService.getStartGroupId();\n let node = this.ProjectService.getNodeById(startGroupId);\n let done = false;\n\n // recursively traverse the start ids\n while (!done) {\n if (node == null) {\n // base case in case something went wrong\n done = true;\n } else if (this.ProjectService.isGroupNode(node.id)) {\n // the node is a group node so we will get its start node\n node = this.ProjectService.getNodeById(node.startId);\n } else if (this.ProjectService.isApplicationNode(node.id)) {\n // the node is a step node so we have found the new start node id\n newStartNodeId = node.id;\n done = true;\n } else {\n // base case in case something went wrong\n done = true;\n }\n }\n\n if (newStartNodeId) {\n this.ProjectService.setStartNodeId(newStartNodeId);\n }\n }\n\n /**\n * Check if the start node id for the project could potentially\n * change.\n */\n checkPotentialStartNodeIdChange() {\n return this.$q((resolve, reject) => {\n let firstLeafNodeId = this.ProjectService.getFirstLeafNodeId();\n if (firstLeafNodeId == null) {\n // there are no steps in the project\n // set the start node id to empty string\n this.ProjectService.setStartNodeId('');\n resolve();\n } else {\n // we have found a leaf node\n let currentStartNodeId = this.ProjectService.getStartNodeId();\n if (currentStartNodeId != firstLeafNodeId) {\n // update the start node id\n this.ProjectService.setStartNodeId(firstLeafNodeId);\n resolve();\n } else {\n resolve();\n }\n }\n });\n }\n\n /**\n * Check if the start node id has changed and then save the project\n */\n checkPotentialStartNodeIdChangeThenSaveProject() {\n return this.checkPotentialStartNodeIdChange().then(() => {\n this.ProjectService.saveProject();\n this.refreshProject();\n });\n }\n\n /**\n * Recalculates step numbering\n */\n refreshProject() {\n /*\n * Use a timeout before we refresh the project in order to allow the\n * spinning progress indicator to show up before the browser starts\n * blocking/freezing.\n */\n this.$timeout(() => {\n this.ProjectService.parseProject();\n this.items = this.ProjectService.idToOrder;\n this.inactiveGroupNodes = this.ProjectService.getInactiveGroupNodes();\n this.inactiveStepNodes = this.ProjectService.getInactiveStepNodes();\n this.inactiveNodes = this.ProjectService.getInactiveNodes();\n this.idToNode = this.ProjectService.getIdToNode();\n this.unselectAllItems();\n });\n }\n\n /**\n * The project title changed so we will update the project title in the\n * project service and save the project\n */\n projectTitleChanged() {\n this.ProjectService.setProjectTitle(this.projectTitle);\n this.ProjectService.saveProject();\n }\n\n /**\n * Toggle the import view and populate the project drop downs if necessary\n */\n importStepClicked() {\n this.toggleView('importStep');\n\n if (this.importMode) {\n if (this.myProjectsList == null) {\n this.myProjectsList = this.ConfigService.getAuthorableProjects();\n }\n\n if (this.libraryProjectsList == null) {\n this.ConfigService.getLibraryProjects().then((libraryProjectsList) => {\n this.libraryProjectsList = libraryProjectsList;\n });\n }\n }\n }\n\n /**\n * The author has chosen an authorable project to import from\n * @param importProjectId the project id to import from\n */\n showMyImportProject(importProjectId) {\n this.importLibraryProjectId = null;\n this.showImportProject(importProjectId);\n }\n\n /**\n * The author has chosen a library project to import from\n * @param importProjectId the project id to import from\n */\n showLibraryImportProject(importProjectId) {\n this.importMyProjectId = null;\n this.showImportProject(importProjectId);\n }\n\n /**\n * Show the project we want to import steps from\n * @param importProjectId the import project id\n */\n showImportProject(importProjectId) {\n this.importProjectId = importProjectId;\n if (this.importProjectId == null) {\n // clear all the import project values\n this.importProjectIdToOrder = {};\n this.importProjectItems = [];\n this.importMyProjectId = null;\n this.importLibraryProjectId = null;\n this.importProjectId = null;\n this.importProject = null;\n } else {\n this.ProjectService.retrieveProjectById(this.importProjectId)\n .then((projectJSON) => {\n this.importProject = projectJSON;\n const nodeOrderOfProject = this.ProjectService\n .getNodeOrderOfProject(this.importProject);\n this.importProjectIdToOrder = nodeOrderOfProject.idToOrder;\n this.importProjectItems = nodeOrderOfProject.nodes;\n });\n }\n }\n\n /**\n * Preview the import project in a new tab\n */\n previewImportProject() {\n if (this.importProject != null) {\n window.open(this.importProject.previewProjectURL);\n }\n }\n\n /**\n * Preview the import step in a new tab\n * @param node\n */\n previewImportNode(node) {\n if (node != null) {\n const nodeId = node.id;\n const previewProjectURL = this.importProject.previewProjectURL;\n const previewStepURL = previewProjectURL + '#/vle/' + nodeId;\n window.open(previewStepURL);\n }\n }\n\n /**\n * Import the selected steps\n */\n importSteps() {\n let selectedNodes = this.getSelectedNodesToImport();\n if (selectedNodes == null || selectedNodes.length == 0) {\n // TODO i18n\n alert('Please select a step to import.');\n } else {\n /*\n * hide the import view because we want to go back to the\n * project view so that the author can choose where to place\n * the new steps\n */\n this.showImportView = false;\n this.insertNodeMode = true;\n this.projectMode = true;\n }\n }\n\n /**\n * Get the selected nodes to import\n * @return an array of selected nodes\n */\n getSelectedNodesToImport() {\n let selectedNodes = [];\n for (let item of this.importProjectItems) {\n if (item.checked) {\n selectedNodes.push(item.node);\n }\n }\n return selectedNodes;\n }\n\n /**\n * Show the view to edit the project rubric\n */\n editProjectRubricClicked() {\n this.toggleView('rubric');\n }\n\n /**\n * Show the advanced authoring view\n */\n advancedClicked() {\n this.toggleView('advanced');\n }\n\n /**\n * The show JSON button was clicked\n */\n showJSONClicked() {\n if (this.showJSONAuthoring) {\n // we were showing the JSON view and the author now wants to hide it\n if (this.isJSONValid()) {\n this.toggleJSONAuthoringView();\n this.UtilService.hideJSONValidMessage();\n } else {\n let answer = confirm(this.$translate('jsonInvalidErrorMessage'));\n if (answer) {\n // the author wants to revert back to the last valid JSON\n this.toggleJSONAuthoringView();\n this.UtilService.hideJSONValidMessage();\n }\n }\n } else {\n // we were not showing the JSON view and now the author wants to show it\n this.toggleJSONAuthoringView();\n this.projectJSONString = angular.toJson(this.ProjectService.project, 4);\n this.UtilService.showJSONValidMessage();\n }\n }\n\n isJSONValid() {\n try {\n angular.fromJson(this.projectJSONString);\n return true;\n } catch(e) {\n return false;\n }\n }\n\n toggleJSONAuthoringView() {\n this.showJSONAuthoring = !this.showJSONAuthoring;\n }\n\n /**\n * Save the project JSON to the server.\n * @return {boolean}\n * True if the JSON is valid.\n * False if the JSON is invalid.\n */\n autoSaveProjectJSONString() {\n try {\n this.saveProjectJSON(this.projectJSONString);\n this.UtilService.showJSONValidMessage();\n return true;\n } catch(e) {\n this.UtilService.showJSONInvalidMessage();\n return false;\n }\n }\n\n /**\n * Save the project JSON string to the server\n * @param projectJSONString\n */\n saveProjectJSON(projectJSONString) {\n let project = angular.fromJson(projectJSONString);\n this.ProjectService.setProject(project);\n let scriptFilename = this.ProjectService.getProjectScriptFilename();\n if (scriptFilename != null) {\n this.projectScriptFilename = scriptFilename;\n }\n this.checkPotentialStartNodeIdChangeThenSaveProject();\n }\n\n /**\n * The author has changed the rubric, so save the changes\n */\n summernoteRubricHTMLChanged() {\n let html = this.summernoteRubricHTML;\n\n /*\n * remove the absolute asset paths\n * e.g.\n * \n * will be changed to\n * \n */\n html = this.ConfigService.removeAbsoluteAssetPaths(html);\n\n /*\n * replace and