├── .gitignore ├── README assets └── screenshot.jpg ├── public ├── scripts │ ├── app.js │ ├── config.js │ └── aad.js ├── services │ ├── drivesFactory.js │ ├── commonFactory.js │ ├── authHelper.js │ ├── groupsFactory.js │ └── usersFactory.js ├── controllers │ ├── navbarController.js │ └── mainController.js ├── views │ └── main.html ├── index.html └── custom.css ├── package.json ├── angular-snippets-rest-sample.yml ├── server.js ├── LICENSE ├── README.md └── CONTRIBUTING.md /.gitignore: -------------------------------------------------------------------------------- 1 | logs/* 2 | !.gitkeep 3 | .vscode/ 4 | node_modules/ 5 | bower_components/ 6 | tmp 7 | .DS_Store 8 | .idea 9 | .vscode -------------------------------------------------------------------------------- /README assets/screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoftgraph/angular-snippets-rest-sample/HEAD/README assets/screenshot.jpg -------------------------------------------------------------------------------- /public/scripts/app.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the source repository root for complete license information. 4 | */ 5 | 6 | (function () { 7 | angular 8 | .module('app', [ 9 | 'ui.bootstrap', 10 | 'angular-loading-bar', 11 | 'ladda' 12 | ]); 13 | })(); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Microsoft-Graph-Snippets-Angular", 3 | "version": "1.2.0", 4 | "description": "Microsoft Graph Snippets Sample for AngularJS.", 5 | "license": "MIT", 6 | "main": "server.js", 7 | "dependencies": { 8 | "express": "^4.14.0", 9 | "ladda-angular": "^1.0.1", 10 | "morgan": "^1.7.0", 11 | "path": "^0.11.14" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /public/scripts/config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the source repository root for complete license information. 4 | */ 5 | 6 | var appId = 'ENTER_YOUR_APP_ID'; 7 | var redirectUrl = "http://localhost:8080"; 8 | var scopes = "user.readwrite mail.read mail.send calendars.readwrite contacts.read files.readwrite"; 9 | var adminScopes = "user.read.all directory.readwrite.all directory.accessasuser.all"; -------------------------------------------------------------------------------- /angular-snippets-rest-sample.yml: -------------------------------------------------------------------------------- 1 | ### YamlMime:Sample 2 | sample: 3 | - name: Microsoft Graph Snippets Sample for AngularJS (REST) 4 | path: '' 5 | description: Provides a repository of code snippets that use Microsoft Graph to perform common tasks such as sending email, managing groups, and other activities from within an AngularJS app. This sample makes REST calls directly to the Microsoft Graph API, and uses the Azure AD v2.0 endpoint to authenticate personal accounts and work or school accounts. 6 | readme: '' 7 | generateZip: FALSE 8 | isLive: TRUE 9 | technologies: 10 | - Azure AD 11 | - Microsoft Graph 12 | azureDeploy: '' 13 | author: martellaj 14 | platforms: [] 15 | languages: 16 | - JavaScript 17 | - Angular.js 18 | extensions: 19 | products: 20 | - Office 365 21 | scenarios: [] 22 | -------------------------------------------------------------------------------- /public/services/drivesFactory.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the source repository root for complete license information. 4 | */ 5 | 6 | (function() { 7 | angular 8 | .module('app') 9 | .factory('drivesFactory', drivesFactory); 10 | 11 | drivesFactory.$inject = ['$log', '$http', '$q', 'commonFactory']; 12 | function drivesFactory($log, $http, $q, common) { 13 | var drives = {}; 14 | 15 | // Methods 16 | drives.getDrives = getDrives; 17 | 18 | ///////////////////////////////////////// 19 | // End of exposed properties and methods. 20 | 21 | var baseUrl = common.baseUrl; 22 | 23 | /** 24 | * Gets the list of drives that exist in the tenant. 25 | */ 26 | function getDrives() { 27 | var req = { 28 | method: 'GET', 29 | url: baseUrl + '/myOrganization/drives' 30 | }; 31 | 32 | return $http(req); 33 | }; 34 | 35 | return drives; 36 | }; 37 | })(); -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the source repository root for complete license information. 4 | */ 5 | 6 | var express = require('express'); 7 | var app = express(); 8 | var morgan = require('morgan'); 9 | var path = require('path'); 10 | 11 | // Initialize variables. 12 | var port = process.env.PORT || 8080; 13 | 14 | // Configure morgan module to log all requests. 15 | app.use(morgan('dev')); 16 | 17 | // Set the public folder to serve public assets. 18 | app.use(express.static(__dirname + '/public')); 19 | app.use(express.static(__dirname)); 20 | app.use("/bower_components", express.static(path.join(__dirname, 'bower_components'))); 21 | 22 | // Set up our one route to the index.html file. 23 | app.get('*', function (req, res) { 24 | res.sendFile(path.join(__dirname + '/public/index.html')); 25 | }); 26 | 27 | // Start the app. 28 | app.listen(port); 29 | console.log('Listening on port ' + port + '...'); -------------------------------------------------------------------------------- /public/scripts/aad.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the source repository root for complete license information. 4 | */ 5 | 6 | // This sample uses an open source OAuth 2.0 library that is compatible with the Azure AD v2.0 endpoint. 7 | // Microsoft does not provide fixes or direct support for this library. 8 | // Refer to the library’s repository to file issues or for other support. 9 | // For more information about auth libraries see: https://azure.microsoft.com/documentation/articles/active-directory-v2-libraries/ 10 | // Library repo: http://adodson.com/hello.js/ 11 | 12 | hello.init({ 13 | 14 | aad: { 15 | name: 'Azure Active Directory', 16 | oauth: { 17 | version: 2, 18 | auth: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize' 19 | }, 20 | scope_delim: ' ', 21 | 22 | 23 | // Don't even try submitting via form. 24 | // This means no POST operations in <=IE9 25 | form: false 26 | } 27 | }); 28 | 29 | hello.on('auth.login', function (auth) { 30 | 31 | // save the auth info into localStorage 32 | localStorage.auth = angular.toJson(auth.authResponse); 33 | }); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Microsoft Graph Snippets Sample for AngularJS 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | MIT License 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining 8 | a copy of this software and associated documentation files (the 9 | "Software"), to deal in the Software without restriction, including 10 | without limitation the rights to use, copy, modify, merge, publish, 11 | distribute, sublicense, and/or sell copies of the Software, and to 12 | permit persons to whom the Software is furnished to do so, subject to 13 | the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 22 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /public/services/commonFactory.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the source repository root for complete license information. 4 | */ 5 | 6 | (function () { 7 | angular 8 | .module('app') 9 | .factory('commonFactory', commonFactory); 10 | 11 | function commonFactory($http, $q) { 12 | var common = {}; 13 | 14 | // Object constructors 15 | common.Snippet = Snippet; 16 | 17 | // Properties 18 | common.baseUrl = 'https://graph.microsoft.com/v1.0'; 19 | 20 | // Methods 21 | common.guid = guid; 22 | 23 | ///////////////////////////////////////// 24 | // End of exposed properties and methods. 25 | 26 | /** 27 | * Constructor for the snippet object. 28 | */ 29 | function Snippet(title, description, documentationUrl, apiUrl, requireAdmin, run) { 30 | this.title = title; 31 | this.description = description; 32 | this.documentationUrl = documentationUrl; 33 | this.apiUrl = apiUrl; 34 | this.requireAdmin = requireAdmin; 35 | this.run = run; 36 | }; 37 | 38 | /** 39 | * Random GUID generator. Copied from Stack Overflow user "broofa". 40 | * http://stackoverflow.com/users/109538/broofa 41 | * http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript 42 | */ 43 | function guid() { 44 | function s4() { 45 | return Math.floor((1 + Math.random()) * 0x10000) 46 | .toString(16) 47 | .substring(1); 48 | } 49 | return s4() + s4() + '-' + s4() + '-' + s4() + '-' + 50 | s4() + '-' + s4() + s4() + s4(); 51 | }; 52 | 53 | return common; 54 | } 55 | })(); -------------------------------------------------------------------------------- /public/controllers/navbarController.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the source repository root for complete license information. 4 | */ 5 | 6 | (function () { 7 | angular 8 | .module('app') 9 | .controller('NavbarController', NavbarController); 10 | 11 | /** 12 | * The NavbarController code. 13 | */ 14 | NavbarController.$inject = ['$log', '$scope', 'authHelper']; 15 | function NavbarController($log, $scope, authHelper) { 16 | var vm = this; 17 | 18 | // Properties 19 | vm.isCollapsed; 20 | vm.isopen = false; 21 | vm.isConnected; 22 | 23 | // Methods 24 | vm.connect = connect; 25 | vm.disconnect = disconnect; 26 | 27 | ///////////////////////////////////////// 28 | // End of exposed properties and methods. 29 | 30 | /** 31 | * This function does any initialization work the 32 | * controller needs. 33 | */ 34 | (function activate() { 35 | vm.isCollapsed = true; 36 | if (hello('aad').getAuthResponse()) vm.isConnected = true; 37 | })(); 38 | 39 | /** 40 | * Expose the login method to the view. 41 | */ 42 | function connect() { 43 | $log.debug('Connecting to Microsoft Graph.'); 44 | authHelper.login(); 45 | }; 46 | 47 | /** 48 | * Expose the logout method to the view. 49 | */ 50 | function disconnect() { 51 | $log.debug('Disconnecting from Microsoft Graph.'); 52 | vm.isConnected = false; 53 | authHelper.logout(); 54 | }; 55 | 56 | /** 57 | * Event listener for dropdown menu in navbar. 58 | */ 59 | $scope.toggleDropdown = function ($event) { 60 | $event.preventDefault(); 61 | $event.stopPropagation(); 62 | $scope.status.isopen = !$scope.status.isopen; 63 | }; 64 | }; 65 | })(); 66 | -------------------------------------------------------------------------------- /public/services/authHelper.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the source repository root for complete license information. 4 | */ 5 | 6 | // This sample uses an open source OAuth 2.0 library that is compatible with the Azure AD v2.0 endpoint. 7 | // Microsoft does not provide fixes or direct support for this library. 8 | // Refer to the library’s repository to file issues or for other support. 9 | // For more information about auth libraries see: https://azure.microsoft.com/documentation/articles/active-directory-v2-libraries/ 10 | // Library repo: https://github.com/MrSwitch/hello.js 11 | 12 | "use strict"; 13 | 14 | (function () { 15 | angular 16 | .module('app') 17 | .service('authHelper', ['$http', function ($http) { 18 | 19 | // Initialize the auth request. 20 | hello.init( { 21 | aad: appId // from public/scripts/config.js 22 | }, { 23 | response_type: 'token', 24 | redirect_uri: redirectUrl, 25 | scope: scopes + ' ' + adminScopes 26 | }); 27 | 28 | // Set global headers for the request. 29 | function setAuthHeader(accessToken) { 30 | 31 | // Add the required Authorization header with bearer token. 32 | $http.defaults.headers.common.Authorization = 'Bearer ' + accessToken; 33 | 34 | // This header has been added to identify our sample in the Microsoft Graph service. If extracting this code for your project please remove. 35 | $http.defaults.headers.common.SampleID = 'angular-snippets-rest-sample'; 36 | } 37 | 38 | return { 39 | 40 | // Sign in and sign out the user. 41 | login: function login() { 42 | hello('aad').login({ 43 | display: 'page', 44 | state: 'abcd' 45 | }); 46 | }, 47 | logout: function logout() { 48 | hello('aad').logout(); 49 | delete localStorage.auth; 50 | }, 51 | 52 | // Get a valid access token. 53 | getToken: function getToken() { 54 | 55 | // If the stored token is valid for another 5 minutes, we'll use it. 56 | let auth = angular.fromJson(localStorage.auth); 57 | let expiration = new Date(); 58 | if (auth.access_token && expiration.setTime((auth.expires - 300) * 1000) > new Date()) { 59 | setAuthHeader(auth.access_token); 60 | } else { 61 | 62 | // This sample just redirects the user to sign back in when the token expires. 63 | this.logout(); 64 | this.login(); 65 | } 66 | } 67 | } 68 | }]); 69 | })(); -------------------------------------------------------------------------------- /public/views/main.html: -------------------------------------------------------------------------------- 1 | 3 | 4 |
5 |
6 |
7 |

