├── .bowerrc ├── .editorconfig ├── .gitattributes ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md ├── ISSUE_TEMPLATE │ ├── Bug_report.md │ └── Feature_request.md ├── PULL_REQUEST_TEMPLATE.md ├── invite-contributors.yml └── settings.yml ├── .gitignore ├── .htmlhintrc ├── .jshintrc ├── .sass-lint.yml ├── .travis.yml ├── .vscode ├── extensions.json ├── launch.json ├── settings.json └── tasks.json ├── .yo-rc.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── Dockerfile ├── Gruntfile.js ├── LICENSE.md ├── README.md ├── app ├── .htaccess ├── .nojekyll ├── 404.html ├── browserconfig.xml ├── config.example.js ├── favicon.ico ├── humans.txt ├── images │ ├── Favicon-24.png │ ├── Favicon-48.png │ ├── Favicon-64.png │ ├── android-icon-144x144.png │ ├── android-icon-192x192.png │ ├── android-icon-36x36.png │ ├── android-icon-48x48.png │ ├── android-icon-72x72.png │ ├── android-icon-96x96.png │ ├── apk.png │ ├── apple-icon-114x114.png │ ├── apple-icon-120x120.png │ ├── apple-icon-144x144.png │ ├── apple-icon-152x152.png │ ├── apple-icon-180x180.png │ ├── apple-icon-57x57.png │ ├── apple-icon-60x60.png │ ├── apple-icon-72x72.png │ ├── apple-icon-76x76.png │ ├── apple-icon-precomposed.png │ ├── apple-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon-96x96.png │ ├── favicon.ico │ ├── flyve-mdm.png │ ├── flyve-mdm.svg │ ├── image4755.png │ ├── logo-flyve-login.png │ ├── logo-flyve-login.svg │ ├── logo-flyve-new.svg │ ├── logo-flyve.png │ ├── logo-flyve.svg │ ├── logo-teclib-blanc-1-2.png │ ├── marker-shadow.png │ ├── ms-icon-144x144.png │ ├── ms-icon-150x150.png │ ├── ms-icon-310x310.png │ ├── ms-icon-70x70.png │ ├── safari-pinned-tab.svg │ ├── stupid-user-avatar.png │ ├── stupid-user-avatar.svg │ ├── teclib-logo.png │ └── upk.png ├── index.html ├── license.html ├── manifest.webmanifest ├── robots.txt ├── scripts │ ├── app.js │ ├── controllers │ │ ├── about.js │ │ ├── accountvalidation.js │ │ ├── applications.js │ │ ├── contact.js │ │ ├── dashboard.js │ │ ├── device.js │ │ ├── devices.js │ │ ├── files.js │ │ ├── fleets.js │ │ ├── invitationlogs.js │ │ ├── invitations.js │ │ ├── login.js │ │ ├── navbar.js │ │ ├── userpreferences.js │ │ └── users.js │ ├── directives │ │ ├── browse-file-button.js │ │ ├── editabletd.js │ │ ├── facarets.js │ │ ├── hasripple.js │ │ ├── loggedusermenu.js │ │ └── stpaginationscroll.js │ └── services │ │ ├── account.js │ │ ├── agent.js │ │ ├── applications.js │ │ ├── auth.js │ │ ├── computers.js │ │ ├── dashboard.js │ │ ├── devices.js │ │ ├── engine.js │ │ ├── entityconfig.js │ │ ├── files.js │ │ ├── fleets.js │ │ ├── fullsession.js │ │ ├── geolocation.js │ │ ├── glosaryobjectnames.js │ │ ├── glpiobjectnames.js │ │ ├── inventory.js │ │ ├── invitationlogs.js │ │ ├── invitations.js │ │ ├── navigation.js │ │ ├── notifications.js │ │ ├── pluginobjectnames.js │ │ ├── policies.js │ │ ├── software.js │ │ ├── userpreferences.js │ │ └── users.js ├── socialmedia.txt ├── styles │ ├── _about_page.sass │ ├── _account_page.sass │ ├── _browse_file_button.sass │ ├── _contact_page.sass │ ├── _dashboard_page.sass │ ├── _device_page.sass │ ├── _dialog.sass │ ├── _dialog_fleet.sass │ ├── _filters.sass │ ├── _input.sass │ ├── _loggedusermenu.sass │ ├── _login_page.sass │ ├── _navigation.sass │ ├── _palette.sass │ ├── _systemreport.sass │ ├── _tables.sass │ ├── _variables.sass │ ├── _viewport.sass │ └── app.sass ├── tos.html └── views │ ├── about.html │ ├── account.html │ ├── accountvalidation.html │ ├── admin_applications.html │ ├── admin_files.html │ ├── admin_fleets.html │ ├── admin_users.html │ ├── contact.html │ ├── dashboard.html │ ├── device.html │ ├── devices.html │ ├── dialog_changepassword.html │ ├── dialog_editapplication.html │ ├── dialog_editfile.html │ ├── dialog_editfleet.html │ ├── dialog_editpolicy.html │ ├── dialog_edituser.html │ ├── dialog_enrollnewdevice.html │ ├── dialog_newapplication.html │ ├── dialog_newfile.html │ ├── dialog_register.html │ ├── help.html │ ├── invitationlogs.html │ ├── invitations.html │ ├── loggedusermenu.html │ ├── login.html │ ├── navigation.html │ └── toast_notification.html ├── bower.json ├── build-dist.sh ├── ci ├── screenshots.js └── script.sh ├── jsconfig.json ├── package-lock.json ├── package.json ├── test ├── .htmlhintrc ├── .jshintrc ├── karma.conf.js ├── mock │ └── services │ │ └── auth.js ├── postman-collections │ ├── 2048.apk │ ├── dev-env.postman_environment.json │ ├── flyve-mdm-tests.postman_collection.json │ └── testFile.txt └── spec │ └── services │ ├── auth.js │ └── users.js └── tools ├── generate-conf.sh └── run-nginx.sh /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "bower_components", 3 | "allow_root": false, 4 | "analytics": false, 5 | "interactive": false, 6 | "scripts": { 7 | "preinstall": "", 8 | "postinstall": "", 9 | "preuninstall": "" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | # Change these settings to your own preference 10 | indent_style = space 11 | indent_size = 2 12 | 13 | # We recommend you to keep these unchanged 14 | end_of_line = crlf 15 | charset = utf-8 16 | trim_trailing_whitespace = true 17 | insert_final_newline = false 18 | # tab_width = 2 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | 23 | [*.sass] 24 | indent_size = 2 -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ## GITATTRIBUTES FOR WEB PROJECTS 2 | # 3 | # These settings are for any web project. 4 | # 5 | # Details per file setting: 6 | # text These files should be normalized (i.e. convert CRLF to LF). 7 | # binary These files are binary and should be left untouched. 8 | # 9 | # Note that binary is a macro for -text -diff. 10 | ###################################################################### 11 | 12 | ## AUTO-DETECT - Handle line endings automatically for files detected 13 | ## as text and leave all files detected as binary untouched. 14 | ## This will handle all files NOT defined below. 15 | * text=auto 16 | 17 | ## SOURCE CODE 18 | *.bat text 19 | *.coffee text 20 | *.css text 21 | *.htm text 22 | *.html text 23 | *.inc text 24 | *.ini text 25 | *.js text 26 | *.jsx text 27 | *.json text 28 | *.less text 29 | *.php text 30 | *.pl text 31 | *.py text 32 | *.rb text 33 | *.sass text 34 | *.scm text 35 | *.scss text 36 | *.sh text 37 | *.sql text 38 | *.styl text 39 | *.ts text 40 | *.xml text 41 | *.xhtml text 42 | 43 | ## DOCUMENTATION 44 | *.markdown text 45 | *.md text 46 | *.mdwn text 47 | *.mdown text 48 | *.mkd text 49 | *.mkdn text 50 | *.mdtxt text 51 | *.mdtext text 52 | *.txt text 53 | AUTHORS text 54 | CHANGELOG text 55 | CHANGES text 56 | CONTRIBUTING text 57 | COPYING text 58 | INSTALL text 59 | license text 60 | LICENSE text 61 | NEWS text 62 | readme text 63 | *README* text 64 | TODO text 65 | 66 | ## TEMPLATES 67 | *.dot text 68 | *.ejs text 69 | *.haml text 70 | *.handlebars text 71 | *.hbs text 72 | *.hbt text 73 | *.jade text 74 | *.latte text 75 | *.mustache text 76 | *.phtml text 77 | *.tmpl text 78 | 79 | ## LINTERS 80 | .csslintrc text 81 | .eslintrc text 82 | .jscsrc text 83 | .jshintrc text 84 | .jshintignore text 85 | .stylelintrc text 86 | 87 | ## CONFIGS 88 | *.bowerrc text 89 | *.cnf text 90 | *.conf text 91 | *.config text 92 | .editorconfig text 93 | .gitattributes text 94 | .gitconfig text 95 | .gitignore text 96 | .htaccess text 97 | *.npmignore text 98 | *.yaml text 99 | *.yml text 100 | Makefile text 101 | makefile text 102 | 103 | ## HEROKU 104 | Procfile text 105 | .slugignore text 106 | 107 | ## GRAPHICS 108 | *.ai binary 109 | *.bmp binary 110 | *.eps binary 111 | *.gif binary 112 | *.ico binary 113 | *.jng binary 114 | *.jp2 binary 115 | *.jpg binary 116 | *.jpeg binary 117 | *.jpx binary 118 | *.jxr binary 119 | *.pdf binary 120 | *.png binary 121 | *.psb binary 122 | *.psd binary 123 | *.svg text 124 | *.svgz binary 125 | *.tif binary 126 | *.tiff binary 127 | *.wbmp binary 128 | *.webp binary 129 | 130 | ## AUDIO 131 | *.kar binary 132 | *.m4a binary 133 | *.mid binary 134 | *.midi binary 135 | *.mp3 binary 136 | *.ogg binary 137 | *.ra binary 138 | 139 | ## VIDEO 140 | *.3gpp binary 141 | *.3gp binary 142 | *.as binary 143 | *.asf binary 144 | *.asx binary 145 | *.fla binary 146 | *.flv binary 147 | *.m4v binary 148 | *.mng binary 149 | *.mov binary 150 | *.mp4 binary 151 | *.mpeg binary 152 | *.mpg binary 153 | *.swc binary 154 | *.swf binary 155 | *.webm binary 156 | 157 | ## ARCHIVES 158 | *.7z binary 159 | *.gz binary 160 | *.rar binary 161 | *.tar binary 162 | *.zip binary 163 | 164 | ## FONTS 165 | *.ttf binary 166 | *.eot binary 167 | *.otf binary 168 | *.woff binary 169 | *.woff2 binary 170 | 171 | ## EXECUTABLES 172 | *.exe binary 173 | *.pyc binary 174 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ### Observed Results: 4 | 5 | 6 | 7 | ### Expected behavior: 8 | 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 1. Go to '...' 13 | 2. Click on '....' 14 | 3. Scroll down to '....' 15 | 4. See error 16 | 17 | **Expected behavior** 18 | A clear and concise description of what you expected to happen. 19 | 20 | **Screenshots** 21 | If applicable, add screenshots to help explain your problem. 22 | 23 | **Desktop (please complete the following information):** 24 | - OS: [e.g. iOS] 25 | - Browser [e.g. chrome, safari] 26 | - Version [e.g. 22] 27 | 28 | **Smartphone (please complete the following information):** 29 | - Device: [e.g. iPhone6] 30 | - OS: [e.g. iOS8.1] 31 | - Browser [e.g. stock browser, safari] 32 | - Version [e.g. 22] 33 | 34 | **Additional context** 35 | Add any other context about the problem here. 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Changes description 2 | 3 | 4 | 5 | ### Checklist 6 | 7 | Please check if your PR fulfills the following specifications: 8 | 9 | - [ ] Tests for the changes have been added 10 | - [ ] Docs have been added/updated 11 | 12 | ### References 13 | 14 | 15 | 16 | Closes #N/A -------------------------------------------------------------------------------- /.github/invite-contributors.yml: -------------------------------------------------------------------------------- 1 | # Team Name 2 | team: contributors -------------------------------------------------------------------------------- /.github/settings.yml: -------------------------------------------------------------------------------- 1 | repository: 2 | name: legacy-web-dashboard 3 | description: Flyve MDM Dashboard 4 | homepage: http://flyve.org/legacy-web-dashboard/ 5 | topics: flyve-mdm, dashboard 6 | private: false 7 | has_issues: true 8 | has_wiki: false 9 | has_downloads: true 10 | default_branch: develop 11 | allow_squash_merge: true 12 | allow_merge_commit: false 13 | allow_rebase_merge: true 14 | labels: 15 | - name: bug 16 | color: f44336 17 | - name: build 18 | color: 795548 19 | - name: ci 20 | color: fbca04 21 | - name: documentation 22 | color: 607d8b 23 | - name: duplicate 24 | color: 9e9e9e 25 | - name: feature 26 | color: 3f51b5 27 | - name: hacktoberfest 28 | color: ff625f 29 | - name: invalid 30 | color: cddc39 31 | - name: performance 32 | color: 009688 33 | - name: question 34 | color: ff5722 35 | - name: refactor 36 | color: 9c27b0 37 | - name: style 38 | color: 2196f3 39 | - name: test 40 | color: 8bc34a 41 | - name: wontfix 42 | color: ffffff 43 | - name: help wanted 44 | color: 33aa3f 45 | - name: good first issue 46 | color: 7057ff 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /dist 3 | /.tmp 4 | /.sass-cache 5 | /bower_components 6 | app/config.js 7 | app/scripts/services/about.js 8 | jshint-report.md 9 | /build/ 10 | /benchpress-build/ 11 | .DS_Store 12 | gen_docs.disable 13 | test.disable 14 | regression/temp*.html 15 | performance/temp*.html 16 | .idea/workspace.xml 17 | *~ 18 | *.swp 19 | angular.js.tmproj 20 | /node_modules/ 21 | bower_components/ 22 | angular.xcodeproj 23 | .idea 24 | *.iml 25 | .agignore 26 | .lvimrc 27 | libpeerconnection.log 28 | npm-debug.log 29 | /tmp/ 30 | /scripts/bower/bower-* 31 | *.log 32 | *.stackdump 33 | *.http 34 | 35 | # Logs 36 | logs 37 | *.log 38 | npm-debug.log* 39 | *.err 40 | *.msg 41 | 42 | # Runtime data 43 | pids 44 | *.pid 45 | *.seed 46 | *.pid.lock 47 | 48 | # Directory for instrumented libs generated by jscoverage/JSCover 49 | lib-cov 50 | 51 | # Coverage directory used by tools like istanbul 52 | coverage 53 | 54 | # nyc test coverage 55 | .nyc_output 56 | 57 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 58 | .grunt 59 | 60 | # node-waf configuration 61 | .lock-wscript 62 | 63 | # Compiled binary addons (http://nodejs.org/api/addons.html) 64 | build/Release 65 | 66 | # Dependency directories 67 | node_modules 68 | jspm_packages 69 | 70 | # Optional npm cache directory 71 | .npm 72 | 73 | # Optional REPL history 74 | .node_repl_history 75 | .gtm/ 76 | .vscode/chrome/ -------------------------------------------------------------------------------- /.htmlhintrc: -------------------------------------------------------------------------------- 1 | { 2 | "tagname-lowercase": true, 3 | "attr-lowercase": true, 4 | "attr-value-double-quotes": true, 5 | "attr-value-not-empty": true, 6 | "attr-no-duplication": true, 7 | "doctype-first": false, 8 | "tag-pair": true, 9 | "tag-self-close": false, 10 | "spec-char-escape": true, 11 | "id-unique": true, 12 | "src-not-empty": true, 13 | "head-script-disabled": false, 14 | "img-alt-require": true, 15 | "doctype-html5": true, 16 | "id-class-value": "dash", 17 | "style-disabled": false, 18 | "space-tab-mixed-disabled": true, 19 | "id-class-ad-disabled": true, 20 | "href-abs-or-rel": true, 21 | "attr-unsafe-chars": true 22 | } -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "bitwise": true, 3 | "browser": true, 4 | "curly": true, 5 | "eqeqeq": true, 6 | "esnext": true, 7 | "jasmine": true, 8 | "latedef": true, 9 | "noarg": true, 10 | "node": true, 11 | "strict": true, 12 | "undef": true, 13 | "unused": true, 14 | "loopfunc": true, 15 | "expr": true, 16 | "globals": { 17 | "angular": false, 18 | "inject": false, 19 | "_": false, 20 | "L": false, 21 | "moment": false, 22 | "Dexie": false, 23 | "PasswordCredential": false 24 | } 25 | } -------------------------------------------------------------------------------- /.sass-lint.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/.sass-lint.yml -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | language: node_js 3 | node_js: 4 | - "8.5" 5 | 6 | branches: 7 | only: 8 | - gh-pages 9 | - /.*/ 10 | 11 | notifications: 12 | webhooks: https://hooks.aethonan.pro/travisci/-1001061475099/ 13 | 14 | dist: trusty 15 | 16 | addons: 17 | chrome: stable 18 | 19 | script: 20 | - "./ci/script.sh" 21 | 22 | before_script: 23 | - export DISPLAY=:99.0 24 | - sh -e /etc/init.d/xvfb start 25 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "EditorConfig.EditorConfig", 6 | "dbaeumer.jshint", 7 | "glen-84.sass-lint", 8 | "DavidAnson.vscode-markdownlint", 9 | "msjsdiag.debugger-for-chrome", 10 | "robinbentley.sass-indented", 11 | "johnpapa.Angular1", 12 | "gerane.Theme-Zenburn", 13 | "PeterJausovec.vscode-docker" 14 | ] 15 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch Chrome against localhost, with sourcemaps", 6 | "type": "chrome", 7 | "request": "launch", 8 | "url": "http://localhost:9001", 9 | "sourceMaps": true, 10 | "webRoot": "${workspaceRoot}", 11 | "userDataDir": "${workspaceRoot}/.vscode/chrome" 12 | //runtimeExecutable 13 | }, 14 | { 15 | "name": "Attach to Chrome, with sourcemaps", 16 | "type": "chrome", 17 | "request": "attach", 18 | "port": 9777, 19 | "sourceMaps": true, 20 | "webRoot": "${workspaceRoot}/app/" 21 | } 22 | ] 23 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "**/.git": true, 4 | "**/.svn": true, 5 | "**/.DS_Store": true, 6 | "**/.gtm": true, 7 | "**/.sass-cache": true, 8 | "**/.tmp": true, 9 | "**/node_modules": true, 10 | "**/bower_components": true 11 | }, 12 | "files.associations": { 13 | ".htmlhintrc": "json" 14 | }, 15 | "files.encoding": "utf8", 16 | "files.eol": "\r\n", 17 | "search.exclude": { 18 | "**/node_modules": true, 19 | "**/bower_components": true, 20 | "**/dist": true, 21 | "**/.vscode": true 22 | }, 23 | "editor.formatOnSave": true, 24 | "jshint.enable": true, 25 | "jshint.config": null, 26 | "jshint.options": {}, 27 | "jshint.excludePath": null, 28 | "jshint.exclude": {}, 29 | "beautify.onSave": true, 30 | "sasslint.enable": true, 31 | "sasslint.configFile": ".sass-lint.yml" 32 | //"sasslint.resolvePathsRelativeToConfig": 33 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "0.1.0", 5 | "command": "grunt", 6 | "isShellCommand": true, 7 | "args": [ 8 | "--no-color" 9 | ], 10 | "showOutput": "always" 11 | } -------------------------------------------------------------------------------- /.yo-rc.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | 6 | # [2.1.0](https://github.com/flyve-mdm/flyve-mdm-web-ui/compare/v2.0.0...v2.1.0) (2017-03-07) 7 | 8 | 9 | ### Bug Fixes 10 | 11 | * **dashboard:** check the existence of the header content-range ([69371b8](https://github.com/flyve-mdm/flyve-mdm-web-ui/commit/69371b8)) 12 | 13 | 14 | ### Features 15 | 16 | * **demo:** endpoint change to split demo mode ([315934b](https://github.com/flyve-mdm/flyve-mdm-web-ui/commit/315934b)) 17 | 18 | 19 | 20 | 21 | # [2.0.0](https://github.com/flyve-mdm/flyve-mdm-web-ui/compare/v1.2.0...v2.0.0) (2017-01-27) 22 | 23 | 24 | ### Features 25 | 26 | * **api:** rename stork ([#26](https://github.com/flyve-mdm/flyve-mdm-web-ui/issues/26)) ([b445ae9](https://github.com/flyve-mdm/flyve-mdm-web-ui/commit/b445ae9)) 27 | * **images:** add new iconography ([#22](https://github.com/flyve-mdm/flyve-mdm-web-ui/issues/22)) ([9d1d445](https://github.com/flyve-mdm/flyve-mdm-web-ui/commit/9d1d445)) 28 | 29 | 30 | ### BREAKING CHANGES 31 | 32 | * api: change endpoints and keys of the body payload 33 | 34 | 35 | 36 | 37 | # [1.2.0](https://github.com/flyve-mdm/flyve-mdm-web-ui/compare/v1.1.1...v1.2.0) (2017-01-23) 38 | 39 | 40 | ### Bug Fixes 41 | 42 | * **notifications:** fix array in error messages ([fee38dc](https://github.com/flyve-mdm/flyve-mdm-web-ui/commit/fee38dc)) 43 | 44 | 45 | ### Features 46 | 47 | * **email:** add validate account page ([2f49dcb](https://github.com/flyve-mdm/flyve-mdm-web-ui/commit/2f49dcb)) 48 | 49 | 50 | 51 | 52 | ## [1.1.1](https://github.com/flyve-mdm/flyve-mdm-web-ui/compare/v1.1.0...v1.1.1) (2016-12-21) 53 | 54 | 55 | ### Bug Fixes 56 | 57 | * **theme:** change banner of login screen ([05f135a](https://github.com/flyve-mdm/flyve-mdm-web-ui/commit/05f135a)) 58 | 59 | 60 | 61 | 62 | # [1.1.0](https://github.com/flyve-mdm/flyve-mdm-web-ui/compare/v1.0.0...v1.1.0) (2016-12-21) 63 | 64 | 65 | ### Features 66 | 67 | * **theme:** Add theme with petrol and gray colors ([ddbd673](https://github.com/flyve-mdm/flyve-mdm-web-ui/commit/ddbd673)) 68 | 69 | 70 | 71 | 72 | # 1.0.0 (2016-12-21) 73 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | As contributors and maintainers of the Flyve MDM projects, we pledge to respect everyone who contributes by posting issues, updating documentation, submitting pull requests, providing feedback in comments, and any other activities. 4 | 5 | Communication through any of our channels (GitHub, Telegram, mailing lists, Google+, Twitter, etc.) must be constructive and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. 6 | 7 | We promise to extend courtesy and respect to everyone involved in this project regardless of gender, gender identity, sexual orientation, disability, age, race, ethnicity, religion, or level of experience. We expect anyone contributing to the Flyve MDM projects to do the same. 8 | 9 | If any member of the community violates this code of conduct, the maintainers of the Flyve MDM projects may take action, removing issues, comments, and PRs or blocking accounts as deemed appropriate. 10 | 11 | If you are subject to or witness unacceptable behavior, or have any other concerns, please email us at ml-flyvemdm@teclib.com 12 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:8 2 | # Install Nginx. 3 | RUN \ 4 | apt-get update && \ 5 | apt-get install -y nginx && \ 6 | apt-get install -y curl && \ 7 | apt-get install -y git-core && \ 8 | curl -sL https://deb.nodesource.com/setup_6.x | bash - && \ 9 | apt-get install -y nodejs && \ 10 | apt-get install -y gcc build-essential && \ 11 | apt-get install -y ruby ruby-dev && \ 12 | gem install --no-rdoc --no-ri sass && \ 13 | gem install compass && \ 14 | npm install bower -g && \ 15 | npm install grunt -g && \ 16 | rm -rf /var/lib/apt/lists/* && \ 17 | echo "\ndaemon off;" >> /etc/nginx/nginx.conf && \ 18 | chown -R www-data:www-data /var/lib/nginx && \ 19 | mkdir -p /var/cache/nginx && \ 20 | chmod -R 777 /var/cache/nginx 21 | 22 | # Define mountable directories. 23 | VOLUME ["/etc/nginx/sites-enabled", "/etc/nginx/certs", "/etc/nginx/conf.d", "/var/log/nginx"] 24 | 25 | ### COPY DIST STUFF TO var/www/html 26 | ADD . /sourcebuild 27 | RUN cd /sourcebuild && chmod +x ./build-dist.sh && ./build-dist.sh && rm -Rf /var/www/html && mv /sourcebuild/dist /var/www/html 28 | 29 | ADD tools /tools 30 | RUN chmod +x /tools/*.sh && \ 31 | chmod -R 777 /var/www/html && \ 32 | chmod -R 777 /var/log/nginx && \ 33 | chown -R www-data:www-data /var/www/ 34 | 35 | # Define working directory. 36 | WORKDIR /etc/nginx 37 | 38 | ENV GLPI_API_URL http://flyve-glpi:8090/api 39 | ENV GLPI_API_TOKEN j8lth8dqvgky79f0dyf4jc59p353u34eao9rwlis3 40 | # Define default command. 41 | CMD ["/tools/run-nginx.sh"] 42 | 43 | # Expose ports. 44 | EXPOSE 80 -------------------------------------------------------------------------------- /app/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/.nojekyll -------------------------------------------------------------------------------- /app/404.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/404.html -------------------------------------------------------------------------------- /app/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | #ffffff 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/config.example.js: -------------------------------------------------------------------------------- 1 | angular.module('FlyveMDM') 2 | // url of the GLPI api 3 | .constant('GLPI_API_URL', 'http://api.flyve.teclib.infra') 4 | // this is the glpi/flyve api_key which is used to save glpi/flyve users 5 | .constant('USER_TOKEN', 'IMAUSERTOKEN') 6 | // Debugging option 7 | .constant('DEBUG', false) 8 | //The unique id of the current build that GitLab CI uses internally 9 | .constant('BUILD_ID', 0); 10 | -------------------------------------------------------------------------------- /app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/favicon.ico -------------------------------------------------------------------------------- /app/humans.txt: -------------------------------------------------------------------------------- 1 | # humanstxt.org/ 2 | # The humans responsible & technology colophon 3 | 4 | /* TEAM */ 5 | 6 | Name: Alexander J. Salas B. 7 | Email: asalas@teclib.com 8 | Twitter: @ajsb85 9 | GitHub: ajsb85 10 | Location: Barcelona, Spain. 11 | 12 | Name: Alexander J. Salas B. 13 | Email: nzamith@teclib.com 14 | GitHub: Newls 15 | Location: Montpellier, France. -------------------------------------------------------------------------------- /app/images/Favicon-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/Favicon-24.png -------------------------------------------------------------------------------- /app/images/Favicon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/Favicon-48.png -------------------------------------------------------------------------------- /app/images/Favicon-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/Favicon-64.png -------------------------------------------------------------------------------- /app/images/android-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/android-icon-144x144.png -------------------------------------------------------------------------------- /app/images/android-icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/android-icon-192x192.png -------------------------------------------------------------------------------- /app/images/android-icon-36x36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/android-icon-36x36.png -------------------------------------------------------------------------------- /app/images/android-icon-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/android-icon-48x48.png -------------------------------------------------------------------------------- /app/images/android-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/android-icon-72x72.png -------------------------------------------------------------------------------- /app/images/android-icon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/android-icon-96x96.png -------------------------------------------------------------------------------- /app/images/apk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/apk.png -------------------------------------------------------------------------------- /app/images/apple-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/apple-icon-114x114.png -------------------------------------------------------------------------------- /app/images/apple-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/apple-icon-120x120.png -------------------------------------------------------------------------------- /app/images/apple-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/apple-icon-144x144.png -------------------------------------------------------------------------------- /app/images/apple-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/apple-icon-152x152.png -------------------------------------------------------------------------------- /app/images/apple-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/apple-icon-180x180.png -------------------------------------------------------------------------------- /app/images/apple-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/apple-icon-57x57.png -------------------------------------------------------------------------------- /app/images/apple-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/apple-icon-60x60.png -------------------------------------------------------------------------------- /app/images/apple-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/apple-icon-72x72.png -------------------------------------------------------------------------------- /app/images/apple-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/apple-icon-76x76.png -------------------------------------------------------------------------------- /app/images/apple-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/apple-icon-precomposed.png -------------------------------------------------------------------------------- /app/images/apple-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/apple-icon.png -------------------------------------------------------------------------------- /app/images/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/favicon-16x16.png -------------------------------------------------------------------------------- /app/images/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/favicon-32x32.png -------------------------------------------------------------------------------- /app/images/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/favicon-96x96.png -------------------------------------------------------------------------------- /app/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/favicon.ico -------------------------------------------------------------------------------- /app/images/flyve-mdm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/flyve-mdm.png -------------------------------------------------------------------------------- /app/images/image4755.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/image4755.png -------------------------------------------------------------------------------- /app/images/logo-flyve-login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/logo-flyve-login.png -------------------------------------------------------------------------------- /app/images/logo-flyve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/logo-flyve.png -------------------------------------------------------------------------------- /app/images/logo-teclib-blanc-1-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/logo-teclib-blanc-1-2.png -------------------------------------------------------------------------------- /app/images/marker-shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/marker-shadow.png -------------------------------------------------------------------------------- /app/images/ms-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/ms-icon-144x144.png -------------------------------------------------------------------------------- /app/images/ms-icon-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/ms-icon-150x150.png -------------------------------------------------------------------------------- /app/images/ms-icon-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/ms-icon-310x310.png -------------------------------------------------------------------------------- /app/images/ms-icon-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/ms-icon-70x70.png -------------------------------------------------------------------------------- /app/images/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 14 | 16 | 18 | Created by potrace 1.11, written by Peter Selinger 2001-2013 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 34 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /app/images/stupid-user-avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/stupid-user-avatar.png -------------------------------------------------------------------------------- /app/images/stupid-user-avatar.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 24 | 25 | 27 | image/svg+xml 28 | 30 | 31 | 32 | 33 | 34 | 36 | 56 | 61 | 66 | 77 | 81 | 86 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /app/images/teclib-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/teclib-logo.png -------------------------------------------------------------------------------- /app/images/upk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/app/images/upk.png -------------------------------------------------------------------------------- /app/manifest.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "lang": "en", 3 | "dir": "ltr", 4 | "name": "FlyveMDM", 5 | "description": "Mobile device management software.", 6 | "short_name": "FlyveMDM", 7 | "icons": [ 8 | { 9 | "src": "images\/android-icon-36x36.png", 10 | "sizes": "36x36", 11 | "type": "image\/png", 12 | "density": "0.75" 13 | }, 14 | { 15 | "src": "images\/android-icon-48x48.png", 16 | "sizes": "48x48", 17 | "type": "image\/png", 18 | "density": "1.0" 19 | }, 20 | { 21 | "src": "images\/android-icon-72x72.png", 22 | "sizes": "72x72", 23 | "type": "image\/png", 24 | "density": "1.5" 25 | }, 26 | { 27 | "src": "images\/android-icon-96x96.png", 28 | "sizes": "96x96", 29 | "type": "image\/png", 30 | "density": "2.0" 31 | }, 32 | { 33 | "src": "images\/android-icon-144x144.png", 34 | "sizes": "144x144", 35 | "type": "image\/png", 36 | "density": "3.0" 37 | }, 38 | { 39 | "src": "images\/android-icon-192x192.png", 40 | "sizes": "192x192", 41 | "type": "image\/png", 42 | "density": "4.0" 43 | } 44 | ], 45 | "scope": "/#/", 46 | "start_url": "index.html", 47 | "display": "fullscreen", 48 | "orientation": "landscape", 49 | "theme_color": "aliceblue", 50 | "background_color": "white" 51 | } -------------------------------------------------------------------------------- /app/robots.txt: -------------------------------------------------------------------------------- 1 | # robotstxt.org 2 | 3 | User-agent: * 4 | Disallow: / 5 | -------------------------------------------------------------------------------- /app/scripts/controllers/about.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc function 4 | * @name FlyveMDM.controller:AboutCtrl 5 | * @description 6 | * # AboutCtrl 7 | * Controller of the FlyveMDM 8 | */ 9 | angular.module('FlyveMDM') 10 | .controller('AboutCtrl', function (GLPI_API_URL, PACKAGE, BOWER, DEBUG, BUILD_ID, UserPreferencesFac, $scope) { 11 | $scope.overview = BOWER.description; 12 | $scope.debug = DEBUG; 13 | $scope.components = []; 14 | UserPreferencesFac.getGLPiVersion().then(function (version) { 15 | $scope.glpiVersion = version; 16 | }); 17 | 18 | UserPreferencesFac.getPluginList().then(function (list) { 19 | $scope.pluginList = []; 20 | list.forEach(function (plugin) { 21 | $scope.pluginList.push({ 22 | name: plugin, 23 | version: null 24 | }); 25 | UserPreferencesFac.getPluginVersion().then(function (version) { 26 | var pluginPosition = $scope.pluginList.map(function (plugin) { return plugin.name; }).indexOf('flyvemdm'); 27 | if (pluginPosition !== -1) { 28 | $scope.pluginList[pluginPosition].version = version; 29 | } 30 | }); 31 | }); 32 | }); 33 | for (var dependency in BOWER.dependencies) { 34 | $scope.components.push({ 35 | name: dependency, 36 | version: BOWER.dependencies[dependency].replace(/\^/g, '') 37 | }); 38 | } 39 | $scope.webAppVersion = BOWER.version; 40 | $scope.build = BUILD_ID; 41 | this.awesomeThings = [ 42 | 'HTML5 Boilerplate', 43 | 'AngularJS', 44 | 'Karma' 45 | ]; 46 | $scope.angularVersion = angular.version.full; 47 | }); 48 | -------------------------------------------------------------------------------- /app/scripts/controllers/accountvalidation.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc function 4 | * @name FlyveMDM.controller:AccountValidationCtrl 5 | * @description 6 | * # AccountValidationCtrl 7 | * Controller of the FlyveMDM 8 | */ 9 | angular.module('FlyveMDM') 10 | .controller('AccountValidationCtrl', function ($scope, AuthProvider, AccountFac, Notifications, $state, $stateParams) { 11 | $scope.lock_submit = false; 12 | $scope.show_login = false; 13 | $scope.validateAccount = function () { 14 | $scope.lock_submit = true; 15 | AccountFac.validateAccount($stateParams.id, $stateParams.hash) 16 | .then(function () { 17 | Notifications.done("Account validated"); 18 | $scope.show_login = true; 19 | }, function () { 20 | $scope.lock_submit = false; 21 | }); 22 | }; 23 | $scope.goToLogin = function () { 24 | $state.go('login'); 25 | }; 26 | }); 27 | -------------------------------------------------------------------------------- /app/scripts/controllers/contact.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc function 4 | * @name FlyveMDM.controller:ContactCtrl 5 | * @description 6 | * # ContactCtrl 7 | * Controller of the FlyveMDM 8 | */ 9 | angular.module('FlyveMDM') 10 | .controller('ContactCtrl', function ($scope, $window, AuthProvider) { 11 | if (!AuthProvider.seemsLogged()) { 12 | return AuthProvider.showLogin(true); 13 | } 14 | $scope.links = function (aLink) { 15 | switch (aLink) { 16 | case 'tel': 17 | $window.open('tel:+34512702140', '_blank'); 18 | break; 19 | case 'email': 20 | $window.open('mailto:contact@teclib.com', '_blank'); 21 | break; 22 | case 'map': 23 | $window.open('https://her.is/2ge9vcS', '_blank'); 24 | break; 25 | case 'ticket': 26 | $window.open('https://support.teclib.com/', '_blank'); 27 | break; 28 | } 29 | }; 30 | }); 31 | -------------------------------------------------------------------------------- /app/scripts/controllers/dashboard.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc function 4 | * @name FlyveMDM.controller:DashboardCtrl 5 | * @description 6 | * # DashboardCtrl 7 | * Controller of the FlyveMDM 8 | */ 9 | angular.module('FlyveMDM') 10 | .controller('DashboardCtrl', function ($scope, $state, $q, AuthProvider, DashboardFac, Notifications) { 11 | if (!AuthProvider.seemsLogged()) { 12 | return AuthProvider.showLogin(true); 13 | } 14 | $scope.lock_refresh = false; 15 | //console.log(GLPi.getOptions('defaults').global.appToken); 16 | //console.log(); 17 | //GLPi.listSearchOptions('PluginFlyvemdmAgent'); 18 | 19 | //console.log(GLPi.getOptions('defaults').global.user_token); 20 | $scope.links = function (aLink) { 21 | $state.go(aLink); 22 | }; 23 | $scope.editDevice = function (deviceId) { 24 | $state.go('device', { id: deviceId }); 25 | }; 26 | DashboardFac.getMacAddress().then(function (macAddress) { 27 | $scope.devicesByMacAddress = macAddress; 28 | }); 29 | $scope.refreshDashboard = function (toast) { 30 | $scope.lock_refresh = true; 31 | if (toast) { 32 | Notifications.loading("Refresh in progress..."); 33 | } 34 | var promises = { 35 | invitations: DashboardFac.getInvitations(), 36 | users: DashboardFac.getNumberOfUsers(), 37 | devices: DashboardFac.getNumberOfDevices(), 38 | applications: DashboardFac.getNumberOfApplications(), 39 | fleets: DashboardFac.getNumberOfFleets(), 40 | files: DashboardFac.getNumberOfFiles(), 41 | devices_os: DashboardFac.getAndroidVersions(), 42 | devicesByMacAddress: DashboardFac.getMacAddress(), 43 | devicesByRealName: DashboardFac.getDevicesByRealName() 44 | }; 45 | $q.all(promises).then(function (data) { 46 | $scope.users = data.users; 47 | $scope.devices = data.devices; 48 | $scope.applications = data.applications; 49 | $scope.fleets = data.fleets; 50 | $scope.files = data.files; 51 | $scope.devicesByMacAddress = data.devicesByMacAddress; 52 | $scope.devicesByRealName = data.devicesByRealName; 53 | $scope.invitations = { 54 | labels: ['Done', 'Pending'], 55 | data: [data.invitations.done, data.invitations.pending], 56 | dataset: { 57 | backgroundColor: ['#6cc2bc', '#158784'], 58 | hoverBackgroundColor: ['#6cc2bc', '#158784'], 59 | hoverBorderColor: ['#6cc2bc', '#158784'] 60 | } 61 | }; 62 | $scope.devices_os = { 63 | series: ['Android', 'iOS'], 64 | labels: data.devices_os.android_version, 65 | data: [data.devices_os.android_version_quantity], 66 | dataset: { 67 | }, 68 | colors: [ 69 | { 70 | backgroundColor: '#6cc2bc', 71 | borderColor: '#6cc2bc', 72 | hoverBackgroundColor: '#6cc2bc', 73 | hoverBorderColor: '#6cc2bc' 74 | }, 75 | { 76 | backgroundColor: '#158784', 77 | borderColor: '#158784', 78 | hoverBackgroundColor: '#158784', 79 | hoverBorderColor: '#158784' 80 | } 81 | ] 82 | }; 83 | if (toast) { 84 | Notifications.done("Dashboard refreshed"); 85 | } 86 | $scope.lock_refresh = false; 87 | }); 88 | }; 89 | $scope.refreshDashboard(); 90 | }); 91 | -------------------------------------------------------------------------------- /app/scripts/controllers/files.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc function 4 | * @name FlyveMDM.controller:FilesadminCtrl 5 | * @description 6 | * # FilesadminCtrl 7 | * Controller of the FlyveMDM 8 | */ 9 | angular.module('FlyveMDM') 10 | .controller('FilesAdminCtrl', function (FilesAdminFac, Notifications, $scope, 11 | $mdDialog) { 12 | var filesControllerScope = $scope; 13 | $scope.displayedCollection = []; 14 | var EditFileController = function ($scope, $mdDialog, file) { 15 | $scope.lock_submit = true; 16 | $scope.file = angular.copy(file); 17 | $scope.$watch('file.name', function () { 18 | $scope.lock_submit = Boolean($scope.file.name.toString() === file.name.toString()); 19 | }); 20 | $scope.cancel = function () { 21 | $mdDialog.hide(); 22 | }; 23 | $scope.saveFile = function () { 24 | $scope.lock_submit = true; 25 | FilesAdminFac.updateFile($scope.file.id, $scope.file.name).then(function () { 26 | $mdDialog.hide().then(function () { 27 | Notifications.done("File edited"); 28 | filesControllerScope.displayedCollection.some(function (file) { 29 | if (file.id === $scope.file.id) { 30 | file.name = $scope.file.name; 31 | return true; 32 | } 33 | }); 34 | }); 35 | }); 36 | }; 37 | }; 38 | var NewFileController = function ($scope, $mdDialog) { 39 | $scope.lock_submit = true; 40 | $scope.uploadProgress = 0; 41 | $scope.file = { 42 | "name": "", 43 | }; 44 | var request; 45 | $scope.showName = function (aFileBlob) { 46 | if (aFileBlob.name) { 47 | $scope.file.name = aFileBlob.name; 48 | $scope.lock_submit = false; 49 | } 50 | }; 51 | /** 52 | * This is the "save" scope function which is 53 | * triggered when the user closes the dialog 54 | * by using the "save" button. 55 | * Is is doing special checkup to verify if 56 | * we're about to POST a new Application 57 | */ 58 | $scope.saveFile = function (aFileBlob) { 59 | $scope.lock_submit = true; 60 | request = FilesAdminFac.uploadFile2(aFileBlob, $scope.file.name); 61 | request.then(function (response) { 62 | $mdDialog.hide().then(function () { 63 | Notifications.done("File uploaded"); 64 | FilesAdminFac.getFile(response.data.id).then(function (aFile) { 65 | filesControllerScope.displayedCollection.push(aFile); 66 | }); 67 | }); 68 | }, function (response) { 69 | if (response.status === -1) { 70 | Notifications.error("Upload cancelled"); 71 | } else { 72 | $mdDialog.show( 73 | $mdDialog.alert() 74 | .parent(angular.element(document.body)) 75 | .clickOutsideToClose(true) 76 | .title('Error when uploading file') 77 | .content(response.data[1]) 78 | .ariaLabel(response.data[1]) 79 | .ok('Accept') 80 | ); 81 | } 82 | }, function (evt) { 83 | $scope.uploadProgress = parseInt(100.0 * evt.loaded / evt.total); 84 | }); 85 | }; 86 | $scope.cancel = function () { 87 | $mdDialog.cancel(); 88 | if (request) { 89 | request.abort(); 90 | } 91 | }; 92 | }; 93 | $scope.insertIntoTable = $scope.newFile = function () { 94 | $mdDialog.show({ 95 | controller: NewFileController, 96 | templateUrl: 'views/dialog_newfile.html', 97 | parent: angular.element(document.body), 98 | clickOutsideToClose: false 99 | }); 100 | }; 101 | $scope.editFile = function (ev, file) { 102 | $mdDialog.show({ 103 | controller: EditFileController, 104 | targetEvent: ev, 105 | locals: { 106 | file: file 107 | }, 108 | templateUrl: 'views/dialog_editfile.html', 109 | parent: angular.element(document.body), 110 | clickOutsideToClose: false 111 | }); 112 | }; 113 | $scope.deleteFile = function (ev, file) { 114 | $mdDialog.show( 115 | $mdDialog.confirm() 116 | .title('Are you certain') 117 | .content('you want to delete the file "' + file.name + '"') 118 | .ok('Accept') 119 | .cancel('Cancel') 120 | .targetEvent(ev) 121 | ).then(function () { 122 | FilesAdminFac.deleteFile(file.id).then(function () { 123 | Notifications.done("File deleted"); 124 | $scope.displayedCollection.some(function (_file, index) { 125 | if (_file.id === file.id) { 126 | $scope.displayedCollection.splice(index, 1); 127 | return true; 128 | } 129 | }); 130 | }); 131 | }); 132 | }; 133 | $scope.fillTable = function (tableState) { 134 | FilesAdminFac.getFiles().then(function (files) { 135 | $scope.displayedCollection = files; 136 | $scope.collectionLength = files.length; 137 | tableState.pagination.totalItemCount = files.length; 138 | }); 139 | }; 140 | }); 141 | -------------------------------------------------------------------------------- /app/scripts/controllers/invitationlogs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc function 4 | * @name FlyveMDM.controller:InvitationLogsCtrl 5 | * @description 6 | * # InvitationLogsCtrl 7 | * Controller of the FlyveMDM 8 | */ 9 | angular.module('FlyveMDM') 10 | .controller('InvitationLogsCtrl', function (GLPI_API_URL, 11 | AuthProvider, InvitationsFac, InvitationLogsFac, UsersAdminFac, $stateParams, $scope) { 12 | if (!AuthProvider.seemsLogged()) { 13 | return AuthProvider.showLogin(true); 14 | } 15 | $scope.displayedInvitationLogs = []; 16 | $scope.invitation_email = "Loading..."; 17 | $scope.loading = false; 18 | InvitationsFac.getInvitation($stateParams.id).then(function (anInvitation) { 19 | UsersAdminFac.getUser(anInvitation.users_id).then(function (aUser) { 20 | $scope.invitation_email = aUser.username; 21 | }); 22 | }); 23 | /** 24 | * -- DEVICE-LISTING/PAGINATION RELATED 25 | */ 26 | var smartTableTableState = null; 27 | $scope.fillTable = function (tableState) { 28 | // saving reference of the tableState 29 | if (smartTableTableState === null) { 30 | smartTableTableState = tableState; 31 | } 32 | $scope.loading = true; 33 | InvitationLogsFac.getLogs($stateParams.id).then(function (logs) { 34 | $scope.loading = false; 35 | $scope.displayedInvitationLogs = logs; 36 | 37 | tableState.pagination.totalItemCount = logs.length; 38 | }); 39 | }; 40 | }); 41 | -------------------------------------------------------------------------------- /app/scripts/controllers/invitations.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc function 4 | * @name FlyveMDM.controller:InvitationsCtrl 5 | * @description 6 | * # InvitationsCtrl 7 | * Controller of the FlyveMDM 8 | */ 9 | angular.module('FlyveMDM') 10 | .controller('InvitationsCtrl', function (GLPI_API_URL, 11 | AuthProvider, InvitationsFac, Notifications, $scope, $state, $mdDialog) { 12 | if (!AuthProvider.seemsLogged()) { 13 | return AuthProvider.showLogin(true); 14 | } 15 | var devicesControllerScope = $scope; 16 | $scope.displayedInvitations = []; 17 | $scope.collectionLength = 0; 18 | $scope.itemsByPage = 5; 19 | $scope.loading = false; 20 | /** 21 | * -- DEVICE-LISTING/PAGINATION RELATED 22 | */ 23 | var smartTableTableState = null; 24 | $scope.fillTable = function (tableState) { 25 | // saving reference of the tableState 26 | if (smartTableTableState === null) { 27 | smartTableTableState = tableState; 28 | } 29 | $scope.loading = true; 30 | InvitationsFac.getInvitations().then(function (response) { 31 | $scope.loading = false; 32 | $scope.displayedInvitations = response.getInvitations.map(function (invitation) { 33 | var userPosition = response.getUsers.data.map(function (user) { return user.id; }).indexOf(invitation.users_id); 34 | if (userPosition !== -1) { 35 | invitation.user_email = response.getUsers.data[userPosition].name; 36 | } 37 | return invitation; 38 | }); 39 | $scope.displayedInvitations = response.getInvitations; 40 | $scope.collectionLength = response.getInvitations.length; 41 | tableState.pagination.totalItemCount = response.getInvitations.length; 42 | }); 43 | }; 44 | /** 45 | * -- Add new device method 46 | */ 47 | var EnrollNewDeviceController = function ($scope, $mdDialog) { 48 | $scope.lock_submit = false; 49 | $scope.user_email = ""; 50 | $scope.cancel = function () { 51 | $mdDialog.cancel(); 52 | }; 53 | $scope.enrollDevice = function () { 54 | $scope.lock_submit = true; 55 | InvitationsFac.enrollNewDevice($scope.user_email) 56 | .then(function (invitationId) { 57 | $mdDialog.hide().then(function () { 58 | Notifications.done("Invitation requested"); 59 | var invitation = { 60 | id: invitationId, 61 | user_email: $scope.user_email 62 | }; 63 | devicesControllerScope.displayedInvitations.push(invitation); 64 | }); 65 | }); 66 | }; 67 | }; 68 | $scope.insertIntoTable = $scope.enrollNewDevice = function () { 69 | $mdDialog.show({ 70 | controller: EnrollNewDeviceController, 71 | templateUrl: 'views/dialog_enrollnewdevice.html', 72 | parent: angular.element(document.body), 73 | clickOutsideToClose: false, 74 | }); 75 | }; 76 | $scope.resendEmail = function (device) { 77 | $mdDialog.show( 78 | $mdDialog.confirm() 79 | .title('Resend invitation #' + device.id) 80 | .content('You are going to resend email ' + device.user_email + '.') 81 | .ariaLabel('Resend this email') 82 | .ok('Accept') 83 | .cancel('Cancel') 84 | ).then(function () { 85 | InvitationsFac.resendInvitation(device.id, device.user_email).then(function () { 86 | Notifications.done("Resend invitation requested"); 87 | }); 88 | }); 89 | }; 90 | $scope.invitationLogs = function (invitationId) { 91 | $state.go('invitation_logs', { id: invitationId }); 92 | }; 93 | $scope.deleteEmail = function (device) { 94 | $mdDialog.show( 95 | $mdDialog.confirm() 96 | .title('Delete invitation #' + device.id) 97 | .content('You are going to delete email ' + device.user_email + '.') 98 | .ariaLabel('Delete this email') 99 | .ok('Accept') 100 | .cancel('Cancel') 101 | ).then(function () { 102 | InvitationsFac.deleteInvitation(device.id).then(function () { 103 | Notifications.done("Invitation deleted"); 104 | devicesControllerScope.displayedInvitations.some(function (_device, index) { 105 | if (_device.id === device.id) { 106 | devicesControllerScope.displayedInvitations.splice(index, 1); 107 | return true; 108 | } 109 | }); 110 | }); 111 | }); 112 | }; 113 | }); 114 | -------------------------------------------------------------------------------- /app/scripts/controllers/login.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc function 4 | * @name FlyveMDM.controller:ConnectionCtrl 5 | * @description 6 | * # ConnectionCtrl 7 | * Controller of the FlyveMDM 8 | */ 9 | angular.module('FlyveMDM') 10 | .directive('registrationPasswordConfirmationField', function () { 11 | return { 12 | restrict: 'A', 13 | require: 'ngModel', 14 | link: function (scope, element, attrs, ctrl) { 15 | scope.$watch('input.password', function () { 16 | ctrl.$validate(); 17 | }); 18 | var passwordAndConfirmationAreTheSame = function () { 19 | return scope.input.password === ctrl.$viewValue; 20 | }; 21 | ctrl.$validators.passwordAndConfirmationAreTheSame = passwordAndConfirmationAreTheSame; 22 | } 23 | }; 24 | }) 25 | .controller('LoginCtrl', function ($scope, AuthProvider, GlpiObjectNames, GLPI_API_URL, $state, $mdDialog) { 26 | var loginControllerScope = $scope; 27 | $scope.loginCredentials = { 28 | email: '', 29 | password: '' 30 | }; 31 | if (navigator.credentials) { 32 | navigator.credentials.get({ 33 | password: true, 34 | unmediated: false 35 | }).then(function (credential) { 36 | if (credential) { 37 | $scope.$apply(function () { 38 | $scope.loginCredentials.username = credential.id; 39 | }); 40 | } 41 | }); 42 | } 43 | $scope.storeCredentials = function (profileInfos) { 44 | if (navigator.credentials) { 45 | //ToDo: iconURL: iconUrl in PasswordCredential 46 | var credentials = new PasswordCredential({ 47 | id: profileInfos.name, 48 | password: profileInfos.password, 49 | name: profileInfos.firstname ? profileInfos.firstname + ' ' + profileInfos.realname : '' 50 | }); 51 | return navigator.credentials.store(credentials); 52 | } 53 | }; 54 | $scope.attemptLogin = function () { 55 | AuthProvider.attemptLogin($scope.loginCredentials.username, 56 | $scope.loginCredentials.password) 57 | .then(function () { 58 | $scope.storeCredentials({ 59 | name: $scope.loginCredentials.username, 60 | password: $scope.loginCredentials.password 61 | }); 62 | $state.go('dashboard'); 63 | }, function () { 64 | $mdDialog.show( 65 | $mdDialog.alert() 66 | .parent(angular.element(document.body)) 67 | .clickOutsideToClose(true) 68 | .title('Wrong credentials') 69 | .content('Wrong credentials were supplied.') 70 | .ariaLabel('wrong crendentials on login attempt') 71 | .ok('Accept') 72 | ); 73 | }); 74 | }; 75 | var RegistrationDialogCtrl = function ($scope, $mdDialog) { 76 | $scope.lock_submit = false; 77 | $scope.input = { 78 | name: '', 79 | password: '', 80 | password2: '', 81 | firstname: '', 82 | realname: '' 83 | }; 84 | $scope.attemptRegister = function () { 85 | $scope.lock_submit = true; 86 | $scope.input.name = $scope.input.username; 87 | AuthProvider.attemptRegister($scope.input) 88 | .then(function () { 89 | loginControllerScope.storeCredentials($scope.input); 90 | $scope.lock_submit = false; 91 | $mdDialog.show( 92 | $mdDialog.alert() 93 | .parent(angular.element(document.body)) 94 | .clickOutsideToClose(false) 95 | .title('Welcome!') 96 | .content('You account has been created! Go and try to login now') 97 | .ariaLabel('your account has been created') 98 | .ok('Accept') 99 | ).then(function () { 100 | $state.go('login'); 101 | }); 102 | }, function () { 103 | $scope.lock_submit = false; 104 | }); 105 | }; 106 | $scope.cancel = function () { 107 | $mdDialog.hide(); 108 | }; 109 | }; 110 | $scope.openRegistrationDialog = function (ev) { 111 | $mdDialog.show({ 112 | controller: RegistrationDialogCtrl, 113 | templateUrl: 'views/dialog_register.html', 114 | targetEvent: ev, 115 | clickOutsideToClose: false 116 | }); 117 | }; 118 | }); 119 | -------------------------------------------------------------------------------- /app/scripts/controllers/navbar.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc function 4 | * @name FlyveMDM.controller:NavbarCtrl 5 | * @description 6 | * # NavbarCtrl 7 | * Controller of the FlyveMDM 8 | */ 9 | angular.module('FlyveMDM') 10 | .run(function ($rootScope) { 11 | $rootScope.currentViewMenu = []; 12 | }) 13 | .controller('NavbarCtrl', function ($scope, $rootScope) { 14 | $scope.menu = []; 15 | $scope.$on('$stateChangeStart', function () { 16 | $rootScope.currentViewMenu = []; 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /app/scripts/controllers/users.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc function 4 | * @name FlyveMDM.controller:UsersAdminCtrl 5 | * @description 6 | * # UsersAdminCtrl 7 | * 8 | * + needs to grab the device names for users with the api 9 | using the user ids 10 | */ 11 | angular.module('FlyveMDM') 12 | .controller('UsersAdminCtrl', function (UsersAdminFac, AgentFac, AuthProvider, Notifications, $scope, 13 | $mdDialog) { 14 | // making use of the login Provider(Angular) 15 | // created for this project to represent the 16 | // "connection" to the Flyve/GLPi API 17 | if (!AuthProvider.seemsLogged()) { 18 | return AuthProvider.showLogin(true); 19 | } 20 | var usersControllerScope = $scope; 21 | $scope.displayedCollection = []; 22 | $scope.itemsByPage = 5; 23 | $scope.loading = false; 24 | $scope.fillTable = function (tableState) { 25 | UsersAdminFac.getUsers().then(function (users) { 26 | tableState.pagination.totalItemCount = $scope.collectionLength = users.length; 27 | AgentFac.evaluateDeviceNames(users).then(function (userCollection) { 28 | $scope.loading = false; 29 | $scope.displayedCollection = userCollection; 30 | }, function () { 31 | }); 32 | }, function () { 33 | }); 34 | }; 35 | var EditUserController = function ($scope, $mdDialog, user) { 36 | $scope.lock_submit = false; 37 | $scope.input = angular.extend({}, user); 38 | $scope.saveUser = function () { 39 | $scope.lock_submit = true; 40 | UsersAdminFac.updateUser($scope.input) 41 | .then(function () { 42 | $mdDialog.hide().then(function () { 43 | Notifications.done("User edited"); 44 | $scope.input.fullname = $scope.input.firstname + ' ' + $scope.input.lastname; 45 | $scope.input.password = ''; 46 | $scope.input.password2 = ''; 47 | usersControllerScope.displayedCollection.some(function (_user, index) { 48 | if (_user.id === $scope.input.id) { 49 | usersControllerScope.displayedCollection[index] = angular.copy($scope.input); 50 | } 51 | }); 52 | }); 53 | }); 54 | }; 55 | $scope.cancel = function () { 56 | $mdDialog.hide(); 57 | }; 58 | }; 59 | $scope.editUser = function (ev, user) { 60 | $mdDialog.show({ 61 | controller: EditUserController, 62 | templateUrl: 'views/dialog_edituser.html', 63 | parent: angular.element(document.body), 64 | clickOutsideToClose: false, 65 | targetEvent: ev, 66 | locals: { 67 | user: user 68 | } 69 | }); 70 | }; 71 | $scope.deleteUser = function (ev, user) { 72 | $mdDialog.show( 73 | $mdDialog.confirm() 74 | .targetEvent(ev) 75 | .title('Confirm the deletion of user') 76 | .content('Are you certain to delete the ' + user.email + ' device') 77 | .ok('Accept') 78 | .cancel('Cancel') 79 | ).then(function () { 80 | UsersAdminFac.deleteUser(user.id).then(function () { 81 | Notifications.done("User deleted"); 82 | usersControllerScope.displayedCollection.some(function (_user, index) { 83 | if (_user.id === user.id) { 84 | usersControllerScope.displayedCollection.splice(index, 1); 85 | } 86 | }); 87 | }); 88 | }); 89 | }; 90 | var RegistrationDialogCtrl = function ($scope, $mdDialog) { 91 | $scope.lock_submit = false; 92 | $scope.input = { 93 | username: '', 94 | password: '', 95 | password2: '', 96 | firstname: '', 97 | lastname: '' 98 | }; 99 | $scope.attemptRegister = function () { 100 | $scope.lock_submit = true; 101 | var request = UsersAdminFac.attemptRegister($scope.input) 102 | .then(function (aUserId) { 103 | Notifications.done("User created"); 104 | $scope.input.fullname = $scope.input.firstname + ' ' + $scope.input.lastname; 105 | if (navigator.credentials) { 106 | var credentials = new PasswordCredential({ 107 | id: $scope.input.username, 108 | password: $scope.input.password, 109 | name: $scope.input.fullname 110 | }); 111 | navigator.credentials.store(credentials); 112 | } 113 | $scope.input.id = aUserId; 114 | $scope.input.password = ''; 115 | $scope.input.password2 = ''; 116 | usersControllerScope.displayedCollection.push($scope.input); 117 | }); 118 | request.finally(function () { 119 | $scope.lock_submit = false; 120 | $mdDialog.hide(); 121 | }); 122 | }; 123 | $scope.cancel = function () { 124 | $mdDialog.hide(); 125 | }; 126 | }; 127 | $scope.insertIntoTable = function (ev) { 128 | $mdDialog.show({ 129 | controller: RegistrationDialogCtrl, 130 | templateUrl: 'views/dialog_register.html', 131 | targetEvent: ev, 132 | clickOutsideToClose: false 133 | }); 134 | }; 135 | }); 136 | -------------------------------------------------------------------------------- /app/scripts/directives/browse-file-button.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc directive 4 | * @name FlyveMDM.directive:browseFileButton 5 | * @description 6 | * # browseFileButton 7 | */ 8 | angular.module('FlyveMDM') 9 | .directive('browseFileButton', function () { 10 | return { 11 | restrict: 'E', 12 | template: 'Upload File ' + 13 | '' + 14 | '
{{model.name}}
', 15 | link: function postLink(scope, element) { 16 | var trigger = element.find('.browse-button'); 17 | var realBrowseButton = element.find('.browse-button-real'); 18 | trigger.on('click', function () { 19 | realBrowseButton.click(); 20 | }); 21 | }, 22 | scope: { 23 | model: "=model" 24 | } 25 | }; 26 | }); 27 | -------------------------------------------------------------------------------- /app/scripts/directives/editabletd.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc directive 4 | * @name FlyveMDM.directive:editableTd 5 | * @description 6 | * # editableTd 7 | */ 8 | angular.module('FlyveMDM') 9 | .directive('editableTd', function () { 10 | return { 11 | restrict: 'A', 12 | template: '{{value}}' + 13 | '
', 14 | link: function postLink(scope, element, attrs, ctrl) { 15 | var input = element.find('input'); 16 | // initializing initial value 17 | ctrl.setValue(scope.model()[scope.key]); 18 | // now binding the event handlers 19 | element.on('click', function () { 20 | if (!scope.opened) { 21 | scope.opened = true; 22 | scope.$apply(); 23 | input.focus(); 24 | } 25 | }); 26 | // haviing the blur event as 27 | // a way to escape the edit 28 | // mode 29 | input.on('blur', function () { 30 | scope.opened = false; 31 | scope.changedValue = scope.value; 32 | scope.$apply(); 33 | }); 34 | }, 35 | controller: function ($scope) { 36 | $scope.value = null; 37 | $scope.changedValue = null; 38 | $scope.opened = false; 39 | this.setValue = function (value) { 40 | // Yes, value and changedValue 41 | // are the same, before the Real 42 | // changedValue exists. 43 | $scope.value = value; 44 | $scope.changedValue = value; 45 | }; 46 | this.updateValue = function () { 47 | $scope.value = $scope.changedValue; 48 | // now closing the stuff 49 | $scope.opened = false; 50 | // making $newValue available to 51 | // the editable-td-on-edit attribute 52 | $scope.$parent.$parent.$newValue = $scope.value; 53 | // running the compiled editable-td-on-edit 54 | $scope.onEdit() 55 | .then(function () { 56 | $scope.model()[$scope.key] = $scope.value; 57 | }); 58 | // restoring the scope like it was 59 | delete $scope.$parent.$parent.$newValue; 60 | }; 61 | }, 62 | controllerAs: 'ctrl', 63 | scope: { 64 | "initValue": "=editableTdInitValue", 65 | "onEdit": "&editableTdOnEdit", 66 | "model": "&editableTdModel", 67 | "key": "=editableTdKey" 68 | } 69 | }; 70 | }); 71 | -------------------------------------------------------------------------------- /app/scripts/directives/facarets.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc directive 4 | * @name FlyveMDM.directive:faCarets 5 | * @description 6 | * # faCarets 7 | */ 8 | angular.module('FlyveMDM') 9 | .directive('faCarets', function () { 10 | return { 11 | template: '', 12 | restrict: 'E' 13 | }; 14 | }); 15 | -------------------------------------------------------------------------------- /app/scripts/directives/hasripple.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc directive 4 | * @name FlyveMDM.directive:hasRipple 5 | * @description 6 | * # hasRipple 7 | */ 8 | angular.module('FlyveMDM') 9 | .directive('hasRipple', function () { 10 | return { 11 | restrict: 'A', 12 | link: function postLink(scope, element, attrs, ctrl) { 13 | ctrl.attachRipple(element); 14 | }, 15 | controller: function ($scope, $mdInkRipple) { 16 | this.attachRipple = function (element) { 17 | $mdInkRipple.attach($scope, element, { 18 | fitRipple: true 19 | }); 20 | }; 21 | } 22 | }; 23 | }); 24 | -------------------------------------------------------------------------------- /app/scripts/directives/loggedusermenu.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc directive 4 | * @name FlyveMDM.directive:loggedUserMenu 5 | * @description 6 | * # loggedUserMenu 7 | */ 8 | angular.module('FlyveMDM') 9 | .directive('loggedUserMenu', function () { 10 | return { 11 | templateUrl: 'views/loggedusermenu.html', 12 | restrict: 'E', 13 | link: function postLink(scope) { 14 | scope.opened = false; 15 | scope.fabModOpened = false; 16 | angular.element(document.querySelector('nav > ul.menu')).css({ 17 | }); 18 | scope.$watch('fabModOpened', function (opened) { 19 | if (opened) { 20 | angular.element(document.querySelector('nav > ul.menu')).removeClass('fab-usermenu-closed'); 21 | } else { 22 | angular.element(document.querySelector('nav > ul.menu')).addClass('fab-usermenu-closed'); 23 | } 24 | }); 25 | }, 26 | scope: {}, 27 | controller: function ($scope, AuthProvider) { 28 | var handleClickOutside = function () { 29 | $scope.$apply(function () { 30 | $scope.forceClose(); 31 | }); 32 | }; 33 | $scope.toggleOpened = function ($event) { 34 | $event.stopPropagation(); 35 | $scope.opened = !$scope.opened; 36 | if ($scope.opened) { 37 | angular.element(document.querySelector('html')).on('click', handleClickOutside); 38 | } 39 | }; 40 | $scope.forceClose = function () { 41 | $scope.opened = false; 42 | angular.element(document.querySelector('html')).off('click', handleClickOutside); 43 | return true; 44 | }; 45 | $scope.disconnect = function () { 46 | AuthProvider.logout().then(function () { 47 | AuthProvider.showLogin(); 48 | }); 49 | }; 50 | $scope.$on('$destroy', function () { 51 | angular.element(document.querySelector('html')).off('click', handleClickOutside); 52 | }); 53 | } 54 | }; 55 | }); 56 | -------------------------------------------------------------------------------- /app/scripts/directives/stpaginationscroll.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc directive 4 | * @name FlyveMDM.directive:stPaginationScroll 5 | * @description 6 | * # stPaginationScroll 7 | */ 8 | angular.module('FlyveMDM') 9 | .directive('flyveTable', ['$timeout', '$q', function (timeout) { 10 | return { 11 | require: 'stTable', 12 | link: function (scope, element, attr, ctrl) { 13 | var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1; 14 | var html = angular.element(document.querySelector('html')); 15 | var body = angular.element(document.body); 16 | var viewport = angular.element(document.querySelector('viewport')); 17 | var container = angular.element(element.parent().parent()); 18 | var tableState = ctrl.tableState(); 19 | var pagination = tableState.pagination; 20 | var lineHeight = 50; 21 | var viewportPaddingBottom = parseInt(viewport.css('padding-bottom').split('px')[0]); 22 | var baseHeight, remainingHeight, itemsByPage; 23 | var calibrate = function () { 24 | baseHeight = element[0].getBoundingClientRect().top + document.querySelector('thead').offsetHeight; 25 | remainingHeight = body[0].clientHeight - baseHeight; 26 | // 3 more in order to var space to scroll 27 | itemsByPage = Math.floor(remainingHeight / lineHeight) + 3; 28 | tableState.pagination.number = itemsByPage; 29 | }; 30 | var fetchNextPage = function () { 31 | //call next page 32 | ctrl.slice(pagination.start + pagination.number, pagination.number); 33 | }; 34 | var promise = null; 35 | var handleScroll = function () { 36 | var invisibleHeight; 37 | if (isFirefox) { 38 | invisibleHeight = html[0].scrollHeight - (html[0].clientHeight + html[0].scrollTop); 39 | } else { 40 | invisibleHeight = body[0].scrollHeight - (body[0].clientHeight + body[0].scrollTop); 41 | } 42 | var readingLastOne = invisibleHeight <= lineHeight + viewportPaddingBottom && 43 | invisibleHeight !== 0; // protecting at initialization 44 | var pastEnd = pagination.start + pagination.number >= pagination.totalItemCount; 45 | // adding the correct class to display the table header in 46 | // fixed mode after the header has been scrolled-out of 47 | // the display 48 | if (body[0].scrollTop >= baseHeight - 20) { 49 | body.addClass('has-fixed-header'); 50 | container.addClass('fixed-header'); 51 | } else { 52 | body.removeClass('has-fixed-header'); 53 | container.removeClass('fixed-header'); 54 | } 55 | if (readingLastOne && !pastEnd) { 56 | // if there is already a timer running which 57 | // has no expired yet we have to cancel 58 | // it and restart the timer 59 | if (promise !== null) { 60 | timeout.cancel(promise); 61 | } 62 | promise = timeout(function () { 63 | fetchNextPage(); 64 | promise = null; 65 | }, 400); 66 | } 67 | }; 68 | var afterResizeTimer = null; 69 | angular.element(window).on('resize', function () { 70 | if (afterResizeTimer !== null) { 71 | timeout.cancel(afterResizeTimer); 72 | } 73 | afterResizeTimer = timeout(function () { 74 | calibrate(); 75 | var currentNDisplayedElems = element.find('tbody tr').length; 76 | if (currentNDisplayedElems !== pagination.totalItemCount && 77 | currentNDisplayedElems < itemsByPage) { 78 | pagination.start = 0; 79 | fetchNextPage(); 80 | } 81 | }, 400); 82 | }); 83 | calibrate(); 84 | angular.element(window).on('scroll', handleScroll); 85 | scope.$on('$destroy', function () { 86 | angular.element(window).off('scroll', handleScroll); 87 | }); 88 | } 89 | }; 90 | }]); 91 | -------------------------------------------------------------------------------- /app/scripts/services/account.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc service 5 | * @name FlyveMDM.AccountFac 6 | * @description 7 | * # AccountFac 8 | * Factory in the FlyveMDM. 9 | */ 10 | angular.module('FlyveMDM') 11 | .factory('AccountFac', function (GLPI_API_URL, PluginObjectNames, AuthProvider, $q, $http) { 12 | // Service logic 13 | // Public API here 14 | return { 15 | validateAccount: function (id, hash) { 16 | var defer = $q.defer(); 17 | AuthProvider.getTempSessionToken().then(function (temp_session_token) { 18 | $http({ 19 | method: 'PUT', 20 | url: GLPI_API_URL + PluginObjectNames.AccountValidation, 21 | data: { 22 | input: { 23 | id: id, 24 | _validate: hash 25 | } 26 | }, 27 | headers: { 28 | 'Session-Token': temp_session_token 29 | } 30 | }).then(function (response) { 31 | defer.resolve(response.data); 32 | }, function () { 33 | defer.reject(); 34 | }); 35 | }, function () { 36 | defer.reject(); 37 | }); 38 | return defer.promise; 39 | } 40 | }; 41 | }); 42 | -------------------------------------------------------------------------------- /app/scripts/services/applications.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc service 5 | * @name FlyveMDM.AppsAdminFac 6 | * @description 7 | * # AppsAdminFac 8 | * Factory in the FlyveMDM. 9 | */ 10 | angular.module('FlyveMDM') 11 | .factory('AppsAdminFac', function (GLPI_API_URL, PluginObjectNames, AuthProvider, Upload, $q, $http) { 12 | // Service logic 13 | function bytesToSize(bytes) { 14 | bytes = parseInt(bytes); 15 | var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; 16 | if (bytes === 0) { 17 | return '0 Byte'; 18 | } 19 | var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024))); 20 | return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i]; 21 | } 22 | // Public API here 23 | return { 24 | getApplication: function (anApplicationId) { 25 | var getApplicationDefer = $q.defer(); 26 | $http({ 27 | method: 'GET', 28 | url: GLPI_API_URL + PluginObjectNames.Application + '/' + anApplicationId 29 | }).then(function (response) { 30 | var anApplication = response.data; 31 | anApplication.filesize = bytesToSize(anApplication.filesize); 32 | anApplication.type = anApplication.dl_filename.substring(anApplication.dl_filename.lastIndexOf(".") + 1, anApplication.dl_filename.length); 33 | getApplicationDefer.resolve(anApplication); 34 | }, function () { 35 | getApplicationDefer.reject(); 36 | }); 37 | return getApplicationDefer.promise; 38 | }, 39 | getApplications: function () { 40 | var getApplicationsDefer = $q.defer(); 41 | $http({ 42 | method: 'GET', 43 | url: GLPI_API_URL + PluginObjectNames.Application 44 | }).then(function (response) { 45 | var applications = response.data; 46 | var rApplications = applications.map(function (anApplication) { 47 | var rApplication = {}; 48 | rApplication.id = anApplication.id; 49 | rApplication.icon = anApplication.icon; 50 | rApplication.alias = anApplication.alias; 51 | rApplication.name = anApplication.name; 52 | rApplication.version = anApplication.version; 53 | rApplication.filesize = bytesToSize(anApplication.filesize); 54 | rApplication.type = anApplication.dl_filename.substring(anApplication.dl_filename.lastIndexOf(".") + 1, anApplication.dl_filename.length); 55 | return rApplication; 56 | }); 57 | getApplicationsDefer.resolve(rApplications); 58 | }, function () { 59 | getApplicationsDefer.reject(); 60 | }); 61 | return getApplicationsDefer.promise; 62 | }, 63 | updateApplication: function (anApplicationId, anApplicationAlias) { 64 | var updateApplicationDefer = $q.defer(); 65 | $http({ 66 | method: 'PUT', 67 | url: GLPI_API_URL + PluginObjectNames.Application, 68 | data: { 69 | input: { 70 | id: anApplicationId, 71 | alias: anApplicationAlias 72 | } 73 | } 74 | }).then(function () { 75 | updateApplicationDefer.resolve(); 76 | }, function () { 77 | updateApplicationDefer.reject(); 78 | }); 79 | return updateApplicationDefer.promise; 80 | }, 81 | deleteApplication: function (anApplicationId) { 82 | var deleteApplicationDefer = $q.defer(); 83 | $http({ 84 | method: 'DELETE', 85 | url: GLPI_API_URL + PluginObjectNames.Application + '/' + anApplicationId 86 | }).then(function () { 87 | deleteApplicationDefer.resolve(); 88 | }, function () { 89 | deleteApplicationDefer.reject(); 90 | }); 91 | return deleteApplicationDefer.promise; 92 | }, 93 | uploadApplication: function (aApplicationToUpload, anApplicationAlias) { 94 | return Upload.upload({ 95 | url: GLPI_API_URL + PluginObjectNames.Application, 96 | data: { 97 | file: aApplicationToUpload, 98 | uploadManifest: JSON.stringify({ 99 | input: { 100 | alias: anApplicationAlias 101 | } 102 | }) 103 | } 104 | }); 105 | } 106 | }; 107 | }); 108 | -------------------------------------------------------------------------------- /app/scripts/services/computers.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc service 5 | * @name FlyveMDM.ComputersFac 6 | * @description 7 | * # ComputersFac 8 | * Factory in the FlyveMDM. 9 | */ 10 | angular.module('FlyveMDM') 11 | .factory('ComputersFac', function (GLPI_API_URL, GlpiObjectNames, $q, $http) { 12 | // Service logic 13 | // Public API here 14 | return { 15 | getComputers: function () { 16 | var getUsersDefer = $q.defer(); 17 | $http({ 18 | method: 'GET', 19 | url: GLPI_API_URL + GlpiObjectNames.Computer 20 | }).then(function (response) { 21 | var computers = response.data; 22 | var rComputers = computers.map(function (aComputer) { 23 | var rComputer = {}; 24 | rComputer.id = aComputer.id; 25 | rComputer.email = aComputer.name; 26 | rComputer.realname = aComputer.realname; 27 | return rComputer; 28 | }); 29 | getUsersDefer.resolve(rComputers); 30 | }, function () { 31 | getUsersDefer.reject(); 32 | }); 33 | return getUsersDefer.promise; 34 | } 35 | }; 36 | }); 37 | -------------------------------------------------------------------------------- /app/scripts/services/devices.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc service 4 | * @name FlyveMDM.DevicesFac 5 | * @description 6 | * # DevicesFac 7 | * Factory in the FlyveMDM. 8 | */ 9 | angular.module('FlyveMDM') 10 | .factory('DevicesFac', function (GLPI_API_URL, GlpiObjectNames, PluginObjectNames, $q, $http) { 11 | // Service logic 12 | // ... 13 | // Public API here 14 | return { 15 | getDevicesData: function () { //param range ToDo 16 | var promises = { 17 | getAgents: $http.get(GLPI_API_URL + PluginObjectNames.Agent), 18 | getUsers: $http.get(GLPI_API_URL + GlpiObjectNames.GlpiUser), 19 | getFleets: $http.get(GLPI_API_URL + PluginObjectNames.Fleet), 20 | getComputers: $http.get(GLPI_API_URL + GlpiObjectNames.Computer, { params: { expand_dropdowns: true } }), 21 | }; 22 | return $q.all(promises); 23 | }, 24 | deleteDevice: function (aDeviceId) { 25 | var deferred = $q.defer(); 26 | $http({ 27 | method: 'DELETE', 28 | url: GLPI_API_URL + PluginObjectNames.Agent + '/' + aDeviceId 29 | }).then(function () { 30 | deferred.resolve(); 31 | }, function () { 32 | deferred.reject(); 33 | }); 34 | return deferred.promise; 35 | }, 36 | }; 37 | }); 38 | -------------------------------------------------------------------------------- /app/scripts/services/entityconfig.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc service 4 | * @name FlyveMDM.EntityConfigFac 5 | * @description 6 | * # EntityConfigFac 7 | * Factory in the FlyveMDM. 8 | */ 9 | angular.module('FlyveMDM') 10 | .factory('EntityConfigFac', function (GLPI_API_URL, PluginObjectNames, $q, $http) { 11 | // Service logic 12 | // Public API here 13 | return { 14 | editConfiguration: function (aEntityId, anInput) { 15 | var deferred = $q.defer(); 16 | $http({ 17 | method: 'PUT', 18 | url: GLPI_API_URL + PluginObjectNames.Entityconfig + '/' + aEntityId, 19 | data: { 20 | input: anInput 21 | } 22 | }).then(function (response) { 23 | deferred.resolve(response.data.data[0]); 24 | }, function () { 25 | deferred.reject(); 26 | }); 27 | return deferred.promise; 28 | }, 29 | getConfiguration: function (aEntityId) { 30 | var deferred = $q.defer(); 31 | $http({ 32 | method: 'GET', 33 | url: GLPI_API_URL + PluginObjectNames.Entityconfig + '/' + aEntityId, 34 | }).then(function (response) { 35 | deferred.resolve(response.data); 36 | }, function () { 37 | deferred.reject(); 38 | }); 39 | return deferred.promise; 40 | }, 41 | getConfigurations: function () { 42 | var deferred = $q.defer(); 43 | $http({ 44 | method: 'GET', 45 | url: GLPI_API_URL + PluginObjectNames.Entityconfig 46 | }).then(function (response) { 47 | deferred.resolve(response.data); 48 | }, function () { 49 | deferred.reject(); 50 | }); 51 | return $q.all(deferred.promise); 52 | } 53 | }; 54 | }); 55 | -------------------------------------------------------------------------------- /app/scripts/services/files.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc service 5 | * @name FlyveMDM.FilesAdminFac 6 | * @description 7 | * # FilesAdminFac 8 | * Factory in the FlyveMDM. 9 | */ 10 | angular.module('FlyveMDM') 11 | .factory('FilesAdminFac', function (GLPI_API_URL, PluginObjectNames, AuthProvider, Upload, $q, $http) { 12 | // Service logic 13 | // Public API here 14 | return { 15 | getFile: function (aFileId) { 16 | var getFileDefer = $q.defer(); 17 | $http({ 18 | method: 'GET', 19 | url: GLPI_API_URL + PluginObjectNames.File + '/' + aFileId 20 | }).then(function (response) { 21 | var aFile = response.data; 22 | var rFile = {}; 23 | rFile.id = aFile.id; 24 | rFile.name = aFile.name; 25 | rFile.source = aFile.source; 26 | getFileDefer.resolve(rFile); 27 | }, function () { 28 | getFileDefer.reject(); 29 | }); 30 | return getFileDefer.promise; 31 | }, 32 | getFiles: function () { 33 | var getFilesDefer = $q.defer(); 34 | $http({ 35 | method: 'GET', 36 | url: GLPI_API_URL + PluginObjectNames.File 37 | }).then(function (response) { 38 | var files = response.data; 39 | var rFiles = files.map(function (aFile) { 40 | var rFile = {}; 41 | rFile.id = aFile.id; 42 | rFile.name = aFile.name; 43 | rFile.source = aFile.source; 44 | return rFile; 45 | }); 46 | getFilesDefer.resolve(rFiles); 47 | }, function () { 48 | getFilesDefer.reject(); 49 | }); 50 | return getFilesDefer.promise; 51 | }, 52 | updateFile: function (aFileId, aFileName) { 53 | var updateFileDefer = $q.defer(); 54 | $http({ 55 | method: 'PUT', 56 | url: GLPI_API_URL + PluginObjectNames.File, 57 | data: { 58 | input: { 59 | id: aFileId, 60 | name: aFileName 61 | } 62 | } 63 | }).then(function () { 64 | updateFileDefer.resolve(); 65 | }, function () { 66 | updateFileDefer.reject(); 67 | }); 68 | return updateFileDefer.promise; 69 | }, 70 | deleteFile: function (aFileId) { 71 | var deleteFileDefer = $q.defer(); 72 | $http({ 73 | method: 'DELETE', 74 | url: GLPI_API_URL + PluginObjectNames.File + '/' + aFileId 75 | }).then(function () { 76 | deleteFileDefer.resolve(); 77 | }, function () { 78 | deleteFileDefer.reject(); 79 | }); 80 | return deleteFileDefer.promise; 81 | }, 82 | uploadFile: function (aFileToUpload) { 83 | var uploadFileDefer = $q.defer(); 84 | Upload.upload({ 85 | url: GLPI_API_URL + '/' + PluginObjectNames.File, 86 | data: { 87 | file: aFileToUpload, 88 | uploadManifest: JSON.stringify({ 89 | session_token: AuthProvider.getCurrentToken(), 90 | input: { 91 | name: aFileToUpload.name 92 | } 93 | }) 94 | } 95 | }).then(function (resp) { 96 | uploadFileDefer.resolve(resp); 97 | }, function (resp) { 98 | uploadFileDefer.resolve(resp.status); 99 | }, function (evt) { 100 | var progressPercentage = parseInt(100.0 * evt.loaded / evt.total); 101 | uploadFileDefer.notify(progressPercentage); 102 | }); 103 | return uploadFileDefer.promise; 104 | }, 105 | uploadFile2: function (aFile, aFileName) { 106 | return Upload.upload({ 107 | url: GLPI_API_URL + '/' + PluginObjectNames.File, 108 | data: { 109 | file: aFile, 110 | uploadManifest: JSON.stringify({ 111 | input: { 112 | name: aFileName 113 | } 114 | }) 115 | } 116 | }); 117 | } 118 | }; 119 | }); 120 | -------------------------------------------------------------------------------- /app/scripts/services/fullsession.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc service 4 | * @name FlyveMDM.FullSessionFac 5 | * @description 6 | * # FullSessionFac 7 | * Factory in the FlyveMDM. 8 | */ 9 | angular.module('FlyveMDM') 10 | .factory('FullSessionFac', function (GLPI_API_URL, GlpiObjectNames, $q, $http) { 11 | return { 12 | getSession: function () { 13 | var promises = { 14 | getFullSession: $http.get(GLPI_API_URL + GlpiObjectNames.FullSession) 15 | }; 16 | return $q.all(promises); 17 | } 18 | }; 19 | }); 20 | -------------------------------------------------------------------------------- /app/scripts/services/geolocation.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc service 4 | * @name FlyveMDM.GeolocationFac 5 | * @description 6 | * # GeolocationFac 7 | * Factory in the FlyveMDM. 8 | */ 9 | angular.module('FlyveMDM') 10 | .factory('GeolocationFac', function (GLPI_API_URL, GlpiObjectNames, PluginObjectNames, $q, $http) { 11 | // Service logic 12 | // Public API here 13 | return { 14 | getDeviceGeolocations: function (aComputerId, from, to) { 15 | // the searchOption IDs for geolocation 16 | var deviceGeolocationsDefer = $q.defer(); 17 | var searchOptionsIds = { 18 | "id": 2, 19 | "name": 1, 20 | "computer_id": 3, 21 | "latitude": 4, 22 | "longitude": 5, 23 | "date": 6 24 | }; 25 | var getSearchOptionIdFromPredicateName = function (predicateName) { 26 | return searchOptionsIds[predicateName]; 27 | }; 28 | $http({ 29 | method: 'GET', 30 | url: GLPI_API_URL + '/search' + PluginObjectNames.Geolocation, 31 | params: { 32 | order: 'DESC', 33 | sort: getSearchOptionIdFromPredicateName('date'), 34 | "forcedisplay[0]": getSearchOptionIdFromPredicateName('latitude'), 35 | "forcedisplay[1]": getSearchOptionIdFromPredicateName('longitude'), 36 | "forcedisplay[2]": getSearchOptionIdFromPredicateName('date'), 37 | "forcedisplay[3]": getSearchOptionIdFromPredicateName('id'), 38 | "criteria[0][field]": getSearchOptionIdFromPredicateName('computer_id'), 39 | "criteria[0][type]": "equals", 40 | "criteria[0][value]": aComputerId, 41 | range: '' + from + '-' + to 42 | }, 43 | //timeout: geolocationPageFetchRequestCanceller.promise 44 | }).then(function (response) { 45 | response.data = response.data.data; 46 | var latestGeolocations = []; 47 | if (response.data) { 48 | response.data.forEach(function (_geolocation) { 49 | latestGeolocations.push({ 50 | id: parseInt(_geolocation[getSearchOptionIdFromPredicateName('id')]), 51 | displayable: { 52 | lat: parseFloat(_geolocation[getSearchOptionIdFromPredicateName('latitude')]), 53 | lng: parseFloat(_geolocation[getSearchOptionIdFromPredicateName('longitude')]), 54 | }, 55 | date: _geolocation[getSearchOptionIdFromPredicateName('date')], 56 | timeAgo: moment.utc(_geolocation[getSearchOptionIdFromPredicateName('date')]).fromNow(), 57 | displayed: 'timeAgo' 58 | }); 59 | }); 60 | } 61 | response.data = latestGeolocations.sort(function (a, b) { 62 | var dateA = -moment(a.date).unix(); 63 | var dateB = -moment(b.date).unix(); 64 | if (dateA < dateB) { 65 | return -1; 66 | } 67 | if (dateA > dateB) { 68 | return 1; 69 | } 70 | // date must be equal 71 | return 0; 72 | }); 73 | deviceGeolocationsDefer.resolve(response); 74 | }, function () { 75 | deviceGeolocationsDefer.reject(); 76 | }); 77 | return deviceGeolocationsDefer.promise; 78 | }, 79 | requestCurrentGeolocation: function (aDeviceId) { 80 | var currentGeolocationDefer = $q.defer(); 81 | $http({ 82 | method: 'PUT', 83 | url: GLPI_API_URL + PluginObjectNames.Agent + '/' + aDeviceId, 84 | data: { 85 | input: { 86 | _geolocate: "" 87 | } 88 | } 89 | }).then(function () { 90 | currentGeolocationDefer.resolve(); 91 | }, function () { 92 | currentGeolocationDefer.reject(); 93 | }); 94 | return currentGeolocationDefer.promise; 95 | } 96 | }; 97 | }); 98 | -------------------------------------------------------------------------------- /app/scripts/services/glosaryobjectnames.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc service 5 | * @name FlyveMDM.GlosaryObjectNames 6 | * @description 7 | * # GlosaryObjectNames 8 | * Constant in the FlyveMDM. 9 | */ 10 | angular.module('FlyveMDM') 11 | .constant('GlosaryObjectNames', { 12 | 'agent.id': null, 13 | 'computer.id': null, 14 | 'device.type': null, 15 | 'device.model': null, 16 | 'device.manufacturer': null, 17 | 'device.serial': null, 18 | 'date.creation': null, 19 | 'date.modification': null, 20 | 'date.last_report': null, 21 | 'date.last_contact': null, 22 | 'launch.announced': 'The time when the device was publicly announced. Sometimes it takes months or even a year for the device to reach the market.\nAgain this is the time the device was ANNOUNCED, not RELEASED.', 23 | 'launch.status': 'Coming soon - Announced, but not yet available in stores.\nAvailable - In production, or still can be found new in stores.\nDiscontinued - Not in production, can be found only second hand.\nCancelled - Announced, then officialy cancelled. Rumored - Not officially announced or even confirmed for market release yet', 24 | 'body.dimensions': 'The size of the device in format (H x L x W) and the volume of the device where available.\nIf the device has a flip, it is measured with the flip closed.', 25 | 'body.weight': 'Lists the weight of the device in grams. Sometimes the manufactures don\'t list the weight before the handset becomes market available. As usual we try and update the field as frequently as needed.', 26 | 'body.sim': null, 27 | 'body.protection': null, 28 | 'display.type': null, 29 | 'display.size': 'The industry standard way of representing display sizes is publishing their length in inches. The screen-to-body ratio is a measure which relates to the size of the screen bezels. The bigger the ratio, the smaller the bezels are, meaning the display takes up a larger area on the device\'s front.', 30 | 'display.resolution': 'The industry standard way of representing screen resolution is publishing the number of pixels that form the two sides of the display rectangle. Usually, the display side that sits at the bottom when you hold the device in your hand is cited first. For the older alphanumeric displays the screen resolution is shown in screen lines or characters per screen line instead. In this case since there will be more pixels per an inch-long line of pixels on the smaller display, the image will look subjectively clearer and more detailed. Hence the importance of the other parameter that we publish - pixel density, which is measured in pixels-per-inch (ppi).', 31 | 'display.multitouch': null, 32 | 'display.protection': null, 33 | 'display.others': null, 34 | 'platform.os': null, 35 | 'platform.chipset': null, 36 | 'platform.cpu': null, 37 | 'platform.gpu': null, 38 | 'memory.card_slot': null, 39 | 'memory.non_volatile': null, 40 | 'memory.volatile': null, 41 | 'memory.partitioning': null, 42 | 'camera.primary': null, 43 | 'camera.features': null, 44 | 'camera.video': null, 45 | 'camera.secondary': null, 46 | 'sound.alert_types': null, 47 | 'sound.loudspeaker': null, 48 | 'sound.connections': null, 49 | 'network.technology': null, 50 | 'network[\'2g_bands\']': null, 51 | 'network[\'3g_bands\']': null, 52 | 'network[\'4g_bands\']': null, 53 | 'network.speed': null, 54 | 'network.gprs': null, 55 | 'network.edge': null, 56 | 'comms.wlan': null, 57 | 'comms.bluetooth': null, 58 | 'comms.gps': null, 59 | 'comms.nfc': null, 60 | 'comms.radio': null, 61 | 'comms.usb': null, 62 | 'sensors.type': null, 63 | 'sensors.manufacturer': null, 64 | 'features.messaging': null, 65 | 'features.browser': null, 66 | 'features.java': null, 67 | 'features.others': null, 68 | 'battery.details': null, 69 | 'battery.[\'stand-by\']': null, 70 | 'battery.talk_time': null, 71 | 'battery.music_play': null, 72 | 'misc.colors': 'Lists all the available optional color schemes the handset is available in.', 73 | 'misc.sar_us': null, 74 | 'misc.sar_eu': null, 75 | 'misc.price_group': 'Mobile device prices are dynamic and change every day. We can\'t monitor the prices of the thousands of models in our database on a daily basis. Instead, we are showing reference pricing information, which can be used for comparison purposes. If you want to know the exact price of a device, please log on to the websites listed in the Check Price list below the device image.', 76 | 'tests.performance': null, 77 | 'tests.display': null, 78 | 'tests.camera': null, 79 | 'tests.loudspeaker': null, 80 | 'tests.audio_quality': null, 81 | 'tests.battery_life': null 82 | }); 83 | -------------------------------------------------------------------------------- /app/scripts/services/glpiobjectnames.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc service 4 | * @name FlyveMDM.GlpiObjectNames 5 | * @description 6 | * # GlpiObjectNames 7 | * Value in the FlyveMDM. 8 | */ 9 | angular.module('FlyveMDM') 10 | .constant('GlpiObjectNames', { 11 | ActiveEntities: "/getActiveEntities", 12 | Computer: "/Computer", 13 | ComputerAntivirus: "/ComputerAntivirus", 14 | ComputerDisk: "/ComputerDisk", 15 | ComputerModel: "/ComputerModel", 16 | ComputerType: "/ComputerType", 17 | ComputerVirtualMachine: "/ComputerVirtualMachine", 18 | Computer_SoftwareVersion: "/Computer_SoftwareVersion", 19 | Computer_SoftwareLicense: "/Computer_SoftwareLicense", 20 | Config: "/Config", 21 | Contract_Item: "/Contract_Item", 22 | DeviceCase: "/DeviceCase", 23 | DeviceControl: "/DeviceControl", 24 | DeviceDrive: "/DeviceDrive", 25 | DeviceGraphicCard: "/DeviceGraphicCard", 26 | DeviceHardDrive: "/DeviceHardDrive", 27 | DeviceMemory: "/DeviceMemory", 28 | DeviceMemoryType: "/DeviceMemoryType", 29 | DeviceMotherboard: "/DeviceMotherboard", 30 | DeviceNetworkCard: "/DeviceNetworkCard", 31 | DevicePci: "/DevicePci", 32 | DevicePowerSupplyrel: "/DevicePowerSupply", 33 | DeviceProcessor: "/DeviceProcessor", 34 | DeviceSoundCard: "/DeviceSoundCard", 35 | Document_Item: "/Document_Item", 36 | Entity: "/Entity", 37 | FileSystem: "/FileSystem", 38 | FullSession: "/getFullSession", 39 | ActiveProfile: "/getActiveProfile", 40 | GlpiUser: "/User", 41 | Infocom: "/Infocom", 42 | InitSession: "/initSession", 43 | IpAddress: "/IpAddress", 44 | Item_Project: "/Item_Project", 45 | Item_Ticket: "/Item_Ticket", 46 | KillSession: "/killSession", 47 | Manufacturer: "/Manufacturer", 48 | NetworkPort: "/NetworkPort", 49 | OperatingSystem: "/OperatingSystem", 50 | OperatingSystemVersion: "/OperatingSystemVersion", 51 | Profile_User: "/Profile_User", 52 | ReservationItem: "/ReservationItem", 53 | Software: "/Software", 54 | SoftwareCategory: "/SoftwareCategory", 55 | SoftwareVersion: "/SoftwareVersion", 56 | VirtualMachineSystem: "/VirtualMachineSystem", 57 | VirtualMachineType: "/VirtualMachineType" 58 | }); 59 | -------------------------------------------------------------------------------- /app/scripts/services/invitationlogs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc service 4 | * @name FlyveMDM.InvitationLogsFac 5 | * @description 6 | * # InvitationLogsFac 7 | * Factory in the FlyveMDM. 8 | */ 9 | angular.module('FlyveMDM') 10 | .factory('InvitationLogsFac', function (GLPI_API_URL, PluginObjectNames, $q, $http) { 11 | // Service logic 12 | // Public API here 13 | return { 14 | getLogs: function (logId) { 15 | var deferred = $q.defer(); 16 | $http({ 17 | method: 'GET', 18 | url: GLPI_API_URL + PluginObjectNames.Invitation + '/' + logId + '/' + PluginObjectNames.InvitationLog 19 | }).then(function (response) { 20 | var logs = response.data; 21 | var rLogs = logs.map(function (aLog) { 22 | var rLog = {}; 23 | rLog.id = aLog.id, 24 | rLog.date_creation = aLog.date_creation; 25 | rLog.event = aLog.event; 26 | return rLog; 27 | }); 28 | deferred.resolve(rLogs); 29 | }, function () { 30 | deferred.reject(); 31 | }); 32 | return deferred.promise; 33 | } 34 | }; 35 | }); 36 | -------------------------------------------------------------------------------- /app/scripts/services/invitations.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc service 4 | * @name FlyveMDM.InvitationsFac 5 | * @description 6 | * # InvitationsFac 7 | * Factory in the FlyveMDM. 8 | */ 9 | angular.module('FlyveMDM') 10 | .factory('InvitationsFac', function (GLPI_API_URL, GlpiObjectNames, PluginObjectNames, $q, $http) { 11 | // Service logic 12 | // Public API here 13 | return { 14 | enrollNewDevice: function (anUserEmail) { 15 | var deferred = $q.defer(); 16 | $http({ 17 | method: 'POST', 18 | url: GLPI_API_URL + PluginObjectNames.Invitation, 19 | data: { 20 | input: { 21 | _useremails: anUserEmail 22 | } 23 | } 24 | }).then(function (response) { 25 | deferred.resolve(response.data.id); 26 | }, function () { 27 | deferred.reject(); 28 | }); 29 | return deferred.promise; 30 | }, 31 | resendInvitation: function (aDeviceId, anUserEmail) { 32 | var deferred = $q.defer(); 33 | $http({ 34 | method: 'PUT', 35 | url: GLPI_API_URL + PluginObjectNames.Invitation + '/' + aDeviceId, 36 | data: { 37 | input: { 38 | _notify: anUserEmail 39 | } 40 | } 41 | }).then(function (response) { 42 | deferred.resolve(response.data[0]); 43 | }, function () { 44 | deferred.reject(); 45 | }); 46 | return deferred.promise; 47 | }, 48 | deleteInvitation: function (aDeviceId) { 49 | var deferred = $q.defer(); 50 | $http({ 51 | method: 'DELETE', 52 | url: GLPI_API_URL + PluginObjectNames.Invitation + '/' + aDeviceId 53 | }).then(function () { 54 | deferred.resolve(); 55 | }, function () { 56 | deferred.reject(); 57 | }); 58 | return deferred.promise; 59 | }, 60 | getInvitations: function () { 61 | var deferred = $q.defer(); 62 | $http({ 63 | method: 'GET', 64 | url: GLPI_API_URL + PluginObjectNames.Invitation 65 | }).then(function (response) { 66 | var status = { status: 'pending' }; 67 | var invitations = response.data.filter(function (invitation) { 68 | return Object.keys(status).every(function (key) { 69 | return invitation[key] === status[key]; 70 | }); 71 | }); 72 | deferred.resolve(invitations); 73 | }, function () { 74 | deferred.reject(); 75 | }); 76 | var promises = { 77 | getInvitations: deferred.promise, 78 | getUsers: $http.get(GLPI_API_URL + GlpiObjectNames.GlpiUser) 79 | }; 80 | return $q.all(promises); 81 | }, 82 | getInvitation: function (invitationId) { 83 | var deferred = $q.defer(); 84 | $http({ 85 | method: 'GET', 86 | url: GLPI_API_URL + PluginObjectNames.Invitation + '/' + invitationId 87 | }).then(function (response) { 88 | var anInvitation = response.data; 89 | var rInvitation = {}; 90 | rInvitation.users_id = anInvitation.users_id; 91 | deferred.resolve(rInvitation); 92 | }, function () { 93 | deferred.reject(); 94 | }); 95 | return deferred.promise; 96 | } 97 | }; 98 | }); 99 | -------------------------------------------------------------------------------- /app/scripts/services/navigation.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc service 4 | * @name FlyveMDM.navigation 5 | * @description 6 | * # navigation 7 | * Provider in the FlyveMDM. 8 | */ 9 | angular.module('FlyveMDM') 10 | .directive('flyveNavigation', function (AuthProvider) { 11 | var disabled_routes = ['login']; 12 | return { 13 | restrict: 'A', 14 | templateUrl: 'views/navigation.html', 15 | link: function (scope, element, attr, ctrl) { 16 | scope.visible = false; 17 | scope.smallForced = false; 18 | var body = angular.element(document.body); 19 | // $watch'ing $scope.visible now in order to 20 | // maintain the correct classes applied on 21 | // the directive's element 22 | scope.$watch('visible', function (visible_boolean) { 23 | if (visible_boolean) { 24 | body.removeClass('nav-invisible'); 25 | } else { 26 | body.addClass('nav-invisible'); 27 | } 28 | }); 29 | scope.$watch('smallForced', function (small_boolean) { 30 | if (small_boolean) { 31 | body.addClass('nav-forced-small'); 32 | } else { 33 | body.removeClass('nav-forced-small'); 34 | } 35 | }); 36 | // enabling display only on non disabled routes using the controller method 37 | scope.$on('$stateChangeSuccess', function (ev, toState) { 38 | if (disabled_routes.indexOf(toState.name) > -1 || !AuthProvider.seemsLogged()) { 39 | ctrl.setVisible(false); 40 | } else { 41 | ctrl.setVisible(true); 42 | } 43 | }); 44 | }, 45 | controller: function ($scope) { 46 | this.toggleSmall = function () { 47 | $scope.smallForced = !$scope.smallForced; 48 | }; 49 | this.setVisible = function (visible_boolean) { 50 | $scope.visible = visible_boolean; 51 | }; 52 | }, 53 | controllerAs: 'nav', 54 | scope: {} 55 | }; 56 | }) 57 | .directive('navbarSubmenu', function () { 58 | return { 59 | restrict: 'E', 60 | link: function (scope, element, attr, ctrl, transcludeFn) { 61 | scope.visible = false; 62 | var button = element.parent()[0].firstElementChild; 63 | button.addEventListener("click", function () { 64 | ctrl.toggleMenu(); 65 | }, false); 66 | scope.$watch('visible', function (visible) { 67 | if (visible) { 68 | element.attr('class', 'visible'); 69 | } else { 70 | element.attr('class', ''); 71 | } 72 | }); 73 | // Applying active class when one of the state is triggered (hardcoded but it's up the be changed in a commit) 74 | scope.$on('$stateChangeSuccess', function (ev, toState) { 75 | if (['admin_fleets', 'admin_files', 'admin_applications', 'admin_users'].indexOf(toState.name) > -1) { 76 | button.setAttribute('class', 'active'); 77 | } else { 78 | button.setAttribute('class', ''); 79 | } 80 | }); 81 | element.append(transcludeFn()); 82 | }, 83 | controller: function ($scope) { 84 | this.toggleMenu = function () { 85 | $scope.$apply(function () { 86 | $scope.visible = !$scope.visible; 87 | }); 88 | }; 89 | }, 90 | transclude: true, 91 | scope: {} 92 | }; 93 | }) 94 | .run(function () { 95 | angular.element(document.body) 96 | .prepend(''); 97 | }); 98 | -------------------------------------------------------------------------------- /app/scripts/services/notifications.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc service 5 | * @name FlyveMDM.Notifications 6 | * @description 7 | * # Notifications 8 | * Service in the FlyveMDM. 9 | */ 10 | angular.module('FlyveMDM') 11 | .service('Notifications', function ($mdToast) { 12 | this.done = function (textContent) { 13 | var notificationEnable = localStorage.notificationEnable ? JSON.parse(localStorage.notificationEnable) : true; 14 | var notificationType = localStorage.notificationType ? localStorage.notificationType : 'Toast'; 15 | if (notificationEnable) { 16 | switch (notificationType) { 17 | case 'Native': 18 | var options = { 19 | body: textContent, 20 | icon: 'images/stupid-user-avatar.png' 21 | }; 22 | var n = new Notification('FlyveMDM', options); 23 | setTimeout(n.close.bind(n), 2000); 24 | return n; 25 | case 'Toast': 26 | var toast = $mdToast.simple() 27 | .textContent(textContent) 28 | .action('CLOSE') 29 | .highlightAction(true) 30 | .highlightClass('md-primary') 31 | .position('top right') 32 | .hideDelay(2000) 33 | .capsule(true); 34 | return $mdToast.show(toast); 35 | } 36 | } 37 | }; 38 | this.loading = function (textContent, resolve) { 39 | var notificationEnable = localStorage.notificationEnable ? JSON.parse(localStorage.notificationEnable) : true; 40 | var notificationType = localStorage.notificationType ? localStorage.notificationType : 'Toast'; 41 | if (notificationEnable) { 42 | switch (notificationType) { 43 | case 'Native': 44 | var options = { 45 | body: textContent, 46 | icon: 'images/stupid-user-avatar.png' 47 | }; 48 | return new Notification('FlyveMDM', options); 49 | case 'Toast': 50 | var toast = $mdToast.simple() 51 | .textContent(textContent) 52 | .action('CANCEL') 53 | .highlightAction(true) 54 | .highlightClass('md-accent') 55 | .position('top right') 56 | .capsule(true) 57 | .hideDelay(false); 58 | $mdToast.show(toast).then(function (response) { 59 | if (response === 'ok') { 60 | if (resolve) { 61 | resolve("User cancelled"); 62 | } 63 | } 64 | }); 65 | } 66 | } 67 | }; 68 | this.error = function (textContent) { 69 | var notificationType = localStorage.notificationType ? localStorage.notificationType : 'Toast'; 70 | switch (notificationType) { 71 | case 'Native': 72 | var options = { 73 | body: textContent, 74 | icon: 'images/stupid-user-avatar.png' 75 | }; 76 | return new Notification('FlyveMDM', options); 77 | case 'Toast': 78 | var toast = $mdToast.simple() 79 | .textContent(textContent) 80 | .action('CLOSE') 81 | .highlightAction(true) 82 | .highlightClass('md-warn') 83 | .position('top right') 84 | .capsule(true) 85 | .hideDelay(false); 86 | return $mdToast.show(toast); 87 | } 88 | }; 89 | this.update = function (textContent) { 90 | $mdToast.updateTextContent(textContent); 91 | }; 92 | this.hide = function (textContent) { 93 | $mdToast.hide(textContent); 94 | }; 95 | }); 96 | -------------------------------------------------------------------------------- /app/scripts/services/pluginobjectnames.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc service 5 | * @name FlyveMDM.PluginObjectNames 6 | * @description 7 | * # PluginObjectNames 8 | * Constant in the FlyveMDM. 9 | */ 10 | angular.module('FlyveMDM') 11 | .constant('PluginObjectNames', { 12 | Agent: "/PluginFlyvemdmAgent", 13 | Entityconfig: "/PluginFlyvemdmEntityconfig", 14 | File: "/PluginFlyvemdmFile", 15 | Fleet: "/PluginFlyvemdmFleet", 16 | FleetPolicy: "/PluginFlyvemdmFleet_Policy", 17 | Geolocation: "/PluginFlyvemdmGeolocation", 18 | Invitation: "/PluginFlyvemdmInvitation", 19 | InvitationLog: "/PluginFlyvemdmInvitationLog", 20 | Application: "/PluginFlyvemdmPackage", 21 | Policy: "/PluginFlyvemdmPolicy", 22 | PolicyCategory: "/PluginFlyvemdmPolicyCategory", 23 | User: "/PluginFlyvemdmdemoUser", 24 | WellknownPath: "/PluginFlyvemdmWellknownPath", 25 | AccountValidation: "/PluginFlyvemdmdemoAccountvalidation" 26 | }); 27 | -------------------------------------------------------------------------------- /app/scripts/services/software.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @ngdoc service 5 | * @name FlyveMDM.software 6 | * @description 7 | * # software 8 | * Factory in the FlyveMDM. 9 | */ 10 | angular.module('FlyveMDM') 11 | .factory('software', function () { 12 | // Service logic 13 | // ... 14 | 15 | var meaningOfLife = 42; 16 | 17 | // Public API here 18 | return { 19 | someMethod: function () { 20 | return meaningOfLife; 21 | } 22 | }; 23 | }); 24 | -------------------------------------------------------------------------------- /app/scripts/services/userpreferences.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @ngdoc service 4 | * @name FlyveMDM.UserPreferencesFac 5 | * @description 6 | * # UserPreferencesFac 7 | * Factory in the FlyveMDM. 8 | */ 9 | angular.module('FlyveMDM') 10 | .factory('UserPreferencesFac', function (GLPI_API_URL, GlpiObjectNames, $q, $http) { 11 | return { 12 | updateMyPassword: function (userId, password, password2) { 13 | var deffered = $q.defer(); 14 | $http.put( 15 | GLPI_API_URL + GlpiObjectNames.GlpiUser + '/' + userId, 16 | { input: { password: password, password2: password2 } } 17 | 18 | ).then(function (response) { 19 | deffered.resolve(response); 20 | }, function () { 21 | deffered.reject(); 22 | }); 23 | return deffered.promise; 24 | }, 25 | changeLanguage: function (aUserId, aCode) { 26 | var deffered = $q.defer(); 27 | $http.put( 28 | GLPI_API_URL + GlpiObjectNames.GlpiUser + '/' + aUserId, 29 | { input: { language: aCode } } 30 | ).then(function (response) { 31 | deffered.resolve(response.data); 32 | }, function () { 33 | deffered.reject(); 34 | }); 35 | return deffered.promise; 36 | }, 37 | updateUserInformation: function (anInput) { 38 | var deffered = $q.defer(); 39 | var user = { 40 | name: anInput.name, 41 | phone: anInput.phone, 42 | phone2: anInput.phone2, 43 | mobile: anInput.mobile, 44 | realname: anInput.realname, 45 | firstname: anInput.firstname, 46 | registration_number: anInput.registration_number, 47 | }; 48 | $http.put( 49 | GLPI_API_URL + GlpiObjectNames.GlpiUser + '/' + anInput.id, 50 | { input: user } 51 | ).then(function (response) { 52 | deffered.resolve(response.data); 53 | }, function () { 54 | deffered.reject(); 55 | }); 56 | return deffered.promise; 57 | }, 58 | getUserInformation: function (aUserId) { 59 | var deffered = $q.defer(); 60 | $http({ 61 | method: 'GET', 62 | url: GLPI_API_URL + GlpiObjectNames.GlpiUser + '/' + aUserId, 63 | }).then(function (response) { 64 | var user = response.data; 65 | var rUser = { 66 | name: user.name, 67 | phone: user.phone, 68 | phone2: user.phone2, 69 | mobile: user.mobile, 70 | realname: user.realname, 71 | firstname: user.firstname, 72 | language: user.language, 73 | last_login: user.last_login, 74 | date_mod: user.date_mod, 75 | date_creation: user.date_creation, 76 | registration_number: user.registration_number, 77 | picture: user.picture 78 | }; 79 | deffered.resolve(rUser); 80 | }, function () { 81 | deffered.reject(); 82 | }); 83 | return deffered.promise; 84 | }, 85 | getPluginVersion: function () { 86 | var deffered = $q.defer(); 87 | $http({ 88 | method: 'GET', 89 | url: GLPI_API_URL + GlpiObjectNames.Config, 90 | params: { 91 | 'searchText[name]': 'version', 92 | 'searchText[context]': 'flyvemdm' 93 | } 94 | }).then(function (response) { 95 | var config = response.data; 96 | var version = config[0].value; 97 | deffered.resolve(version); 98 | }, function () { 99 | deffered.reject(); 100 | }); 101 | return deffered.promise; 102 | }, 103 | getGLPiVersion: function () { 104 | var deffered = $q.defer(); 105 | $http({ 106 | method: 'GET', 107 | url: GLPI_API_URL + GlpiObjectNames.Config, 108 | params: { 109 | 'searchText[name]': 'version', 110 | 'searchText[context]': 'core' 111 | } 112 | }).then(function (response) { 113 | var config = response.data; 114 | var version = config[0].value; 115 | deffered.resolve(version); 116 | }, function () { 117 | deffered.reject(); 118 | }); 119 | return deffered.promise; 120 | }, 121 | getPluginList: function () { 122 | var deffered = $q.defer(); 123 | $http({ 124 | method: 'GET', 125 | url: GLPI_API_URL + GlpiObjectNames.FullSession 126 | }).then(function (response) { 127 | var glpi_plugins = []; 128 | for (var plugin in response.data.session.glpi_plugins) { 129 | glpi_plugins.push(response.data.session.glpi_plugins[plugin]); 130 | } 131 | deffered.resolve(glpi_plugins); 132 | }, function () { 133 | deffered.reject(); 134 | }); 135 | return deffered.promise; 136 | } 137 | }; 138 | }); -------------------------------------------------------------------------------- /app/socialmedia.txt: -------------------------------------------------------------------------------- 1 | https://twitter.com/FlyveMDM 2 | https://plus.google.com/collection/c32TsB 3 | -------------------------------------------------------------------------------- /app/styles/_about_page.sass: -------------------------------------------------------------------------------- 1 | .about-page 2 | padding: 24px 10px 3 | md-tabs 4 | md-tab-content 5 | margin-bottom: 10px 6 | md-tabs-wrapper 7 | margin-bottom: 30px 8 | // md-dummy-tab are used to evaluate 9 | // the width of the pagination which 10 | // has inkbar [in the md-tabs directive, 11 | // of course] 12 | md-dummy-tab 13 | font-size: 20px 14 | span 15 | box-sizing: content-box 16 | padding: 0 0 0 12px 17 | &:last-child 18 | span 19 | padding: 0 20 | md-pagination-wrapper 21 | width: 100% 22 | md-tab-item 23 | background-color: #f2f2f2 24 | color: #3e3e3e 25 | font-size: 20px 26 | margin-left: 10px 27 | &:first-child 28 | margin-left: 0 29 | &.md-active 30 | background-color: #158784 31 | color: #fff 32 | md-ink-bar 33 | display: none 34 | .about-panel .system-information 35 | max-width: 900px 36 | 37 | iframe.license 38 | min-height: 65vh 39 | min-width: 70vw 40 | overflow-y: visible 41 | overflow-x: hidden -------------------------------------------------------------------------------- /app/styles/_account_page.sass: -------------------------------------------------------------------------------- 1 | .account-page 2 | padding: 24px 10px 3 | md-tabs 4 | md-tab-content 5 | margin-bottom: 10px 6 | md-tabs-wrapper 7 | margin-bottom: 30px 8 | // md-dummy-tab are used to evaluate 9 | // the width of the pagination which 10 | // has inkbar [in the md-tabs directive, 11 | // of course] 12 | md-dummy-tab 13 | font-size: 20px 14 | span 15 | box-sizing: content-box 16 | padding: 0 0 0 12px 17 | &:last-child 18 | span 19 | padding: 0 20 | md-pagination-wrapper 21 | width: 100% 22 | md-tab-item 23 | background-color: #f2f2f2 24 | color: #3e3e3e 25 | font-size: 20px 26 | margin-left: 10px 27 | &:first-child 28 | margin-left: 0 29 | &.md-active 30 | background-color: #158784 31 | color: #fff 32 | md-ink-bar 33 | display: none 34 | .account-panel md-tab-content 35 | max-width: 900px -------------------------------------------------------------------------------- /app/styles/_browse_file_button.sass: -------------------------------------------------------------------------------- 1 | browse-file-button 2 | .browse-button-real 3 | display: none 4 | .current-file 5 | line-height: 20px -------------------------------------------------------------------------------- /app/styles/_contact_page.sass: -------------------------------------------------------------------------------- 1 | .contact-infos 2 | font-size: 16px 3 | color: #3e3e3e 4 | font-style: italic 5 | font-weight: 600 6 | line-height: 100px 7 | 8 | .contact-info 9 | text-align: center 10 | h2 11 | font-size: 16px 12 | line-height: 18px 13 | font-weight: 600 14 | h3 15 | font-size: 16px 16 | line-height: 18px 17 | 18 | .white 19 | background-color: #fff 20 | 21 | .contact-panel 22 | md-grid-tile 23 | &.link 24 | cursor: pointer 25 | div i 26 | color: #3e3e3e 27 | md-grid-tile div 28 | text-align: center 29 | md-grid-tile-footer figcaption h3 30 | margin: 0 31 | font-weight: 700 32 | width: 100% 33 | text-align: center 34 | text-transform: uppercase 35 | -webkit-user-select: none 36 | -moz-user-select: none 37 | -ms-user-select: none 38 | user-select: none 39 | font-family: "Open Sans" 40 | md-grid-tile md-grid-tile-footer 41 | background: #158784 42 | height: 36px 43 | md-grid-list md-grid-tile 44 | md-grid-tile 45 | md-icon 46 | padding-bottom: 32px 47 | md-grid-tile-footer 48 | background: red 49 | height: 36px 50 | md-grid-tile-footer figcaption 51 | width: 100% 52 | h3 53 | margin: 0 54 | width: 100% 55 | text-align: center -------------------------------------------------------------------------------- /app/styles/_dashboard_page.sass: -------------------------------------------------------------------------------- 1 | .dashboard 2 | md-grid-list 3 | margin: 8px 4 | .white 5 | background: #ffffff 6 | md-grid-tile 7 | transition: all 400ms ease-out 50ms 8 | h2 9 | font-size: 72px 10 | color: $palette-title 11 | font-style: italic 12 | font-weight: 600 13 | line-height: 100px 14 | md-icon 15 | padding-bottom: 32px 16 | md-grid-tile-footer 17 | background: #158784 18 | height: 36px 19 | md-grid-tile-footer figcaption 20 | width: 100% 21 | h3 22 | margin: 0 23 | font-weight: 700 24 | width: 100% 25 | text-align: center 26 | text-transform: uppercase 27 | user-select: none 28 | font-family: "Open Sans" 29 | md-grid-tile.link 30 | cursor: pointer -------------------------------------------------------------------------------- /app/styles/_dialog.sass: -------------------------------------------------------------------------------- 1 | /** 2 | * This block of style rules applies to every 3 | * dialogs, that are all spawned accross the 4 | * app by the $mdDialog service 5 | */ 6 | md-dialog, md-dialog.flyve-dialog 7 | h1, h2 8 | color: $palette-dialog-title 9 | h2 10 | line-height: 40px 11 | font-weight: 600 12 | font-style: italic 13 | font-size: 24px 14 | display: block 15 | .close-dialog-button 16 | color: #4d4d4d 17 | margin-top: 14px 18 | i 19 | font-size: 20px 20 | // This is kind of a custom replacement for md-toolbar 21 | .dialog-header 22 | @include clearfix 23 | user-select: none 24 | h2 25 | float: left 26 | padding-left: 40px 27 | line-height: 80px 28 | .close-dialog-button 29 | float: right 30 | // This is kind of a custom replacement for md-dialog-content 31 | .dialog-content 32 | padding: 0 40px 30px 40px 33 | h1, h2 34 | color: #333 35 | form 36 | @include clearfix 37 | md-input-container input.ng-invalid 38 | border-color: rgb(244,67,54) 39 | border-width: 0 0 2px 0 40 | .categories 41 | overflow-x: hidden 42 | overflow-y: auto 43 | height: 350px 44 | .flyvemdm-select-all-checkboxes 45 | padding-left: 30px 46 | md-tabs 47 | md-tab-content 48 | margin-bottom: 10px 49 | md-tabs-wrapper 50 | margin-bottom: 30px 51 | // md-dummy-tab are used to evaluate 52 | // the width of the pagination which 53 | // has inkbar [in the md-tabs directive, 54 | // of course] 55 | md-dummy-tab 56 | font-size: 20px 57 | span 58 | box-sizing: content-box 59 | padding: 0 0 0 12px 60 | &:last-child 61 | span 62 | padding: 0 63 | md-pagination-wrapper 64 | width: 100% 65 | md-tab-item 66 | background-color: #f2f2f2 67 | color: #3e3e3e 68 | font-size: 20px 69 | margin-left: 10px 70 | &:first-child 71 | margin-left: 0 72 | &.md-active 73 | background-color: #158784 74 | color: #fff 75 | md-ink-bar 76 | display: none 77 | md-progress-linear 78 | margin-bottom: 20px !important 79 | /** 80 | * This code is only used in the 81 | * 'Edit Configuration' dialog 82 | * It's the 'current files' dialog 83 | */ 84 | .add-files-panel 85 | .current-files 86 | .file 87 | @include clearfix 88 | border-bottom: 1px solid #f2f2f2 89 | height: 50px 90 | line-height: 50px 91 | button.md-icon-button 92 | float: right 93 | i 94 | color: #d94a3a 95 | line-height: 34px 96 | .add-file 97 | @include clearfix 98 | margin-bottom: 20px 99 | md-progress-linear 100 | margin-bottom: 0 !important 101 | browse-file-button, .main-action-button, md-progress-linear 102 | display: block 103 | &:first-child 104 | margin-top: 0 105 | margin-top: 10px 106 | .main-action-button 107 | float: right 108 | .form-errors 109 | float: left 110 | ul 111 | list-style-type: disc 112 | padding-left: 24px 113 | color: #d94a3a 114 | li 115 | line-height: 26px 116 | // Making the tab buttons text non selectable 117 | md-dialog .dialog-content md-tabs md-pagination-wrapper md-tab-item 118 | user-select: none 119 | -------------------------------------------------------------------------------- /app/styles/_dialog_fleet.sass: -------------------------------------------------------------------------------- 1 | /** 2 | * This file contains the css rules to display 3 | * the 'Policies' tab in the fleet dialog 4 | */ 5 | .policies-box 6 | height: 300px 7 | .policies-categories 8 | overflow-y: scroll 9 | height: 100% 10 | margin-top: 56px 11 | .policies-used 12 | top: 0px 13 | left: 50% 14 | bottom: 10px 15 | width: 50% 16 | overflow-y: scroll 17 | height: 100% 18 | .policies-filter 19 | padding: 0px 20 | top: 0px 21 | left: 0px 22 | bottom: 0px 23 | width: 50% 24 | 25 | md-tabs.md-dynamic-height 26 | md-tabs-content-wrapper 27 | overflow: hidden 28 | 29 | md-pagination-wrapper 30 | width: 100% !important -------------------------------------------------------------------------------- /app/styles/_filters.sass: -------------------------------------------------------------------------------- 1 | .current-filters 2 | &>div 3 | position: relative 4 | padding-left: 16px 5 | &:before 6 | content: '+' 7 | display: block 8 | position: absolute 9 | left: 0 10 | top: 8px 11 | .filter-fleet 12 | @include clearfix 13 | p 14 | line-height: 30px 15 | p, ul 16 | float: left 17 | ul 18 | @include clearfix 19 | margin-left: 10px 20 | li 21 | float: left 22 | position: relative 23 | margin-right: 10px 24 | background-color: rgb(224,224,224) 25 | color: rgb(66,66,66) 26 | padding: 7px 16px 27 | border-radius: 18px 28 | user-select: none 29 | cursor: default 30 | i 31 | &:hover 32 | color: #aaa 33 | cursor: pointer 34 | .filters-controls 35 | width: 466px 36 | -------------------------------------------------------------------------------- /app/styles/_input.sass: -------------------------------------------------------------------------------- 1 | // Input containers 2 | .input-container 3 | &:first-child 4 | margin-top: 0 5 | margin-top: 20px 6 | // Input heights 7 | input[type='text'], input[type='password'], button[type='submit'], button[type='button'] 8 | outline: 0 9 | &.size-1 10 | height: 44px 11 | &.size-2 12 | height: 52px 13 | // Text input controls 14 | input[type='text'], input[type='password'] 15 | width: 100% 16 | padding: 0 22px 17 | @include input-placeholder 18 | color: $palette-input-text 19 | color: darken($palette-input-text, 20%) 20 | &.rounded 21 | background-color: #fff 22 | &:focus 23 | background-color: darken(#fff, 4%) 24 | border-radius: 50px 25 | border: none 26 | // Buttons 27 | button 28 | background-color: #3e3e3e 29 | color: #fff 30 | border-radius: 3px 31 | border: none 32 | padding: 0 24px 33 | text-transform: uppercase 34 | user-select: none 35 | outline: 0 36 | position: relative 37 | overflow: hidden 38 | outline: 0 39 | &.main-action-button 40 | background-color: #0ac99e 41 | line-height: 45px 42 | &[disabled='disabled'] 43 | background-color: #637F6F 44 | &.dialog-main-button 45 | float: right 46 | &.blue 47 | background-color: #158784 48 | &.green 49 | background-color: #0ac99e 50 | &.yellow 51 | background-color: #f8aa00 52 | &.red 53 | background-color: #d94a3a 54 | .md-ripple-container 55 | border-radius: 50px 56 | background-clip: padding-box 57 | overflow: hidden 58 | -webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC) 59 | -------------------------------------------------------------------------------- /app/styles/_loggedusermenu.sass: -------------------------------------------------------------------------------- 1 | logged-user-menu 2 | @include clearfix 3 | position: absolute 4 | top: 20px 5 | width: 100% 6 | padding: 0 10px 7 | .menu-bar 8 | @include clearfix 9 | cursor: pointer 10 | height: 48px 11 | line-height: 48px 12 | background: #e6e6e6 13 | position: relative 14 | padding-left: 48px 15 | padding-right: 32px 16 | outline: none 17 | border-radius: 3px 18 | user-select: none 19 | &.opened 20 | border-radius: 3px 3px 0 3px 21 | .avatar 22 | width: 48px 23 | height: 48px 24 | position: absolute 25 | top: 0 26 | left: 0 27 | img 28 | border-radius: 3px 29 | display: block 30 | width: 44px 31 | height: 44px 32 | margin: 2px 0 0 2px 33 | .message 34 | line-height: 48px 35 | padding-left: 12px 36 | color: #4d4d4d 37 | font-weight: 600 38 | p 39 | color: #4d4d4d 40 | .caret 41 | position: absolute 42 | top: 0 43 | right: 0 44 | width: 40px 45 | text-align: center 46 | color: #3e3e3e 47 | .submenu 48 | padding-left: 40px 49 | ul 50 | background-color: #e6e6e6 51 | border-radius: 0 0 3px 3px 52 | li 53 | padding: 0 12px 54 | height: 25px 55 | line-height: 25px 56 | user-select: none 57 | cursor: pointer 58 | a 59 | text-decoration: none 60 | color: #4d4d4d 61 | i 62 | margin-right: 12px 63 | color: #3e3e3e 64 | &:hover 65 | background-color: #eee 66 | &:last-child 67 | border-radius: 0 0 3px 3px 68 | nav logged-user-menu 69 | .when-nav-small 70 | md-fab-speed-dial 71 | // &.md-is-open 72 | // md-fab-actions 73 | // display: flex 74 | md-fab-trigger 75 | button.md-fab:not([disabled]) 76 | width: 44px 77 | height: 44px 78 | text-align: center 79 | background-color: #fff 80 | &:hover, &.md-focused 81 | background-color: #fff 82 | .avatar 83 | display: inline-block 84 | width: 35px 85 | height: 35px 86 | line-height: 68px 87 | img 88 | width: 100% 89 | height: auto 90 | md-fab-actions 91 | .md-fab-action-item 92 | margin-top: 10px 93 | button.md-fab:not([disabled]) 94 | background-color: #fff 95 | color: #000 96 | -------------------------------------------------------------------------------- /app/styles/_login_page.sass: -------------------------------------------------------------------------------- 1 | .login-page 2 | // sizing 3 | width: 100% 4 | height: 100% 5 | // colors 6 | background-color: #003533 7 | // inner container which hold the 8 | // welcome text and the login form 9 | .container 10 | @include clearfix 11 | width: 410px 12 | margin: 0 auto 13 | padding-top: 120px 14 | margin-bottom: 120px 15 | .welcome-paragraph 16 | background-color: $palette-bg3 17 | width: 45% 18 | float: left 19 | border-radius: 6px 20 | min-height: 440px 21 | padding: 0 25px 22 | user-select: none 23 | cursor: default 24 | .company-logo 25 | margin-top: 40px 26 | h2 27 | margin-top: 30px 28 | font-size: 20px 29 | user-select: initial 30 | cursor: auto 31 | p 32 | margin-top: 16px 33 | font-size: 16px 34 | line-height: 22px 35 | user-select: initial 36 | cursor: auto 37 | .login-form 38 | width: 45% 39 | float: right 40 | .logo 41 | display: block 42 | margin: 0 auto 43 | user-select: none 44 | form 45 | margin-top: 50px 46 | .buttons 47 | @include clearfix 48 | .create-account-button 49 | float: left 50 | background-color: #f8aa00 51 | .login-button 52 | float: right 53 | button 54 | margin-top: 36px 55 | .create-account-catchy 56 | color: #fff 57 | font-size: 22px 58 | margin-top: 15px 59 | text-align: center 60 | a 61 | text-transform: uppercase 62 | color: inherit 63 | line-height: 40px 64 | md-card.md-flyve-mdm-theme.login-card 65 | background-color: #f2f2f2 66 | 67 | .nav-invisible 68 | background-color: #003533 69 | 70 | md-card.md-flyve-mdm-theme .md-card-image 71 | border-radius: 0px 72 | 73 | .login-page .md-headline 74 | text-align: center 75 | 76 | .foo 77 | position: fixed 78 | bottom: 0 79 | right: 0 80 | color: white -------------------------------------------------------------------------------- /app/styles/_palette.sass: -------------------------------------------------------------------------------- 1 | $palette-bg: #158784 2 | $palette-bg2: #f2f2f2 3 | $palette-bg3: #fff 4 | $palette-nav-entry-bg: #158784 5 | $palette-nav-copyright-bg: #3e3e3e 6 | $palette-nav-toggle-button-bgcolor: #5bcbf3 7 | $palette-nav-toggle-button-fgcolor: #0579ad 8 | $palette-input-text: #808080 9 | $palette-views-bg: #f2f2f2 10 | $palette-title: #4d4d4d 11 | $palette-title-span: #158784 12 | $palette-table-header-line: #158784 13 | $palette-table-body-line: #4d4d4d 14 | $palette-table-border: #f2f2f2 15 | $palette-table-insert-into-link: #0ac99e 16 | $palette-table-loading-bg: #158784 17 | $palette-dialog-title: #158784 18 | $palette-tabs-pagination-item-bg: #f2f2f2 19 | $palette-tabs-pagination-item-fg: #3e3e3e 20 | -------------------------------------------------------------------------------- /app/styles/_tables.sass: -------------------------------------------------------------------------------- 1 | .collection-infos 2 | font-size: 36px 3 | color: $palette-title 4 | font-style: italic 5 | font-weight: 600 6 | line-height: 100px 7 | span 8 | color: $palette-title-span 9 | font-weight: 400 10 | .invitationlog-name 11 | color: #158784 12 | .invitationlog-title 13 | color: $palette-title 14 | font-weight: 600 15 | .device-name 16 | color: #158784 17 | .device-title 18 | color: $palette-title 19 | font-weight: 600 20 | .table-container 21 | background-color: #fff 22 | margin-bottom: 30px 23 | border-radius: 3px 24 | .table-wrapper 25 | padding: 0 20px 26 | position: relative 27 | .fixed-header-background 28 | display: none 29 | z-index: 2 30 | .collection-infos 31 | position: absolute 32 | top: 0 33 | right: 85px 34 | font-size: 30px 35 | line-height: 62px 36 | .table-container.fixed-header & 37 | .fixed-header-background 38 | display: block 39 | position: fixed 40 | top: 0 41 | left: 0 42 | width: 100% 43 | height: 64px 44 | background-color: #fff 45 | border-bottom: 1px solid #eee 46 | &:before 47 | content: '' 48 | display: block 49 | background-color: $palette-bg2 50 | height: 100% 51 | position: absolute 52 | top: 0 53 | left: 0 54 | width: 240px + 50px 55 | @include nav-when-small 56 | width: 50px + 50px 57 | &:after 58 | content: '' 59 | display: block 60 | background-color: $palette-bg2 61 | height: 100% 62 | width: 50px 63 | position: absolute 64 | top: 0 65 | right: 0 66 | .insert-into-table-link 67 | background-color: $palette-table-insert-into-link 68 | display: block 69 | color: #fff 70 | width: 54px 71 | height: 54px 72 | line-height: 54px 73 | text-align: center 74 | border-radius: 50px 75 | font-size: 30px 76 | cursor: pointer 77 | position: fixed 78 | right: 23px 79 | top: 72px 80 | body.has-fixed-header & 81 | position: fixed 82 | bottom: 20px 83 | right: 23px 84 | top: initial 85 | body.md-dialog-is-showing & 86 | display: none 87 | &:hover 88 | background-color: lighten($palette-table-insert-into-link, 4%) 89 | .fab-action-box 90 | display: block 91 | position: fixed 92 | right: 23px 93 | top: 72px 94 | body.md-dialog-is-showing & 95 | display: none 96 | /** 97 | body.has-fixed-header & 98 | position: fixed 99 | bottom: 20px 100 | right: 23px 101 | top: initial 102 | */ 103 | /** 104 | * This is the st-table module 105 | * revamped by the Teclib' Team 106 | */ 107 | table[st-table] 108 | width: 100% 109 | thead 110 | tr 111 | height: 64px 112 | tr th 113 | font-weight: 600 114 | font-style: italic 115 | font-size: 21px 116 | color: $palette-table-header-line 117 | text-indent: 38px 118 | white-space: nowrap 119 | span 120 | display: none 121 | position: fixed 122 | top: 20px 123 | text-indent: 38px 124 | z-index: 3 125 | .table-container.fixed-header & 126 | display: block 127 | .table-container.fixed-header & 128 | &.id-column 129 | span 130 | text-indent: 12px 131 | tbody 132 | tr 133 | height: 50px 134 | tr td 135 | color: $palette-table-body-line 136 | border-width: 1px 0 1px 0 137 | border-color: $palette-table-border 138 | border-style: solid 139 | position: relative 140 | &:before 141 | content: '' 142 | width: 10px 143 | height: 2px 144 | background-color: #fff 145 | position: absolute 146 | top: -1px 147 | display: none 148 | display: block 149 | left: 0 150 | &:after 151 | content: '' 152 | width: 10px 153 | height: 2px 154 | background-color: #fff 155 | position: absolute 156 | top: -1px 157 | display: none 158 | display: block 159 | right: 0 160 | &.action-column 161 | width: 48px 162 | button.md-icon-button 163 | display: block 164 | margin: 0 auto 165 | &.edit-action 166 | color: #4d4d4d 167 | &.delete-action 168 | color: #4d4d4d 169 | th, td 170 | &.id-column 171 | text-indent: 0 172 | text-align: center 173 | td.os-column 174 | text-align: center 175 | img 176 | height: 21px 177 | width: 21px 178 | td.icon-column 179 | text-align: center 180 | img 181 | height: 48px 182 | width: 48px 183 | td:not(.id-column):not(.action-column) 184 | padding-left: 12px 185 | @media (min-width: 1110px) 186 | table[st-table] 187 | td:not(.id-column):not(.action-column) 188 | padding-left: 20px 189 | /** 190 | * Things related to the 'now loading' 191 | * spinner. 192 | */ 193 | .table-loading 194 | line-height: 26px 195 | position: absolute 196 | bottom: 15px 197 | left: 0 198 | background-color: #fff 199 | padding-left: 40px 200 | width: 100% 201 | color: $palette-table-loading-bg 202 | i 203 | margin-right: 20px 204 | -------------------------------------------------------------------------------- /app/styles/_variables.sass: -------------------------------------------------------------------------------- 1 | // variables 2 | $nav-full-width: 240px 3 | $nav-mini-width: 50px 4 | $nav-footer-height: 70px 5 | -------------------------------------------------------------------------------- /app/styles/_viewport.sass: -------------------------------------------------------------------------------- 1 | @mixin media-phones 2 | @media (max-width: 767px) 3 | @content 4 | @mixin media-tablets 5 | @media (min-width: 768px) and (max-width: 991px) 6 | @content 7 | @mixin media-desktop 8 | @media (min-width: 992px) 9 | @content 10 | @mixin media-no-desktop 11 | @media (max-width: 991px) 12 | @content 13 | /* This mixin should always been included directly in a 14 | * `nav` sass selector, it is not meant to be included 15 | * from another selector 16 | */ 17 | @mixin nav-when-small 18 | @include media-no-desktop 19 | @content 20 | body.nav-forced-small & 21 | @content 22 | html, body 23 | min-height: 100% 24 | body 25 | font-family: 'Open Sans' 26 | background-color: $palette-views-bg 27 | viewport 28 | background-color: $palette-views-bg 29 | display: block 30 | width: 100% 31 | padding-left: $nav-full-width 32 | /*padding-bottom: 16px*/ 33 | @include nav-when-small 34 | padding-left: $nav-mini-width 35 | body.nav-invisible & 36 | padding-left: 0 37 | body.hundred-percent-height-page & 38 | padding-bottom: 0 39 | .view 40 | padding: 0 50px 41 | height: 100% 42 | -------------------------------------------------------------------------------- /app/styles/app.sass: -------------------------------------------------------------------------------- 1 | @charset 'utf-8' 2 | @import 'compass' 3 | @import 'compass/reset' 4 | // applying border-box mode 5 | html 6 | box-sizing: border-box 7 | *, *:before, *:after 8 | box-sizing: inherit 9 | // general application style 10 | @import 'palette' 11 | @import 'variables' 12 | @import 'viewport' 13 | @import 'input' 14 | @import 'tables' 15 | @import 'filters' 16 | @import 'dialog' 17 | @import 'dialog_fleet' 18 | @import 'systemreport' 19 | @import 'contact_page' 20 | @import 'about_page' 21 | @import 'account_page' 22 | @import 'device_page' 23 | @import 'dashboard_page' 24 | // partials style 25 | @import 'navigation' 26 | @import 'loggedusermenu' 27 | // view-specific styles 28 | @import 'login_page' 29 | @import 'browse_file_button' 30 | -------------------------------------------------------------------------------- /app/views/about.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | About 4 |

