├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug-report.md │ └── enhancement_request.md └── pull_request_template.md ├── .gitignore ├── .rescriptsrc.js ├── .webpack.config.js ├── .yarnclean ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── assets ├── entitlements.mac.plist └── icons │ ├── create-icon.sh │ ├── icon.icns │ ├── icon_128x128.png │ ├── icon_128x128@2x.png │ ├── icon_16x16.png │ ├── icon_16x16@2x.png │ ├── icon_256x256.png │ ├── icon_256x256@2x.png │ ├── icon_32x32.png │ ├── icon_32x32@2x.png │ ├── icon_512x512.png │ ├── icon_512x512@2x.png │ └── rubrik-gql-logo.png ├── build ├── asset-manifest.json ├── electron.js ├── index.html ├── manifest.json ├── precache-manifest.4f7bfaaef02f289fea20afe32c695f26.js ├── service-worker.js └── static │ ├── css │ ├── 2.20e21577.chunk.css │ ├── 2.20e21577.chunk.css.map │ ├── main.29d4883d.chunk.css │ └── main.29d4883d.chunk.css.map │ ├── js │ ├── 2.b1d11dab.chunk.js │ ├── 2.b1d11dab.chunk.js.map │ ├── main.e15b519c.chunk.js │ ├── main.e15b519c.chunk.js.map │ ├── runtime~main.8c97409f.js │ └── runtime~main.8c97409f.js.map │ └── media │ └── rubrikLogo.b5f40d5b.svg ├── package-lock.json ├── package.json ├── public ├── electron.js ├── index.html └── manifest.json ├── script └── notarize.js ├── src ├── App.js ├── App.test.js ├── components │ ├── defaultSettings │ │ ├── CdmApiTokenToggle.js │ │ ├── DefaultPlatformSelection.js │ │ ├── PolarisDevelopmentModeToggle.js │ │ └── SettingsDialog.js │ ├── graphiql │ │ ├── GraphiQl.css │ │ └── GraphiQl.js │ ├── landingPage │ │ ├── LandingPage.css │ │ └── LandingPage.js │ └── loginForm │ │ └── LoginForm.js ├── images │ ├── pattern.png │ └── rubrikLogo.svg ├── index.css ├── index.js ├── serviceWorker.js └── utils │ └── api.js └── yarn.lock /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @rubrikinc/octo -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Report a bug 4 | title: '' 5 | labels: kind-bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | 12 | **Expected Behavior** 13 | 14 | **Current Behavior** 15 | 16 | **Failure Information** 17 | 18 | 19 | 20 | **Steps to Reproduce** 21 | 22 | 23 | 24 | **Context** 25 | 26 | 31 | 32 | **Failure Logs** 33 | 34 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/enhancement_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Enhancement Request 3 | about: Suggest an enhancement 4 | title: '' 5 | labels: kind-enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | 12 | **Is your feature request related to a problem? Please describe.** 13 | 14 | **Describe the solution you'd like** 15 | 16 | **Describe alternatives you've considered** 17 | 18 | **Additional context** 19 | 20 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | 4 | 5 | ## Related Issue 6 | 7 | 8 | 9 | 10 | 11 | ## Motivation and Context 12 | 13 | 14 | 15 | ## How Has This Been Tested? 16 | 17 | 19 | 20 | ## Screenshots (if appropriate): 21 | 22 | ## Types of changes 23 | 24 | What types of changes does your code introduce? Put an `x` in all the boxes that apply: 25 | - [ ] Bug fix (non-breaking change which fixes an issue) 26 | - [ ] New feature (non-breaking change which adds functionality) 27 | - [ ] Breaking change (fix or feature that would cause existing functionality to change) 28 | 29 | ## Checklist: 30 | 31 | Go over all the following points, and put an `x` in all the boxes that apply. If you're unsure about any of these, don't hesitate to ask. We're here to help! 32 | 33 | - [ ] My change requires a change to the documentation. 34 | - [ ] I have updated the documentation accordingly. 35 | - [ ] I have read the **[CONTRIBUTION](https://github.com/rubrikinc/welcome-to-rubrik-build/blob/master/CONTRIBUTING.md)** document. 36 | - [ ] I have updated the CHANGELOG file accordingly for the version that this merge modifies. -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Tags 2 | tags 3 | 4 | # Logs 5 | logs 6 | *.log 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | 13 | # Directory for instrumented libs generated by jscoverage/JSCover 14 | lib-cov 15 | 16 | # Coverage directory used by tools like istanbul 17 | coverage 18 | 19 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 20 | .grunt 21 | 22 | # node-waf configuration 23 | .lock-wscript 24 | 25 | # Compiled binary addons (http://nodejs.org/api/addons.html) 26 | build/Release 27 | 28 | # Dependency directory 29 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 30 | node_modules 31 | 32 | # OSX 33 | .DS_Store 34 | 35 | # App packaged 36 | release 37 | dist 38 | 39 | .envrc 40 | # Ignore the ./script/.env environment file which is used 41 | # for macOS Notarizing 42 | .env* 43 | build/* -------------------------------------------------------------------------------- /.rescriptsrc.js: -------------------------------------------------------------------------------- 1 | module.exports = [require.resolve('./.webpack.config.js')] -------------------------------------------------------------------------------- /.webpack.config.js: -------------------------------------------------------------------------------- 1 | // define child rescript 2 | module.exports = config => { 3 | config.target = 'electron-renderer'; 4 | return config; 5 | } -------------------------------------------------------------------------------- /.yarnclean: -------------------------------------------------------------------------------- 1 | # test directories 2 | __tests__ 3 | test 4 | tests 5 | powered-test 6 | 7 | # asset directories 8 | docs 9 | doc 10 | website 11 | images 12 | assets 13 | 14 | # examples 15 | example 16 | examples 17 | 18 | # code coverage directories 19 | coverage 20 | .nyc_output 21 | 22 | # build scripts 23 | Makefile 24 | Gulpfile.js 25 | Gruntfile.js 26 | 27 | # configs 28 | appveyor.yml 29 | circle.yml 30 | codeship-services.yml 31 | codeship-steps.yml 32 | wercker.yml 33 | .tern-project 34 | .gitattributes 35 | .editorconfig 36 | .*ignore 37 | .eslintrc 38 | .jshintrc 39 | .flowconfig 40 | .documentup.json 41 | .yarn-metadata.json 42 | .travis.yml 43 | 44 | # misc 45 | *.md 46 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](http://keepachangelog.com/) 6 | and this project adheres to [Semantic Versioning](http://semver.org/). 7 | 8 | ## Types of changes 9 | 10 | * **Added** for new features. 11 | * **Changed** for changes in existing functionality. 12 | * **Deprecated** for soon-to-be removed features. 13 | * **Removed** for now removed features. 14 | * **Fixed** for any bug fixes. 15 | * **Security** in case of vulnerabilities. 16 | 17 | ## v2.0.1 18 | 19 | ### Added 20 | 21 | * Authenticate against a CDM cluster using an API Token. [Issue 17](https://github.com/rubrikinc/graphql-playground/issues/17) 22 | * Allow the end user to save application defaults [Issue 21](https://github.com/rubrikinc/graphql-playground/issues/21) 23 | 24 | ## Unreleased 25 | 26 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributions via GitHub pull requests are gladly accepted from their original author. Along with any pull requests, please state that the contribution is your original work and that you license the work to the project under the project's open source license. Whether or not you state this explicitly, by submitting any copyrighted material via pull request, email, or other means you agree to license the material under the project's open source license and warrant that you have the legal authority to do so. 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Rubrik 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rubrik GraphQL Playground 2 | 3 | The Rubrik GraphQL Playground is a cross-platform desktop application designed to allow you to interact with the Rubrik GraphQL services for both Polaris and CDM. The latest versions can be downloaded on the GitHub [releases page](https://github.com/rubrikinc/graphql-playground/releases). 4 | 5 | GraphQL is fully supported in CDM v5.2 but _currently_ has limited support in Polaris. More information on GraphQL can be found in our [An Introduction to GraphQL and Rubrik](https://www.rubrik.com/content/dam/rubrik/en/resources/white-paper/an-introduction-to-graphql-and-rubrik.pdf) whitepaper. 6 | 7 | Welcome screen 8 | 9 | Playground 10 | 11 | 12 | 13 | ## :muscle: How You Can Help 14 | 15 | We glady welcome contributions from the community. From updating the documentation to adding more functions for Python, all ideas are welcome. Thank you in advance for all of your issues, pull requests, and comments! :star: 16 | 17 | - [Contributing Guide](CONTRIBUTING.md) 18 | - [Code of Conduct](CODE_OF_CONDUCT.md) 19 | 20 | ## :pushpin: License 21 | 22 | - [MIT License](LICENSE) 23 | 24 | ## :point_right: About Rubrik Build 25 | 26 | We encourage all contributors to become members. We aim to grow an active, healthy community of contributors, reviewers, and code owners. Learn more in our [Welcome to the Rubrik Build Community](https://github.com/rubrikinc/welcome-to-rubrik-build) page. 27 | 28 | We'd love to hear from you! Email us: build@rubrik.com :love_letter: 29 | -------------------------------------------------------------------------------- /assets/entitlements.mac.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.cs.allow-unsigned-executable-memory 6 | 7 | 8 | -------------------------------------------------------------------------------- /assets/icons/create-icon.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Creates an icns file from a source image 3 | 4 | src_image="$1" 5 | if [ -z "$1" ]; then 6 | echo "No source image was passed to this script" 7 | exit 1 8 | fi 9 | 10 | icns_name="$2" 11 | if [ -z "$2" ]; then 12 | icns_name="iconbuilder" 13 | fi 14 | 15 | if [ "${src_image:(-3)}" != "png" ]; then 16 | echo "Source image is not a PNG, making a converted copy..." 17 | /usr/bin/sips -s format png "$src_image" --out "${src_image}.png" 18 | if [ $? -ne 0 ]; then 19 | echo "The source image could not be converted to PNG format." 20 | exit 1 21 | fi 22 | src_image="${src_image}.png" 23 | fi 24 | 25 | iconset_path="./${icns_name}.iconset" 26 | if [ -e "$iconset_path" ]; then 27 | /bin/rm -r "$iconset_path" 28 | if [ $? -ne 0 ]; then 29 | echo "There is a pre-existing file/dir $iconset_path the could not be deleted" 30 | exit 1 31 | fi 32 | fi 33 | 34 | /bin/mkdir "$iconset_path" 35 | 36 | icon_file_list=( 37 | "icon_16x16.png" 38 | "icon_16x16@2x.png" 39 | "icon_32x32.png" 40 | "icon_32x32@2x.png" 41 | "icon_128x128.png" 42 | "icon_128x128@2x.png" 43 | "icon_256x256.png" 44 | "icon_256x256@2x.png" 45 | "icon_512x512.png" 46 | "icon_512x512@2x.png" 47 | ) 48 | 49 | icon_size=( 50 | '16' 51 | '32' 52 | '32' 53 | '64' 54 | '128' 55 | '256' 56 | '256' 57 | '512' 58 | '512' 59 | '1024' 60 | ) 61 | 62 | counter=0 63 | for a in ${icon_file_list[@]}; do 64 | icon="${iconset_path}/${a}" 65 | /bin/cp "$src_image" "$icon" 66 | icon_size=${icon_size[$counter]} 67 | /usr/bin/sips -z $icon_size $icon_size "$icon" 68 | counter=$(($counter + 1)) 69 | done 70 | 71 | echo "Creating .icns file from $iconset_path" 72 | /usr/bin/iconutil -c icns "$iconset_path" 73 | if [ $? -ne 0 ]; then 74 | echo "There was an error creating the .icns file" 75 | exit 1 76 | fi 77 | 78 | echo "Done" 79 | exit 0 -------------------------------------------------------------------------------- /assets/icons/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubrikinc/graphql-playground/b7840cda3a422847538525289f71a707dc7b2d25/assets/icons/icon.icns -------------------------------------------------------------------------------- /assets/icons/icon_128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubrikinc/graphql-playground/b7840cda3a422847538525289f71a707dc7b2d25/assets/icons/icon_128x128.png -------------------------------------------------------------------------------- /assets/icons/icon_128x128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubrikinc/graphql-playground/b7840cda3a422847538525289f71a707dc7b2d25/assets/icons/icon_128x128@2x.png -------------------------------------------------------------------------------- /assets/icons/icon_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubrikinc/graphql-playground/b7840cda3a422847538525289f71a707dc7b2d25/assets/icons/icon_16x16.png -------------------------------------------------------------------------------- /assets/icons/icon_16x16@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubrikinc/graphql-playground/b7840cda3a422847538525289f71a707dc7b2d25/assets/icons/icon_16x16@2x.png -------------------------------------------------------------------------------- /assets/icons/icon_256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubrikinc/graphql-playground/b7840cda3a422847538525289f71a707dc7b2d25/assets/icons/icon_256x256.png -------------------------------------------------------------------------------- /assets/icons/icon_256x256@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubrikinc/graphql-playground/b7840cda3a422847538525289f71a707dc7b2d25/assets/icons/icon_256x256@2x.png -------------------------------------------------------------------------------- /assets/icons/icon_32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubrikinc/graphql-playground/b7840cda3a422847538525289f71a707dc7b2d25/assets/icons/icon_32x32.png -------------------------------------------------------------------------------- /assets/icons/icon_32x32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubrikinc/graphql-playground/b7840cda3a422847538525289f71a707dc7b2d25/assets/icons/icon_32x32@2x.png -------------------------------------------------------------------------------- /assets/icons/icon_512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubrikinc/graphql-playground/b7840cda3a422847538525289f71a707dc7b2d25/assets/icons/icon_512x512.png -------------------------------------------------------------------------------- /assets/icons/icon_512x512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubrikinc/graphql-playground/b7840cda3a422847538525289f71a707dc7b2d25/assets/icons/icon_512x512@2x.png -------------------------------------------------------------------------------- /assets/icons/rubrik-gql-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubrikinc/graphql-playground/b7840cda3a422847538525289f71a707dc7b2d25/assets/icons/rubrik-gql-logo.png -------------------------------------------------------------------------------- /build/asset-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "main.css": "./static/css/main.29d4883d.chunk.css", 3 | "main.js": "./static/js/main.e15b519c.chunk.js", 4 | "main.js.map": "./static/js/main.e15b519c.chunk.js.map", 5 | "runtime~main.js": "./static/js/runtime~main.8c97409f.js", 6 | "runtime~main.js.map": "./static/js/runtime~main.8c97409f.js.map", 7 | "static/css/2.20e21577.chunk.css": "./static/css/2.20e21577.chunk.css", 8 | "static/js/2.b1d11dab.chunk.js": "./static/js/2.b1d11dab.chunk.js", 9 | "static/js/2.b1d11dab.chunk.js.map": "./static/js/2.b1d11dab.chunk.js.map", 10 | "index.html": "./index.html", 11 | "precache-manifest.4f7bfaaef02f289fea20afe32c695f26.js": "./precache-manifest.4f7bfaaef02f289fea20afe32c695f26.js", 12 | "service-worker.js": "./service-worker.js", 13 | "static/css/2.20e21577.chunk.css.map": "./static/css/2.20e21577.chunk.css.map", 14 | "static/css/main.29d4883d.chunk.css.map": "./static/css/main.29d4883d.chunk.css.map", 15 | "static/media/rubrikLogo.svg": "./static/media/rubrikLogo.b5f40d5b.svg" 16 | } -------------------------------------------------------------------------------- /build/electron.js: -------------------------------------------------------------------------------- 1 | const electron = require("electron"); 2 | const { autoUpdater } = require("electron-updater"); 3 | const app = electron.app; 4 | app.commandLine.appendSwitch("ignore-certificate-errors", "true"); 5 | 6 | const BrowserWindow = electron.BrowserWindow; 7 | 8 | const path = require("path"); 9 | const isDev = require("electron-is-dev"); 10 | var Menu = electron.Menu; 11 | 12 | let mainWindow; 13 | 14 | function sendStatusToWindow(text) { 15 | mainWindow.webContents.send("message", text); 16 | } 17 | 18 | function createWindow() { 19 | mainWindow = new BrowserWindow({ 20 | show: false, 21 | webPreferences: { 22 | webSecurity: false, 23 | }, 24 | }); 25 | mainWindow.maximize(); 26 | mainWindow.show(); 27 | mainWindow.loadURL( 28 | isDev 29 | ? "http://localhost:3000" 30 | : `file://${path.join(__dirname, "../build/index.html")}` 31 | ); 32 | require("update-electron-app")(); 33 | 34 | if (isDev) { 35 | // Open the DevTools. 36 | //BrowserWindow.addDevToolsExtension(''); 37 | mainWindow.webContents.openDevTools(); 38 | } 39 | 40 | sendStatusToWindow("This is a test message."); 41 | 42 | if (process.platform === "darwin") { 43 | template = [ 44 | { 45 | label: "Rubrik GraphQL Playground", 46 | submenu: [ 47 | { 48 | label: "About Rubrik GraphQL Playground", 49 | selector: "orderFrontStandardAboutPanel:", 50 | }, 51 | { 52 | type: "separator", 53 | }, 54 | { 55 | label: "Quit", 56 | accelerator: "Command+Q", 57 | click: function () { 58 | app.quit(); 59 | }, 60 | }, 61 | ], 62 | }, 63 | { 64 | label: "File", 65 | submenu: [ 66 | { 67 | label: "Logout", 68 | accelerator: "Command+L", 69 | click: function () { 70 | if (mainWindow.restart) { 71 | mainWindow.restart(); 72 | } else if (mainWindow.reload) { 73 | mainWindow.reload(); 74 | } 75 | }, 76 | }, 77 | { 78 | label: "Quit", 79 | accelerator: "Command+Q", 80 | click() { 81 | app.quit(); 82 | }, 83 | }, 84 | ], 85 | }, 86 | { 87 | label: "Edit", 88 | submenu: [ 89 | { 90 | label: "Undo", 91 | accelerator: "Command+Z", 92 | selector: "undo:", 93 | }, 94 | { 95 | label: "Redo", 96 | accelerator: "Shift+Command+Z", 97 | selector: "redo:", 98 | }, 99 | { 100 | type: "separator", 101 | }, 102 | { 103 | label: "Cut", 104 | accelerator: "Command+X", 105 | selector: "cut:", 106 | }, 107 | { 108 | label: "Copy", 109 | accelerator: "Command+C", 110 | selector: "copy:", 111 | }, 112 | { 113 | label: "Paste", 114 | accelerator: "Command+V", 115 | selector: "paste:", 116 | }, 117 | { 118 | label: "Select All", 119 | accelerator: "Command+A", 120 | selector: "selectAll:", 121 | }, 122 | ], 123 | }, 124 | { 125 | label: "View", 126 | submenu: [ 127 | { 128 | label: "Toggle Full Screen", 129 | accelerator: "Ctrl+Command+F", 130 | click: function () { 131 | mainWindow.setFullScreen(!mainWindow.isFullScreen()); 132 | }, 133 | }, 134 | { 135 | label: "Toggle Developer Tools", 136 | accelerator: "Alt+Command+I", 137 | click: function () { 138 | mainWindow.toggleDevTools(); 139 | }, 140 | }, 141 | { 142 | role: "resetzoom", 143 | }, 144 | { 145 | role: "zoomin", 146 | }, 147 | { 148 | role: "zoomout", 149 | }, 150 | ], 151 | }, 152 | { 153 | label: "Window", 154 | submenu: [ 155 | { 156 | label: "Minimize", 157 | accelerator: "Command+M", 158 | selector: "performMiniaturize:", 159 | }, 160 | { 161 | type: "separator", 162 | }, 163 | { 164 | label: "Bring All to Front", 165 | selector: "arrangeInFront:", 166 | }, 167 | ], 168 | }, 169 | ]; 170 | 171 | menu = Menu.buildFromTemplate(template); 172 | Menu.setApplicationMenu(menu); 173 | } else { 174 | template = [ 175 | { 176 | label: "&File", 177 | submenu: [ 178 | { 179 | label: "Logout", 180 | accelerator: "Command+L", 181 | click: function () { 182 | if (mainWindow.restart) { 183 | mainWindow.restart(); 184 | } else if (mainWindow.reload) { 185 | mainWindow.reload(); 186 | } 187 | }, 188 | }, 189 | { 190 | label: "Quit", 191 | accelerator: "Command+Q", 192 | click() { 193 | app.quit(); 194 | }, 195 | }, 196 | ], 197 | }, 198 | { 199 | label: "&View", 200 | submenu: [ 201 | { 202 | label: "Toggle &Full Screen", 203 | accelerator: "F11", 204 | click: function () { 205 | mainWindow.setFullScreen(!mainWindow.isFullScreen()); 206 | }, 207 | }, 208 | { 209 | label: "Toggle &Developer Tools", 210 | accelerator: "Alt+Ctrl+I", 211 | click: function () { 212 | mainWindow.toggleDevTools(); 213 | }, 214 | }, 215 | ], 216 | }, 217 | ]; 218 | menu = Menu.buildFromTemplate(template); 219 | mainWindow.setMenu(menu); 220 | } 221 | 222 | mainWindow.on("closed", () => (mainWindow = null)); 223 | } 224 | 225 | autoUpdater.on("checking-for-update", () => { 226 | sendStatusToWindow("Checking for update..."); 227 | }); 228 | autoUpdater.on("update-available", (info) => { 229 | sendStatusToWindow("Update available."); 230 | }); 231 | autoUpdater.on("update-not-available", (info) => { 232 | sendStatusToWindow("Update not available."); 233 | }); 234 | autoUpdater.on("error", (err) => { 235 | sendStatusToWindow("Error in auto-updater. " + err); 236 | }); 237 | autoUpdater.on("download-progress", (progressObj) => { 238 | let log_message = "Download speed: " + progressObj.bytesPerSecond; 239 | log_message = log_message + " - Downloaded " + progressObj.percent + "%"; 240 | log_message = 241 | log_message + 242 | " (" + 243 | progressObj.transferred + 244 | "/" + 245 | progressObj.total + 246 | ")"; 247 | sendStatusToWindow(log_message); 248 | }); 249 | autoUpdater.on("update-downloaded", (info) => { 250 | sendStatusToWindow("Update downloaded - please restart latest version"); 251 | //autoUpdater.quitAndInstall(); 252 | }); 253 | 254 | app.on("ready", createWindow); 255 | 256 | app.on("window-all-closed", () => { 257 | if (process.platform !== "darwin") { 258 | app.quit(); 259 | } 260 | }); 261 | 262 | app.on("activate", () => { 263 | if (mainWindow === null) { 264 | require("update-electron-app")(); 265 | 266 | createWindow(); 267 | } 268 | }); 269 | 270 | // app quits. 271 | //------------------------------------------------------------------- 272 | app.on("ready", function () { 273 | autoUpdater.checkForUpdatesAndNotify(); 274 | }); 275 | -------------------------------------------------------------------------------- /build/index.html: -------------------------------------------------------------------------------- 1 | Rubrik GraphQL Playground
-------------------------------------------------------------------------------- /build/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Rubrik GraphQL Playground", 3 | "name": "Rubrik GraphQL Playground", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /build/precache-manifest.4f7bfaaef02f289fea20afe32c695f26.js: -------------------------------------------------------------------------------- 1 | self.__precacheManifest = [ 2 | { 3 | "revision": "e15b519ccaa8188ced43", 4 | "url": "./static/css/main.29d4883d.chunk.css" 5 | }, 6 | { 7 | "revision": "e15b519ccaa8188ced43", 8 | "url": "./static/js/main.e15b519c.chunk.js" 9 | }, 10 | { 11 | "revision": "8c97409f0ee389fe75da", 12 | "url": "./static/js/runtime~main.8c97409f.js" 13 | }, 14 | { 15 | "revision": "b1d11dab72b1351125b3", 16 | "url": "./static/css/2.20e21577.chunk.css" 17 | }, 18 | { 19 | "revision": "b1d11dab72b1351125b3", 20 | "url": "./static/js/2.b1d11dab.chunk.js" 21 | }, 22 | { 23 | "revision": "b5f40d5b13fd84bd0fd0ace2cd361ce2", 24 | "url": "./static/media/rubrikLogo.b5f40d5b.svg" 25 | }, 26 | { 27 | "revision": "f0f52bcd229750246198992cbbdfb706", 28 | "url": "./index.html" 29 | } 30 | ]; -------------------------------------------------------------------------------- /build/service-worker.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to your Workbox-powered service worker! 3 | * 4 | * You'll need to register this file in your web app and you should 5 | * disable HTTP caching for this file too. 6 | * See https://goo.gl/nhQhGp 7 | * 8 | * The rest of the code is auto-generated. Please don't update this file 9 | * directly; instead, make changes to your Workbox build configuration 10 | * and re-run your build process. 11 | * See https://goo.gl/2aRDsh 12 | */ 13 | 14 | importScripts("https://storage.googleapis.com/workbox-cdn/releases/3.6.3/workbox-sw.js"); 15 | 16 | importScripts( 17 | "./precache-manifest.4f7bfaaef02f289fea20afe32c695f26.js" 18 | ); 19 | 20 | workbox.clientsClaim(); 21 | 22 | /** 23 | * The workboxSW.precacheAndRoute() method efficiently caches and responds to 24 | * requests for URLs in the manifest. 25 | * See https://goo.gl/S9QRab 26 | */ 27 | self.__precacheManifest = [].concat(self.__precacheManifest || []); 28 | workbox.precaching.suppressWarnings(); 29 | workbox.precaching.precacheAndRoute(self.__precacheManifest, {}); 30 | 31 | workbox.routing.registerNavigationRoute("./index.html", { 32 | 33 | blacklist: [/^\/_/,/\/[^/]+\.[^/]+$/], 34 | }); 35 | -------------------------------------------------------------------------------- /build/static/css/2.20e21577.chunk.css: -------------------------------------------------------------------------------- 1 | .graphiql-container,.graphiql-container button,.graphiql-container input{color:#141823;font-family:system,-apple-system,San Francisco,\.SFNSDisplay-Regular,Segoe UI,Segoe,Segoe WP,Helvetica Neue,helvetica,Lucida Grande,arial,sans-serif;font-size:14px}.graphiql-container{display:flex;flex-direction:row;height:100%;margin:0;overflow:hidden;width:100%}.graphiql-container .editorWrap{display:flex;flex-direction:column;flex:1 1;overflow-x:hidden}.graphiql-container .title{font-size:18px}.graphiql-container .title em{font-family:georgia;font-size:19px}.graphiql-container .topBarWrap{display:flex;flex-direction:row}.graphiql-container .topBar{align-items:center;background:linear-gradient(#f7f7f7,#e2e2e2);border-bottom:1px solid #d0d0d0;cursor:default;display:flex;flex-direction:row;flex:1 1;height:34px;overflow-y:visible;padding:7px 14px 6px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.graphiql-container .toolbar{overflow-x:visible;display:flex}.graphiql-container .docExplorerShow,.graphiql-container .historyShow{background:linear-gradient(#f7f7f7,#e2e2e2);border-radius:0;border-bottom:1px solid #d0d0d0;border-right:none;border-top:none;color:#3b5998;cursor:pointer;font-size:14px;margin:0;padding:2px 20px 0 18px}.graphiql-container .docExplorerShow{border-left:1px solid rgba(0,0,0,.2)}.graphiql-container .historyShow{border-right:1px solid rgba(0,0,0,.2);border-left:0}.graphiql-container .docExplorerShow:before{border-left:2px solid #3b5998;border-top:2px solid #3b5998;content:"";display:inline-block;height:9px;margin:0 3px -1px 0;position:relative;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);width:9px}.graphiql-container .editorBar{display:flex;flex-direction:row;flex:1 1}.graphiql-container .queryWrap,.graphiql-container .resultWrap{display:flex;flex-direction:column;flex:1 1}.graphiql-container .resultWrap{border-left:1px solid #e0e0e0;flex-basis:1em;position:relative}.graphiql-container .docExplorerWrap,.graphiql-container .historyPaneWrap{background:#fff;box-shadow:0 0 8px rgba(0,0,0,.15);position:relative;z-index:3}.graphiql-container .historyPaneWrap{min-width:230px;z-index:5}.graphiql-container .docExplorerResizer{cursor:col-resize;height:100%;left:-5px;position:absolute;top:0;width:10px;z-index:10}.graphiql-container .docExplorerHide{cursor:pointer;font-size:18px;margin:-7px -8px -6px 0;padding:18px 16px 15px 12px;background:0;border:0;line-height:14px}.graphiql-container div .query-editor{flex:1 1;position:relative}.graphiql-container .variable-editor{display:flex;flex-direction:column;height:30px;position:relative}.graphiql-container .variable-editor-title{background:#eee;border-bottom:1px solid #d6d6d6;border-top:1px solid #e0e0e0;color:#777;-webkit-font-feature-settings:"c2sc";font-feature-settings:"c2sc";font-variant:small-caps;font-weight:700;letter-spacing:1px;line-height:14px;padding:6px 0 8px 43px;text-transform:lowercase;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.graphiql-container .codemirrorWrap,.graphiql-container .result-window{flex:1 1;height:100%;position:relative}.graphiql-container .footer{background:#f6f7f8;border-left:1px solid #e0e0e0;border-top:1px solid #e0e0e0;margin-left:12px;position:relative}.graphiql-container .footer:before{background:#eee;bottom:0;content:" ";left:-13px;position:absolute;top:-1px;width:12px}.result-window .CodeMirror{background:#f6f7f8}.graphiql-container .result-window .CodeMirror-gutters{background-color:#eee;border-color:#e0e0e0;cursor:col-resize}.graphiql-container .result-window .CodeMirror-foldgutter,.graphiql-container .result-window .CodeMirror-foldgutter-folded:after,.graphiql-container .result-window .CodeMirror-foldgutter-open:after{padding-left:3px}.graphiql-container .toolbar-button{background:#fdfdfd;background:linear-gradient(#f9f9f9,#ececec);border:0;border-radius:3px;box-shadow:inset 0 0 0 1px rgba(0,0,0,.2),0 1px 0 hsla(0,0%,100%,.7),inset 0 1px #fff;color:#555;cursor:pointer;display:inline-block;margin:0 5px;padding:3px 11px 5px;text-decoration:none;text-overflow:ellipsis;white-space:nowrap;max-width:150px}.graphiql-container .toolbar-button:active{background:linear-gradient(#ececec,#d5d5d5);box-shadow:0 1px 0 hsla(0,0%,100%,.7),inset 0 0 0 1px rgba(0,0,0,.1),inset 0 1px 1px 1px rgba(0,0,0,.12),inset 0 0 5px rgba(0,0,0,.1)}.graphiql-container .toolbar-button.error{background:linear-gradient(#fdf3f3,#e6d6d7);color:#b00}.graphiql-container .toolbar-button-group{margin:0 5px;white-space:nowrap}.graphiql-container .toolbar-button-group>*{margin:0}.graphiql-container .toolbar-button-group>:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.graphiql-container .toolbar-button-group>:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0;margin-left:-1px}.graphiql-container .execute-button-wrap{height:34px;margin:0 14px 0 28px;position:relative}.graphiql-container .execute-button{background:linear-gradient(#fdfdfd,#d2d3d6);border-radius:17px;border:1px solid rgba(0,0,0,.25);box-shadow:0 1px 0 #fff;cursor:pointer;fill:#444;height:34px;margin:0;padding:0;width:34px}.graphiql-container .execute-button svg{pointer-events:none}.graphiql-container .execute-button:active{background:linear-gradient(#e6e6e6,#c3c3c3);box-shadow:0 1px 0 #fff,inset 0 0 2px rgba(0,0,0,.2),inset 0 0 6px rgba(0,0,0,.1)}.graphiql-container .toolbar-menu,.graphiql-container .toolbar-select{position:relative}.graphiql-container .execute-options,.graphiql-container .toolbar-menu-items,.graphiql-container .toolbar-select-options{background:#fff;box-shadow:0 0 0 1px rgba(0,0,0,.1),0 2px 4px rgba(0,0,0,.25);margin:0;padding:6px 0;position:absolute;z-index:100}.graphiql-container .execute-options{min-width:100px;top:37px;left:-1px}.graphiql-container .toolbar-menu-items{left:1px;margin-top:-1px;min-width:110%;top:100%;visibility:hidden}.graphiql-container .toolbar-menu-items.open{visibility:visible}.graphiql-container .toolbar-select-options{left:0;min-width:100%;top:-5px;visibility:hidden}.graphiql-container .toolbar-select-options.open{visibility:visible}.graphiql-container .execute-options>li,.graphiql-container .toolbar-menu-items>li,.graphiql-container .toolbar-select-options>li{cursor:pointer;display:block;margin:none;max-width:300px;overflow:hidden;padding:2px 20px 4px 11px;white-space:nowrap}.graphiql-container .execute-options>li.selected,.graphiql-container .history-contents>li:active,.graphiql-container .history-contents>li:hover,.graphiql-container .toolbar-menu-items>li.hover,.graphiql-container .toolbar-menu-items>li:active,.graphiql-container .toolbar-menu-items>li:hover,.graphiql-container .toolbar-select-options>li.hover,.graphiql-container .toolbar-select-options>li:active,.graphiql-container .toolbar-select-options>li:hover{background:#e10098;color:#fff}.graphiql-container .toolbar-select-options>li>svg{display:inline;fill:#666;margin:0 -6px 0 6px;pointer-events:none;vertical-align:middle}.graphiql-container .toolbar-select-options>li.hover>svg,.graphiql-container .toolbar-select-options>li:active>svg,.graphiql-container .toolbar-select-options>li:hover>svg{fill:#fff}.graphiql-container .CodeMirror-scroll{overflow-scrolling:touch}.graphiql-container .CodeMirror{color:#141823;font-family:Consolas,Inconsolata,Droid Sans Mono,Monaco,monospace;font-size:13px;height:100%;left:0;position:absolute;top:0;width:100%}.graphiql-container .CodeMirror-lines{padding:20px 0}.CodeMirror-hint-information .content{box-orient:vertical;color:#141823;display:flex;font-family:system,-apple-system,San Francisco,\.SFNSDisplay-Regular,Segoe UI,Segoe,Segoe WP,Helvetica Neue,helvetica,Lucida Grande,arial,sans-serif;font-size:13px;line-clamp:3;line-height:16px;max-height:48px;overflow:hidden;text-overflow:-o-ellipsis-lastline}.CodeMirror-hint-information .content p:first-child{margin-top:0}.CodeMirror-hint-information .content p:last-child{margin-bottom:0}.CodeMirror-hint-information .infoType{color:#ca9800;cursor:pointer;display:inline;margin-right:.5em}.autoInsertedLeaf.cm-property{-webkit-animation-duration:6s;animation-duration:6s;-webkit-animation-name:insertionFade;animation-name:insertionFade;border-bottom:2px solid hsla(0,0%,100%,0);border-radius:2px;margin:-2px -4px -1px;padding:2px 4px 1px}@-webkit-keyframes insertionFade{0%,to{background:hsla(0,0%,100%,0);border-color:hsla(0,0%,100%,0)}15%,85%{background:#fbffc9;border-color:#f0f3c0}}@keyframes insertionFade{0%,to{background:hsla(0,0%,100%,0);border-color:hsla(0,0%,100%,0)}15%,85%{background:#fbffc9;border-color:#f0f3c0}}div.CodeMirror-lint-tooltip{background-color:#fff;border-radius:2px;border:0;color:#141823;box-shadow:0 1px 3px rgba(0,0,0,.45);font-size:13px;line-height:16px;max-width:430px;opacity:0;padding:8px 10px;transition:opacity .15s;white-space:pre-wrap}div.CodeMirror-lint-tooltip>*{padding-left:23px}div.CodeMirror-lint-tooltip>*+*{margin-top:12px}.graphiql-container .CodeMirror-foldmarker{border-radius:4px;background:#08f;background:linear-gradient(#43a8ff,#0f83e8);box-shadow:0 1px 1px rgba(0,0,0,.2),inset 0 0 0 1px rgba(0,0,0,.1);color:#fff;font-family:arial;font-size:12px;line-height:0;margin:0 3px;padding:0 4px 1px;text-shadow:0 -1px rgba(0,0,0,.1)}.graphiql-container div.CodeMirror span.CodeMirror-matchingbracket{color:#555;text-decoration:underline}.graphiql-container div.CodeMirror span.CodeMirror-nonmatchingbracket{color:red}.cm-comment{color:#999}.cm-punctuation{color:#555}.cm-keyword{color:#b11a04}.cm-def{color:#d2054e}.cm-property{color:#1f61a0}.cm-qualifier{color:#1c92a9}.cm-attribute{color:#8b2bb9}.cm-number{color:#2882f9}.cm-string{color:#d64292}.cm-builtin{color:#d47509}.cm-string-2{color:#0b7fc7}.cm-variable{color:#397d13}.cm-meta{color:#b33086}.cm-atom{color:#ca9800}.CodeMirror{color:#000;font-family:monospace;height:300px}.CodeMirror-lines{padding:4px 0}.CodeMirror pre{padding:0 4px}.CodeMirror-gutter-filler,.CodeMirror-scrollbar-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{color:#999;min-width:20px;padding:0 3px 0 5px;text-align:right;white-space:nowrap}.CodeMirror-guttermarker{color:#000}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror .CodeMirror-cursor{border-left:1px solid #000}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.CodeMirror.cm-fat-cursor div.CodeMirror-cursor{background:#7e7;border:0;width:auto}.CodeMirror.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-animate-fat-cursor{-webkit-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite;border:0;width:auto}@-webkit-keyframes blink{0%{background:#7e7}50%{background:none}to{background:#7e7}}@keyframes blink{0%{background:#7e7}50%{background:none}to{background:#7e7}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-ruler{border-left:1px solid #ccc;position:absolute}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-variable-3{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta,.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-header{color:#00f}.cm-s-default .cm-quote{color:#090}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:700}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-invalidchar,.cm-s-default .cm-error{color:red}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0f0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#f22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{background:#fff;overflow:hidden;position:relative}.CodeMirror-scroll{height:100%;margin-bottom:-30px;margin-right:-30px;outline:none;overflow:scroll!important;padding-bottom:30px;position:relative}.CodeMirror-sizer{border-right:30px solid transparent;position:relative}.CodeMirror-gutter-filler,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-vscrollbar{display:none;position:absolute;z-index:6}.CodeMirror-vscrollbar{overflow-x:hidden;overflow-y:scroll;right:0;top:0}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-x:scroll;overflow-y:hidden}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{min-height:100%;position:absolute;left:0;top:0;z-index:3}.CodeMirror-gutter{display:inline-block;height:100%;margin-bottom:-30px;vertical-align:top;white-space:normal;*zoom:1;*display:inline}.CodeMirror-gutter-wrapper{background:none!important;border:none!important;position:absolute;z-index:4}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{cursor:default;position:absolute;z-index:4}.CodeMirror-gutter-wrapper{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre{-webkit-tap-highlight-color:transparent;background:transparent;border-radius:0;border-width:0;color:inherit;font-family:inherit;font-size:inherit;-webkit-font-feature-settings:none;font-feature-settings:none;-webkit-font-variant-ligatures:none;font-variant-ligatures:none;line-height:inherit;margin:0;overflow:visible;position:relative;white-space:pre;word-wrap:normal;z-index:2}.CodeMirror-wrap pre{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{overflow:auto;position:relative;z-index:2}.CodeMirror-code{outline:none}.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber,.CodeMirror-scroll,.CodeMirror-sizer{box-sizing:content-box}.CodeMirror-measure{height:0;overflow:hidden;position:absolute;visibility:hidden;width:100%}.CodeMirror-cursor{position:absolute}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{position:relative;visibility:hidden;z-index:3}.CodeMirror-focused div.CodeMirror-cursors,div.CodeMirror-dragcursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background:#ffa;background:rgba(255,255,0,.4)}.CodeMirror span{*vertical-align:text-bottom}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:""}span.CodeMirror-selectedtext{background:none}.CodeMirror-dialog{background:inherit;color:inherit;left:0;right:0;overflow:hidden;padding:.1em .8em;position:absolute;z-index:15}.CodeMirror-dialog-top{border-bottom:1px solid #eee;top:0}.CodeMirror-dialog-bottom{border-top:1px solid #eee;bottom:0}.CodeMirror-dialog input{background:transparent;border:1px solid #d3d6db;color:inherit;font-family:monospace;outline:none;width:20em}.CodeMirror-dialog button{font-size:70%}.CodeMirror-foldmarker{color:#00f;cursor:pointer;font-family:arial;line-height:.3;text-shadow:#b9f 1px 1px 2px,#b9f -1px -1px 2px,#b9f 1px -1px 2px,#b9f -1px 1px 2px}.CodeMirror-foldgutter{width:.7em}.CodeMirror-foldgutter-folded,.CodeMirror-foldgutter-open{cursor:pointer}.CodeMirror-foldgutter-open:after{content:"\25BE"}.CodeMirror-foldgutter-folded:after{content:"\25B8"}.CodeMirror-info{background:#fff;border-radius:2px;box-shadow:0 1px 3px rgba(0,0,0,.45);box-sizing:border-box;color:#555;font-family:system,-apple-system,San Francisco,\.SFNSDisplay-Regular,Segoe UI,Segoe,Segoe WP,Helvetica Neue,helvetica,Lucida Grande,arial,sans-serif;font-size:13px;line-height:16px;margin:8px -8px;max-width:400px;opacity:0;overflow:hidden;padding:8px;position:fixed;transition:opacity .15s;z-index:50}.CodeMirror-info :first-child{margin-top:0}.CodeMirror-info :last-child{margin-bottom:0}.CodeMirror-info p{margin:1em 0}.CodeMirror-info .info-description{color:#777;line-height:16px;margin-top:1em;max-height:80px;overflow:hidden}.CodeMirror-info .info-deprecation{background:#fffae8;box-shadow:inset 0 1px 1px -1px #bfb063;color:#867f70;line-height:16px;margin:8px -8px -8px;max-height:80px;overflow:hidden;padding:8px}.CodeMirror-info .info-deprecation-label{color:#c79b2e;cursor:default;display:block;font-size:9px;font-weight:700;letter-spacing:1px;line-height:1;padding-bottom:5px;text-transform:uppercase;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.CodeMirror-info .info-deprecation-label+*{margin-top:0}.CodeMirror-info a{text-decoration:none}.CodeMirror-info a:hover{text-decoration:underline}.CodeMirror-info .type-name{color:#ca9800}.CodeMirror-info .field-name{color:#1f61a0}.CodeMirror-info .enum-value{color:#0b7fc7}.CodeMirror-info .arg-name{color:#8b2bb9}.CodeMirror-info .directive-name{color:#b33086}.CodeMirror-jump-token{text-decoration:underline;cursor:pointer}.CodeMirror-lint-markers{width:16px}.CodeMirror-lint-tooltip{background-color:infobackground;border-radius:4px 4px 4px 4px;border:1px solid #000;color:infotext;font-family:monospace;font-size:10pt;max-width:600px;opacity:0;overflow:hidden;padding:2px 5px;position:fixed;transition:opacity .4s;white-space:pre-wrap;z-index:100}.CodeMirror-lint-mark-error,.CodeMirror-lint-mark-warning{background-position:0 100%;background-repeat:repeat-x}.CodeMirror-lint-mark-error{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==")}.CodeMirror-lint-mark-warning{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII=")}.CodeMirror-lint-marker-error,.CodeMirror-lint-marker-warning{background-position:50%;background-repeat:no-repeat;cursor:pointer;display:inline-block;height:16px;position:relative;vertical-align:middle;width:16px}.CodeMirror-lint-message-error,.CodeMirror-lint-message-warning{background-position:0 0;background-repeat:no-repeat;padding-left:18px}.CodeMirror-lint-marker-error,.CodeMirror-lint-message-error{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII=")}.CodeMirror-lint-marker-warning,.CodeMirror-lint-message-warning{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII=")}.CodeMirror-lint-marker-multiple{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAMAAADzjKfhAAAACVBMVEUAAAAAAAC/v7914kyHAAAAAXRSTlMAQObYZgAAACNJREFUeNo1ioEJAAAIwmz/H90iFFSGJgFMe3gaLZ0od+9/AQZ0ADosbYraAAAAAElFTkSuQmCC");background-position:100% 100%;background-repeat:no-repeat;width:100%;height:100%}.graphiql-container .spinner-container{height:36px;left:50%;position:absolute;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);width:36px;z-index:10}.graphiql-container .spinner{-webkit-animation:rotation .6s linear infinite;animation:rotation .6s linear infinite;border-radius:100%;border:6px solid hsla(0,0%,58.8%,.15);border-top-color:hsla(0,0%,58.8%,.8);display:inline-block;height:24px;position:absolute;vertical-align:middle;width:24px}@-webkit-keyframes rotation{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes rotation{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.CodeMirror-hints{background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.45);font-family:Consolas,Inconsolata,Droid Sans Mono,Monaco,monospace;font-size:13px;list-style:none;margin:0;max-height:14.5em;overflow:hidden;overflow-y:auto;padding:0;position:absolute;z-index:10}.CodeMirror-hint{border-top:1px solid #f7f7f7;color:#141823;cursor:pointer;margin:0;max-width:300px;overflow:hidden;padding:2px 6px;white-space:pre}li.CodeMirror-hint-active{background-color:#08f;border-top-color:#fff;color:#fff}.CodeMirror-hint-information{border-top:1px solid silver;max-width:300px;padding:4px 6px;position:relative;z-index:1}.CodeMirror-hint-information:first-child{border-bottom:1px solid silver;border-top:none;margin-bottom:-1px}.CodeMirror-hint-deprecation{background:#fffae8;box-shadow:inset 0 1px 1px -1px #bfb063;color:#867f70;font-family:system,-apple-system,San Francisco,\.SFNSDisplay-Regular,Segoe UI,Segoe,Segoe WP,Helvetica Neue,helvetica,Lucida Grande,arial,sans-serif;font-size:13px;line-height:16px;margin-top:4px;max-height:80px;overflow:hidden;padding:6px}.CodeMirror-hint-deprecation .deprecation-label{color:#c79b2e;cursor:default;display:block;font-size:9px;font-weight:700;letter-spacing:1px;line-height:1;padding-bottom:5px;text-transform:uppercase;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.CodeMirror-hint-deprecation .deprecation-label+*{margin-top:0}.CodeMirror-hint-deprecation :last-child{margin-bottom:0}.graphiql-container .doc-explorer{background:#fff}.graphiql-container .doc-explorer-title-bar,.graphiql-container .history-title-bar{cursor:default;display:flex;height:34px;line-height:14px;padding:8px 8px 5px;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.graphiql-container .doc-explorer-title,.graphiql-container .history-title{flex:1 1;font-weight:700;overflow-x:hidden;padding:10px 0 10px 10px;text-align:center;text-overflow:ellipsis;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text;white-space:nowrap}.graphiql-container .doc-explorer-back{color:#3b5998;cursor:pointer;margin:-7px 0 -6px -8px;overflow-x:hidden;padding:17px 12px 16px 16px;text-overflow:ellipsis;white-space:nowrap;background:0;border:0;line-height:14px}.doc-explorer-narrow .doc-explorer-back{width:0}.graphiql-container .doc-explorer-back:before{border-left:2px solid #3b5998;border-top:2px solid #3b5998;content:"";display:inline-block;height:9px;margin:0 3px -1px 0;position:relative;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);width:9px}.graphiql-container .doc-explorer-rhs{position:relative}.graphiql-container .doc-explorer-contents,.graphiql-container .history-contents{background-color:#fff;border-top:1px solid #d6d6d6;bottom:0;left:0;overflow-y:auto;padding:20px 15px;position:absolute;right:0;top:47px}.graphiql-container .doc-explorer-contents{min-width:300px}.graphiql-container .doc-type-description blockquote:first-child,.graphiql-container .doc-type-description p:first-child{margin-top:0}.graphiql-container .doc-explorer-contents a{cursor:pointer;text-decoration:none}.graphiql-container .doc-explorer-contents a:hover{text-decoration:underline}.graphiql-container .doc-value-description>:first-child{margin-top:4px}.graphiql-container .doc-value-description>:last-child{margin-bottom:4px}.graphiql-container .doc-category code,.graphiql-container .doc-category pre,.graphiql-container .doc-type-description code,.graphiql-container .doc-type-description pre{--saf-0:rgba(var(--sk_foreground_low,29,28,29),0.13);font-size:12px;line-height:1.50001;-webkit-font-feature-settings:none;font-feature-settings:none;-webkit-font-variant-ligatures:none;font-variant-ligatures:none;white-space:pre;white-space:pre-wrap;word-wrap:break-word;word-break:normal;-webkit-tab-size:4;-moz-tab-size:4;tab-size:4}.graphiql-container .doc-category code,.graphiql-container .doc-type-description code{padding:2px 3px 1px;border:1px solid var(--saf-0);border-radius:3px;background-color:rgba(29,28,29,.04);background-color:rgba(var(--sk_foreground_min,29,28,29),.04);color:#e01e5a;background-color:#fff}.graphiql-container .doc-category{margin:20px 0}.graphiql-container .doc-category-title{border-bottom:1px solid #e0e0e0;color:#777;cursor:default;font-size:14px;-webkit-font-feature-settings:"c2sc";font-feature-settings:"c2sc";font-variant:small-caps;font-weight:700;letter-spacing:1px;margin:0 -15px 10px 0;padding:10px 0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.graphiql-container .doc-category-item{margin:12px 0;color:#555}.graphiql-container .keyword{color:#b11a04}.graphiql-container .type-name{color:#ca9800}.graphiql-container .field-name{color:#1f61a0}.graphiql-container .field-short-description{color:#999;margin-left:5px;overflow:hidden;text-overflow:ellipsis}.graphiql-container .enum-value{color:#0b7fc7}.graphiql-container .arg-name{color:#8b2bb9}.graphiql-container .arg{display:block;margin-left:1em}.graphiql-container .arg:first-child:last-child,.graphiql-container .arg:first-child:nth-last-child(2),.graphiql-container .arg:first-child:nth-last-child(2)~.arg{display:inherit;margin:inherit}.graphiql-container .arg:first-child:nth-last-child(2):after{content:", "}.graphiql-container .arg-default-value{color:#43a047}.graphiql-container .doc-deprecation{background:#fffae8;box-shadow:inset 0 0 1px #bfb063;color:#867f70;line-height:16px;margin:8px -8px;max-height:80px;overflow:hidden;padding:8px;border-radius:3px}.graphiql-container .doc-deprecation:before{content:"Deprecated:";color:#c79b2e;cursor:default;display:block;font-size:9px;font-weight:700;letter-spacing:1px;line-height:1;padding-bottom:5px;text-transform:uppercase;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.graphiql-container .doc-deprecation>:first-child{margin-top:0}.graphiql-container .doc-deprecation>:last-child{margin-bottom:0}.graphiql-container .show-btn{-webkit-appearance:initial;display:block;border-radius:3px;border:1px solid #ccc;text-align:center;padding:8px 12px 10px;width:100%;box-sizing:border-box;background:#fbfcfc;color:#555;cursor:pointer}.graphiql-container .search-box{border-bottom:1px solid #d3d6db;display:block;font-size:14px;margin:-15px -15px 12px 0;position:relative}.graphiql-container .search-box-icon{display:block;font-size:24px;top:-2px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.graphiql-container .search-box-icon,.graphiql-container .search-box .search-box-clear{cursor:pointer;position:absolute;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.graphiql-container .search-box .search-box-clear{background-color:#d0d0d0;border-radius:12px;color:#fff;font-size:11px;padding:1px 5px 2px;right:3px;top:8px;border:0}.graphiql-container .search-box .search-box-clear:hover{background-color:#b9b9b9}.graphiql-container .search-box>input{border:none;box-sizing:border-box;font-size:14px;outline:none;padding:6px 24px 8px 20px;width:100%}.graphiql-container .error-container{font-weight:700;left:0;letter-spacing:1px;opacity:.5;position:absolute;right:0;text-align:center;text-transform:uppercase;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.graphiql-container .history-contents{font-family:Consolas,Inconsolata,Droid Sans Mono,Monaco,monospace;margin:0;padding:0}.graphiql-container .history-contents li{align-items:center;display:flex;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin:0;padding:8px;border-bottom:1px solid #e0e0e0}.graphiql-container .history-contents li button:not(.history-label){display:none;margin-left:10px}.graphiql-container .history-contents li:focus-within button:not(.history-label),.graphiql-container .history-contents li:hover button:not(.history-label){display:inline-block}.graphiql-container .history-contents button,.graphiql-container .history-contents input{padding:0;background:0;border:0;font-size:inherit;font-family:inherit;line-height:14px;color:inherit}.graphiql-container .history-contents input{flex-grow:1}.graphiql-container .history-contents input::-webkit-input-placeholder{color:inherit}.graphiql-container .history-contents input::-ms-input-placeholder{color:inherit}.graphiql-container .history-contents input::placeholder{color:inherit}.graphiql-container .history-contents button{cursor:pointer;text-align:left}.graphiql-container .history-contents .history-label{flex-grow:1;overflow:hidden;text-overflow:ellipsis} 2 | /*# sourceMappingURL=2.20e21577.chunk.css.map */ -------------------------------------------------------------------------------- /build/static/css/main.29d4883d.chunk.css: -------------------------------------------------------------------------------- 1 | #root{height:100vh}body{margin:0;padding:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;min-height:100vh}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}.landing-page{display:flex}.welcome-message{display:flex;flex-direction:column;background-image:url(data:image/png;base64,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),radial-gradient(circle at center center,#00588c 5%,#16292b 80%);flex-grow:1;justify-content:space-between;align-items:center;height:100vh}.center-white-text{color:#fff;text-align:center;font-size:1.86rem}.larger-font-size{font-size:2.086rem}.bold-text{font-weight:600}.bottom-white-small-text{color:#fff;font-size:1.143rem;margin-bottom:2.286rem}.thin-text{font-weight:200}.login{flex-grow:0;flex-basis:38.857rem;align-items:center}.login-text{font-weight:100;font-size:1.986rem}.error-text,.login-text{color:#16292b;margin-bottom:1.023rem}.error-text{font-weight:400;font-size:1.286rem;text-align:center}.flex-container{height:85%;display:flex;align-items:center;justify-content:center}.flex-row{width:85%}.display-flex-justify{display:flex!important;justify-content:center!important}.primary-button{border-radius:.286rem;line-height:.23;color:#fff;background-color:#0086c0;border-color:#0086c0;box-shadow:none;display:inline-block;width:100%;margin-top:20px;box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12)}.primary-button:hover{background-color:#18b8e9;border-color:#18b8e9}.btn-row{display:flex}.btn-column{flex:33.33% 1;padding:5px}h3{font-weight:200;font-size:1.0775rem;font-family:Open Sans,sans-serif;text-transform:uppercase}.hide{display:none}a:link{color:#000;font-weight:100;color:#16292b;font-size:.986rem;margin-top:1.023rem;text-decoration:none}.bottom-right{position:fixed;bottom:0;right:0;margin-bottom:1.023rem;margin-right:1.023rem} 2 | /*# sourceMappingURL=main.29d4883d.chunk.css.map */ -------------------------------------------------------------------------------- /build/static/css/main.29d4883d.chunk.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["/Users/drewrussell/Development/graphql-playground/src/index.css","main.29d4883d.chunk.css","/Users/drewrussell/Development/graphql-playground/src/components/LandingPage.css"],"names":[],"mappings":"AAAA,MACE,YCCF,CDEA,KACE,QAAA,CACA,SAAA,CACA,mICEY,CDCZ,kCAAA,CACA,iCAAA,CACA,gBCCF,CDEA,KACE,uECEF,CClBA,cACE,YDqBF,CCnBA,iBACE,YAAA,CACA,qBAAA,CACA,wgLDyBG,CCnBH,WAAA,CACA,6BAAA,CAEA,kBAAA,CACA,YDqBF,CClBA,mBACE,UAAA,CACA,iBAAA,CACA,iBDqBF,CClBA,kBACE,kBDqBF,CClBA,WACE,eDqBF,CClBA,yBACE,UAAA,CACA,kBAAA,CACA,sBDqBF,CClBA,WACE,eDqBF,CClBA,OAEE,WAAA,CACA,oBAAA,CACA,kBDoBF,CCjBA,YACE,eAAA,CAEA,kBDqBF,CCjBA,wBALE,aAAA,CAEA,sBD4BF,CCzBA,YACE,eAAA,CAEA,kBAAA,CAEA,iBDoBF,CCjBA,gBACE,UAAA,CAKA,YAAA,CACA,kBAAA,CACA,sBDgBF,CCdA,UACE,SDgBF,CCbA,sBACE,sBAAA,CACA,gCDgBF,CCbA,gBACE,qBAAA,CACA,eAAA,CACA,UAAA,CACA,wBAAA,CACA,oBAAA,CAEA,eAAA,CACA,oBAAA,CACA,UAAA,CACA,eAAA,CACA,gGDiBF,CCbA,sBACE,wBAAA,CACA,oBDgBF,CCbA,SACE,YDgBF,CCbA,YACE,aAAA,CACA,WDgBF,CCbA,GACE,eAAA,CACA,mBAAA,CACA,gCAAA,CACA,wBDgBF,CCbA,MACE,YDgBF,CCbA,OACE,UAAA,CACA,eAAA,CACA,aAAA,CACA,iBAAA,CACA,mBAAA,CACA,oBDgBF,CCbA,cACE,cAAA,CACA,QAAA,CACA,OAAA,CACA,sBAAA,CACA,qBDgBF","file":"main.29d4883d.chunk.css","sourcesContent":["#root {\n height: 100vh;\n}\n\nbody {\n margin: 0;\n padding: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Oxygen\",\n \"Ubuntu\", \"Cantarell\", \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\",\n sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n min-height: 100vh;\n}\n\ncode {\n font-family: source-code-pro, Menlo, Monaco, Consolas, \"Courier New\",\n monospace;\n}\n","#root {\n height: 100vh;\n}\n\nbody {\n margin: 0;\n padding: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Oxygen\",\n \"Ubuntu\", \"Cantarell\", \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\",\n sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n min-height: 100vh;\n}\n\ncode {\n font-family: source-code-pro, Menlo, Monaco, Consolas, \"Courier New\",\n monospace;\n}\n\n.landing-page {\n display: flex;\n}\n.welcome-message {\n display: flex;\n flex-direction: column;\n background-image: url(data:image/png;base64,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),\n radial-gradient(\n circle at center center,\n rgb(0, 88, 140) 5%,\n rgb(22, 41, 43) 80%\n );\n flex-grow: 1;\n justify-content: space-between;\n\n align-items: center;\n height: 100vh;\n}\n\n.center-white-text {\n color: rgb(255, 255, 255);\n text-align: center;\n font-size: 1.86rem;\n}\n\n.larger-font-size {\n font-size: 2.086rem;\n}\n\n.bold-text {\n font-weight: 600;\n}\n\n.bottom-white-small-text {\n color: rgb(255, 255, 255);\n font-size: 1.143rem;\n margin-bottom: 2.286rem;\n}\n\n.thin-text {\n font-weight: 200;\n}\n\n.login {\n flex-grow: 0;\n flex-basis: 38.857rem;\n align-items: center;\n}\n\n.login-text {\n font-weight: 100;\n color: rgb(22, 41, 43);\n font-size: 1.986rem;\n margin-bottom: 1.023rem;\n}\n\n.error-text {\n font-weight: 400;\n color: rgb(22, 41, 43);\n font-size: 1.286rem;\n margin-bottom: 1.023rem;\n text-align: center;\n}\n\n.flex-container {\n height: 85%;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.flex-row {\n width: 85%;\n}\n\n.display-flex-justify {\n display: flex !important;\n justify-content: center !important;\n}\n\n.primary-button {\n border-radius: 0.286rem;\n line-height: 0.23;\n color: #fff;\n background-color: rgb(0, 134, 192);\n border-color: rgb(0, 134, 192);\n\n box-shadow: none;\n display: inline-block;\n width: 100%;\n margin-top: 20px;\n box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2),\n 0 1px 5px 0 rgba(0, 0, 0, 0.12);\n}\n\n.primary-button:hover {\n background-color: #18b8e9;\n border-color: #18b8e9;\n}\n\n.btn-row {\n display: flex;\n}\n\n.btn-column {\n flex: 33.33% 1;\n padding: 5px;\n}\n\nh3 {\n font-weight: 200;\n font-size: 1.0775rem;\n font-family: \"Open Sans\", sans-serif;\n text-transform: uppercase;\n}\n\n.hide {\n display: none;\n}\n\na:link {\n color: black;\n font-weight: 100;\n color: rgb(22, 41, 43);\n font-size: 0.986rem;\n margin-top: 1.023rem;\n text-decoration: none;\n}\n\n.bottom-right {\n position: fixed;\n bottom: 0;\n right: 0;\n margin-bottom: 1.023rem;\n margin-right: 1.023rem;\n}\n\n",".landing-page {\n display: flex;\n}\n.welcome-message {\n display: flex;\n flex-direction: column;\n background-image: url(\"../images/pattern.png\"),\n radial-gradient(\n circle at center center,\n rgb(0, 88, 140) 5%,\n rgb(22, 41, 43) 80%\n );\n flex-grow: 1;\n justify-content: space-between;\n\n align-items: center;\n height: 100vh;\n}\n\n.center-white-text {\n color: rgb(255, 255, 255);\n text-align: center;\n font-size: 1.86rem;\n}\n\n.larger-font-size {\n font-size: 2.086rem;\n}\n\n.bold-text {\n font-weight: 600;\n}\n\n.bottom-white-small-text {\n color: rgb(255, 255, 255);\n font-size: 1.143rem;\n margin-bottom: 2.286rem;\n}\n\n.thin-text {\n font-weight: 200;\n}\n\n.login {\n -webkit-box-flex: 0;\n flex-grow: 0;\n flex-basis: 38.857rem;\n align-items: center;\n}\n\n.login-text {\n font-weight: 100;\n color: rgb(22, 41, 43);\n font-size: 1.986rem;\n margin-bottom: 1.023rem;\n}\n\n.error-text {\n font-weight: 400;\n color: rgb(22, 41, 43);\n font-size: 1.286rem;\n margin-bottom: 1.023rem;\n text-align: center;\n}\n\n.flex-container {\n height: 85%;\n display: -webkit-box;\n display: -moz-box;\n display: -ms-flexbox;\n display: -webkit-flex;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.flex-row {\n width: 85%;\n}\n\n.display-flex-justify {\n display: flex !important;\n justify-content: center !important;\n}\n\n.primary-button {\n border-radius: 0.286rem;\n line-height: 0.23;\n color: #fff;\n background-color: rgb(0, 134, 192);\n border-color: rgb(0, 134, 192);\n\n box-shadow: none;\n display: inline-block;\n width: 100%;\n margin-top: 20px;\n box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2),\n 0 1px 5px 0 rgba(0, 0, 0, 0.12);\n}\n\n.primary-button:hover {\n background-color: #18b8e9;\n border-color: #18b8e9;\n}\n\n.btn-row {\n display: flex;\n}\n\n.btn-column {\n flex: 33.33%;\n padding: 5px;\n}\n\nh3 {\n font-weight: 200;\n font-size: 1.0775rem;\n font-family: \"Open Sans\", sans-serif;\n text-transform: uppercase;\n}\n\n.hide {\n display: none;\n}\n\na:link {\n color: black;\n font-weight: 100;\n color: rgb(22, 41, 43);\n font-size: 0.986rem;\n margin-top: 1.023rem;\n text-decoration: none;\n}\n\n.bottom-right {\n position: fixed;\n bottom: 0;\n right: 0;\n margin-bottom: 1.023rem;\n margin-right: 1.023rem;\n}\n"]} -------------------------------------------------------------------------------- /build/static/js/main.e15b519c.chunk.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[0],{140:function(e,t,a){e.exports=a.p+"static/media/rubrikLogo.b5f40d5b.svg"},147:function(e,t){e.exports=require("https")},168:function(e,t,a){},220:function(e,t,a){e.exports=a(362)},225:function(e,t,a){},311:function(e,t){e.exports=require("punycode")},319:function(e,t,a){var n={"./Range.js":79,"./file.js":99,"./getASTNodeAtPosition.js":98,"./index.js":35,"./validateWithCustomRules.js":115};function r(e){var t=o(e);return a(t)}function o(e){var t=n[e];if(!(t+1)){var a=new Error("Cannot find module '"+e+"'");throw a.code="MODULE_NOT_FOUND",a}return t}r.keys=function(){return Object.keys(n)},r.resolve=o,e.exports=r,r.id=319},320:function(e,t){function a(e){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}a.keys=function(){return[]},a.resolve=a,e.exports=a,a.id=320},321:function(e,t,a){var n={"./Range.js":[79],"./file.js":[99],"./getASTNodeAtPosition.js":[98],"./index.js":[35],"./validateWithCustomRules.js":[115]};function r(e){var t=n[e];return t?Promise.all(t.slice(1).map(a.e)).then(function(){var e=t[0];return a(e)}):Promise.resolve().then(function(){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t})}r.keys=function(){return Object.keys(n)},r.id=321,e.exports=r},322:function(e,t){function a(e){return Promise.resolve().then(function(){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t})}a.keys=function(){return[]},a.resolve=a,e.exports=a,a.id=322},362:function(e,t,a){"use strict";a.r(t);var n=a(0),r=a.n(n),o=a(25),s=a.n(o),i=(a(225),a(57)),l=a(42),c=a(93),u=a(88),p=a(94),m=a(26),d=a(139),h=a(24),f=a.n(h),g=a(50),b=(a(168),a(140)),v=a.n(b),w=a(400),k=a(393),E=a(398),y=a(397),j=Object(k.a)(function(e){return{root:{"& .MuiTextField-root":{margin:e.spacing(1),width:"100%"}}}}),O=Object(k.a)(function(e){return{root:{"& > *":{backgroundColor:"#FFF","&:hover":{backgroundColor:"#FFF"},width:"100%",textTransform:"none","font-weight":100,"font-size":" 1.0775rem"}}}}),x=Object(k.a)(function(e){return{root:{"& > *":{margin:e.spacing(1),width:"100%","&:hover":{"background-color":"#18b8e9","border-color":"#18b8e9"},"border-radius":"0.286rem","line-height":" 1.83",color:"#fff","background-color":"rgb(0, 134, 192)","border-color":"rgb(0, 134, 192)",display:"inline-block","margin-top":"20px","font-weight":200,"font-size":"1.0775rem","text-transform":"uppercase","box-shadow":"0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12)"}}}});function L(e){var t=j(),a=O(),n=x();return r.a.createElement("form",{className:t.root,noValidate:!0,autoComplete:"off"},r.a.createElement("div",null,r.a.createElement(w.a,{autoFocus:!0,error:null!==e.ip&&""===e.ip,required:!0,id:"ip",label:"cdm"===e.platform?"CDM IP or FQDN":"Polaris Domain",onChange:e.onChange,InputProps:"cdm"===e.platform?null:{endAdornment:r.a.createElement(y.a,{position:"end"},e.polarisDomain)}}),r.a.createElement(w.a,{required:!0,id:"username",label:"Username",onChange:e.onChange,error:null!==e.username&&""===e.username}),r.a.createElement(w.a,{required:!0,id:"password",label:"Password",type:"password",onChange:e.onChange,error:null!==e.password&&""===e.password})),r.a.createElement("div",{className:n.root},r.a.createElement(E.a,{color:"primary",variant:"contained",onClick:e.loginButton,disabled:null===e.ip||null===e.username||null===e.password||null!==e.ip&&e.ip.length<=0||null!==e.username&&e.username.length<=0||null!==e.password&&e.password.length<=0||"Login"!==e.loginButtonText||void 0},e.loginButtonText)),r.a.createElement("div",{className:a.root},r.a.createElement(E.a,{onClick:e.selectYourPlatform},"cdm"===e.platform?"Switch to Polaris":"Switch to CDM")))}var C=a(207),N=a.n(C),D=a(147),T=a.n(D),S={"Content-Type":"application/json","User-Agent":"RubrikGraphQLPlayground"};function P(e){return e.replace("https://","").replace(".my.rubrik.com","").replace("/","")}function B(e){try{console.log(e.response)}catch(e){console.log("No additional error detail")}return e.response?401===e.response.status||422===e.response.status?"Sorry, you entered an incorrect email or password.":400===e.response.status||401===e.response.status?"Sorry, the request was rejected as malformed by the Rubrik platform.":"Sorry, the request was rejected with a ".concat(e.response.status," (").concat(e.response.data.message,") HTTP response status code."):e.message.includes("getaddrinfo ENOTFOUND")||e.message.includes("Network Error")?"Sorry, we were unable to connect to the provided Rubrik platform.":e.message.includes("connect ETIMEDOUT")||e.message.includes("timeout of 15000ms exceeded")?"Sorry, the connection to the Rubrik platform timeout and we were unable to connect.":e.message}function F(e,t,a){return M.apply(this,arguments)}function M(){return(M=Object(g.a)(f.a.mark(function e(t,a,n){var r,o;return f.a.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return console.log("rubrikApiPost"),console.log(a),console.log(n),r=N.a.create({timeout:15e3,httpsAgent:new T.a.Agent({rejectUnauthorized:!1})}),e.next=6,r({method:"post",url:t,headers:a,data:n});case 6:return o=e.sent,e.abrupt("return",o);case 8:case"end":return e.stop()}},e)}))).apply(this,arguments)}function U(e,t,a,n,r){return R.apply(this,arguments)}function R(){return(R=Object(g.a)(f.a.mark(function e(t,a,n,r,o){var s,i,l,c,u,p;return f.a.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return s=S,"cdm"===t?(s.Authorization="Basic "+btoa(n+":"+r),i="/api/v1/session",l={}):(s.Accept="application/json, text/plain",s["Content-Type"]="application/json;charset=UTF-8",i="".concat(o,"/api/session"),l={username:n,password:r}),console.log(s),c=P(a),console.log(c),console.log(i),u="https://".concat(c).concat(i),console.log(u),e.next=10,F(u,s,l);case 10:if(p=e.sent,"cdm"!==t){e.next=15;break}return e.abrupt("return",p.data.token);case 15:return e.abrupt("return",p.data.access_token);case 16:case"end":return e.stop()}},e)}))).apply(this,arguments)}var A=a(209),I=a.n(A),q=a(208),_=a.n(q),z=a(399),H=a(401),W=a(13),Y=a(363),J="Select your Platform",G="Login",Q=".my.rubrik.com",V=function(e){function t(e){var a;return Object(i.a)(this,t),(a=Object(c.a)(this,Object(u.a)(t).call(this,e))).state={formHeader:J,platform:null,loginButtonText:G,loginErrorMessage:null,apiToken:null,ip:null,username:null,password:null,polarisDomain:Q},a.createLoginForm=a.createLoginForm.bind(Object(m.a)(Object(m.a)(a))),a.handleSwitchToLogin=a.handleSwitchToLogin.bind(Object(m.a)(Object(m.a)(a))),a.handleSelectYourPlatform=a.handleSelectYourPlatform.bind(Object(m.a)(Object(m.a)(a))),a.onChange=a.onChange.bind(Object(m.a)(Object(m.a)(a))),a.handleLoginButton=a.handleLoginButton.bind(Object(m.a)(Object(m.a)(a))),a.createLoginHeader=a.createLoginHeader.bind(Object(m.a)(Object(m.a)(a))),a.createDevModeIcon=a.createDevModeIcon.bind(Object(m.a)(Object(m.a)(a))),a.handleModeButton=a.handleModeButton.bind(Object(m.a)(Object(m.a)(a))),a}return Object(p.a)(t,e),Object(l.a)(t,[{key:"handleSwitchToLogin",value:function(e){e.preventDefault(),this.setState({platform:e.target.textContent.toLowerCase(),formHeader:G})}},{key:"handleLoginButton",value:function(){var e=Object(g.a)(f.a.mark(function e(t){var a;return f.a.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return this.setState({loginButtonText:"Attempting to Connect",loginErrorMessage:null}),e.prev=1,e.next=4,U(this.state.platform,this.state.ip,this.state.username,this.state.password,this.state.polarisDomain);case 4:a=e.sent,this.setState({apiToken:a,loginButtonText:"Login"}),this.props.credentialUpdate(this.state.platform,this.state.ip,this.state.username,this.state.password,this.state.apiToken,this.state.polarisDomain),e.next=12;break;case 9:e.prev=9,e.t0=e.catch(1),this.setState({loginErrorMessage:B(e.t0),loginButtonText:G});case 12:case"end":return e.stop()}},e,this,[[1,9]])}));return function(t){return e.apply(this,arguments)}}()},{key:"handleSelectYourPlatform",value:function(e,t){this.setState({platform:"polaris"===this.state.platform?"cdm":"polaris",loginErrorMessage:null})}},{key:"handleModeButton",value:function(){this.setState({polarisDomain:this.state.polarisDomain===Q?".dev.my.rubrik-lab.com":Q})}},{key:"onChange",value:function(e){this.setState(Object(d.a)({},e.target.id,e.target.value))}},{key:"createFullLandingPageUi",value:function(){return r.a.createElement(r.a.Fragment,null,r.a.createElement("div",{className:"landing-page"},this.createWelcome(),this.createLogin()))}},{key:"createWelcome",value:function(){return r.a.createElement("div",{className:"welcome-message"},r.a.createElement("div",null),r.a.createElement("div",{className:"center-white-text"},r.a.createElement("div",{className:"larger-font-size"},r.a.createElement("span",null,"Welcome to the "),r.a.createElement("span",{className:"bold-text"},r.a.createElement("span",null,"Rubrik GraphQL Playground")))),r.a.createElement("div",{className:"bottom-white-small-text"},r.a.createElement("span",{className:"thin-text"},r.a.createElement("span",null,"Don't Backup. ")),r.a.createElement("span",null,"Go Forward.")))}},{key:"createLogin",value:function(){return r.a.createElement("div",{className:"login"},r.a.createElement("div",{className:"flex-container"},r.a.createElement("div",{className:"flex-row"},this.createLoginLogo(),this.createLoginHeader(),null===this.state.platform&&this.createLoginPlatformButtons(),null!=this.state.platform&&this.createLoginForm(),this.createRwpLink(),this.createDevModeIcon())))}},{key:"createLoginLogo",value:function(){return r.a.createElement("div",{className:"display-flex-justify"},r.a.createElement("img",{alt:"Rubrik logo",src:v.a,width:"80"}))}},{key:"createLoginHeader",value:function(){return r.a.createElement(r.a.Fragment,null,r.a.createElement("div",{className:"login-text display-flex-justify"},this.state.formHeader),null!=this.state.platform&&this.createLoginErrorMessage())}},{key:"createLoginErrorMessage",value:function(){return r.a.createElement("div",{className:"error-text display-flex-justify"},this.state.loginErrorMessage)}},{key:"createLoginPlatformButtons",value:function(){return r.a.createElement("div",{className:"btn-row {this.state.platform}"},r.a.createElement("div",{className:"btn-column"},r.a.createElement("button",{type:"submit",className:"primary-button",onClick:this.handleSwitchToLogin},r.a.createElement("h3",null,"Polaris"))),r.a.createElement("div",{className:"btn-column"},r.a.createElement("button",{type:"submit",className:"primary-button",onClick:this.handleSwitchToLogin},r.a.createElement("h3",null,"CDM"))))}},{key:"createRwpLink",value:function(){}},{key:"createDevModeIcon",value:function(){var e=Object(W.a)(function(e){return{tooltip:{backgroundColor:"rgb(255, 255, 255)",color:"rgba(0, 0, 0, 0.87)",maxWidth:220,"text-align":"center"}}})(H.a);return"polaris"===this.state.platform?r.a.createElement("div",{className:"bottom-right"},r.a.createElement(e,{title:r.a.createElement(r.a.Fragment,null,r.a.createElement(Y.a,{color:"inherit",variant:"body2"},this.state.polarisDomain===Q?"Set the Polaris Domain to development. Internal Rubrik use only.":"Set the Polaris Domain to production."))},r.a.createElement(z.a,{"aria-label":"delete",onClick:this.handleModeButton},this.state.polarisDomain===Q?r.a.createElement(_.a,null):r.a.createElement(I.a,null)))):void 0}},{key:"createLoginForm",value:function(){return r.a.createElement(L,{platform:this.state.platform,ip:this.state.ip,username:this.state.username,password:this.state.password,selectYourPlatform:this.handleSelectYourPlatform,onChange:this.onChange,loginButton:this.handleLoginButton,loginButtonText:this.state.loginButtonText,polarisDomain:this.state.polarisDomain})}},{key:"render",value:function(){return this.createFullLandingPageUi()}}]),t}(n.Component),$=a(164),K=a.n($),X=(a(361),function(e){function t(){return Object(i.a)(this,t),Object(c.a)(this,Object(u.a)(t).apply(this,arguments))}return Object(p.a)(t,e),Object(l.a)(t,[{key:"test",value:function(){console.log("test")}},{key:"render",value:function(){var e=this;return r.a.createElement(K.a,{fetcher:function(t){return function(e,t,a,n,r,o,s){var i,l=P(a),c=S,u="https://".concat(l),p="".concat(s,"/api/graphql");"polaris"===t?(c.Authorization="Bearer ".concat(o),i=u+p):(c.Authorization="Basic "+btoa(n+":"+r),i=u+"/api/internal/graphql");var m=new URL(i),d={method:"post",protocol:m.protocol,hostname:m.hostname,port:m.port,path:m.pathname+m.search,headers:c,rejectUnauthorized:!1},h=Object(D.request)(d);return new Promise(function(t,a){h.on("response",function(e){var n=[];e.on("data",function(e){n.push(Buffer.from(e))}),e.on("end",function(r){var o=Buffer.concat(n).toString();e.statusCode>=400?a(o):t(JSON.parse(o))})}),h.on("error",a),h.end(JSON.stringify(e))})}(t,e.props.platform,e.props.nodeIp,e.props.username,e.props.password,e.props.apiToken,e.props.polarisDomain)}},r.a.createElement(K.a.Logo,null,r.a.createElement("img",{src:v.a,width:"40",align:"middle",alt:"Rubrik logo"})))}}]),t}(n.Component)),Z=function(e){function t(e){var a;return Object(i.a)(this,t),(a=Object(c.a)(this,Object(u.a)(t).call(this,e))).state={platform:null,nodeIp:null,username:null,password:null,apiToken:null,polarisDomain:null},a.handleCredentialUpdate=a.handleCredentialUpdate.bind(Object(m.a)(Object(m.a)(a))),a}return Object(p.a)(t,e),Object(l.a)(t,[{key:"handleCredentialUpdate",value:function(e,t,a,n,r,o){this.setState({platform:e,nodeIp:t,username:a,password:n,apiToken:r,polarisDomain:o})}},{key:"render",value:function(){var e=this;return null==this.state.apiToken?r.a.createElement(V,{credentialUpdate:function(t,a,n,r,o,s){return e.handleCredentialUpdate(t,a,n,r,o,s)}}):r.a.createElement(X,{platform:this.state.platform,nodeIp:this.state.nodeIp,username:this.state.username,password:this.state.password,apiToken:this.state.apiToken,polarisDomain:this.state.polarisDomain})}}]),t}(n.Component);Boolean("localhost"===window.location.hostname||"[::1]"===window.location.hostname||window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/));s.a.render(r.a.createElement(Z,null),document.getElementById("root")),"serviceWorker"in navigator&&navigator.serviceWorker.ready.then(function(e){e.unregister()})},71:function(e,t){e.exports=require("assert")}},[[220,1,2]]]); 2 | //# sourceMappingURL=main.e15b519c.chunk.js.map -------------------------------------------------------------------------------- /build/static/js/main.e15b519c.chunk.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["../../../Desktop/electron-cra-boilerplate/src/images/rubrikLogo.svg","../external \"https\"","../external \"punycode\"","../../../Desktop/electron-cra-boilerplate/node_modules/graphql-language-service-utils/esm sync /^.*/.js$","../../../Desktop/electron-cra-boilerplate/node_modules/graphql-language-service-utils/esm sync /^.*/.json$","../../../Desktop/electron-cra-boilerplate/node_modules/graphql-language-service-utils/esm lazy /^.*/.js$/ groupOptions: {} namespace object","../../../Desktop/electron-cra-boilerplate/node_modules/graphql-language-service-utils/esm lazy /^.*/.json$/ groupOptions: {} namespace object","../../../Desktop/electron-cra-boilerplate/src/components/LoginForm.js","../../../Desktop/electron-cra-boilerplate/src/utils/api.js","../../../Desktop/electron-cra-boilerplate/src/components/LandingPage.js","../../../Desktop/electron-cra-boilerplate/src/components/GraphiQl.js","../../../Desktop/electron-cra-boilerplate/src/App.js","../../../Desktop/electron-cra-boilerplate/src/serviceWorker.js","../../../Desktop/electron-cra-boilerplate/src/index.js","../external \"assert\""],"names":["module","exports","__webpack_require__","p","require","map","./Range.js","./file.js","./getASTNodeAtPosition.js","./index.js","./validateWithCustomRules.js","webpackContext","req","id","webpackContextResolve","e","Error","code","keys","Object","resolve","webpackEmptyContext","webpackAsyncContext","ids","Promise","all","slice","then","webpackEmptyAsyncContext","useStylesForm","makeStyles","theme","root","& .MuiTextField-root","margin","spacing","width","useStylesSlectPlatformButton","& > *","backgroundColor","&:hover","textTransform","font-weight","font-size","useStylesLoginButton","background-color","border-color","border-radius","line-height","color","display","margin-top","text-transform","box-shadow","LoginForm","props","classesForm","classesSelectPlatformButton","classesLoginButton","react_default","a","createElement","className","noValidate","autoComplete","TextField","autoFocus","error","ip","required","label","platform","onChange","InputProps","endAdornment","InputAdornment","position","polarisDomain","username","type","password","Button","variant","onClick","loginButton","disabled","length","loginButtonText","selectYourPlatform","defaultHttpHeader","Content-Type","User-Agent","formatIp","replace","userFiendlyErrorMessage","console","log","response","status","concat","data","message","includes","rubrikApiPost","_callee","url","httpHeaders","body","instance","regenerator_default","wrap","_context","prev","next","axios","create","timeout","httpsAgent","https","Agent","rejectUnauthorized","method","headers","sent","abrupt","stop","validateCredentials","_x4","_x5","_x6","_x7","_x8","_validateCredentials","apply","this","arguments","_callee2","nodeIp","httpHeader","endpoint","postBody","formattedNodeIp","_context2","Authorization","btoa","Accept","token","access_token","selectYourPlatformFormHeader","polarisUserDomain","LandingPage","_this","classCallCheck","possibleConstructorReturn","getPrototypeOf","call","state","formHeader","loginErrorMessage","apiToken","createLoginForm","bind","assertThisInitialized","handleSwitchToLogin","handleSelectYourPlatform","handleLoginButton","createLoginHeader","createDevModeIcon","handleModeButton","event","preventDefault","setState","target","textContent","toLowerCase","credentialUpdate","t0","defineProperty","value","Fragment","createWelcome","createLogin","createLoginLogo","createLoginPlatformButtons","createRwpLink","alt","src","rubrikLogo","createLoginErrorMessage","HtmlTooltip","withStyles","tooltip","maxWidth","text-align","Tooltip","title","Typography","IconButton","aria-label","Person_default","Code_default","createFullLandingPageUi","Component","GraphiQl","dist_default","fetcher","graphQLParams","endpointPrefix","endpointSuffixPolaris","URL","requestOptions","protocol","hostname","port","path","pathname","search","request","httpsRequest","reject","on","chunks","push","Buffer","from","end","toString","statusCode","JSON","parse","stringify","graphQLFetcher","Logo","align","App","handleCredentialUpdate","_this2","src_components_LandingPage","components_GraphiQl","Boolean","window","location","match","ReactDOM","render","src_App","document","getElementById","navigator","serviceWorker","ready","registration","unregister"],"mappings":"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","file":"static/js/main.e15b519c.chunk.js","sourcesContent":["module.exports = __webpack_public_path__ + \"static/media/rubrikLogo.b5f40d5b.svg\";","module.exports = require(\"https\");","module.exports = require(\"punycode\");","var map = {\n\t\"./Range.js\": 79,\n\t\"./file.js\": 99,\n\t\"./getASTNodeAtPosition.js\": 98,\n\t\"./index.js\": 35,\n\t\"./validateWithCustomRules.js\": 115\n};\n\n\nfunction webpackContext(req) {\n\tvar id = webpackContextResolve(req);\n\treturn __webpack_require__(id);\n}\nfunction webpackContextResolve(req) {\n\tvar id = map[req];\n\tif(!(id + 1)) { // check for number or string\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\treturn id;\n}\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = 319;","function webpackEmptyContext(req) {\n\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\te.code = 'MODULE_NOT_FOUND';\n\tthrow e;\n}\nwebpackEmptyContext.keys = function() { return []; };\nwebpackEmptyContext.resolve = webpackEmptyContext;\nmodule.exports = webpackEmptyContext;\nwebpackEmptyContext.id = 320;","var map = {\n\t\"./Range.js\": [\n\t\t79\n\t],\n\t\"./file.js\": [\n\t\t99\n\t],\n\t\"./getASTNodeAtPosition.js\": [\n\t\t98\n\t],\n\t\"./index.js\": [\n\t\t35\n\t],\n\t\"./validateWithCustomRules.js\": [\n\t\t115\n\t]\n};\nfunction webpackAsyncContext(req) {\n\tvar ids = map[req];\n\tif(!ids) {\n\t\treturn Promise.resolve().then(function() {\n\t\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\t\te.code = 'MODULE_NOT_FOUND';\n\t\t\tthrow e;\n\t\t});\n\t}\n\treturn Promise.all(ids.slice(1).map(__webpack_require__.e)).then(function() {\n\t\tvar id = ids[0];\n\t\treturn __webpack_require__(id);\n\t});\n}\nwebpackAsyncContext.keys = function webpackAsyncContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackAsyncContext.id = 321;\nmodule.exports = webpackAsyncContext;","function webpackEmptyAsyncContext(req) {\n\t// Here Promise.resolve().then() is used instead of new Promise() to prevent\n\t// uncaught exception popping up in devtools\n\treturn Promise.resolve().then(function() {\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t});\n}\nwebpackEmptyAsyncContext.keys = function() { return []; };\nwebpackEmptyAsyncContext.resolve = webpackEmptyAsyncContext;\nmodule.exports = webpackEmptyAsyncContext;\nwebpackEmptyAsyncContext.id = 322;","import React from \"react\";\nimport TextField from \"@material-ui/core/TextField\";\nimport { makeStyles } from \"@material-ui/core/styles\";\nimport { Button } from \"@material-ui/core\";\n\nimport InputAdornment from \"@material-ui/core/InputAdornment\";\nimport \"../components/LandingPage.css\";\n\nconst useStylesForm = makeStyles((theme) => ({\n root: {\n \"& .MuiTextField-root\": {\n margin: theme.spacing(1),\n width: \"100%\",\n },\n },\n}));\n\nconst useStylesSlectPlatformButton = makeStyles((theme) => ({\n root: {\n \"& > *\": {\n backgroundColor: \"#FFF\",\n \"&:hover\": {\n backgroundColor: \"#FFF\",\n },\n width: \"100%\",\n textTransform: \"none\",\n \"font-weight\": 100,\n \"font-size\": \" 1.0775rem\",\n },\n },\n}));\n\nconst useStylesLoginButton = makeStyles((theme) => ({\n root: {\n \"& > *\": {\n margin: theme.spacing(1),\n width: \"100%\",\n \"&:hover\": {\n \"background-color\": \"#18b8e9\",\n \"border-color\": \"#18b8e9\",\n },\n \"border-radius\": \"0.286rem\",\n \"line-height\": \" 1.83\",\n color: \"#fff\",\n \"background-color\": \"rgb(0, 134, 192)\",\n \"border-color\": \"rgb(0, 134, 192)\",\n display: \"inline-block\",\n \"margin-top\": \"20px\",\n \"font-weight\": 200,\n \"font-size\": \"1.0775rem\",\n \"text-transform\": \"uppercase\",\n \"box-shadow\":\n \"0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12)\",\n },\n },\n}));\n\nexport default function LoginForm(props) {\n const classesForm = useStylesForm();\n const classesSelectPlatformButton = useStylesSlectPlatformButton();\n const classesLoginButton = useStylesLoginButton();\n\n function diableLoginButton() {\n // This function controls whether or not the field button is disabled.\n // The logic is super ugly and can be cleaned up but it works\n if (\n props.ip === null ||\n props.username === null ||\n props.password === null\n ) {\n return true;\n }\n if (props.ip !== null) {\n if (props.ip.length <= 0) {\n return true;\n }\n }\n\n if (props.username !== null) {\n if (props.username.length <= 0) {\n return true;\n }\n }\n\n if (props.password !== null) {\n if (props.password.length <= 0) {\n return true;\n }\n }\n\n if (props.loginButtonText !== \"Login\") {\n return true;\n }\n }\n return (\n
\n
\n \n {props.polarisDomain}\n \n ),\n }\n }\n />\n \n\n \n
\n
\n \n {props.loginButtonText}\n \n
\n
\n \n
\n
\n );\n}\n","import axios from \"axios\";\nimport https from \"https\";\nimport { request as httpsRequest } from \"https\";\n\nconst defaultHttpHeader = {\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"RubrikGraphQLPlayground\",\n};\n\nfunction formatIp(ip) {\n /*\n * This function will processes the user provide CDM IP or Polaris Domain\n * and removes any values that will prevent connection to the platforms.\n */\n\n return ip\n .replace(\"https://\", \"\")\n .replace(\".my.rubrik.com\", \"\")\n .replace(\"/\", \"\");\n}\n\nexport function userFiendlyErrorMessage(error) {\n /*\n * This function will processes an error mesage returned by an API call\n * and then provide a user friendly version of that error message\n */\n let userFiendlyErrorMessage;\n try {\n console.log(error.response);\n } catch (error) {\n console.log(\"No additional error detail\");\n }\n\n if (error.response) {\n if (error.response.status === 401 || error.response.status === 422) {\n userFiendlyErrorMessage =\n \"Sorry, you entered an incorrect email or password.\";\n } else if (error.response.status === 400 || error.response.status === 401) {\n userFiendlyErrorMessage =\n \"Sorry, the request was rejected as malformed by the Rubrik platform.\";\n } else {\n userFiendlyErrorMessage = `Sorry, the request was rejected with a ${error.response.status} (${error.response.data.message}) HTTP response status code.`;\n }\n } else if (\n error.message.includes(\"getaddrinfo ENOTFOUND\") ||\n error.message.includes(\"Network Error\")\n ) {\n userFiendlyErrorMessage =\n \"Sorry, we were unable to connect to the provided Rubrik platform.\";\n } else if (\n error.message.includes(\"connect ETIMEDOUT\") ||\n error.message.includes(\"timeout of 15000ms exceeded\")\n ) {\n userFiendlyErrorMessage =\n \"Sorry, the connection to the Rubrik platform timeout and we were unable to connect.\";\n } else {\n userFiendlyErrorMessage = error.message;\n }\n\n return userFiendlyErrorMessage;\n}\n\nasync function rubrikApiPost(url, httpHeaders, body) {\n /*\n * This function will make an HTTP Post using the supplied endpoint and\n * httpHeaders.\n */\n console.log(\"rubrikApiPost\");\n console.log(httpHeaders);\n console.log(body);\n\n const instance = axios.create({\n timeout: 15000,\n httpsAgent: new https.Agent({\n rejectUnauthorized: false,\n }),\n });\n const response = await instance({\n method: \"post\",\n url: url,\n headers: httpHeaders,\n data: body,\n });\n\n return response;\n}\n\nexport async function validateCredentials(\n platform,\n nodeIp,\n username,\n password,\n polarisDomain\n) {\n /*\n * This function makes an API request to CDM to validate the supplied\n * credentials. Since we use Basic authentication to make GQL calls to CDM,\n * which prevent token timeouts issues, we don't actually use the returned\n * API Token.\n */\n let httpHeader = defaultHttpHeader;\n var endpoint;\n var postBody;\n if (platform === \"cdm\") {\n httpHeader.Authorization = \"Basic \" + btoa(username + \":\" + password);\n endpoint = \"/api/v1/session\";\n postBody = {};\n } else {\n httpHeader.Accept = \"application/json, text/plain\";\n httpHeader[\"Content-Type\"] = \"application/json;charset=UTF-8\";\n endpoint = `${polarisDomain}/api/session`;\n postBody = {\n username: username,\n password: password,\n };\n }\n\n console.log(httpHeader);\n\n const formattedNodeIp = formatIp(nodeIp);\n console.log(formattedNodeIp);\n console.log(endpoint);\n\n let url = `https://${formattedNodeIp}${endpoint}`;\n console.log(url);\n\n var response = await rubrikApiPost(url, httpHeader, postBody);\n\n if (platform === \"cdm\") {\n return response.data.token;\n } else {\n return response.data.access_token;\n }\n}\n\nexport function graphQLFetcher(\n graphQLParams,\n platform,\n nodeIp,\n username,\n password,\n apiToken,\n polarisDomain\n) {\n /*\n * This function is used by GraphiQl to make the GraphQL API calls.\n */\n const formattedNodeIp = formatIp(nodeIp);\n let httpHeader = defaultHttpHeader;\n let endpointPrefix = `https://${formattedNodeIp}`;\n let endpointSuffixPolaris = `${polarisDomain}/api/graphql`;\n let endpointSuffixCdm = \"/api/internal/graphql\";\n\n var endpoint;\n if (platform === \"polaris\") {\n httpHeader.Authorization = `Bearer ${apiToken}`;\n endpoint = endpointPrefix + endpointSuffixPolaris;\n } else {\n httpHeader.Authorization = \"Basic \" + btoa(username + \":\" + password);\n endpoint = endpointPrefix + endpointSuffixCdm;\n }\n\n // TODO: Update to use rubrikApiPost\n const url = new URL(endpoint);\n\n const requestOptions = {\n method: \"post\",\n protocol: url.protocol,\n hostname: url.hostname,\n port: url.port,\n path: url.pathname + url.search,\n headers: httpHeader,\n rejectUnauthorized: false, // avoid problems with self-signed certs\n };\n\n const request = httpsRequest(requestOptions);\n\n return new Promise((resolve, reject) => {\n request.on(\"response\", (response) => {\n const chunks = [];\n response.on(\"data\", (data) => {\n chunks.push(Buffer.from(data));\n });\n response.on(\"end\", (end) => {\n const data = Buffer.concat(chunks).toString();\n if (response.statusCode >= 400) {\n reject(data);\n } else {\n resolve(JSON.parse(data));\n }\n });\n });\n\n request.on(\"error\", reject);\n\n request.end(JSON.stringify(graphQLParams));\n });\n}\n","import React, { Component } from \"react\";\n// App Component related imports\nimport \"./LandingPage.css\";\nimport rubrikLogo from \"../images/rubrikLogo.svg\";\nimport LoginForm from \"./LoginForm\";\nimport { validateCredentials, userFiendlyErrorMessage } from \"../utils/api\";\n// Material-UI related imports\nimport CodeIcon from \"@material-ui/icons/Code\";\nimport PersonIcon from \"@material-ui/icons/Person\";\nimport IconButton from \"@material-ui/core/IconButton\";\nimport Tooltip from \"@material-ui/core/Tooltip\";\nimport { withStyles } from \"@material-ui/core/styles\";\nimport Typography from \"@material-ui/core/Typography\";\n\nconst selectYourPlatformFormHeader = \"Select your Platform\";\nconst loginButtonText = \"Login\";\nconst connectingToPlatformButtonText = \"Attempting to Connect\";\nconst polarisUserDomain = \".my.rubrik.com\";\nconst polarisDevDomain = \".dev.my.rubrik-lab.com\";\n\nclass LandingPage extends Component {\n constructor(props) {\n super(props);\n\n this.state = {\n formHeader: selectYourPlatformFormHeader,\n platform: null,\n loginButtonText: loginButtonText,\n loginErrorMessage: null,\n apiToken: null,\n ip: null,\n username: null,\n password: null,\n polarisDomain: polarisUserDomain,\n };\n\n this.createLoginForm = this.createLoginForm.bind(this);\n this.handleSwitchToLogin = this.handleSwitchToLogin.bind(this);\n this.handleSelectYourPlatform = this.handleSelectYourPlatform.bind(this);\n this.onChange = this.onChange.bind(this);\n this.handleLoginButton = this.handleLoginButton.bind(this);\n this.createLoginHeader = this.createLoginHeader.bind(this);\n this.createDevModeIcon = this.createDevModeIcon.bind(this);\n this.handleModeButton = this.handleModeButton.bind(this);\n }\n\n handleSwitchToLogin(event) {\n event.preventDefault();\n\n this.setState({\n platform: event.target.textContent.toLowerCase(),\n formHeader: loginButtonText,\n });\n }\n\n async handleLoginButton(event) {\n this.setState({\n loginButtonText: connectingToPlatformButtonText,\n loginErrorMessage: null,\n });\n\n try {\n let apiToken = await validateCredentials(\n this.state.platform,\n this.state.ip,\n this.state.username,\n this.state.password,\n this.state.polarisDomain\n );\n\n this.setState({\n apiToken: apiToken,\n loginButtonText: \"Login\",\n });\n\n this.props.credentialUpdate(\n this.state.platform,\n this.state.ip,\n this.state.username,\n this.state.password,\n this.state.apiToken,\n this.state.polarisDomain\n );\n } catch (error) {\n this.setState({\n loginErrorMessage: userFiendlyErrorMessage(error),\n loginButtonText: loginButtonText,\n });\n }\n }\n\n handleSelectYourPlatform(event, platform) {\n this.setState({\n platform: this.state.platform === \"polaris\" ? \"cdm\" : \"polaris\",\n loginErrorMessage: null,\n });\n }\n\n handleModeButton() {\n this.setState({\n polarisDomain:\n this.state.polarisDomain === polarisUserDomain\n ? polarisDevDomain\n : polarisUserDomain,\n });\n }\n\n onChange(event) {\n // This function handles the input from the form fields and sets the\n // appropriate state.\n this.setState({ [event.target.id]: event.target.value });\n }\n\n createFullLandingPageUi() {\n return (\n \n
\n {this.createWelcome()}\n\n {this.createLogin()}\n
\n
\n );\n }\n\n // Creates the \"Welcome to the Rubrik GraphQL Playground\" UI\n createWelcome() {\n return (\n
\n
\n
\n
\n Welcome to the \n \n Rubrik GraphQL Playground\n \n
\n
\n
\n \n Don't Backup. \n \n Go Forward.\n
\n
\n );\n }\n\n // Creates the right side of the Welcome screen where the login form lives\n createLogin() {\n return (\n
\n
\n
\n {this.createLoginLogo()}\n {this.createLoginHeader()}\n {this.state.platform === null && this.createLoginPlatformButtons()}\n {this.state.platform != null && this.createLoginForm()}\n {this.createRwpLink()}\n {this.createDevModeIcon()}\n
\n
\n
\n );\n }\n\n createLoginLogo() {\n return (\n
\n \"Rubrik\n
\n );\n }\n\n createLoginHeader() {\n return (\n \n
\n {this.state.formHeader}\n
\n {this.state.platform != null && this.createLoginErrorMessage()}\n
\n );\n }\n\n createLoginErrorMessage() {\n return (\n
\n {this.state.loginErrorMessage}\n
\n );\n }\n\n createLoginPlatformButtons() {\n return (\n
\n
\n \n

Polaris

\n \n
\n
\n \n

CDM

\n \n
\n
\n );\n }\n\n createRwpLink() {\n // TODO: If you try to download the link when you don't have internet access the app goes blank\n // Until error handling is in place for this, we are are just going to return null\n // return (\n //
\n // \n // An Introduction to GraphQL and Rubrik Whitepaper\n // \n //
\n // );\n return;\n }\n\n createDevModeIcon() {\n const HtmlTooltip = withStyles((theme) => ({\n tooltip: {\n backgroundColor: \"rgb(255, 255, 255)\",\n color: \"rgba(0, 0, 0, 0.87)\",\n maxWidth: 220,\n \"text-align\": \"center\",\n },\n }))(Tooltip);\n\n if (this.state.platform === \"polaris\") {\n return (\n
\n \n \n {this.state.polarisDomain === polarisUserDomain\n ? \"Set the Polaris Domain to development. Internal Rubrik use only.\"\n : \"Set the Polaris Domain to production.\"}\n \n \n }\n >\n \n {this.state.polarisDomain === polarisUserDomain ? (\n \n ) : (\n \n )}\n \n \n
\n );\n } else {\n return;\n }\n }\n\n createLoginForm() {\n return (\n \n );\n }\n\n render() {\n return this.createFullLandingPageUi();\n }\n}\n\nexport default LandingPage;\n","import React, { Component } from \"react\";\nimport GraphiQL from \"graphiql\";\nimport \"graphiql/graphiql.css\";\nimport { graphQLFetcher } from \"../utils/api\";\nimport rubrikLogo from \"../images/rubrikLogo.svg\";\n\nclass GraphiQl extends Component {\n test() {\n console.log(\"test\");\n }\n render() {\n return (\n \n graphQLFetcher(\n graphQLParams,\n this.props.platform,\n this.props.nodeIp,\n this.props.username,\n this.props.password,\n this.props.apiToken,\n this.props.polarisDomain\n )\n }\n >\n \n \"Rubrik\n \n \n );\n }\n}\n\nexport default GraphiQl;\n","import React, { Component } from \"react\";\nimport LandingPage from \"./components/LandingPage\";\nimport GraphiQl from \"./components/GraphiQl\";\n\nclass App extends Component {\n constructor(props) {\n super(props);\n\n this.state = {\n platform: null,\n nodeIp: null,\n username: null,\n password: null,\n apiToken: null,\n polarisDomain: null,\n };\n\n this.handleCredentialUpdate = this.handleCredentialUpdate.bind(this);\n }\n\n handleCredentialUpdate(\n platform,\n nodeIp,\n username,\n password,\n apiToken,\n polarisDomain\n ) {\n this.setState({\n platform,\n nodeIp,\n username,\n password,\n apiToken,\n polarisDomain,\n });\n }\n\n render() {\n if (this.state.apiToken == null) {\n return (\n \n this.handleCredentialUpdate(\n platform,\n nodeIp,\n username,\n password,\n apiToken,\n polarisDomain\n )\n }\n />\n );\n } else {\n return (\n \n );\n }\n }\n}\n\nexport default App;\n","// This optional code is used to register a service worker.\n// register() is not called by default.\n\n// This lets the app load faster on subsequent visits in production, and gives\n// it offline capabilities. However, it also means that developers (and users)\n// will only see deployed updates on subsequent visits to a page, after all the\n// existing tabs open on the page have been closed, since previously cached\n// resources are updated in the background.\n\n// To learn more about the benefits of this model and instructions on how to\n// opt-in, read http://bit.ly/CRA-PWA\n\nconst isLocalhost = Boolean(\n window.location.hostname === 'localhost' ||\n // [::1] is the IPv6 localhost address.\n window.location.hostname === '[::1]' ||\n // 127.0.0.1/8 is considered localhost for IPv4.\n window.location.hostname.match(\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\n )\n);\n\nexport function register(config) {\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\n // The URL constructor is available in all browsers that support SW.\n const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);\n if (publicUrl.origin !== window.location.origin) {\n // Our service worker won't work if PUBLIC_URL is on a different origin\n // from what our page is served on. This might happen if a CDN is used to\n // serve assets; see https://github.com/facebook/create-react-app/issues/2374\n return;\n }\n\n window.addEventListener('load', () => {\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\n\n if (isLocalhost) {\n // This is running on localhost. Let's check if a service worker still exists or not.\n checkValidServiceWorker(swUrl, config);\n\n // Add some additional logging to localhost, pointing developers to the\n // service worker/PWA documentation.\n navigator.serviceWorker.ready.then(() => {\n console.log(\n 'This web app is being served cache-first by a service ' +\n 'worker. To learn more, visit http://bit.ly/CRA-PWA'\n );\n });\n } else {\n // Is not localhost. Just register service worker\n registerValidSW(swUrl, config);\n }\n });\n }\n}\n\nfunction registerValidSW(swUrl, config) {\n navigator.serviceWorker\n .register(swUrl)\n .then(registration => {\n registration.onupdatefound = () => {\n const installingWorker = registration.installing;\n if (installingWorker == null) {\n return;\n }\n installingWorker.onstatechange = () => {\n if (installingWorker.state === 'installed') {\n if (navigator.serviceWorker.controller) {\n // At this point, the updated precached content has been fetched,\n // but the previous service worker will still serve the older\n // content until all client tabs are closed.\n console.log(\n 'New content is available and will be used when all ' +\n 'tabs for this page are closed. See http://bit.ly/CRA-PWA.'\n );\n\n // Execute callback\n if (config && config.onUpdate) {\n config.onUpdate(registration);\n }\n } else {\n // At this point, everything has been precached.\n // It's the perfect time to display a\n // \"Content is cached for offline use.\" message.\n console.log('Content is cached for offline use.');\n\n // Execute callback\n if (config && config.onSuccess) {\n config.onSuccess(registration);\n }\n }\n }\n };\n };\n })\n .catch(error => {\n console.error('Error during service worker registration:', error);\n });\n}\n\nfunction checkValidServiceWorker(swUrl, config) {\n // Check if the service worker can be found. If it can't reload the page.\n fetch(swUrl)\n .then(response => {\n // Ensure service worker exists, and that we really are getting a JS file.\n const contentType = response.headers.get('content-type');\n if (\n response.status === 404 ||\n (contentType != null && contentType.indexOf('javascript') === -1)\n ) {\n // No service worker found. Probably a different app. Reload the page.\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister().then(() => {\n window.location.reload();\n });\n });\n } else {\n // Service worker found. Proceed as normal.\n registerValidSW(swUrl, config);\n }\n })\n .catch(() => {\n console.log(\n 'No internet connection found. App is running in offline mode.'\n );\n });\n}\n\nexport function unregister() {\n if ('serviceWorker' in navigator) {\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister();\n });\n }\n}\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.css';\nimport App from './App';\nimport * as serviceWorker from './serviceWorker';\n\nReactDOM.render(, document.getElementById('root'));\n\n// If you want your app to work offline and load faster, you can change\n// unregister() to register() below. Note this comes with some pitfalls.\n// Learn more about service workers: http://bit.ly/CRA-PWA\nserviceWorker.unregister();\n","module.exports = require(\"assert\");"],"sourceRoot":""} -------------------------------------------------------------------------------- /build/static/js/runtime~main.8c97409f.js: -------------------------------------------------------------------------------- 1 | !function(e){function r(r){for(var n,f,i=r[0],l=r[1],a=r[2],c=0,s=[];c 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rubrik-graphql-playground", 3 | "description": "An API Playground for the Rubrik GraphQL APIs.", 4 | "version": "2.0.1", 5 | "license": "MIT", 6 | "author": { 7 | "name": "Drew Russell (@drusse11)", 8 | "url": "https://build.rubrik.com" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/rubrikinc/graphql-playground.git" 13 | }, 14 | "build": { 15 | "productName": "Rubrik GraphQL Playground", 16 | "asar": true, 17 | "afterSign": "script/notarize.js", 18 | "appId": "com.rubrikinc.graphql-playground", 19 | "copyright": "Copyright © 2019 Rubrik", 20 | "publish": [ 21 | { 22 | "provider": "github", 23 | "owner": "rubrikinc", 24 | "repo": "graphql-playground" 25 | } 26 | ], 27 | "mac": { 28 | "category": "public.app-category.developer-tools", 29 | "hardenedRuntime": true, 30 | "entitlements": "assets/entitlements.mac.plist", 31 | "entitlementsInherit": "assets/entitlements.mac.plist", 32 | "gatekeeperAssess": false 33 | }, 34 | "dmg": { 35 | "contents": [ 36 | { 37 | "x": 410, 38 | "y": 168, 39 | "type": "link", 40 | "path": "/Applications" 41 | }, 42 | { 43 | "x": 104, 44 | "y": 168, 45 | "type": "file" 46 | } 47 | ] 48 | }, 49 | "linux": { 50 | "category": "Development", 51 | "target": [ 52 | "AppImage" 53 | ] 54 | }, 55 | "nsis": { 56 | "perMachine": true 57 | }, 58 | "files": [ 59 | "build/**/*", 60 | "node_modules/**/*" 61 | ], 62 | "directories": { 63 | "buildResources": "assets", 64 | "output": "release" 65 | } 66 | }, 67 | "homepage": "./", 68 | "main": "public/electron.js", 69 | "scripts": { 70 | "start": "rescripts start", 71 | "electron": "NODE_ENV=development electron .", 72 | "build": "rescripts build", 73 | "test": "rescripts test", 74 | "eject": "react-scripts eject", 75 | "electron-dev": "concurrently \"BROWSER=none yarn start\" \"wait-on http://localhost:3000 && electron .\"", 76 | "postinstall": "electron-builder install-app-deps", 77 | "preelectron-pack": "yarn build", 78 | "dist-clean": "rm -rf ./release ./dist", 79 | "electron-pack": "npm run dist-clean && electron-builder", 80 | "electron-release": "npm run dist-clean && electron-builder --mac --linux --win" 81 | }, 82 | "eslintConfig": { 83 | "extends": "react-app" 84 | }, 85 | "browserslist": [ 86 | ">0.2%", 87 | "not dead", 88 | "not ie <= 11", 89 | "not op_mini all" 90 | ], 91 | "dependencies": { 92 | "@material-ui/core": "^4.9.11", 93 | "@material-ui/icons": "^4.9.1", 94 | "@material-ui/lab": "^4.0.0-alpha.50", 95 | "axios": "^0.19.2", 96 | "electron-is-dev": "^1.2.0", 97 | "electron-updater": "^4.3.1", 98 | "graphiql": "^0.17.5", 99 | "graphql": "^14.4.2", 100 | "https": "^1.0.0", 101 | "react": "^16.13.1", 102 | "react-dom": "^16.13.1", 103 | "react-icons": "^3.10.0", 104 | "react-scripts": "2.1.5", 105 | "update-electron-app": "^1.5.0" 106 | }, 107 | "devDependencies": { 108 | "@rescripts/cli": "^0.0.10", 109 | "@rescripts/rescript-env": "^0.0.5", 110 | "concurrently": "^4.1.2", 111 | "electron": "^4.2.12", 112 | "electron-builder": "^22.5.1", 113 | "electron-notarize": "^0.3.0", 114 | "electron-packager": "^12.2.0", 115 | "typescript": "^3.8.3", 116 | "wait-on": "^3.3.0" 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /public/electron.js: -------------------------------------------------------------------------------- 1 | const electron = require("electron"); 2 | const { autoUpdater } = require("electron-updater"); 3 | const app = electron.app; 4 | app.commandLine.appendSwitch("ignore-certificate-errors", "true"); 5 | 6 | const BrowserWindow = electron.BrowserWindow; 7 | 8 | const path = require("path"); 9 | const isDev = require("electron-is-dev"); 10 | var Menu = electron.Menu; 11 | 12 | let mainWindow; 13 | 14 | function sendStatusToWindow(text) { 15 | mainWindow.webContents.send("message", text); 16 | } 17 | 18 | function createWindow() { 19 | mainWindow = new BrowserWindow({ 20 | show: false, 21 | webPreferences: { 22 | webSecurity: false, 23 | }, 24 | }); 25 | mainWindow.maximize(); 26 | mainWindow.show(); 27 | mainWindow.loadURL( 28 | isDev 29 | ? "http://localhost:3000" 30 | : `file://${path.join(__dirname, "../build/index.html")}` 31 | ); 32 | require("update-electron-app")(); 33 | 34 | if (isDev) { 35 | // Open the DevTools. 36 | //BrowserWindow.addDevToolsExtension(''); 37 | mainWindow.webContents.openDevTools(); 38 | } 39 | 40 | if (process.platform === "darwin") { 41 | template = [ 42 | { 43 | label: "Rubrik GraphQL Playground", 44 | submenu: [ 45 | { 46 | label: "About Rubrik GraphQL Playground", 47 | selector: "orderFrontStandardAboutPanel:", 48 | }, 49 | { 50 | type: "separator", 51 | }, 52 | { 53 | label: "Quit", 54 | accelerator: "Command+Q", 55 | click: function () { 56 | app.quit(); 57 | }, 58 | }, 59 | ], 60 | }, 61 | { 62 | label: "File", 63 | submenu: [ 64 | { 65 | label: "Logout", 66 | accelerator: "Command+L", 67 | click: function () { 68 | if (mainWindow.restart) { 69 | mainWindow.restart(); 70 | } else if (mainWindow.reload) { 71 | mainWindow.reload(); 72 | } 73 | }, 74 | }, 75 | { 76 | label: "Quit", 77 | accelerator: "Command+Q", 78 | click() { 79 | app.quit(); 80 | }, 81 | }, 82 | ], 83 | }, 84 | { 85 | label: "Edit", 86 | submenu: [ 87 | { 88 | label: "Undo", 89 | accelerator: "Command+Z", 90 | selector: "undo:", 91 | }, 92 | { 93 | label: "Redo", 94 | accelerator: "Shift+Command+Z", 95 | selector: "redo:", 96 | }, 97 | { 98 | type: "separator", 99 | }, 100 | { 101 | label: "Cut", 102 | accelerator: "Command+X", 103 | selector: "cut:", 104 | }, 105 | { 106 | label: "Copy", 107 | accelerator: "Command+C", 108 | selector: "copy:", 109 | }, 110 | { 111 | label: "Paste", 112 | accelerator: "Command+V", 113 | selector: "paste:", 114 | }, 115 | { 116 | label: "Select All", 117 | accelerator: "Command+A", 118 | selector: "selectAll:", 119 | }, 120 | ], 121 | }, 122 | { 123 | label: "View", 124 | submenu: [ 125 | { 126 | label: "Toggle Full Screen", 127 | accelerator: "Ctrl+Command+F", 128 | click: function () { 129 | mainWindow.setFullScreen(!mainWindow.isFullScreen()); 130 | }, 131 | }, 132 | { 133 | label: "Toggle Developer Tools", 134 | accelerator: "Alt+Command+I", 135 | click: function () { 136 | mainWindow.toggleDevTools(); 137 | }, 138 | }, 139 | { 140 | role: "resetzoom", 141 | }, 142 | { 143 | role: "zoomin", 144 | }, 145 | { 146 | role: "zoomout", 147 | }, 148 | ], 149 | }, 150 | { 151 | label: "Window", 152 | submenu: [ 153 | { 154 | label: "Minimize", 155 | accelerator: "Command+M", 156 | selector: "performMiniaturize:", 157 | }, 158 | { 159 | type: "separator", 160 | }, 161 | { 162 | label: "Bring All to Front", 163 | selector: "arrangeInFront:", 164 | }, 165 | ], 166 | }, 167 | ]; 168 | 169 | menu = Menu.buildFromTemplate(template); 170 | Menu.setApplicationMenu(menu); 171 | } else { 172 | template = [ 173 | { 174 | label: "&File", 175 | submenu: [ 176 | { 177 | label: "Logout", 178 | accelerator: "Command+L", 179 | click: function () { 180 | if (mainWindow.restart) { 181 | mainWindow.restart(); 182 | } else if (mainWindow.reload) { 183 | mainWindow.reload(); 184 | } 185 | }, 186 | }, 187 | { 188 | label: "Quit", 189 | accelerator: "Command+Q", 190 | click() { 191 | app.quit(); 192 | }, 193 | }, 194 | ], 195 | }, 196 | { 197 | label: "&View", 198 | submenu: [ 199 | { 200 | label: "Toggle &Full Screen", 201 | accelerator: "F11", 202 | click: function () { 203 | mainWindow.setFullScreen(!mainWindow.isFullScreen()); 204 | }, 205 | }, 206 | { 207 | label: "Toggle &Developer Tools", 208 | accelerator: "Alt+Ctrl+I", 209 | click: function () { 210 | mainWindow.toggleDevTools(); 211 | }, 212 | }, 213 | ], 214 | }, 215 | ]; 216 | menu = Menu.buildFromTemplate(template); 217 | mainWindow.setMenu(menu); 218 | } 219 | 220 | mainWindow.on("closed", () => (mainWindow = null)); 221 | } 222 | 223 | app.on("ready", createWindow); 224 | 225 | app.on("window-all-closed", () => { 226 | if (process.platform !== "darwin") { 227 | app.quit(); 228 | } 229 | }); 230 | 231 | app.on("activate", () => { 232 | if (mainWindow === null) { 233 | require("update-electron-app")(); 234 | 235 | createWindow(); 236 | } 237 | }); 238 | 239 | app.on("ready", function () { 240 | autoUpdater.checkForUpdatesAndNotify(); 241 | }); 242 | // app quits. 243 | //------------------------------------------------------------------- 244 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 15 | 16 | 25 | Rubrik GraphQL Playground 26 | 27 | 28 | 29 |
30 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Rubrik GraphQL Playground", 3 | "name": "Rubrik GraphQL Playground", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /script/notarize.js: -------------------------------------------------------------------------------- 1 | require("dotenv").config(); 2 | const { notarize } = require("electron-notarize"); 3 | 4 | exports.default = async function notarizing(context) { 5 | const { electronPlatformName, appOutDir } = context; 6 | if (electronPlatformName !== "darwin") { 7 | return; 8 | } 9 | 10 | const appName = context.packager.appInfo.productFilename; 11 | 12 | return await notarize({ 13 | appBundleId: "com.rubrikinc.graphql-playground", 14 | appPath: `${appOutDir}/${appName}.app`, 15 | appleId: process.env.APPLEID, 16 | appleIdPassword: process.env.APPLEIDPASS, 17 | }); 18 | }; 19 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import LandingPage from "./components/landingPage/LandingPage"; 3 | import GraphiQl from "./components/graphiql/GraphiQl"; 4 | 5 | class App extends Component { 6 | constructor(props) { 7 | super(props); 8 | 9 | this.state = { 10 | platform: null, 11 | nodeIp: null, 12 | username: null, 13 | password: null, 14 | cdmApiToken: null, 15 | apiToken: null, 16 | polarisDomain: null, 17 | }; 18 | 19 | this.handleCredentialUpdate = this.handleCredentialUpdate.bind(this); 20 | } 21 | 22 | handleCredentialUpdate( 23 | platform, 24 | nodeIp, 25 | username, 26 | password, 27 | apiToken, 28 | polarisDomain 29 | ) { 30 | this.setState({ 31 | platform, 32 | nodeIp, 33 | username, 34 | password, 35 | apiToken, 36 | polarisDomain, 37 | }); 38 | } 39 | 40 | render() { 41 | if (this.state.apiToken == null) { 42 | return ( 43 | 52 | this.handleCredentialUpdate( 53 | platform, 54 | nodeIp, 55 | username, 56 | password, 57 | apiToken, 58 | polarisDomain 59 | ) 60 | } 61 | /> 62 | ); 63 | } else { 64 | return ( 65 | 73 | ); 74 | } 75 | } 76 | } 77 | 78 | export default App; 79 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /src/components/defaultSettings/CdmApiTokenToggle.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import List from "@material-ui/core/List"; 4 | import ListItem from "@material-ui/core/ListItem"; 5 | import ListItemIcon from "@material-ui/core/ListItemIcon"; 6 | import ListItemSecondaryAction from "@material-ui/core/ListItemSecondaryAction"; 7 | import ListItemText from "@material-ui/core/ListItemText"; 8 | 9 | import AssignmentIndIcon from "@material-ui/icons/AssignmentInd"; 10 | 11 | import Switch from "@material-ui/core/Switch"; 12 | import FormControlLabel from "@material-ui/core/FormControlLabel"; 13 | 14 | const storage = window.localStorage; 15 | 16 | const convertStringToBoolean = (string) => { 17 | let bool; 18 | string === "false" ? (bool = false) : (bool = true); 19 | return bool; 20 | }; 21 | 22 | const CdmApiTokenToggle = ({ handleCdmApiTokenState }) => { 23 | const [state, setState] = React.useState( 24 | storage.getItem("cdmApiToken") === null 25 | ? false 26 | : convertStringToBoolean(storage.getItem("cdmApiToken")) 27 | ); 28 | 29 | const handleChange = (event) => { 30 | setState(event.target.checked); 31 | handleCdmApiTokenState(event.target.checked); 32 | }; 33 | 34 | return ( 35 | 36 | 37 | 38 | 39 | 40 | 44 | 45 | 54 | } 55 | /> 56 | 57 | 58 | 59 | ); 60 | }; 61 | 62 | export default CdmApiTokenToggle; 63 | -------------------------------------------------------------------------------- /src/components/defaultSettings/DefaultPlatformSelection.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import FormControl from "@material-ui/core/FormControl"; 4 | import { makeStyles } from "@material-ui/core/styles"; 5 | import List from "@material-ui/core/List"; 6 | import ListItem from "@material-ui/core/ListItem"; 7 | import ListItemIcon from "@material-ui/core/ListItemIcon"; 8 | import ListItemSecondaryAction from "@material-ui/core/ListItemSecondaryAction"; 9 | import ListItemText from "@material-ui/core/ListItemText"; 10 | import Select from "@material-ui/core/Select"; 11 | import MenuItem from "@material-ui/core/MenuItem"; 12 | 13 | import DesktopMacIcon from "@material-ui/icons/DesktopMac"; 14 | 15 | // Used to format the Select dropdown 16 | const useStyles = makeStyles(() => ({ 17 | formControl: { 18 | minWidth: 100, 19 | marginRight: 20, 20 | }, 21 | })); 22 | 23 | const storage = window.localStorage; 24 | 25 | const DefaultPlatform = ({ handleDefaultPlatform }) => { 26 | const classes = useStyles(); 27 | const [platform, setPlatform] = React.useState( 28 | storage.getItem("platform") === null ? "none" : storage.getItem("platform") 29 | ); 30 | 31 | const handleChange = (event) => { 32 | setPlatform(event.target.value); 33 | handleDefaultPlatform(event.target.value); 34 | }; 35 | 36 | return ( 37 | 38 | 39 | 40 | 41 | 42 | 46 | 47 | 48 | 58 | 59 | 60 | 61 | 62 | ); 63 | }; 64 | 65 | export default DefaultPlatform; 66 | -------------------------------------------------------------------------------- /src/components/defaultSettings/PolarisDevelopmentModeToggle.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import List from "@material-ui/core/List"; 4 | import ListItem from "@material-ui/core/ListItem"; 5 | import ListItemIcon from "@material-ui/core/ListItemIcon"; 6 | import ListItemSecondaryAction from "@material-ui/core/ListItemSecondaryAction"; 7 | import ListItemText from "@material-ui/core/ListItemText"; 8 | import CodeIcon from "@material-ui/icons/Code"; 9 | 10 | import Switch from "@material-ui/core/Switch"; 11 | import FormControlLabel from "@material-ui/core/FormControlLabel"; 12 | 13 | const storage = window.localStorage; 14 | 15 | const convertStringToBoolean = (string) => { 16 | let bool; 17 | string === "false" ? (bool = false) : (bool = true); 18 | return bool; 19 | }; 20 | 21 | const PolarisDevelopmentModeToggle = ({ handlePolarisDevModeState }) => { 22 | const [state, setState] = React.useState( 23 | storage.getItem("polarisDevMode") === null 24 | ? false 25 | : convertStringToBoolean(storage.getItem("polarisDevMode")) 26 | ); 27 | 28 | const handleChange = (event) => { 29 | setState(event.target.checked); 30 | 31 | handlePolarisDevModeState(event.target.checked); 32 | }; 33 | 34 | return ( 35 | 36 | 37 | 38 | 39 | 40 | 44 | 45 | 53 | } 54 | /> 55 | 56 | 57 | 58 | ); 59 | }; 60 | 61 | export default PolarisDevelopmentModeToggle; 62 | -------------------------------------------------------------------------------- /src/components/defaultSettings/SettingsDialog.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { withStyles } from "@material-ui/core/styles"; 3 | 4 | import IconButton from "@material-ui/core/IconButton"; 5 | import CloseIcon from "@material-ui/icons/Close"; 6 | import SettingsIcon from "@material-ui/icons/Settings"; 7 | 8 | import Typography from "@material-ui/core/Typography"; 9 | 10 | import Button from "@material-ui/core/Button"; 11 | 12 | import Dialog from "@material-ui/core/Dialog"; 13 | import MuiDialogTitle from "@material-ui/core/DialogTitle"; 14 | import MuiDialogContent from "@material-ui/core/DialogContent"; 15 | import MuiDialogActions from "@material-ui/core/DialogActions"; 16 | 17 | import CdmApiTokenToggle from "./CdmApiTokenToggle"; 18 | import PolarisDevelopmentModeToggle from "./PolarisDevelopmentModeToggle"; 19 | import DefaultPlatformSelection from "./DefaultPlatformSelection"; 20 | 21 | import { createMuiTheme } from "@material-ui/core/styles"; 22 | import { ThemeProvider } from "@material-ui/styles"; 23 | 24 | const theme = createMuiTheme({ 25 | palette: { 26 | primary: { 27 | main: "#0086C0", 28 | }, 29 | }, 30 | }); 31 | 32 | const styles = (theme) => ({ 33 | root: { 34 | margin: 0, 35 | padding: theme.spacing(2), 36 | }, 37 | closeButton: { 38 | position: "absolute", 39 | right: theme.spacing(1), 40 | top: theme.spacing(1), 41 | color: theme.palette.grey[500], 42 | }, 43 | colorstrip: { 44 | "border-top": "solid 6px #0086C0", 45 | }, 46 | }); 47 | 48 | const DialogTitle = withStyles(styles)((props) => { 49 | const { children, classes, onClose, ...other } = props; 50 | return ( 51 | 56 | {children} 57 | {onClose ? ( 58 | 63 | 64 | 65 | ) : null} 66 | 67 | ); 68 | }); 69 | 70 | const DialogContent = withStyles((theme) => ({ 71 | root: { 72 | padding: theme.spacing(2), 73 | }, 74 | }))(MuiDialogContent); 75 | 76 | const DialogActions = withStyles((theme) => ({ 77 | root: { 78 | margin: 0, 79 | padding: theme.spacing(1), 80 | }, 81 | }))(MuiDialogActions); 82 | 83 | const storage = window.localStorage; 84 | 85 | export default function SettingsDialog(props) { 86 | const [settingsOpen, setSettingsOpen] = React.useState(false); 87 | const [cdmApiToken, setCdmApiTokenState] = React.useState(false); 88 | const [polarisDevMode, setPolarisDevModeState] = React.useState(false); 89 | const [defaultPlatform, setDefaultPlatform] = React.useState("none"); 90 | 91 | const handleSettingsOpen = () => { 92 | setSettingsOpen(true); 93 | }; 94 | 95 | const handleSettingsClose = () => { 96 | setSettingsOpen(false); 97 | }; 98 | 99 | const handleSaveSettings = (event) => { 100 | event.preventDefault(); 101 | 102 | storage.setItem("platform", defaultPlatform); 103 | storage.setItem("cdmApiToken", cdmApiToken); 104 | storage.setItem("polarisDevMode", polarisDevMode); 105 | 106 | props.handleDefaultUpdate(defaultPlatform, cdmApiToken, polarisDevMode); 107 | setSettingsOpen(false); 108 | }; 109 | 110 | const settingsIcon = () => { 111 | return ( 112 |
113 | 114 | 115 | 116 |
117 | ); 118 | }; 119 | 120 | // TODO: Combine the toggle handles into a single function 121 | const handleCdmApiTokenState = (state) => { 122 | setCdmApiTokenState(state); 123 | }; 124 | 125 | const handlePolarisDevModeState = (state) => { 126 | setPolarisDevModeState(state); 127 | }; 128 | 129 | const handleDefaultPlatform = (platform) => { 130 | setDefaultPlatform(platform); 131 | }; 132 | 133 | const settingsDialog = () => { 134 | return ( 135 | 136 | {settingsIcon()} 137 | handleSettingsClose(event)} 139 | aria-labelledby="customized-dialog-title" 140 | open={settingsOpen} 141 | fullWidth={true} 142 | maxWidth="md" 143 | > 144 | handleSettingsClose(event)} 147 | > 148 | Default Playground Settings 149 | 150 | 151 |
152 | 153 | 154 | 157 | 158 | 161 | 164 | 165 | 166 | 167 | 168 | 171 | 172 | 173 |
174 |
175 |
176 | ); 177 | }; 178 | 179 | return settingsDialog(); 180 | } 181 | -------------------------------------------------------------------------------- /src/components/graphiql/GraphiQl.css: -------------------------------------------------------------------------------- 1 | .graphiql-container .type-name { 2 | font-weight: 350; 3 | } 4 | -------------------------------------------------------------------------------- /src/components/graphiql/GraphiQl.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import GraphiQL from "graphiql"; 3 | import "graphiql/graphiql.css"; 4 | // Import custom changes to the GraphiQl CSS that improves the visability 5 | // of the Types 6 | import "./GraphiQl.css"; 7 | import { graphQLFetcher } from "../../utils/api"; 8 | import rubrikLogo from "../../images/rubrikLogo.svg"; 9 | 10 | class GraphiQl extends Component { 11 | render() { 12 | return ( 13 | 15 | graphQLFetcher( 16 | graphQLParams, 17 | this.props.platform, 18 | this.props.nodeIp, 19 | this.props.username, 20 | this.props.password, 21 | this.props.apiToken, 22 | this.props.polarisDomain 23 | ) 24 | } 25 | > 26 | 27 | Rubrik logo 28 | 29 | 30 | ); 31 | } 32 | } 33 | 34 | export default GraphiQl; 35 | -------------------------------------------------------------------------------- /src/components/landingPage/LandingPage.css: -------------------------------------------------------------------------------- 1 | .landing-page { 2 | display: flex; 3 | } 4 | .welcome-message { 5 | display: flex; 6 | flex-direction: column; 7 | background-image: url("../../images/pattern.png"), 8 | radial-gradient( 9 | circle at center center, 10 | rgb(0, 88, 140) 5%, 11 | rgb(22, 41, 43) 80% 12 | ); 13 | flex-grow: 1; 14 | justify-content: space-between; 15 | 16 | align-items: center; 17 | height: 100vh; 18 | } 19 | 20 | .center-white-text { 21 | color: rgb(255, 255, 255); 22 | text-align: center; 23 | font-size: 1.86rem; 24 | } 25 | 26 | .larger-font-size { 27 | font-size: 2.086rem; 28 | } 29 | 30 | .bold-text { 31 | font-weight: 600; 32 | } 33 | 34 | .bottom-white-small-text { 35 | color: rgb(255, 255, 255); 36 | font-size: 1.143rem; 37 | margin-bottom: 2.286rem; 38 | } 39 | 40 | .thin-text { 41 | font-weight: 200; 42 | } 43 | 44 | .login { 45 | -webkit-box-flex: 0; 46 | flex-grow: 0; 47 | flex-basis: 38.857rem; 48 | align-items: center; 49 | } 50 | 51 | .login-text { 52 | font-weight: 100; 53 | color: rgb(22, 41, 43); 54 | font-size: 1.986rem; 55 | margin-bottom: 1.023rem; 56 | } 57 | 58 | .error-text { 59 | font-weight: 400; 60 | color: rgb(22, 41, 43); 61 | font-size: 1.286rem; 62 | margin-bottom: 1.023rem; 63 | text-align: center; 64 | } 65 | 66 | .flex-container { 67 | height: 85%; 68 | display: -webkit-box; 69 | display: -moz-box; 70 | display: -ms-flexbox; 71 | display: -webkit-flex; 72 | display: flex; 73 | align-items: center; 74 | justify-content: center; 75 | } 76 | .flex-row { 77 | width: 85%; 78 | } 79 | 80 | .display-flex-justify { 81 | display: flex !important; 82 | justify-content: center !important; 83 | } 84 | 85 | .primary-button { 86 | border-radius: 0.286rem; 87 | line-height: 0.23; 88 | color: #fff; 89 | background-color: rgb(0, 134, 192); 90 | border-color: rgb(0, 134, 192); 91 | 92 | box-shadow: none; 93 | display: inline-block; 94 | width: 100%; 95 | margin-top: 20px; 96 | box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 97 | 0 1px 5px 0 rgba(0, 0, 0, 0.12); 98 | } 99 | 100 | .primary-button:hover { 101 | background-color: #18b8e9; 102 | border-color: #18b8e9; 103 | } 104 | 105 | .btn-row { 106 | display: flex; 107 | } 108 | 109 | .btn-column { 110 | flex: 33.33%; 111 | padding: 5px; 112 | } 113 | 114 | h3 { 115 | font-weight: 200; 116 | font-size: 1.0775rem; 117 | font-family: "Open Sans", sans-serif; 118 | text-transform: uppercase; 119 | } 120 | 121 | .hide { 122 | display: none; 123 | } 124 | 125 | a:link { 126 | color: black; 127 | font-weight: 100; 128 | color: rgb(22, 41, 43); 129 | font-size: 0.986rem; 130 | margin-top: 1.023rem; 131 | text-decoration: none; 132 | } 133 | 134 | .bottom-right { 135 | position: fixed; 136 | bottom: 0; 137 | right: 0; 138 | margin-bottom: 1.023rem; 139 | margin-right: 1.023rem; 140 | } 141 | 142 | .top-right { 143 | position: fixed; 144 | top: 0; 145 | right: 0; 146 | margin-bottom: 1.023rem; 147 | margin-right: 1.023rem; 148 | } 149 | -------------------------------------------------------------------------------- /src/components/landingPage/LandingPage.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | 3 | import SettingsDialog from "../defaultSettings/SettingsDialog"; 4 | 5 | // App Component related imports 6 | import "./LandingPage.css"; 7 | import rubrikLogo from "../../images/rubrikLogo.svg"; 8 | import LoginForm from "../loginForm/LoginForm"; 9 | import { validateCredentials, userFiendlyErrorMessage } from "../../utils/api"; 10 | 11 | // Material-UI related imports 12 | import CodeIcon from "@material-ui/icons/Code"; 13 | import PersonIcon from "@material-ui/icons/Person"; 14 | import IconButton from "@material-ui/core/IconButton"; 15 | 16 | import Tooltip from "@material-ui/core/Tooltip"; 17 | import Typography from "@material-ui/core/Typography"; 18 | 19 | import { withStyles } from "@material-ui/core/styles"; 20 | 21 | const selectYourPlatformFormHeader = "Select your Platform"; 22 | const loginButtonText = "Login"; 23 | const connectingToPlatformButtonText = "Attempting to Connect"; 24 | const polarisUserDomain = ".my.rubrik.com"; 25 | const polarisDevDomain = ".dev.my.rubrik-lab.com"; 26 | 27 | const storage = window.localStorage; 28 | 29 | const convertStringToBoolean = (string) => { 30 | let bool; 31 | string === "false" ? (bool = false) : (bool = true); 32 | return bool; 33 | }; 34 | 35 | class LandingPage extends Component { 36 | constructor(props) { 37 | super(props); 38 | 39 | this.state = { 40 | formHeader: selectYourPlatformFormHeader, 41 | platform: 42 | storage.getItem("platform") === "none" 43 | ? null 44 | : storage.getItem("platform"), 45 | loginButtonText: loginButtonText, 46 | loginErrorMessage: null, 47 | apiToken: null, 48 | ip: null, 49 | username: null, 50 | password: null, 51 | cdmApiToken: null, 52 | polarisDomain: polarisUserDomain, 53 | usingCdmApiToken: 54 | storage.getItem("cdmApiToken") === null 55 | ? false 56 | : convertStringToBoolean(storage.getItem("cdmApiToken")), 57 | 58 | settingsOpen: true, 59 | }; 60 | 61 | this.createLoginForm = this.createLoginForm.bind(this); 62 | this.handleSwitchToLogin = this.handleSwitchToLogin.bind(this); 63 | this.handleSelectYourPlatform = this.handleSelectYourPlatform.bind(this); 64 | this.onFormChange = this.onFormChange.bind(this); 65 | this.handleLoginButton = this.handleLoginButton.bind(this); 66 | this.createLoginHeader = this.createLoginHeader.bind(this); 67 | this.createDevModeIcon = this.createDevModeIcon.bind(this); 68 | this.handleModeButton = this.handleModeButton.bind(this); 69 | this.handleDefaultUpdate = this.handleDefaultUpdate.bind(this); 70 | } 71 | 72 | componentDidMount() { 73 | // storage.clear(); 74 | 75 | if (storage.getItem("platform") !== null) { 76 | this.setState({ 77 | formHeader: loginButtonText, 78 | }); 79 | } 80 | 81 | if (storage.getItem("polarisDevMode") === "true") { 82 | this.setState({ 83 | polarisDomain: polarisDevDomain, 84 | }); 85 | } 86 | } 87 | 88 | handleSwitchToLogin(event) { 89 | event.preventDefault(); 90 | 91 | this.setState({ 92 | platform: event.target.textContent.toLowerCase(), 93 | formHeader: loginButtonText, 94 | }); 95 | } 96 | 97 | async handleLoginButton(event) { 98 | event.preventDefault(); 99 | this.setState({ 100 | loginButtonText: connectingToPlatformButtonText, 101 | loginErrorMessage: null, 102 | }); 103 | 104 | try { 105 | let apiToken = await validateCredentials( 106 | this.state.platform, 107 | this.state.ip, 108 | this.state.username, 109 | this.state.password, 110 | this.state.cdmApiToken, 111 | this.state.usingCdmApiToken, 112 | this.state.polarisDomain 113 | ); 114 | 115 | this.setState({ 116 | apiToken: this.state.cdmApiToken ? this.state.cdmApiToken : apiToken, 117 | loginButtonText: "Login", 118 | }); 119 | 120 | // If using API Token Authentication for CDM connectivity, reset the username 121 | // and password to null in case they were also filled out in the login form 122 | if (this.state.usingCdmApiToken) { 123 | this.setState({ 124 | username: null, 125 | password: null, 126 | }); 127 | } 128 | 129 | this.props.credentialUpdate( 130 | this.state.platform, 131 | this.state.ip, 132 | this.state.username, 133 | this.state.password, 134 | this.state.apiToken, 135 | this.state.polarisDomain 136 | ); 137 | } catch (error) { 138 | this.setState({ 139 | loginErrorMessage: userFiendlyErrorMessage( 140 | error, 141 | this.state.usingCdmApiToken 142 | ), 143 | loginButtonText: loginButtonText, 144 | }); 145 | } 146 | } 147 | 148 | handleSelectYourPlatform(event, platform) { 149 | this.setState({ 150 | platform: this.state.platform === "polaris" ? "cdm" : "polaris", 151 | loginErrorMessage: null, 152 | // usingCdmApiToken: false, 153 | }); 154 | } 155 | 156 | handleDefaultUpdate(platform, cdmApiToken, polarisDevMode) { 157 | if (this.state.platform !== platform) { 158 | this.setState({ 159 | platform: platform === "none" ? null : platform, 160 | }); 161 | } 162 | 163 | if (this.state.usingCdmApiToken !== cdmApiToken) { 164 | this.setState({ 165 | usingCdmApiToken: cdmApiToken, 166 | }); 167 | } 168 | 169 | this.setState({ 170 | polarisDomain: 171 | polarisDevMode === true ? polarisDevDomain : polarisUserDomain, 172 | }); 173 | } 174 | 175 | handleModeButton() { 176 | this.setState({ 177 | polarisDomain: 178 | this.state.polarisDomain === polarisUserDomain 179 | ? polarisDevDomain 180 | : polarisUserDomain, 181 | }); 182 | } 183 | 184 | onFormChange(event) { 185 | // This function handles the input from the form fields and sets the 186 | // appropriate state. 187 | 188 | if (event.target.id !== "useApiTokenCheckBox") { 189 | this.setState({ [event.target.id]: event.target.value }); 190 | } else { 191 | this.setState({ 192 | usingCdmApiToken: event.target.checked, 193 | }); 194 | } 195 | } 196 | 197 | createFullLandingPageUi() { 198 | return ( 199 | 200 |
201 | 202 | {this.createWelcome()} 203 | 204 | {this.createLogin()} 205 |
206 |
207 | ); 208 | } 209 | 210 | // Creates the "Welcome to the Rubrik GraphQL Playground" UI 211 | createWelcome() { 212 | return ( 213 |
214 |
215 |
216 |
217 | Welcome to the 218 | 219 | Rubrik GraphQL Playground 220 | 221 |
222 |
223 |
224 | 225 | Don't Backup. 226 | 227 | Go Forward. 228 |
229 |
230 | ); 231 | } 232 | 233 | // Creates the right side of the Welcome screen where the login form lives 234 | createLogin() { 235 | return ( 236 |
237 |
238 |
239 | {this.createLoginLogo()} 240 | {this.createLoginHeader()} 241 | {this.state.platform === null && this.createLoginPlatformButtons()} 242 | {this.state.platform != null && this.createLoginForm()} 243 | {this.createRwpLink()} 244 | {this.createDevModeIcon()} 245 |
246 |
247 |
248 | ); 249 | } 250 | 251 | createLoginLogo() { 252 | return ( 253 |
254 | Rubrik logo 255 |
256 | ); 257 | } 258 | 259 | createLoginHeader() { 260 | return ( 261 | 262 |
263 | {this.state.formHeader} 264 |
265 | {this.state.platform != null && this.createLoginErrorMessage()} 266 |
267 | ); 268 | } 269 | 270 | createLoginErrorMessage() { 271 | return ( 272 |
273 | {this.state.loginErrorMessage} 274 |
275 | ); 276 | } 277 | 278 | createLoginPlatformButtons() { 279 | return ( 280 |
281 |
282 | 289 |
290 |
291 | 298 |
299 |
300 | ); 301 | } 302 | 303 | createRwpLink() { 304 | // TODO: If you try to download the link when you don't have internet access the app goes blank 305 | // Until error handling is in place for this, we are are just going to return null 306 | // return ( 307 | // 312 | // ); 313 | return; 314 | } 315 | 316 | createDevModeIcon() { 317 | const HtmlTooltip = withStyles((theme) => ({ 318 | tooltip: { 319 | backgroundColor: "rgb(255, 255, 255)", 320 | color: "rgba(0, 0, 0, 0.87)", 321 | maxWidth: 220, 322 | "text-align": "center", 323 | }, 324 | }))(Tooltip); 325 | 326 | if (this.state.platform === "polaris") { 327 | return ( 328 |
329 | 332 | 333 | {this.state.polarisDomain === polarisUserDomain 334 | ? "Set the Polaris Domain to development. Internal Rubrik use only." 335 | : "Set the Polaris Domain to production."} 336 | 337 | 338 | } 339 | > 340 | 341 | {this.state.polarisDomain === polarisUserDomain ? ( 342 | 343 | ) : ( 344 | 345 | )} 346 | 347 | 348 |
349 | ); 350 | } else { 351 | return; 352 | } 353 | } 354 | 355 | createLoginForm() { 356 | return ( 357 | 370 | ); 371 | } 372 | 373 | render() { 374 | return this.createFullLandingPageUi(); 375 | } 376 | } 377 | 378 | export default LandingPage; 379 | -------------------------------------------------------------------------------- /src/components/loginForm/LoginForm.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import TextField from "@material-ui/core/TextField"; 3 | import { makeStyles } from "@material-ui/core/styles"; 4 | import { Button } from "@material-ui/core"; 5 | import FormControlLabel from "@material-ui/core/FormControlLabel"; 6 | import Checkbox from "@material-ui/core/Checkbox"; 7 | 8 | import InputAdornment from "@material-ui/core/InputAdornment"; 9 | import "../../components/landingPage/LandingPage.css"; 10 | 11 | const useStylesForm = makeStyles((theme) => ({ 12 | root: { 13 | "& .MuiTextField-root": { 14 | margin: theme.spacing(1), 15 | width: "100%", 16 | }, 17 | }, 18 | })); 19 | 20 | const useStylesSlectPlatformButton = makeStyles((theme) => ({ 21 | root: { 22 | "& > *": { 23 | backgroundColor: "#FFF", 24 | "&:hover": { 25 | backgroundColor: "#FFF", 26 | }, 27 | width: "100%", 28 | textTransform: "none", 29 | "font-weight": 100, 30 | "font-size": " 1.0775rem", 31 | }, 32 | }, 33 | })); 34 | 35 | const useStylesLoginButton = makeStyles((theme) => ({ 36 | root: { 37 | "& > *": { 38 | margin: theme.spacing(1), 39 | width: "100%", 40 | "&:hover": { 41 | "background-color": "#18b8e9", 42 | "border-color": "#18b8e9", 43 | }, 44 | "border-radius": "0.286rem", 45 | "line-height": " 1.83", 46 | color: "#fff", 47 | "background-color": "rgb(0, 134, 192)", 48 | "border-color": "rgb(0, 134, 192)", 49 | display: "inline-block", 50 | "margin-top": "20px", 51 | "font-weight": 200, 52 | "font-size": "1.0775rem", 53 | "text-transform": "uppercase", 54 | "box-shadow": 55 | "0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12)", 56 | }, 57 | }, 58 | })); 59 | 60 | export default function LoginForm(props) { 61 | const classesForm = useStylesForm(); 62 | const classesSelectPlatformButton = useStylesSlectPlatformButton(); 63 | const classesLoginButton = useStylesLoginButton(); 64 | 65 | function diableLoginButton() { 66 | // TODO: This function controls whether or not the LOGIN button is disabled. 67 | // The logic is super super ugly and can be cleaned up but it works 68 | 69 | if (props.usingCdmApiToken === false) { 70 | if ( 71 | props.ip === null || 72 | props.username === null || 73 | props.password === null 74 | ) { 75 | return true; 76 | } 77 | if (props.ip !== null) { 78 | if (props.ip.length <= 0) { 79 | return true; 80 | } 81 | } 82 | 83 | if (props.username !== null) { 84 | if (props.username.length <= 0) { 85 | return true; 86 | } 87 | } 88 | 89 | if (props.password !== null) { 90 | if (props.password.length <= 0) { 91 | return true; 92 | } 93 | } 94 | 95 | if (props.loginButtonText !== "Login") { 96 | return true; 97 | } 98 | } else { 99 | if (props.platform === "polaris") { 100 | if ( 101 | props.ip === null || 102 | props.username === null || 103 | props.password === null 104 | ) { 105 | return true; 106 | } 107 | if (props.ip !== null) { 108 | if (props.ip.length <= 0) { 109 | return true; 110 | } 111 | } 112 | 113 | if (props.username !== null) { 114 | if (props.username.length <= 0) { 115 | return true; 116 | } 117 | } 118 | 119 | if (props.password !== null) { 120 | if (props.password.length <= 0) { 121 | return true; 122 | } 123 | } 124 | 125 | if (props.loginButtonText !== "Login") { 126 | return true; 127 | } 128 | } else { 129 | if (props.ip === null || props.cdmApiToken === null) { 130 | return true; 131 | } 132 | if (props.ip !== null) { 133 | if (props.ip.length <= 0) { 134 | return true; 135 | } 136 | } 137 | 138 | if (props.cdmApiToken !== null) { 139 | if (props.cdmApiToken.length <= 0) { 140 | return true; 141 | } 142 | } 143 | 144 | if (props.loginButtonText !== "Login") { 145 | return true; 146 | } 147 | } 148 | } 149 | } 150 | 151 | return ( 152 |
props.loginButton(event)} 155 | autoComplete="off" 156 | > 157 |
158 | 171 | {props.polarisDomain} 172 | 173 | ), 174 | } 175 | } 176 | /> 177 | 178 | 191 | 192 | 204 | 205 | 218 | {/* TODO: Enable Remember Me functionality */} 219 | {/* 227 | } 228 | label="Remember me" 229 | /> */} 230 | 239 | } 240 | style={props.platform === "polaris" ? { display: "none" } : {}} 241 | label="Use API Token Authentication" 242 | /> 243 |
244 |
245 | 253 |
254 |
255 | 258 |
259 |
260 | ); 261 | } 262 | -------------------------------------------------------------------------------- /src/images/pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubrikinc/graphql-playground/b7840cda3a422847538525289f71a707dc7b2d25/src/images/pattern.png -------------------------------------------------------------------------------- /src/images/rubrikLogo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | #root { 2 | height: 100vh; 3 | } 4 | 5 | body { 6 | margin: 0; 7 | padding: 0; 8 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 9 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 10 | sans-serif; 11 | -webkit-font-smoothing: antialiased; 12 | -moz-osx-font-smoothing: grayscale; 13 | min-height: 100vh; 14 | } 15 | 16 | code { 17 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 18 | monospace; 19 | } 20 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | 9 | // If you want your app to work offline and load faster, you can change 10 | // unregister() to register() below. Note this comes with some pitfalls. 11 | // Learn more about service workers: http://bit.ly/CRA-PWA 12 | serviceWorker.unregister(); 13 | -------------------------------------------------------------------------------- /src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read http://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.1/8 is considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit http://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' + 74 | 'tabs for this page are closed. See http://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch(error => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl) 104 | .then(response => { 105 | // Ensure service worker exists, and that we really are getting a JS file. 106 | const contentType = response.headers.get('content-type'); 107 | if ( 108 | response.status === 404 || 109 | (contentType != null && contentType.indexOf('javascript') === -1) 110 | ) { 111 | // No service worker found. Probably a different app. Reload the page. 112 | navigator.serviceWorker.ready.then(registration => { 113 | registration.unregister().then(() => { 114 | window.location.reload(); 115 | }); 116 | }); 117 | } else { 118 | // Service worker found. Proceed as normal. 119 | registerValidSW(swUrl, config); 120 | } 121 | }) 122 | .catch(() => { 123 | console.log( 124 | 'No internet connection found. App is running in offline mode.' 125 | ); 126 | }); 127 | } 128 | 129 | export function unregister() { 130 | if ('serviceWorker' in navigator) { 131 | navigator.serviceWorker.ready.then(registration => { 132 | registration.unregister(); 133 | }); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/utils/api.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import https from "https"; 3 | import { request as httpsRequest } from "https"; 4 | 5 | const defaultHttpHeader = { 6 | "Content-Type": "application/json", 7 | "User-Agent": "RubrikGraphQLPlayground", 8 | }; 9 | 10 | function formatIp(ip) { 11 | /* 12 | * This function will processes the user provide CDM IP or Polaris Domain 13 | * and removes any values that will prevent connection to the platforms. 14 | */ 15 | 16 | return ip 17 | .replace("https://", "") 18 | .replace(".my.rubrik.com", "") 19 | .replace("/", ""); 20 | } 21 | 22 | export function userFiendlyErrorMessage(error, usingCdmApiToken) { 23 | /* 24 | * This function will processes an error mesage returned by an API call 25 | * and then provide a user friendly version of that error message 26 | */ 27 | if (error.response) { 28 | if (error.response.status === 401 || error.response.status === 422) { 29 | if (usingCdmApiToken === true) { 30 | return "Sorry, you entered an incorrect API token."; 31 | } else { 32 | return "Sorry, you entered an incorrect email or password."; 33 | } 34 | } else if (error.response.status === 400 || error.response.status === 401) { 35 | return "Sorry, the request was rejected as malformed by the Rubrik platform."; 36 | } else { 37 | return `Sorry, the request was rejected with a ${error.response.status} (${error.response.data.message}) HTTP response status code.`; 38 | } 39 | } else if ( 40 | error.message.includes("getaddrinfo ENOTFOUND") || 41 | error.message.includes("Network Error") 42 | ) { 43 | return "Sorry, we were unable to connect to the provided Rubrik platform."; 44 | } else if ( 45 | error.message.includes("connect ETIMEDOUT") || 46 | error.message.includes("timeout of 15000ms exceeded") 47 | ) { 48 | return "Sorry, the connection to the Rubrik platform timeout and we were unable to connect."; 49 | } else { 50 | return error.message; 51 | } 52 | } 53 | 54 | async function rubrikApiPost(url, httpHeaders, body) { 55 | /* 56 | * This function will make an HTTP Post using the supplied endpoint and 57 | * httpHeaders. 58 | */ 59 | 60 | const instance = axios.create({ 61 | timeout: 15000, 62 | httpsAgent: new https.Agent({ 63 | rejectUnauthorized: false, 64 | }), 65 | }); 66 | const response = await instance({ 67 | method: "post", 68 | url: url, 69 | headers: httpHeaders, 70 | data: body, 71 | }); 72 | 73 | return response; 74 | } 75 | 76 | async function rubrikApiGet(url, httpHeaders) { 77 | /* 78 | * This function will make an HTTP Post using the supplied endpoint and 79 | * httpHeaders. 80 | */ 81 | 82 | const instance = axios.create({ 83 | timeout: 15000, 84 | httpsAgent: new https.Agent({ 85 | rejectUnauthorized: false, 86 | }), 87 | }); 88 | const response = await instance({ 89 | method: "get", 90 | url: url, 91 | headers: httpHeaders, 92 | }); 93 | return response; 94 | } 95 | 96 | export async function validateCredentials( 97 | platform, 98 | nodeIp, 99 | username, 100 | password, 101 | cdmApiToken, 102 | usingCdmApiToken, 103 | polarisDomain 104 | ) { 105 | /* 106 | * This function makes an API request to CDM to validate the supplied 107 | * credentials. Since we use Basic authentication to make GQL calls to CDM, 108 | * which prevent token timeouts issues, we don't actually use the returned 109 | * API Token. 110 | */ 111 | let httpHeader = defaultHttpHeader; 112 | var endpoint; 113 | var postBody; 114 | if (platform === "cdm") { 115 | if (usingCdmApiToken) { 116 | httpHeader.Authorization = "Bearer " + cdmApiToken; 117 | } else { 118 | httpHeader.Authorization = "Basic " + btoa(username + ":" + password); 119 | } 120 | endpoint = "/api/v1/cluster/me/version"; 121 | postBody = {}; 122 | } else { 123 | httpHeader.Accept = "application/json, text/plain"; 124 | httpHeader["Content-Type"] = "application/json;charset=UTF-8"; 125 | endpoint = `${polarisDomain}/api/session`; 126 | postBody = { 127 | username: username, 128 | password: password, 129 | }; 130 | } 131 | const formattedNodeIp = formatIp(nodeIp); 132 | 133 | let url = `https://${formattedNodeIp}${endpoint}`; 134 | 135 | let response; 136 | if (platform === "cdm") { 137 | response = await rubrikApiGet(url, httpHeader); 138 | return response.data.version; 139 | } else { 140 | response = await rubrikApiPost(url, httpHeader, postBody); 141 | return response.data.access_token; 142 | } 143 | } 144 | 145 | export function graphQLFetcher( 146 | graphQLParams, 147 | platform, 148 | nodeIp, 149 | username, 150 | password, 151 | apiToken, 152 | polarisDomain 153 | ) { 154 | /* 155 | * This function is used by GraphiQl to make the GraphQL API calls. 156 | */ 157 | const formattedNodeIp = formatIp(nodeIp); 158 | let httpHeader = defaultHttpHeader; 159 | let endpointPrefix = `https://${formattedNodeIp}`; 160 | let endpointSuffixPolaris = `${polarisDomain}/api/graphql`; 161 | let endpointSuffixCdm = "/api/internal/graphql"; 162 | 163 | var endpoint; 164 | if (platform === "polaris") { 165 | httpHeader.Authorization = `Bearer ${apiToken}`; 166 | endpoint = endpointPrefix + endpointSuffixPolaris; 167 | } else { 168 | if (password === null) { 169 | httpHeader.Authorization = "Bearer " + apiToken; 170 | } else { 171 | httpHeader.Authorization = "Basic " + btoa(username + ":" + password); 172 | } 173 | endpoint = endpointPrefix + endpointSuffixCdm; 174 | } 175 | 176 | // TODO: Update to use rubrikApiPost 177 | const url = new URL(endpoint); 178 | 179 | const requestOptions = { 180 | method: "post", 181 | protocol: url.protocol, 182 | hostname: url.hostname, 183 | port: url.port, 184 | path: url.pathname + url.search, 185 | headers: httpHeader, 186 | rejectUnauthorized: false, // avoid problems with self-signed certs 187 | }; 188 | 189 | const request = httpsRequest(requestOptions); 190 | 191 | return new Promise((resolve, reject) => { 192 | request.on("response", (response) => { 193 | const chunks = []; 194 | response.on("data", (data) => { 195 | chunks.push(Buffer.from(data)); 196 | }); 197 | response.on("end", (end) => { 198 | const data = Buffer.concat(chunks).toString(); 199 | if (response.statusCode >= 400) { 200 | reject(JSON.parse(data)); 201 | } else { 202 | resolve(JSON.parse(data)); 203 | } 204 | }); 205 | }); 206 | 207 | request.on("error", reject); 208 | 209 | request.end(JSON.stringify(graphQLParams)); 210 | }); 211 | } 212 | --------------------------------------------------------------------------------