Use the button in the navigation bar to connect to Microsoft Graph and explore the Microsoft Graph API using your own data.

8 |
9 |
10 |
11 | 23 |
24 |

{{ main.activeSnippet.title }}

25 | 27 |
28 |
29 |

Description

30 |
31 |
32 |

{{ main.activeSnippet.description }}

33 |

This operation requires a user with an admin account.

34 |
35 |

Documentation link: 36 | {{ main.activeSnippet.documentationUrl }} 37 |

38 |
39 |
40 |
41 |
42 |

API URL

43 |
44 |
45 |

{{ main.activeSnippet.apiUrl }}

46 |
47 |
48 |
49 |
50 |

Setup error

51 |
52 |
53 |

This snippet required setup and it failed.

54 |

{{ main.activeSnippet.setupError }}

55 |
56 |
57 |
58 |
59 |

Request

60 |
61 |
62 |
{{ main.activeSnippet.request | json }}
63 |
64 |
65 |
66 |
67 |

Response

68 |
69 |
70 |
{{ main.activeSnippet.response | json }}
71 |
72 |
73 |
74 |
75 |
-------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Microsoft Graph Snippets Sample 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 65 |
66 |
67 |
68 |
69 |
70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /public/custom.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Move down content because we have a fixed navbar that is 50px tall. 3 | */ 4 | body { 5 | padding-top: 50px; 6 | } 7 | 8 | /* 9 | * Top navigation. 10 | * Hide default border to remove 1px line. 11 | */ 12 | .navbar-fixed-top { 13 | border: 0; 14 | } 15 | 16 | .navbar-default .navbar-brand { 17 | color: #fff; 18 | background: #252525; 19 | } 20 | 21 | /* Navbar links. */ 22 | .navbar-default .navbar-nav > li > a { 23 | color: white; 24 | } 25 | .navbar-default .navbar-nav > li > a:hover, 26 | .navbar-default .navbar-nav > li > a:focus { 27 | color: lightgray; 28 | } 29 | .navbar-default .navbar-nav > .active > a, 30 | .navbar-default .navbar-nav > .active > a:hover, 31 | .navbar-default .navbar-nav > .active > a:focus { 32 | color: white; 33 | background-color: #eb3c00 !important; 34 | } 35 | 36 | .navbar-signin { 37 | background-color: #505050; 38 | color: white; 39 | } 40 | 41 | .navbar-inverse .navbar-nav>.open>a, .navbar-inverse .navbar-nav>.open>a:focus, .navbar-inverse .navbar-nav>.open>a:hover { 42 | background-color: #373737; 43 | color: white; 44 | } 45 | 46 | .detailKey { 47 | font-weight: bold; 48 | display: inline-block; 49 | } 50 | 51 | .detailValue { 52 | display: inline-block; 53 | } 54 | 55 | /* 56 | * Base structure 57 | */ 58 | 59 | /* Move down content because we have a fixed navbar that is 50px tall */ 60 | body { 61 | padding-top: 50px; 62 | } 63 | 64 | /* 65 | * Global add-ons 66 | */ 67 | 68 | .sub-header { 69 | padding-bottom: 10px; 70 | border-bottom: 1px solid #eee; 71 | } 72 | 73 | /* 74 | * Top navigation 75 | * Hide default border to remove 1px line. 76 | */ 77 | .navbar-fixed-top { 78 | border: 0; 79 | } 80 | 81 | .admin-description { 82 | font-size: .9em; 83 | font-weight: bold; 84 | color: #2e6da4; 85 | } 86 | 87 | /* 88 | * Sidebar 89 | */ 90 | 91 | /* Hide for mobile, show later */ 92 | .sidebar { 93 | display: none; 94 | } 95 | @media (min-width: 768px) { 96 | .sidebar { 97 | position: fixed; 98 | top: 51px; 99 | bottom: 0; 100 | left: 0; 101 | z-index: 1000; 102 | display: block; 103 | padding: 20px; 104 | overflow-x: hidden; 105 | overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */ 106 | background-color: #f5f5f5; 107 | border-right: 1px solid #eee; 108 | } 109 | } 110 | 111 | /* Sidebar navigation */ 112 | .nav-sidebar { 113 | margin-right: -21px; /* 20px padding + 1px border */ 114 | margin-bottom: 20px; 115 | margin-left: -20px; 116 | } 117 | .nav-sidebar > li > a { 118 | padding-right: 20px; 119 | padding-left: 20px; 120 | } 121 | .nav-sidebar > .active > a, 122 | .nav-sidebar > .active > a:hover, 123 | .nav-sidebar > .active > a:focus { 124 | color: #fff; 125 | background-color: #428bca; 126 | } 127 | 128 | .nav > li { 129 | margin-left: 10px; 130 | } 131 | 132 | .groupTitle { 133 | font-weight: bold; 134 | } 135 | 136 | .admin-sidebar { 137 | color: black; 138 | font-size: .8em; 139 | } 140 | 141 | .active .admin-sidebar { 142 | color: white; 143 | } 144 | 145 | /* 146 | * Main content 147 | */ 148 | 149 | .main { 150 | padding: 20px; 151 | } 152 | @media (min-width: 768px) { 153 | .main { 154 | padding-right: 40px; 155 | padding-left: 40px; 156 | } 157 | } 158 | .main .page-header { 159 | margin-top: 0; 160 | } 161 | 162 | .detailKey { 163 | font-weight: bold; 164 | display: inline-block; 165 | } 166 | 167 | .detailValue { 168 | display: inline-block; 169 | } 170 | 171 | .avatar { 172 | margin-bottom: 10px; 173 | } 174 | 175 | .navbar-inverse .navbar-text { 176 | color: white; 177 | } 178 | 179 | /* 180 | * Panel 181 | */ 182 | .panel-heading { 183 | border-top: 1px solid transparent; 184 | } 185 | 186 | .panel-title { 187 | font-weight: bold; 188 | } 189 | 190 | .panel { 191 | margin-top: 15px; 192 | } -------------------------------------------------------------------------------- /public/services/groupsFactory.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the source repository root for complete license information. 4 | */ 5 | 6 | (function () { 7 | angular 8 | .module('app') 9 | .factory('groupsFactory', groupsFactory); 10 | 11 | groupsFactory.$inject = ['$log', '$http', '$q', 'commonFactory']; 12 | function groupsFactory($log, $http, $q, common) { 13 | var groups = {}; 14 | 15 | // Methods 16 | groups.getGroups = getGroups; 17 | groups.createGroup = createGroup; 18 | groups.getGroup = getGroup; 19 | groups.updateGroup = updateGroup; 20 | groups.deleteGroup = deleteGroup; 21 | groups.getMembers = getMembers; 22 | groups.getOwners = getOwners; 23 | 24 | ///////////////////////////////////////// 25 | // End of exposed properties and methods. 26 | 27 | var baseUrl = common.baseUrl; 28 | 29 | /** 30 | * Gets the list of groups that exist in the tenant. 31 | */ 32 | function getGroups() { 33 | var req = { 34 | method: 'GET', 35 | url: baseUrl + '/myOrganization/groups' 36 | }; 37 | 38 | return $http(req); 39 | }; 40 | 41 | /** 42 | * Creates a new security group in the tenant. 43 | */ 44 | function createGroup() { 45 | var uuid = common.guid(); 46 | 47 | var newGroup = { 48 | displayName: uuid, 49 | mailEnabled: false, // Set to true for mail-enabled groups. 50 | mailNickname: uuid, 51 | securityEnabled: true // Set to true for security-enabled groups. Do not set this property if creating an Office 365 group. 52 | }; 53 | 54 | var req = { 55 | method: 'POST', 56 | url: baseUrl + '/myOrganization/groups', 57 | data: newGroup 58 | }; 59 | 60 | return $http(req); 61 | }; 62 | 63 | /** 64 | * Gets information about a specific group. 65 | */ 66 | function getGroup() { 67 | return getGroupsSetup(''); 68 | }; 69 | 70 | /** 71 | * Updates the description of a specific group. 72 | */ 73 | function updateGroup() { 74 | var deferred = $q.defer(); 75 | 76 | // You can only update groups created via the Microsoft Graph API, so to make sure we have one, 77 | // we'll create it here and then update its description. 78 | createGroup() 79 | .then(function (response) { 80 | var groupId = response.data.id; 81 | $log.debug('Group "' + groupId + '" was created. Updating the group\'s description...'); 82 | 83 | var groupUpdates = { 84 | description: 'This is a group.' 85 | }; 86 | 87 | var req = { 88 | method: 'PATCH', 89 | url: baseUrl + '/myOrganization/groups/' + groupId, 90 | data: groupUpdates 91 | }; 92 | 93 | deferred.resolve($http(req)); 94 | }, function (error) { 95 | deferred.reject({ 96 | setupError: 'Unable to create a new group to update.', 97 | response: error 98 | }); 99 | }); 100 | 101 | return deferred.promise; 102 | }; 103 | 104 | /** 105 | * Deletes a specific group. 106 | */ 107 | function deleteGroup() { 108 | var deferred = $q.defer(); 109 | 110 | // You can only delete groups created via the Microsoft Graph API, so to make sure we have one, 111 | // we'll create it here and then delete its description. 112 | createGroup() 113 | .then(function (response) { 114 | var groupId = response.data.id; 115 | $log.debug('Group "' + groupId + '" was created. Deleting the group...'); 116 | 117 | var req = { 118 | method: 'DELETE', 119 | url: baseUrl + '/myOrganization/groups/' + groupId 120 | }; 121 | 122 | deferred.resolve($http(req)); 123 | }, function (error) { 124 | deferred.reject({ 125 | setupError: 'Unable to create a new group to delete.', 126 | response: error 127 | }); 128 | }); 129 | 130 | return deferred.promise; 131 | }; 132 | 133 | /** 134 | * Gets members of a specific group. 135 | */ 136 | function getMembers() { 137 | return getGroupsSetup('members'); 138 | }; 139 | 140 | /** 141 | * Gets owners of a specific group. 142 | */ 143 | function getOwners() { 144 | return getGroupsSetup('owners'); 145 | }; 146 | 147 | /** 148 | * Several snippets require a group ID to work. This method does the setup work 149 | * required to get the ID of a group in the tenant and then makes a request to the 150 | * desired navigation property. 151 | */ 152 | function getGroupsSetup(endpoint) { 153 | var deferred = $q.defer(); 154 | 155 | getGroups() 156 | .then(function (response) { 157 | // Check to make sure at least 1 group is returned. 158 | if (response.data.value.length >= 1) { 159 | var groupId = response.data.value[0].id; 160 | 161 | var req = { 162 | method: 'GET', 163 | url: baseUrl + '/myOrganization/groups/' + groupId + '/' + endpoint 164 | }; 165 | 166 | deferred.resolve($http(req)); 167 | } 168 | else { 169 | deferred.reject({ 170 | setupError: 'Tenant doesn\'t have any groups.', 171 | response: response 172 | }); 173 | } 174 | }, function (error) { 175 | deferred.reject({ 176 | setupError: 'Unable to get list of tenant\'s groups.', 177 | response: error 178 | }); 179 | }); 180 | 181 | return deferred.promise; 182 | }; 183 | 184 | return groups; 185 | }; 186 | })(); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [ARCHIVED] Microsoft Graph Snippets Sample for AngularJS (REST) 2 | 3 | ## IMPORTANT 4 | 5 | **This project is being archived and replaced with the [Build Angular single-page apps with Microsoft Graph](https://github.com/microsoftgraph/msgraph-training-angularspa). As part of the archival process, we're closing all open issues and pull requests.** 6 | 7 | **You can continue to use this sample "as-is", but it won't be maintained moving forward. We apologize for any inconvenience.** 8 | 9 | ## Table of contents 10 | 11 | * [Prerequisites](#prerequisites) 12 | * [Register the application](#register-the-application) 13 | * [Build and run the sample](#build-and-run-the-sample) 14 | * [Code of note](#code-of-note) 15 | * [Questions and comments](#questions-and-comments) 16 | * [Contributing](#contributing) 17 | * [Additional resources](#additional-resources) 18 | 19 | This sample shows how to use the Microsoft Graph API to send email, manage groups, and perform other activities. Microsoft Graph exposes multiple APIs from Microsoft cloud services through a single REST API endpoint. This repository shows you how to access multiple resources, including Microsoft Azure Active Directory (AD) and the Office 365 APIs, by making HTTP requests to Microsoft Graph in an AngularJS app. The sample uses the Azure AD v2.0 endpoint, which supports Microsoft Accounts and work or school Office 365 accounts. 20 | 21 | ![Microsoft Graph Snippets sample screenshot](./README%20assets/screenshot.jpg) 22 | 23 | **Note:** This sample does not always clean up the entities that it creates, so you might want to use a test account to run the sample. 24 | 25 | ## Prerequisites 26 | 27 | * [Node.js](https://nodejs.org/). Node is required to run the sample on a development server and to install dependencies. 28 | 29 | * [Bower](https://bower.io). Bower is required to install front-end dependencies. 30 | 31 | * Either a [Microsoft account](https://www.outlook.com) or [work or school account](http://dev.office.com/devprogram) (admin) 32 | 33 | ## Register the application 34 | 35 | 1. Sign into the [App Registration Portal](https://apps.dev.microsoft.com/) using either your personal or work or school account. 36 | 37 | 2. Choose **Add an app**. 38 | 39 | 3. Enter a name for the app, and choose **Create application**. 40 | 41 | The registration page displays, listing the properties of your app. 42 | 43 | 4. Copy the application ID. This is the unique identifier for your app that you'll use to configure the sample. 44 | 45 | 5. Under **Platforms**, choose **Add Platform** > **Web**. 46 | 47 | 6. Make sure the **Allow Implicit Flow** check box is selected, and enter *http://localhost:8080* as the Redirect URI. 48 | 49 | 7. Choose **Save**. 50 | 51 | ## Build and run the sample 52 | 53 | 1. Download or clone the Microsoft Graph Snippets Sample for AngularJS. 54 | 55 | 2. Using your favorite IDE, open **config.js** in *public/scripts*. 56 | 57 | 3. Replace the **appId** placeholder value with the application ID of your registered Azure application. 58 | 59 | 4. In a command prompt, run the following commands in the sample's root directory. This installs project dependencies, including the [HelloJS](http://adodson.com/hello.js/) client-side authentication library. 60 | 61 | ``` 62 | npm install 63 | bower install hello 64 | ``` 65 | 66 | 5. Run `npm start` to start the development server. 67 | 68 | 6. Navigate to `http://localhost:8080` in your web browser. 69 | 70 | 7. Sign in with your personal or admin work or school account and grant the requested permissions. 71 | 72 | 8. Choose a snippet from the left-hand navigation pane, and then choose the **Run snippet** button. The request and response display in the center pane. 73 | 74 | >**Note** Operations that are not supported for Microsoft Accounts are marked with an asterisk. 75 | 76 | ### How the sample affects your data 77 | 78 | This sample runs REST commands that create, read, update, or delete data. The sample creates fake entities so that your actual tenant data is unaffected. The sample will leave behind the fake entities that it creates. 79 | 80 | ## Code of note 81 | 82 | public/scripts/aad.js - Contains HelloJS configuration properties for the Azure AD provider. 83 | public/scripts/config.js - Contains the constants used for authentication parameters. 84 | public/services/authHelper.js - Initializes the HelloJS provider, calls the login and logout methods exposed by HelloJS, and gets the token from local storage and adds it to the HTTP request. 85 | public/services/Factory.js - Constructs the HTTP requests for Microsoft Graph. 86 | public/controllers/mainController.js - Gets snippets from the factories, and parses the responses from Microsoft Graph. 87 | 88 | >**Note** The simple authentication and token handling in this project is for sample purposes only. In a production app, you should construct a more robust way of handling authentication, including validation and secure token handling. 89 | 90 | ## Questions and comments 91 | 92 | We'd love to get your feedback about the Microsoft Graph Snippets Sample for AngularJS. You can send your questions and suggestions to us in the [Issues](https://github.com/microsoftgraph/angular-snippets-rest-sample/issues) section of this repository. 93 | 94 | For general questions about Microsoft Graph development, connect with us on [Stack Overflow](http://stackoverflow.com/questions/tagged/microsoftgraph). Tag your questions with [MicrosoftGraph]. 95 | 96 | ## Contributing 97 | 98 | If you'd like to contribute to this sample, see [CONTRIBUTING.MD](/CONTRIBUTING.md). 99 | 100 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 101 | 102 | ## Additional resources 103 | 104 | * [Microsoft Graph](http://graph.microsoft.io) 105 | * [Other Microsoft Graph samples for AngularJS](https://github.com/microsoftgraph?utf8=%E2%9C%93&query=angular) 106 | 107 | ## Copyright 108 | Copyright (c) 2016 Microsoft. All rights reserved. 109 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contribute to this documentation 2 | 3 | Thank you for your interest in our documentation! 4 | 5 | * [Ways to contribute](#ways-to-contribute) 6 | * [Contribute using GitHub](#contribute-using-github) 7 | * [Contribute using Git](#contribute-using-git) 8 | * [How to use Markdown to format your topic](#how-to-use-markdown-to-format-your-topic) 9 | * [FAQ](#faq) 10 | * [More resources](#more-resources) 11 | 12 | ## Ways to contribute 13 | 14 | Here are some ways you can contribute to this documentation: 15 | 16 | * To make small changes to an article, [Contribute using GitHub](#contribute-using-github). 17 | * To make large changes, or changes that involve code, [Contribute using Git](#contribute-using-git). 18 | * Report documentation bugs via GitHub Issues 19 | * Request new documentation at the [Office Developer Platform UserVoice](http://officespdev.uservoice.com) site. 20 | 21 | ## Contribute using GitHub 22 | 23 | Use GitHub to contribute to this documentation without having to clone the repo to your desktop. This is the easiest way to create a pull request in this repository. Use this method to make a minor change that doesn't involve code changes. 24 | 25 | **Note** Using this method allows you to contribute to one article at a time. 26 | 27 | ### To Contribute using GitHub 28 | 29 | 1. Find the article you want to contribute to on GitHub. 30 | 31 | If the article is in MSDN, choose the **suggest and submit changes** link in the **Contribute to this content** section and you'll be taken to the same article on GitHub. 32 | 2. Once you are on the article in GitHub, sign in to GitHub (get a free account [Join GitHub](https://github.com/join). 33 | 3. Choose the **pencil icon** (edit the file in your fork of this project) and make your changes in the **<>Edit file** window. 34 | 4. Scroll to the bottom and enter a description. 35 | 5. Choose **Propose file change**>**Create pull request**. 36 | 37 | You now have successfully submitted a pull request. Pull requests are typically reviewed within 10 business days. 38 | 39 | 40 | ## Contribute using Git 41 | 42 | Use Git to contribute substantive changes, such as: 43 | 44 | * Contributing code. 45 | * Contributing changes that affect meaning. 46 | * Contributing large changes to text. 47 | * Adding new topics. 48 | 49 | ### To Contribute using Git 50 | 51 | 1. If you don't have a GitHub account, set one up at [GitHub](https://github.com/join). 52 | 2. After you have an account, install Git on your computer. Follow the steps in [Setting up Git Tutorial](https://help.github.com/articles/set-up-git/). 53 | 3. To submit a pull request using Git, follow the steps in [Use GitHub, Git, and this repository](#use-github-git-and-this-repository). 54 | 4. You will be asked to sign the Contributor's License Agreement if you are: 55 | 56 | * A member of the Microsoft Open Technologies group. 57 | * A contributors who doesn't work for Microsoft. 58 | 59 | As a community member, you must sign the Contribution License Agreement (CLA) before you can contribute large submissions to a project. You only need to complete and submit the documentation once. Carefully review the document. You may be required to have your employer sign the document. 60 | 61 | Signing the CLA does not grant you rights to commit to the main repository, but it does mean that the Office Developer and Office Developer Content Publishing teams will be able to review and approve your contributions. You will be credited for your submissions. 62 | 63 | Pull requests are typically reviewed within 10 business days. 64 | 65 | ## Use GitHub, Git, and this repository 66 | 67 | **Note:** Most of the information in this section can be found in [GitHub Help] articles. If you're familiar with Git and GitHub, skip to the **Contribute and edit content** section for the specifics of the code/content flow of this repository. 68 | 69 | ### To set up your fork of the repository 70 | 71 | 1. Set up a GitHub account so you can contribute to this project. If you haven't done this, go to [GitHub](https://github.com/join) and do it now. 72 | 2. Install Git on your computer. Follow the steps in the [Setting up Git Tutorial] [Set Up Git]. 73 | 3. Create your own fork of this repository. To do this, at the top of the page, choose the **Fork** button. 74 | 4. Copy your fork to your computer. To do this, open Git Bash. At the command prompt enter: 75 | 76 | git clone https://github.com//.git 77 | 78 | Next, create a reference to the root repository by entering these commands: 79 | 80 | cd 81 | git remote add upstream https://github.com/microsoftgraph/.git 82 | git fetch upstream 83 | 84 | Congratulations! You've now set up your repository. You won't need to repeat these steps again. 85 | 86 | ### Contribute and edit content 87 | 88 | To make the contribution process as seamless as possible, follow these steps. 89 | 90 | #### To contribute and edit content 91 | 92 | 1. Create a new branch. 93 | 2. Add new content or edit existing content. 94 | 3. Submit a pull request to the main repository. 95 | 4. Delete the branch. 96 | 97 | **Important** Limit each branch to a single concept/article to streamline the work flow and reduce the chance of merge conflicts. Content appropriate for a new branch includes: 98 | 99 | * A new article. 100 | * Spelling and grammar edits. 101 | * Applying a single formatting change across a large set of articles (for example, applying a new copyright footer). 102 | 103 | #### To create a new branch 104 | 105 | 1. Open Git Bash. 106 | 2. At the Git Bash command prompt, type `git pull upstream master:`. This creates a new branch locally that is copied from the latest MicrosoftGraph master branch. 107 | 3. At the Git Bash command prompt, type `git push origin `. This alerts GitHub to the new branch. You should now see the new branch in your fork of the repository on GitHub. 108 | 4. At the Git Bash command prompt, type `git checkout ` to switch to your new branch. 109 | 110 | #### Add new content or edit existing content 111 | 112 | You navigate to the repository on your computer by using File Explorer. The repository files are in `C:\Users\\`. 113 | 114 | To edit files, open them in an editor of your choice and modify them. To create a new file, use the editor of your choice and save the new file in the appropriate location in your local copy of the repository. While working, save your work frequently. 115 | 116 | The files in `C:\Users\\` are a working copy of the new branch that you created in your local repository. Changing anything in this folder doesn't affect the local repository until you commit a change. To commit a change to the local repository, type the following commands in GitBash: 117 | 118 | git add . 119 | git commit -v -a -m "" 120 | 121 | The `add` command adds your changes to a staging area in preparation for committing them to the repository. The period after the `add` command specifies that you want to stage all of the files that you added or modified, checking subfolders recursively. (If you don't want to commit all of the changes, you can add specific files. You can also undo a commit. For help, type `git add -help` or `git status`.) 122 | 123 | The `commit` command applies the staged changes to the repository. The switch `-m` means you are providing the commit comment in the command line. The -v and -a switches can be omitted. The -v switch is for verbose output from the command, and -a does what you already did with the add command. 124 | 125 | You can commit multiple times while you are doing your work, or you can commit once when you're done. 126 | 127 | #### Submit a pull request to the main repository 128 | 129 | When you're finished with your work and are ready to have it merged into the main repository, follow these steps. 130 | 131 | #### To submit a pull request to the main repository 132 | 133 | 1. In the Git Bash command prompt, type `git push origin `. In your local repository, `origin` refers to your GitHub repository that you cloned the local repository from. This command pushes the current state of your new branch, including all commits made in the previous steps, to your GitHub fork. 134 | 2. On the GitHub site, navigate in your fork to the new branch. 135 | 3. Choose the **Pull Request** button at the top of the page. 136 | 4. Verify the Base branch is `microsoftgraph/@master` and the Head branch is `/@`. 137 | 5. Choose the **Update Commit Range** button. 138 | 6. Add a title to your pull request, and describe all the changes you're making. 139 | 7. Submit the pull request. 140 | 141 | One of the site administrators will process your pull request. Your pull request will surface on the microsoftgraph/ site under Issues. When the pull request is accepted, the issue will be resolved. 142 | 143 | #### Create a new branch after merge 144 | 145 | After a branch is successfully merged (that is, your pull request is accepted), don't continue working in that local branch. This can lead to merge conflicts if you submit another pull request. To do another update, create a new local branch from the successfully merged upstream branch, and then delete your initial local branch. 146 | 147 | For example, if your local branch X was successfully merged into the OfficeDev/microsoft-graph-docs master branch and you want to make additional updates to the content that was merged. Create a new local branch, X2, from the OfficeDev/microsoft-graph-docs master branch. To do this, open GitBash and execute the following commands: 148 | 149 | cd microsoft-graph-docs 150 | git pull upstream master:X2 151 | git push origin X2 152 | 153 | You now have local copies (in a new local branch) of the work that you submitted in branch X. The X2 branch also contains all the work other writers have merged, so if your work depends on others' work (for example, shared images), it is available in the new branch. You can verify that your previous work (and others' work) is in the branch by checking out the new branch... 154 | 155 | git checkout X2 156 | 157 | ...and verifying the content. (The `checkout` command updates the files in `C:\Users\\microsoft-graph-docs` to the current state of the X2 branch.) Once you check out the new branch, you can make updates to the content and commit them as usual. However, to avoid working in the merged branch (X) by mistake, it's best to delete it (see the following **Delete a branch** section). 158 | 159 | #### Delete a branch 160 | 161 | Once your changes are successfully merged into the main repository, delete the branch you used because you no longer need it. Any additional work should be done in a new branch. 162 | 163 | #### To delete a branch 164 | 165 | 1. In the Git Bash command prompt, type `git checkout master`. This ensures that you aren't in the branch to be deleted (which isn't allowed). 166 | 2. Next, at the command prompt, type `git branch -d `. This deletes the branch on your computer only if it has been successfully merged to the upstream repository. (You can override this behavior with the `–D` flag, but first be sure you want to do this.) 167 | 3. Finally, type `git push origin :` at the command prompt (a space before the colon and no space after it). This will delete the branch on your github fork. 168 | 169 | Congratulations, you have successfully contributed to the project! 170 | 171 | ## How to use Markdown to format your topic 172 | 173 | ### Article template 174 | 175 | The [markdown template](/articles/0-markdown-template-for-new-articles.md) contains the basic Markdown for a topic that includes a table of contents, sections with subheadings, links to other Office developer topics, links to other sites, bold text, italic text, numbered and bulleted lists, code snippets, and images. 176 | 177 | 178 | ### Standard Markdown 179 | 180 | All of the articles in this repository use Markdown. A complete introduction (and listing of all the syntax) can be found at [Markdown Home] []. 181 | 182 | ## FAQ 183 | 184 | ### How do I get a GitHub account? 185 | 186 | Fill out the form at [Join GitHub](https://github.com/join) to open a free GitHub account. 187 | 188 | ### Where do I get a Contributor's License Agreement? 189 | 190 | You will automatically be sent a notice that you need to sign the Contributor's License Agreement (CLA) if your pull request requires one. 191 | 192 | As a community member, **you must sign the Contribution License Agreement (CLA) before you can contribute large submissions to this project**. You only need complete and submit the documentation once. Carefully review the document. You may be required to have your employer sign the document. 193 | 194 | ### What happens with my contributions? 195 | 196 | When you submit your changes, via a pull request, our team will be notified and will review your pull request. You will receive notifications about your pull request from GitHub; you may also be notified by someone from our team if we need more information. We reserve the right to edit your submission for legal, style, clarity, or other issues. 197 | 198 | ### Can I become an approver for this repository's GitHub pull requests? 199 | 200 | Currently, we are not allowing external contributors to approve pull requests in this repository. 201 | 202 | ### How soon will I get a response about my change request or issue? 203 | 204 | We typically review pull requests and respond to issues within 10 business days. 205 | 206 | ## More resources 207 | 208 | * To learn more about Markdown, go to the Git creator's site [Daring Fireball]. 209 | * To learn more about using Git and GitHub, first check out the [GitHub Help section] [GitHub Help]. 210 | 211 | [GitHub Home]: http://github.com 212 | [GitHub Help]: http://help.github.com/ 213 | [Set Up Git]: http://help.github.com/win-set-up-git/ 214 | [Markdown Home]: http://daringfireball.net/projects/markdown/ 215 | [Daring Fireball]: http://daringfireball.net/ 216 | -------------------------------------------------------------------------------- /public/services/usersFactory.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the source repository root for complete license information. 4 | */ 5 | 6 | (function () { 7 | angular 8 | .module('app') 9 | .factory('usersFactory', usersFactory); 10 | 11 | usersFactory.$inject = ['$log', '$http', '$q', 'commonFactory']; 12 | function usersFactory($log, $http, $q, common) { 13 | var users = {}; 14 | 15 | // Methods 16 | users.getMe = getMe; 17 | users.getUsers = getUsers; 18 | users.createUser = createUser; 19 | users.getDrive = getDrive; 20 | users.getEvents = getEvents; 21 | users.createEvent = createEvent; 22 | users.updateEvent = updateEvent; 23 | users.deleteEvent = deleteEvent; 24 | users.getMessages = getMessages; 25 | users.sendMessage = sendMessage; 26 | users.getUserPhoto = getUserPhoto; 27 | users.getManager = getManager; 28 | users.getDirectReports = getDirectReports; 29 | users.getMemberOf = getMemberOf; 30 | users.getFiles = getFiles; 31 | users.createFile = createFile; 32 | users.downloadFile = downloadFile; 33 | users.updateFile = updateFile; 34 | users.renameFile = renameFile; 35 | users.deleteFile = deleteFile; 36 | users.createFolder = createFolder; 37 | 38 | ///////////////////////////////////////// 39 | // End of exposed properties and methods. 40 | 41 | var baseUrl = common.baseUrl; 42 | 43 | /** 44 | * Get information about the signed-in user. 45 | */ 46 | function getMe(useSelect) { 47 | var reqUrl = baseUrl + '/me'; 48 | 49 | // Append $select OData query string. 50 | if (useSelect) { 51 | reqUrl += '?$select=AboutMe,Responsibilities' 52 | } 53 | 54 | var req = { 55 | method: 'GET', 56 | url: reqUrl 57 | } 58 | 59 | return $q(function (resolve, reject) { 60 | $http(req) 61 | .then(function (res) { 62 | resolve(res); 63 | }, function (err) { 64 | resolve(err); 65 | }); 66 | }); 67 | }; 68 | 69 | /** 70 | * Get existing users collection from the tenant. 71 | */ 72 | function getUsers(useFilter) { 73 | var reqUrl = baseUrl + '/myOrganization/users'; 74 | 75 | // Append $filter OData query string. 76 | if (useFilter) { 77 | // This filter will return users in your tenant based in the US. 78 | reqUrl += '?$filter=country eq \'United States\''; 79 | } 80 | 81 | var req = { 82 | method: 'GET', 83 | url: reqUrl 84 | }; 85 | 86 | return $http(req); 87 | }; 88 | 89 | /** 90 | * Add a user to the tenant's users collection. 91 | */ 92 | function createUser() { 93 | var deferred = $q.defer(); 94 | 95 | // First get the tenant name for the new user. 96 | getOrganization() 97 | .then(function(response) { 98 | 99 | let tenant = response.data.value[0]; 100 | if (!angular.isUndefined(tenant)) { 101 | let domainName = tenant.verifiedDomains[0].name; 102 | 103 | // Then define the new user. The data in newUser are the minimum required properties. 104 | var randomUserName = common.guid(); 105 | var newUser = { 106 | accountEnabled: true, 107 | displayName: 'User ' + randomUserName, 108 | mailNickname: randomUserName, 109 | passwordProfile: { 110 | password: 'p@ssw0rd!' 111 | }, 112 | userPrincipalName: randomUserName + '@' + domainName 113 | }; 114 | 115 | var req = { 116 | method: 'POST', 117 | url: baseUrl + '/myOrganization/users', 118 | data: newUser 119 | }; 120 | 121 | deferred.resolve($http(req)); 122 | } 123 | else { 124 | deferred.reject({ 125 | setupError: 'Unable to create a user.', 126 | response: {statusText:'No tenant found for this account.'} 127 | }); 128 | } 129 | }, function (error) { 130 | deferred.reject({ 131 | setupError: 'Unable to create a user.', 132 | response: error 133 | }); 134 | }); 135 | 136 | return deferred.promise; 137 | }; 138 | 139 | /** 140 | * Get the signed-in user's drive. 141 | */ 142 | function getDrive() { 143 | var req = { 144 | method: 'GET', 145 | url: baseUrl + '/me/drive' 146 | }; 147 | 148 | return $http(req); 149 | }; 150 | 151 | /** 152 | * Get the signed-in user's calendar events. 153 | */ 154 | function getEvents() { 155 | var req = { 156 | method: 'GET', 157 | url: baseUrl + '/me/events' 158 | }; 159 | 160 | return $http(req); 161 | }; 162 | 163 | /** 164 | * Adds an event to the signed-in user's calendar. 165 | */ 166 | function createEvent() { 167 | // The new event will be 30 minutes and take place tomorrow at the current time. 168 | var startTime = new Date(); 169 | startTime.setDate(startTime.getDate() + 1); 170 | var endTime = new Date(startTime.getTime() + 30 * 60000); 171 | 172 | var newEvent = { 173 | Subject: 'Weekly Sync', 174 | Location: { 175 | DisplayName: 'Water cooler' 176 | }, 177 | Attendees: [{ 178 | Type: 'Required', 179 | EmailAddress: { 180 | Address: 'mara@fabrikam.com' 181 | } 182 | }], 183 | Start: { 184 | 'DateTime': startTime, 185 | 'TimeZone': 'PST' 186 | }, 187 | End: { 188 | 'DateTime': endTime, 189 | 'TimeZone': 'PST' 190 | }, 191 | Body: { 192 | Content: 'Status updates, blocking issues, and next steps.', 193 | ContentType: 'Text' 194 | } 195 | }; 196 | 197 | var req = { 198 | method: 'POST', 199 | url: baseUrl + '/me/events', 200 | data: newEvent 201 | }; 202 | 203 | return $http(req); 204 | }; 205 | 206 | /** 207 | * Creates an event, adds it to the signed-in user's calendar, and then 208 | * updates the Subject. 209 | */ 210 | function updateEvent() { 211 | var deferred = $q.defer(); 212 | 213 | var eventUpdates = { 214 | Subject: 'Sync of the Week' 215 | }; 216 | 217 | // Create an event to update. 218 | createEvent() 219 | // If successful, take event ID and update it. 220 | .then(function (response) { 221 | var eventId = response.data.id; 222 | 223 | var req = { 224 | method: 'PATCH', 225 | url: baseUrl + '/me/events/' + eventId, 226 | data: eventUpdates 227 | }; 228 | 229 | deferred.resolve($http(req)); 230 | }, function (error) { 231 | deferred.reject({ 232 | setupError: 'Unable to create an event to update.', 233 | response: error 234 | }); 235 | }); 236 | 237 | return deferred.promise; 238 | }; 239 | 240 | /** 241 | * Creates an event, adds it to the signed-in user's calendar, and then 242 | * deletes the event. 243 | */ 244 | function deleteEvent() { 245 | var deferred = $q.defer(); 246 | 247 | // Create an event to update first. 248 | createEvent() 249 | // If successful, take event ID and update it. 250 | .then(function (response) { 251 | var eventId = response.data.id; 252 | 253 | var req = { 254 | method: 'DELETE', 255 | url: baseUrl + '/me/events/' + eventId 256 | }; 257 | 258 | deferred.resolve($http(req)); 259 | }, function (error) { 260 | deferred.reject({ 261 | setupError: 'Unable to create an event to delete.', 262 | response: error 263 | }); 264 | }); 265 | 266 | return deferred.promise; 267 | }; 268 | 269 | /** 270 | * Get the signed-in user's messages. 271 | */ 272 | function getMessages() { 273 | var req = { 274 | method: 'GET', 275 | url: baseUrl + '/me/messages' 276 | }; 277 | 278 | return $http(req); 279 | }; 280 | 281 | /** 282 | * Send a message as the signed-in user. 283 | */ 284 | function sendMessage(recipientEmailAddress) { 285 | var deferred = $q.defer(); 286 | 287 | // First get the email address for the recipient. 288 | getMe() 289 | .then(function(response) { 290 | let me = response.data; 291 | let emailAddress = me.mail || me.userPrincipalName; 292 | 293 | // Then create the message. 294 | var newMessage = { 295 | Message: { 296 | Subject: 'Microsoft Graph Snippets Sample', 297 | Body: { 298 | ContentType: 'Text', 299 | Content: 'You can send an email by making a POST request to /me/sendMail.' 300 | }, 301 | ToRecipients: [ 302 | { 303 | EmailAddress: { 304 | Address: emailAddress 305 | } 306 | } 307 | ] 308 | }, 309 | SaveToSentItems: true 310 | }; 311 | 312 | var req = { 313 | method: 'POST', 314 | url: baseUrl + '/me/sendMail', 315 | data: newMessage 316 | }; 317 | 318 | deferred.resolve($http(req)); 319 | }, function (error) { 320 | deferred.reject({ 321 | setupError: 'Unable to get user info.', 322 | response: error 323 | }); 324 | }); 325 | 326 | return deferred.promise; 327 | }; 328 | 329 | /** 330 | * Get signed-in user's photo. 331 | */ 332 | function getUserPhoto() { 333 | var req = { 334 | method: 'GET', 335 | url: baseUrl + '/me/photo' 336 | }; 337 | 338 | return $http(req); 339 | }; 340 | 341 | /** 342 | * Get signed-in user's manager. 343 | */ 344 | function getManager() { 345 | var req = { 346 | method: 'GET', 347 | url: baseUrl + '/me/manager' 348 | }; 349 | 350 | return $http(req); 351 | }; 352 | 353 | /** 354 | * Get signed-in user's direct reports. 355 | */ 356 | function getDirectReports() { 357 | var req = { 358 | method: 'GET', 359 | url: baseUrl + '/me/directReports' 360 | }; 361 | 362 | return $http(req); 363 | }; 364 | 365 | /** 366 | * Get groups that signed-in user is a member of. 367 | */ 368 | function getMemberOf() { 369 | var req = { 370 | method: 'GET', 371 | url: baseUrl + '/me/memberOf' 372 | }; 373 | 374 | return $http(req); 375 | }; 376 | 377 | /** 378 | * Get signed-in user's files. 379 | */ 380 | function getFiles() { 381 | var req = { 382 | method: 'GET', 383 | url: baseUrl + '/me/drive/root/children' 384 | }; 385 | 386 | return $http(req); 387 | }; 388 | 389 | /** 390 | * Create a file in signed-in user's root directory. 391 | */ 392 | function createFile() { 393 | var randomFileName = common.guid() + '.txt'; 394 | 395 | var req = { 396 | method: 'PUT', 397 | url: baseUrl + '/me/drive/root/children/' + randomFileName + '/content', 398 | data: { 399 | content: randomFileName + ' is the name of this file.' 400 | } 401 | } 402 | 403 | return $http(req); 404 | }; 405 | 406 | /** 407 | * Get contents of a specific file. 408 | */ 409 | function downloadFile() { 410 | var deferred = $q.defer(); 411 | 412 | createFile() 413 | .then(function (response) { 414 | var fileId = response.data.id; 415 | 416 | var req = { 417 | method: 'GET', 418 | url: baseUrl + '/me/drive/items/' + fileId + '/content' 419 | }; 420 | 421 | deferred.resolve($http(req)); 422 | }, function (error) { 423 | deferred.reject({ 424 | setupError: 'Unable to create a file to download.', 425 | response: error 426 | }); 427 | }); 428 | 429 | return deferred.promise; 430 | }; 431 | 432 | /** 433 | * Updates the contents of a specific file. 434 | */ 435 | function updateFile() { 436 | var deferred = $q.defer(); 437 | 438 | createFile() 439 | .then(function (response) { 440 | var fileId = response.data.id; 441 | 442 | var req = { 443 | method: 'PUT', 444 | url: baseUrl + '/me/drive/items/' + fileId + '/content', 445 | data: { 446 | content: 'Updated file contents.' 447 | } 448 | }; 449 | 450 | deferred.resolve($http(req)); 451 | }, function (error) { 452 | deferred.reject({ 453 | setupError: 'Unable to create a file to update.', 454 | response: error 455 | }); 456 | }); 457 | 458 | return deferred.promise; 459 | }; 460 | 461 | /** 462 | * Renames a specific file. 463 | */ 464 | function renameFile(fileId) { 465 | var deferred = $q.defer(); 466 | 467 | createFile() 468 | .then(function (response) { 469 | var fileId = response.data.id; 470 | var fileName = response.data.name.replace('.txt', '-renamed.txt'); 471 | 472 | var req = { 473 | method: 'PATCH', 474 | url: baseUrl + '/me/drive/items/' + fileId, 475 | data: { 476 | name: fileName 477 | } 478 | }; 479 | 480 | deferred.resolve($http(req)); 481 | }, function (error) { 482 | deferred.reject({ 483 | setupError: 'Unable to create a file to rename.', 484 | response: error 485 | }); 486 | }); 487 | 488 | return deferred.promise; 489 | }; 490 | 491 | /** 492 | * Deletes a specific file. 493 | */ 494 | function deleteFile(fileId) { 495 | var deferred = $q.defer(); 496 | 497 | createFile() 498 | .then(function (response) { 499 | var fileId = response.data.id; 500 | 501 | var req = { 502 | method: 'DELETE', 503 | url: baseUrl + '/me/drive/items/' + fileId 504 | }; 505 | 506 | deferred.resolve($http(req)); 507 | }, function (error) { 508 | deferred.reject({ 509 | setupError: 'Unable to create a file to delete.', 510 | response: error 511 | }); 512 | }); 513 | 514 | return deferred.promise; 515 | }; 516 | 517 | /** 518 | * Creates a folder in the root directory. 519 | */ 520 | function createFolder() { 521 | var req = { 522 | method: 'POST', 523 | url: baseUrl + '/me/drive/root/children', 524 | data: { 525 | name: common.guid(), 526 | folder: {}, 527 | '@name.conflictBehavior': 'rename' 528 | } 529 | }; 530 | 531 | return $http(req); 532 | }; 533 | 534 | /** 535 | * Gets the current tenant. 536 | */ 537 | function getOrganization() { 538 | return $http.get(baseUrl + '/organization'); 539 | }; 540 | 541 | return users; 542 | } 543 | })(); -------------------------------------------------------------------------------- /public/controllers/mainController.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. 3 | * See LICENSE in the source repository root for complete license information. 4 | */ 5 | 6 | (function () { 7 | angular 8 | .module('app') 9 | .controller('MainController', MainController); 10 | 11 | /** 12 | * The MainController code. 13 | */ 14 | MainController.$inject = ['$scope', 'authHelper', 'commonFactory', 'usersFactory', 'groupsFactory', 'drivesFactory']; 15 | function MainController($scope, authHelper, common, users, groups, drives) { 16 | let vm = this; 17 | 18 | // Snippet constructor from commonFactory. 19 | let Snippet = common.Snippet; 20 | 21 | ///////////////////////// 22 | // Snippet // 23 | // ------- // 24 | // Title // 25 | // Description // 26 | // Documenation URL // 27 | // API URL // 28 | // Require admin? // 29 | // Snippet code // 30 | ///////////////////////// 31 | 32 | //////////////////////////////////////////////// 33 | // All of the snippets that fall under the // 34 | // 'users' tenant-level resource collection. // 35 | //////////////////////////////////////////////// 36 | var usersSnippets = { 37 | groupTitle: 'users', 38 | snippets: [ 39 | /////////////////////////////// 40 | // USER SNIPPETS // 41 | /////////////////////////////// 42 | new Snippet( 43 | 'GET myOrganization/users', 44 | 'Gets all of the users in your tenant\'s directory.', 45 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/user_list', 46 | common.baseUrl + '/myOrganization/users', 47 | false, 48 | function () { 49 | doSnippet(partial(users.getUsers, false)); 50 | }), 51 | new Snippet( 52 | 'GET myOrganization/users?$filter=country eq \'United States\'', 53 | 'Gets all of the users in your tenant\'s directory who are from the United States, using $filter.', 54 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/user_list', 55 | common.baseUrl + '/myOrganization/users?$filter=country eq \'United States\'', 56 | false, 57 | function () { 58 | doSnippet(partial(users.getUsers, true)); 59 | }), 60 | new Snippet( 61 | 'POST myOrganization/users *', 62 | 'Adds a new user to the tenant\'s directory.', 63 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/user_post_users', 64 | common.baseUrl + '/myOrganization/users', 65 | true, 66 | function () { 67 | doSnippet(partial(users.createUser)); 68 | }), 69 | new Snippet( 70 | 'GET me', 71 | 'Gets information about the signed-in user.', 72 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/user_get', 73 | common.baseUrl + '/me', 74 | false, 75 | function () { 76 | doSnippet(partial(users.getMe, false)); 77 | }), 78 | new Snippet( 79 | 'GET me?$select=AboutMe,Responsibilities *', 80 | 'Gets select information about the signed-in user, using $select.', 81 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/user_get', 82 | common.baseUrl + '/me?$select=AboutMe,Responsibilities', 83 | false, 84 | function () { 85 | doSnippet(partial(users.getMe, true)); 86 | }), 87 | ////////////////////////////////////// 88 | // USER/DRIVE SNIPPETS // 89 | ////////////////////////////////////// 90 | new Snippet( 91 | 'GET me/drive', 92 | 'Gets the signed-in user\'s drive.', 93 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/drive_get', 94 | common.baseUrl + '/me/drive', 95 | false, 96 | function () { 97 | doSnippet(users.getDrive); 98 | }), 99 | /////////////////////////////////////// 100 | // USER/EVENTS SNIPPETS // 101 | /////////////////////////////////////// 102 | new Snippet( 103 | 'GET me/events', 104 | 'Gets the signed-in user\'s calendar events.', 105 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/user_list_events', 106 | common.baseUrl + '/me/events', 107 | false, 108 | function () { 109 | doSnippet(users.getEvents); 110 | }), 111 | new Snippet( 112 | 'POST me/events', 113 | 'Adds an event to the signed-in user\'s calendar.', 114 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/user_post_events', 115 | common.baseUrl + '/me/events', 116 | false, 117 | function () { 118 | doSnippet(users.createEvent); 119 | }), 120 | new Snippet( 121 | 'PATCH me/events/{Event.id}', 122 | 'Adds an event to the signed-in user\'s calendar, then updates the subject of the event.', 123 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/event_update', 124 | common.baseUrl + '/me/events/{Event.id}', 125 | false, 126 | function () { 127 | doSnippet(users.updateEvent); 128 | }), 129 | new Snippet( 130 | 'DELETE me/events/{Event.id}', 131 | 'Adds an event to the signed-in user\'s calendar, then deletes the event.', 132 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/event_delete', 133 | common.baseUrl + '/me/events/{Event.id}', 134 | false, 135 | function () { 136 | doSnippet(users.deleteEvent); 137 | }), 138 | ////////////////////////////////////////// 139 | // USER/MESSAGES SNIPPETS // 140 | ////////////////////////////////////////// 141 | new Snippet( 142 | 'GET me/messages', 143 | 'Gets the signed-in user\'s emails.', 144 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/user_list_messages', 145 | common.baseUrl + '/me/messages', 146 | false, 147 | function () { 148 | doSnippet(users.getMessages); 149 | }), 150 | new Snippet( 151 | 'POST me/sendMail', 152 | 'Sends an email as the signed-in user and saves a copy to their Sent Items folder.', 153 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/user_sendmail', 154 | common.baseUrl + '/me/sendMail', 155 | false, 156 | function () { 157 | doSnippet(partial(users.sendMessage)); 158 | }), 159 | ////////////////////////////////////////// 160 | // USER/FILES SNIPPETS // 161 | ////////////////////////////////////////// 162 | new Snippet( 163 | 'GET me/drive/root/children', 164 | 'Gets files from the signed-in user\'s root directory.', 165 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/item_list_children', 166 | common.baseUrl + '/me/drive/root/children', 167 | false, 168 | function () { 169 | doSnippet(users.getFiles); 170 | }), 171 | new Snippet( 172 | 'PUT me/drive/root/children/{FileName}/content', 173 | 'Creates a file with content in the signed-in user\'s root directory.', 174 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/item_uploadcontent', 175 | common.baseUrl + '/me/drive/root/children/{FileName}/content', 176 | false, 177 | function () { 178 | doSnippet(users.createFile); 179 | }), 180 | new Snippet( 181 | 'GET me/drive/items/{File.id}/content', 182 | 'Downloads a file.', 183 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/item_downloadcontent', 184 | common.baseUrl + '/me/drive/items/{File.id}/content', 185 | false, 186 | function () { 187 | doSnippet(users.downloadFile); 188 | }), 189 | new Snippet( 190 | 'PUT me/drive/items/{File.id}/content', 191 | 'Updates the contents of a file.', 192 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/item_downloadcontent', 193 | common.baseUrl + '/me/drive/items/{File.id}/content', 194 | false, 195 | function () { 196 | doSnippet(users.updateFile); 197 | }), 198 | new Snippet( 199 | 'PATCH me/drive/items/{File.id}', 200 | 'Renames a file.', 201 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/item_update', 202 | common.baseUrl + '/me/drive/items/{File.id}', 203 | false, 204 | function () { 205 | doSnippet(users.renameFile); 206 | }), 207 | new Snippet( 208 | 'DELETE me/drive/items/{File.id}', 209 | 'Deletes a file.', 210 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/item_delete', 211 | common.baseUrl + '/me/drive/items/{File.id}', 212 | false, 213 | function () { 214 | doSnippet(users.deleteFile); 215 | }), 216 | new Snippet( 217 | 'POST me/drive/root/children', 218 | 'Creates a folder in the signed-in user\'s root directory.', 219 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/item_post_children', 220 | common.baseUrl + '/me/drive/root/children', 221 | false, 222 | function () { 223 | doSnippet(users.createFolder); 224 | }), 225 | /////////////////////////////////////////////// 226 | // MISCELLANEOUS USER SNIPPETS // 227 | /////////////////////////////////////////////// 228 | new Snippet( 229 | 'GET me/manager *', 230 | 'Gets the signed-in user\'s manager.', 231 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/user_list_manager', 232 | common.baseUrl + '/me/manager', 233 | false, 234 | function () { 235 | doSnippet(users.getManager); 236 | }), 237 | new Snippet( 238 | 'GET me/directReports *', 239 | 'Gets the signed-in user\'s direct reports.', 240 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/user_list_directreports', 241 | common.baseUrl + '/me/directReports', 242 | false, 243 | function () { 244 | doSnippet(users.getDirectReports); 245 | }), 246 | new Snippet( 247 | 'GET me/photo *', 248 | 'Gets the signed-in user\'s photo.', 249 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/profilephoto_get', 250 | common.baseUrl + '/me/photo', 251 | false, 252 | function () { 253 | doSnippet(users.getUserPhoto); 254 | }), 255 | new Snippet( 256 | 'GET me/memberOf *', 257 | 'Gets the groups that the signed-in user is a member of.', 258 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/user_list_memberof', 259 | common.baseUrl + '/me/memberOf', 260 | false, 261 | function () { 262 | doSnippet(users.getMemberOf); 263 | }) 264 | ] 265 | }; 266 | 267 | //////////////////////////////////////////////// 268 | // All of the snippets that fall under the // 269 | // 'groups' tenant-level resource collection. // 270 | //////////////////////////////////////////////// 271 | var groupsSnippets = { 272 | groupTitle: 'groups', 273 | snippets: [ 274 | ///////////////////////////////// 275 | // GROUPS SNIPPETS // 276 | ///////////////////////////////// 277 | new Snippet( 278 | 'GET myOrganization/groups', 279 | 'Gets all of the groups in your tenant\'s directory.', 280 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/group_list', 281 | common.baseUrl + '/myOrganization/groups', 282 | false, 283 | function () { 284 | doSnippet(groups.getGroups); 285 | }), 286 | new Snippet( 287 | 'POST myOrganization/groups *', 288 | 'Adds a new security group to the tenant.', 289 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/group_post_groups', 290 | common.baseUrl + '/myOrganization/groups', 291 | false, 292 | function () { 293 | doSnippet(groups.createGroup); 294 | }), 295 | new Snippet( 296 | 'GET myOrganization/groups/{Group.id}', 297 | 'Gets information about a group in the tenant by ID.', 298 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/group_get', 299 | common.baseUrl + '/myOrganization/groups/{Group.id}', 300 | false, 301 | function () { 302 | doSnippet(groups.getGroup); 303 | }), 304 | new Snippet( 305 | 'PATCH myOrganization/groups/{Group.id} *', 306 | 'Adds a new group to the tenant, then updates the description of that group.', 307 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/group_update', 308 | common.baseUrl + '/myOrganization/groups/{Group.id}', 309 | false, 310 | function () { 311 | doSnippet(groups.updateGroup); 312 | }), 313 | new Snippet( 314 | 'DELETE myOrganization/groups/{Group.id} *', 315 | 'Adds a new group to the tenant, then deletes the group.', 316 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/group_delete', 317 | common.baseUrl + '/myOrganization/groups/{Group.id}', 318 | false, 319 | function () { 320 | doSnippet(groups.deleteGroup); 321 | }), 322 | new Snippet( 323 | 'GET myOrganization/groups/{Group.id}/members', 324 | 'Gets the members of a group.', 325 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/group_list_members', 326 | common.baseUrl + '/myOrganization/groups/{Group.id}/members', 327 | false, 328 | function () { 329 | doSnippet(groups.getMembers); 330 | }), 331 | new Snippet( 332 | 'GET myOrganization/groups/{Group.id}/owners', 333 | 'Gets the owners of a group.', 334 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/group_list_owners', 335 | common.baseUrl + '/myOrganization/groups/{Group.id}/owners', 336 | false, 337 | function () { 338 | doSnippet(groups.getOwners); 339 | }) 340 | ] 341 | }; 342 | 343 | //////////////////////////////////////////////// 344 | // All of the snippets that fall under the // 345 | // 'drives' tenant-level resource collection. // 346 | //////////////////////////////////////////////// 347 | var drivesSnippets = { 348 | groupTitle: 'drives', 349 | snippets: [ 350 | ///////////////////////////////// 351 | // DRIVES SNIPPETS // 352 | ///////////////////////////////// 353 | new Snippet( 354 | 'GET myOrganization/drives', 355 | 'Gets all of the drives in your tenant.', 356 | 'http://graph.microsoft.io/docs/api-reference/v1.0/api/drive_get', 357 | common.baseUrl + '/myOrganization/drives', 358 | false, 359 | function () { 360 | doSnippet(drives.getDrives); 361 | }) 362 | ] 363 | }; 364 | 365 | // Properties 366 | vm.activeSnippet; 367 | vm.snippetGroups = [ 368 | usersSnippets, 369 | groupsSnippets, 370 | drivesSnippets 371 | ]; 372 | 373 | // Methods 374 | vm.isAuthenticated = isAuthenticated; 375 | vm.setActive = setActive; 376 | 377 | ///////////////////////////////////////// 378 | // End of exposed properties and methods. 379 | 380 | /** 381 | * This function does any initialization work the 382 | * controller needs. 383 | */ 384 | (function activate() { 385 | if (!localStorage.auth) { 386 | let auth = hello('aad').getAuthResponse(); 387 | if (auth !== null) { 388 | localStorage.auth = angular.toJson(auth); 389 | } 390 | } 391 | vm.activeSnippet = vm.snippetGroups[0].snippets[0]; 392 | })(); 393 | 394 | function isAuthenticated() { 395 | return localStorage.getItem('auth') !== null; 396 | } 397 | 398 | /** 399 | * Takes in a snippet, starts animation, executes snippet and handles response, 400 | * then stops animation. 401 | */ 402 | function doSnippet(snippet) { 403 | 404 | // Get the access token and attach it to the request. 405 | authHelper.getToken(); 406 | 407 | // Starts button animation. 408 | $scope.laddaLoading = true; 409 | 410 | // Clear old data. 411 | vm.activeSnippet.request = null; 412 | vm.activeSnippet.response = null; 413 | vm.activeSnippet.setupError = null; 414 | 415 | snippet() 416 | .then(function (response) { 417 | // Format request and response. 418 | var request = response.config; 419 | response = { 420 | status: response.status, 421 | statusText: response.statusText, 422 | data: response.data 423 | }; 424 | 425 | // Attach response to view model. 426 | vm.activeSnippet.request = request; 427 | vm.activeSnippet.response = response; 428 | }, function (error) { 429 | // If a snippet requires setup (i.e. creating an event to update, creating a file 430 | // to delete, etc.) and it fails, handle that error message differently. 431 | if (error.setupError) { 432 | // Extract setup error message. 433 | vm.activeSnippet.setupError = error.setupError; 434 | 435 | // Extract response data. 436 | vm.activeSnippet.response = { 437 | status: error.response.data, 438 | statusText: error.response.statusText, 439 | data: error.response.data 440 | } 441 | 442 | return; 443 | } 444 | 445 | // Format request and response. 446 | var request = error.config; 447 | error = { 448 | status: error.status, 449 | statusText: error.statusText, 450 | data: error.data 451 | }; 452 | 453 | // Attach response to view model. 454 | vm.activeSnippet.request = request; 455 | vm.activeSnippet.response = error; 456 | }) 457 | .finally(function () { 458 | // Stops button animation. 459 | $scope.laddaLoading = false; 460 | }); 461 | }; 462 | 463 | /** 464 | * Sets class of list item in the sidebar. 465 | */ 466 | function setActive(title) { 467 | if (vm.isAuthenticated()) { 468 | return; 469 | } 470 | 471 | if (vm.activeSnippet !== undefined) { 472 | if (title === vm.activeSnippet.title) { 473 | return 'active'; 474 | } 475 | } 476 | else { 477 | return ''; 478 | } 479 | }; 480 | 481 | /** 482 | * Function to create partial functions. Taken 483 | * from Stack Overflow user Jason Bunting. 484 | * 485 | * http://stackoverflow.com/users/1790/jason-bunting 486 | * http://stackoverflow.com/questions/321113/how-can-i-pre-set-arguments-in-javascript- 487 | * function-call-partial-function-appli/321527#321527 488 | */ 489 | function partial(func /*, 0..n args */) { 490 | var args = Array.prototype.slice.call(arguments, 1); 491 | return function () { 492 | var allArguments = args.concat(Array.prototype.slice.call(arguments)); 493 | return func.apply(this, allArguments); 494 | }; 495 | }; 496 | }; 497 | })(); --------------------------------------------------------------------------------