5 |
6 |
7 |
8 |

About

9 |
10 | 11 | 12 | Overview 13 | 14 | 15 |

Flyve MDM is a mobile device management software (SaaS) that enables you to secure and manage all the mobile 16 | devices of your business via a unique web-based console (MDM).

17 |
18 |

Our solution allows you to efficiently and easily control any aspects of your Android-based mobile fleet, providing 19 | a panel of functionalities:

20 |
21 |
    22 |
  • – Provided as a SaaS platform
  • 23 |
  • – Google independent
  • 24 |
  • – Deploy and configure applications
  • 25 |
  • – Deploy files
  • 26 |
  • – Wipe a device
  • 27 |
  • – Work with devices running Android 4.4 or higher
  • 28 |
  • – Simple web application user interface
  • 29 |
30 |
31 |

Source codes will be released during fall 2016.

32 |
33 |
34 |
35 |
36 | 37 | System Information 38 | 39 | 40 | System sumary 41 | 42 |

Admin console

43 |

{{webAppVersion}}

44 |
45 | 46 |

Build

47 |

{{build}}

48 |
49 | 50 |

GLPi core

51 |

{{glpiVersion}}

52 |
53 | GLPi Plugins 54 | 55 |

{{plugin.name}}

56 |

{{plugin.version}}

