├── .gitignore ├── docs ├── _config.yml ├── index.md ├── High Level Class Diagram.pdf ├── UserGuide.md └── DevGuide.md ├── .DS_Store ├── .idea ├── vcs.xml └── workspace.xml ├── start.js ├── root.json ├── server.js ├── init.js ├── package.json ├── LICENSE.txt ├── README.md ├── index.html └── src └── mindmap.main.ts /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-modernist -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JabRef/scimappr/HEAD/.DS_Store -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # SciMappr 2 | 3 | - [User Guide](UserGuide) 4 | - [Developer Guide](DevGuide) 5 | -------------------------------------------------------------------------------- /docs/High Level Class Diagram.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JabRef/scimappr/HEAD/docs/High Level Class Diagram.pdf -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /start.js: -------------------------------------------------------------------------------- 1 | var app = require('app'); 2 | var BrowserWindow = require('browser-window'); 3 | 4 | app.on('ready', function(){ 5 | var mainWindow = new BrowserWindow({ 6 | width: 1920, 7 | height:1080 8 | }) 9 | }) -------------------------------------------------------------------------------- /root.json: -------------------------------------------------------------------------------- 1 | [{"text":"MyThesis","nodes":[{"text":"DB-BAHN-Confirmation.pdf","icon":"glyphicon glyphicon-file","href":"C:\\Users\\mdand\\testProject\\DB-BAHN-Confirmation.pdf"},{"text":"FLT_SMOWSW39687_0.pdf","icon":"glyphicon glyphicon-file","href":"C:\\Users\\mdand\\testProject\\FLT_SMOWSW39687_0.pdf"},{"text":"test.pdf","icon":"glyphicon glyphicon-file","href":"C:\\Users\\mdand\\testProject\\test.pdf"}]}] -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var app = express(); 3 | var path = require('path'); 4 | var bodyParser = require('body-parser'); 5 | var baseUrl = path.resolve(__dirname, 'build'); 6 | app.use( express.static( baseUrl ) ); 7 | 8 | /** 9 | * set index.html in public folder as default landing router 10 | */ 11 | app.use('*',function (req, res) { 12 | res.sendFile( baseUrl ); 13 | }); 14 | 15 | app.use(bodyParser.json()); 16 | 17 | app.use('/sendData', function (req, res) { 18 | console.log(req.body); 19 | res.send('ok') 20 | }); 21 | 22 | /** 23 | * Start server at port 24 | */ 25 | app.listen(8080, function() { 26 | console.log('Server started at :8080'); 27 | }); -------------------------------------------------------------------------------- /init.js: -------------------------------------------------------------------------------- 1 | const electron = require('electron'); 2 | const {app} = electron; 3 | const {BrowserWindow} = electron; 4 | const path = require('path'); 5 | const url = require('url'); 6 | 7 | let win; 8 | //let dirname = '/scimappr/'; 9 | 10 | function createWindow() { 11 | 12 | win = new BrowserWindow({ 13 | width:1920, 14 | height:1080, 15 | webPreferences: { 16 | devTools: true, 17 | 'node-integration': false 18 | } 19 | }) 20 | 21 | win.loadURL('file://' + __dirname + '/index.html'); 22 | 23 | win.on('closed', ()=> { 24 | win = null; 25 | }); 26 | 27 | } 28 | 29 | app.on('ready', createWindow); 30 | 31 | app.on('window-all-closed', ()=> { 32 | if(process.platform !== 'mdand') { 33 | app.quit(); 34 | } 35 | }); 36 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Scimappr", 3 | "version": "1.0.0", 4 | "description": "application for mindmap in internet", 5 | "main": "init.js", 6 | "scripts": { 7 | "start": "electron .", 8 | "build": "electron-packager . --overwrite --platform=win32 --electron-version=1.6.8 --out=release-builds --version-string.CompanyName=CE --version-string.FileDescription=CE --version-string.ProductName=\"Mindmap\"" 9 | }, 10 | "author": "Scimappr_Team", 11 | "license": "MIT", 12 | "devDependencies": { 13 | "electron-prebuilt": "^1.4.13", 14 | "electron-packager": "~9.1.0" 15 | }, 16 | "dependencies": { 17 | "bootstrap": "^3.3.7", 18 | "bootstrap-treeview": "1.2.0", 19 | "jquery": "3.2.1", 20 | "jqueryui": "1.11.1" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /docs/UserGuide.md: -------------------------------------------------------------------------------- 1 | # SciMappr User Guide 2 | 3 | 4 | 5 | # Installation using NPM, Git, and Bower 6 | To Install Scimappr, first we need to install node.js. Download the node.js using the link,install it (next,next) https://nodejs.org/en/ 7 | 8 | After installing node.js, use git to clone this project. 9 | But first, make sure you have install git in your repository by using this command: 10 | 11 | ```npm install -g git``` 12 | 13 | After installing git, install also bower by using this command: 14 | 15 | ```npm install -g bower``` 16 | 17 | After installing bower, clone this project into your repository using git command: 18 | 19 | ```git clone https://github.com/koppor/scimappr.git``` 20 | 21 | After clone this project, then go to one further folder by using command: 22 | 23 | ```cd scimappr``` 24 | 25 | Then install all dependencies that are used by scimappr by typing command: 26 | 27 | ```npm install package.json --save``` 28 | 29 | Lastly, to run this project, type this command: 30 | 31 | ```npm start``` 32 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [2017] [Scimappr Team IPVS-AS] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SciMappr [![License:MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://tldrlegal.com/license/mit-license) 2 | 3 | > SciMappr is [Docear](http://www.docear.org/) in the cloud. 4 | 5 | SciMappr is a project for Native App look using javascript to build a mindmap extracted from PDF. 6 | Scimappr is using Electron Framework to build cross platform apps with HTML, Javascript, and CSS. 7 | 8 | ## Installation 9 | 10 | To Install Scimappr, first we need to install node.js. Download the node.js using the link,install it (next,next) https://nodejs.org/en/ 11 | 12 | After installing node.js, use git to clone this project. 13 | But first, make sure you have install git in your repository by using this command: 14 | 15 | npm install -g git 16 | 17 | After installing git, install also bower by using this command: 18 | 19 | npm install -g bower 20 | 21 | After installing bower, clone this project into your repository using git command: 22 | 23 | git clone https://github.com/JabRef/scimappr.git 24 | 25 | After clone this project, then go to one further folder by using command: 26 | 27 | cd scimappr 28 | 29 | Then install all dependencies that are used by scimappr by typing command: 30 | 31 | npm install package.json --save 32 | 33 | Lastly, to run this project, type this command: 34 | 35 | npm start 36 | 37 | Happy Mindmapping :) 38 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Scimappr 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 83 | 84 | 85 |
86 | 87 | 88 | 115 | 116 | 117 |
118 |
119 |
120 | 121 | 122 |
123 |
124 | 125 |
126 | 127 | 128 |
129 | 141 | 142 | 143 | 144 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | -------------------------------------------------------------------------------- /docs/DevGuide.md: -------------------------------------------------------------------------------- 1 | # SciMappr Development Guide 2 | 3 | In this document, you will be informed about the internal structure of SciMappr application. 4 | 5 | # Structure of SciMappr Root Folder 6 | 7 | The structure for the SciMappr root folder consists of: 8 | 9 | |_docs 10 | 11 | |____DevGuide.md 12 | 13 | |____index.md 14 | 15 | |____UserGuide.md 16 | 17 | |_build 18 | 19 | |____assets 20 | 21 | |__________mindmap.main.js 22 | 23 | |__________jsmind.js 24 | 25 | |__________mindmap.css 26 | 27 | |__________jsmind.css 28 | 29 | |__________mindmap.js 30 | 31 | |__________sha1.js 32 | 33 | |__________sha1-min.js 34 | 35 | |__________jsmind.draggable.js 36 | 37 | |__________jsmind.droppable.js 38 | 39 | |____img 40 | 41 | |__________pdf.png 42 | 43 | |____pdf.js 44 | 45 | 46 | |_node_modules 47 | 48 | 49 | |_src 50 | 51 | |___mindmap.main.ts 52 | 53 | 54 | |_server.js 55 | 56 | |_start.js 57 | 58 | |_init.js 59 | 60 | |_package.json 61 | 62 | |_README 63 | 64 | |_index.html 65 | 66 | The main program is mindmap.main.ts which is written in Typescript and is located in /src folder. 67 | The transpile program from the main program is mindmap.main.js which is located in the /build/assets folder. 68 | The HTML file is index.html & configuration for electron can be found in the package.json. Both of them are located in the /root folder. 69 | 70 | 71 | # Explanation of Scimappr Program in Typescript 72 | 73 | There will be explanation about the class structures, important functions and the variables. 74 | For readability and the usability concerns the development of the application is done using object-oriented programming. 75 | The development language is TypeScript. TypeScript is an extension language to the Javascript. 76 | For further information, you can visit www.typescriptlang.org/. 77 | 78 | The Scimappr in the Typescript consists of several classes, such as: Main Program, Gui, Project, Annotation, Utils, PDF and Nodes. These classes will be described in detail in this developer guide. 79 | 80 | 1. Class Node 81 | 82 | Description: this class is used to set the sidebar annotation’s node parameters. 83 | 84 | Variables: 85 | 86 | private id: string; 87 | private topic: string; 88 | private filename: string; 89 | private pagenumber: number; 90 | 91 | Methods: 92 | * public setId() – this method is used to save the id of the node to the variable id 93 | * public getId() – this method is used to get the saved id from the variable id 94 | * public setTopic() – this method is used to save the topic of the node to the variable topic 95 | * public getTopic() – this method is used to get the saved topic from variable topic 96 | * public setFileName() – this method is used to save the filename of the node to the variable filename 97 | * public getFileName() – this method is used to get the saved filename from variable filename 98 | * public setPageNumber() – this method is used to save the page number of the node to the variable pagenumber 99 | * public getTopic() – this method is used to get the saved topic from variable topic 100 | * public setDraggable() – this method configures the options for the draggable 101 | * public setDroppable() – this method configures the options for the droppable 102 | 103 | 2. Class Pdf 104 | 105 | Description: This class is used to save a pdf file property details. 106 | 107 | Variables: 108 | 109 | private pdfName: string; 110 | private pdfLocation: string; 111 | private pdfLastModifiedDate: string; 112 | 113 | Methods: 114 | * public setPdfName() – this method saves the pdfName of the pdf to the variable pdfName 115 | * public getPdfName() – this method fetches the saved pdfName from variable pdfName 116 | * public setPdfLocation() – this method saves the pdfLocation of the pdf to the variable pdfLocation 117 | * public getPdfLocation() – this method fetches the saved pdfLocation from variable pdfLocation 118 | * public setPdfLastModifiedDate() – this method saves the pdfLastModifiedDate of the pdf to the variable pdfLastModifiedDate 119 | * public getPdfLastModifiedDate() – this method fetches the saved pdfLastModifiedDate from variable pdfLastModifiedDate 120 | 121 | 3. Class ListPdf -> extends Class Pdf 122 | 123 | Description: This class, as the extension from the Class Pdf, is used to save many pdf files property details in List. 124 | 125 | Variables: 126 | 127 | private listPdfFiles: string[]; 128 | private lastModDatePdfFiles: string[]; 129 | private directory: string; 130 | 131 | Methods: 132 | * public setLastModDate(list:string[]) – this method sets the modified date for a pdf 133 | * public getModDateFs(util, location:string, listFile:string[]) – this method fetches the modified date for all pdfs in the selected directory using electron file system. 134 | * public getLastModDate(idx:number) – this method fetches the saved mod date using a specific index. 135 | * public getListCount() - this method fetches the number of pdfs in the listPdfFiles 136 | * public getListPdf() - this method fetches all of the list of pdfs. 137 | * public getPdfFromFs() – this method reads pdf contents from file system using electron file system. 138 | * private readPdfInDirectory(path:string) – this method reads all pdf files in the specified path directory using electron (extended from method getPdfFromFs()). 139 | * public getPdfPage(filePath:string, fileName:string) – this method fetches the pages in a selected pdf file. 140 | * private getPdfFilesPage() – this method reads all pages in a selected pdf (extended from method getPdfPage()). 141 | * public chkDateChange(util, list:string[]) – this method compares with the last modified date with previous saved last modified date to find the changes in one or more pdf(s). 142 | 143 | 4. Class Annotation 144 | 145 | Description: This class is used to save an annotation property details. 146 | 147 | Variables: 148 | 149 | private fileName: string; 150 | private id: string; 151 | private topic: string; 152 | private subtype: string; 153 | private title: string; 154 | private pagenumber: number; 155 | 156 | Methods: 157 | * public setFileName() – this method saves the annotation’s name to the variable fileName 158 | * public getFileName() – this method fetches the saved annotation’s name from variable fileName. 159 | * public setId() – this method saves the annotation’s id to the variable id. 160 | * public getId() – this method fetches the saved annotation’s id from variable id. 161 | * public setTopic() – this method saves the annotation’s topic to the variable topic. 162 | * public getTopic() – this method fetches the saved annotation’s topic from variable topic. 163 | * public setSubType() – this method saves the annotation’s subtype to the variable subtype. 164 | * public getSubType() – this method fetches the saved annotation’s subtype from variable subtype. 165 | * public setTitle() – this method saves the annotation’s title to the variable title. 166 | * public getTitle() – this method fetches the saved annotation’s title from variable title. 167 | * public setPageNumber() – this method saves the annotation’s pagenumber to the variable pagenumber. 168 | * public getPageNumber() – this method fetches the saved annotation’s pagenumber from variable pagenumber. 169 | 170 | 171 | 5. Class ListAnnotations -> extends Class Annotation 172 | 173 | Description: This class, as an extension from Class Annotation, is used to save many annotations property details in List. 174 | 175 | Variables: 176 | 177 | private listPdfFilesAnnotations: string[]; 178 | 179 | Methods: 180 | 181 | * public setListPdfFilesAnnotations() – this method is to save all annotations extracted from PDFs into listPdfFilesAnnotation variable. 182 | * public getListPdfFilesAnnotations() – this method fetches all annotations from variable listPdfFilesAnnotations. 183 | * Public getAnnotations(pages, filename: string) – this method will call another private method of getAnnotationDetail(). 184 | * private getAnnotationsDetail(pages, fileName: string) – this method fetches all the annotations from PDFs. 185 | 186 | 187 | 6. Class Utils 188 | 189 | Description: This class is used to do some routines or utilities which will be used frequently during some methods calling, including making JSON object and JSON string, read and write file into the system, etc. 190 | 191 | Variables: 192 | 193 | private jsonFile: string; 194 | private jsonObject: NodesObject; 195 | 196 | Methods: 197 | * public setJsonFile(input: any[]) – this method will be used to make a JSON file from any lists given to this method for the input. 198 | * public setJsonString(input: string) – this method will be used to make a JSON file from string JSON given as an input for this method. 199 | * public parseJsonFile(input:string) – this method parses a JSON file string input and make it as JSON object. 200 | * public concatJsonFiles(input: string) – this method will merge two different JSON files 201 | * public getJsonFile() – this method will return a string JSON file which has been saved in the jsonFile variable. 202 | * public getJsonObject() – this method will return an object of JSON file which has been saved in the jsonObject variable. 203 | * public getHashFunction(input: string) – to give the unique id to the nodes using hash function. 204 | * public getLastModFs(location: string, url: string) – this method will return the last modification date of the given url which is read using electron. 205 | * Public getComparedLastMod(parm1:string, parm2: string) – this method compares two last modification dates and return Boolean whether the two dates are different or not. 206 | * public writeAnyTypeFile(path: string, input: string, name: string) – to save file into the system (can be .json or .mm or .jm). 207 | * public readAnyTypeFile(fullpath: string, readingtype: string, type: string) – to read any type of file from the system (can be .json or .mm or .jm) 208 | 209 | 210 | 7. Class Gui 211 | 212 | Description: This Class is used as a general Gui operations (except the sidebar Gui) 213 | 214 | Variables: 215 | 216 | private jsMindProjectNameState: string; 217 | private jsMindProjectSavedState: string; 218 | private jsMindSavedState: string; 219 | private jsMindStatusState: string; 220 | private jsMindCurrentlyOpenedProject: number; 221 | private savedStateChildElement: any; 222 | 223 | Methods: 224 | * public setGuiInitialize(mindmapMenu:any) – initializes all things regarding Gui. 225 | * public loadPdfButton(contents:any) – loads the PDF icon in the mindmap. 226 | * public setJsmindListener() – this method listens all changes regarding mindmap operation in the mindmap section. 227 | * public setContextMenu() – this method provides the list of options during event of users do right click. 228 | * public setEffectShaking(id:string) – this method is used to shake the prompter in a certain event 229 | * public setElementVisibility() – this method is used to populate all elements which have class .hide/.show and call method setShowHide(). 230 | * public setShowHide() – this method is used to show / hide a selected element. 231 | * public showRecentProject() – this method is used to give href to the recent project in the project menu. 232 | * public findNodeByAttribute(attr:any, val:string) – this method finds the mindmap’s node by specifying its attribute 233 | 234 | 8. Class ContextMenu -> extends Class Gui 235 | 236 | Description: This class is used when users do right click in the mindmap section. 237 | 238 | Variables: 239 | 240 | private listData: string[]; 241 | private tempBoard: string; 242 | private clipBoard: string; 243 | 244 | Methods: 245 | * public actionCopy() - to copy the content of the node 246 | * public actionPaste(project:any) – to paste the content of the node 247 | * public actionOpenPdf(directory:string) – to open pdf 248 | * public actionOpenPdfUserDefine(directory:string) – to enable editing the pdf using user defined PDF reader 249 | * public actionCancel() – to close the dialog 250 | * public actionDelete() – to delete the selected node 251 | 252 | 9. Class MindmapMenu -> extends Class Gui 253 | 254 | Description: This method, as an extension of the Class Gui, is used for all operations regarding the mindmap menu & mindmap changes. 255 | 256 | Variables: 257 | 258 | private jsMindObject: any; 259 | private fileTypeSave:string; 260 | 261 | Methods: 262 | * public setFileType() – to save the state of the filetype (.mm or .jm) into fileTypeSave variable 263 | * public getFileType() – to fetch the state of the filetype from fileTypeSave variable 264 | * public newMap(project:any, rootName:string) - creates new mindmap 265 | * public loadFile(filetype: string) – this method loads current mindmap state on the mindmap 266 | * public saveFile(fileType:string) – saves the mindmap 267 | * public getJsMindData() – fetch data from mindmap current state. 268 | * public selectFile() – selects the file chose by the user 269 | * public setOpenFileListener() – this method listens to the changes of the file .mm or .jm change 270 | * public loadFileJsMind(content:any, type:string, freemind_name:any) - opens the existing mindmaps 271 | 272 | 10. Class GuiSideBar 273 | 274 | Description: This class, as extension of the Class Gui, is used for all operations regarding to the sidebar Gui (tab project and tab annotation). 275 | 276 | Variables: 277 | 278 | private basicHtmlTitle:any; 279 | private basicHtmlContent:any; 280 | 281 | Functions: 282 | * public setGuiInit() – this method initializes the sidebar Gui 283 | * public setGuiOnAppend() – this method inserts annotation(s) extracted from PDFs when refresh button is pressed (in case annotation is added after opening scimappr application). 284 | * public resetSidebarAnnotation() – this method will clear all annotations in the sidebar 285 | * public checkSideBar() – check whether the annotation in the sidebar exist or not 286 | * public searchAnnotation(keyword:string, directory:string) – searches the annotations 287 | * public openTreeView(input: string) – this method sets the treeview based on the JSON data input. 288 | * public setTreeViewListener() – this method listens to the changes of the nodes in the treeview of the sidebar project tab. 289 | * public resetTreeView() – this method clears the treeview. 290 | * public setTreeView() – this method populate all pdf files and creating the treeview JSON file. 291 | * public setReCreateTreeView() – this method recreates treeview after a project is closed. 292 | * private setDynamicHtmlTitle() – this method creates dynamic html for the pdf title in the sidebar. 293 | * private setDynamicHtml() – checks if same nodes present in the mindmap and sidebar and execute method setDynamicHtmlContent() create dynamic html for the annotations in the sidebar. 294 | * private setDynamicHtmlContent() – this method is the real method to create dynamic html and fill the html attributes. 295 | * public setAnnotationVisibility() – this method sets the annotation title visibility by comparing some annotation(s) which have become mindmap and the remaining annotation(s) in the sidebar. 296 | * private checkJsMindNode() – this method checks whether the nodes are already in the mindmap or still in the annotation’s sidebar section. 297 | * public checkAnnotationExistInSidebar() – this method checks whether there is annotation(s) in the sidebar or not. 298 | * public findAnnotationByAttribute() – this method searches for the annotation(s) in the sidebar by their attribute. 299 | 300 | 301 | 11. Class Project 302 | 303 | Description: This class is mainly about all operations regarding to the project, such as new project, open project, save project and close project. 304 | 305 | Variables: 306 | 307 | private projectName: string; 308 | private projectLocation: string; 309 | private projectPdfList: string[]; 310 | private projectStatus: string; 311 | private projectSavedFileLocation: string; 312 | private projectSavedPdfLocation: string; 313 | private projectTreeView: string; 314 | private projectPromises: string; 315 | 316 | Functions: 317 | * public setProjectName() – this method saves the name of the project in the variable projectName. 318 | * public getProjectName() – this method fetches the name of the project from the saved variable projectName. 319 | * public setProjectLocation() – this method saves the project location in the variable projectLocation. 320 | * public getProjectLocation() – this method fetches the project location from the variable projectLocation. 321 | * public setProjectPdfList() – this method saves the list of PDF(s) name into the variable projectPdfList. 322 | * public getProjectPdfList() – this method fetches the list of PDF(s) name from the variable projectPdfList. 323 | * public setProjectStatus() – this method saves the status of the project into variable projectStatus. 324 | * public getProjectStatus() – this method fetches the status of the project from variable projectStatus. 325 | * public setProjectSavedFileLocation() – this method saves the location/directory of the saved mindmap file (.mm or .jm) into variable projectSavedFileLocation. 326 | * public getProjectSavedFileLocation() – this method fetches the location/directory of the saved mindmap file (.mm or .jm) from variable projectSavedFileLocation. 327 | * public setProjectPdfFileLocation() – this method saves the location/directory of the PDF(s) file into variable projectSavedPdfLocation. 328 | * public getProjectPdfFileLocation() – this method fetches the location/directory of the PDF(s) file from variable projectSavedPdfLocation. 329 | * public setProjectTreeView() – this method saves the currently opened project treeview’s JSON file into variable projectTreeView 330 | * public getProjectTreeView() – this method fetches the currently opened project treeview’s JSON file from variable projectTreeView 331 | * public setProjectPromises() – this method saves promise results which are produced during opening new project modal into variable projectPromises. 332 | * public getProjectPromises() – this method fetches back promise results which are produced during opening new project modal from variable projectPromises. 333 | * public checkNewProject() - this method checks the requirements for the new project and returns the Boolean of the project status. 334 | * public newProjectModal() – this method opens the new project modal. 335 | * public setNewProjectListener() – this method listens to the changes of the new project requirements during the new project modal is being opened. 336 | * public createNewProject() – this method is executed when user click saves from the new project modal. 337 | * public setSaveProject() – this method is the routine which is called in order to save project. 338 | * private saveProject() – this method is the main program executed to do some stuffs, such as populating JSON data, building save mindmap file (.mm or .jm), etc, during saving the project. 339 | * public setTempSaveProject() – this method saves the temporary state of the running project (including after some changes have been made by the user). 340 | * public addToRecentProject() – this method adds the recently opened project to the shortcut of recent project in the project menu and saves it into JSON file (project.json) in the root system. 341 | * public openRecentProject() – this method opens the saved recent project from JSON file (project.json) in the root system. 342 | * public setOpenProjectModal() – this method is executed during the open project click by the user. 343 | * private setOpenProjectListener() – this method listens to the change made by project configuration file chooser (.json file). 344 | * public openProject() – this method is the main program to open a project. 345 | * public openProjectFromTreeView() – this method is used to open project based on treeview’s project selection. 346 | * public setCloseProject() – when close project is pressed, then this method is executed. 347 | * public clrProjectState() – this method clears some parameter’s states. 348 | 349 | 350 | 351 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | md5 107 | 108 | 109 | 110 | 112 | 113 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | true 126 | DEFINITION_ORDER 127 | 128 | 129 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 157 | 158 | 161 | 162 | 163 | 164 | 167 | 168 | 171 | 172 | 175 | 176 | 177 | 178 | 181 | 182 | 185 | 186 | 189 | 190 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | project 263 | 264 | 265 | true 266 | 267 | 268 | 269 | DIRECTORY 270 | 271 | false 272 | 273 | 274 | 275 | 276 | 278 | 279 | 280 | 281 | 1498229050768 282 | 287 | 288 | 289 | 290 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 318 | 319 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | -------------------------------------------------------------------------------- /src/mindmap.main.ts: -------------------------------------------------------------------------------- 1 | declare var PDFJS: any; 2 | declare var Promise: any; 3 | declare var $: any; 4 | declare var hex_sha1: any; 5 | declare var require: any; 6 | 7 | declare var hex_hmac_sha1: any; 8 | declare var _jm: { begin_edit: Function, get_selected_node: Function, remove_node: Function, resize: Function, select_node: Function, show: Function, add_node: Function, mind: { nodes: Function }, view_provider: { edit_node_end: Function }, add_event_listener: Function, get_data: Function }; 9 | declare var jsMind: any; 10 | declare var jmnodes: any; 11 | declare var Buffer: any; 12 | const path = require('path'); 13 | 14 | // ========================================================= // 15 | // Class Section 16 | // ========================================================= // 17 | 18 | 19 | /** 20 | * Used to set the Node's parameters in sidebar 21 | */ 22 | class Nodes { 23 | private id: string; 24 | private topic: string; 25 | private filename: string; 26 | private pagenumber: number; 27 | 28 | /** 29 | * 30 | * @param nodeId 31 | * @param nodeTopic 32 | */ 33 | constructor(nodeId: string, nodeTopic: string, fileName: string, pagenumber: number) { 34 | this.id = nodeId; 35 | this.topic = nodeTopic; 36 | this.filename = fileName; 37 | this.pagenumber = pagenumber; 38 | } 39 | 40 | /** 41 | * 42 | * @param id 43 | */ 44 | public setId(id: string) { 45 | this.id = id; 46 | } 47 | 48 | /** 49 | * 50 | * @returns {string} 51 | */ 52 | public getId(): string { 53 | return this.id; 54 | } 55 | 56 | /** 57 | * 58 | * @param topic 59 | */ 60 | public setTopic(topic: string) { 61 | this.topic = topic; 62 | } 63 | 64 | /** 65 | * 66 | * @returns {string} 67 | */ 68 | public getTopic(): string { 69 | return this.topic; 70 | } 71 | 72 | /** 73 | * 74 | * @param filename 75 | */ 76 | public setFileName(filename: string) { 77 | this.filename = filename; 78 | } 79 | 80 | /** 81 | * 82 | * @returns {string} 83 | */ 84 | public getFileName(): string { 85 | return this.filename; 86 | } 87 | 88 | /** 89 | * 90 | * @param pagenumber 91 | */ 92 | public setPageNumber(pagenumber: number) { 93 | this.pagenumber = pagenumber; 94 | } 95 | 96 | /** 97 | * 98 | * @returns {number} 99 | */ 100 | public getPageNumber(): number { 101 | return this.pagenumber; 102 | } 103 | 104 | /** 105 | * set Node to be Draggable 106 | * @returns {DragObject} 107 | */ 108 | public setDraggable(): any { 109 | var temp: DragObject = { 110 | helper: 'clone', 111 | containment: 'frame', 112 | opacity: '0.5', 113 | revert: 'invalid', 114 | appendTo: 'body', 115 | stop: (ev: Event, ui): string => { 116 | var pos = $(ui.helper).offset(); 117 | return "finish"; 118 | } 119 | }; 120 | return temp; 121 | } 122 | 123 | /** 124 | * set Node to be Droppable 125 | * @returns {DropObject} 126 | */ 127 | public setDroppable(): any { 128 | var temp: DropObject = { 129 | drop: (ev: Event, ui): string => { 130 | var selected_node = _jm.get_selected_node(); // select node when mouseover 131 | if (!selected_node) { 132 | alert('please select a node first.'); 133 | return; 134 | } 135 | var nodeid: string = ui.helper.prevObject[0].id; 136 | var topic: string = ui.helper.prevObject[0].innerHTML; 137 | var pdfid: string = ui.helper.prevObject[0].title; 138 | var pagenumber: number = ui.helper.prevObject[0].value; 139 | var directory: string = ui.helper.prevObject[0].href; 140 | var node: any = _jm.add_node(selected_node, nodeid, topic, "", pdfid, pagenumber); 141 | 142 | gui.setPdfButton(nodeid, pdfid, pagenumber, this); 143 | 144 | project.setProjectStatus('edited'); 145 | project.setTempSaveProject("chgProject"); 146 | } 147 | } 148 | 149 | return temp 150 | } 151 | 152 | } 153 | 154 | /** 155 | * Pdf file details in folder 156 | */ 157 | class Pdf { 158 | private pdfName: string; 159 | private pdfLocation: string; 160 | private pdfLastModifiedDate: string; 161 | 162 | public setPdfName(input: string) { 163 | this.pdfName = input; 164 | } 165 | 166 | public getPdfName() { 167 | return this.pdfName; 168 | } 169 | 170 | public setPdfLocation(input: string) { 171 | this.pdfLocation = input; 172 | } 173 | 174 | public getPdfLocation() { 175 | return this.getPdfLocation; 176 | } 177 | 178 | public setPdfModifiedDate(input: string) { 179 | this.pdfLastModifiedDate = input; 180 | } 181 | 182 | public getPdfModifiedDate() { 183 | return this.getPdfModifiedDate; 184 | } 185 | } 186 | 187 | /** 188 | * List of PDF files in a folder 189 | */ 190 | class ListPdf extends Pdf { 191 | /** 192 | * Saves PDF Files' Name, Last Modification and Folder Directory 193 | */ 194 | private listPdfFiles: string[]; 195 | private lastModDatePdfFiles: string[]; 196 | private directory: string; 197 | 198 | /** 199 | * 200 | * @param listPdfFiles 201 | * @param lastModDatePdfFiles 202 | * @param directory 203 | */ 204 | constructor(listPdfFiles: string[], lastModDatePdfFiles: string[], directory: string) { 205 | super(); 206 | this.listPdfFiles = listPdfFiles; 207 | this.directory = directory; 208 | this.lastModDatePdfFiles = lastModDatePdfFiles; 209 | } 210 | 211 | /** 212 | * save list of pdf files' name with input of pdf file lists 213 | * @param list 214 | */ 215 | public setListPdfFile(list: string[]) { 216 | for (var x = 0; x < list.length; x++) { 217 | this.listPdfFiles[x] = list[x]; 218 | } 219 | } 220 | 221 | /** 222 | * fetch list of pdf files' names with giving input by array index from saved file list 223 | * @param idx 224 | * @returns {string} 225 | */ 226 | public getListPdfFile(idx: number): string { 227 | return this.listPdfFiles[idx]; 228 | } 229 | 230 | /** 231 | *fetch list of pdf files' all names from saved file list 232 | * @returns {string[]} 233 | */ 234 | public getListPdf(): string[] { 235 | return this.listPdfFiles; 236 | } 237 | 238 | /** 239 | *save list of pdf files' last modifiy date with input of last modifyed date lists 240 | * @param list 241 | */ 242 | public setLastModDate(list: string[]) { 243 | for (var x = 0; x < list.length; x++) { 244 | this.lastModDatePdfFiles[x] = list[x]; 245 | } 246 | } 247 | 248 | 249 | /** 250 | * extract the all last modifyed date information from the pdf file list 251 | * @param util 252 | * @param listFile 253 | * @returns {Array} 254 | */ 255 | public getModDateFs(util, location: string, listFile: string[]) { 256 | var counter: number = 0; 257 | var modDateList = []; 258 | for (var x = 0; x < listFile.length; x++) { 259 | modDateList.push(util.getLastModFs(location, listFile[x])); 260 | } 261 | return modDateList; 262 | } 263 | 264 | /** 265 | * get all last modified date from last modified date list 266 | * @returns {string[]} 267 | */ 268 | public getLastMod(): string[] { 269 | return this.lastModDatePdfFiles; 270 | } 271 | 272 | /** 273 | *Counting all the pdf files names inside the pdf files list 274 | * @returns {number} 275 | */ 276 | public getCount(): number { 277 | return this.listPdfFiles.length; 278 | } 279 | 280 | public getPdfFromFs(): any { 281 | var result = this.readPdfInDirectory(this.directory); 282 | return result; 283 | } 284 | 285 | /** 286 | * subroutine for calling get pdf file page 287 | * @param filePath 288 | * @param fileName 289 | * @returns {any} 290 | */ 291 | public getPdfPage(filePath: string, fileName: string): any { 292 | var result = this.getPdfFilesPage(filePath, fileName); 293 | return result; 294 | } 295 | 296 | /** 297 | * save the directory that contains pdf files 298 | * @param dir 299 | */ 300 | public setDirectory(dir: string) { 301 | dir = path.normalize(dir); 302 | this.directory = dir; 303 | } 304 | 305 | /** 306 | *get the saved directory 307 | * @returns {string} 308 | */ 309 | public getDirectory(): string { 310 | return this.directory; 311 | } 312 | 313 | /** 314 | *For comparing last modify date changes for updating the annotation 315 | * @param util 316 | * @param list 317 | * @returns {[boolean,string[],number]} 318 | */ 319 | public chkDateChange(util, list: string[]): any { 320 | var newLastMod: string[] = []; 321 | var listChange: string[] = []; 322 | var stsChange: boolean = false; 323 | var indexChange: number = 0; 324 | for (var x = 0; x < list.length; x++) { 325 | newLastMod[x] = util.getLastModFs(project.getProjectSavedPdfLocation(), list[x]); 326 | } 327 | for (var x = 0; x < list.length; x++) { 328 | if (newLastMod[x] != this.lastModDatePdfFiles[x]) { 329 | stsChange = true; 330 | listChange[indexChange] = this.getListPdfFile(x); 331 | indexChange++; 332 | } 333 | } 334 | 335 | return [stsChange, listChange, indexChange]; 336 | } 337 | 338 | /** 339 | * reading all pdf files in the specified directory 340 | * @param paths 341 | */ 342 | private readPdfInDirectory(paths: string): any { 343 | 344 | var process = new Promise(function (resolve, reject) { 345 | var promises = [], promise; 346 | var fs = require("fs"); 347 | fs.readdir(paths, function (err, filenames) { 348 | if (err) { 349 | alert("error reading directory"); 350 | return; 351 | } 352 | filenames.forEach(function (filename) { 353 | if (filename.indexOf(".pdf") != -1) { 354 | promise = filename; 355 | promises.push(promise); 356 | } 357 | }); 358 | resolve(promises); 359 | }) 360 | }); 361 | 362 | return process; 363 | } 364 | 365 | /** 366 | * For each Pdf files get list of the pages that contain annotation 367 | * @param filePath 368 | * @param fileName 369 | * @returns {any} 370 | */ 371 | private getPdfFilesPage(filePath: string, fileName: string): any { 372 | 373 | var processPage = new Promise(function (resolve, reject) { 374 | // Adding timestamp forces the browser to always trigger a 375 | // new request for the PDF file. This is a way to prevent 376 | // the browser to use the cached version of the file 377 | PDFJS.getDocument(`${filePath}?${Date.now()}`).then(function (pdf) { 378 | var promises = [], promise; 379 | for (var i = 1; i <= pdf.numPages; i++) { 380 | promise = pdf.getPage(i).then(function (page) { 381 | return page.getAnnotations(); 382 | }); 383 | promises.push(promise); 384 | } 385 | var resolvedPromises = Promise.all(promises); 386 | resolve(resolvedPromises); 387 | }); 388 | }); 389 | 390 | return processPage; 391 | 392 | } 393 | 394 | /** 395 | * to clear states of list Pdf 396 | */ 397 | public clrListPdfState() { 398 | this.listPdfFiles = new Array(); 399 | this.lastModDatePdfFiles = new Array(); 400 | } 401 | } 402 | 403 | /** 404 | *Details of annotation 405 | */ 406 | class Annotation { 407 | private fileName: string; 408 | private id: string; 409 | private topic: string; 410 | private subtype: string; 411 | private title: string; 412 | private pagenumber: number 413 | 414 | /** 415 | * 416 | * @param fileName 417 | * @param annotId 418 | * @param annotTopic 419 | * @param annotSubtype 420 | * @param annotTitle 421 | */ 422 | constructor(fileName: string, annotId: string, annotTopic: string, annotSubtype: string, annotTitle: string, pagenumber: number) { 423 | this.fileName = fileName; 424 | this.id = annotId; 425 | this.topic = annotTopic; 426 | this.subtype = annotSubtype; 427 | this.title = annotTitle; 428 | this.pagenumber = pagenumber; 429 | } 430 | 431 | /** 432 | *Set pdf file name for this annotation 433 | * @param fileName 434 | */ 435 | public setFileName(fileName: string) { 436 | this.fileName = fileName; 437 | } 438 | 439 | /** 440 | * Get pdf file name from the given annotation 441 | * @returns {string} 442 | */ 443 | public getFileName() { 444 | return this.fileName; 445 | } 446 | 447 | /** 448 | * Set the Id of annotation 449 | * @param id 450 | */ 451 | public setId(id: string) { 452 | this.id = id; 453 | } 454 | 455 | /** 456 | * Get the Id 457 | * @returns {string} 458 | */ 459 | public getId(): string { 460 | return this.id; 461 | } 462 | 463 | /** 464 | * Set the topic of the annotation 465 | * @param topic 466 | */ 467 | public setTopic(topic: string) { 468 | this.topic = topic; 469 | } 470 | 471 | /** 472 | * Get the topic 473 | * @returns {string} 474 | */ 475 | public getTopic(): string { 476 | return this.topic; 477 | } 478 | 479 | /** 480 | * For the Pop up or Rectangle annotation type choose. We have only get popup option right now 481 | * But for the future implementation the Rectangle also can be choose 482 | * @param subtype 483 | */ 484 | public setSubtype(subtype: string) { 485 | this.subtype = subtype; 486 | } 487 | 488 | /** 489 | * Get defined subtype from annotation 490 | * @returns {string} 491 | */ 492 | public getSubtype() { 493 | return this.subtype; 494 | } 495 | 496 | /** 497 | * The name of the creator of this annotations 498 | * @param title 499 | */ 500 | public setTitle(title: string) { 501 | this.title = title; 502 | } 503 | 504 | /** 505 | * Get the name of the creator of this annotations 506 | * @returns {string} 507 | */ 508 | public getTitle(): string { 509 | return this.title; 510 | } 511 | /** 512 | * Set the number of page that stores the Annotation 513 | * @param pagenumber 514 | */ 515 | public setPageNumber(pagenumber: number) { 516 | this.pagenumber = pagenumber; 517 | } 518 | /** 519 | * get the number of page that stores the Annotation 520 | */ 521 | public getPageNumber(): number { 522 | return this.pagenumber; 523 | } 524 | ss 525 | } 526 | 527 | /** 528 | * Used to manipulate list of annotations 529 | */ 530 | class ListAnnotations extends Annotation { 531 | 532 | private listPdfFilesAnnotations: string[]; 533 | 534 | /** 535 | * set The constructor when class is called 536 | * @param input 537 | */ 538 | constructor(input: string) { 539 | super("", "", "", "", "", 0); 540 | this.listPdfFilesAnnotations = new Array; 541 | } 542 | 543 | /** 544 | *After you get all the annotations you save it into listpdffilesanotations 545 | * @param input 546 | */ 547 | public setListPdfFilesAnnotations(input: string[]) { 548 | this.listPdfFilesAnnotations = input; 549 | } 550 | 551 | /** 552 | * get listofannotations 553 | * @returns {string[]} 554 | */ 555 | public getListPdfFilesAnnotations(): string[] { 556 | return this.listPdfFilesAnnotations; 557 | } 558 | 559 | /** 560 | *routine to get annotations detail 561 | * @param pages 562 | * @param fileName 563 | * @returns {any} 564 | */ 565 | public getAnnotations(pages, fileName: string): any { 566 | var result = this.getAnnotationsDetail(pages, fileName); 567 | return result; 568 | } 569 | 570 | /** 571 | *Prommise for getting annotation details for eachpages of the pdf 572 | * @param pages 573 | * @param fileName 574 | * @returns {any} 575 | */ 576 | private getAnnotationsDetail(pages, fileName: string): any { 577 | var util = new Utils(); 578 | var ignoreList = ['Link']; 579 | var items = []; 580 | var processAnot = new Promise(function (resolve, reject) { 581 | var pageNumber: number = 0; 582 | pages.forEach(annotations => { 583 | pageNumber++; 584 | annotations.forEach(function (annotation) { 585 | if ((annotation.contents != "") && (annotation.subtype == "Popup")) { 586 | items.push({ 587 | filename: fileName, 588 | id: util.getHashFunction(fileName + " " + annotation.contents), 589 | subtype: annotation.subtype, 590 | title: annotation.title, 591 | topic: annotation.contents, 592 | pagenumber: pageNumber, 593 | }); 594 | this.listPdfFilesAnnotations = annotation.contents; 595 | } 596 | }); 597 | var temp = util.setJsonFile(items); 598 | util.concatJsonFiles(temp); 599 | }); 600 | resolve(util.getJsonFile()) 601 | }); 602 | return processAnot; 603 | } 604 | } 605 | 606 | 607 | /** 608 | * Utilities that are used to support the main program 609 | */ 610 | class Utils { 611 | 612 | private jsonFile: string; 613 | private jsonObject: NodesObject; 614 | 615 | /** 616 | * Make a json file from anthing that is giving a list input to this method 617 | * @param input 618 | * @returns {string} 619 | */ 620 | public setJsonFile(input: any[]): string { 621 | this.jsonFile = JSON.stringify(input); 622 | return this.jsonFile; 623 | } 624 | 625 | /** 626 | * The input is from only one section of the list, one by one 627 | * @param input 628 | * @returns {string} 629 | */ 630 | public setJsonString(input: string): string { 631 | this.jsonFile = input; 632 | return this.jsonFile; 633 | } 634 | 635 | /** 636 | * Parsing json file to get the json object 637 | * @param input 638 | * @returns {NodesObject} 639 | */ 640 | public parseJsonFile(input: string): NodesObject { 641 | this.jsonObject = JSON.parse(input); 642 | return this.jsonObject; 643 | } 644 | 645 | /** 646 | * Concat two json files into one json file 647 | * @param input 648 | * @returns {string} 649 | */ 650 | public concatJsonFiles(input: string): string { 651 | var obj1 = JSON.parse(input); 652 | var obj2 = JSON.parse(this.jsonFile); 653 | var concatJson: string; 654 | var idxObj1 = obj1.length; 655 | for (var key in obj2) { 656 | obj1[idxObj1] = obj2[key]; 657 | idxObj1++; 658 | } 659 | concatJson = JSON.stringify(obj1) 660 | return concatJson 661 | } 662 | 663 | /** 664 | *to get json file from the saved json file 665 | * @returns {string} 666 | */ 667 | public getJsonFile() { 668 | return this.jsonFile; 669 | } 670 | 671 | /** 672 | * To get a json object from the saved json object 673 | * @returns {NodesObject} 674 | */ 675 | public getJsonObject() { 676 | return this.jsonObject; 677 | } 678 | 679 | /** 680 | * Hashing method for hashing the sended strings 681 | * @param input 682 | * @returns {string} 683 | */ 684 | public getHashFunction(input: string): string { 685 | var hash: string = hex_sha1("string"); 686 | var hmac: string = hex_hmac_sha1("19", input); 687 | return hmac; 688 | } 689 | 690 | /** 691 | * The real method in order to get the last modified date from the given URL (using fs) 692 | * @param url 693 | * @returns {any} 694 | */ 695 | public getLastModFs(location: string, url: string): any { 696 | var lastModifiedDate: any; 697 | var fs = require('fs'); 698 | 699 | 700 | //fs.stat(location + "//" + url, function (err, stats) { 701 | //lastModifiedDate = stats.mtime; 702 | //}); 703 | 704 | var result = fs.statSync(path.join(location, url)); 705 | console.log(result); 706 | lastModifiedDate = result.mtime; 707 | 708 | return lastModifiedDate; 709 | } 710 | 711 | /** 712 | * Comparison function in order to understand whether the pdf file is changed or not 713 | * @param lstMod1 714 | * @param lstMod2 715 | * @returns {boolean} 716 | */ 717 | public getCompareLastMod(lstMod1: string, lstMod2: string): boolean { 718 | var stsResult = false; 719 | if (lstMod1 != lstMod2) { 720 | stsResult = true; 721 | } 722 | return stsResult; 723 | } 724 | 725 | public writeAnyTypeFile(paths: string, input: string, name: string, type: string) { 726 | var fs = require('fs'); 727 | var buffer = new Buffer(input); 728 | 729 | fs.open(path.join(paths, name) + "." + type, 'w', function (err, fd) { 730 | if (err) { 731 | throw 'error opening file: ' + err; 732 | } 733 | 734 | fs.write(fd, buffer, 0, buffer.length, null, function (err) { 735 | if (err) throw 'error writing file: ' + err; 736 | fs.close(fd, function () { 737 | console.log('file has been written to ' + path.join(paths, name) + "." + type); 738 | }) 739 | }); 740 | }); 741 | } 742 | 743 | public readAnyTypeFile(fullpath: string, readingtype: string, type: string): any { 744 | var fs = require('fs'); 745 | var filepath: string = null; 746 | 747 | if (type != null) { 748 | filepath = fullpath + "." + type; 749 | } else { 750 | filepath = fullpath; 751 | } 752 | 753 | var result = new Promise(function (resolve, reject) { 754 | fs.readFile(filepath, readingtype, function (err, contents) { 755 | resolve(contents); 756 | }); 757 | }); 758 | 759 | return result; 760 | 761 | } 762 | 763 | } 764 | 765 | /** 766 | * for GUI operations in general (except the gui sidebar) 767 | */ 768 | class Gui { 769 | 770 | private jsMindProjectNameState: string[]; // for saving temporary project name state related to currently opened JsMind 771 | private jsMindProjectSavedState: string[]; // for saving temporary project state related to currently opened JsMind (in .json format) 772 | private jsMindSavedState: string[]; // for saving temporary jsmind state related to currently opened JsMind (in .mm or .jm format) 773 | private jsMindStatusState: string[]; // for saving temporary jsmind status state related to currently opened JsMind (edited or noedit) 774 | private jsMindCurrentlyOpenedProject: number // for saving currently opened project state by its index number (1, 2, 3, etc) 775 | private savedStateChildElement: any // for saving child element (PDF Button) during edit or moving node in JsMind 776 | 777 | constructor() { 778 | this.jsMindProjectNameState = new Array(); 779 | this.jsMindSavedState = new Array(); 780 | this.jsMindProjectSavedState = new Array(); 781 | this.jsMindStatusState = new Array(); 782 | this.jsMindCurrentlyOpenedProject = 0; 783 | this.savedStateChildElement = null; 784 | } 785 | 786 | /** 787 | * to save the state of the name of JsMind project 788 | * @param input 789 | * @param idx 790 | */ 791 | public setJsMindProjectNameState(input: string, idx: number) { 792 | this.jsMindProjectNameState[idx] = input; 793 | } 794 | 795 | /** 796 | * to find the sequence of the project's name in the saved state 797 | * @param name 798 | */ 799 | public getJsMindProjectNameState(name: string): number { 800 | for (var x = 1; x <= this.jsMindProjectNameState.length; x++) { 801 | if (this.jsMindProjectNameState[x] == name) { 802 | return x; 803 | } 804 | } 805 | } 806 | 807 | /** 808 | * to get the name of the project whose state has been saved in temporary 809 | * @param idx 810 | */ 811 | public getMindProjectName(idx: number): string { 812 | return this.jsMindProjectNameState[idx]; 813 | } 814 | 815 | /** 816 | * to get the sequence of the saved state 817 | */ 818 | public getCountProjectStatesNumber(): number { 819 | var projCounter: number = 0; 820 | if (this.jsMindProjectNameState.length == 0) { 821 | projCounter = 1; 822 | } else { 823 | projCounter = this.jsMindProjectNameState.length; 824 | } 825 | return projCounter; 826 | } 827 | 828 | /** 829 | * to set the current state of the project 830 | * @param input 831 | * @param idx 832 | */ 833 | public setJsMindProjectState(input: string, idx: number) { 834 | this.jsMindProjectSavedState[idx] = input; 835 | } 836 | 837 | /** 838 | * to return back the state of the current project 839 | * @param idx 840 | */ 841 | public getJsMindProjectState(idx: number): string { 842 | return this.jsMindProjectSavedState[idx]; 843 | } 844 | /** 845 | * to save the current state of mindmap 846 | * @param input 847 | * @param idx 848 | */ 849 | public setJsMindSavedState(input: string, idx: number) { 850 | this.jsMindSavedState[idx] = input; 851 | } 852 | 853 | /** 854 | * to get the current saved state of the mindmap 855 | * @param idx 856 | */ 857 | public getJsMindSavedState(idx: number): string { 858 | return this.jsMindSavedState[idx]; 859 | } 860 | 861 | /** 862 | * to save the state of the status of the project (edited or noedit) 863 | * @param input 864 | * @param idx 865 | */ 866 | public setJsMindStatusState(input: string, idx: number) { 867 | this.jsMindStatusState[idx] = input; 868 | } 869 | 870 | /** 871 | * to get the current saved state of the status of the project 872 | * @param idx 873 | */ 874 | public getJsMindStatusState(idx: number) { 875 | return this.jsMindStatusState[idx]; 876 | } 877 | 878 | /** 879 | * to save the state of which current project is being opened 880 | * @param input 881 | */ 882 | public setJsMindOpenProject(input: number) { 883 | this.jsMindCurrentlyOpenedProject = input; 884 | } 885 | 886 | /** 887 | * to get the state of which current project is being opened 888 | */ 889 | public getJsMindOpenProject(): number { 890 | return this.jsMindCurrentlyOpenedProject; 891 | } 892 | 893 | /** 894 | * to save the child element 895 | */ 896 | public setChildElement(input: any) { 897 | this.savedStateChildElement = input; 898 | } 899 | 900 | /** 901 | * to get the child element 902 | */ 903 | public getChildElement(): any { 904 | return this.savedStateChildElement; 905 | } 906 | 907 | /** 908 | * to recreate the saved state of the opened projects after a project is being closed 909 | * @param list 910 | */ 911 | public setReCreateState(list: any) { 912 | 913 | var newListName: string[] = new Array(); 914 | var newSavedState: string[] = new Array(); 915 | var newProjectState: string[] = new Array(); 916 | var newStatusState: string[] = new Array(); 917 | var newOpenedProject: number = 0; 918 | for (var i = 0; i < list.length; i++) { 919 | for (var j = 1; j <= this.jsMindProjectNameState.length; j++) { 920 | if (list[i].text == this.jsMindProjectNameState[j]) { 921 | newListName[i] = this.jsMindProjectNameState[j]; 922 | newSavedState[i] = this.jsMindSavedState[j]; 923 | newProjectState[i] = this.jsMindProjectSavedState[j]; 924 | newStatusState[i] = this.jsMindStatusState[j]; 925 | } 926 | } 927 | } 928 | 929 | newOpenedProject = list.length; 930 | 931 | this.jsMindProjectNameState = new Array(); 932 | this.jsMindSavedState = new Array(); 933 | this.jsMindProjectSavedState = new Array(); 934 | this.jsMindStatusState = new Array(); 935 | this.jsMindCurrentlyOpenedProject = 0; 936 | 937 | this.setJsMindOpenProject(newOpenedProject); 938 | var x = 1; 939 | for (var i = 0; i < newListName.length; i++) { 940 | this.setJsMindProjectNameState(newListName[i], x); 941 | this.setJsMindSavedState(newSavedState[i], x); 942 | this.setJsMindProjectState(newProjectState[i], x); 943 | this.setJsMindStatusState(newStatusState[i], x); 944 | x++; 945 | } 946 | } 947 | 948 | /** 949 | * Setting GUI when Initializing the program 950 | * @param mindmapMenu 951 | */ 952 | public setGuiInitialize(mindmapMenu: any): any { 953 | //to set nodes as draggable and droppable 954 | $(".drag").draggable(node.setDraggable()); 955 | $(".drop").droppable(node.setDroppable()); 956 | 957 | // Render existing MindMap 958 | var options = { 959 | container: 'jsmind_container', 960 | theme: 'primary', 961 | editable: true 962 | } 963 | var mindmap = { 964 | "meta": { 965 | "name": "jsMind", 966 | "version": "0.2" 967 | }, 968 | "format": "node_tree", 969 | "data": { "id": "root", "topic": "Root", "children": [] } 970 | }; 971 | 972 | _jm = jsMind.show(options, mindmap); 973 | mindmapMenu = new MindmapMenu(_jm); 974 | mindmapMenu.setOpenFileListener(); 975 | 976 | return mindmapMenu; 977 | } 978 | 979 | /** 980 | * used for creating confirmation window 981 | * @param msg 982 | */ 983 | public windowConfirmation(msg: string): boolean { 984 | var result: boolean = confirm(msg); 985 | return result; 986 | } 987 | 988 | /** 989 | * used for creating alert window 990 | * @param msg 991 | */ 992 | public windowAlert(msg: string) { 993 | alert(msg); 994 | } 995 | 996 | /** 997 | * listener for size changing 998 | */ 999 | public windowResizeListener() { 1000 | var c = document.getElementById('jsmind_container'); 1001 | var widthSize = c.offsetWidth; 1002 | var heightSize = c.offsetHeight; 1003 | 1004 | window.addEventListener('resize', function (result) { 1005 | if ((window.innerWidth == widthSize) && (window.innerHeight == heightSize)) { 1006 | c.style.width = widthSize.toString(); 1007 | c.style.height = heightSize.toString(); 1008 | _jm.resize(); 1009 | } else { 1010 | var width = window.innerWidth - 170; 1011 | var height = window.innerHeight - 300; 1012 | c.style.width = width.toString(); 1013 | c.style.height = height.toString(); 1014 | _jm.resize(); 1015 | } 1016 | }); 1017 | } 1018 | 1019 | /** 1020 | * give pdf button to all nodes when opening a new project 1021 | * @param contents 1022 | */ 1023 | public loadPdfButton(contents: any) { 1024 | var self = this; 1025 | 1026 | jmnodes = document.querySelectorAll('jmnodes'); 1027 | var nodes = jmnodes[0].children; 1028 | var node = null; 1029 | var content = contents[0]; 1030 | var counter: number = 0 1031 | 1032 | for (var i = 0; i < nodes.length; i++) { 1033 | if (nodes[i].nodeName == "JMNODE") { 1034 | var tempContent = content.annotation[counter]; 1035 | var realContent = tempContent[0]; 1036 | counter++; 1037 | if (realContent.id == nodes[i].attributes[0].value) { 1038 | if (realContent.id != "root") { 1039 | node = new Nodes(realContent.id, realContent.text, realContent.file, realContent.page); 1040 | self.setPdfButton(node.getId(), node.getFileName(), node.getPageNumber().toString(), node); 1041 | var tempElement = this.findNodeByAttribute("nodeid", node.getId()); 1042 | if ((tempElement != null) && (tempElement != undefined)) { 1043 | tempElement.setAttribute("pdfid", node.getFileName()); 1044 | } 1045 | } 1046 | } else { 1047 | counter--; 1048 | } 1049 | } 1050 | } 1051 | } 1052 | 1053 | /** 1054 | * setting pdf button in all nodes 1055 | * @param nodeid 1056 | * @param pdfid 1057 | * @param pagenumber 1058 | * @param node 1059 | */ 1060 | public setPdfButton(nodeid: string, pdfid: string, pagenumber: string, node: any) { 1061 | if ((pdfid != "undefine") || (pdfid != null)) { 1062 | 1063 | var pdfViewer: string = "./build/pdf.js/web/viewer.html"; 1064 | //var fileName:string = "?File=" + "./" + pdfid; 1065 | var fileName: string = "?file=" + pdfid; 1066 | var pageNumber: string = "#page=" + pagenumber.toString(); 1067 | var link: string = pdfViewer + fileName + pageNumber; 1068 | 1069 | var linkElement: any = document.createElement("a") 1070 | linkElement.setAttribute("href", link); 1071 | linkElement.setAttribute("target", "_blank"); 1072 | linkElement.setAttribute("style", "z-index:5; float:left; padding-right:5px"); 1073 | 1074 | var imgElement: any = document.createElement("img"); 1075 | imgElement.setAttribute("id", nodeid); 1076 | imgElement.setAttribute("src", "./build/img/pdf.png"); 1077 | 1078 | linkElement.appendChild(imgElement); 1079 | var selection = this.findNodeByAttribute("nodeid", nodeid); 1080 | selection.appendChild(linkElement); 1081 | } 1082 | } 1083 | 1084 | /** 1085 | * used for creating new project window 1086 | */ 1087 | public windowNewProject() { 1088 | $("#myModal").modal(); 1089 | (document.getElementById("projectName")).value = "MyThesis"; 1090 | (document.getElementById("projectPdf")).value = ""; 1091 | (document.getElementById("projectHome")).value = ""; 1092 | } 1093 | 1094 | /** 1095 | * used for opening existing project window 1096 | */ 1097 | public windowOpenProject() { 1098 | var input = $(document.getElementById('file-chooser')); 1099 | input.trigger("click"); // opening dialog 1100 | } 1101 | 1102 | /** 1103 | * set listener of the JsMind and make changes during drag and drop of the annotations into JsMind 1104 | */ 1105 | public setJsmindListener() { 1106 | var self = this; 1107 | 1108 | _jm.add_event_listener(function () { 1109 | self.setContextMenu(); 1110 | var nodes = $('#annotation-group').get(); 1111 | var children = nodes[0].children; 1112 | // Update the annotation panel on each MindMap addition event (when mindmap has been dropped, annotation in the sidebar will be hide) 1113 | for (var i = 0; i < children.length; i++) { 1114 | var tempNode = children[i]; 1115 | if (_jm.mind.nodes[tempNode.id]) { 1116 | $('#' + tempNode.id).removeClass("show"); 1117 | $('#' + tempNode.id).addClass("hide"); 1118 | //$('#' + tempNode.id).hide(); 1119 | } else { 1120 | $('#' + tempNode.id).removeClass("hide"); 1121 | $('#' + tempNode.id).addClass("show"); 1122 | //$('#' + tempNode.id).show(); 1123 | } 1124 | } 1125 | 1126 | guiSideBar.setAnnotationTitleVisibility(); 1127 | 1128 | self.setElementVisibility(); 1129 | 1130 | }); 1131 | 1132 | 1133 | $('#wrapper').click(function(){ 1134 | $('#contextMenu').hide(); 1135 | }); 1136 | } 1137 | 1138 | /** 1139 | * set listener of the context menu (when user do right click) 1140 | */ 1141 | public setContextMenu() { 1142 | jmnodes = document.querySelectorAll('jmnode'); 1143 | for (var i = 0; i < jmnodes.length; i++) { 1144 | // Not efficient, need to figure out another way to do this. 1145 | jmnodes[i].oncontextmenu = function (e) { 1146 | e.preventDefault(); 1147 | if (e.target.getAttribute('pdfid') != 'undefined') { 1148 | $('#contextMenu .actionOpenPdf').show(); 1149 | } else { 1150 | $('#contextMenu .actionOpenPdf').hide(); 1151 | } 1152 | $('#contextMenu').show(); 1153 | $('#contextMenu').css({ position: 'absolute', marginLeft: e.clientX, marginTop: e.clientY - 45 }); 1154 | contextMenu.setTempBoard(e.target.innerHTML); 1155 | } 1156 | } 1157 | } 1158 | 1159 | /** 1160 | * Used for creating shaking effect into modal 1161 | * @param id 1162 | */ 1163 | public setEffectShaking(id: string) { 1164 | var element: any = document.getElementById(id); 1165 | $(element).effect("shake"); 1166 | } 1167 | 1168 | /** 1169 | * populate all elements and deciding the visibility 1170 | */ 1171 | public setElementVisibility() { 1172 | // set show all elements that have show attribute 1173 | var nodesShow = $('.show').get(); 1174 | if ((nodesShow != undefined) && (nodesShow != null)) { 1175 | for (var j = 0; j < nodesShow.length; j++) { 1176 | var tempNodeShow = nodesShow[j]; 1177 | this.setShowHide(tempNodeShow, "show"); 1178 | } 1179 | } 1180 | 1181 | 1182 | // set hide all elements that have hide attribute 1183 | var nodesHide = $('.hide').get(); 1184 | if ((nodesHide != undefined) && (nodesHide != null)) { 1185 | for (var j = 0; j < nodesHide.length; j++) { 1186 | var tempNodeHide = nodesHide[j]; 1187 | this.setShowHide(tempNodeHide, "hide"); 1188 | } 1189 | } 1190 | 1191 | } 1192 | 1193 | /** 1194 | * set whether the element is visible or hide 1195 | * @param elementName 1196 | * @param mode 1197 | */ 1198 | private setShowHide(elementName: string, mode: string) { 1199 | if (mode == "hide") { 1200 | $(elementName).hide(); 1201 | } else { 1202 | $(elementName).show(); 1203 | } 1204 | } 1205 | 1206 | /** 1207 | * to load recent project for the recent project in project 1208 | */ 1209 | public loadRecentProjects() { 1210 | var data = []; 1211 | var fs = require('fs'); 1212 | try { 1213 | 1214 | data = JSON.parse(fs.readFileSync('./projects.json')); 1215 | } catch (e) { } 1216 | if (data.length == 0) { 1217 | $('#recentProjectsList').html('
  •   No Projects
  • '); 1218 | } else { 1219 | var projectList: any = data.map(function (each) { 1220 | return `
  •   ${each.projectName} (${each.projectFilePath})
  • `; 1221 | }); 1222 | $('#recentProjectsList').html(projectList.join('')); 1223 | } 1224 | } 1225 | 1226 | /** 1227 | * Routine to find Node of the mindmap by its attribute's name (ex:nodeid, topic, pdfid) 1228 | * @param attr 1229 | * @param val 1230 | * @returns {any} 1231 | */ 1232 | public findNodeByAttribute(attr: any, val: string): any { 1233 | var All: any = document.getElementsByTagName('jmnode'); 1234 | 1235 | for (var i = 0; i < All.length; i++) { 1236 | if (All[i].getAttribute(attr) == val) { return All[i]; } 1237 | } 1238 | 1239 | } 1240 | } 1241 | 1242 | /** 1243 | * Used when users do right click (to select some menus) 1244 | */ 1245 | class ContextMenu extends Gui { 1246 | 1247 | private tempBoard: string; 1248 | private clipBoard: string; 1249 | 1250 | /** 1251 | * to save the current copied data into clipboard 1252 | * @param input 1253 | */ 1254 | public setTempBoard(input: string) { 1255 | this.tempBoard = input; 1256 | } 1257 | 1258 | public setClipBoard() { 1259 | this.clipBoard = this.tempBoard; 1260 | } 1261 | 1262 | public getClipBoard(): string { 1263 | return this.clipBoard; 1264 | } 1265 | 1266 | /** 1267 | * actual routine for copy 1268 | */ 1269 | public actionCopy() { 1270 | this.setClipBoard(); 1271 | $('#contextMenu').hide(); 1272 | } 1273 | 1274 | /** 1275 | * actual routine for paste 1276 | * @param project 1277 | */ 1278 | public actionPaste(project: any) { 1279 | var selected_node = _jm.get_selected_node(); // select node when mouseover 1280 | var topic = this.getClipBoard(); 1281 | _jm.add_node(selected_node, Date.now(), topic, '', ''); 1282 | project.setProjectStatus('edited'); 1283 | $('#contextMenu').hide(); 1284 | } 1285 | 1286 | /** 1287 | * open the pdf based on selected node using pdfjs viewer 1288 | * @param directory 1289 | */ 1290 | public actionOpenPdf(directory: string) { 1291 | var selected_node = _jm.get_selected_node(); // select node when mouseover 1292 | var pdfViewer: string = "./build/pdf.js/web/viewer.html"; 1293 | var fileName: string = null; 1294 | var page: string = null; 1295 | if ((selected_node.pdfid != null) && (selected_node.pdfid != undefined)) { fileName = "?file=" + selected_node.pdfid; page = "#page=" + selected_node.index; } 1296 | else { 1297 | var id_temp = selected_node.id; 1298 | var temp_element = gui.findNodeByAttribute("id", id_temp); 1299 | var temp_html = temp_element.outerHTML; 1300 | fileName = temp_html.substring(temp_html.indexOf("?file="), temp_html.indexOf("target=")); 1301 | page = null; 1302 | } 1303 | 1304 | window.open(pdfViewer + fileName + page, "_blank", "toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width=1000, height=1000"); 1305 | $('#contextMenu').hide(); 1306 | } 1307 | 1308 | /** 1309 | * open the pdf based on selected node using user defined pdf viewer 1310 | * @param directory 1311 | */ 1312 | public actionOpenPdfUserDefine(directory: string) { 1313 | var selected_node = _jm.get_selected_node(); 1314 | const { shell } = require('electron'); 1315 | 1316 | var fileName: string = null; 1317 | if ((selected_node.pdfid != null) && (selected_node.pdfid != undefined)) { fileName = selected_node.pdfid } 1318 | else { 1319 | var id_temp = selected_node.id; 1320 | var temp_element = gui.findNodeByAttribute("id", id_temp); 1321 | var temp_html = temp_element.outerHTML; 1322 | fileName = temp_html.substring(temp_html.indexOf("pdfid=") + 7, temp_html.indexOf("style=") - 2); 1323 | } 1324 | shell.openItem(fileName); 1325 | $('#contextMenu').hide(); 1326 | } 1327 | 1328 | /** 1329 | * actual cancel routine 1330 | */ 1331 | public actionCancel() { 1332 | $('#contextMenu').hide(); 1333 | } 1334 | 1335 | /** 1336 | * actual delete node routine 1337 | */ 1338 | public actionDelete() { 1339 | var selected_node = _jm.get_selected_node(); 1340 | var selected_id = selected_node.id; 1341 | if (!selected_id) { gui.windowAlert('please select a node first.'); return; } 1342 | 1343 | _jm.remove_node(selected_id); 1344 | project.setTempSaveProject("chgProject"); 1345 | $('#contextMenu').hide(); 1346 | } 1347 | } 1348 | 1349 | /** 1350 | * All Operations related to the Menu GUI 1351 | */ 1352 | class MindmapMenu extends Gui { 1353 | private jsMindObject: any; 1354 | private fileTypeSave: string; 1355 | 1356 | constructor(jsMindObject) { 1357 | super(); 1358 | this.jsMindObject = jsMindObject; 1359 | } 1360 | 1361 | /** 1362 | * saving the state of filetype (.jm or .mm) 1363 | * @param input 1364 | */ 1365 | public setFileTypeSave(input: string) { 1366 | this.fileTypeSave = input; 1367 | } 1368 | 1369 | /** 1370 | * getting the state of filetype 1371 | */ 1372 | public getFileTypeSave(): string { 1373 | return this.fileTypeSave; 1374 | } 1375 | 1376 | /** 1377 | * setting a new mindmap with only root file 1378 | * @param project 1379 | * @param rootName 1380 | */ 1381 | public newMap(project: any, rootName: string) { 1382 | var mindmap = { 1383 | "meta": { 1384 | "name": "jsMind", 1385 | "version": "0.2" 1386 | }, 1387 | "format": "node_tree", 1388 | "data": { "id": "root", "topic": rootName, "children": [] } 1389 | }; 1390 | this.jsMindObject.show(mindmap); 1391 | (document.querySelector('#mindmap-chooser')).value = '';// Reset the file selector 1392 | if ((project != null) || (project != undefined)) { project.setProjectStatus('edited'); } 1393 | } 1394 | 1395 | // loading State of JsMind which will be implemented into .jm or .mm 1396 | public loadFile(fileType: string): string { 1397 | var mind_data: any; 1398 | var mind_object = this.getJsMindData(); 1399 | 1400 | this.setFileTypeSave(fileType); 1401 | 1402 | if (fileType === 'jm') { 1403 | mind_data = mind_object.get_data(); 1404 | } else { 1405 | mind_data = mind_object.get_data('freemind'); 1406 | } 1407 | var mind_str = (fileType === 'jm') ? jsMind.util.json.json2string(mind_data) : mind_data.data; 1408 | 1409 | return mind_str; 1410 | } 1411 | 1412 | /** 1413 | * Saving .mm or .jm file implementation 1414 | */ 1415 | public saveFile(fileType: string, mind_str): string { 1416 | // Saving State into Project 1417 | project.setProjectSavedFileLocation(path.join(project.getProjectLocation(), project.getProjectName()) + "." + fileType); 1418 | project.setSaveProject(); 1419 | project.setProjectStatus('noedit'); 1420 | util.writeAnyTypeFile(project.getProjectLocation(), mind_str, project.getProjectName(), fileType); 1421 | 1422 | return (path.join(project.getProjectLocation(), project.getProjectName()) + "." + fileType) 1423 | } 1424 | 1425 | /** 1426 | * get data from JsMind 1427 | */ 1428 | public getJsMindData(): any { 1429 | var mindmapData: any; 1430 | mindmapData = this.jsMindObject; 1431 | return mindmapData; 1432 | } 1433 | 1434 | /** 1435 | * selecting a file from open mind map 1436 | */ 1437 | public selectFile() { 1438 | var file_input = document.getElementById('mindmap-chooser'); 1439 | file_input.click(); 1440 | } 1441 | 1442 | /** 1443 | * set listener to the open mindmap 1444 | */ 1445 | public setOpenFileListener() { 1446 | var self = this; 1447 | var mindMapChooser = document.getElementById('mindmap-chooser'); 1448 | 1449 | mindMapChooser.addEventListener('change', function (event) { 1450 | var files: FileList = mindMapChooser.files; 1451 | if (files.length <= 0) { 1452 | gui.windowAlert('please choose a file first') 1453 | } 1454 | 1455 | var file_data = files[0]; 1456 | if (/.*\.mm$/.test(file_data.name)) { 1457 | jsMind.util.file.read(file_data, function (freemind_data, freemind_name) { 1458 | self.loadFileJsMind(freemind_data, "mm", freemind_name); 1459 | }); 1460 | } else { 1461 | jsMind.util.file.read(file_data, function (jsmind_data, jsmind_name) { 1462 | self.loadFileJsMind(jsmind_data, "jm", jsmind_name); 1463 | }); 1464 | } 1465 | 1466 | }); 1467 | } 1468 | 1469 | /** 1470 | * loading all jsmind contents and view it into GUI 1471 | * @param content 1472 | * @param type 1473 | * @param freemind_name 1474 | */ 1475 | public loadFileJsMind(content: any, type: string, freemind_name: any): any { 1476 | if (type == "mm") { 1477 | var freemind_data = content; 1478 | if (freemind_data) { 1479 | var mind_name = freemind_name.substring(0, freemind_name.length - 3); 1480 | var mind = { 1481 | "meta": { 1482 | "name": mind_name, 1483 | "author": "user@gmail.com", 1484 | "version": "1.0.1" 1485 | }, 1486 | "format": "freemind", 1487 | "data": freemind_data 1488 | }; 1489 | _jm.show(mind); 1490 | } else { 1491 | alert('The selected file is not supported'); 1492 | } 1493 | } else { 1494 | var jsmind_data = content; 1495 | mind = jsMind.util.json.string2json(jsmind_data); 1496 | if (!!mind) { 1497 | _jm.show(mind); 1498 | } else { 1499 | alert('The selected file is not supported'); 1500 | } 1501 | } 1502 | 1503 | return mind; 1504 | } 1505 | } 1506 | 1507 | /** 1508 | * For the creation of the side bar GUI 1509 | */ 1510 | class GuiSideBar extends Gui { 1511 | 1512 | private basicHtmlTitle: any; 1513 | private basicHtmlContent: any; 1514 | 1515 | /** 1516 | * Initilize the Sidebar for the first time or when Refresh 1517 | * @param data 1518 | * @param directory 1519 | */ 1520 | public setGuiInit(data: string, directory: string) { 1521 | $("#loading-data").remove(); 1522 | $("#drag").remove(); 1523 | 1524 | var util = new Utils(); 1525 | 1526 | // Parse JSON File 1527 | var objekt = util.parseJsonFile(data); 1528 | var titleFile: any = null; 1529 | 1530 | for (var i = 0; i < objekt.length; i++) { 1531 | var tempObject = objekt[i]; 1532 | titleFile = this.setDynamicHtmlTitle(util, tempObject["filename"], tempObject["filename"]) 1533 | } 1534 | 1535 | $(titleFile).appendTo("#annotation-group"); 1536 | 1537 | this.setDynamicHtml(objekt, "init", directory); 1538 | 1539 | } 1540 | 1541 | /** 1542 | * Adding GUI on SideBar when refreshAnnotation is done 1543 | * @param object 1544 | * @param directory 1545 | */ 1546 | public setGuiOnAppend(object: any, directory: string) { 1547 | this.setDynamicHtml(object, "append", directory); 1548 | } 1549 | 1550 | /** 1551 | *Clear the side bar annotation tab 1552 | */ 1553 | public resetSidebarAnnotation() { 1554 | $("#annotation-group").empty(); 1555 | } 1556 | 1557 | /** 1558 | * check if the SideBar Nodes have existed 1559 | * if no then do refresh 1560 | * if yes then do refreshAnnotation 1561 | */ 1562 | public checkSideBar(): boolean { 1563 | var isSideBarExist: boolean = false; 1564 | var nodes: any = $('.drag').get(); 1565 | 1566 | if (nodes.length != 0) { 1567 | isSideBarExist = true; 1568 | } 1569 | 1570 | return isSideBarExist; 1571 | } 1572 | 1573 | /** 1574 | * Is used for searching the annotation using a form and button search 1575 | * @param directory 1576 | */ 1577 | public searchAnnotation(directory: string) { 1578 | var keyword: string = (document.getElementById("annotSearch")).value; 1579 | if (keyword == "") { 1580 | this.resetSidebarAnnotation(); 1581 | programCaller("refreshAll"); 1582 | } else { 1583 | var listAnnotation: any = document.querySelectorAll("#annotation-group"); 1584 | var list: any = listAnnotation[0].children; 1585 | var nodeObject: NodesObject = null; 1586 | var temp: any = []; 1587 | for (var i = 0; i < listAnnotation[0].children.length; i++) { 1588 | var value = listAnnotation[0].children[i].innerHTML; 1589 | if (value.toLowerCase().includes(keyword.toLowerCase()) == true) { 1590 | temp.push({ 1591 | filename: listAnnotation[0].children[i].getAttribute("filename"), 1592 | id: listAnnotation[0].children[i].id, 1593 | topic: value, 1594 | subtype: "", 1595 | title: "", 1596 | pagenumber: listAnnotation[0].children[i].value 1597 | }); 1598 | } 1599 | } 1600 | 1601 | // Set The GUI based on selected annotation 1602 | this.resetSidebarAnnotation(); 1603 | this.setGuiInit(util.setJsonFile(temp), directory); 1604 | } 1605 | } 1606 | 1607 | /** 1608 | * Set Treeview in sidebar project tab based on input data in JSON Format (root.json) 1609 | * @param input 1610 | */ 1611 | 1612 | public openTreeView(input: string) { 1613 | $('#tree').treeview({ data: input }); 1614 | } 1615 | 1616 | /** 1617 | * Set listener to the treeview (when selected or unselected mode) 1618 | */ 1619 | public setTreeViewListener() { 1620 | // when a project in tab project section treeview has been selected 1621 | $('#tree').on('nodeSelected', function (event, data) { 1622 | if (data.href == undefined) { 1623 | if (project.getProjectName() == data.text) { 1624 | // do nothing 1625 | } else { 1626 | project.openProjectFromTreeView(data.text); 1627 | } 1628 | } 1629 | }); 1630 | } 1631 | 1632 | /** 1633 | * Clear Treeview in sidebar project tab 1634 | */ 1635 | public resetTreeView() { 1636 | $('#tree').treeview({ data: "" }); 1637 | } 1638 | 1639 | /** 1640 | * Create bootstrap treeview file & populate file from all pdf lists 1641 | * @param projectName 1642 | * @param projectLoc 1643 | * @param listFiles 1644 | */ 1645 | public setTreeView(projectName: string, projectLoc: string, listFiles: string[]) { 1646 | var itemDirProject: any = []; 1647 | var tempNodeName: any = []; 1648 | 1649 | // populate the JSON data for the new opened treeview 1650 | for (var j = 0; j < listFiles.length; j++) { 1651 | tempNodeName.push({ 1652 | text: listFiles[j], 1653 | icon: "glyphicon glyphicon-file", 1654 | href: path.join(projectLoc, listFiles[j]) 1655 | }); 1656 | } 1657 | 1658 | itemDirProject.push({ 1659 | text: projectName, 1660 | state: { selected: true }, 1661 | nodes: tempNodeName 1662 | }); 1663 | 1664 | var resultDir: string = util.setJsonFile(itemDirProject); 1665 | var currentDir: string = project.getProjectTreeView(); 1666 | var statusExist: boolean = false; 1667 | 1668 | /** 1669 | * Select and unselect the project automation process 1670 | */ 1671 | try { 1672 | if ((currentDir != null) && (currentDir != undefined) && (currentDir != "")) { 1673 | var currentDirObject = JSON.parse(currentDir); 1674 | for (var x = 0; x < currentDirObject.length; x++) { 1675 | currentDirObject[x].state.selected = false; 1676 | } 1677 | currentDir = JSON.stringify(currentDirObject); 1678 | } 1679 | } catch (e) { 1680 | gui.windowAlert(e); 1681 | } 1682 | 1683 | /** 1684 | * check whether the project has exist or not 1685 | */ 1686 | try { 1687 | if ((currentDir != null) && (currentDir != undefined) && (currentDir != "") && (resultDir != null) && (resultDir != undefined) && (resultDir != "")) { 1688 | var currentDirObject = JSON.parse(currentDir); 1689 | var resultDirObject = JSON.parse(resultDir); 1690 | 1691 | for (var x = 0; x < currentDirObject.length; x++) { 1692 | if (currentDirObject[x].text == resultDirObject[0].text) { 1693 | 1694 | // set all state to false 1695 | for (var p = 0; p < currentDirObject.length; p++) { 1696 | currentDirObject[p].state.selected = false; 1697 | } 1698 | 1699 | currentDirObject[x].state.selected = true; 1700 | currentDir = JSON.stringify(currentDirObject); 1701 | this.openTreeView(currentDir); 1702 | this.setTreeViewListener(); 1703 | statusExist = true; 1704 | 1705 | // stop next sequence and return to caller 1706 | return; 1707 | } 1708 | } 1709 | } 1710 | } catch (e) { 1711 | gui.windowAlert(e); 1712 | } 1713 | 1714 | // append the JSON if there is still current directory exist 1715 | if ((currentDir != null) && (currentDir != "") && (currentDir != undefined)) { 1716 | resultDir = util.concatJsonFiles(currentDir); 1717 | } 1718 | 1719 | /** 1720 | * the rest operations after opening new treeview 1721 | */ 1722 | this.openTreeView(resultDir); 1723 | // set listener for tree view changes 1724 | this.setTreeViewListener(); 1725 | 1726 | listPdf.setListPdfFile(listFiles); 1727 | listPdf.setLastModDate(listPdf.getModDateFs(util, project.getProjectSavedPdfLocation(), listFiles)); 1728 | project.setProjectTreeView(resultDir); 1729 | } 1730 | 1731 | /** 1732 | * recreate the treeview after a project is being closed 1733 | */ 1734 | public setReCreateTreeView(): any { 1735 | try { 1736 | var tempTreeView: any = JSON.parse(project.getProjectTreeView()); 1737 | } catch (e) { 1738 | alert(e); 1739 | } 1740 | 1741 | var idx: number = gui.getJsMindOpenProject(); 1742 | if (idx > 0) { 1743 | var tempOpenProjectName: string = gui.getMindProjectName(idx); 1744 | var newTreeViewList: any = new Array(); 1745 | var j = 0; 1746 | for (var i = 1; i <= tempTreeView.length; i++) { 1747 | if (tempTreeView[i - 1].text != tempOpenProjectName) { 1748 | newTreeViewList[j] = tempTreeView[i - 1]; 1749 | j++; 1750 | } 1751 | } 1752 | 1753 | var tempTreeViewString = JSON.stringify(newTreeViewList); 1754 | this.openTreeView(tempTreeViewString); 1755 | project.setProjectTreeView(tempTreeViewString); 1756 | } else { 1757 | newTreeViewList = new Array(); 1758 | } 1759 | return newTreeViewList; 1760 | } 1761 | 1762 | 1763 | /** 1764 | * Set the dynamic HTML for the input of the object 1765 | * @param objekt 1766 | * @param mode 1767 | * @param directory 1768 | */ 1769 | private setDynamicHtml(objekt: NodesObject, mode: string, directory: string) { 1770 | var node; 1771 | for (var i = 0; i < objekt.length; i++) { 1772 | var input = objekt[i]; 1773 | var annot = new Annotation(input["filename"], input["id"], input["topic"], input["subtype"], input["title"], input["pagenumber"]) 1774 | node = new Nodes(annot.getId(), annot.getTopic(), annot.getFileName(), annot.getPageNumber()); 1775 | // All annotations must exist in the Sidebar, whether hidden or visible 1776 | if (!this.checkAnnotationExistInSidebar(node.getId())) { 1777 | // If the annotation does not exist in JsMind then add it to sidebar 1778 | this.setDynamicHtmlContent(node, "#annotation-group", "list-group-item drag", mode, directory); 1779 | } 1780 | // Based on whether the annotation exists in mindmap or not, toggle the visibility 1781 | if (this.checkJsmindNode(node.getId())) { 1782 | $('#' + node.getId()).removeClass('show'); 1783 | $('#' + node.getId()).addClass('hide'); 1784 | } else { 1785 | $('#' + node.getId()).removeClass("hide"); 1786 | $('#' + node.getId()).addClass('show'); 1787 | } 1788 | } 1789 | 1790 | this.setAnnotationTitleVisibility(); 1791 | this.setElementVisibility(); 1792 | } 1793 | 1794 | /** 1795 | * Set the dynamic HTML for the title so called pdf name 1796 | * @param util 1797 | * @param id 1798 | * @param fileName 1799 | * @returns {string} 1800 | */ 1801 | private setDynamicHtmlTitle(util, id: string, fileName: string): string { 1802 | var pdfId = util.getHashFunction(id); 1803 | var htmlContent = document.createElement("li"); 1804 | htmlContent.setAttribute("id", pdfId); 1805 | htmlContent.setAttribute("name", "pdf-title"); 1806 | htmlContent.setAttribute("class", "pdf-title show"); 1807 | htmlContent.setAttribute("style", 'cursor: no-drop; background-color: #ccc; padding: 10px 18px; font-weight:bold'); 1808 | htmlContent.innerHTML = fileName; 1809 | this.basicHtmlTitle = htmlContent; 1810 | return this.basicHtmlTitle; 1811 | } 1812 | 1813 | /** 1814 | * real routine to set the dynamic HTML for the annotation contents 1815 | * @param node 1816 | * @param appendToName 1817 | * @param className 1818 | * @param mode 1819 | * @param directory 1820 | */ 1821 | private setDynamicHtmlContent(node, appendToName: string, className: string, mode: string, directory: string) { 1822 | var htmlContent = document.createElement("li"); 1823 | htmlContent.setAttribute("id", node.getId()); 1824 | htmlContent.setAttribute("name", "annotation"); 1825 | htmlContent.setAttribute("pagenumber", node.getPageNumber()); 1826 | htmlContent.setAttribute("filename", node.getFileName()); 1827 | htmlContent.setAttribute("parentid", util.getHashFunction(node.getFileName())); 1828 | htmlContent.value = node.getPageNumber(); 1829 | htmlContent.innerHTML = node.getTopic(); 1830 | htmlContent.title = path.join(directory, node.getFileName()); 1831 | this.basicHtmlContent = htmlContent; 1832 | 1833 | if (mode == "init") { 1834 | $(this.basicHtmlContent).appendTo(appendToName); 1835 | } else { 1836 | var temp = node.getFileName(); 1837 | var pdfId = util.getHashFunction(temp); 1838 | $(this.basicHtmlContent).insertAfter('#' + pdfId); 1839 | } 1840 | 1841 | $(this.basicHtmlContent).draggable(node.setDraggable()); 1842 | $(this.basicHtmlContent).droppable(node.setDroppable()); 1843 | document.getElementById(node.getId()).className += " " + className; 1844 | } 1845 | 1846 | 1847 | /** 1848 | * setting the annotation-title visibility 1849 | */ 1850 | public setAnnotationTitleVisibility() { 1851 | // Update the annotation panel on section pdf-title on each MindMap addition event (if all annotations is in the JsMind, then hide pdf-title) 1852 | var nodesTitle = $('.pdf-title').get(); 1853 | for (var j = 0; j < nodesTitle.length; j++) { 1854 | $('#' + nodesTitle[j].id).removeClass("hide"); 1855 | $('#' + nodesTitle[j].id).addClass("show"); 1856 | var results = guiSideBar.findGuiAnnotationByAttribute('annotation', 'parentid', nodesTitle[j].id); 1857 | if ((results != undefined) && (results != null)) { 1858 | var count: number = 0; 1859 | for (var x = 0; x < results.length; x++) { 1860 | if (results[x].getAttribute('class').indexOf('hide') != -1) { 1861 | count++; 1862 | } 1863 | } 1864 | if (results.length == count) { 1865 | $('#' + nodesTitle[j].id).removeClass("show"); 1866 | $('#' + nodesTitle[j].id).addClass("hide"); 1867 | } 1868 | } 1869 | } 1870 | } 1871 | 1872 | /** 1873 | *Check whether the nodes already in the jsmind tree in the right side or not 1874 | * @param id 1875 | * @returns {boolean} 1876 | */ 1877 | private checkJsmindNode(id: string): boolean { 1878 | return !!_jm.mind.nodes[id]; 1879 | } 1880 | 1881 | /** 1882 | *Check whether the nodes already in the Annotations List in the left side or not 1883 | * @param id 1884 | * @returns {boolean} 1885 | */ 1886 | public checkAnnotationExistInSidebar(id: string): boolean { 1887 | // Get the IDs of all annotations in the sidebar 1888 | var nodesInSidebar = $('.list-group-item').get().map(function (eachNode) { 1889 | return eachNode.id; 1890 | }); 1891 | return (nodesInSidebar.indexOf(id) != -1); 1892 | } 1893 | 1894 | /** 1895 | * to find the annotation in guisidebar by its attribute 1896 | * @param attr 1897 | * @param val 1898 | */ 1899 | public findGuiAnnotationByAttribute(name: string, attr: any, val: string): any { 1900 | var All: any = document.getElementsByName(name); 1901 | var tempResult = []; 1902 | 1903 | for (var i = 0; i < All.length; i++) { 1904 | if (All[i].getAttribute(attr) == val) { 1905 | tempResult.push(All[i]); 1906 | } 1907 | } 1908 | 1909 | return tempResult; 1910 | } 1911 | 1912 | } 1913 | 1914 | /** 1915 | * All operations with Project 1916 | */ 1917 | class Project { 1918 | private projectName: string; // to save the name of a project 1919 | private projectLocation: string; // to save the folder location of a project 1920 | private projectPdfList: string[]; // to save the pdf filename lists of a project 1921 | private projectStatus: string; // to save whether the project has been edited or not 1922 | private projectSavedFileLocation: string // to save the location of .mm or .jm file 1923 | private projectSavedPDFLocation: string // to save the location of PDFs file 1924 | private projectTreeView: string // to save treeview JSON file 1925 | private projectPromises: any[] // to save new Project promises (for saving home folder & pdfs) 1926 | 1927 | constructor() { 1928 | this.projectPdfList = new Array(); 1929 | this.projectPromises = new Array(); 1930 | this.projectStatus = "noedit"; 1931 | this.projectTreeView = ""; 1932 | this.projectName = ""; 1933 | this.projectLocation = ""; 1934 | this.projectSavedFileLocation = ""; 1935 | this.projectSavedPDFLocation = ""; 1936 | } 1937 | 1938 | /** 1939 | * to save the project name 1940 | * @param input 1941 | */ 1942 | public setProjectName(input: string) { 1943 | this.projectName = input; 1944 | } 1945 | /** 1946 | * to get the project name 1947 | */ 1948 | public getProjectName(): string { 1949 | return this.projectName; 1950 | } 1951 | /** 1952 | * to save the project location 1953 | * @param input 1954 | */ 1955 | public setProjectLocation(input: string) { 1956 | input = path.normalize(input); 1957 | this.projectLocation = input; 1958 | } 1959 | /** 1960 | * to get the project location 1961 | */ 1962 | public getProjectLocation(): string { 1963 | return this.projectLocation; 1964 | } 1965 | /** 1966 | * to save list of pdf files of a project 1967 | * @param input 1968 | */ 1969 | public setProjectPdfList(input: string[]) { 1970 | for (var i = 0; i < input.length; i++) { 1971 | this.projectPdfList[i] = input[i]; 1972 | } 1973 | } 1974 | /** 1975 | * to get the list of pdf files of a project 1976 | */ 1977 | public getProjectPdfList(): string[] { 1978 | return this.projectPdfList; 1979 | } 1980 | 1981 | /** 1982 | * to set the status of the project (edited or noedit) 1983 | * @param input 1984 | */ 1985 | public setProjectStatus(input: string) { 1986 | this.projectStatus = input; 1987 | } 1988 | 1989 | /** 1990 | * to get the status of the project 1991 | */ 1992 | public getProjectStatus(): string { 1993 | return this.projectStatus; 1994 | } 1995 | 1996 | /** 1997 | * to save the file (.mm or .jm) location 1998 | */ 1999 | public setProjectSavedFileLocation(input: string) { 2000 | input = path.normalize(input); 2001 | this.projectSavedFileLocation = input; 2002 | } 2003 | 2004 | /** 2005 | * to get the file (.mm or .jm) location 2006 | */ 2007 | public getProjectSavedFileLocation(): string { 2008 | return this.projectSavedFileLocation; 2009 | } 2010 | 2011 | /** 2012 | * to save the PDFs file location 2013 | * @param input 2014 | */ 2015 | public setProjectSavedPdfLocation(input: string) { 2016 | input = path.normalize(input); 2017 | this.projectSavedPDFLocation = input; 2018 | } 2019 | 2020 | /** 2021 | * to get the PDFs file location 2022 | */ 2023 | public getProjectSavedPdfLocation(): string { 2024 | return this.projectSavedPDFLocation; 2025 | } 2026 | 2027 | /** 2028 | * to save the treeview JSON file 2029 | * @param input 2030 | */ 2031 | public setProjectTreeView(input: string) { 2032 | this.projectTreeView = input; 2033 | } 2034 | 2035 | /** 2036 | * to get the treeview JSON file 2037 | */ 2038 | public getProjectTreeView(): string { 2039 | return this.projectTreeView; 2040 | } 2041 | 2042 | /** 2043 | * to save some promises in the new project prompter which are used in a project 2044 | * @param input 2045 | */ 2046 | public setProjectPromises(input: any[]) { 2047 | for (var i = 0; i < input.length; i++) { 2048 | this.projectPromises[i] = input[i]; 2049 | } 2050 | } 2051 | 2052 | /** 2053 | * to get the saved promises in the new project prompter which are used in a project 2054 | */ 2055 | public getProjectPromises(): any[] { 2056 | return this.projectPromises; 2057 | } 2058 | 2059 | /** 2060 | * to validate & check the requirements for new project 2061 | */ 2062 | public checkNewProject(): boolean { 2063 | var checkStatus: boolean = true; 2064 | var parm1: string = (document.getElementById("projectName")).value; 2065 | var parm2: string = (document.getElementById("projectPdf")).value; 2066 | var parm3: string = (document.getElementById("projectHome")).value; 2067 | 2068 | $("p.ProjName").attr("hidden", true); 2069 | $("p.ProjPdf").attr("hidden", true); 2070 | $("p.ProjHome").attr("hidden", true); 2071 | 2072 | if (parm1 == "") { 2073 | checkStatus = false; 2074 | $("p.ProjName").attr("hidden", false); 2075 | } 2076 | 2077 | if (parm2 == "") { 2078 | checkStatus = false; 2079 | $("p.ProjPdf").attr("hidden", false); 2080 | } 2081 | 2082 | if (parm3 == "") { 2083 | checkStatus = false; 2084 | $("p.ProjHome").attr("hidden", false); 2085 | } 2086 | 2087 | if (checkStatus == false) { 2088 | gui.setEffectShaking("myModal"); 2089 | } else { 2090 | $("#myModal").modal('hide'); 2091 | } 2092 | 2093 | return checkStatus; 2094 | } 2095 | 2096 | /** 2097 | * when new project modal is opened 2098 | */ 2099 | public setNewProjectModal() { 2100 | gui.windowNewProject(); 2101 | this.setNewProjectListener(); 2102 | } 2103 | 2104 | /** 2105 | * Listener to the New Project 2106 | */ 2107 | private setNewProjectListener() { 2108 | var self = this; 2109 | var pathName: string = ""; 2110 | var dirProcess: any = null; 2111 | var promises: any[] = new Array(); 2112 | 2113 | var promise = new Promise(function (resolve, reject) { 2114 | $("#pdf-chooser").on("change", function (result) { 2115 | var lastResult: any[] = new Array; 2116 | var listFiles: string = ""; 2117 | pathName = result.target.files[0].path; 2118 | listPdf.setDirectory(pathName); 2119 | dirProcess = listPdf.getPdfFromFs(); 2120 | lastResult.push(pathName); 2121 | 2122 | Promise.all([dirProcess]).then(function (result) { 2123 | var temp = result[0]; 2124 | var arrayList: any = []; 2125 | 2126 | for (var i = 0; i < temp.length; i++) { 2127 | if (i == 0) { 2128 | listFiles += temp[i]; 2129 | } else { 2130 | listFiles += ", " + temp[i]; 2131 | } 2132 | arrayList[i] = temp[i]; 2133 | } 2134 | 2135 | (document.getElementById("projectPdf")).value = listFiles; 2136 | lastResult.push(arrayList); 2137 | resolve(lastResult); 2138 | }); 2139 | }); 2140 | 2141 | }); 2142 | 2143 | promises.push(promise); 2144 | 2145 | var promise2 = new Promise(function (resolve, reject) { 2146 | $("#folder-chooser").on("change", function (result) { 2147 | pathName = result.target.files[0].path; 2148 | (document.getElementById("projectHome")).value = pathName; 2149 | resolve(pathName); 2150 | }); 2151 | }); 2152 | 2153 | Promise.all([promise, promise2]).then(function (result) { 2154 | var tempResult: any = result[0]; 2155 | var tempResult2: any = result[1]; 2156 | self.projectPdfList = new Array(); 2157 | self.setProjectSavedPdfLocation(tempResult[0]); 2158 | self.setProjectPdfList(tempResult[1]); 2159 | self.setProjectLocation(tempResult2); 2160 | }); 2161 | 2162 | promises.push(promise2); 2163 | 2164 | this.setProjectPromises(promises); 2165 | } 2166 | 2167 | /** 2168 | * When save button is pressed in new project modal 2169 | */ 2170 | public createNewProject() { 2171 | var promises: any[] = this.getProjectPromises(); 2172 | var promise = promises[0]; 2173 | var promise2 = promises[1]; 2174 | var self = this; 2175 | 2176 | Promise.all([promise, promise2]).then(function (result) { 2177 | self.setProjectName((document.getElementById("projectName")).value); 2178 | self.saveProject(util, self.getProjectName(), self.getProjectLocation(), self.getProjectPdfList(), "", ""); 2179 | self.setProjectStatus("edited"); 2180 | mindmapMenu.newMap(self, self.getProjectName()); 2181 | guiSideBar.setTreeView(self.getProjectName(), self.getProjectLocation(), self.getProjectPdfList()); 2182 | self.setTempSaveProject("newProject"); 2183 | programCaller('refreshAll'); 2184 | $("#pdf-chooser").val(""); 2185 | $("#folder-chooser").val(""); 2186 | }); 2187 | } 2188 | 2189 | /** 2190 | * the routine called everywhere in order to save project 2191 | */ 2192 | public setSaveProject(): string { 2193 | var msg: string = this.getProjectLocation(); 2194 | var result = this.saveProject(util, this.getProjectName(), this.getProjectLocation(), this.getProjectPdfList(), this.getProjectSavedFileLocation(), this.getProjectSavedPdfLocation()); 2195 | util.writeAnyTypeFile(this.getProjectLocation(), result, this.getProjectName(), "json"); 2196 | return msg; 2197 | } 2198 | 2199 | /** 2200 | * real routine used for saving project and creating file (.json) in local 2201 | * @param util 2202 | * @param projectName 2203 | * @param projectLoc 2204 | * @param listFiles 2205 | * @param projectSavedFile 2206 | * @param projectSavedPdf 2207 | */ 2208 | private saveProject(util: any, projectName: string, projectLoc: string, listFiles: string[], projectSavedFile: string, projectSavedPdf: string): string { 2209 | var project: any = []; 2210 | var annotation: any = []; 2211 | var childnode: any = []; 2212 | var itemResult: any = []; 2213 | var nodes: any = []; 2214 | var counter: number = 0; 2215 | 2216 | // to convert JSON from Object to array file 2217 | var jsMindData: any = mindmapMenu.getJsMindData(); 2218 | var nodesJSON = jsMindData.mind.nodes; 2219 | for (var x in nodesJSON) { 2220 | nodes.push(nodesJSON[x]); 2221 | } 2222 | 2223 | // to populate the annotation section from .JSON file 2224 | for (var i = 0; i < nodes.length; i++) { 2225 | var temp = nodes[i]; 2226 | childnode = []; 2227 | if (temp.children.length == 0) { 2228 | childnode.push(""); 2229 | } else { 2230 | for (var j = 0; j < temp.children.length; j++) { 2231 | childnode.push([ 2232 | temp.children[j].id 2233 | ]); 2234 | } 2235 | 2236 | } 2237 | annotation.push(this.setArrayAnnotation(childnode, nodes, i)); 2238 | } 2239 | 2240 | // to populate the project section from .JSON file 2241 | project.push({ 2242 | name: projectName, 2243 | location: projectLoc, 2244 | savedfile: projectSavedFile, 2245 | savedPdf: projectSavedPdf, 2246 | files: listFiles 2247 | }); 2248 | 2249 | // build the JSON file with combine of project and annotation 2250 | itemResult.push({ 2251 | project, 2252 | annotation 2253 | }); 2254 | var result: string = util.setJsonFile(itemResult); 2255 | this.addToRecentProjects(projectName, path.join(projectLoc, projectName) + ".json"); 2256 | gui.loadRecentProjects(); 2257 | return result; 2258 | } 2259 | 2260 | /** 2261 | * routine for setting the array of annotations 2262 | * @param childnode 2263 | * @param nodes 2264 | * @param i 2265 | */ 2266 | private setArrayAnnotation(childnode: any, nodes: any, i: any): any { 2267 | var annotation: any = []; 2268 | annotation.push({ 2269 | id: nodes[i].id, 2270 | text: nodes[i].topic, 2271 | childnode, 2272 | file: nodes[i].pdfid, 2273 | page: nodes[i].index, 2274 | placed: nodes[i].expanded 2275 | }); 2276 | return annotation; 2277 | } 2278 | 2279 | /** 2280 | * to save temporary project for Multiple Project 2281 | * @param param 2282 | */ 2283 | public setTempSaveProject(param: string) { 2284 | 2285 | switch (param) { 2286 | 2287 | // when there is a change in the project, then save the last edited state of the project 2288 | case "chgProject": 2289 | var projectState = this.saveProject(util, this.getProjectName(), this.getProjectLocation(), this.getProjectPdfList(), this.getProjectSavedFileLocation(), this.getProjectSavedPdfLocation()); 2290 | var x = gui.getJsMindProjectNameState(this.getProjectName()); 2291 | 2292 | gui.setJsMindProjectState(projectState, x); 2293 | var jsMindState = mindmapMenu.loadFile("mm"); 2294 | gui.setJsMindSavedState(jsMindState, x); 2295 | var jsMindStatusState = this.getProjectStatus(); 2296 | gui.setJsMindStatusState(jsMindStatusState, x); 2297 | break; 2298 | 2299 | // when opening the project, then save the project before state before opening a new one 2300 | case "openProject": 2301 | var projectState = this.saveProject(util, this.getProjectName(), this.getProjectLocation(), this.getProjectPdfList(), this.getProjectSavedFileLocation(), this.getProjectSavedPdfLocation()); 2302 | var x = gui.getCountProjectStatesNumber(); 2303 | gui.setJsMindProjectNameState(this.getProjectName(), x); 2304 | 2305 | gui.setJsMindProjectState(projectState, x); 2306 | var jsMindState = mindmapMenu.loadFile("mm"); 2307 | gui.setJsMindSavedState(jsMindState, x); 2308 | var jsMindStatusState = this.getProjectStatus(); 2309 | gui.setJsMindStatusState(jsMindStatusState, x); 2310 | break; 2311 | 2312 | // when new project, save the last state of the before project (if any) and do new one 2313 | case "newProject": 2314 | var projectState = this.saveProject(util, this.getProjectName(), this.getProjectLocation(), this.getProjectPdfList(), this.getProjectSavedFileLocation(), this.getProjectSavedPdfLocation()); 2315 | var x = gui.getCountProjectStatesNumber(); 2316 | gui.setJsMindProjectNameState(this.getProjectName(), x); 2317 | 2318 | gui.setJsMindProjectState(projectState, x); 2319 | var jsMindState = mindmapMenu.loadFile("mm"); 2320 | gui.setJsMindSavedState(jsMindState, x); 2321 | var jsMindStatusState = this.getProjectStatus(); 2322 | gui.setJsMindStatusState(jsMindStatusState, x); 2323 | break; 2324 | } 2325 | 2326 | } 2327 | 2328 | /** 2329 | * The projects.json format looks like: 2330 | * { 2331 | * projectName: 'name', 2332 | * projectFilePath: '/project.json', 2333 | * } 2334 | * @param projectName 2335 | * @param projectFilePath 2336 | */ 2337 | public addToRecentProjects(projectName: string, projectFilePath: string) { 2338 | var data; 2339 | var files; 2340 | var fs = require('fs'); 2341 | try { 2342 | data = fs.readFileSync('./projects.json'); 2343 | } catch (e) { 2344 | fs.writeFileSync('./projects.json', '[]'); 2345 | data = '[]'; 2346 | } 2347 | var recentProjects = JSON.parse(data); 2348 | // Prevent duplicate entries during recent projects tab 2349 | var alreadyExists = recentProjects.filter(function (e) { return e.projectFilePath == projectFilePath }).length > 0; 2350 | if (alreadyExists) { return; } 2351 | recentProjects.push({ projectName, projectFilePath }); 2352 | fs.writeFileSync('./projects.json', JSON.stringify(recentProjects)); 2353 | } 2354 | 2355 | /** 2356 | * routine to open the project in the tab of recent projects 2357 | * @param projectFilePath 2358 | */ 2359 | public openRecentProject(projectFilePath: string) { 2360 | var self = this; 2361 | var fs = require('fs'); 2362 | fs.readFile(projectFilePath, function (err, data) { 2363 | if (err) { return console.error(err); } 2364 | self.openProject(data, self, null, null); 2365 | guiSideBar.setTreeView(self.getProjectName(), self.getProjectLocation(), self.getProjectPdfList()); 2366 | }); 2367 | } 2368 | 2369 | 2370 | /** 2371 | * when open project is pressed 2372 | */ 2373 | public setOpenProjectModal() { 2374 | gui.windowOpenProject(); 2375 | this.setOpenProjectListener(this); 2376 | } 2377 | 2378 | /** 2379 | * Listener of the open project 2380 | * @param self 2381 | */ 2382 | private setOpenProjectListener(self: any) { 2383 | $("#file-chooser").on("change", function (result) { 2384 | var fs = require("fs"); 2385 | var filePath = result.target.files[0].path; 2386 | console.log(result); 2387 | fs.readFile(filePath, function (err, data) { 2388 | if (err) { return console.error(err); } 2389 | self.clrProjectState(); 2390 | self.openProject(data, self, "listener", null); 2391 | guiSideBar.setTreeView(self.getProjectName(), self.getProjectLocation(), self.getProjectPdfList()); 2392 | }); 2393 | $("#file-chooser").val(""); 2394 | }); 2395 | } 2396 | 2397 | /** 2398 | * Open Project Main Program 2399 | * @param data 2400 | * @param self 2401 | * @param mode 2402 | * @param fileContent 2403 | */ 2404 | public openProject(data: string, self: any, mode: string, fileContent: string) { 2405 | var dataObject: object = util.parseJsonFile(data); 2406 | self.setProjectName(dataObject[0].project[0].name); 2407 | self.setProjectLocation(dataObject[0].project[0].location); 2408 | self.setProjectPdfList(dataObject[0].project[0].files); 2409 | self.setProjectSavedFileLocation(dataObject[0].project[0].savedfile); 2410 | self.setProjectSavedPdfLocation(dataObject[0].project[0].savedPdf); 2411 | 2412 | listPdf.listPdfFiles = new Array(); 2413 | listPdf.setDirectory(self.getProjectSavedPdfLocation()); 2414 | listPdf.setListPdfFile(self.getProjectPdfList()); 2415 | 2416 | if ((fileContent != null) && (fileContent != undefined)) { 2417 | // .mm file data is given from fileContent 2418 | mindmapMenu.loadFileJsMind(fileContent, "mm", fileName + "." + "mm"); 2419 | gui.loadPdfButton(dataObject); 2420 | 2421 | if (mode == "listener") { 2422 | self.setTempSaveProject("openProject"); 2423 | } 2424 | 2425 | programCaller('refreshAll'); 2426 | } else { 2427 | // fetch data from .jm or .mm file 2428 | var htmlContent: any = (document.getElementById('mindmap-chooser')); 2429 | var fileName: string = self.getProjectName(); 2430 | 2431 | // if there is no mindmap, savedFileLocation will be undefined 2432 | if (self.getProjectSavedFileLocation()) { 2433 | var content = util.readAnyTypeFile(self.getProjectSavedFileLocation(), 'utf8'); 2434 | } 2435 | 2436 | Promise.all([content]).then(function (result) { 2437 | if (self.getProjectSavedFileLocation()) { 2438 | if (self.getProjectSavedFileLocation().indexOf(".mm") == -1) { 2439 | // if file is not .mm 2440 | var type: string = "jm"; 2441 | } else { 2442 | //if file is .mm 2443 | type = "mm"; 2444 | } 2445 | 2446 | mindmapMenu.loadFileJsMind(result, type, fileName + "." + type); 2447 | 2448 | gui.loadPdfButton(dataObject); 2449 | } 2450 | 2451 | if (mode == "listener") { 2452 | self.setTempSaveProject("openProject"); 2453 | var idx: number = gui.getJsMindProjectNameState(self.getProjectName()); 2454 | gui.setJsMindOpenProject(idx); 2455 | } 2456 | 2457 | programCaller('refreshAll'); 2458 | }); 2459 | 2460 | } 2461 | 2462 | 2463 | } 2464 | 2465 | /** 2466 | * Opening Project Using TreeView Event Handler (when select a project in the treeview or close project) 2467 | * @param input 2468 | */ 2469 | public openProjectFromTreeView(input: string) { 2470 | var idx: number = gui.getJsMindProjectNameState(input); 2471 | if (idx > 0) { 2472 | gui.setJsMindOpenProject(idx); 2473 | // read from last state of the project 2474 | var lastProjectState = gui.getJsMindProjectState(idx); 2475 | var lastJsMindState = gui.getJsMindSavedState(idx); 2476 | var lastJsMindStatusState = gui.getJsMindStatusState(idx); 2477 | project.clrProjectState(); 2478 | project.openProject(lastProjectState, project, "chgProject", lastJsMindState); 2479 | project.setProjectStatus(lastJsMindStatusState); 2480 | } else { 2481 | // read from existing project file .json 2482 | var projFullPath: string = path.join(project.getProjectLocation(), input) + ".json"; 2483 | var content = util.readAnyTypeFile(projFullPath, "utf8"); 2484 | Promise.all([content]).then(function (result) { 2485 | project.clrProjectState(); 2486 | project.openProject(result[0], project, "chgProject", null); 2487 | }) 2488 | } 2489 | } 2490 | 2491 | /** 2492 | * When close project is pressed, recreate the treeview, set the opened project again and get the state of actual opened project 2493 | * @param status 2494 | */ 2495 | public setCloseProject(status: string) { 2496 | 2497 | if (status == "noedit") { 2498 | // do nothing 2499 | } else { 2500 | var closeProjectStatus = gui.windowConfirmation("you are about to close project, save changes?"); 2501 | if (closeProjectStatus) { 2502 | this.setSaveProject(); 2503 | if ((mindmapMenu.getFileTypeSave() != null)) { 2504 | var content = mindmapMenu.loadFile(mindmapMenu.getFileTypeSave()); 2505 | var locationFile = mindmapMenu.saveFile(mindmapMenu.getFileTypeSave(), content); 2506 | gui.windowAlert("file is saved in" + " " + locationFile); 2507 | } else { 2508 | gui.windowConfirmation('file has not been saved in .mm or .jm, save changes in .mm file instead?'); 2509 | var content = mindmapMenu.loadFile("mm"); 2510 | var locationFile = mindmapMenu.saveFile("mm", content); 2511 | gui.windowAlert("MM file is saved in" + " " + locationFile); 2512 | } 2513 | } 2514 | } 2515 | 2516 | this.setProjectStatus("noedit"); 2517 | guiSideBar.resetTreeView(); 2518 | var newList = guiSideBar.setReCreateTreeView(); 2519 | guiSideBar.resetSidebarAnnotation(); 2520 | if (newList.length != 0) { 2521 | gui.setReCreateState(newList); 2522 | var tempProjectName: string = gui.getMindProjectName(gui.getJsMindOpenProject()); 2523 | this.openProjectFromTreeView(tempProjectName); 2524 | guiSideBar.setTreeViewListener(); 2525 | } else { 2526 | mindmapMenu.newMap(project, "Root"); 2527 | project.clrProjectState(); 2528 | listPdf.clrListPdfState(); 2529 | } 2530 | } 2531 | 2532 | /** 2533 | * to clear some of the project states 2534 | */ 2535 | public clrProjectState() { 2536 | this.projectPdfList = new Array(); 2537 | this.projectPromises = new Array(); 2538 | this.projectName = null; 2539 | this.projectLocation = null; 2540 | this.projectStatus = "noedit"; 2541 | } 2542 | 2543 | } 2544 | 2545 | // ========================================================= // 2546 | // Interface Section 2547 | // ========================================================= // 2548 | 2549 | /** 2550 | * The template for the DragObject 2551 | */ 2552 | interface DragObject { 2553 | helper: string, 2554 | containment: string, 2555 | opacity: string, 2556 | revert: string, 2557 | appendTo: string, 2558 | stop: (ev: Event, ui) => string 2559 | } 2560 | /** 2561 | * Template for dropobject 2562 | */ 2563 | interface DropObject { 2564 | drop: (ev: Event, ui) => string 2565 | } 2566 | /** 2567 | *Tempate for nodeobject 2568 | */ 2569 | interface NodesObject extends Array { 2570 | filename: string, 2571 | id: string; 2572 | topic: string; 2573 | subtype: string; 2574 | title: string; 2575 | pagenumber: number; 2576 | } 2577 | 2578 | // ========================================================= // 2579 | // Function Section 2580 | // ========================================================= // 2581 | 2582 | var node: any; 2583 | var dir: string; 2584 | var listPdf: any = new ListPdf(new Array, new Array, dir); 2585 | var listAnnotation: any = new ListAnnotations(dir); 2586 | var util: any = new Utils(); 2587 | var contextMenu: any = new ContextMenu(); 2588 | var mindmapMenu: MindmapMenu; 2589 | var gui: any = null; 2590 | var guiSideBar: any = null; 2591 | var project: any = null; 2592 | var pdf: any = null; 2593 | 2594 | /** 2595 | * Main program, it is also called from the HTML file 2596 | * @param data 2597 | */ 2598 | function programCaller(data: any, param: any = '') { 2599 | 2600 | switch (data) { 2601 | 2602 | /** 2603 | * For the first initilization for the program 2604 | */ 2605 | case "init": 2606 | 2607 | // set initialize for node 2608 | node = new Nodes("", "", "", 0); 2609 | 2610 | // set Initialize for Gui 2611 | gui = new Gui(); 2612 | mindmapMenu = gui.setGuiInitialize(); 2613 | 2614 | // set listener for JsMind changes 2615 | gui.setJsmindListener(); 2616 | 2617 | // Load recent projects list 2618 | gui.loadRecentProjects(); 2619 | 2620 | // go to these section when resize the window 2621 | gui.windowResizeListener(); 2622 | 2623 | // set initialize for Gui in sidebar 2624 | guiSideBar = new GuiSideBar(); 2625 | 2626 | // set Initialize for project 2627 | project = new Project(); 2628 | 2629 | // set Initialize for Pdf 2630 | pdf = new Pdf(); 2631 | 2632 | break; 2633 | 2634 | /** 2635 | *When refresh pdf is pressed 2636 | */ 2637 | case "refresh": 2638 | 2639 | /** 2640 | * check if sidebar has been existed, if yes then do refreshAnnotation 2641 | */ 2642 | var isSideBarExist: boolean = guiSideBar.checkSideBar(); 2643 | if (isSideBarExist) { 2644 | programCaller("refreshAnnotation"); 2645 | break; 2646 | } 2647 | 2648 | //get PDF's lists 2649 | var pdfProcess = listPdf.getPdfFromFs(); 2650 | guiSideBar.resetSidebarAnnotation(); 2651 | 2652 | // get annotation's lists 2653 | Promise.all([pdfProcess]).then(function (response) { 2654 | listPdf.setListPdfFile(response[0]); 2655 | for (var i = 0; i < listPdf.getCount(); i++) { 2656 | var pdfPages = listPdf.getPdfPage(path.join(listPdf.getDirectory(), listPdf.getListPdfFile(i)), listPdf.getListPdfFile(i)); 2657 | Promise.all([pdfPages, pdfProcess, i]).then(function (responsePages) { 2658 | var pdfAnnots = listAnnotation.getAnnotations(responsePages[0], listPdf.getListPdfFile(responsePages[2])); 2659 | Promise.all([pdfProcess, pdfPages, pdfAnnots]).then(function (responseResult) { 2660 | var resultJson: string = responseResult[2]; 2661 | guiSideBar.setGuiInit(resultJson, listPdf.getDirectory()); 2662 | }) 2663 | }) 2664 | } 2665 | 2666 | }) 2667 | 2668 | break; 2669 | 2670 | /** 2671 | * When the refresh annotation is called 2672 | */ 2673 | case "refreshAnnotation": 2674 | // change has flag, saying if files changed or not. 2675 | // change[1] list of changed pdfs 2676 | // change[2] num of files changed 2677 | var change: any = listPdf.chkDateChange(util, listPdf.getListPdf()); 2678 | var listChange: string[] = change[1]; 2679 | var numChange: number = change[2]; 2680 | if (change[0] == true) { 2681 | for (var i = 0; i < numChange; i++) { 2682 | var pdfPages = listPdf.getPdfPage(path.join(project.getProjectSavedPdfLocation(), listChange[i]), listChange[i]); 2683 | Promise.all([pdfPages, i]).then(function (responsePages) { 2684 | var pdfAnnots = listAnnotation.getAnnotations(responsePages[0], listChange[responsePages[1]]); 2685 | Promise.all([pdfProcess, pdfPages, pdfAnnots]).then(function (responseResult) { 2686 | var newNodes: NodesObject = JSON.parse(responseResult[2]); 2687 | guiSideBar.setGuiOnAppend(newNodes, listPdf.getDirectory()); 2688 | }) 2689 | }) 2690 | } 2691 | 2692 | } else { 2693 | gui.windowAlert("No Change in Annotation"); 2694 | } 2695 | 2696 | break; 2697 | 2698 | /** 2699 | * refresh without consent of sidebar checking 2700 | */ 2701 | case "refreshAll": 2702 | //get PDF's lists 2703 | var pdfProcess = listPdf.getPdfFromFs(); 2704 | guiSideBar.resetSidebarAnnotation(); 2705 | 2706 | // get annotation's lists 2707 | Promise.all([pdfProcess]).then(function (response) { 2708 | listPdf.setListPdfFile(response[0]); 2709 | for (var i = 0; i < listPdf.getCount(); i++) { 2710 | var pdfPages = listPdf.getPdfPage(path.join(listPdf.getDirectory(), listPdf.getListPdfFile(i)), listPdf.getListPdfFile(i)); 2711 | Promise.all([pdfPages, pdfProcess, i]).then(function (responsePages) { 2712 | var pdfAnnots = listAnnotation.getAnnotations(responsePages[0], listPdf.getListPdfFile(responsePages[2])); 2713 | Promise.all([pdfProcess, pdfPages, pdfAnnots]).then(function (responseResult) { 2714 | var resultJson: string = responseResult[2]; 2715 | guiSideBar.setGuiInit(resultJson, listPdf.getDirectory()); 2716 | }) 2717 | }) 2718 | } 2719 | 2720 | }) 2721 | 2722 | break; 2723 | 2724 | case "copyMenu": 2725 | contextMenu.actionCopy(); 2726 | break; 2727 | case "pasteMenu": 2728 | contextMenu.actionPaste(project); 2729 | break; 2730 | case "openPDFMenu": 2731 | dir = listPdf.getDirectory(); 2732 | contextMenu.actionOpenPdf(dir); 2733 | break; 2734 | case "openPDFUserDefine": 2735 | dir = listPdf.getDirectory(); 2736 | contextMenu.actionOpenPdfUserDefine(dir); 2737 | break; 2738 | case "cancelMenu": 2739 | contextMenu.actionCancel(); 2740 | break; 2741 | case "deleteMenu": 2742 | contextMenu.actionDelete(); 2743 | break; 2744 | 2745 | case "newMindmap": 2746 | mindmapMenu.newMap(project, "Root"); 2747 | break; 2748 | case "openExisting": 2749 | mindmapMenu.selectFile(); 2750 | break; 2751 | case "saveFileMM": 2752 | var content = mindmapMenu.loadFile("mm"); 2753 | var locationFile = mindmapMenu.saveFile("mm", content); 2754 | gui.windowAlert("MM file is saved in" + " " + locationFile); 2755 | break; 2756 | case "saveFileJM": 2757 | var content = mindmapMenu.loadFile("jm"); 2758 | var locationFile = mindmapMenu.saveFile("jm", content); 2759 | gui.windowAlert("JM file is saved in" + " " + locationFile); 2760 | break; 2761 | 2762 | case "searchAnnotation": 2763 | //searching annotation based on a keyword 2764 | guiSideBar.searchAnnotation(listPdf.getDirectory()); 2765 | break; 2766 | case "newProjectModal": 2767 | //set modal of the new project 2768 | project.setNewProjectModal(); 2769 | break; 2770 | case "openProjectModal": 2771 | //set modal of the open project 2772 | project.setOpenProjectModal(); 2773 | break; 2774 | 2775 | case "newProject": 2776 | //set routine for new project (when save in new project is pressed) 2777 | var newProjectStatus = project.checkNewProject(); 2778 | if (newProjectStatus) { project.createNewProject(); } 2779 | break; 2780 | case "closeProject": 2781 | //set routine for close project 2782 | var status = project.getProjectStatus(); 2783 | project.setCloseProject(status); 2784 | 2785 | break; 2786 | case "saveProject": 2787 | // set routine for save project 2788 | var saveProjectStatus = gui.windowConfirmation("save changes?"); 2789 | if (saveProjectStatus) { 2790 | var msg: string = project.setSaveProject(); 2791 | if ((mindmapMenu.getFileTypeSave() != null)) { 2792 | var content = mindmapMenu.loadFile(mindmapMenu.getFileTypeSave()); 2793 | var locationFile = mindmapMenu.saveFile(mindmapMenu.getFileTypeSave(), content); 2794 | } 2795 | project.setProjectStatus('noedit'); 2796 | gui.windowAlert("project is saved in" + " " + msg); 2797 | } 2798 | break; 2799 | case "openRecentProject": 2800 | // set routine for recent project 2801 | project.openRecentProject(param); 2802 | break; 2803 | 2804 | } 2805 | } --------------------------------------------------------------------------------