57 |
58 | Components 59 | 60 |

{{component.name}}

61 |

{{component.version}}

62 |
63 | Software Environment 64 | 65 |

Debug

66 |

{{debug}}

67 |
68 | 69 |
70 |
71 |
72 | 73 | Release Notes 74 | 75 | 76 | 77 | 78 | Terms of use 79 | 80 | 83 | 84 | 85 | 86 | License 87 | 88 | 91 | 92 | 93 |
94 |
95 |
96 |
-------------------------------------------------------------------------------- /app/views/accountvalidation.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 10 |
11 | 12 |
13 |

A solution powered by

14 | Flyve Logo 15 |
16 |
-------------------------------------------------------------------------------- /app/views/admin_applications.html: -------------------------------------------------------------------------------- 1 |
2 |

{{collectionLength}} Applications

3 |
4 |
5 |
6 |

{{collectionLength}} Applications

7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 36 | 41 | 42 | 43 |
# #Alias AliasApplication Name Application NameVersionSize
{{application.id}}{{application.name}}'s icon{{application.alias}}{{application.type}} icon{{application.name}}{{application.version}}{{application.filesize}} 32 | 33 | 34 | 35 | 37 | 38 | 39 | 40 |
44 |

45 | Loading items... 46 |

47 |
48 |
49 |
50 | 51 | 52 | 53 |
54 |
-------------------------------------------------------------------------------- /app/views/admin_files.html: -------------------------------------------------------------------------------- 1 |
2 |

{{collectionLength}} Files

3 |
4 |
5 |
6 |

{{collectionLength}} Files

7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 30 | 35 | 36 | 37 |
# #Name NameSource Source
{{file.id}}{{file.name}} 23 | {{file.source}} 24 | 26 | 27 | 28 | 29 | 31 | 32 | 33 | 34 |
38 |

39 | Loading items... 40 |

41 |
42 |
43 |
44 | 45 | 46 | 47 |
48 |
-------------------------------------------------------------------------------- /app/views/admin_fleets.html: -------------------------------------------------------------------------------- 1 |
2 |

{{collectionLength}} Fleets

3 |
4 |
5 |
6 |

{{collectionLength}} Fleets

7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 26 | 31 | 32 | 33 |
# #Name Name
{{fleet.id}}{{fleet.name}} 22 | 23 | 24 | 25 | 27 | 28 | 29 | 30 |
34 |

35 | Loading items... 36 |

37 |
38 |
39 |
40 | 41 | 42 | 43 |
44 |
-------------------------------------------------------------------------------- /app/views/admin_users.html: -------------------------------------------------------------------------------- 1 |
2 |

{{collectionLength}} Users

3 |
4 |
5 |
6 |

{{collectionLength}} Users

7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 30 | 35 | 36 | 37 |
# #Name NameUsername UsernameDevice Device
{{user.id}}{{user.fullname}}{{user.username}}{{user.device_name}} 26 | 27 | 28 | 29 | 31 | 32 | 33 | 34 |
38 |

39 | Loading items... 40 |

41 |
42 |
43 |
44 | 45 | 46 | 47 |
48 |
-------------------------------------------------------------------------------- /app/views/contact.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Contact us 4 |

5 |
6 |
7 |
8 |

About

9 |
10 | 11 |

Feel free to contact us at any time, selecting your preferred channel. A Teclib' expert will answer your request 12 | and provide you with all the information and advice you need about: our Products, Partnership Programs, Training 13 | Courses and Support solutions.

14 |

"The connexion between open source Communities, Partners, Customers, and R&D Organizations, is made simple and streamlined 15 | with Teclib'"

16 |
17 |
18 |
19 | 21 | 22 |
23 | 24 |

Barcelona, Spain

25 |
26 | 27 |

Teclib' Address

28 |
29 |
30 | 31 |
32 | 33 |

+34 512 702 140

34 |
35 | 36 |

Phone

37 |
38 |
39 | 40 |
41 | 42 |

contact@teclib.com

43 |
44 | 45 |

Email

46 |
47 |
48 | 49 |
50 | 51 |

Send a ticket

52 |
53 | 54 |

Support Ticket

55 |
56 |
57 |
58 |
-------------------------------------------------------------------------------- /app/views/dashboard.html: -------------------------------------------------------------------------------- 1 |
2 |

Dashboard

3 | 5 | 6 | 7 | 8 | 9 |

{{ device.realname }}

10 |
11 |
12 | 13 |

Devices by Users

14 |
15 |
16 | 17 | 18 |

{{devices}}

19 | 20 |

Devices

21 |
22 |
23 | 24 | 25 |

{{fleets}}

26 | 27 |

Fleets

28 |
29 |
30 | 31 | 32 |

{{applications}}

33 | 34 |

Applications

35 |
36 |
37 | 38 | 39 | 40 |

{{files}}

41 | 42 |

Files

43 |
44 |
45 | 46 | 47 | 48 |

{{users}}

49 | 50 |

Users

51 |
52 |
53 | 54 | 55 | 56 | 57 |

Invitations

58 |
59 |
60 | 61 | 62 | 64 | 65 |

Devices by Operating System version

66 |
67 |
68 | 69 |
70 |
71 | 72 | 73 | 74 |
75 |
-------------------------------------------------------------------------------- /app/views/devices.html: -------------------------------------------------------------------------------- 1 |
2 |

{{collectionLength}} Devices

3 |
4 |
5 |
6 |
7 |

In Fleets :

8 |
    9 |
  • 10 | {{fleet.name}} 11 | 12 |
  • 13 |
14 |
15 |
16 |
17 | 18 | 19 | 20 | 21 | {{fleet.name}} 22 | 23 | 24 | 25 |
26 |
27 | 28 |
29 |
30 |
31 |
32 |

{{collectionLength}} Devices

33 |
34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 63 | 71 | 72 | 73 |
# #Name NameDevice DeviceSerial SerialFleet FleetLast contact Last contact
{{device.id}}{{device.realname}}{{device.manufacturer_model}}{{device.serial}}{{device.fleet.name}}{{device._contacted || 'Never contacted'}} 56 | 57 | 58 | Open device panel 59 | 60 | 61 | 62 | 64 | 65 | 66 | Delete device 67 | 68 | 69 | 70 |
74 |

75 | Loading items... 76 |

77 |
78 |
79 |
80 | 81 | 82 | 83 |
84 |
-------------------------------------------------------------------------------- /app/views/dialog_changepassword.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |

Change Password

4 | 5 | 6 | 7 | 8 |
9 |
10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Cancel 23 | Save 24 | 25 |
26 |
27 |
-------------------------------------------------------------------------------- /app/views/dialog_editapplication.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |

Edit Application

4 | 5 | 6 | 7 | 8 |
9 |
10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | Cancel 19 | Save 20 | 21 |
22 |
23 |
-------------------------------------------------------------------------------- /app/views/dialog_editfile.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |

Edit File

4 | 5 | 6 | 7 | 8 |
9 |
10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | Cancel 19 | Save 20 | 21 |
22 |
23 |
-------------------------------------------------------------------------------- /app/views/dialog_editpolicy.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |

{{ policy.name }}

4 | 5 | 6 | 7 | 8 |
9 | 10 |
11 |
12 |

{{ policy.comment }}

13 |
14 | 15 | 16 | {{ policy.symbol }} 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | {{value}} 26 | 27 | 28 | 29 |
30 | 31 | Cancel 32 | Accept 33 | 34 |
' -------------------------------------------------------------------------------- /app/views/dialog_edituser.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |

Edit user

4 | 5 | 6 | 7 | 8 |
9 |
10 |
11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 35 | 36 |
37 |
38 |
    39 |
  • 40 | Enter a valid email 41 |
  • 42 |
  • 43 | Confirmation password doesn't match provided password 44 |
  • 45 |
46 |
47 |
48 | 49 | Cancel 50 | Save 51 | 52 |
53 |
54 |
-------------------------------------------------------------------------------- /app/views/dialog_enrollnewdevice.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |

Enroll new device

4 | 5 | 6 | 7 | 8 |
9 |
10 |
11 | 12 |

Please insert an active email address.

13 |

An email will be sent with a QR code.

14 | 15 | 16 | 17 | 18 |
19 | 20 | Cancel 21 | Save 22 | 23 |
24 |
25 |
-------------------------------------------------------------------------------- /app/views/dialog_newapplication.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |

New Application

4 | 5 | 6 | 7 | 8 |
9 |
10 |
11 | 12 |

You are adding a new application available for your fleets.

13 |
14 |
15 | 16 | 17 | 18 | 19 | 21 |
22 | 23 |
24 |
    25 |
  • 26 | {{errors.message}} 27 |
  • 28 |
29 |
30 |
31 | 32 | Cancel 33 | Save 34 | 35 |
36 |
37 |
-------------------------------------------------------------------------------- /app/views/dialog_newfile.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |

New File

4 | 5 | 6 | 7 | 8 |
9 |
10 |
11 | 12 |

You are adding a new file available for your fleets.

13 |
14 |
15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 |
23 | 24 | Cancel 25 | Save 26 | 27 |
28 |
29 |
-------------------------------------------------------------------------------- /app/views/dialog_register.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |

New user

4 | 5 | 6 | 7 | 8 |
9 |
10 |
11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 31 | 32 | 33 | 34 | 36 | 37 |
38 |
39 |
    40 |
  • 41 | Enter a valid email 42 |
  • 43 |
  • 44 | Confirmation password doesn't match provided password 45 |
  • 46 |
47 |
48 |
49 | 50 | Cancel 51 | Register 52 | 53 |
54 |
55 |
-------------------------------------------------------------------------------- /app/views/help.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Help 4 |

5 | 6 |
7 |

Documentation in progress. Contact us for more information 8 | about the documentation.

9 |
10 |
11 |
-------------------------------------------------------------------------------- /app/views/invitationlogs.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Invitation 4 | {{invitation_email}} 5 |

6 |
7 |
8 |
9 |

{{invitation_email}} Invitation

10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
# #Date DateEvent Event
{{log.id}}{{log.date_creation}}{{log.event}}
27 |

28 | Loading logs... 29 |

30 |
31 |
32 |
-------------------------------------------------------------------------------- /app/views/invitations.html: -------------------------------------------------------------------------------- 1 |
2 |

{{collectionLength}} Pending Invitation

3 |
4 |
5 |
6 |

{{collectionLength}} Pending Invitation

7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 30 | 38 | 46 | 47 | 48 |
# #Email Email
{{invitation.id}}{{invitation.user_email}} 23 | 24 | 25 | Get logs 26 | 27 | 28 | 29 | 31 | 32 | 33 | Resend Email 34 | 35 | 36 | 37 | 39 | 40 | 41 | Delete Email 42 | 43 | 44 | 45 |
49 |

50 | Loading invitations... 51 |

52 |
53 |
54 |
55 | 56 | 57 | 58 |
59 |
-------------------------------------------------------------------------------- /app/views/loggedusermenu.html: -------------------------------------------------------------------------------- 1 |
2 | 13 | 19 |
20 |
21 | 22 | 23 | 24 | 25 |
26 | User Image 27 |
28 |
29 |
30 |
31 | 32 | 33 | 34 | 35 | My account 36 | 37 | 38 | 39 | 40 | Disconnect 41 | 42 | 43 |
44 |
-------------------------------------------------------------------------------- /app/views/login.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 8 |
9 | 33 |
34 |
35 |
36 |
37 |

A solution powered by

38 | Flyve Logo 39 |
-------------------------------------------------------------------------------- /app/views/navigation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 69 | 70 | -------------------------------------------------------------------------------- /app/views/toast_notification.html: -------------------------------------------------------------------------------- 1 | 2 | Custom toast! 3 | 4 | More info 5 | 6 | 7 | Close 8 | 9 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flyve-mdm-web-ui", 3 | "version": "2.1.0", 4 | "description": "Mobile device management software.", 5 | "homepage": "https://flyve-mdm.com/", 6 | "main": [ 7 | "app/scripts/app.js", 8 | "app/styles/app.scss" 9 | ], 10 | "appPath": "app", 11 | "moduleName": "FlyveMDM", 12 | "moduleType": [ 13 | "globals" 14 | ], 15 | "keywords": [ 16 | "flyve", 17 | "uhuru", 18 | "mdm", 19 | "mobile", 20 | "device", 21 | "management" 22 | ], 23 | "authors": [ 24 | { 25 | "name": "Nelson Zamith", 26 | "email": "nzamith@teclib.com" 27 | }, 28 | { 29 | "name": "Alexander Salas Bastidas", 30 | "email": "asalas@teclib.com" 31 | } 32 | ], 33 | "license": "AGPL-3.0", 34 | "ignore": [ 35 | "**/.*", 36 | "node_modules", 37 | "bower_components", 38 | "jspm_packages", 39 | "tmp", 40 | "temp", 41 | "test", 42 | "tests", 43 | "dist", 44 | ".tmp", 45 | ".gtm", 46 | ".vscode", 47 | ".sass-cache", 48 | "app/config.js" 49 | ], 50 | "repository": { 51 | "type": "git", 52 | "url": "git+https://github.com/flyve-mdm/flyve-mdm-web-ui.git" 53 | }, 54 | "private": true, 55 | "dependencies": { 56 | "angular": "^1.6.2", 57 | "angular-animate": "^1.6.2", 58 | "angular-cookies": "^1.6.2", 59 | "angular-resource": "^1.6.2", 60 | "angular-route": "^1.6.2", 61 | "angular-sanitize": "^1.6.2", 62 | "angular-material": "^1.1.3", 63 | "angular-ui-router": "^0.4.2", 64 | "angular-smart-table": "^2.1.8", 65 | "components-font-awesome": "^4.7.0", 66 | "ng-file-upload": "^12.2.13", 67 | "open-sans-fontface": "^1.4.2", 68 | "moment": "^2.17.1", 69 | "angular-material-accordion": "^1.0.5", 70 | "leaflet": "^1.0.3", 71 | "angular-chart.js": "^1.1.1", 72 | "dexie": "^1.5.1" 73 | }, 74 | "devDependencies": { 75 | "angular-mocks": "^1.6.2" 76 | }, 77 | "resolutions": { 78 | "angular": "1.6.0" 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /build-dist.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | npm install 4 | bower install --allow-root 5 | grunt --force build -------------------------------------------------------------------------------- /ci/screenshots.js: -------------------------------------------------------------------------------- 1 | const puppeteer = require('puppeteer'); 2 | 3 | (async() => { 4 | const browser = await puppeteer.launch(); 5 | const page = await browser.newPage(); 6 | 7 | // Ann array of viewport sizes for different devices. 8 | const viewports = [{ 9 | width: 1600, 10 | height: 992 11 | }, 12 | { 13 | width: 1280, 14 | height: 802 15 | }, 16 | { 17 | width: 768, 18 | height: 1024 19 | }, 20 | { 21 | width: 320, 22 | height: 480 23 | } 24 | ] 25 | 26 | await page.goto('http://flyve.org/'); 27 | 28 | for (let i = 0; i < viewports.length; i++) { 29 | let vw = viewports[i]; 30 | 31 | // The height doesn't matter since we are screenshotting the full page. 32 | await page.setViewport({ 33 | width: vw.width, 34 | height: vw.height 35 | }); 36 | 37 | await page.screenshot({ 38 | path: `screenshots/screen-${vw.width}x${vw.height}.png`, 39 | fullPage: true 40 | }); 41 | } 42 | 43 | browser.close(); 44 | })(); -------------------------------------------------------------------------------- /ci/script.sh: -------------------------------------------------------------------------------- 1 | if [[ -n $GH_TOKEN ]]; then 2 | git config --global user.email $GH_EMAIL 3 | git config --global user.name $GH_NAME 4 | git remote remove origin 5 | git remote add origin https://$GH_USER:$GH_TOKEN@github.com/$TRAVIS_REPO_SLUG.git 6 | git checkout $TRAVIS_BRANCH -f 7 | fi 8 | 9 | if [[ "$TRAVIS_BRANCH" == "develop" && "$TRAVIS_PULL_REQUEST" == "false" ]]; then 10 | npm i puppeteer 11 | mkdir "screenshots" 12 | node ci/screenshots.js 13 | git add . 14 | # NOTICE: this commit is not sent 15 | git commit -m "temp" 16 | git fetch origin gh-pages 17 | git checkout gh-pages 18 | git checkout $TRAVIS_BRANCH screenshots/ 19 | git add screenshots 20 | git commit -m "docs(screenshots): add screenshots of the project" 21 | 22 | git push origin gh-pages 23 | fi -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=759670 3 | // for the documentation about the jsconfig.json format 4 | "compilerOptions": { 5 | "target": "es6", 6 | "module": "commonjs", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "exclude": [ 10 | "node_modules", 11 | "bower_components", 12 | "jspm_packages", 13 | "tmp", 14 | "temp", 15 | "test", 16 | "tests", 17 | "dist", 18 | ".tmp", 19 | ".sass-cache", 20 | ".gtm", 21 | ".vscode" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@teclib/flyve-mdm-web-ui", 3 | "version": "2.1.0", 4 | "description": "Mobile device management software.", 5 | "homepage": "https://flyve-mdm.com/", 6 | "devDependencies": { 7 | "grunt": "^1.0.1", 8 | "grunt-angular-templates": "^1.1.0", 9 | "grunt-autoprefixer": "^3.0.4", 10 | "grunt-concurrent": "^2.3.1", 11 | "grunt-contrib-clean": "^1.0.0", 12 | "grunt-contrib-compass": "^1.1.1", 13 | "grunt-contrib-concat": "^1.0.1", 14 | "grunt-contrib-connect": "^1.0.2", 15 | "grunt-contrib-copy": "^1.0.0", 16 | "grunt-contrib-cssmin": "^2.2.1", 17 | "grunt-contrib-htmlmin": "^2.1.0", 18 | "grunt-contrib-imagemin": "^2.0.1", 19 | "grunt-contrib-jshint": "^1.1.0", 20 | "grunt-contrib-uglify": "^3.1.0", 21 | "grunt-contrib-watch": "^1.0.0", 22 | "grunt-filerev": "^2.3.1", 23 | "grunt-gh-pages": "^2.0.0", 24 | "grunt-git": "^1.0.3", 25 | "grunt-htmlhint-plus": "^0.5.1", 26 | "grunt-karma": "^2.0.0", 27 | "grunt-newer": "^1.2.0", 28 | "grunt-ng-annotate": "^3.0.0", 29 | "grunt-ng-constant": "^2.0.1", 30 | "grunt-sass-lint": "^0.2.2", 31 | "grunt-svgmin": "^5.0.0", 32 | "grunt-usemin": "^3.1.1", 33 | "grunt-wiredep": "^3.0.1", 34 | "jasmine-core": "^3.0.0", 35 | "jit-grunt": "^0.10.0", 36 | "jshint-stylish": "^2.2.1", 37 | "karma": "^2.0.0", 38 | "karma-coverage": "^1.1.1", 39 | "karma-jasmine": "^1.1.0", 40 | "karma-phantomjs-launcher": "^1.0.2", 41 | "markdownlint": "^0.9.0", 42 | "newman": "^3.4.2", 43 | "phantomjs-prebuilt": "^2.1.14", 44 | "puppeteer": "^1.0.0", 45 | "sass-lint": "^1.10.2", 46 | "serve-static": "^1.11.2", 47 | "time-grunt": "^1.4.0" 48 | }, 49 | "engines": { 50 | "node": ">=0.10.0" 51 | }, 52 | "scripts": { 53 | "test": "grunt test", 54 | "start": "npm i & bower i & grunt build & grunt serve", 55 | "watch": "grunt serve", 56 | "release": "standard-version --sign --message 'chore(release): bump to %s and new CHANGELOG'", 57 | "debug": "node --nolazy --debug-brk=5858 node_modules/grunt/bin/grunt serve" 58 | }, 59 | "keywords": [ 60 | "flyve", 61 | "uhuru", 62 | "mdm", 63 | "mobile", 64 | "device", 65 | "management" 66 | ], 67 | "authors": [ 68 | { 69 | "name": "Nelson Zamith", 70 | "email": "nzamith@teclib.com" 71 | }, 72 | { 73 | "name": "Alexander Salas Bastidas", 74 | "email": "asalas@teclib.com" 75 | } 76 | ], 77 | "license": "AGPL-3.0", 78 | "ignore": [ 79 | "**/.*", 80 | "node_modules", 81 | "bower_components", 82 | "jspm_packages", 83 | "tmp", 84 | "temp", 85 | "test", 86 | "tests", 87 | "dist", 88 | ".tmp", 89 | ".gtm", 90 | ".vscode", 91 | ".sass-cache", 92 | "app/config.js" 93 | ], 94 | "repository": { 95 | "type": "git", 96 | "url": "git+https://github.com/flyve-mdm/flyve-mdm-web-ui.git" 97 | }, 98 | "bugs": { 99 | "url": "https://github.com/flyve-mdm/flyve-mdm-web-ui/issues" 100 | }, 101 | "private": true, 102 | "dependencies": {} 103 | } 104 | -------------------------------------------------------------------------------- /test/.htmlhintrc: -------------------------------------------------------------------------------- 1 | { 2 | "tagname-lowercase": true, 3 | "attr-lowercase": true, 4 | "attr-value-double-quotes": true, 5 | "attr-value-not-empty": true, 6 | "attr-no-duplication": true, 7 | "doctype-first": false, 8 | "tag-pair": true, 9 | "tag-self-close": false, 10 | "spec-char-escape": true, 11 | "id-unique": true, 12 | "src-not-empty": true, 13 | "head-script-disabled": false, 14 | "img-alt-require": true, 15 | "doctype-html5": true, 16 | "id-class-value": "dash", 17 | "style-disabled": false, 18 | "space-tab-mixed-disabled": true, 19 | "id-class-ad-disabled": true, 20 | "href-abs-or-rel": true, 21 | "attr-unsafe-chars": true 22 | } -------------------------------------------------------------------------------- /test/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "bitwise": true, 3 | "browser": true, 4 | "curly": true, 5 | "eqeqeq": true, 6 | "esnext": true, 7 | "jasmine": true, 8 | "latedef": true, 9 | "noarg": true, 10 | "node": true, 11 | "strict": true, 12 | "undef": true, 13 | "unused": true, 14 | "loopfunc": true, 15 | "expr": true, 16 | "globals": { 17 | "angular": false, 18 | "inject": false, 19 | "_": false, 20 | "L": false, 21 | "moment": false, 22 | "Dexie": false 23 | } 24 | } -------------------------------------------------------------------------------- /test/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // http://karma-runner.github.io/0.12/config/configuration-file.html 3 | // Generated on 2015-11-13 using 4 | // generator-karma 1.0.0 5 | module.exports = function (config) { 6 | 'use strict'; 7 | config.set({ 8 | // enable / disable watching file and executing tests whenever any file changes 9 | autoWatch: true, 10 | // base path, that will be used to resolve files and exclude 11 | basePath: '../', 12 | // testing framework to use (jasmine/mocha/qunit/...) 13 | // as well as any additional frameworks (requirejs/chai/sinon/...) 14 | frameworks: [ 15 | "jasmine" 16 | ], 17 | // list of files / patterns to load in the browser 18 | files: [ 19 | // bower:js 20 | 'bower_components/angular/angular.js', 21 | 'bower_components/angular-animate/angular-animate.js', 22 | 'bower_components/angular-cookies/angular-cookies.js', 23 | 'bower_components/angular-resource/angular-resource.js', 24 | 'bower_components/angular-route/angular-route.js', 25 | 'bower_components/angular-sanitize/angular-sanitize.js', 26 | 'bower_components/angular-aria/angular-aria.js', 27 | 'bower_components/angular-messages/angular-messages.js', 28 | 'bower_components/angular-material/angular-material.js', 29 | 'bower_components/angular-ui-router/release/angular-ui-router.js', 30 | 'bower_components/angular-smart-table/dist/smart-table.js', 31 | 'bower_components/ng-file-upload/ng-file-upload.js', 32 | 'bower_components/moment/moment.js', 33 | 'bower_components/angular-material-accordion/dist/angular-material-accordion.js', 34 | 'bower_components/leaflet/dist/leaflet-src.js', 35 | 'bower_components/chart.js/dist/Chart.js', 36 | 'bower_components/angular-chart.js/dist/angular-chart.js', 37 | 'bower_components/dexie/dist/dexie.min.js', 38 | 'bower_components/angular-mocks/angular-mocks.js', 39 | // endbower 40 | "app/scripts/app.js", 41 | "app/config.js", 42 | "app/scripts/**/*.js", 43 | //"test/mock/**/*.js", 44 | "test/spec/**/*.js" 45 | ], 46 | // list of files / patterns to exclude 47 | exclude: [ 48 | ], 49 | // coverage reporter generates the coverage 50 | reporters: ['progress', 'coverage'], 51 | preprocessors: { 52 | // source files, that you wanna generate coverage for 53 | // do not include tests or libraries 54 | // (these files will be instrumented by Istanbul) 55 | 'app/**/*.js': ['coverage'] 56 | }, 57 | coverageReporter: { 58 | reporters: [ 59 | { type: 'text-summary' } 60 | ], 61 | }, 62 | // web server port 63 | port: 8000, 64 | // Start these browsers, currently available: 65 | // - Chrome 66 | // - ChromeCanary 67 | // - Firefox 68 | // - Opera 69 | // - Safari (only Mac) 70 | // - PhantomJS 71 | // - IE (only Windows) 72 | browsers: [ 73 | "PhantomJS" 74 | ], 75 | // Which plugins to enable 76 | plugins: [ 77 | "karma-coverage", 78 | "karma-phantomjs-launcher", 79 | "karma-jasmine" 80 | ], 81 | // Continuous Integration mode 82 | // if true, it capture browsers, run tests and exit 83 | singleRun: false, 84 | colors: true, 85 | // level of logging 86 | // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG 87 | logLevel: config.LOG_INFO, 88 | // Uncomment the following lines if you are using grunt's server to run the tests 89 | // proxies: { 90 | // '/': 'http://localhost:9000/' 91 | // }, 92 | // URL root prevent conflicts with the site root 93 | // urlRoot: '_karma_' 94 | }); 95 | }; 96 | -------------------------------------------------------------------------------- /test/mock/services/auth.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/test/mock/services/auth.js -------------------------------------------------------------------------------- /test/postman-collections/2048.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flyve-mdm/legacy-web-dashboard/2d7c92cdf0815fbde206818d718be51b92ee5838/test/postman-collections/2048.apk -------------------------------------------------------------------------------- /test/postman-collections/testFile.txt: -------------------------------------------------------------------------------- 1 | Hello123 -------------------------------------------------------------------------------- /test/spec/services/auth.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | describe('Service: AuthProvider', function () { 3 | var $httpBackend, $rootScope, AuthProvider, url, PluginObjectNames, GlpiObjectNames; 4 | var mockCredentials = { login: 'user1@teclib.com', password: "********" }; 5 | var mockUserId = { id: true }; 6 | var mockSessionToken = { session_token: "39b37kafd4klb1o7bi0tjd79e2" }; 7 | var mockResponseSessionToken = {data: mockSessionToken}; 8 | beforeEach(module('FlyveMDM')); 9 | beforeEach(inject(function ($injector) { 10 | $httpBackend = $injector.get('$httpBackend'); 11 | url = $injector.get('GLPI_API_URL'); 12 | GlpiObjectNames = $injector.get('GlpiObjectNames'); 13 | PluginObjectNames = $injector.get('PluginObjectNames'); 14 | $httpBackend.when('GET', GlpiObjectNames.InitSession).respond(200, mockResponseSessionToken); 15 | $httpBackend.when('GET', GlpiObjectNames.KillSession).respond(200); 16 | $httpBackend.when('POST', PluginObjectNames.User).respond(200, mockUserId); 17 | $rootScope = $injector.get('$rootScope'); 18 | AuthProvider = $injector.get('AuthProvider'); 19 | })); 20 | afterEach(function () { 21 | $httpBackend.verifyNoOutstandingExpectation(); 22 | $httpBackend.verifyNoOutstandingRequest(); 23 | }); 24 | it('should fetch and temporaly session token and register an user', function () { 25 | console.log('ACCOUNT_1: Create an account on the platform with login user1@teclib.com'); 26 | $httpBackend.expectGET(url + GlpiObjectNames.InitSession).respond(200, mockSessionToken); 27 | $httpBackend.expectGET('views/dashboard.html').respond(200); 28 | $httpBackend.expectPOST(url + PluginObjectNames.User).respond(200, mockSessionToken); 29 | $httpBackend.expectGET(url + GlpiObjectNames.KillSession).respond(200); 30 | AuthProvider.attemptRegister(mockCredentials.email, mockCredentials.password); 31 | $httpBackend.flush(); 32 | }); 33 | it('should fetch authentication token', function () { 34 | console.log('ACCOUNT_4: Login on the platform'); 35 | $httpBackend.expectGET(url + GlpiObjectNames.InitSession).respond(200, mockSessionToken); 36 | $httpBackend.expectGET('views/dashboard.html').respond(200); 37 | AuthProvider.attemptLogin(mockCredentials.email, mockCredentials.password).then(function () { 38 | expect($rootScope.sessionToken).toBe(mockSessionToken.session_token); 39 | }); 40 | $httpBackend.flush(); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /test/spec/services/users.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: UsersAdminFac', function () { 4 | 5 | // load the service's module 6 | beforeEach(module('FlyveMDM')); 7 | 8 | // instantiate service 9 | var UsersAdminFac; 10 | 11 | beforeEach(inject(function($injector) { 12 | UsersAdminFac = $injector.get('UsersAdminFac'); 13 | })); 14 | 15 | it('should be injected', function () { 16 | expect(!!UsersAdminFac).toBeTruthy(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /tools/generate-conf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | CONFFILE=config.js 4 | APPDIR=/var/www/html 5 | 6 | if [ -z "$GLPI_API_URL" ]; then 7 | echo "GLPI API Url Env Not Set. Exit" 8 | exit 1 9 | fi 10 | if [ -z "$GLPI_API_TOKEN" ]; then 11 | echo "GLPI API TOKEN Url Env Not Set. Exit" 12 | exit 1 13 | fi 14 | echo "Generating Flyve MDM Front Configuration File config.js" 15 | 16 | 17 | #j8lth8dqvgky79f0dyf4jc59p353u34eao9rwlis3 18 | rm ${APPDIR}/$CONFFILE 19 | echo "angular.module('FlyveMDM')" >> $APPDIR/$CONFFILE 20 | echo ".constant('GLPI_API_URL', '${GLPI_API_URL}')" >> $APPDIR/$CONFFILE 21 | echo ".constant('USER_TOKEN', '${GLPI_API_TOKEN}')" >> $APPDIR/$CONFFILE 22 | echo ".constant('DEBUG', false)" >> $APPDIR/$CONFFILE 23 | echo ".constant('BUILD_ID', 0);" >> $APPDIR/$CONFFILE 24 | -------------------------------------------------------------------------------- /tools/run-nginx.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | /tools/generate-conf.sh 4 | 5 | echo "Starting Nginx" 6 | 7 | nginx 8 | --------------------------------------------------------------------------------