From 36581fb6d94a7ea188bf44df46d992ca6fbfa69a Mon Sep 17 00:00:00 2001 From: Steve Faulkner Date: Mon, 25 May 2020 21:30:55 -0500 Subject: [PATCH] Initial Move from Azure DevOps to GitHub --- .eslintignore | 436 + .eslintrc.js | 45 + .github/CODEOWNERS | 1 + .gitignore | 18 + .npmrc | 1 + .vscode/launch.json | 40 + .vscode/settings.json | 21 + DataExplorer.nuspec | 24 + LICENSE | 21 + README.md | 95 + ReleaseNotes.md | 10 + __mocks__/AddDatabaseUtility.ts | 5 + __mocks__/monaco-editor.ts | 4 + azure-pipelines.yaml | 211 + babel.config.js | 3 + copyToConsumers.js | 24 + cypress/.gitignore | 1 + cypress/cypress.json | 15 + .../CASSANDRA/addCollection.spec.ts | 66 + .../dataexplorer/GRAPH/addCollection.spec.ts | 81 + .../dataexplorer/MONGO/addCollection.spec.ts | 80 + .../MONGO/addCollectionAutopilot.spec.ts | 96 + .../addCollectionExistingDatabase.spec.ts | 67 + .../MONGO/provisionDatabaseThroughput.spec.ts | 203 + .../dataexplorer/SQL/addCollection.spec.ts | 78 + .../dataexplorer/TABLE/addCollection.spec.ts | 60 + .../ci-tests/addCollectionPane.spec.ts | 55 + .../ci-tests/createDatabase.spec.ts | 65 + .../ci-tests/deleteCollection.spec.ts | 46 + .../ci-tests/deleteDatabase.spec.ts | 83 + cypress/integration/notebook/README.md | 35 + .../integration/notebook/newNotebook.spec.ts | 93 + .../integration/notebook/resourceTree.spec.ts | 172 + cypress/package-lock.json | 3148 +++ cypress/package.json | 23 + cypress/support/index.js | 23 + cypress/tsconfig.json | 11 + cypress/utilities/connectionString.js | 56 + cypress/utilities/cosmosClient.js | 6 + externals/adal.js | 1963 ++ externals/bootstrap.js | 7 + externals/bootstrap.min.js | 7 + externals/bootstrap_ase.css | 6 + externals/bops.js | 595 + externals/crossroads.js | 723 + externals/dataTables.colReorder.js | 1254 ++ externals/dataTables.colResize.js | 846 + externals/datatables.js | 15321 +++++++++++++ externals/images/cut.png | Bin 0 -> 648 bytes externals/images/door.png | Bin 0 -> 412 bytes externals/images/page_white_add.png | Bin 0 -> 442 bytes externals/images/page_white_copy.png | Bin 0 -> 309 bytes externals/images/page_white_delete.png | Bin 0 -> 536 bytes externals/images/page_white_edit.png | Bin 0 -> 618 bytes externals/images/page_white_paste.png | Bin 0 -> 620 bytes externals/images/sort_both.png | Bin 0 -> 201 bytes .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 86 bytes externals/images/ui-icons_444444_256x240.png | Bin 0 -> 3756 bytes externals/images/ui-icons_555555_256x240.png | Bin 0 -> 3756 bytes externals/images/ui-icons_777620_256x240.png | Bin 0 -> 3756 bytes externals/images/ui-icons_777777_256x240.png | Bin 0 -> 3756 bytes externals/images/ui-icons_cc0000_256x240.png | Bin 0 -> 3756 bytes externals/images/ui-icons_ffffff_256x240.png | Bin 0 -> 3756 bytes externals/jquery-ui.min.css | 7 + externals/jquery-ui.min.js | 13 + externals/jquery-ui.structure.min.css | 5 + externals/jquery-ui.theme.min.css | 5 + externals/jquery.contextMenu.css | 177 + externals/jquery.contextMenu.js | 1686 ++ externals/jquery.dataTables.min.css | 1 + externals/jquery.dataTables.min.js | 163 + externals/jquery.dataTables.min_ase.css | 1 + externals/jquery.dataTables.min_ase.js | 160 + externals/jquery.datatables.js | 15129 +++++++++++++ externals/jquery.datatables_ase.js | 14950 ++++++++++++ externals/jquery.js | 11 + externals/jquery.min.js | 5 + externals/jquery.typeahead.css | 544 + externals/jquery.typeahead.js | 3083 +++ externals/jquery.typeahead.min.css | 1 + externals/jquery.typeahead.min.js | 11 + externals/jquery.ui.position.js | 497 + externals/msrCrypto.js | 19 + .../segoe-ui/west-european/normal/latest.woff | 177 + images/ASX_Delete.svg | 1 + images/ASX_More.svg | 45 + images/ASX_QueryBuilder.svg | 8 + images/ASX_Refresh.svg | 1 + images/ASX_Remove.svg | 1 + images/Add-disabled.svg | 3 + images/Add-property.svg | 8 + images/Add.svg | 3 + images/AddCollection-1.svg | 12 + images/AddCollection.svg | 12 + images/AddDatabase-disabled.svg | 4 + images/AddDatabase.svg | 4 + images/AddDocument-disabled.svg | 6 + images/AddDocument.svg | 8 + images/AddEntity-1.svg | 8 + images/AddEntity.svg | 8 + images/AddGraphQuery_16x16-1.svg | 17 + images/AddGraphQuery_16x16.svg | 17 + images/AddSqlQuery_16x16-1.svg | 8 + images/AddSqlQuery_16x16.svg | 8 + images/AddStoredProcedure-disabled.svg | 4 + images/AddStoredProcedure.svg | 4 + images/AddTrigger-disabled.svg | 4 + images/AddTrigger.svg | 4 + images/AddUdf-disabled.svg | 12 + images/AddUdf.svg | 12 + images/And-Or-disabled.svg | 5 + images/And-Or.svg | 5 + images/Arrow.svg | 10 + images/Azure-Cosmos-DB.svg | 7 + images/BrowseQuery-disabled.svg | 4 + images/BrowseQuery.svg | 4 + images/Chevron_Up-disabled.svg | 3 + images/Chevron_Up.svg | 3 + images/Chevron_down-disabled.svg | 3 + images/Chevron_down.svg | 3 + images/Clear-disabled.svg | 10 + images/Clear.svg | 10 + images/CollapseLeftNav-disabled.svg | 11 + images/CollapseLeftNav.svg | 11 + images/Collapse_arrow_14x14-disabled.svg | 3 + images/Collapse_arrow_14x14.svg | 3 + images/Connect-disabled.svg | 11 + images/Connect.svg | 11 + images/ConnectionString_Artwork.png | Bin 0 -> 47666 bytes images/Copy-disabled.svg | 3 + images/Copy.svg | 3 + images/Cosmos-Terminal-disabled.svg | 6 + images/Cosmos-Terminal.svg | 6 + images/CosmosDBHostedLogo.svg | 19 + images/CosmosDB_20170524.svg | 63 + images/CosmosDB_20170829.svg | 32 + images/CosmosDB_black.svg | 12 + images/CosmosDB_gray.svg | 36 + images/CosmosDB_rgb_ui_lighttheme.ico | Bin 0 -> 40368 bytes images/DeleteCollection-disabled.svg | 4 + images/DeleteCollection.svg | 4 + images/DeleteDatabase-disabled.svg | 4 + images/DeleteDatabase.svg | 4 + images/DeleteDocument-disabled.svg | 4 + images/DeleteDocument.svg | 4 + images/DeleteEntities-disabled.svg | 4 + images/DeleteEntities.svg | 4 + images/DeleteSproc-disabled.svg | 4 + images/DeleteSproc.svg | 4 + images/DeleteTrigger-disabled.svg | 4 + images/DeleteTrigger.svg | 4 + images/DeleteUDF-disabled.svg | 5 + images/DeleteUDF.svg | 5 + images/DirectorySwitch-disabled.svg | 3 + images/DirectorySwitch.svg | 3 + images/DocumentExplorerIcon-Blue.svg | 7 + images/DocumentExplorerIcon.svg | 19 + images/DocumentWaterMark.svg | 14 + images/Down-disabled.svg | 3 + images/Down.svg | 3 + images/DownloadQuery-disabled.svg | 10 + images/DownloadQuery.svg | 10 + images/Edit-entity-disabled.svg | 5 + images/Edit-entity.svg | 5 + images/Edit_entity-disabled.svg | 10 + images/Edit_entity.svg | 10 + images/Entity_cancel-disabled.svg | 3 + images/Entity_cancel.svg | 3 + images/ExecuteQuery-bigicon.svg | 4 + images/ExecuteQuery-disabled.svg | 10 + images/ExecuteQuery.svg | 10 + images/ExpandLeftNav-disabled.svg | 11 + images/ExpandLeftNav.svg | 11 + images/Expand_14x14-disabled.svg | 3 + images/Expand_14x14.svg | 3 + images/Explorer.svg | 11 + images/Feedback-Command.svg | 10 + images/Feedback.svg | 4 + images/GalleryIcon.svg | 10 + images/Halo_ProgressSpinner.svg | 12 + images/Hamburger.svg | 3 + images/HdeConnectCosmosDB.svg | 18 + images/Hero-new-container.svg | 4 + images/Hero-new-notebook.svg | 5 + images/Hero-sample.svg | 19 + images/HorizontalSplitter-disabled.svg | 4 + images/HorizontalSplitter.svg | 4 + images/Hosted-Terminal-disabled.svg | 3 + images/Hosted-Terminal.svg | 3 + images/HostedConnectwhite.svg | 4 + images/HostedExplorer.svg | 4 + images/HostedSettings-disabled.svg | 4 + images/HostedSettings.svg | 4 + images/Info.svg | 3 + images/LoadGraph.png | Bin 0 -> 5597 bytes images/LoadingIndicator_3Squares.gif | Bin 0 -> 2659 bytes images/NewDocument-disabled.svg | 4 + images/NewDocument.svg | 4 + images/NewVertex-disabled.svg | 8 + images/NewVertex.svg | 8 + images/OpenQueryFromDisk-disabled.svg | 15 + images/OpenQueryFromDisk.svg | 15 + images/Options-disabled.svg | 11 + images/Options.svg | 11 + images/Query-Builder-disabled.svg | 14 + images/Query-Builder.svg | 14 + images/Query-Editor-Next-Disabled.svg | 17 + images/Query-Editor-Next.svg | 14 + images/Query-Text-disabled.svg | 3 + images/Query-Text.svg | 3 + images/QueryBuilder/Add_green_16x.png | Bin 0 -> 203 bytes .../QueryBuilder/CollapseChevronDown_16x.png | Bin 0 -> 277 bytes images/QueryBuilder/CollapseChevronUp_16x.png | Bin 0 -> 345 bytes .../QueryBuilder/CustomActionEditor_16x.png | Bin 0 -> 21903 bytes images/QueryBuilder/Delete_16x.png | Bin 0 -> 283 bytes images/QueryBuilder/DropdownMenu_16x.png | Bin 0 -> 185 bytes images/QueryBuilder/EditEntity_16x.png | Bin 0 -> 532 bytes images/QueryBuilder/GroupClause_16x.png | Bin 0 -> 348 bytes images/QueryBuilder/Halo_ProgressSpinner.svg | 56 + images/QueryBuilder/QueryInformation_16x.png | Bin 0 -> 341 bytes images/QueryBuilder/ResetColumnOrder_16x.png | Bin 0 -> 540 bytes images/QueryBuilder/ShiftToLeft_16x.png | Bin 0 -> 354 bytes images/QueryBuilder/StatusInvalid_16x.png | Bin 0 -> 358 bytes images/QueryBuilder/StatusWarning_16x.png | Bin 0 -> 460 bytes images/QueryBuilder/UngroupClause_16x.png | Bin 0 -> 358 bytes images/Quickstart.svg | 4 + images/Reorder-disabled.svg | 5 + images/Reorder.svg | 5 + images/Reset-column-options-disabled.svg | 10 + images/Reset-column-options.svg | 10 + images/RevertBack.svg | 10 + images/RunQuery.png | Bin 0 -> 1232 bytes images/Scale_15x15-disabled.svg | 17 + images/Scale_15x15.svg | 17 + images/Settings.svg | 10 + images/Share-disabled.svg | 3 + images/Share.svg | 3 + images/Stop-disabled.svg | 10 + images/Stop.svg | 10 + images/Style-disabled.svg | 3 + images/Style.svg | 3 + images/Triangle-down.svg | 3 + images/Triangle-right.svg | 3 + images/Triangle-up.svg | 3 + images/Up-disabled.svg | 3 + images/Up.svg | 3 + images/Upload_16x16-disabled.svg | 3 + images/Upload_16x16.svg | 3 + images/apply-bigicon.svg | 1 + images/back.svg | 9 + images/cancel-disabled.svg | 3 + images/cancel-hover.svg | 8 + images/cancel.svg | 3 + images/check-disabled.svg | 10 + images/check.svg | 10 + images/chevron-right-disabled.svg | 3 + images/chevron-right.svg | 3 + images/circular_loader_black_16x16.gif | Bin 0 -> 11824 bytes images/close-black-active.svg | 6 + images/close-black-hover.svg | 6 + images/close-black.svg | 16 + images/close.svg | 6 + images/collections.svg | 155 + images/createDoc-bigicon.svg | 8 + images/createDoc-disabled.svg | 7 + images/createDoc.svg | 7 + images/createQuery-disabled.svg | 13 + images/createQuery.svg | 13 + images/delete-bigicon.svg | 9 + images/delete-disabled.svg | 3 + images/delete.svg | 3 + images/discard-bigicon.svg | 8 + images/discard-disabled.svg | 3 + images/discard.svg | 3 + images/documentDBCollectionsIcon.svg | 18 + images/documentDBLogo.svg | 5 + images/dotnet.png | Bin 0 -> 7074 bytes images/edit-disabled.svg | 10 + images/edit.svg | 10 + images/error.svg | 4 + images/error_black.svg | 3 + images/error_no_outline.svg | 1 + images/error_no_outline_hover.svg | 1 + images/error_red.svg | 10 + images/error_upload.svg | 3 + images/exploreDocDB.svg | 19 + images/favicon.ico | Bin 0 -> 17174 bytes images/filter-disabled.svg | 3 + images/filter.svg | 3 + images/folder_16x16-disabled.svg | 3 + images/folder_16x16.svg | 3 + images/github.svg | 3 + images/imgarrowlefticon-white.svg | 2 + images/imgarrowlefticon.svg | 5 + images/info-bubble-9x9.svg | 3 + images/info-bubble.svg | 3 + images/info_color.svg | 5 + images/java.png | Bin 0 -> 6707 bytes images/loading.svg | 3 + images/minusDefault.png | Bin 0 -> 15029 bytes images/minusDisabled.png | Bin 0 -> 15029 bytes images/minus_disabled.svg | 7 + images/minus_hover.svg | 7 + images/minus_normal.svg | 7 + images/minus_pressed.svg | 7 + images/new-edge-disabled.svg | 13 + images/new-edge.svg | 13 + images/nodejs.png | Bin 0 -> 7117 bytes images/notebook/Apache-spark-disabled.svg | 3 + images/notebook/Apache-spark.svg | 3 + .../notebook/Notebook resource-disabled.svg | 4 + images/notebook/Notebook resource.svg | 4 + .../Notebook-clear-all-outputs-disabled.svg | 3 + .../notebook/Notebook-clear-all-outputs.svg | 3 + images/notebook/Notebook-copy-disabled.svg | 3 + images/notebook/Notebook-copy.svg | 3 + images/notebook/Notebook-cut-disabled.svg | 3 + images/notebook/Notebook-cut.svg | 3 + images/notebook/Notebook-enable-disabled.svg | 4 + images/notebook/Notebook-enable.svg | 4 + .../Notebook-insert-cell-disabled.svg | 3 + images/notebook/Notebook-insert-cell.svg | 3 + .../Notebook-move cell down-disabled.svg | 3 + images/notebook/Notebook-move cell down.svg | 3 + .../Notebook-move cell up-disabled.svg | 3 + images/notebook/Notebook-move cell up.svg | 3 + images/notebook/Notebook-new-disabled.svg | 5 + images/notebook/Notebook-new.svg | 5 + images/notebook/Notebook-paste-disabled.svg | 3 + images/notebook/Notebook-paste.svg | 3 + images/notebook/Notebook-redo-disabled.svg | 10 + images/notebook/Notebook-redo.svg | 10 + .../Notebook-reset-workspace-disabled.svg | 10 + images/notebook/Notebook-reset-workspace.svg | 10 + .../notebook/Notebook-resource-disabled.svg | 4 + images/notebook/Notebook-resource.svg | 4 + .../Notebook-restart & rerun-disabled.svg | 9 + images/notebook/Notebook-restart & rerun.svg | 9 + images/notebook/Notebook-restart-disabled.svg | 8 + images/notebook/Notebook-restart.svg | 8 + images/notebook/Notebook-run-all-disabled.svg | 14 + images/notebook/Notebook-run-all.svg | 14 + images/notebook/Notebook-run-disabled.svg | 3 + images/notebook/Notebook-run.svg | 3 + images/notebook/Notebook-stop-disabled.svg | 3 + images/notebook/Notebook-stop.svg | 3 + images/notebook/Notebook-undo-disabled.svg | 10 + images/notebook/Notebook-undo.svg | 10 + .../Spark-library-manage-disabled.svg | 3 + images/notebook/Spark-library-manage.svg | 3 + images/notebook/Spark-query-new-disabled.svg | 15 + images/notebook/Spark-query-new.svg | 15 + images/notebook/add-code-cell.svg | 3 + images/notebook/add-text-cell.svg | 3 + images/notebook/file-cosmos.svg | 3 + images/notebook/file-disabled.svg | 3 + images/open-in-tab-disabled.svg | 3 + images/open-in-tab.svg | 3 + images/openQuery.svg | 16 + images/plus.svg | 154 + images/plusDefault.png | Bin 0 -> 15054 bytes images/plusDisabled.png | Bin 0 -> 15043 bytes images/plus_disabled.svg | 8 + images/plus_hover.svg | 8 + images/plus_normal.svg | 8 + images/plus_pressed.svg | 8 + images/previousPage-disabled.svg | 8 + images/previousPage.svg | 10 + images/price.png | Bin 0 -> 10639 bytes images/python.png | Bin 0 -> 6824 bytes images/refresh-cosmos.svg | 3 + images/refresh-disabled.svg | 3 + images/row-collapsed.svg | 3 + images/row-expanded.svg | 3 + images/save-bigicon.svg | 3 + images/save-cosmos.svg | 3 + images/save-disabled.svg | 3 + images/save_query_banner.png | Bin 0 -> 187210 bytes images/settings_15x15-disabled.svg | 10 + images/settings_15x15.svg | 10 + images/sort-down.svg | 12 + images/sort-right.svg | 13 + images/synapse-link.svg | 3 + images/tree-collection-disabled.svg | 3 + images/tree-collection.svg | 3 + images/tree-database.svg | 13 + images/tree-notebook.svg | 4 + images/uploadDoc-disabled.svg | 7 + images/uploadDoc.svg | 7 + images/warning.svg | 3 + images/win_hr_loader_black.gif | Bin 0 -> 9425 bytes jest.config.js | 184 + less/Common/Constants.less | 270 + less/Common/TabCommon.less | 10 + less/StorageExplorer.less | 1910 ++ less/TableStyles/CustomizeColumns.less | 126 + less/TableStyles/EntityEditor.less | 129 + less/TableStyles/fulldatatables.less | 653 + less/TableStyles/queryBuilder.less | 527 + less/documentDB.less | 2974 +++ less/forms.less | 203 + less/forms_ase.less | 17 + less/hostedexplorer.less | 718 + less/index.less | 611 + less/infobox.less | 33 + less/menus.less | 44 + less/messagebox.less | 266 + less/quickstart.less | 1311 ++ less/resourceTree.less | 23 + less/tree.less | 280 + mockModule.js | 2 + package-lock.json | 18689 ++++++++++++++++ package.json | 204 + quickstart/DocumentDB-Quickstart-DotNet.zip | Bin 0 -> 7807 bytes .../DocumentDB-Quickstart-DotNetCore.zip | Bin 0 -> 7807 bytes quickstart/DocumentDB-Quickstart-Java.zip | Bin 0 -> 9380 bytes quickstart/DocumentDB-Quickstart-NodeJs.zip | Bin 0 -> 4383 bytes quickstart/DocumentDB-Quickstart-Python.zip | Bin 0 -> 3328 bytes runIntegrationTests.cmd | 24 + sampleData/gremlinSampleData.json | 16 + sampleData/sqlSampleData.json | 26 + src/Api/Apis.ts | 13 + src/AuthType.ts | 6 + src/Bindings/BindingHandlersRegisterer.ts | 26 + src/Bindings/ReactBindingHandler.ts | 48 + src/Common/ArrayHashMap.ts | 87 + src/Common/Constants.ts | 541 + src/Common/CosmosClient.test.ts | 134 + src/Common/CosmosClient.ts | 176 + src/Common/DataAccessUtilityBase.test.ts | 13 + src/Common/DataAccessUtilityBase.ts | 678 + src/Common/DeleteFeedback.ts | 15 + src/Common/DocumentClientUtilityBase.ts | 1183 + src/Common/EditableUtility.ts | 94 + src/Common/EnvironmentUtility.ts | 48 + src/Common/ErrorParserUtility.test.ts | 24 + src/Common/ErrorParserUtility.ts | 67 + src/Common/HashMap.test.ts | 70 + src/Common/HashMap.ts | 45 + src/Common/HeadersUtility.test.ts | 25 + src/Common/HeadersUtility.ts | 28 + src/Common/IteratorUtilities.test.ts | 20 + src/Common/IteratorUtilities.ts | 32 + src/Common/Logger.test.ts | 46 + src/Common/Logger.ts | 87 + src/Common/MessageHandler.test.ts | 65 + src/Common/MessageHandler.ts | 85 + src/Common/MongoProxyClient.test.ts | 297 + src/Common/MongoProxyClient.ts | 475 + src/Common/MongoUtility.ts | 168 + src/Common/NotificationsClientBase.ts | 47 + src/Common/ObjectCache.test.ts | 33 + src/Common/ObjectCache.ts | 56 + src/Common/QueriesClient.ts | 286 + src/Common/Splitter.ts | 108 + src/Common/ThemeUtility.ts | 19 + src/Common/UrlUtility.ts | 55 + .../__snapshots__/CosmosClient.test.ts.snap | 21 + .../DataAccessUtilityBase.test.ts.snap | 21 + .../IteratorUtilities.test.ts.snap | 14 + src/Config.ts | 83 + src/Contracts/ActionContracts.ts | 83 + src/Contracts/DataModels.ts | 753 + src/Contracts/Diagnostics.ts | 55 + src/Contracts/ExplorerContracts.ts | 38 + src/Contracts/Versions.ts | 4 + src/Contracts/ViewModels.ts | 1321 ++ src/Controls/Heatmap/Heatmap.html | 11 + src/Controls/Heatmap/Heatmap.less | 55 + src/Controls/Heatmap/Heatmap.test.ts | 141 + src/Controls/Heatmap/Heatmap.ts | 268 + src/Controls/Heatmap/HeatmapDatatypes.ts | 106 + src/Definitions/adal.d.ts | 383 + src/Definitions/datatables.d.ts | 1954 ++ src/Definitions/gif.d.ts | 4 + src/Definitions/globals.d.ts | 9 + src/Definitions/html.d.ts | 4 + src/Definitions/jquery-typescript.d.ts | 34 + src/Definitions/jquery-ui.d.ts | 1771 ++ src/Definitions/jquery.contextmenu.d.ts | 42 + src/Definitions/jquery.d.ts | 1890 ++ .../plotly.js-cartesian-dist.d-min.ts | 1 + src/Definitions/png.d.ts | 4 + src/Definitions/svg.d.ts | 4 + src/Definitions/worker.d.ts | 7 + src/Explorer/ComponentRegisterer.test.ts | 178 + src/Explorer/ComponentRegisterer.ts | 98 + src/Explorer/ContextMenuButtonFactory.ts | 422 + .../AccessibleElement/AccessibleElement.tsx | 37 + .../Accordion/AccordionComponent.less | 35 + .../Controls/Accordion/AccordionComponent.tsx | 92 + .../AccountSwitchComponent.test.tsx | 159 + .../AccountSwitch/AccountSwitchComponent.tsx | 177 + .../AccountSwitchComponentAdapter.tsx | 11 + .../AccountSwitchComponent.test.tsx.snap | 71 + .../Controls/Arcadia/ArcadiaMenuPicker.tsx | 146 + .../CollapsiblePanel/CollapsiblePanel.tsx | 93 + .../CollapsiblePanelComponent.less | 116 + .../CollapsiblePanelComponent.ts | 56 + .../collapsible-panel-component.html | 44 + .../Controls/CommandButton/CommandButton.less | 200 + .../CommandButton/CommandButton.test.ts | 139 + .../Controls/CommandButton/CommandButton.ts | 191 + .../CommandButton/CommandButtonComponent.tsx | 280 + .../CommandButton/command-button.html | 40 + .../DialogReactComponent/DialogComponent.tsx | 93 + .../DialogComponentAdapter.tsx | 16 + .../DiffEditor/DiffEditorComponent.ts | 160 + .../DiffEditor/diff-editor-component.html | 1 + ...DefaultDirectoryDropdownComponent.test.tsx | 111 + .../DefaultDirectoryDropdownComponent.tsx | 70 + .../Directory/DirectoryComponentAdapter.tsx | 36 + .../Directory/DirectoryListComponent.test.tsx | 78 + .../Directory/DirectoryListComponent.tsx | 121 + ...ltDirectoryDropdownComponent.test.tsx.snap | 93 + .../DirectoryListComponent.test.tsx.snap | 1774 ++ .../Controls/DynamicList/DynamicList.test.ts | 64 + .../DynamicList/DynamicListComponent.less | 59 + .../DynamicList/DynamicListComponent.ts | 116 + .../Controls/DynamicList/dynamic-list.html | 34 + .../Controls/Editor/EditorComponent.ts | 63 + src/Explorer/Controls/Editor/EditorReact.tsx | 83 + .../Controls/Editor/editor-component.html | 1 + .../ErrorDisplayComponent.less | 57 + .../ErrorDisplayComponent.ts | 30 + .../error-display-component.html | 6 + .../Controls/GitHub/AddRepoComponent.tsx | 132 + .../GitHub/AuthorizeAccessComponent.tsx | 91 + .../Controls/GitHub/GitHubReposComponent.tsx | 82 + .../GitHub/GitHubReposComponentAdapter.tsx | 20 + .../Controls/GitHub/GitHubStyleConstants.ts | 58 + .../Controls/GitHub/ReposListComponent.tsx | 301 + .../InputTypeahead/InputTypeahead.less | 7 + .../Controls/InputTypeahead/InputTypeahead.ts | 189 + .../InputTypeaheadComponent.tsx | 228 + .../InputTypeahead/input-typeahead.html | 19 + .../JsonEditor/JsonEditorComponent.less | 8 + .../JsonEditor/JsonEditorComponent.ts | 171 + .../JsonEditor/json-editor-component.html | 1 + .../LibraryManagement/ClusterLibraryGrid.tsx | 40 + .../ClusterLibraryGridAdapter.tsx | 11 + .../LibraryManagement/LibraryManage.tsx | 156 + .../LibraryManageComponentAdapter.tsx | 11 + .../Notebook/NotebookAppMessageHandler.ts | 80 + .../Notebook/NotebookTerminalComponent.less | 13 + .../NotebookTerminalComponent.test.tsx | 158 + .../Notebook/NotebookTerminalComponent.tsx | 90 + .../NotebookMetadataComponent.tsx | 131 + .../NotebookViewer/NotebookViewer.less | 11 + .../NotebookViewer/NotebookViewer.tsx | 41 + .../NotebookViewerComponent.less | 26 + .../NotebookViewerComponent.tsx | 88 + .../NotebookViewer/notebookViewer.html | 13 + .../QueriesGridComponent.tsx | 288 + .../QueriesGridComponentAdapter.tsx | 32 + .../ResizeSensorComponent.tsx | 45 + .../Spark/ClusterSettingsComponent.less | 17 + .../Spark/ClusterSettingsComponent.tsx | 159 + .../Spark/ClusterSettingsComponentAdapter.tsx | 11 + src/Explorer/Controls/Tabs/TabComponent.less | 27 + src/Explorer/Controls/Tabs/TabComponent.tsx | 84 + .../ThroughputInput/ThroughputInput.test.ts | 222 + .../ThroughputInputComponent.html | 145 + .../ThroughputInputComponent.ts | 261 + .../ThroughputInputComponentAutoPilotV3.ts | 279 + .../ThroughputInputComponentAutoscaleV3.html | 164 + .../Controls/Toolbar/IToolbarAction.ts | 12 + .../Controls/Toolbar/IToolbarDisplayable.ts | 18 + .../Controls/Toolbar/IToolbarDropDown.ts | 56 + src/Explorer/Controls/Toolbar/IToolbarItem.ts | 12 + .../Controls/Toolbar/IToolbarSeperator.ts | 10 + .../Controls/Toolbar/IToolbarToggle.ts | 12 + src/Explorer/Controls/Toolbar/KeyCodes.ts | 58 + src/Explorer/Controls/Toolbar/Toolbar.ts | 145 + .../Controls/Toolbar/ToolbarAction.ts | 86 + .../Controls/Toolbar/ToolbarDropDown.ts | 167 + .../Controls/Toolbar/ToolbarToggle.ts | 109 + src/Explorer/Controls/Toolbar/Utilities.ts | 166 + src/Explorer/Controls/Toolbar/toolbar.html | 44 + .../TreeComponent/TreeComponent.test.tsx | 162 + .../Controls/TreeComponent/TreeComponent.tsx | 323 + .../__snapshots__/TreeComponent.test.tsx.snap | 497 + .../Controls/TreeComponent/treeComponent.less | 80 + .../ContainerSampleGenerator.test.ts | 156 + .../DataSamples/ContainerSampleGenerator.ts | 120 + .../DataSamples/DataSamplesUtil.test.ts | 32 + src/Explorer/DataSamples/DataSamplesUtil.ts | 60 + src/Explorer/Explorer.ts | 3433 +++ .../ArraysByKeyCache.test.ts | 78 + .../ArraysByKeyCache.ts | 97 + .../D3ForceGraph.test.ts | 158 + .../GraphExplorerComponent/D3ForceGraph.ts | 1353 ++ .../GraphExplorerComponent/EdgeInfoCache.ts | 41 + .../EditorNeighborsComponent.tsx | 226 + .../EditorNodePropertiesComponent.test.tsx | 89 + .../EditorNodePropertiesComponent.tsx | 247 + .../GraphExplorerComponent/GraphData.test.ts | 112 + .../Graph/GraphExplorerComponent/GraphData.ts | 521 + .../GraphExplorer.test.tsx | 694 + .../GraphExplorerComponent/GraphExplorer.tsx | 1997 ++ .../GraphExplorerAdapter.tsx | 70 + .../GraphExplorerComponent/GraphUtil.test.ts | 202 + .../Graph/GraphExplorerComponent/GraphUtil.ts | 185 + .../GraphVizComponent.tsx | 172 + .../GremlinClient.test.ts | 266 + .../GraphExplorerComponent/GremlinClient.ts | 199 + .../GremlinSimpleClient.test.ts | 617 + .../GremlinSimpleClient.ts | 357 + .../LeftPaneComponent.tsx | 70 + .../MiddlePaneComponent.tsx | 38 + .../NodePropertiesComponent.test.tsx | 163 + .../NodePropertiesComponent.tsx | 539 + .../QueryContainerComponent.tsx | 102 + .../ReadOnlyNeighborsComponent.tsx | 65 + .../ReadOnlyNodePropertiesComponent.test.tsx | 67 + .../ReadOnlyNodePropertiesComponent.tsx | 89 + ...ditorNodePropertiesComponent.test.tsx.snap | 420 + ...dOnlyNodePropertiesComponent.test.tsx.snap | 247 + .../GraphExplorerComponent/graphExplorer.less | 622 + .../GraphStyleComponent/GraphStyle.test.ts | 51 + .../GraphStyleComponent.ts | 103 + .../graph-style-component.html | 74 + .../NewVertexComponent/NewVertex.test.ts | 75 + .../NewVertexComponent.html | 74 + .../NewVertexComponent/NewVertexComponent.ts | 99 + .../newVertexComponent.less | 97 + .../Menus/CommandBar/CommandBarComponent.less | 14 + .../CommandBar/CommandBarComponentAdapter.tsx | 103 + .../CommandBarComponentButtonFactory.test.ts | 315 + .../CommandBarComponentButtonFactory.ts | 727 + .../Menus/CommandBar/CommandBarUtil.test.tsx | 82 + .../Menus/CommandBar/CommandBarUtil.tsx | 183 + .../CommandBar/MemoryTrackerComponent.less | 24 + .../CommandBar/MemoryTrackerComponent.tsx | 50 + src/Explorer/Menus/ContextMenu.ts | 43 + .../Menus/NavBar/ControlBarComponent.tsx | 31 + .../NavBar/ControlBarComponentAdapter.tsx | 28 + .../Menus/NavBar/MeControlComponent.less | 93 + .../Menus/NavBar/MeControlComponent.test.tsx | 108 + .../Menus/NavBar/MeControlComponent.tsx | 167 + .../NavBar/MeControlComponentAdapter.tsx | 16 + .../MeControlComponent.test.tsx.snap | 90 + .../NotificationConsole.less | 160 + .../NotificationConsoleComponent.test.tsx | 164 + .../NotificationConsoleComponent.tsx | 273 + .../NotificationConsoleComponentAdapter.tsx | 46 + ...NotificationConsoleComponent.test.tsx.snap | 192 + .../MostRecentActivity/MostRecentActivity.ts | 197 + src/Explorer/Notebook/FileSystemUtil.ts | 37 + src/Explorer/Notebook/NTeractUtil.ts | 22 + src/Explorer/Notebook/NotebookClientV2.ts | 264 + .../NotebookComponent/NotebookComponent.less | 13 + .../NotebookComponent/NotebookComponent.tsx | 25 + .../NotebookComponentAdapter.tsx | 52 + .../NotebookComponentBootstrapper.tsx | 314 + .../NotebookContentProvider.ts | 69 + .../VirtualCommandBarComponent.tsx | 79 + .../NotebookComponent/__mocks__/rx-jupyter.ts | 20 + .../Notebook/NotebookComponent/actions.ts | 83 + .../NotebookComponent/contents/file/index.tsx | 97 + .../contents/file/text-file.tsx | 143 + .../NotebookComponent/contents/index.tsx | 173 + .../Notebook/NotebookComponent/epics.test.ts | 492 + .../Notebook/NotebookComponent/epics.ts | 925 + .../NotebookComponent/loadTransform.ts | 35 + .../Notebook/NotebookComponent/reducers.ts | 80 + .../Notebook/NotebookComponent/store.ts | 112 + .../Notebook/NotebookComponent/types.ts | 25 + .../Notebook/NotebookContainerClient.ts | 148 + .../Notebook/NotebookContentClient.ts | 293 + src/Explorer/Notebook/NotebookContentItem.ts | 14 + .../Notebook/NotebookRenderer/AzureTheme.tsx | 115 + .../NotebookReadOnlyRenderer.less | 56 + .../NotebookReadOnlyRenderer.tsx | 95 + .../NotebookRenderer/NotebookRenderer.less | 108 + .../NotebookRenderer/NotebookRenderer.tsx | 165 + .../Notebook/NotebookRenderer/Prompt.less | 30 + .../Notebook/NotebookRenderer/Prompt.tsx | 90 + .../NotebookRenderer/PromptContent.tsx | 56 + .../NotebookRenderer/StatusBar.test.tsx | 55 + .../Notebook/NotebookRenderer/StatusBar.tsx | 128 + .../Notebook/NotebookRenderer/Toolbar.tsx | 181 + .../Notebook/NotebookRenderer/base.css | 143 + .../decorators/CellCreator.tsx | 214 + .../decorators/CellLabeler.less | 8 + .../decorators/CellLabeler.tsx | 45 + .../decorators/HoverableCell.tsx | 40 + .../decorators/draggable/index.tsx | 234 + .../decorators/hijack-scroll/index.tsx | 97 + .../decorators/kbd-shortcuts/index.tsx | 142 + .../Notebook/NotebookRenderer/default.css | 181 + src/Explorer/Notebook/NotebookUtil.ts | 75 + src/Explorer/OpenActions.test.ts | 519 + src/Explorer/OpenActions.ts | 198 + src/Explorer/OpenActionsStubs.ts | 929 + src/Explorer/Panes/AddCollectionPane.html | 602 + src/Explorer/Panes/AddCollectionPane.test.ts | 74 + src/Explorer/Panes/AddCollectionPane.ts | 1357 ++ src/Explorer/Panes/AddDatabasePane.html | 169 + src/Explorer/Panes/AddDatabasePane.test.ts | 49 + src/Explorer/Panes/AddDatabasePane.ts | 600 + src/Explorer/Panes/BrowseQueriesPane.html | 33 + src/Explorer/Panes/BrowseQueriesPane.ts | 104 + .../Panes/CassandraAddCollectionPane.html | 333 + .../Panes/CassandraAddCollectionPane.ts | 615 + src/Explorer/Panes/ClusterLibraryPane.html | 59 + src/Explorer/Panes/ClusterLibraryPane.ts | 236 + src/Explorer/Panes/ContextualPaneBase.ts | 129 + .../DeleteCollectionConfirmationPane.html | 109 + .../DeleteCollectionConfirmationPane.test.ts | 158 + .../Panes/DeleteCollectionConfirmationPane.ts | 143 + .../Panes/DeleteDatabaseConfirmationPane.html | 109 + .../DeleteDatabaseConfirmationPane.test.ts | 151 + .../Panes/DeleteDatabaseConfirmationPane.ts | 150 + .../Panes/ExecuteSprocParamsPane.html | 165 + src/Explorer/Panes/ExecuteSprocParamsPane.ts | 172 + src/Explorer/Panes/GitHubReposPane.html | 14 + src/Explorer/Panes/GitHubReposPane.ts | 349 + src/Explorer/Panes/GraphNewVertexPane.html | 60 + src/Explorer/Panes/GraphNewVertexPane.less | 10 + src/Explorer/Panes/GraphStylingPane.html | 59 + src/Explorer/Panes/GraphStylingPane.ts | 68 + src/Explorer/Panes/LibraryManagePane.html | 55 + src/Explorer/Panes/LibraryManagePane.ts | 372 + src/Explorer/Panes/LoadQueryPane.html | 88 + src/Explorer/Panes/LoadQueryPane.ts | 150 + .../Panes/ManageSparkClusterPane.html | 37 + src/Explorer/Panes/ManageSparkClusterPane.ts | 153 + src/Explorer/Panes/NewVertexPane.ts | 64 + src/Explorer/Panes/PaneComponents.ts | 266 + src/Explorer/Panes/RenewAdHocAccessPane.html | 90 + src/Explorer/Panes/RenewAdHocAccessPane.ts | 102 + src/Explorer/Panes/SaveQueryPane.html | 63 + src/Explorer/Panes/SaveQueryPane.ts | 160 + src/Explorer/Panes/SettingsPane.html | 268 + src/Explorer/Panes/SettingsPane.test.ts | 40 + src/Explorer/Panes/SettingsPane.ts | 185 + src/Explorer/Panes/SetupNotebooksPane.html | 45 + src/Explorer/Panes/SetupNotebooksPane.ts | 111 + src/Explorer/Panes/SetupSparkClusterPane.html | 52 + src/Explorer/Panes/SetupSparkClusterPane.ts | 99 + src/Explorer/Panes/StringInputPane.html | 66 + src/Explorer/Panes/StringInputPane.ts | 98 + src/Explorer/Panes/SwitchDirectoryPane.html | 21 + src/Explorer/Panes/SwitchDirectoryPane.ts | 88 + .../Panes/Tables/AddTableEntityPane.ts | 146 + .../Panes/Tables/EditTableEntityPane.ts | 228 + .../Panes/Tables/EntityPropertyViewModel.ts | 164 + src/Explorer/Panes/Tables/QuerySelectPane.ts | 174 + .../Panes/Tables/TableAddEntityPane.html | 190 + .../Panes/Tables/TableColumnOptionsPane.html | 78 + .../Panes/Tables/TableColumnOptionsPane.ts | 195 + .../Panes/Tables/TableEditEntityPane.html | 188 + src/Explorer/Panes/Tables/TableEntityPane.ts | 281 + .../Panes/Tables/TableQuerySelectPane.html | 79 + .../Validators/EntityPropertyNameValidator.ts | 306 + .../EntityPropertyValidationCommon.ts | 23 + .../EntityPropertyValueValidator.ts | 341 + src/Explorer/Panes/UploadFilePane.html | 72 + src/Explorer/Panes/UploadFilePane.ts | 130 + src/Explorer/Panes/UploadItemsPane.html | 130 + src/Explorer/Panes/UploadItemsPane.ts | 147 + .../SplashScreen/SplashScreenComponent.less | 177 + .../SplashScreen/SplashScreenComponent.tsx | 129 + .../SplashScreenComponentAdapter.test.ts | 66 + .../SplashScreenComponentApdapter.tsx | 228 + src/Explorer/Tables/Constants.ts | 169 + src/Explorer/Tables/DataTable/CacheBase.ts | 26 + .../DataTable/DataTableBindingManager.ts | 396 + .../Tables/DataTable/DataTableBuilder.ts | 52 + .../Tables/DataTable/DataTableContextMenu.ts | 150 + .../DataTable/DataTableOperationManager.ts | 313 + .../Tables/DataTable/DataTableOperations.ts | 192 + .../Tables/DataTable/DataTableUtilities.ts | 148 + .../Tables/DataTable/DataTableViewModel.ts | 270 + .../Tables/DataTable/TableCommands.ts | 155 + .../Tables/DataTable/TableEntityCache.ts | 27 + .../DataTable/TableEntityListViewModel.ts | 541 + src/Explorer/Tables/Entities.ts | 38 + .../Tables/QueryBuilder/ClauseGroup.ts | 327 + .../QueryBuilder/ClauseGroupViewModel.ts | 49 + .../QueryBuilder/CustomTimestampHelper.ts | 377 + .../QueryBuilder/DateTimeUtilities.test.ts | 110 + .../Tables/QueryBuilder/DateTimeUtilities.ts | 67 + .../QueryBuilder/QueryBuilderViewModel.ts | 796 + .../QueryBuilder/QueryClauseViewModel.ts | 285 + .../Tables/QueryBuilder/QueryViewModel.ts | 234 + src/Explorer/Tables/TableDataClient.ts | 746 + src/Explorer/Tables/TableEntityProcessor.ts | 194 + src/Explorer/Tables/Utilities.ts | 279 + src/Explorer/Tabs/ConflictsTab.html | 153 + src/Explorer/Tabs/ConflictsTab.ts | 716 + src/Explorer/Tabs/DatabaseSettingsTab.html | 101 + src/Explorer/Tabs/DatabaseSettingsTab.ts | 719 + src/Explorer/Tabs/DocumentsTab.html | 226 + src/Explorer/Tabs/DocumentsTab.test.ts | 196 + src/Explorer/Tabs/DocumentsTab.ts | 977 + src/Explorer/Tabs/GalleryTab.html | 1 + src/Explorer/Tabs/GalleryTab.tsx | 45 + src/Explorer/Tabs/GraphTab.html | 1 + src/Explorer/Tabs/GraphTab.ts | 237 + src/Explorer/Tabs/MongoDocumentsTab.html | 417 + src/Explorer/Tabs/MongoDocumentsTab.ts | 331 + src/Explorer/Tabs/MongoQueryTab.html | 120 + src/Explorer/Tabs/MongoQueryTab.ts | 29 + src/Explorer/Tabs/MongoShellTab.html | 15 + src/Explorer/Tabs/MongoShellTab.ts | 221 + src/Explorer/Tabs/NotebookTab.html | 7 + src/Explorer/Tabs/NotebookTab.ts | 539 + src/Explorer/Tabs/NotebookV2Tab.html | 1 + src/Explorer/Tabs/NotebookV2Tab.ts | 435 + src/Explorer/Tabs/NotebookViewerTab.html | 1 + src/Explorer/Tabs/NotebookViewerTab.tsx | 71 + src/Explorer/Tabs/QueryTab.html | 334 + src/Explorer/Tabs/QueryTab.less | 311 + src/Explorer/Tabs/QueryTab.test.ts | 98 + src/Explorer/Tabs/QueryTab.ts | 632 + src/Explorer/Tabs/QueryTablesTab.html | 249 + src/Explorer/Tabs/QueryTablesTab.ts | 278 + src/Explorer/Tabs/ScriptTabBase.ts | 385 + src/Explorer/Tabs/SettingsTab.html | 755 + src/Explorer/Tabs/SettingsTab.test.ts | 656 + src/Explorer/Tabs/SettingsTab.ts | 1732 ++ src/Explorer/Tabs/SparkMasterTab.html | 7 + src/Explorer/Tabs/SparkMasterTab.ts | 29 + src/Explorer/Tabs/StoredProcedureTab.html | 89 + src/Explorer/Tabs/StoredProcedureTab.ts | 296 + src/Explorer/Tabs/TabComponents.ts | 196 + src/Explorer/Tabs/TabsBase.ts | 239 + src/Explorer/Tabs/TerminalTab.html | 1 + src/Explorer/Tabs/TerminalTab.tsx | 89 + src/Explorer/Tabs/TriggerTab.html | 39 + src/Explorer/Tabs/TriggerTab.ts | 184 + src/Explorer/Tabs/UserDefinedFunctionTab.html | 30 + src/Explorer/Tabs/UserDefinedFunctionTab.ts | 166 + src/Explorer/Tabs/__mocks__/NotebookTab.ts | 8 + src/Explorer/Tree/AccessibleVerticalList.ts | 119 + src/Explorer/Tree/Collection.test.ts | 114 + src/Explorer/Tree/Collection.ts | 1657 ++ src/Explorer/Tree/CollectionTreeNode.html | 425 + .../Tree/CollectionTreeNodeContextMenu.html | 16 + src/Explorer/Tree/ConflictId.ts | 151 + src/Explorer/Tree/Database.ts | 465 + src/Explorer/Tree/DatabaseTreeNode.html | 110 + src/Explorer/Tree/DocumentId.ts | 71 + src/Explorer/Tree/ObjectId.ts | 14 + src/Explorer/Tree/ResourceTokenCollection.ts | 183 + src/Explorer/Tree/ResourceTree.html | 11 + src/Explorer/Tree/ResourceTreeAdapter.tsx | 803 + ...sourceTreeAdapterForResourceToken.test.tsx | 50 + .../ResourceTreeAdapterForResourceToken.tsx | 116 + src/Explorer/Tree/StoredProcedure.ts | 239 + .../Tree/StoredProcedureTreeNode.html | 63 + src/Explorer/Tree/TreeComponents.ts | 76 + src/Explorer/Tree/Trigger.ts | 180 + src/Explorer/Tree/TriggerTreeNode.html | 62 + src/Explorer/Tree/UserDefinedFunction.ts | 167 + .../Tree/UserDefinedFunctionTreeNode.html | 62 + ...eTreeAdapterForResourceToken.test.tsx.snap | 35 + src/Explorer/WaitsForTemplateViewModel.ts | 37 + .../Cards/CardStyleConstants.tsx | 55 + .../Cards/GalleryCardComponent.tsx | 65 + src/GalleryViewer/GalleryViewer.less | 9 + src/GalleryViewer/GalleryViewer.tsx | 20 + src/GalleryViewer/GalleryViewerComponent.tsx | 207 + src/GalleryViewer/galleryViewer.html | 13 + src/GitHub/GitHubClient.test.ts | 92 + src/GitHub/GitHubClient.ts | 528 + src/GitHub/GitHubConnector.ts | 30 + src/GitHub/GitHubContentProvider.test.ts | 312 + src/GitHub/GitHubContentProvider.ts | 406 + src/GitHub/GitHubOAuthService.test.ts | 162 + src/GitHub/GitHubOAuthService.ts | 112 + src/HostedExplorer.ts | 1172 + src/Index.ts | 33 + src/Juno/JunoClient.test.ts | 128 + src/Juno/JunoClient.ts | 151 + src/Libs/is-integer-polyfill.js | 5 + src/Libs/jquery.js | 5 + src/Main.ts | 130 + .../NotebookWorkspaceManager.ts | 96 + ...ookWorkspaceResourceProviderMockClients.ts | 50 + src/Platform/Emulator/DataAccessUtility.ts | 12 + src/Platform/Emulator/ExplorerFactory.ts | 39 + src/Platform/Emulator/Main.ts | 7 + src/Platform/Emulator/NotificationsClient.ts | 16 + src/Platform/Hosted/ArmResourceUtils.ts | 171 + src/Platform/Hosted/Authorization.ts | 310 + src/Platform/Hosted/DataAccessUtility.ts | 12 + src/Platform/Hosted/ExplorerFactory.ts | 27 + .../Helpers/ConnectionStringParser.test.ts | 75 + .../Hosted/Helpers/ConnectionStringParser.ts | 46 + src/Platform/Hosted/HostedUtils.test.ts | 32 + src/Platform/Hosted/HostedUtils.ts | 35 + src/Platform/Hosted/Main.ts | 588 + src/Platform/Hosted/Maint.test.ts | 45 + src/Platform/Hosted/NotificationsClient.ts | 9 + src/Platform/Portal/DataAccessUtility.ts | 96 + src/Platform/Portal/ExplorerFactory.ts | 20 + src/Platform/Portal/Main.ts | 11 + src/Platform/Portal/NotificationsClient.ts | 9 + src/PlatformType.ts | 10 + src/ReactDevTools.ts | 3 + .../IResourceProviderClient.test.ts | 163 + .../IResourceProviderClient.ts | 11 + .../ResourceProviderClient.ts | 170 + .../ResourceProviderClientFactory.ts | 18 + src/RouteHandlers/RouteHandler.ts | 35 + src/RouteHandlers/TabRouteHandler.test.ts | 108 + src/RouteHandlers/TabRouteHandler.ts | 428 + src/Shared/AddCollectionUtility.test.ts | 1143 + src/Shared/AddCollectionUtility.ts | 645 + src/Shared/AddDatabaseUtility.test.ts | 153 + src/Shared/AddDatabaseUtility.ts | 192 + src/Shared/Ajax.ts | 43 + src/Shared/Constants.ts | 348 + src/Shared/DefaultExperienceUtility.test.ts | 133 + src/Shared/DefaultExperienceUtility.ts | 139 + src/Shared/ExplorerSettings.ts | 22 + src/Shared/PriceEstimateCalculator.ts | 47 + src/Shared/StorageUtility.test.ts | 55 + src/Shared/StorageUtility.ts | 76 + src/Shared/StringUtility.test.ts | 15 + src/Shared/StringUtility.ts | 9 + src/Shared/Telemetry/TelemetryConstants.ts | 155 + src/Shared/Telemetry/TelemetryProcessor.ts | 136 + src/Shared/appInsights.ts | 10 + .../ArcadiaResourceManager.ts | 79 + .../SparkClusterManager.ts | 137 + src/Terminal/JupyterLabAppFactory.ts | 40 + src/Terminal/NotebookAppContracts.d.ts | 111 + src/Terminal/README.md | 76 + src/Terminal/index.css | 26 + src/Terminal/index.html | 13 + src/Terminal/index.ts | 52 + src/TokenProviders/PortalTokenProvider.ts | 13 + src/TokenProviders/TokenProviderFactory.ts | 20 + src/Utils/AuthorizationUtils.test.ts | 112 + src/Utils/AuthorizationUtils.ts | 72 + src/Utils/AutoPilotUtils.test.ts | 119 + src/Utils/AutoPilotUtils.ts | 94 + src/Utils/DatabaseAccountUtils.test.ts | 154 + src/Utils/DatabaseAccountUtils.ts | 53 + src/Utils/GitHubUtils.test.ts | 50 + src/Utils/GitHubUtils.ts | 56 + src/Utils/JunoUtils.ts | 44 + src/Utils/MessageValidation.ts | 16 + src/Utils/NotebookConfigurationUtils.ts | 86 + src/Utils/NotificationConsoleUtils.ts | 28 + src/Utils/OfferUtils.test.ts | 51 + src/Utils/OfferUtils.ts | 12 + src/Utils/PricingUtils.test.ts | 386 + src/Utils/PricingUtils.ts | 290 + src/Utils/QueryUtils.test.ts | 187 + src/Utils/QueryUtils.ts | 128 + src/Utils/StringUtils.test.ts | 30 + src/Utils/StringUtils.ts | 21 + src/applyExplorerBindings.ts | 16 + src/connectToGitHub.html | 14 + src/explorer.html | 498 + src/global.d.ts | 15 + src/hostedExplorer.html | 64 + src/index.html | 62 + src/quickstart.html | 353 + src/quickstart.ts | 5 + src/setupTests.ts | 13 + src/workers/upload/definitions.ts | 28 + src/workers/upload/index.ts | 139 + strict-migration-tools/.gitignore | 1 + strict-migration-tools/README.md | 25 + strict-migration-tools/autoAdd.js | 55 + strict-migration-tools/index.js | 53 + strict-migration-tools/package-lock.json | 90 + strict-migration-tools/package.json | 17 + strict-migration-tools/src/config.js | 3 + .../src/getStrictNullCheckEligibleFiles.js | 94 + strict-migration-tools/src/tsHelper.js | 44 + trxProcessor.js | 7 + tsconfig.contracts.json | 15 + tsconfig.json | 23 + tsconfig.strict.json | 54 + tsconfig.test.json | 6 + tslint.json | 16 + utils/generateResourceToken.js | 56 + web.config | 59 + webpack.config.js | 269 + 986 files changed, 195242 insertions(+) create mode 100644 .eslintignore create mode 100644 .eslintrc.js create mode 100644 .github/CODEOWNERS create mode 100644 .gitignore create mode 100644 .npmrc create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 DataExplorer.nuspec create mode 100644 LICENSE create mode 100644 README.md create mode 100644 ReleaseNotes.md create mode 100644 __mocks__/AddDatabaseUtility.ts create mode 100644 __mocks__/monaco-editor.ts create mode 100644 azure-pipelines.yaml create mode 100644 babel.config.js create mode 100644 copyToConsumers.js create mode 100644 cypress/.gitignore create mode 100644 cypress/cypress.json create mode 100644 cypress/integration/dataexplorer/CASSANDRA/addCollection.spec.ts create mode 100644 cypress/integration/dataexplorer/GRAPH/addCollection.spec.ts create mode 100644 cypress/integration/dataexplorer/MONGO/addCollection.spec.ts create mode 100644 cypress/integration/dataexplorer/MONGO/addCollectionAutopilot.spec.ts create mode 100644 cypress/integration/dataexplorer/MONGO/addCollectionExistingDatabase.spec.ts create mode 100644 cypress/integration/dataexplorer/MONGO/provisionDatabaseThroughput.spec.ts create mode 100644 cypress/integration/dataexplorer/SQL/addCollection.spec.ts create mode 100644 cypress/integration/dataexplorer/TABLE/addCollection.spec.ts create mode 100644 cypress/integration/dataexplorer/ci-tests/addCollectionPane.spec.ts create mode 100644 cypress/integration/dataexplorer/ci-tests/createDatabase.spec.ts create mode 100644 cypress/integration/dataexplorer/ci-tests/deleteCollection.spec.ts create mode 100644 cypress/integration/dataexplorer/ci-tests/deleteDatabase.spec.ts create mode 100644 cypress/integration/notebook/README.md create mode 100644 cypress/integration/notebook/newNotebook.spec.ts create mode 100644 cypress/integration/notebook/resourceTree.spec.ts create mode 100644 cypress/package-lock.json create mode 100644 cypress/package.json create mode 100644 cypress/support/index.js create mode 100644 cypress/tsconfig.json create mode 100644 cypress/utilities/connectionString.js create mode 100644 cypress/utilities/cosmosClient.js create mode 100644 externals/adal.js create mode 100644 externals/bootstrap.js create mode 100644 externals/bootstrap.min.js create mode 100644 externals/bootstrap_ase.css create mode 100644 externals/bops.js create mode 100644 externals/crossroads.js create mode 100644 externals/dataTables.colReorder.js create mode 100644 externals/dataTables.colResize.js create mode 100644 externals/datatables.js create mode 100644 externals/images/cut.png create mode 100644 externals/images/door.png create mode 100644 externals/images/page_white_add.png create mode 100644 externals/images/page_white_copy.png create mode 100644 externals/images/page_white_delete.png create mode 100644 externals/images/page_white_edit.png create mode 100644 externals/images/page_white_paste.png create mode 100644 externals/images/sort_both.png create mode 100644 externals/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 externals/images/ui-icons_444444_256x240.png create mode 100644 externals/images/ui-icons_555555_256x240.png create mode 100644 externals/images/ui-icons_777620_256x240.png create mode 100644 externals/images/ui-icons_777777_256x240.png create mode 100644 externals/images/ui-icons_cc0000_256x240.png create mode 100644 externals/images/ui-icons_ffffff_256x240.png create mode 100644 externals/jquery-ui.min.css create mode 100644 externals/jquery-ui.min.js create mode 100644 externals/jquery-ui.structure.min.css create mode 100644 externals/jquery-ui.theme.min.css create mode 100644 externals/jquery.contextMenu.css create mode 100644 externals/jquery.contextMenu.js create mode 100644 externals/jquery.dataTables.min.css create mode 100644 externals/jquery.dataTables.min.js create mode 100644 externals/jquery.dataTables.min_ase.css create mode 100644 externals/jquery.dataTables.min_ase.js create mode 100644 externals/jquery.datatables.js create mode 100644 externals/jquery.datatables_ase.js create mode 100644 externals/jquery.js create mode 100644 externals/jquery.min.js create mode 100644 externals/jquery.typeahead.css create mode 100644 externals/jquery.typeahead.js create mode 100644 externals/jquery.typeahead.min.css create mode 100644 externals/jquery.typeahead.min.js create mode 100644 externals/jquery.ui.position.js create mode 100644 externals/msrCrypto.js create mode 100644 fonts/segoe-ui/west-european/normal/latest.woff create mode 100644 images/ASX_Delete.svg create mode 100644 images/ASX_More.svg create mode 100644 images/ASX_QueryBuilder.svg create mode 100644 images/ASX_Refresh.svg create mode 100644 images/ASX_Remove.svg create mode 100644 images/Add-disabled.svg create mode 100644 images/Add-property.svg create mode 100644 images/Add.svg create mode 100644 images/AddCollection-1.svg create mode 100644 images/AddCollection.svg create mode 100644 images/AddDatabase-disabled.svg create mode 100644 images/AddDatabase.svg create mode 100644 images/AddDocument-disabled.svg create mode 100644 images/AddDocument.svg create mode 100644 images/AddEntity-1.svg create mode 100644 images/AddEntity.svg create mode 100644 images/AddGraphQuery_16x16-1.svg create mode 100644 images/AddGraphQuery_16x16.svg create mode 100644 images/AddSqlQuery_16x16-1.svg create mode 100644 images/AddSqlQuery_16x16.svg create mode 100644 images/AddStoredProcedure-disabled.svg create mode 100644 images/AddStoredProcedure.svg create mode 100644 images/AddTrigger-disabled.svg create mode 100644 images/AddTrigger.svg create mode 100644 images/AddUdf-disabled.svg create mode 100644 images/AddUdf.svg create mode 100644 images/And-Or-disabled.svg create mode 100644 images/And-Or.svg create mode 100644 images/Arrow.svg create mode 100644 images/Azure-Cosmos-DB.svg create mode 100644 images/BrowseQuery-disabled.svg create mode 100644 images/BrowseQuery.svg create mode 100644 images/Chevron_Up-disabled.svg create mode 100644 images/Chevron_Up.svg create mode 100644 images/Chevron_down-disabled.svg create mode 100644 images/Chevron_down.svg create mode 100644 images/Clear-disabled.svg create mode 100644 images/Clear.svg create mode 100644 images/CollapseLeftNav-disabled.svg create mode 100644 images/CollapseLeftNav.svg create mode 100644 images/Collapse_arrow_14x14-disabled.svg create mode 100644 images/Collapse_arrow_14x14.svg create mode 100644 images/Connect-disabled.svg create mode 100644 images/Connect.svg create mode 100644 images/ConnectionString_Artwork.png create mode 100644 images/Copy-disabled.svg create mode 100644 images/Copy.svg create mode 100644 images/Cosmos-Terminal-disabled.svg create mode 100644 images/Cosmos-Terminal.svg create mode 100644 images/CosmosDBHostedLogo.svg create mode 100644 images/CosmosDB_20170524.svg create mode 100644 images/CosmosDB_20170829.svg create mode 100644 images/CosmosDB_black.svg create mode 100644 images/CosmosDB_gray.svg create mode 100644 images/CosmosDB_rgb_ui_lighttheme.ico create mode 100644 images/DeleteCollection-disabled.svg create mode 100644 images/DeleteCollection.svg create mode 100644 images/DeleteDatabase-disabled.svg create mode 100644 images/DeleteDatabase.svg create mode 100644 images/DeleteDocument-disabled.svg create mode 100644 images/DeleteDocument.svg create mode 100644 images/DeleteEntities-disabled.svg create mode 100644 images/DeleteEntities.svg create mode 100644 images/DeleteSproc-disabled.svg create mode 100644 images/DeleteSproc.svg create mode 100644 images/DeleteTrigger-disabled.svg create mode 100644 images/DeleteTrigger.svg create mode 100644 images/DeleteUDF-disabled.svg create mode 100644 images/DeleteUDF.svg create mode 100644 images/DirectorySwitch-disabled.svg create mode 100644 images/DirectorySwitch.svg create mode 100644 images/DocumentExplorerIcon-Blue.svg create mode 100644 images/DocumentExplorerIcon.svg create mode 100644 images/DocumentWaterMark.svg create mode 100644 images/Down-disabled.svg create mode 100644 images/Down.svg create mode 100644 images/DownloadQuery-disabled.svg create mode 100644 images/DownloadQuery.svg create mode 100644 images/Edit-entity-disabled.svg create mode 100644 images/Edit-entity.svg create mode 100644 images/Edit_entity-disabled.svg create mode 100644 images/Edit_entity.svg create mode 100644 images/Entity_cancel-disabled.svg create mode 100644 images/Entity_cancel.svg create mode 100644 images/ExecuteQuery-bigicon.svg create mode 100644 images/ExecuteQuery-disabled.svg create mode 100644 images/ExecuteQuery.svg create mode 100644 images/ExpandLeftNav-disabled.svg create mode 100644 images/ExpandLeftNav.svg create mode 100644 images/Expand_14x14-disabled.svg create mode 100644 images/Expand_14x14.svg create mode 100644 images/Explorer.svg create mode 100644 images/Feedback-Command.svg create mode 100644 images/Feedback.svg create mode 100644 images/GalleryIcon.svg create mode 100644 images/Halo_ProgressSpinner.svg create mode 100644 images/Hamburger.svg create mode 100644 images/HdeConnectCosmosDB.svg create mode 100644 images/Hero-new-container.svg create mode 100644 images/Hero-new-notebook.svg create mode 100644 images/Hero-sample.svg create mode 100644 images/HorizontalSplitter-disabled.svg create mode 100644 images/HorizontalSplitter.svg create mode 100644 images/Hosted-Terminal-disabled.svg create mode 100644 images/Hosted-Terminal.svg create mode 100644 images/HostedConnectwhite.svg create mode 100644 images/HostedExplorer.svg create mode 100644 images/HostedSettings-disabled.svg create mode 100644 images/HostedSettings.svg create mode 100644 images/Info.svg create mode 100644 images/LoadGraph.png create mode 100644 images/LoadingIndicator_3Squares.gif create mode 100644 images/NewDocument-disabled.svg create mode 100644 images/NewDocument.svg create mode 100644 images/NewVertex-disabled.svg create mode 100644 images/NewVertex.svg create mode 100644 images/OpenQueryFromDisk-disabled.svg create mode 100644 images/OpenQueryFromDisk.svg create mode 100644 images/Options-disabled.svg create mode 100644 images/Options.svg create mode 100644 images/Query-Builder-disabled.svg create mode 100644 images/Query-Builder.svg create mode 100644 images/Query-Editor-Next-Disabled.svg create mode 100644 images/Query-Editor-Next.svg create mode 100644 images/Query-Text-disabled.svg create mode 100644 images/Query-Text.svg create mode 100644 images/QueryBuilder/Add_green_16x.png create mode 100644 images/QueryBuilder/CollapseChevronDown_16x.png create mode 100644 images/QueryBuilder/CollapseChevronUp_16x.png create mode 100644 images/QueryBuilder/CustomActionEditor_16x.png create mode 100644 images/QueryBuilder/Delete_16x.png create mode 100644 images/QueryBuilder/DropdownMenu_16x.png create mode 100644 images/QueryBuilder/EditEntity_16x.png create mode 100644 images/QueryBuilder/GroupClause_16x.png create mode 100644 images/QueryBuilder/Halo_ProgressSpinner.svg create mode 100644 images/QueryBuilder/QueryInformation_16x.png create mode 100644 images/QueryBuilder/ResetColumnOrder_16x.png create mode 100644 images/QueryBuilder/ShiftToLeft_16x.png create mode 100644 images/QueryBuilder/StatusInvalid_16x.png create mode 100644 images/QueryBuilder/StatusWarning_16x.png create mode 100644 images/QueryBuilder/UngroupClause_16x.png create mode 100644 images/Quickstart.svg create mode 100644 images/Reorder-disabled.svg create mode 100644 images/Reorder.svg create mode 100644 images/Reset-column-options-disabled.svg create mode 100644 images/Reset-column-options.svg create mode 100644 images/RevertBack.svg create mode 100644 images/RunQuery.png create mode 100644 images/Scale_15x15-disabled.svg create mode 100644 images/Scale_15x15.svg create mode 100644 images/Settings.svg create mode 100644 images/Share-disabled.svg create mode 100644 images/Share.svg create mode 100644 images/Stop-disabled.svg create mode 100644 images/Stop.svg create mode 100644 images/Style-disabled.svg create mode 100644 images/Style.svg create mode 100644 images/Triangle-down.svg create mode 100644 images/Triangle-right.svg create mode 100644 images/Triangle-up.svg create mode 100644 images/Up-disabled.svg create mode 100644 images/Up.svg create mode 100644 images/Upload_16x16-disabled.svg create mode 100644 images/Upload_16x16.svg create mode 100644 images/apply-bigicon.svg create mode 100644 images/back.svg create mode 100644 images/cancel-disabled.svg create mode 100644 images/cancel-hover.svg create mode 100644 images/cancel.svg create mode 100644 images/check-disabled.svg create mode 100644 images/check.svg create mode 100644 images/chevron-right-disabled.svg create mode 100644 images/chevron-right.svg create mode 100644 images/circular_loader_black_16x16.gif create mode 100644 images/close-black-active.svg create mode 100644 images/close-black-hover.svg create mode 100644 images/close-black.svg create mode 100644 images/close.svg create mode 100644 images/collections.svg create mode 100644 images/createDoc-bigicon.svg create mode 100644 images/createDoc-disabled.svg create mode 100644 images/createDoc.svg create mode 100644 images/createQuery-disabled.svg create mode 100644 images/createQuery.svg create mode 100644 images/delete-bigicon.svg create mode 100644 images/delete-disabled.svg create mode 100644 images/delete.svg create mode 100644 images/discard-bigicon.svg create mode 100644 images/discard-disabled.svg create mode 100644 images/discard.svg create mode 100644 images/documentDBCollectionsIcon.svg create mode 100644 images/documentDBLogo.svg create mode 100644 images/dotnet.png create mode 100644 images/edit-disabled.svg create mode 100644 images/edit.svg create mode 100644 images/error.svg create mode 100644 images/error_black.svg create mode 100644 images/error_no_outline.svg create mode 100644 images/error_no_outline_hover.svg create mode 100644 images/error_red.svg create mode 100644 images/error_upload.svg create mode 100644 images/exploreDocDB.svg create mode 100644 images/favicon.ico create mode 100644 images/filter-disabled.svg create mode 100644 images/filter.svg create mode 100644 images/folder_16x16-disabled.svg create mode 100644 images/folder_16x16.svg create mode 100644 images/github.svg create mode 100644 images/imgarrowlefticon-white.svg create mode 100644 images/imgarrowlefticon.svg create mode 100644 images/info-bubble-9x9.svg create mode 100644 images/info-bubble.svg create mode 100644 images/info_color.svg create mode 100644 images/java.png create mode 100644 images/loading.svg create mode 100644 images/minusDefault.png create mode 100644 images/minusDisabled.png create mode 100644 images/minus_disabled.svg create mode 100644 images/minus_hover.svg create mode 100644 images/minus_normal.svg create mode 100644 images/minus_pressed.svg create mode 100644 images/new-edge-disabled.svg create mode 100644 images/new-edge.svg create mode 100644 images/nodejs.png create mode 100644 images/notebook/Apache-spark-disabled.svg create mode 100644 images/notebook/Apache-spark.svg create mode 100644 images/notebook/Notebook resource-disabled.svg create mode 100644 images/notebook/Notebook resource.svg create mode 100644 images/notebook/Notebook-clear-all-outputs-disabled.svg create mode 100644 images/notebook/Notebook-clear-all-outputs.svg create mode 100644 images/notebook/Notebook-copy-disabled.svg create mode 100644 images/notebook/Notebook-copy.svg create mode 100644 images/notebook/Notebook-cut-disabled.svg create mode 100644 images/notebook/Notebook-cut.svg create mode 100644 images/notebook/Notebook-enable-disabled.svg create mode 100644 images/notebook/Notebook-enable.svg create mode 100644 images/notebook/Notebook-insert-cell-disabled.svg create mode 100644 images/notebook/Notebook-insert-cell.svg create mode 100644 images/notebook/Notebook-move cell down-disabled.svg create mode 100644 images/notebook/Notebook-move cell down.svg create mode 100644 images/notebook/Notebook-move cell up-disabled.svg create mode 100644 images/notebook/Notebook-move cell up.svg create mode 100644 images/notebook/Notebook-new-disabled.svg create mode 100644 images/notebook/Notebook-new.svg create mode 100644 images/notebook/Notebook-paste-disabled.svg create mode 100644 images/notebook/Notebook-paste.svg create mode 100644 images/notebook/Notebook-redo-disabled.svg create mode 100644 images/notebook/Notebook-redo.svg create mode 100644 images/notebook/Notebook-reset-workspace-disabled.svg create mode 100644 images/notebook/Notebook-reset-workspace.svg create mode 100644 images/notebook/Notebook-resource-disabled.svg create mode 100644 images/notebook/Notebook-resource.svg create mode 100644 images/notebook/Notebook-restart & rerun-disabled.svg create mode 100644 images/notebook/Notebook-restart & rerun.svg create mode 100644 images/notebook/Notebook-restart-disabled.svg create mode 100644 images/notebook/Notebook-restart.svg create mode 100644 images/notebook/Notebook-run-all-disabled.svg create mode 100644 images/notebook/Notebook-run-all.svg create mode 100644 images/notebook/Notebook-run-disabled.svg create mode 100644 images/notebook/Notebook-run.svg create mode 100644 images/notebook/Notebook-stop-disabled.svg create mode 100644 images/notebook/Notebook-stop.svg create mode 100644 images/notebook/Notebook-undo-disabled.svg create mode 100644 images/notebook/Notebook-undo.svg create mode 100644 images/notebook/Spark-library-manage-disabled.svg create mode 100644 images/notebook/Spark-library-manage.svg create mode 100644 images/notebook/Spark-query-new-disabled.svg create mode 100644 images/notebook/Spark-query-new.svg create mode 100644 images/notebook/add-code-cell.svg create mode 100644 images/notebook/add-text-cell.svg create mode 100644 images/notebook/file-cosmos.svg create mode 100644 images/notebook/file-disabled.svg create mode 100644 images/open-in-tab-disabled.svg create mode 100644 images/open-in-tab.svg create mode 100644 images/openQuery.svg create mode 100644 images/plus.svg create mode 100644 images/plusDefault.png create mode 100644 images/plusDisabled.png create mode 100644 images/plus_disabled.svg create mode 100644 images/plus_hover.svg create mode 100644 images/plus_normal.svg create mode 100644 images/plus_pressed.svg create mode 100644 images/previousPage-disabled.svg create mode 100644 images/previousPage.svg create mode 100644 images/price.png create mode 100644 images/python.png create mode 100644 images/refresh-cosmos.svg create mode 100644 images/refresh-disabled.svg create mode 100644 images/row-collapsed.svg create mode 100644 images/row-expanded.svg create mode 100644 images/save-bigicon.svg create mode 100644 images/save-cosmos.svg create mode 100644 images/save-disabled.svg create mode 100644 images/save_query_banner.png create mode 100644 images/settings_15x15-disabled.svg create mode 100644 images/settings_15x15.svg create mode 100644 images/sort-down.svg create mode 100644 images/sort-right.svg create mode 100644 images/synapse-link.svg create mode 100644 images/tree-collection-disabled.svg create mode 100644 images/tree-collection.svg create mode 100644 images/tree-database.svg create mode 100644 images/tree-notebook.svg create mode 100644 images/uploadDoc-disabled.svg create mode 100644 images/uploadDoc.svg create mode 100644 images/warning.svg create mode 100644 images/win_hr_loader_black.gif create mode 100644 jest.config.js create mode 100644 less/Common/Constants.less create mode 100644 less/Common/TabCommon.less create mode 100644 less/StorageExplorer.less create mode 100644 less/TableStyles/CustomizeColumns.less create mode 100644 less/TableStyles/EntityEditor.less create mode 100644 less/TableStyles/fulldatatables.less create mode 100644 less/TableStyles/queryBuilder.less create mode 100644 less/documentDB.less create mode 100644 less/forms.less create mode 100644 less/forms_ase.less create mode 100644 less/hostedexplorer.less create mode 100644 less/index.less create mode 100644 less/infobox.less create mode 100644 less/menus.less create mode 100644 less/messagebox.less create mode 100644 less/quickstart.less create mode 100644 less/resourceTree.less create mode 100644 less/tree.less create mode 100644 mockModule.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 quickstart/DocumentDB-Quickstart-DotNet.zip create mode 100644 quickstart/DocumentDB-Quickstart-DotNetCore.zip create mode 100644 quickstart/DocumentDB-Quickstart-Java.zip create mode 100644 quickstart/DocumentDB-Quickstart-NodeJs.zip create mode 100644 quickstart/DocumentDB-Quickstart-Python.zip create mode 100644 runIntegrationTests.cmd create mode 100644 sampleData/gremlinSampleData.json create mode 100644 sampleData/sqlSampleData.json create mode 100644 src/Api/Apis.ts create mode 100644 src/AuthType.ts create mode 100644 src/Bindings/BindingHandlersRegisterer.ts create mode 100644 src/Bindings/ReactBindingHandler.ts create mode 100644 src/Common/ArrayHashMap.ts create mode 100644 src/Common/Constants.ts create mode 100644 src/Common/CosmosClient.test.ts create mode 100644 src/Common/CosmosClient.ts create mode 100644 src/Common/DataAccessUtilityBase.test.ts create mode 100644 src/Common/DataAccessUtilityBase.ts create mode 100644 src/Common/DeleteFeedback.ts create mode 100644 src/Common/DocumentClientUtilityBase.ts create mode 100644 src/Common/EditableUtility.ts create mode 100644 src/Common/EnvironmentUtility.ts create mode 100644 src/Common/ErrorParserUtility.test.ts create mode 100644 src/Common/ErrorParserUtility.ts create mode 100644 src/Common/HashMap.test.ts create mode 100644 src/Common/HashMap.ts create mode 100644 src/Common/HeadersUtility.test.ts create mode 100644 src/Common/HeadersUtility.ts create mode 100644 src/Common/IteratorUtilities.test.ts create mode 100644 src/Common/IteratorUtilities.ts create mode 100644 src/Common/Logger.test.ts create mode 100644 src/Common/Logger.ts create mode 100644 src/Common/MessageHandler.test.ts create mode 100644 src/Common/MessageHandler.ts create mode 100644 src/Common/MongoProxyClient.test.ts create mode 100644 src/Common/MongoProxyClient.ts create mode 100644 src/Common/MongoUtility.ts create mode 100644 src/Common/NotificationsClientBase.ts create mode 100644 src/Common/ObjectCache.test.ts create mode 100644 src/Common/ObjectCache.ts create mode 100644 src/Common/QueriesClient.ts create mode 100644 src/Common/Splitter.ts create mode 100644 src/Common/ThemeUtility.ts create mode 100644 src/Common/UrlUtility.ts create mode 100644 src/Common/__snapshots__/CosmosClient.test.ts.snap create mode 100644 src/Common/__snapshots__/DataAccessUtilityBase.test.ts.snap create mode 100644 src/Common/__snapshots__/IteratorUtilities.test.ts.snap create mode 100644 src/Config.ts create mode 100644 src/Contracts/ActionContracts.ts create mode 100644 src/Contracts/DataModels.ts create mode 100644 src/Contracts/Diagnostics.ts create mode 100644 src/Contracts/ExplorerContracts.ts create mode 100644 src/Contracts/Versions.ts create mode 100644 src/Contracts/ViewModels.ts create mode 100644 src/Controls/Heatmap/Heatmap.html create mode 100644 src/Controls/Heatmap/Heatmap.less create mode 100644 src/Controls/Heatmap/Heatmap.test.ts create mode 100644 src/Controls/Heatmap/Heatmap.ts create mode 100644 src/Controls/Heatmap/HeatmapDatatypes.ts create mode 100644 src/Definitions/adal.d.ts create mode 100644 src/Definitions/datatables.d.ts create mode 100644 src/Definitions/gif.d.ts create mode 100644 src/Definitions/globals.d.ts create mode 100644 src/Definitions/html.d.ts create mode 100644 src/Definitions/jquery-typescript.d.ts create mode 100644 src/Definitions/jquery-ui.d.ts create mode 100644 src/Definitions/jquery.contextmenu.d.ts create mode 100644 src/Definitions/jquery.d.ts create mode 100644 src/Definitions/plotly.js-cartesian-dist.d-min.ts create mode 100644 src/Definitions/png.d.ts create mode 100644 src/Definitions/svg.d.ts create mode 100644 src/Definitions/worker.d.ts create mode 100644 src/Explorer/ComponentRegisterer.test.ts create mode 100644 src/Explorer/ComponentRegisterer.ts create mode 100644 src/Explorer/ContextMenuButtonFactory.ts create mode 100644 src/Explorer/Controls/AccessibleElement/AccessibleElement.tsx create mode 100644 src/Explorer/Controls/Accordion/AccordionComponent.less create mode 100644 src/Explorer/Controls/Accordion/AccordionComponent.tsx create mode 100644 src/Explorer/Controls/AccountSwitch/AccountSwitchComponent.test.tsx create mode 100644 src/Explorer/Controls/AccountSwitch/AccountSwitchComponent.tsx create mode 100644 src/Explorer/Controls/AccountSwitch/AccountSwitchComponentAdapter.tsx create mode 100644 src/Explorer/Controls/AccountSwitch/__snapshots__/AccountSwitchComponent.test.tsx.snap create mode 100644 src/Explorer/Controls/Arcadia/ArcadiaMenuPicker.tsx create mode 100644 src/Explorer/Controls/CollapsiblePanel/CollapsiblePanel.tsx create mode 100644 src/Explorer/Controls/CollapsiblePanel/CollapsiblePanelComponent.less create mode 100644 src/Explorer/Controls/CollapsiblePanel/CollapsiblePanelComponent.ts create mode 100644 src/Explorer/Controls/CollapsiblePanel/collapsible-panel-component.html create mode 100644 src/Explorer/Controls/CommandButton/CommandButton.less create mode 100644 src/Explorer/Controls/CommandButton/CommandButton.test.ts create mode 100644 src/Explorer/Controls/CommandButton/CommandButton.ts create mode 100644 src/Explorer/Controls/CommandButton/CommandButtonComponent.tsx create mode 100644 src/Explorer/Controls/CommandButton/command-button.html create mode 100644 src/Explorer/Controls/DialogReactComponent/DialogComponent.tsx create mode 100644 src/Explorer/Controls/DialogReactComponent/DialogComponentAdapter.tsx create mode 100644 src/Explorer/Controls/DiffEditor/DiffEditorComponent.ts create mode 100644 src/Explorer/Controls/DiffEditor/diff-editor-component.html create mode 100644 src/Explorer/Controls/Directory/DefaultDirectoryDropdownComponent.test.tsx create mode 100644 src/Explorer/Controls/Directory/DefaultDirectoryDropdownComponent.tsx create mode 100644 src/Explorer/Controls/Directory/DirectoryComponentAdapter.tsx create mode 100644 src/Explorer/Controls/Directory/DirectoryListComponent.test.tsx create mode 100644 src/Explorer/Controls/Directory/DirectoryListComponent.tsx create mode 100644 src/Explorer/Controls/Directory/__snapshots__/DefaultDirectoryDropdownComponent.test.tsx.snap create mode 100644 src/Explorer/Controls/Directory/__snapshots__/DirectoryListComponent.test.tsx.snap create mode 100644 src/Explorer/Controls/DynamicList/DynamicList.test.ts create mode 100644 src/Explorer/Controls/DynamicList/DynamicListComponent.less create mode 100644 src/Explorer/Controls/DynamicList/DynamicListComponent.ts create mode 100644 src/Explorer/Controls/DynamicList/dynamic-list.html create mode 100644 src/Explorer/Controls/Editor/EditorComponent.ts create mode 100644 src/Explorer/Controls/Editor/EditorReact.tsx create mode 100644 src/Explorer/Controls/Editor/editor-component.html create mode 100644 src/Explorer/Controls/ErrorDisplayComponent/ErrorDisplayComponent.less create mode 100644 src/Explorer/Controls/ErrorDisplayComponent/ErrorDisplayComponent.ts create mode 100644 src/Explorer/Controls/ErrorDisplayComponent/error-display-component.html create mode 100644 src/Explorer/Controls/GitHub/AddRepoComponent.tsx create mode 100644 src/Explorer/Controls/GitHub/AuthorizeAccessComponent.tsx create mode 100644 src/Explorer/Controls/GitHub/GitHubReposComponent.tsx create mode 100644 src/Explorer/Controls/GitHub/GitHubReposComponentAdapter.tsx create mode 100644 src/Explorer/Controls/GitHub/GitHubStyleConstants.ts create mode 100644 src/Explorer/Controls/GitHub/ReposListComponent.tsx create mode 100644 src/Explorer/Controls/InputTypeahead/InputTypeahead.less create mode 100644 src/Explorer/Controls/InputTypeahead/InputTypeahead.ts create mode 100644 src/Explorer/Controls/InputTypeahead/InputTypeaheadComponent.tsx create mode 100644 src/Explorer/Controls/InputTypeahead/input-typeahead.html create mode 100644 src/Explorer/Controls/JsonEditor/JsonEditorComponent.less create mode 100644 src/Explorer/Controls/JsonEditor/JsonEditorComponent.ts create mode 100644 src/Explorer/Controls/JsonEditor/json-editor-component.html create mode 100644 src/Explorer/Controls/LibraryManagement/ClusterLibraryGrid.tsx create mode 100644 src/Explorer/Controls/LibraryManagement/ClusterLibraryGridAdapter.tsx create mode 100644 src/Explorer/Controls/LibraryManagement/LibraryManage.tsx create mode 100644 src/Explorer/Controls/LibraryManagement/LibraryManageComponentAdapter.tsx create mode 100644 src/Explorer/Controls/Notebook/NotebookAppMessageHandler.ts create mode 100644 src/Explorer/Controls/Notebook/NotebookTerminalComponent.less create mode 100644 src/Explorer/Controls/Notebook/NotebookTerminalComponent.test.tsx create mode 100644 src/Explorer/Controls/Notebook/NotebookTerminalComponent.tsx create mode 100644 src/Explorer/Controls/NotebookViewer/NotebookMetadataComponent.tsx create mode 100644 src/Explorer/Controls/NotebookViewer/NotebookViewer.less create mode 100644 src/Explorer/Controls/NotebookViewer/NotebookViewer.tsx create mode 100644 src/Explorer/Controls/NotebookViewer/NotebookViewerComponent.less create mode 100644 src/Explorer/Controls/NotebookViewer/NotebookViewerComponent.tsx create mode 100644 src/Explorer/Controls/NotebookViewer/notebookViewer.html create mode 100644 src/Explorer/Controls/QueriesGridReactComponent/QueriesGridComponent.tsx create mode 100644 src/Explorer/Controls/QueriesGridReactComponent/QueriesGridComponentAdapter.tsx create mode 100644 src/Explorer/Controls/ResizeSensorReactComponent/ResizeSensorComponent.tsx create mode 100644 src/Explorer/Controls/Spark/ClusterSettingsComponent.less create mode 100644 src/Explorer/Controls/Spark/ClusterSettingsComponent.tsx create mode 100644 src/Explorer/Controls/Spark/ClusterSettingsComponentAdapter.tsx create mode 100644 src/Explorer/Controls/Tabs/TabComponent.less create mode 100644 src/Explorer/Controls/Tabs/TabComponent.tsx create mode 100644 src/Explorer/Controls/ThroughputInput/ThroughputInput.test.ts create mode 100644 src/Explorer/Controls/ThroughputInput/ThroughputInputComponent.html create mode 100644 src/Explorer/Controls/ThroughputInput/ThroughputInputComponent.ts create mode 100644 src/Explorer/Controls/ThroughputInput/ThroughputInputComponentAutoPilotV3.ts create mode 100644 src/Explorer/Controls/ThroughputInput/ThroughputInputComponentAutoscaleV3.html create mode 100644 src/Explorer/Controls/Toolbar/IToolbarAction.ts create mode 100644 src/Explorer/Controls/Toolbar/IToolbarDisplayable.ts create mode 100644 src/Explorer/Controls/Toolbar/IToolbarDropDown.ts create mode 100644 src/Explorer/Controls/Toolbar/IToolbarItem.ts create mode 100644 src/Explorer/Controls/Toolbar/IToolbarSeperator.ts create mode 100644 src/Explorer/Controls/Toolbar/IToolbarToggle.ts create mode 100644 src/Explorer/Controls/Toolbar/KeyCodes.ts create mode 100644 src/Explorer/Controls/Toolbar/Toolbar.ts create mode 100644 src/Explorer/Controls/Toolbar/ToolbarAction.ts create mode 100644 src/Explorer/Controls/Toolbar/ToolbarDropDown.ts create mode 100644 src/Explorer/Controls/Toolbar/ToolbarToggle.ts create mode 100644 src/Explorer/Controls/Toolbar/Utilities.ts create mode 100644 src/Explorer/Controls/Toolbar/toolbar.html create mode 100644 src/Explorer/Controls/TreeComponent/TreeComponent.test.tsx create mode 100644 src/Explorer/Controls/TreeComponent/TreeComponent.tsx create mode 100644 src/Explorer/Controls/TreeComponent/__snapshots__/TreeComponent.test.tsx.snap create mode 100644 src/Explorer/Controls/TreeComponent/treeComponent.less create mode 100644 src/Explorer/DataSamples/ContainerSampleGenerator.test.ts create mode 100644 src/Explorer/DataSamples/ContainerSampleGenerator.ts create mode 100644 src/Explorer/DataSamples/DataSamplesUtil.test.ts create mode 100644 src/Explorer/DataSamples/DataSamplesUtil.ts create mode 100644 src/Explorer/Explorer.ts create mode 100644 src/Explorer/Graph/GraphExplorerComponent/ArraysByKeyCache.test.ts create mode 100644 src/Explorer/Graph/GraphExplorerComponent/ArraysByKeyCache.ts create mode 100644 src/Explorer/Graph/GraphExplorerComponent/D3ForceGraph.test.ts create mode 100644 src/Explorer/Graph/GraphExplorerComponent/D3ForceGraph.ts create mode 100644 src/Explorer/Graph/GraphExplorerComponent/EdgeInfoCache.ts create mode 100644 src/Explorer/Graph/GraphExplorerComponent/EditorNeighborsComponent.tsx create mode 100644 src/Explorer/Graph/GraphExplorerComponent/EditorNodePropertiesComponent.test.tsx create mode 100644 src/Explorer/Graph/GraphExplorerComponent/EditorNodePropertiesComponent.tsx create mode 100644 src/Explorer/Graph/GraphExplorerComponent/GraphData.test.ts create mode 100644 src/Explorer/Graph/GraphExplorerComponent/GraphData.ts create mode 100644 src/Explorer/Graph/GraphExplorerComponent/GraphExplorer.test.tsx create mode 100644 src/Explorer/Graph/GraphExplorerComponent/GraphExplorer.tsx create mode 100644 src/Explorer/Graph/GraphExplorerComponent/GraphExplorerAdapter.tsx create mode 100644 src/Explorer/Graph/GraphExplorerComponent/GraphUtil.test.ts create mode 100644 src/Explorer/Graph/GraphExplorerComponent/GraphUtil.ts create mode 100644 src/Explorer/Graph/GraphExplorerComponent/GraphVizComponent.tsx create mode 100644 src/Explorer/Graph/GraphExplorerComponent/GremlinClient.test.ts create mode 100644 src/Explorer/Graph/GraphExplorerComponent/GremlinClient.ts create mode 100644 src/Explorer/Graph/GraphExplorerComponent/GremlinSimpleClient.test.ts create mode 100644 src/Explorer/Graph/GraphExplorerComponent/GremlinSimpleClient.ts create mode 100644 src/Explorer/Graph/GraphExplorerComponent/LeftPaneComponent.tsx create mode 100644 src/Explorer/Graph/GraphExplorerComponent/MiddlePaneComponent.tsx create mode 100644 src/Explorer/Graph/GraphExplorerComponent/NodePropertiesComponent.test.tsx create mode 100644 src/Explorer/Graph/GraphExplorerComponent/NodePropertiesComponent.tsx create mode 100644 src/Explorer/Graph/GraphExplorerComponent/QueryContainerComponent.tsx create mode 100644 src/Explorer/Graph/GraphExplorerComponent/ReadOnlyNeighborsComponent.tsx create mode 100644 src/Explorer/Graph/GraphExplorerComponent/ReadOnlyNodePropertiesComponent.test.tsx create mode 100644 src/Explorer/Graph/GraphExplorerComponent/ReadOnlyNodePropertiesComponent.tsx create mode 100644 src/Explorer/Graph/GraphExplorerComponent/__snapshots__/EditorNodePropertiesComponent.test.tsx.snap create mode 100644 src/Explorer/Graph/GraphExplorerComponent/__snapshots__/ReadOnlyNodePropertiesComponent.test.tsx.snap create mode 100644 src/Explorer/Graph/GraphExplorerComponent/graphExplorer.less create mode 100644 src/Explorer/Graph/GraphStyleComponent/GraphStyle.test.ts create mode 100644 src/Explorer/Graph/GraphStyleComponent/GraphStyleComponent.ts create mode 100644 src/Explorer/Graph/GraphStyleComponent/graph-style-component.html create mode 100644 src/Explorer/Graph/NewVertexComponent/NewVertex.test.ts create mode 100644 src/Explorer/Graph/NewVertexComponent/NewVertexComponent.html create mode 100644 src/Explorer/Graph/NewVertexComponent/NewVertexComponent.ts create mode 100644 src/Explorer/Graph/NewVertexComponent/newVertexComponent.less create mode 100644 src/Explorer/Menus/CommandBar/CommandBarComponent.less create mode 100644 src/Explorer/Menus/CommandBar/CommandBarComponentAdapter.tsx create mode 100644 src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.test.ts create mode 100644 src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.ts create mode 100644 src/Explorer/Menus/CommandBar/CommandBarUtil.test.tsx create mode 100644 src/Explorer/Menus/CommandBar/CommandBarUtil.tsx create mode 100644 src/Explorer/Menus/CommandBar/MemoryTrackerComponent.less create mode 100644 src/Explorer/Menus/CommandBar/MemoryTrackerComponent.tsx create mode 100644 src/Explorer/Menus/ContextMenu.ts create mode 100644 src/Explorer/Menus/NavBar/ControlBarComponent.tsx create mode 100644 src/Explorer/Menus/NavBar/ControlBarComponentAdapter.tsx create mode 100644 src/Explorer/Menus/NavBar/MeControlComponent.less create mode 100644 src/Explorer/Menus/NavBar/MeControlComponent.test.tsx create mode 100644 src/Explorer/Menus/NavBar/MeControlComponent.tsx create mode 100644 src/Explorer/Menus/NavBar/MeControlComponentAdapter.tsx create mode 100644 src/Explorer/Menus/NavBar/__snapshots__/MeControlComponent.test.tsx.snap create mode 100644 src/Explorer/Menus/NotificationConsole/NotificationConsole.less create mode 100644 src/Explorer/Menus/NotificationConsole/NotificationConsoleComponent.test.tsx create mode 100644 src/Explorer/Menus/NotificationConsole/NotificationConsoleComponent.tsx create mode 100644 src/Explorer/Menus/NotificationConsole/NotificationConsoleComponentAdapter.tsx create mode 100644 src/Explorer/Menus/NotificationConsole/__snapshots__/NotificationConsoleComponent.test.tsx.snap create mode 100644 src/Explorer/MostRecentActivity/MostRecentActivity.ts create mode 100644 src/Explorer/Notebook/FileSystemUtil.ts create mode 100644 src/Explorer/Notebook/NTeractUtil.ts create mode 100644 src/Explorer/Notebook/NotebookClientV2.ts create mode 100644 src/Explorer/Notebook/NotebookComponent/NotebookComponent.less create mode 100644 src/Explorer/Notebook/NotebookComponent/NotebookComponent.tsx create mode 100644 src/Explorer/Notebook/NotebookComponent/NotebookComponentAdapter.tsx create mode 100644 src/Explorer/Notebook/NotebookComponent/NotebookComponentBootstrapper.tsx create mode 100644 src/Explorer/Notebook/NotebookComponent/NotebookContentProvider.ts create mode 100644 src/Explorer/Notebook/NotebookComponent/VirtualCommandBarComponent.tsx create mode 100644 src/Explorer/Notebook/NotebookComponent/__mocks__/rx-jupyter.ts create mode 100644 src/Explorer/Notebook/NotebookComponent/actions.ts create mode 100644 src/Explorer/Notebook/NotebookComponent/contents/file/index.tsx create mode 100644 src/Explorer/Notebook/NotebookComponent/contents/file/text-file.tsx create mode 100644 src/Explorer/Notebook/NotebookComponent/contents/index.tsx create mode 100644 src/Explorer/Notebook/NotebookComponent/epics.test.ts create mode 100644 src/Explorer/Notebook/NotebookComponent/epics.ts create mode 100644 src/Explorer/Notebook/NotebookComponent/loadTransform.ts create mode 100644 src/Explorer/Notebook/NotebookComponent/reducers.ts create mode 100644 src/Explorer/Notebook/NotebookComponent/store.ts create mode 100644 src/Explorer/Notebook/NotebookComponent/types.ts create mode 100644 src/Explorer/Notebook/NotebookContainerClient.ts create mode 100644 src/Explorer/Notebook/NotebookContentClient.ts create mode 100644 src/Explorer/Notebook/NotebookContentItem.ts create mode 100644 src/Explorer/Notebook/NotebookRenderer/AzureTheme.tsx create mode 100644 src/Explorer/Notebook/NotebookRenderer/NotebookReadOnlyRenderer.less create mode 100644 src/Explorer/Notebook/NotebookRenderer/NotebookReadOnlyRenderer.tsx create mode 100644 src/Explorer/Notebook/NotebookRenderer/NotebookRenderer.less create mode 100644 src/Explorer/Notebook/NotebookRenderer/NotebookRenderer.tsx create mode 100644 src/Explorer/Notebook/NotebookRenderer/Prompt.less create mode 100644 src/Explorer/Notebook/NotebookRenderer/Prompt.tsx create mode 100644 src/Explorer/Notebook/NotebookRenderer/PromptContent.tsx create mode 100644 src/Explorer/Notebook/NotebookRenderer/StatusBar.test.tsx create mode 100644 src/Explorer/Notebook/NotebookRenderer/StatusBar.tsx create mode 100644 src/Explorer/Notebook/NotebookRenderer/Toolbar.tsx create mode 100644 src/Explorer/Notebook/NotebookRenderer/base.css create mode 100644 src/Explorer/Notebook/NotebookRenderer/decorators/CellCreator.tsx create mode 100644 src/Explorer/Notebook/NotebookRenderer/decorators/CellLabeler.less create mode 100644 src/Explorer/Notebook/NotebookRenderer/decorators/CellLabeler.tsx create mode 100644 src/Explorer/Notebook/NotebookRenderer/decorators/HoverableCell.tsx create mode 100644 src/Explorer/Notebook/NotebookRenderer/decorators/draggable/index.tsx create mode 100644 src/Explorer/Notebook/NotebookRenderer/decorators/hijack-scroll/index.tsx create mode 100644 src/Explorer/Notebook/NotebookRenderer/decorators/kbd-shortcuts/index.tsx create mode 100644 src/Explorer/Notebook/NotebookRenderer/default.css create mode 100644 src/Explorer/Notebook/NotebookUtil.ts create mode 100644 src/Explorer/OpenActions.test.ts create mode 100644 src/Explorer/OpenActions.ts create mode 100644 src/Explorer/OpenActionsStubs.ts create mode 100644 src/Explorer/Panes/AddCollectionPane.html create mode 100644 src/Explorer/Panes/AddCollectionPane.test.ts create mode 100644 src/Explorer/Panes/AddCollectionPane.ts create mode 100644 src/Explorer/Panes/AddDatabasePane.html create mode 100644 src/Explorer/Panes/AddDatabasePane.test.ts create mode 100644 src/Explorer/Panes/AddDatabasePane.ts create mode 100644 src/Explorer/Panes/BrowseQueriesPane.html create mode 100644 src/Explorer/Panes/BrowseQueriesPane.ts create mode 100644 src/Explorer/Panes/CassandraAddCollectionPane.html create mode 100644 src/Explorer/Panes/CassandraAddCollectionPane.ts create mode 100644 src/Explorer/Panes/ClusterLibraryPane.html create mode 100644 src/Explorer/Panes/ClusterLibraryPane.ts create mode 100644 src/Explorer/Panes/ContextualPaneBase.ts create mode 100644 src/Explorer/Panes/DeleteCollectionConfirmationPane.html create mode 100644 src/Explorer/Panes/DeleteCollectionConfirmationPane.test.ts create mode 100644 src/Explorer/Panes/DeleteCollectionConfirmationPane.ts create mode 100644 src/Explorer/Panes/DeleteDatabaseConfirmationPane.html create mode 100644 src/Explorer/Panes/DeleteDatabaseConfirmationPane.test.ts create mode 100644 src/Explorer/Panes/DeleteDatabaseConfirmationPane.ts create mode 100644 src/Explorer/Panes/ExecuteSprocParamsPane.html create mode 100644 src/Explorer/Panes/ExecuteSprocParamsPane.ts create mode 100644 src/Explorer/Panes/GitHubReposPane.html create mode 100644 src/Explorer/Panes/GitHubReposPane.ts create mode 100644 src/Explorer/Panes/GraphNewVertexPane.html create mode 100644 src/Explorer/Panes/GraphNewVertexPane.less create mode 100644 src/Explorer/Panes/GraphStylingPane.html create mode 100644 src/Explorer/Panes/GraphStylingPane.ts create mode 100644 src/Explorer/Panes/LibraryManagePane.html create mode 100644 src/Explorer/Panes/LibraryManagePane.ts create mode 100644 src/Explorer/Panes/LoadQueryPane.html create mode 100644 src/Explorer/Panes/LoadQueryPane.ts create mode 100644 src/Explorer/Panes/ManageSparkClusterPane.html create mode 100644 src/Explorer/Panes/ManageSparkClusterPane.ts create mode 100644 src/Explorer/Panes/NewVertexPane.ts create mode 100644 src/Explorer/Panes/PaneComponents.ts create mode 100644 src/Explorer/Panes/RenewAdHocAccessPane.html create mode 100644 src/Explorer/Panes/RenewAdHocAccessPane.ts create mode 100644 src/Explorer/Panes/SaveQueryPane.html create mode 100644 src/Explorer/Panes/SaveQueryPane.ts create mode 100644 src/Explorer/Panes/SettingsPane.html create mode 100644 src/Explorer/Panes/SettingsPane.test.ts create mode 100644 src/Explorer/Panes/SettingsPane.ts create mode 100644 src/Explorer/Panes/SetupNotebooksPane.html create mode 100644 src/Explorer/Panes/SetupNotebooksPane.ts create mode 100644 src/Explorer/Panes/SetupSparkClusterPane.html create mode 100644 src/Explorer/Panes/SetupSparkClusterPane.ts create mode 100644 src/Explorer/Panes/StringInputPane.html create mode 100644 src/Explorer/Panes/StringInputPane.ts create mode 100644 src/Explorer/Panes/SwitchDirectoryPane.html create mode 100644 src/Explorer/Panes/SwitchDirectoryPane.ts create mode 100644 src/Explorer/Panes/Tables/AddTableEntityPane.ts create mode 100644 src/Explorer/Panes/Tables/EditTableEntityPane.ts create mode 100644 src/Explorer/Panes/Tables/EntityPropertyViewModel.ts create mode 100644 src/Explorer/Panes/Tables/QuerySelectPane.ts create mode 100644 src/Explorer/Panes/Tables/TableAddEntityPane.html create mode 100644 src/Explorer/Panes/Tables/TableColumnOptionsPane.html create mode 100644 src/Explorer/Panes/Tables/TableColumnOptionsPane.ts create mode 100644 src/Explorer/Panes/Tables/TableEditEntityPane.html create mode 100644 src/Explorer/Panes/Tables/TableEntityPane.ts create mode 100644 src/Explorer/Panes/Tables/TableQuerySelectPane.html create mode 100644 src/Explorer/Panes/Tables/Validators/EntityPropertyNameValidator.ts create mode 100644 src/Explorer/Panes/Tables/Validators/EntityPropertyValidationCommon.ts create mode 100644 src/Explorer/Panes/Tables/Validators/EntityPropertyValueValidator.ts create mode 100644 src/Explorer/Panes/UploadFilePane.html create mode 100644 src/Explorer/Panes/UploadFilePane.ts create mode 100644 src/Explorer/Panes/UploadItemsPane.html create mode 100644 src/Explorer/Panes/UploadItemsPane.ts create mode 100644 src/Explorer/SplashScreen/SplashScreenComponent.less create mode 100644 src/Explorer/SplashScreen/SplashScreenComponent.tsx create mode 100644 src/Explorer/SplashScreen/SplashScreenComponentAdapter.test.ts create mode 100644 src/Explorer/SplashScreen/SplashScreenComponentApdapter.tsx create mode 100644 src/Explorer/Tables/Constants.ts create mode 100644 src/Explorer/Tables/DataTable/CacheBase.ts create mode 100644 src/Explorer/Tables/DataTable/DataTableBindingManager.ts create mode 100644 src/Explorer/Tables/DataTable/DataTableBuilder.ts create mode 100644 src/Explorer/Tables/DataTable/DataTableContextMenu.ts create mode 100644 src/Explorer/Tables/DataTable/DataTableOperationManager.ts create mode 100644 src/Explorer/Tables/DataTable/DataTableOperations.ts create mode 100644 src/Explorer/Tables/DataTable/DataTableUtilities.ts create mode 100644 src/Explorer/Tables/DataTable/DataTableViewModel.ts create mode 100644 src/Explorer/Tables/DataTable/TableCommands.ts create mode 100644 src/Explorer/Tables/DataTable/TableEntityCache.ts create mode 100644 src/Explorer/Tables/DataTable/TableEntityListViewModel.ts create mode 100644 src/Explorer/Tables/Entities.ts create mode 100644 src/Explorer/Tables/QueryBuilder/ClauseGroup.ts create mode 100644 src/Explorer/Tables/QueryBuilder/ClauseGroupViewModel.ts create mode 100644 src/Explorer/Tables/QueryBuilder/CustomTimestampHelper.ts create mode 100644 src/Explorer/Tables/QueryBuilder/DateTimeUtilities.test.ts create mode 100644 src/Explorer/Tables/QueryBuilder/DateTimeUtilities.ts create mode 100644 src/Explorer/Tables/QueryBuilder/QueryBuilderViewModel.ts create mode 100644 src/Explorer/Tables/QueryBuilder/QueryClauseViewModel.ts create mode 100644 src/Explorer/Tables/QueryBuilder/QueryViewModel.ts create mode 100644 src/Explorer/Tables/TableDataClient.ts create mode 100644 src/Explorer/Tables/TableEntityProcessor.ts create mode 100644 src/Explorer/Tables/Utilities.ts create mode 100644 src/Explorer/Tabs/ConflictsTab.html create mode 100644 src/Explorer/Tabs/ConflictsTab.ts create mode 100644 src/Explorer/Tabs/DatabaseSettingsTab.html create mode 100644 src/Explorer/Tabs/DatabaseSettingsTab.ts create mode 100644 src/Explorer/Tabs/DocumentsTab.html create mode 100644 src/Explorer/Tabs/DocumentsTab.test.ts create mode 100644 src/Explorer/Tabs/DocumentsTab.ts create mode 100644 src/Explorer/Tabs/GalleryTab.html create mode 100644 src/Explorer/Tabs/GalleryTab.tsx create mode 100644 src/Explorer/Tabs/GraphTab.html create mode 100644 src/Explorer/Tabs/GraphTab.ts create mode 100644 src/Explorer/Tabs/MongoDocumentsTab.html create mode 100644 src/Explorer/Tabs/MongoDocumentsTab.ts create mode 100644 src/Explorer/Tabs/MongoQueryTab.html create mode 100644 src/Explorer/Tabs/MongoQueryTab.ts create mode 100644 src/Explorer/Tabs/MongoShellTab.html create mode 100644 src/Explorer/Tabs/MongoShellTab.ts create mode 100644 src/Explorer/Tabs/NotebookTab.html create mode 100644 src/Explorer/Tabs/NotebookTab.ts create mode 100644 src/Explorer/Tabs/NotebookV2Tab.html create mode 100644 src/Explorer/Tabs/NotebookV2Tab.ts create mode 100644 src/Explorer/Tabs/NotebookViewerTab.html create mode 100644 src/Explorer/Tabs/NotebookViewerTab.tsx create mode 100644 src/Explorer/Tabs/QueryTab.html create mode 100644 src/Explorer/Tabs/QueryTab.less create mode 100644 src/Explorer/Tabs/QueryTab.test.ts create mode 100644 src/Explorer/Tabs/QueryTab.ts create mode 100644 src/Explorer/Tabs/QueryTablesTab.html create mode 100644 src/Explorer/Tabs/QueryTablesTab.ts create mode 100644 src/Explorer/Tabs/ScriptTabBase.ts create mode 100644 src/Explorer/Tabs/SettingsTab.html create mode 100644 src/Explorer/Tabs/SettingsTab.test.ts create mode 100644 src/Explorer/Tabs/SettingsTab.ts create mode 100644 src/Explorer/Tabs/SparkMasterTab.html create mode 100644 src/Explorer/Tabs/SparkMasterTab.ts create mode 100644 src/Explorer/Tabs/StoredProcedureTab.html create mode 100644 src/Explorer/Tabs/StoredProcedureTab.ts create mode 100644 src/Explorer/Tabs/TabComponents.ts create mode 100644 src/Explorer/Tabs/TabsBase.ts create mode 100644 src/Explorer/Tabs/TerminalTab.html create mode 100644 src/Explorer/Tabs/TerminalTab.tsx create mode 100644 src/Explorer/Tabs/TriggerTab.html create mode 100644 src/Explorer/Tabs/TriggerTab.ts create mode 100644 src/Explorer/Tabs/UserDefinedFunctionTab.html create mode 100644 src/Explorer/Tabs/UserDefinedFunctionTab.ts create mode 100644 src/Explorer/Tabs/__mocks__/NotebookTab.ts create mode 100644 src/Explorer/Tree/AccessibleVerticalList.ts create mode 100644 src/Explorer/Tree/Collection.test.ts create mode 100644 src/Explorer/Tree/Collection.ts create mode 100644 src/Explorer/Tree/CollectionTreeNode.html create mode 100644 src/Explorer/Tree/CollectionTreeNodeContextMenu.html create mode 100644 src/Explorer/Tree/ConflictId.ts create mode 100644 src/Explorer/Tree/Database.ts create mode 100644 src/Explorer/Tree/DatabaseTreeNode.html create mode 100644 src/Explorer/Tree/DocumentId.ts create mode 100644 src/Explorer/Tree/ObjectId.ts create mode 100644 src/Explorer/Tree/ResourceTokenCollection.ts create mode 100644 src/Explorer/Tree/ResourceTree.html create mode 100644 src/Explorer/Tree/ResourceTreeAdapter.tsx create mode 100644 src/Explorer/Tree/ResourceTreeAdapterForResourceToken.test.tsx create mode 100644 src/Explorer/Tree/ResourceTreeAdapterForResourceToken.tsx create mode 100644 src/Explorer/Tree/StoredProcedure.ts create mode 100644 src/Explorer/Tree/StoredProcedureTreeNode.html create mode 100644 src/Explorer/Tree/TreeComponents.ts create mode 100644 src/Explorer/Tree/Trigger.ts create mode 100644 src/Explorer/Tree/TriggerTreeNode.html create mode 100644 src/Explorer/Tree/UserDefinedFunction.ts create mode 100644 src/Explorer/Tree/UserDefinedFunctionTreeNode.html create mode 100644 src/Explorer/Tree/__snapshots__/ResourceTreeAdapterForResourceToken.test.tsx.snap create mode 100644 src/Explorer/WaitsForTemplateViewModel.ts create mode 100644 src/GalleryViewer/Cards/CardStyleConstants.tsx create mode 100644 src/GalleryViewer/Cards/GalleryCardComponent.tsx create mode 100644 src/GalleryViewer/GalleryViewer.less create mode 100644 src/GalleryViewer/GalleryViewer.tsx create mode 100644 src/GalleryViewer/GalleryViewerComponent.tsx create mode 100644 src/GalleryViewer/galleryViewer.html create mode 100644 src/GitHub/GitHubClient.test.ts create mode 100644 src/GitHub/GitHubClient.ts create mode 100644 src/GitHub/GitHubConnector.ts create mode 100644 src/GitHub/GitHubContentProvider.test.ts create mode 100644 src/GitHub/GitHubContentProvider.ts create mode 100644 src/GitHub/GitHubOAuthService.test.ts create mode 100644 src/GitHub/GitHubOAuthService.ts create mode 100644 src/HostedExplorer.ts create mode 100644 src/Index.ts create mode 100644 src/Juno/JunoClient.test.ts create mode 100644 src/Juno/JunoClient.ts create mode 100644 src/Libs/is-integer-polyfill.js create mode 100644 src/Libs/jquery.js create mode 100644 src/Main.ts create mode 100644 src/NotebookWorkspaceManager/NotebookWorkspaceManager.ts create mode 100644 src/NotebookWorkspaceManager/NotebookWorkspaceResourceProviderMockClients.ts create mode 100644 src/Platform/Emulator/DataAccessUtility.ts create mode 100644 src/Platform/Emulator/ExplorerFactory.ts create mode 100644 src/Platform/Emulator/Main.ts create mode 100644 src/Platform/Emulator/NotificationsClient.ts create mode 100644 src/Platform/Hosted/ArmResourceUtils.ts create mode 100644 src/Platform/Hosted/Authorization.ts create mode 100644 src/Platform/Hosted/DataAccessUtility.ts create mode 100644 src/Platform/Hosted/ExplorerFactory.ts create mode 100644 src/Platform/Hosted/Helpers/ConnectionStringParser.test.ts create mode 100644 src/Platform/Hosted/Helpers/ConnectionStringParser.ts create mode 100644 src/Platform/Hosted/HostedUtils.test.ts create mode 100644 src/Platform/Hosted/HostedUtils.ts create mode 100644 src/Platform/Hosted/Main.ts create mode 100644 src/Platform/Hosted/Maint.test.ts create mode 100644 src/Platform/Hosted/NotificationsClient.ts create mode 100644 src/Platform/Portal/DataAccessUtility.ts create mode 100644 src/Platform/Portal/ExplorerFactory.ts create mode 100644 src/Platform/Portal/Main.ts create mode 100644 src/Platform/Portal/NotificationsClient.ts create mode 100644 src/PlatformType.ts create mode 100644 src/ReactDevTools.ts create mode 100644 src/ResourceProvider/IResourceProviderClient.test.ts create mode 100644 src/ResourceProvider/IResourceProviderClient.ts create mode 100644 src/ResourceProvider/ResourceProviderClient.ts create mode 100644 src/ResourceProvider/ResourceProviderClientFactory.ts create mode 100644 src/RouteHandlers/RouteHandler.ts create mode 100644 src/RouteHandlers/TabRouteHandler.test.ts create mode 100644 src/RouteHandlers/TabRouteHandler.ts create mode 100644 src/Shared/AddCollectionUtility.test.ts create mode 100644 src/Shared/AddCollectionUtility.ts create mode 100644 src/Shared/AddDatabaseUtility.test.ts create mode 100644 src/Shared/AddDatabaseUtility.ts create mode 100644 src/Shared/Ajax.ts create mode 100644 src/Shared/Constants.ts create mode 100644 src/Shared/DefaultExperienceUtility.test.ts create mode 100644 src/Shared/DefaultExperienceUtility.ts create mode 100644 src/Shared/ExplorerSettings.ts create mode 100644 src/Shared/PriceEstimateCalculator.ts create mode 100644 src/Shared/StorageUtility.test.ts create mode 100644 src/Shared/StorageUtility.ts create mode 100644 src/Shared/StringUtility.test.ts create mode 100644 src/Shared/StringUtility.ts create mode 100644 src/Shared/Telemetry/TelemetryConstants.ts create mode 100644 src/Shared/Telemetry/TelemetryProcessor.ts create mode 100644 src/Shared/appInsights.ts create mode 100644 src/SparkClusterManager/ArcadiaResourceManager.ts create mode 100644 src/SparkClusterManager/SparkClusterManager.ts create mode 100644 src/Terminal/JupyterLabAppFactory.ts create mode 100644 src/Terminal/NotebookAppContracts.d.ts create mode 100644 src/Terminal/README.md create mode 100644 src/Terminal/index.css create mode 100644 src/Terminal/index.html create mode 100644 src/Terminal/index.ts create mode 100644 src/TokenProviders/PortalTokenProvider.ts create mode 100644 src/TokenProviders/TokenProviderFactory.ts create mode 100644 src/Utils/AuthorizationUtils.test.ts create mode 100644 src/Utils/AuthorizationUtils.ts create mode 100644 src/Utils/AutoPilotUtils.test.ts create mode 100644 src/Utils/AutoPilotUtils.ts create mode 100644 src/Utils/DatabaseAccountUtils.test.ts create mode 100644 src/Utils/DatabaseAccountUtils.ts create mode 100644 src/Utils/GitHubUtils.test.ts create mode 100644 src/Utils/GitHubUtils.ts create mode 100644 src/Utils/JunoUtils.ts create mode 100644 src/Utils/MessageValidation.ts create mode 100644 src/Utils/NotebookConfigurationUtils.ts create mode 100644 src/Utils/NotificationConsoleUtils.ts create mode 100644 src/Utils/OfferUtils.test.ts create mode 100644 src/Utils/OfferUtils.ts create mode 100644 src/Utils/PricingUtils.test.ts create mode 100644 src/Utils/PricingUtils.ts create mode 100644 src/Utils/QueryUtils.test.ts create mode 100644 src/Utils/QueryUtils.ts create mode 100644 src/Utils/StringUtils.test.ts create mode 100644 src/Utils/StringUtils.ts create mode 100644 src/applyExplorerBindings.ts create mode 100644 src/connectToGitHub.html create mode 100644 src/explorer.html create mode 100644 src/global.d.ts create mode 100644 src/hostedExplorer.html create mode 100644 src/index.html create mode 100644 src/quickstart.html create mode 100644 src/quickstart.ts create mode 100644 src/setupTests.ts create mode 100644 src/workers/upload/definitions.ts create mode 100644 src/workers/upload/index.ts create mode 100644 strict-migration-tools/.gitignore create mode 100644 strict-migration-tools/README.md create mode 100644 strict-migration-tools/autoAdd.js create mode 100644 strict-migration-tools/index.js create mode 100644 strict-migration-tools/package-lock.json create mode 100644 strict-migration-tools/package.json create mode 100644 strict-migration-tools/src/config.js create mode 100644 strict-migration-tools/src/getStrictNullCheckEligibleFiles.js create mode 100644 strict-migration-tools/src/tsHelper.js create mode 100644 trxProcessor.js create mode 100644 tsconfig.contracts.json create mode 100644 tsconfig.json create mode 100644 tsconfig.strict.json create mode 100644 tsconfig.test.json create mode 100644 tslint.json create mode 100644 utils/generateResourceToken.js create mode 100644 web.config create mode 100644 webpack.config.js diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..5003732c5 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,436 @@ +**/node_modules/ +src/Api/Apis.ts +src/AuthType.ts +src/Bindings/BindingHandlersRegisterer.ts +src/Bindings/ReactBindingHandler.ts +src/Common/ArrayHashMap.ts +src/Common/Constants.ts +src/Common/CosmosClient.test.ts +src/Common/CosmosClient.ts +src/Common/DataAccessUtilityBase.test.ts +src/Common/DataAccessUtilityBase.ts +src/Common/DeleteFeedback.ts +src/Common/DocumentClientUtilityBase.ts +src/Common/EditableUtility.ts +src/Common/EnvironmentUtility.ts +src/Common/ErrorParserUtility.test.ts +src/Common/ErrorParserUtility.ts +src/Common/HashMap.test.ts +src/Common/HashMap.ts +src/Common/HeadersUtility.test.ts +src/Common/HeadersUtility.ts +src/Common/IteratorUtilities.test.ts +src/Common/IteratorUtilities.ts +src/Common/Logger.test.ts +src/Common/MessageHandler.test.ts +src/Common/MessageHandler.ts +src/Common/MongoProxyClient.test.ts +src/Common/MongoProxyClient.ts +src/Common/MongoUtility.ts +src/Common/NotificationsClientBase.ts +src/Common/ObjectCache.test.ts +src/Common/ObjectCache.ts +src/Common/QueriesClient.ts +src/Common/Splitter.ts +src/Common/ThemeUtility.ts +src/Common/UrlUtility.ts +src/Config.ts +src/Contracts/ActionContracts.ts +src/Contracts/DataModels.ts +src/Contracts/Diagnostics.ts +src/Contracts/ExplorerContracts.ts +src/Contracts/Versions.ts +src/Contracts/ViewModels.ts +src/Controls/Heatmap/Heatmap.test.ts +src/Controls/Heatmap/Heatmap.ts +src/Controls/Heatmap/HeatmapDatatypes.ts +src/Definitions/adal.d.ts +src/Definitions/datatables.d.ts +src/Definitions/gif.d.ts +src/Definitions/globals.d.ts +src/Definitions/html.d.ts +src/Definitions/jquery-typescript.d.ts +src/Definitions/jquery-ui.d.ts +src/Definitions/jquery.contextmenu.d.ts +src/Definitions/jquery.d.ts +src/Definitions/plotly.js-cartesian-dist.d-min.ts +src/Definitions/png.d.ts +src/Definitions/svg.d.ts +src/Definitions/worker.d.ts +src/Explorer/ComponentRegisterer.test.ts +src/Explorer/ComponentRegisterer.ts +src/Explorer/ContextMenuButtonFactory.ts +src/Explorer/Controls/CollapsiblePanel/CollapsiblePanelComponent.ts +src/Explorer/Controls/CommandButton/CommandButton.test.ts +src/Explorer/Controls/CommandButton/CommandButton.ts +src/Explorer/Controls/DiffEditor/DiffEditorComponent.ts +src/Explorer/Controls/DynamicList/DynamicList.test.ts +src/Explorer/Controls/DynamicList/DynamicListComponent.ts +src/Explorer/Controls/Editor/EditorComponent.ts +src/Explorer/Controls/ErrorDisplayComponent/ErrorDisplayComponent.ts +src/Explorer/Controls/InputTypeahead/InputTypeahead.ts +src/Explorer/Controls/JsonEditor/JsonEditorComponent.ts +src/Explorer/Controls/Notebook/NotebookAppMessageHandler.ts +src/Explorer/Controls/ThroughputInput/ThroughputInput.test.ts +src/Explorer/Controls/ThroughputInput/ThroughputInputComponent.ts +src/Explorer/Controls/ThroughputInput/ThroughputInputComponentAutoPilotV3.ts +src/Explorer/Controls/Toolbar/IToolbarAction.ts +src/Explorer/Controls/Toolbar/IToolbarDisplayable.ts +src/Explorer/Controls/Toolbar/IToolbarDropDown.ts +src/Explorer/Controls/Toolbar/IToolbarItem.ts +src/Explorer/Controls/Toolbar/IToolbarSeperator.ts +src/Explorer/Controls/Toolbar/IToolbarToggle.ts +src/Explorer/Controls/Toolbar/KeyCodes.ts +src/Explorer/Controls/Toolbar/Toolbar.ts +src/Explorer/Controls/Toolbar/ToolbarAction.ts +src/Explorer/Controls/Toolbar/ToolbarDropDown.ts +src/Explorer/Controls/Toolbar/ToolbarToggle.ts +src/Explorer/Controls/Toolbar/Utilities.ts +src/Explorer/DataSamples/ContainerSampleGenerator.test.ts +src/Explorer/DataSamples/ContainerSampleGenerator.ts +src/Explorer/DataSamples/DataSamplesUtil.test.ts +src/Explorer/DataSamples/DataSamplesUtil.ts +src/Explorer/Explorer.ts +src/Explorer/Graph/GraphExplorerComponent/ArraysByKeyCache.test.ts +src/Explorer/Graph/GraphExplorerComponent/ArraysByKeyCache.ts +src/Explorer/Graph/GraphExplorerComponent/D3ForceGraph.test.ts +src/Explorer/Graph/GraphExplorerComponent/D3ForceGraph.ts +src/Explorer/Graph/GraphExplorerComponent/EdgeInfoCache.ts +src/Explorer/Graph/GraphExplorerComponent/GraphData.test.ts +src/Explorer/Graph/GraphExplorerComponent/GraphData.ts +src/Explorer/Graph/GraphExplorerComponent/GraphUtil.test.ts +src/Explorer/Graph/GraphExplorerComponent/GraphUtil.ts +src/Explorer/Graph/GraphExplorerComponent/GremlinClient.test.ts +src/Explorer/Graph/GraphExplorerComponent/GremlinClient.ts +src/Explorer/Graph/GraphExplorerComponent/GremlinSimpleClient.test.ts +src/Explorer/Graph/GraphExplorerComponent/GremlinSimpleClient.ts +src/Explorer/Graph/GraphStyleComponent/GraphStyle.test.ts +src/Explorer/Graph/GraphStyleComponent/GraphStyleComponent.ts +src/Explorer/Graph/NewVertexComponent/NewVertex.test.ts +src/Explorer/Graph/NewVertexComponent/NewVertexComponent.ts +src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.test.ts +src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.ts +src/Explorer/Menus/ContextMenu.ts +src/Explorer/MostRecentActivity/MostRecentActivity.ts +src/Explorer/Notebook/FileSystemUtil.ts +src/Explorer/Notebook/NTeractUtil.ts +src/Explorer/Notebook/NotebookClientV2.ts +src/Explorer/Notebook/NotebookComponent/NotebookContentProvider.ts +src/Explorer/Notebook/NotebookComponent/__mocks__/rx-jupyter.ts +src/Explorer/Notebook/NotebookComponent/actions.ts +src/Explorer/Notebook/NotebookComponent/epics.test.ts +src/Explorer/Notebook/NotebookComponent/epics.ts +src/Explorer/Notebook/NotebookComponent/loadTransform.ts +src/Explorer/Notebook/NotebookComponent/reducers.ts +src/Explorer/Notebook/NotebookComponent/store.ts +src/Explorer/Notebook/NotebookComponent/types.ts +src/Explorer/Notebook/NotebookContainerClient.ts +src/Explorer/Notebook/NotebookContentClient.ts +src/Explorer/Notebook/NotebookContentItem.ts +src/Explorer/Notebook/NotebookUtil.ts +src/Explorer/OpenActions.test.ts +src/Explorer/OpenActions.ts +src/Explorer/OpenActionsStubs.ts +src/Explorer/Panes/AddCollectionPane.test.ts +src/Explorer/Panes/AddCollectionPane.ts +src/Explorer/Panes/AddDatabasePane.test.ts +src/Explorer/Panes/AddDatabasePane.ts +src/Explorer/Panes/BrowseQueriesPane.ts +src/Explorer/Panes/CassandraAddCollectionPane.ts +src/Explorer/Panes/ClusterLibraryPane.ts +src/Explorer/Panes/ContextualPaneBase.ts +src/Explorer/Panes/DeleteCollectionConfirmationPane.test.ts +src/Explorer/Panes/DeleteCollectionConfirmationPane.ts +src/Explorer/Panes/DeleteDatabaseConfirmationPane.test.ts +src/Explorer/Panes/DeleteDatabaseConfirmationPane.ts +src/Explorer/Panes/ExecuteSprocParamsPane.ts +src/Explorer/Panes/GraphStylingPane.ts +src/Explorer/Panes/LibraryManagePane.ts +src/Explorer/Panes/LoadQueryPane.ts +src/Explorer/Panes/ManageSparkClusterPane.ts +src/Explorer/Panes/NewVertexPane.ts +src/Explorer/Panes/PaneComponents.ts +src/Explorer/Panes/RenewAdHocAccessPane.ts +src/Explorer/Panes/SaveQueryPane.ts +src/Explorer/Panes/SettingsPane.test.ts +src/Explorer/Panes/SettingsPane.ts +src/Explorer/Panes/SetupNotebooksPane.ts +src/Explorer/Panes/SetupSparkClusterPane.ts +src/Explorer/Panes/StringInputPane.ts +src/Explorer/Panes/SwitchDirectoryPane.ts +src/Explorer/Panes/Tables/AddTableEntityPane.ts +src/Explorer/Panes/Tables/EditTableEntityPane.ts +src/Explorer/Panes/Tables/EntityPropertyViewModel.ts +src/Explorer/Panes/Tables/QuerySelectPane.ts +src/Explorer/Panes/Tables/TableColumnOptionsPane.ts +src/Explorer/Panes/Tables/TableEntityPane.ts +src/Explorer/Panes/Tables/Validators/EntityPropertyNameValidator.ts +src/Explorer/Panes/Tables/Validators/EntityPropertyValidationCommon.ts +src/Explorer/Panes/Tables/Validators/EntityPropertyValueValidator.ts +src/Explorer/Panes/UploadFilePane.ts +src/Explorer/Panes/UploadItemsPane.ts +src/Explorer/SplashScreen/SplashScreenComponentAdapter.test.ts +src/Explorer/Tables/Constants.ts +src/Explorer/Tables/DataTable/CacheBase.ts +src/Explorer/Tables/DataTable/DataTableBindingManager.ts +src/Explorer/Tables/DataTable/DataTableBuilder.ts +src/Explorer/Tables/DataTable/DataTableContextMenu.ts +src/Explorer/Tables/DataTable/DataTableOperationManager.ts +src/Explorer/Tables/DataTable/DataTableOperations.ts +src/Explorer/Tables/DataTable/DataTableUtilities.ts +src/Explorer/Tables/DataTable/DataTableViewModel.ts +src/Explorer/Tables/DataTable/TableCommands.ts +src/Explorer/Tables/DataTable/TableEntityCache.ts +src/Explorer/Tables/DataTable/TableEntityListViewModel.ts +src/Explorer/Tables/Entities.ts +src/Explorer/Tables/QueryBuilder/ClauseGroup.ts +src/Explorer/Tables/QueryBuilder/ClauseGroupViewModel.ts +src/Explorer/Tables/QueryBuilder/CustomTimestampHelper.ts +src/Explorer/Tables/QueryBuilder/DateTimeUtilities.test.ts +src/Explorer/Tables/QueryBuilder/DateTimeUtilities.ts +src/Explorer/Tables/QueryBuilder/QueryBuilderViewModel.ts +src/Explorer/Tables/QueryBuilder/QueryClauseViewModel.ts +src/Explorer/Tables/QueryBuilder/QueryViewModel.ts +src/Explorer/Tables/TableDataClient.ts +src/Explorer/Tables/TableEntityProcessor.ts +src/Explorer/Tables/Utilities.ts +src/Explorer/Tabs/ConflictsTab.ts +src/Explorer/Tabs/DatabaseSettingsTab.ts +src/Explorer/Tabs/DocumentsTab.test.ts +src/Explorer/Tabs/DocumentsTab.ts +src/Explorer/Tabs/GraphTab.ts +src/Explorer/Tabs/MongoDocumentsTab.ts +src/Explorer/Tabs/MongoQueryTab.ts +src/Explorer/Tabs/MongoShellTab.ts +src/Explorer/Tabs/NotebookTab.ts +src/Explorer/Tabs/NotebookV2Tab.ts +src/Explorer/Tabs/QueryTab.test.ts +src/Explorer/Tabs/QueryTab.ts +src/Explorer/Tabs/QueryTablesTab.ts +src/Explorer/Tabs/ScriptTabBase.ts +src/Explorer/Tabs/SettingsTab.test.ts +src/Explorer/Tabs/SettingsTab.ts +src/Explorer/Tabs/SparkMasterTab.ts +src/Explorer/Tabs/StoredProcedureTab.ts +src/Explorer/Tabs/TabComponents.ts +src/Explorer/Tabs/TabsBase.ts +src/Explorer/Tabs/TriggerTab.ts +src/Explorer/Tabs/UserDefinedFunctionTab.ts +src/Explorer/Tabs/__mocks__/NotebookTab.ts +src/Explorer/Tree/AccessibleVerticalList.ts +src/Explorer/Tree/Collection.test.ts +src/Explorer/Tree/Collection.ts +src/Explorer/Tree/ConflictId.ts +src/Explorer/Tree/Database.ts +src/Explorer/Tree/DocumentId.ts +src/Explorer/Tree/ObjectId.ts +src/Explorer/Tree/ResourceTokenCollection.ts +src/Explorer/Tree/StoredProcedure.ts +src/Explorer/Tree/TreeComponents.ts +src/Explorer/Tree/Trigger.ts +src/Explorer/Tree/UserDefinedFunction.ts +src/Explorer/WaitsForTemplateViewModel.ts +src/GitHub/GitHubClient.test.ts +src/GitHub/GitHubClient.ts +src/GitHub/GitHubConnector.ts +src/GitHub/GitHubContentProvider.test.ts +src/GitHub/GitHubContentProvider.ts +src/GitHub/GitHubOAuthService.ts +src/HostedExplorer.ts +src/Index.ts +src/Juno/JunoClient.test.ts +src/Juno/JunoClient.ts +src/Main.ts +src/NotebookWorkspaceManager/NotebookWorkspaceManager.ts +src/NotebookWorkspaceManager/NotebookWorkspaceResourceProviderMockClients.ts +src/Platform/Emulator/DataAccessUtility.ts +src/Platform/Emulator/ExplorerFactory.ts +src/Platform/Emulator/Main.ts +src/Platform/Emulator/NotificationsClient.ts +src/Platform/Hosted/ArmResourceUtils.ts +src/Platform/Hosted/Authorization.ts +src/Platform/Hosted/DataAccessUtility.ts +src/Platform/Hosted/ExplorerFactory.ts +src/Platform/Hosted/Helpers/ConnectionStringParser.test.ts +src/Platform/Hosted/Helpers/ConnectionStringParser.ts +src/Platform/Hosted/HostedUtils.test.ts +src/Platform/Hosted/HostedUtils.ts +src/Platform/Hosted/Main.ts +src/Platform/Hosted/Maint.test.ts +src/Platform/Hosted/NotificationsClient.ts +src/Platform/Portal/DataAccessUtility.ts +src/Platform/Portal/ExplorerFactory.ts +src/Platform/Portal/Main.ts +src/Platform/Portal/NotificationsClient.ts +src/PlatformType.ts +src/ReactDevTools.ts +src/ResourceProvider/IResourceProviderClient.test.ts +src/ResourceProvider/IResourceProviderClient.ts +src/ResourceProvider/ResourceProviderClient.ts +src/ResourceProvider/ResourceProviderClientFactory.ts +src/RouteHandlers/RouteHandler.ts +src/RouteHandlers/TabRouteHandler.test.ts +src/RouteHandlers/TabRouteHandler.ts +src/Shared/AddCollectionUtility.test.ts +src/Shared/AddCollectionUtility.ts +src/Shared/AddDatabaseUtility.test.ts +src/Shared/AddDatabaseUtility.ts +src/Shared/Ajax.ts +src/Shared/Constants.ts +src/Shared/DefaultExperienceUtility.test.ts +src/Shared/DefaultExperienceUtility.ts +src/Shared/ExplorerSettings.ts +src/Shared/PriceEstimateCalculator.ts +src/Shared/StorageUtility.test.ts +src/Shared/StorageUtility.ts +src/Shared/StringUtility.test.ts +src/Shared/StringUtility.ts +src/Shared/Telemetry/TelemetryConstants.ts +src/Shared/Telemetry/TelemetryProcessor.ts +src/Shared/appInsights.ts +src/SparkClusterManager/ArcadiaResourceManager.ts +src/SparkClusterManager/SparkClusterManager.ts +src/Terminal/JupyterLabAppFactory.ts +src/Terminal/NotebookAppContracts.d.ts +src/Terminal/index.ts +src/TokenProviders/PortalTokenProvider.ts +src/TokenProviders/TokenProviderFactory.ts +src/Utils/AuthorizationUtils.test.ts +src/Utils/AuthorizationUtils.ts +src/Utils/AutoPilotUtils.test.ts +src/Utils/AutoPilotUtils.ts +src/Utils/DatabaseAccountUtils.test.ts +src/Utils/DatabaseAccountUtils.ts +src/Utils/JunoUtils.ts +src/Utils/MessageValidation.ts +src/Utils/NotebookConfigurationUtils.ts +src/Utils/NotificationConsoleUtils.ts +src/Utils/OfferUtils.test.ts +src/Utils/OfferUtils.ts +src/Utils/PricingUtils.test.ts +src/Utils/PricingUtils.ts +src/Utils/QueryUtils.test.ts +src/Utils/QueryUtils.ts +src/Utils/StringUtils.test.ts +src/Utils/StringUtils.ts +src/applyExplorerBindings.ts +src/global.d.ts +src/quickstart.ts +src/setupTests.ts +src/workers/upload/definitions.ts +src/workers/upload/index.ts +src/Explorer/Controls/AccessibleElement/AccessibleElement.tsx +src/Explorer/Controls/Accordion/AccordionComponent.tsx +src/Explorer/Controls/AccountSwitch/AccountSwitchComponent.test.tsx +src/Explorer/Controls/AccountSwitch/AccountSwitchComponent.tsx +src/Explorer/Controls/AccountSwitch/AccountSwitchComponentAdapter.tsx +src/Explorer/Controls/Arcadia/ArcadiaMenuPicker.tsx +src/Explorer/Controls/CollapsiblePanel/CollapsiblePanel.tsx +src/Explorer/Controls/CommandButton/CommandButtonComponent.tsx +src/Explorer/Controls/DialogReactComponent/DialogComponent.tsx +src/Explorer/Controls/DialogReactComponent/DialogComponentAdapter.tsx +src/Explorer/Controls/Directory/DefaultDirectoryDropdownComponent.test.tsx +src/Explorer/Controls/Directory/DefaultDirectoryDropdownComponent.tsx +src/Explorer/Controls/Directory/DirectoryComponentAdapter.tsx +src/Explorer/Controls/Directory/DirectoryListComponent.test.tsx +src/Explorer/Controls/Directory/DirectoryListComponent.tsx +src/Explorer/Controls/Editor/EditorReact.tsx +src/Explorer/Controls/InputTypeahead/InputTypeaheadComponent.tsx +src/Explorer/Controls/LibraryManagement/ClusterLibraryGrid.tsx +src/Explorer/Controls/LibraryManagement/ClusterLibraryGridAdapter.tsx +src/Explorer/Controls/LibraryManagement/LibraryManage.tsx +src/Explorer/Controls/LibraryManagement/LibraryManageComponentAdapter.tsx +src/Explorer/Controls/Notebook/NotebookTerminalComponent.test.tsx +src/Explorer/Controls/Notebook/NotebookTerminalComponent.tsx +src/Explorer/Controls/NotebookViewer/NotebookMetadataComponent.tsx +src/Explorer/Controls/NotebookViewer/NotebookViewer.tsx +src/Explorer/Controls/NotebookViewer/NotebookViewerComponent.tsx +src/Explorer/Controls/QueriesGridReactComponent/QueriesGridComponent.tsx +src/Explorer/Controls/QueriesGridReactComponent/QueriesGridComponentAdapter.tsx +src/Explorer/Controls/ResizeSensorReactComponent/ResizeSensorComponent.tsx +src/Explorer/Controls/Spark/ClusterSettingsComponent.tsx +src/Explorer/Controls/Spark/ClusterSettingsComponentAdapter.tsx +src/Explorer/Controls/Tabs/TabComponent.tsx +src/Explorer/Controls/TreeComponent/TreeComponent.test.tsx +src/Explorer/Controls/TreeComponent/TreeComponent.tsx +src/Explorer/Graph/GraphExplorerComponent/EditorNeighborsComponent.tsx +src/Explorer/Graph/GraphExplorerComponent/EditorNodePropertiesComponent.test.tsx +src/Explorer/Graph/GraphExplorerComponent/EditorNodePropertiesComponent.tsx +src/Explorer/Graph/GraphExplorerComponent/GraphExplorer.test.tsx +src/Explorer/Graph/GraphExplorerComponent/GraphExplorer.tsx +src/Explorer/Graph/GraphExplorerComponent/GraphExplorerAdapter.tsx +src/Explorer/Graph/GraphExplorerComponent/GraphVizComponent.tsx +src/Explorer/Graph/GraphExplorerComponent/LeftPaneComponent.tsx +src/Explorer/Graph/GraphExplorerComponent/MiddlePaneComponent.tsx +src/Explorer/Graph/GraphExplorerComponent/NodePropertiesComponent.test.tsx +src/Explorer/Graph/GraphExplorerComponent/NodePropertiesComponent.tsx +src/Explorer/Graph/GraphExplorerComponent/QueryContainerComponent.tsx +src/Explorer/Graph/GraphExplorerComponent/ReadOnlyNeighborsComponent.tsx +src/Explorer/Graph/GraphExplorerComponent/ReadOnlyNodePropertiesComponent.test.tsx +src/Explorer/Graph/GraphExplorerComponent/ReadOnlyNodePropertiesComponent.tsx +src/Explorer/Menus/CommandBar/CommandBarComponentAdapter.tsx +src/Explorer/Menus/CommandBar/CommandBarUtil.test.tsx +src/Explorer/Menus/CommandBar/CommandBarUtil.tsx +src/Explorer/Menus/CommandBar/MemoryTrackerComponent.tsx +src/Explorer/Menus/NavBar/ControlBarComponent.tsx +src/Explorer/Menus/NavBar/ControlBarComponentAdapter.tsx +src/Explorer/Menus/NavBar/MeControlComponent.test.tsx +src/Explorer/Menus/NavBar/MeControlComponent.tsx +src/Explorer/Menus/NavBar/MeControlComponentAdapter.tsx +src/Explorer/Menus/NotificationConsole/NotificationConsoleComponent.test.tsx +src/Explorer/Menus/NotificationConsole/NotificationConsoleComponent.tsx +src/Explorer/Menus/NotificationConsole/NotificationConsoleComponentAdapter.tsx +src/Explorer/Notebook/NotebookComponent/NotebookComponent.tsx +src/Explorer/Notebook/NotebookComponent/NotebookComponentAdapter.tsx +src/Explorer/Notebook/NotebookComponent/NotebookComponentBootstrapper.tsx +src/Explorer/Notebook/NotebookComponent/VirtualCommandBarComponent.tsx +src/Explorer/Notebook/NotebookComponent/contents/file/index.tsx +src/Explorer/Notebook/NotebookComponent/contents/file/text-file.tsx +src/Explorer/Notebook/NotebookComponent/contents/index.tsx +src/Explorer/Notebook/NotebookRenderer/AzureTheme.tsx +src/Explorer/Notebook/NotebookRenderer/NotebookReadOnlyRenderer.tsx +src/Explorer/Notebook/NotebookRenderer/NotebookRenderer.tsx +src/Explorer/Notebook/NotebookRenderer/Prompt.tsx +src/Explorer/Notebook/NotebookRenderer/PromptContent.tsx +src/Explorer/Notebook/NotebookRenderer/StatusBar.test.tsx +src/Explorer/Notebook/NotebookRenderer/StatusBar.tsx +src/Explorer/Notebook/NotebookRenderer/Toolbar.tsx +src/Explorer/Notebook/NotebookRenderer/decorators/CellCreator.tsx +src/Explorer/Notebook/NotebookRenderer/decorators/CellLabeler.tsx +src/Explorer/Notebook/NotebookRenderer/decorators/HoverableCell.tsx +src/Explorer/Notebook/NotebookRenderer/decorators/draggable/index.tsx +src/Explorer/Notebook/NotebookRenderer/decorators/hijack-scroll/index.tsx +src/Explorer/Notebook/NotebookRenderer/decorators/kbd-shortcuts/index.tsx +src/Explorer/Notebook/temp/inputs/connected-editors/codemirror.tsx +src/Explorer/Notebook/temp/inputs/editor.tsx +src/Explorer/Notebook/temp/markdown-cell.tsx +src/Explorer/Notebook/temp/source.tsx +src/Explorer/Notebook/temp/syntax-highlighter/index.tsx +src/Explorer/SplashScreen/SplashScreenComponent.tsx +src/Explorer/SplashScreen/SplashScreenComponentApdapter.tsx +src/Explorer/Tabs/GalleryTab.tsx +src/Explorer/Tabs/NotebookViewerTab.tsx +src/Explorer/Tabs/TerminalTab.tsx +src/Explorer/Tree/ResourceTreeAdapter.tsx +src/Explorer/Tree/ResourceTreeAdapterForResourceToken.tsx +src/GalleryViewer/Cards/CardStyleConstants.tsx +src/GalleryViewer/Cards/GalleryCardComponent.tsx +src/GalleryViewer/GalleryViewer.tsx +src/GalleryViewer/GalleryViewerComponent.tsx +cypress/integration/dataexplorer/CASSANDRA/addCollection.spec.ts +cypress/integration/dataexplorer/GRAPH/addCollection.spec.ts +cypress/integration/dataexplorer/ci-tests/addCollectionPane.spec.ts +cypress/integration/dataexplorer/ci-tests/createDatabase.spec.ts +cypress/integration/dataexplorer/ci-tests/deleteCollection.spec.ts +cypress/integration/dataexplorer/ci-tests/deleteDatabase.spec.ts +cypress/integration/dataexplorer/MONGO/addCollection.spec.ts +cypress/integration/dataexplorer/MONGO/addCollectionAutopilot.spec.ts +cypress/integration/dataexplorer/MONGO/addCollectionExistingDatabase.spec.ts +cypress/integration/dataexplorer/MONGO/provisionDatabaseThroughput.spec.ts +cypress/integration/dataexplorer/SQL/addCollection.spec.ts +cypress/integration/dataexplorer/TABLE/addCollection.spec.ts +cypress/integration/notebook/newNotebook.spec.ts +cypress/integration/notebook/resourceTree.spec.ts +__mocks__/AddDatabaseUtility.ts +__mocks__/monaco-editor.ts +src/Explorer/Tree/ResourceTreeAdapterForResourceToken.test.tsx \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 000000000..2635f3e21 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,45 @@ +module.exports = { + env: { + browser: true, + es6: true + }, + plugins: ["@typescript-eslint"], + extends: [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" + ], + globals: { + Atomics: "readonly", + SharedArrayBuffer: "readonly" + }, + parser: "@typescript-eslint/parser", + parserOptions: { + ecmaFeatures: { + jsx: true + }, + ecmaVersion: 2018, + sourceType: "module" + }, + overrides: [ + { + files: ["**/*.tsx"], + env: { + jest: true + }, + extends: ["plugin:react/recommended"], + plugins: ["react"] + }, + { + files: ["**/*.test.{ts,tsx}"], + env: { + jest: true + }, + extends: ["plugin:jest/recommended"], + plugins: ["jest"] + } + ], + rules: { + curly: "error" + } +}; diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..4c7d641eb --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @southpolesteve @ato9000 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..0930d4888 --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +built/* +dist/* +coverage/** +css/* +Definitions/**/* +libs/**/* +**/node_modules/* +pkg/DataExplorer/* +test/out/* +workers/**/*.js +*.trx +cypress/videos +cypress/screenshots +cypress/fixtures +notebookapp/* +Contracts/* +.DS_Store +.cache/ \ No newline at end of file diff --git a/.npmrc b/.npmrc new file mode 100644 index 000000000..449691b70 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +save-exact=true \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..46e9150b3 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,40 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Debug Jest Tests", + "type": "node", + "request": "launch", + "runtimeArgs": [ + "--inspect-brk", + "${workspaceRoot}/node_modules/jest/bin/jest.js", + "--runInBand", + "--coverage", "false" + ], + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "port": 9229 + }, + { + "name": "Debug Jest Current Test", + "type": "node", + "request": "launch", + "runtimeArgs": [ + "--inspect-brk", + "${workspaceRoot}/node_modules/jest/bin/jest.js", + "${fileBasenameNoExtension}", + "--coverage", "false", + // "--watch", + // // --no-cache only used to make --watch work. Otherwise jest ignores the breakpoints. + // // https://github.com/facebook/jest/issues/6683 + // "--no-cache" + ], + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "port": 9229 + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..f4c1f6881 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,21 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.exclude": { + ".vs": true, + ".vscode/**": true, + "*.trx": true, + "**/.DS_Store": true, + "**/.git": true, + "**/.hg": true, + "**/.svn": true, + "built/**": true, + "coverage/**": true, + "libs/**": true, + "node_modules/**": true, + "package-lock.json": true, + "quickstart/**": true, + "test/out/**": true, + "workers/libs/**": true + }, + "typescript.tsdk": "node_modules/typescript/lib" +} \ No newline at end of file diff --git a/DataExplorer.nuspec b/DataExplorer.nuspec new file mode 100644 index 000000000..34fff1ccf --- /dev/null +++ b/DataExplorer.nuspec @@ -0,0 +1,24 @@ + + + + Azure.Cosmos.DB.Data.Explorer + 0.0.1-preview + Azure Cosmos DB Data Explorer + Microsoft + Microsoft + true + http://go.microsoft.com/fwlink/?LinkId=848760 + http://go.microsoft.com/fwlink/?LinkId=848761 + http://go.microsoft.com/fwlink/?LinkID=288890 + Cosmos DB Data Explorer + Cosmos DB Data Explorer + Cosmos DB Data Explorer + + + + + + + + + \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..21071075c --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/README.md b/README.md new file mode 100644 index 000000000..440ac514e --- /dev/null +++ b/README.md @@ -0,0 +1,95 @@ +# CosmosDB Explorer + +## Getting Started + +- `npm install` +- `npm run build` + +## Developing + +### Watch mode + +Run `npm run watch` to start the development server and automatically rebuild on changes + +### Specifying Development Platform + +Setting the environment variable `PLATFORM` during the build process will force the explorer to load the specified platform. By default in development it will run in `Hosted` mode. Valid options: + +- Hosted +- Emulator +- Portal + +`PLATFORM=Emulator npm run watch` + +### Hosted Development + +The default webpack dev server configuration will proxy requests to the production portal backend: `https://main.documentdb.ext.azure.com`. This will allow you to use production connection strings on your local machine. + +To run pure hosted mode, in `webpack.config.js` change index HtmlWebpackPlugin to use hostedExplorer.html and change entry for index to use HostedExplorer.ts. + +### Emulator Development + +In a window environment, running `npm run build` will automatically copy the built files from `/dist` over to the default emulator install paths. In a non-windows enironment you can specify an alternate endpoint using `EMULATOR_ENDPOINT` and webpack dev server will proxy requests for you. + +`PLATFORM=Emulator EMULATOR_ENDPOINT=https://my-vm.azure.com:8081 npm run watch` + +#### Setting up a Remote Emulator + +The Cosmos emulator currently only runs in Windows environments. You can still develop on a non-Windows machine by setting up an emulator on a windows box and exposing its ports publicly: + +1. Expose these ports publicly: 8081, 8900, 8979, 10250, 10251, 10252, 10253, 10254, 10255, 10256 + +2. Download and install the emulator: https://docs.microsoft.com/en-us/azure/cosmos-db/local-emulator + +3. Start the emulator from PowerShell: + +``` +> cd C:/ + +> .\CosmosDB.Emulator.exe -AllowNetworkAccess -Key="" +``` + +### Portal Development + +The Cosmos Portal that consumes this repo is not currently open source. If you have access to this project, `npm run build` will copy the built files over to the portal where they will be loaded by the portal development environment + +You can however load a local running instance of data explorer in the production portal. + +1. Turn off browser SSL validation for localhost: chrome://flags/#allow-insecure-localhost OR Install valid SSL certs for localhost (on IE, follow these [instructions](https://www.technipages.com/ie-bypass-problem-with-this-websites-security-certificate) to install the localhost certificate in the right place) +2. Whitelist `https://localhost:1234` domain for CORS in the Azure Cosmos DB portal +3. Start the project in portal mode: `PLATFORM=Portal npm run watch` +4. Load the portal using the following link: https://ms.portal.azure.com/?dataExplorerSource=https%3A%2F%2Flocalhost%3A1234%2Fexplorer.html + +Live reload will occur, but data explorer will not properly integrate again with the parent iframe. You will have to manually reload the page. + +### Testing + +#### Unit Tests + +Unit tests are located adjacent to the code under test and run with [Jest](https://jestjs.io/): + +`npm run test` + +#### End to End Tests + +[Cypress](https://www.cypress.io/) is used for end to end tests and are contained in `cypress/`. Currently, it operates as sub project with its own typescript config and dependencies. It also only operates against the emulator. To run cypress tests: + +1. Ensure the emulator is running +2. Start cosmos explorer in emulator mode: `PLATFORM=Emulator npm run watch` +3. Move into `cypress/` folder: `cd cypress` +4. Install dependencies: `npm install` +5. Run cypress headless(`npm run test`) or in interactive mode(`npm run test:debug`) + +# Contributing + +This project welcomes contributions and suggestions. Most contributions require you to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us +the rights to use your contribution. For details, visit https://cla.microsoft.com. + +When you submit a pull request, a CLA-bot will automatically determine whether you need to provide +a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions +provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/ReleaseNotes.md b/ReleaseNotes.md new file mode 100644 index 000000000..73ec07db8 --- /dev/null +++ b/ReleaseNotes.md @@ -0,0 +1,10 @@ +#Release Note - Cosmos Explorer + +##August 2019 +* Added support to display multiple-values properties for Graph +* Added support for query modes to migrated Fixed containers +* Updated Azure Cosmos DB JavaScript library used in Data Explorer to version 3.1.1 +* Remove spatial index from default indexing policy on container creation +* Disable stored procedures, UDF and triggers in Cosmos Explorer for accounts with Azure Cosmos DB for MongoDB API +* Disallow composite keys for Gremlin +* Performance Improvement \ No newline at end of file diff --git a/__mocks__/AddDatabaseUtility.ts b/__mocks__/AddDatabaseUtility.ts new file mode 100644 index 000000000..11561a643 --- /dev/null +++ b/__mocks__/AddDatabaseUtility.ts @@ -0,0 +1,5 @@ +export class AddDbUtilities { + createGremlinDatabase(params: any) { + return Promise.resolve(1) + } +} \ No newline at end of file diff --git a/__mocks__/monaco-editor.ts b/__mocks__/monaco-editor.ts new file mode 100644 index 000000000..b87c4b994 --- /dev/null +++ b/__mocks__/monaco-editor.ts @@ -0,0 +1,4 @@ +export const editor = { + create: () => {}, + setTheme: () => {} +}; diff --git a/azure-pipelines.yaml b/azure-pipelines.yaml new file mode 100644 index 000000000..aca1ec5a6 --- /dev/null +++ b/azure-pipelines.yaml @@ -0,0 +1,211 @@ +trigger: + branches: + include: + - master + - "*" + paths: + include: + - "*" + exclude: + - Product/Portal/CapacityCalculator/* + - Product/Portal/DefaultConsistency/* +pool: + vmImage: "windows-latest" +jobs: + - job: FormatLintCompile + displayName: "Format/Lint/Compile" + steps: + - task: Npm@1 + displayName: "Install Dependencies" + inputs: + workingDir: 'Product\Portal\DataExplorer' + verbose: false + - task: Npm@1 + displayName: "Format" + inputs: + command: custom + workingDir: 'Product\Portal\DataExplorer' + verbose: false + customCommand: "run format:check" + - task: Npm@1 + displayName: "Lint" + inputs: + command: custom + workingDir: 'Product\Portal\DataExplorer' + verbose: false + customCommand: "run lint" + - task: Npm@1 + displayName: "Compile" + inputs: + command: custom + workingDir: 'Product\Portal\DataExplorer' + verbose: false + customCommand: "run compile" + - task: Npm@1 + displayName: "Compile Strict Mode Files" + inputs: + command: custom + workingDir: 'Product\Portal\DataExplorer' + verbose: false + customCommand: "run compile:strict" + - job: EndToEndTests + displayName: "End to End Tests" + steps: + - powershell: | + Write-Host "Starting Comsos DB Emulator" + Start-Process "$env:ProgramFiles\Azure Cosmos DB Emulator\CosmosDB.Emulator.exe" "/NoUI /DisableRateLimiting" -Verb RunAs + displayName: "Start Emulator" + - bash: | + npm ci --prefix ./Product/Portal/DataExplorer + npm start --prefix ./Product/Portal/DataExplorer & + npm ci --prefix ./Product/Portal/DataExplorer/cypress + npm run test:ci --prefix ./Product/Portal/DataExplorer/cypress -- --spec ./integration/dataexplorer/ci-tests/createDatabase.spec.ts + displayName: "Start Server and Run Tests" + env: + EMULATOR_ENDPOINT: https://0.0.0.0:8081/ + NODE_TLS_REJECT_UNAUTHORIZED: 0 + - task: PublishBuildArtifacts@1 + displayName: "Publish Screenshots" + inputs: + targetPath: $(System.DefaultWorkingDirectory)/Product/Portal/DataExplorer/cypress/cypress/screenshots + artifactName: e2e-screenshots + condition: failed() + continueOnError: true + + - task: PublishBuildArtifacts@1 + displayName: "Publish Videos" + inputs: + pathtoPublish: $(System.DefaultWorkingDirectory)/Product/Portal/DataExplorer/cypress/cypress/videos + artifactName: e2e-videos + condition: succeededOrFailed() + continueOnError: true + - job: UnitTests + displayName: "Unit Tests" + steps: + - task: NodeTool@0 + displayName: "Use Node 12.x" + inputs: + versionSpec: 12.x + + - task: Npm@1 + displayName: "Install Dependencies" + inputs: + command: custom + workingDir: "$(System.DefaultWorkingDirectory)/Product/Portal/DataExplorer" + verbose: false + customCommand: "ci" + + - task: Npm@1 + displayName: "Run Unit Tests" + inputs: + command: custom + workingDir: "$(System.DefaultWorkingDirectory)/Product/Portal/DataExplorer" + verbose: false + customCommand: "run test" + + - task: PublishTestResults@2 + displayName: "Publish Test Results" + inputs: + testResultsFormat: VSTest + testResultsFiles: "**/*.trx" + mergeTestResults: true + testRunTitle: "Check-in Tests" + condition: succeededOrFailed() + + - task: PublishCodeCoverageResults@1 + displayName: "Publish Code Coverage Report" + inputs: + codeCoverageTool: Cobertura + summaryFileLocation: "$(System.DefaultWorkingDirectory)/Product/Portal/DataExplorer/coverage/cobertura-coverage.xml" + pathToSources: "$(System.DefaultWorkingDirectory)/Product/Portal/DataExplorer" + reportDirectory: "$(System.DefaultWorkingDirectory)/Product/Portal/DataExplorer/coverage/html" + - job: Build + steps: + - task: Cache@2 + inputs: + key: 'dataexplorer | "$(Agent.OS)" |' + restoreKeys: 'dataexplorer | "$(Agent.OS)" |' + path: $(System.DefaultWorkingDirectory)/Product/Portal/DataExplorer/.cache + displayName: Restore Build Caches + - task: NodeTool@0 + displayName: "Use Node 12.x" + inputs: + versionSpec: 12.x + + - task: Npm@1 + displayName: "Install Dependencies" + inputs: + workingDir: 'Product\Portal\DataExplorer' + verbose: false + + - task: Npm@1 + displayName: "Build Contracts" + inputs: + command: custom + workingDir: 'Product\Portal\DataExplorer' + verbose: false + customCommand: "run build:contracts" + - task: Npm@1 + displayName: "Bundle - Production" + inputs: + command: custom + workingDir: 'Product\Portal\DataExplorer' + verbose: false + customCommand: "run pack:prod" + - task: Npm@1 + displayName: "Copy Output Files to Consumers" + inputs: + command: custom + workingDir: 'Product\Portal\DataExplorer' + verbose: false + customCommand: "run copyToConsumers" + - powershell: | + $GitCommitSHA = $env:BUILD_SOURCEVERSION + $NuspecPath = "$env:BUILD_ARTIFACTSTAGINGDIRECTORY" + $VersionToReplace = "0.0.1-preview" + ((Get-Content -path "$NuspecPath\DataExplorer.nuspec" -Raw) -replace $VersionToReplace ,("1.2.0-$GitCommitSHA")) | Set-Content -Path "$NuspecPath\DataExplorer.nuspec" + cat "$NuspecPath\DataExplorer.nuspec" + displayName: "Bump Package Version" + continueOnError: true + + - task: NuGetCommand@2 + displayName: "Create NuGet package" + inputs: + command: pack + packagesToPack: "$(Build.ArtifactStagingDirectory)/**/*.nuspec" + packDestination: '$(Build.ArtifactStagingDirectory)\NuGet' + + - task: NuGetCommand@2 + displayName: "NuGet push" + inputs: + command: push + publishVstsFeed: "4e0718b3-a885-4d77-b8c2-09bb2f6eecec" + allowPackageConflicts: true + + - powershell: | + $NuspecPath = "$env:BUILD_ARTIFACTSTAGINGDIRECTORY" + $PackageId= "Azure.Cosmos.DB.Data.Explorer" + ((Get-Content -path "$NuspecPath\DataExplorer.nuspec" -Raw) -replace $PackageId,("$PackageId.MPAC")) | Set-Content -Path "$NuspecPath\DataExplorer.nuspec" + cat "$NuspecPath\DataExplorer.nuspec" + displayName: "Create MPAC nuspec" + continueOnError: true + + - task: NuGetCommand@2 + displayName: "Create NuGet MPAC package " + inputs: + command: pack + packagesToPack: "$(Build.ArtifactStagingDirectory)/**/*.nuspec" + packDestination: '$(Build.ArtifactStagingDirectory)\NuGet' + + - task: NuGetCommand@2 + displayName: "NuGet push MPAC" + inputs: + command: push + publishVstsFeed: "4e0718b3-a885-4d77-b8c2-09bb2f6eecec" + allowPackageConflicts: true + + - task: PublishBuildArtifacts@1 + displayName: "Publish Artifact: DataExplorer NuGet" + inputs: + PathtoPublish: '$(Build.ArtifactStagingDirectory)\NuGet' + ArtifactName: DataExplorerNuGet diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 000000000..73cba71b1 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: [["@babel/preset-env", { targets: { node: "current" } }], "@babel/preset-react", "@babel/preset-typescript"] +}; diff --git a/copyToConsumers.js b/copyToConsumers.js new file mode 100644 index 000000000..72da59af2 --- /dev/null +++ b/copyToConsumers.js @@ -0,0 +1,24 @@ +const fs = require("fs-extra"); + +const dataExplorerLocalPath = process.env.BUILD_ARTIFACTSTAGINGDIRECTORY || process.env.DATAEXPLORER_PATH; +const dataExplorerEmulatorPath = process.env.ProgramFiles + "/Azure Cosmos DB Emulator/Packages/DataExplorer"; +const newDataExplorerEmulatorPath = process.env.ProgramFiles + "/Azure Cosmos Emulator/Packages/DataExplorer"; + +console.log("Copying dist/ to portal and emulator"); +cleanAndCopy(dataExplorerLocalPath); +cleanAndCopy(dataExplorerEmulatorPath); +cleanAndCopy(newDataExplorerEmulatorPath); + +function cleanAndCopy(path) { + if (fs.existsSync(path)) { + fs.removeSync(path); + fs.copySync("dist", path); + if (fs.existsSync("Contracts")) { + fs.copySync("Contracts", path + "/contracts"); + } else { + console.log("Contracts folder does not exist. Doing nothing."); + } + } else { + console.log(`Path: "${path}" does not exist. Doing nothing.`); + } +} diff --git a/cypress/.gitignore b/cypress/.gitignore new file mode 100644 index 000000000..d5a44f201 --- /dev/null +++ b/cypress/.gitignore @@ -0,0 +1 @@ +cypress.env.json \ No newline at end of file diff --git a/cypress/cypress.json b/cypress/cypress.json new file mode 100644 index 000000000..4c9e0a6cb --- /dev/null +++ b/cypress/cypress.json @@ -0,0 +1,15 @@ +{ + "integrationFolder": "./integration", + "pluginsFile": false, + "fixturesFolder": false, + "supportFile": "./support/index.js", + "defaultCommandTimeout": 60000, + "chromeWebSecurity": false, + "reporter": "mochawesome", + "reporterOptions": { + "reportDir": "cypress/report", + "json": true, + "overwrite": false, + "html": false + } +} diff --git a/cypress/integration/dataexplorer/CASSANDRA/addCollection.spec.ts b/cypress/integration/dataexplorer/CASSANDRA/addCollection.spec.ts new file mode 100644 index 000000000..d063da6f0 --- /dev/null +++ b/cypress/integration/dataexplorer/CASSANDRA/addCollection.spec.ts @@ -0,0 +1,66 @@ +// 1. Click on "New Container" on the command bar. +// 2. Pane with the title "Add Container" should appear on the right side of the screen +// 3. It includes an input box for the database Id. +// 4. It includes a checkbox called "Create now". +// 5. When the checkbox is marked, enter new database id. +// 3. Create a database WITH "Provision throughput" checked. +// 4. Enter minimum throughput value of 400. +// 5. Enter container id to the container id text box. +// 6. Enter partition key to the partition key text box. +// 7. Click "OK" to create a new container. +// 8. Verify the new container is created along with the database id and should appead in the Data Explorer list in the left side of the screen. + +const connectionString = require("../../../utilities/connectionString"); + +let crypt = require("crypto"); + +context("Cassandra API Test - createDatabase", () => { + beforeEach(() => { + connectionString.loginUsingConnectionString(connectionString.constants.cassandra); + }); + + it("Create a new table in Cassandra API", () => { + const keyspaceId = `KeyspaceId${crypt.randomBytes(8).toString("hex")}`; + const tableId = `TableId112`; + + cy.get("iframe").then($element => { + const $body = $element.contents().find("body"); + cy.wrap($body) + .find('div[class="commandBarContainer"]') + .should("be.visible") + .find('button[data-test="New Table"]') + .should("be.visible") + .click(); + + cy.wrap($body) + .find('div[class="contextual-pane-in"]') + .should("be.visible") + .find('span[id="containerTitle"]'); + + cy.wrap($body) + .find('input[id="keyspace-id"]') + .should("be.visible") + .type(keyspaceId); + + cy.wrap($body) + .find('input[class="textfontclr"]') + .type(tableId); + + cy.wrap($body) + .find('input[data-test="databaseThroughputValue"]') + .should("have.value", "400"); + + cy.wrap($body) + .find('data-test="addCollection-createCollection"') + .click(); + + cy.wait(10000); + + cy.wrap($body) + .find('div[data-test="resourceTreeId"]') + .should("exist") + .find('div[class="treeComponent dataResourceTree"]') + .should("contain", tableId); + }); + }); +}); diff --git a/cypress/integration/dataexplorer/GRAPH/addCollection.spec.ts b/cypress/integration/dataexplorer/GRAPH/addCollection.spec.ts new file mode 100644 index 000000000..a212f3a67 --- /dev/null +++ b/cypress/integration/dataexplorer/GRAPH/addCollection.spec.ts @@ -0,0 +1,81 @@ +// 1. Click on "New Graph" on the command bar. +// 2. Pane with the title "Add Container" should appear on the right side of the screen +// 3. It includes an input box for the database Id. +// 4. It includes a checkbox called "Create now". +// 5. When the checkbox is marked, enter new database id. +// 3. Create a database WITH "Provision throughput" checked. +// 4. Enter minimum throughput value of 400. +// 5. Enter container id to the container id text box. +// 6. Enter partition key to the partition key text box. +// 7. Click "OK" to create a new container. +// 8. Verify the new container is created along with the database id and should appead in the Data Explorer list in the left side of the screen. + +const connectionString = require("../../../utilities/connectionString"); + +let crypt = require("crypto"); + +context("Graph API Test", () => { + beforeEach(() => { + connectionString.loginUsingConnectionString(connectionString.constants.graph); + }); + + it("Create a new graph in Graph API", () => { + const dbId = `TestDatabase${crypt.randomBytes(8).toString("hex")}`; + const graphId = `TestGraph${crypt.randomBytes(8).toString("hex")}`; + const partitionKey = `SharedKey${crypt.randomBytes(8).toString("hex")}`; + + cy.get("iframe").then($element => { + const $body = $element.contents().find("body"); + cy.wrap($body) + .find('div[class="commandBarContainer"]') + .should("be.visible") + .find('button[data-test="New Graph"]') + .should("be.visible") + .click(); + + cy.wrap($body) + .find('div[class="contextual-pane-in"]') + .should("be.visible") + .find('span[id="containerTitle"]'); + + cy.wrap($body) + .find('input[data-test="addCollection-createNewDatabase"]') + .check(); + + cy.wrap($body) + .find('input[data-test="addCollection-newDatabaseId"]') + .should("be.visible") + .type(dbId); + + cy.wrap($body) + .find('input[data-test="addCollectionPane-databaseSharedThroughput"]') + .check(); + + cy.wrap($body) + .find('input[data-test="databaseThroughputValue"]') + .should("have.value", "400"); + + cy.wrap($body) + .find('input[data-test="addCollection-collectionId"]') + .type(graphId); + + cy.wrap($body) + .find('input[data-test="addCollection-partitionKeyValue"]') + .type(partitionKey); + + cy.wrap($body) + .find('input[data-test="addCollection-createCollection"]') + .click(); + + cy.wait(10000); + + cy.wrap($body) + .find('div[data-test="resourceTreeId"]') + .should("exist") + .find('div[class="treeComponent dataResourceTree"]') + .should("contain", dbId) + .click() + .should("contain", graphId); + }); + }); +}); diff --git a/cypress/integration/dataexplorer/MONGO/addCollection.spec.ts b/cypress/integration/dataexplorer/MONGO/addCollection.spec.ts new file mode 100644 index 000000000..56d2fa868 --- /dev/null +++ b/cypress/integration/dataexplorer/MONGO/addCollection.spec.ts @@ -0,0 +1,80 @@ +// 1. Click on "New Container" on the command bar. +// 2. Pane with the title "Add Container" should appear on the right side of the screen +// 3. It includes an input box for the database Id. +// 4. It includes a checkbox called "Create now". +// 5. When the checkbox is marked, enter new database id. +// 3. Create a database WITH "Provision throughput" checked. +// 4. Enter minimum throughput value of 400. +// 5. Enter container id to the container id text box. +// 6. Enter partition key to the partition key text box. +// 7. Click "OK" to create a new container. +// // 8. Verify the new container is created along with the database id and should appead in the Data Explorer list in the left side of the screen. + +const connectionString = require("../../../utilities/connectionString"); + +let crypt = require("crypto"); + +context("Mongo API Test - createDatabase", () => { + beforeEach(() => { + connectionString.loginUsingConnectionString(connectionString.constants.mongo); + }); + + it("Create a new collection in Mongo API", () => { + const dbId = `TestDatabase${crypt.randomBytes(8).toString("hex")}`; + const collectionId = `TestCollection${crypt.randomBytes(8).toString("hex")}`; + const sharedKey = `SharedKey${crypt.randomBytes(8).toString("hex")}`; + + cy.get("iframe").then($element => { + const $body = $element.contents().find("body"); + cy.wrap($body) + .find('div[class="commandBarContainer"]') + .should("be.visible") + .find('button[data-test="New Collection"]') + .should("be.visible") + .click(); + + cy.wrap($body) + .find('div[class="contextual-pane-in"]') + .should("be.visible") + .find('span[id="containerTitle"]'); + + cy.wrap($body) + .find('input[data-test="addCollection-createNewDatabase"]') + .check(); + + cy.wrap($body) + .find('input[data-test="addCollection-newDatabaseId"]') + .type(dbId); + + cy.wrap($body) + .find('input[data-test="addCollectionPane-databaseSharedThroughput"]') + .check(); + + cy.wrap($body) + .find('input[data-test="addCollection-collectionId"]') + .type(collectionId); + + cy.wrap($body) + .find('input[data-test="databaseThroughputValue"]') + .should("have.value", "400"); + + cy.wrap($body) + .find('input[data-test="addCollection-partitionKeyValue"]') + .type(sharedKey); + + cy.wrap($body) + .find('input[data-test="addCollection-createCollection"]') + .click(); + + cy.wait(10000); + + cy.wrap($body) + .find('div[data-test="resourceTreeId"]') + .should("exist") + .find('div[class="treeComponent dataResourceTree"]') + .should("contain", dbId) + .click() + .should("contain", collectionId); + }); + }); +}); diff --git a/cypress/integration/dataexplorer/MONGO/addCollectionAutopilot.spec.ts b/cypress/integration/dataexplorer/MONGO/addCollectionAutopilot.spec.ts new file mode 100644 index 000000000..af9f3fe61 --- /dev/null +++ b/cypress/integration/dataexplorer/MONGO/addCollectionAutopilot.spec.ts @@ -0,0 +1,96 @@ +// 1. Click on "New Container" on the command bar. +// 2. Pane with the title "Add Container" should appear on the right side of the screen +// 3. It includes an input box for the database Id. +// 4. It includes a checkbox called "Create now". +// 5. When the checkbox is marked, enter new database id. +// 3. Create a database WITH "Provision throughput" checked. +// 4. Enter minimum throughput value of 400. +// 5. Enter container id to the container id text box. +// 6. Enter partition key to the partition key text box. +// 7. Click "OK" to create a new container. +// 8. Verify the new container is created along with the database id and should appead in the Data Explorer list in the left side of the screen. + +const connectionString = require("../../../utilities/connectionString"); + +let crypt = require("crypto"); + +context("Mongo API Test", () => { + beforeEach(() => { + connectionString.loginUsingConnectionString(connectionString.constants.mongo); + }); + + it("Create a new collection in Mongo API - Autopilot", () => { + const dbId = `TestDatabase${crypt.randomBytes(8).toString("hex")}`; + const collectionId = `TestCollection${crypt.randomBytes(8).toString("hex")}`; + const sharedKey = `SharedKey${crypt.randomBytes(8).toString("hex")}`; + + cy.get("iframe").then($element => { + const $body = $element.contents().find("body"); + cy.wrap($body) + .find('div[class="commandBarContainer"]') + .should("be.visible") + .find('button[data-test="New Collection"]') + .should("be.visible") + .click(); + + cy.wrap($body) + .find('div[class="contextual-pane-in"]') + .should("be.visible") + .find('span[id="containerTitle"]'); + + cy.wrap($body) + .find('input[data-test="addCollection-createNewDatabase"]') + .check(); + + cy.wrap($body) + .find('input[data-test="addCollection-newDatabaseId"]') + .type(dbId); + + cy.wrap($body) + .find('input[data-test="addCollectionPane-databaseSharedThroughput"]') + .check(); + + cy.wrap($body) + .find('div[class="throughputModeContainer"]') + .should("be.visible") + .and(input => { + expect(input.get(0).textContent, "first item").contains("Autopilot (preview)"); + expect(input.get(1).textContent, "second item").contains("Manual"); + }); + + cy.wrap($body) + .find('input[id="newContainer-databaseThroughput-autoPilotRadio"]') + .check(); + + cy.wrap($body) + .find('select[name="autoPilotTiers"]') + // .eq(1).should('contain', '4,000 RU/s'); + // // .select('4,000 RU/s').should('have.value', '1'); + + .find('option[value="2"]') + .then($element => $element.get(1).setAttribute("selected", "selected")); + + cy.wrap($body) + .find('input[data-test="addCollection-collectionId"]') + .type(collectionId); + + cy.wrap($body) + .find('input[data-test="addCollection-partitionKeyValue"]') + .type(sharedKey); + + cy.wrap($body) + .find('input[data-test="addCollection-createCollection"]') + .click(); + + cy.wait(10000); + + cy.wrap($body) + .find('div[data-test="resourceTreeId"]') + .should("exist") + .find('div[class="treeComponent dataResourceTree"]') + .should("contain", dbId) + .click() + .should("contain", collectionId); + }); + }); +}); diff --git a/cypress/integration/dataexplorer/MONGO/addCollectionExistingDatabase.spec.ts b/cypress/integration/dataexplorer/MONGO/addCollectionExistingDatabase.spec.ts new file mode 100644 index 000000000..c012ef8b9 --- /dev/null +++ b/cypress/integration/dataexplorer/MONGO/addCollectionExistingDatabase.spec.ts @@ -0,0 +1,67 @@ +const connectionString = require("../../../utilities/connectionString"); + +let crypt = require("crypto"); + +context("Mongo API Test", () => { + beforeEach(() => { + connectionString.loginUsingConnectionString(connectionString.constants.mongo); + }); + + it("Create a new collection in existing database in Mongo API", () => { + const collectionId = `TestCollection${crypt.randomBytes(8).toString("hex")}`; + const sharedKey = `SharedKey${crypt.randomBytes(8).toString("hex")}`; + + cy.get("iframe").then($element => { + const $body = $element.contents().find("body"); + + cy.wrap($body) + .find('span[class="nodeLabel"]') + .should("be.visible") + .then($span => { + const dbId1 = $span.text(); + cy.log("DBBB", dbId1); + + cy.wrap($body) + .find('div[class="commandBarContainer"]') + .should("be.visible") + .find('button[data-test="New Collection"]') + .should("be.visible") + .click(); + + cy.wrap($body) + .find('div[class="contextual-pane-in"]') + .should("be.visible") + .find('span[id="containerTitle"]'); + + cy.wrap($body) + .find('input[data-test="addCollection-existingDatabase"]') + .check(); + + cy.wrap($body) + .find('input[data-test="addCollection-existingDatabase"]') + .type(dbId1); + + cy.wrap($body) + .find('input[data-test="addCollection-collectionId"]') + .type(collectionId); + + cy.wrap($body) + .find('input[data-test="addCollection-partitionKeyValue"]') + .type(sharedKey); + + cy.wrap($body) + .find('input[data-test="addCollection-createCollection"]') + .click(); + + cy.wait(10000); + + cy.wrap($body) + .find('div[data-test="resourceTreeId"]') + .should("exist") + .find('div[class="treeComponent dataResourceTree"]') + .click() + .should("contain", collectionId); + }); + }); + }); +}); diff --git a/cypress/integration/dataexplorer/MONGO/provisionDatabaseThroughput.spec.ts b/cypress/integration/dataexplorer/MONGO/provisionDatabaseThroughput.spec.ts new file mode 100644 index 000000000..b6c40f183 --- /dev/null +++ b/cypress/integration/dataexplorer/MONGO/provisionDatabaseThroughput.spec.ts @@ -0,0 +1,203 @@ +const connectionString = require("../../../utilities/connectionString"); + +let crypt = require("crypto"); + +context("Mongo API Test", () => { + beforeEach(() => { + connectionString.loginUsingConnectionString(connectionString.constants.mongo); + }); + + it("Create a new collection in Mongo API - Provision database throughput", () => { + const dbId = `TestDatabase${crypt.randomBytes(8).toString("hex")}`; + const collectionId = `TestCollection${crypt.randomBytes(8).toString("hex")}`; + const sharedKey = `SharedKey${crypt.randomBytes(8).toString("hex")}`; + + cy.get("iframe").then($element => { + const $body = $element.contents().find("body"); + cy.wrap($body) + .find('div[class="commandBarContainer"]') + .should("be.visible") + .find('button[data-test="New Collection"]') + .should("be.visible") + .click(); + + cy.wrap($body) + .find('div[class="contextual-pane-in"]') + .should("be.visible") + .find('span[id="containerTitle"]'); + + cy.wrap($body) + .find(".createNewDatabaseOrUseExisting") + .should("have.length", 2) + .and(input => { + expect(input.get(0).textContent, "first item").contains("Create new"); + expect(input.get(1).textContent, "second item").contains("Use existing"); + }); + + cy.wrap($body) + .find('input[data-test="addCollection-createNewDatabase"]') + .check(); + + cy.wrap($body) + .find('input[data-test="addCollectionPane-databaseSharedThroughput"]') + .check(); + + cy.wrap($body) + .find('input[data-test="addCollection-newDatabaseId"]') + .type(dbId); + + cy.wrap($body) + .find('input[data-test="addCollectionPane-databaseSharedThroughput"]') + .check(); + + cy.wrap($body) + .find('input[data-test="databaseThroughputValue"]') + .should("have.value", "400"); + + cy.wrap($body) + .find('input[data-test="addCollection-collectionId"]') + .type(collectionId); + + cy.wrap($body) + .find('input[data-test="addCollection-partitionKeyValue"]') + .type(sharedKey); + + cy.wrap($body) + .find('input[data-test="addCollection-createCollection"]') + .click(); + + cy.wait(10000); + + cy.wrap($body) + .find('div[data-test="resourceTreeId"]') + .should("exist") + .find('div[class="treeComponent dataResourceTree"]') + .should("contain", dbId) + .click() + .should("contain", collectionId); + }); + }); + + it("Create a new collection - without provision database throughput", () => { + const dbId = `TestDatabase${crypt.randomBytes(8).toString("hex")}`; + const collectionId = `TestCollection${crypt.randomBytes(8).toString("hex")}`; + const collectionIdTitle = `Add Collection`; + const sharedKey = `SharedKey${crypt.randomBytes(8).toString("hex")}`; + + cy.get("iframe").then($element => { + const $body = $element.contents().find("body"); + cy.wrap($body) + .find('div[class="commandBarContainer"]') + .should("be.visible") + .find('button[data-test="New Collection"]') + .should("be.visible") + .click(); + + cy.wrap($body) + .find('div[class="contextual-pane-in"]') + .should("be.visible") + .find('span[id="containerTitle"]'); + + cy.wrap($body) + .find('input[data-test="addCollection-createNewDatabase"]') + .check(); + + cy.wrap($body) + .find('input[data-test="addCollection-newDatabaseId"]') + .type(dbId); + + cy.wrap($body) + .find('input[data-test="addCollectionPane-databaseSharedThroughput"]') + .uncheck(); + + cy.wrap($body) + .find('input[data-test="addCollection-collectionId"]') + .type(collectionId); + + cy.wrap($body) + .find('input[id="tab2"]') + .check({ force: true }); + + cy.wrap($body) + .find('input[data-test="addCollection-partitionKeyValue"]') + .type(sharedKey); + + cy.wrap($body) + .find('input[data-test="databaseThroughputValue"]') + .should("have.value", "400"); + + cy.wrap($body) + .find('input[data-test="addCollection-createCollection"]') + .click(); + + cy.wait(10000); + + cy.wrap($body) + .find('div[data-test="resourceTreeId"]') + .should("exist") + .find('div[class="treeComponent dataResourceTree"]') + .should("contain", dbId) + .click() + .should("contain", collectionId); + }); + }); + + it("Create a new collection - without provision database throughput Fixed Storage Capacity", () => { + const dbId = `TestDatabase${crypt.randomBytes(8).toString("hex")}`; + const collectionId = `TestCollection${crypt.randomBytes(8).toString("hex")}`; + const sharedKey = `SharedKey${crypt.randomBytes(8).toString("hex")}`; + + cy.get("iframe").then($element => { + const $body = $element.contents().find("body"); + cy.wrap($body) + .find('div[class="commandBarContainer"]') + .should("be.visible") + .find('button[data-test="New Collection"]') + .should("be.visible") + .click(); + + cy.wrap($body) + .find('div[class="contextual-pane-in"]') + .should("be.visible") + .find('span[id="containerTitle"]'); + + cy.wrap($body) + .find('input[data-test="addCollection-createNewDatabase"]') + .check(); + + cy.wrap($body) + .find('input[data-test="addCollection-newDatabaseId"]') + .type(dbId); + + cy.wrap($body) + .find('input[data-test="addCollectionPane-databaseSharedThroughput"]') + .uncheck(); + + cy.wrap($body) + .find('input[data-test="addCollection-collectionId"]') + .type(collectionId); + + cy.wrap($body) + .find('input[id="tab1"]') + .check({ force: true }); + + cy.wrap($body) + .find('input[data-test="databaseThroughputValue"]') + .should("have.value", "400"); + + cy.wrap($body) + .find('input[data-test="addCollection-createCollection"]') + .click(); + + cy.wait(10000); + + cy.wrap($body) + .find('div[data-test="resourceTreeId"]') + .should("exist") + .find('div[class="treeComponent dataResourceTree"]') + .should("contain", dbId) + .click() + .should("contain", collectionId); + }); + }); +}); diff --git a/cypress/integration/dataexplorer/SQL/addCollection.spec.ts b/cypress/integration/dataexplorer/SQL/addCollection.spec.ts new file mode 100644 index 000000000..6ac9965a7 --- /dev/null +++ b/cypress/integration/dataexplorer/SQL/addCollection.spec.ts @@ -0,0 +1,78 @@ +// 1. Click on "New Container" on the command bar. +// 2. Pane with the title "Add Container" should appear on the right side of the screen +// 3. It includes an input box for the database Id. +// 4. It includes a checkbox called "Create now". +// 5. When the checkbox is marked, enter new database id. +// 3. Create a database WITH "Provision throughput" checked. +// 4. Enter minimum throughput value of 400. +// 5. Enter container id to the container id text box. +// 6. Enter partition key to the partition key text box. +// 7. Click "OK" to create a new container. +// 8. Verify the new container is created along with the database id and should appead in the Data Explorer list in the left side of the screen. + +const connectionString = require("../../../utilities/connectionString"); + +let crypt = require("crypto"); + +context("SQL API Test", () => { + beforeEach(() => { + connectionString.loginUsingConnectionString(connectionString.constants.sql); + }); + + it("Create a new container in SQL API", () => { + const dbId = `TestDatabase${crypt.randomBytes(8).toString("hex")}`; + const collectionId = `TestCollection${crypt.randomBytes(8).toString("hex")}`; + const sharedKey = `SharedKey${crypt.randomBytes(8).toString("hex")}`; + + cy.get("iframe").then($element => { + const $body = $element.contents().find("body"); + cy.wrap($body) + .find('div[class="commandBarContainer"]') + .should("be.visible") + .find('button[data-test="New Container"]') + .should("be.visible") + .click(); + + cy.wrap($body) + .find('div[class="contextual-pane-in"]') + .should("be.visible") + .find('span[id="containerTitle"]'); + + cy.wrap($body) + .find('input[data-test="addCollection-createNewDatabase"]') + .check(); + + cy.wrap($body) + .find('input[data-test="addCollectionPane-databaseSharedThroughput"]') + .check(); + + cy.wrap($body) + .find('input[data-test="addCollection-newDatabaseId"]') + .type(dbId); + + cy.wrap($body) + .find('input[data-test="addCollection-collectionId"]') + .type(collectionId); + + cy.wrap($body) + .find('input[data-test="databaseThroughputValue"]') + .should("have.value", "400"); + + cy.wrap($body) + .find('input[data-test="addCollection-partitionKeyValue"]') + .type(sharedKey); + + cy.wrap($body) + .find('input[data-test="addCollection-createCollection"]') + .click(); + + cy.wait(10000); + + cy.wrap($body) + .find('div[data-test="resourceTreeId"]') + .should("exist") + .find('div[class="treeComponent dataResourceTree"]') + .should("contain", dbId); + }); + }); +}); diff --git a/cypress/integration/dataexplorer/TABLE/addCollection.spec.ts b/cypress/integration/dataexplorer/TABLE/addCollection.spec.ts new file mode 100644 index 000000000..4f65e0b2c --- /dev/null +++ b/cypress/integration/dataexplorer/TABLE/addCollection.spec.ts @@ -0,0 +1,60 @@ +// 1. Click on "New Container" on the command bar. +// 2. Pane with the title "Add Container" should appear on the right side of the screen +// 3. It includes an input box for the database Id. +// 4. It includes a checkbox called "Create now". +// 5. When the checkbox is marked, enter new database id. +// 3. Create a database WITH "Provision throughput" checked. +// 4. Enter minimum throughput value of 400. +// 5. Enter container id to the container id text box. +// 6. Enter partition key to the partition key text box. +// 7. Click "OK" to create a new container. +// 8. Verify the new container is created along with the database id and should appead in the Data Explorer list in the left side of the screen. + +const connectionString = require("../../../utilities/connectionString"); + +let crypt = require("crypto"); + +context("Table API Test", () => { + beforeEach(() => { + connectionString.loginUsingConnectionString(connectionString.constants.table); + }); + + it("Create a new table in Table API", () => { + const collectionId = `TestCollection${crypt.randomBytes(8).toString("hex")}`; + + cy.get("iframe").then($element => { + const $body = $element.contents().find("body"); + cy.wrap($body) + .find('div[class="commandBarContainer"]') + .should("be.visible") + .find('button[data-test="New Table"]') + .should("be.visible") + .click(); + + cy.wrap($body) + .find('div[class="contextual-pane-in"]') + .should("be.visible") + .find('span[id="containerTitle"]'); + + cy.wrap($body) + .find('input[data-test="addCollection-collectionId"]') + .type(collectionId); + + cy.wrap($body) + .find('input[data-test="databaseThroughputValue"]') + .should("have.value", "400"); + + cy.wrap($body) + .find('input[data-test="addCollection-createCollection"]') + .click(); + + cy.wait(10000); + + cy.wrap($body) + .find('div[data-test="resourceTreeId"]') + .should("exist") + .find('div[class="treeComponent dataResourceTree"]') + .should("contain", collectionId); + }); + }); +}); diff --git a/cypress/integration/dataexplorer/ci-tests/addCollectionPane.spec.ts b/cypress/integration/dataexplorer/ci-tests/addCollectionPane.spec.ts new file mode 100644 index 000000000..aa13709ea --- /dev/null +++ b/cypress/integration/dataexplorer/ci-tests/addCollectionPane.spec.ts @@ -0,0 +1,55 @@ +// 1. Click on "New Container" on the command bar. +// 2. Pane with the title "Add Container" should appear on the right side of the screen +// 3. It includes an input box for the database Id. +// 4. It includes a checkbox called "Create now". +// 5. When the checkbox is marked, enter new database id. +// 3. Create a database WITH "Provision throughput" checked. +// 4. Enter minimum throughput value of 400. +// 5. Enter container id to the container id text box. +// 6. Enter partition key to the partition key text box. +// 7. Click "OK" to create a new container. +// 8. Verify the new container is created along with the database id and should appead in the Data Explorer list in the left side of the screen. + +let crypt = require("crypto"); + +context("Emulator - createDatabase", () => { + beforeEach(() => { + cy.visit("http://localhost:1234/explorer.html"); + }); + + const dbId = `TestDatabase${crypt.randomBytes(8).toString("hex")}`; + const collectionId = `TestCollection${crypt.randomBytes(8).toString("hex")}`; + const collectionIdTitle = `Add Collection`; + const partitionKey = `PartitionKey${crypt.randomBytes(8).toString("hex")}`; + + it("Create a new collection", () => { + cy.contains("New Container").click(); + + // cy.contains(collectionIdTitle); + + cy.get(".createNewDatabaseOrUseExisting") + .should("have.length", 2) + .and(input => { + expect(input.get(0).textContent, "first item").contains("Create new"); + expect(input.get(1).textContent, "second item").contains("Use existing"); + }); + + cy.get('input[data-test="addCollection-createNewDatabase"]').check(); + + cy.get('input[data-test="addCollection-newDatabaseId"]').type(dbId); + + cy.get('input[data-test="addCollection-collectionId"]').type(collectionId); + + cy.get('input[data-test="databaseThroughputValue"]').should("have.value", "400"); + + cy.get('input[data-test="addCollection-partitionKeyValue"]').type(partitionKey); + + cy.get('input[data-test="addCollection-createCollection"]').click(); + + cy.get('div[data-test="resourceTreeId"]').should("exist"); + + cy.get('div[data-test="resourceTree-collectionsTree"]').should("contain", dbId); + + cy.get('div[data-test="databaseList"]').should("contain", collectionId); + }); +}); diff --git a/cypress/integration/dataexplorer/ci-tests/createDatabase.spec.ts b/cypress/integration/dataexplorer/ci-tests/createDatabase.spec.ts new file mode 100644 index 000000000..58f90aff8 --- /dev/null +++ b/cypress/integration/dataexplorer/ci-tests/createDatabase.spec.ts @@ -0,0 +1,65 @@ +// 1. Click on "New Database" on the command bar +// 2. a Pane with the title "Add Database" should appear on the right side of the screen +// i. It includes an input box for the database Id. +// ii. It includes a checkbox called "Provision throughput". +// iii. Whe the checkbox is marked, a new input with a throughput control let's you customize RU at the database level +// 3. Create a database WITHOUT "Provision throughput" checked. +// 4. It should appear in the Data Explorer list. +// 5. Repeat steps 1-3 but create a database WITH "Provision throughput" with the default RU value. +// 6. It should appear in the Data Explorer list. +// 7. If expanded, it should have the list item called "Scale", that once clicked, it should show the "Scale" tab. +// 8. Inside that tab, a throughput control will let you change the RU value within the permited range. +// 9. If you change the value, it should enable the "Save" button. +// 10. Click "Save" and verify that the process completes without error. +// 11. Close the tab and reopen it and verify that the input contains the last saved value.% + +const crypto = require("crypto"); +const client = require("../../../utilities/cosmosClient"); +const randomString = crypto.randomBytes(2).toString("hex"); +const databaseId = `TestDB-${randomString}`; +const collectionId = `TestColl-${randomString}`; + +context("Emulator - Create database -> container -> item", () => { + beforeEach(async () => { + const { resources } = await client.databases.readAll().fetchAll(); + for (const database of resources) { + await client.database(database.id).delete(); + } + }); + + it("creates a new database", () => { + cy.visit("https://0.0.0.0:1234/explorer.html?platform=Emulator"); + cy.contains("New Container").click(); + cy.get("[data-test=addCollection-newDatabaseId]").click(); + cy.get("[data-test=addCollection-newDatabaseId]").type(databaseId); + cy.get("[data-test=addCollection-collectionId]").click(); + cy.get("[data-test=addCollection-collectionId]").type(collectionId); + cy.get("[data-test=addCollection-partitionKeyValue]").click(); + cy.get("[data-test=addCollection-partitionKeyValue]").type("/pk"); + cy.get('input[name="createCollection"]').click(); + cy.get(".dataResourceTree").should("contain", databaseId); + cy.get(".dataResourceTree") + .contains(databaseId) + .click(); + cy.get(".dataResourceTree").should("contain", collectionId); + cy.get(".dataResourceTree") + .contains(collectionId) + .click(); + cy.get(".dataResourceTree") + .contains("Items") + .click(); + cy.get(".dataResourceTree") + .contains("Items") + .click(); + cy.wait(1000); // React rendering inside KO causes some weird async rendering that makes this test flaky without waiting + cy.get(".commandBarContainer") + .contains("New Item") + .click(); + cy.wait(1000); // React rendering inside KO causes some weird async rendering that makes this test flaky without waiting + cy.get(".commandBarContainer") + .contains("Save") + .click(); + cy.wait(1000); // React rendering inside KO causes some weird async rendering that makes this test flaky without waiting + cy.get(".documentsGridHeaderContainer").should("contain", "replace_with_new_document_id"); + }); +}); diff --git a/cypress/integration/dataexplorer/ci-tests/deleteCollection.spec.ts b/cypress/integration/dataexplorer/ci-tests/deleteCollection.spec.ts new file mode 100644 index 000000000..a5516a551 --- /dev/null +++ b/cypress/integration/dataexplorer/ci-tests/deleteCollection.spec.ts @@ -0,0 +1,46 @@ +// 1. Click last database in the resource tree +// 2. Click the last collection within the database +// 3. Select the context menu within the collection +// 4. Select "Delete Container" option in the dropdown +// 5. On Selection, Delete Container pane opens on the right side +// 6. Enter the same collection id that is to be deleted and click ok +// 7. Now, the resource tree refreshes, the deleted collection should not appear under the database + +let crypt = require("crypto"); + +context("Emulator - deleteCollection", () => { + beforeEach(() => { + cy.visit("http://localhost:1234/explorer.html"); + }); + + it("Delete a collection", () => { + cy.get(".databaseId") + .last() + .click(); + + cy.get(".collectionList") + .last() + .then($id => { + const collectionId = $id.text(); + + cy.get('span[data-test="collectionEllipsisMenu"]').should("exist"); + + cy.get('span[data-test="collectionEllipsisMenu"]') + .invoke("show") + .last() + .click(); + + cy.get('div[data-test="collectionContextMenu"]') + .contains("Delete Container") + .click({ force: true }); + + cy.get('input[data-test="confirmCollectionId"]').type(collectionId.trim()); + + cy.get('input[data-test="deleteCollection"]').click(); + + cy.get('div[data-test="databaseList"]').should("not.contain", collectionId); + + cy.get('div[data-test="databaseMenu"]').should("not.contain", collectionId); + }); + }); +}); diff --git a/cypress/integration/dataexplorer/ci-tests/deleteDatabase.spec.ts b/cypress/integration/dataexplorer/ci-tests/deleteDatabase.spec.ts new file mode 100644 index 000000000..152bc3aaf --- /dev/null +++ b/cypress/integration/dataexplorer/ci-tests/deleteDatabase.spec.ts @@ -0,0 +1,83 @@ +// 1. Click last database in the resource tree +// 2. Select the context menu within the database +// 4. Select "Delete Database" option in the dropdown +// 5. On Selection, Delete Database pane opens on the right side +// 6. Enter the same database id that is to be deleted and click ok +// 7. Now, the resource tree refreshes, the deleted database should not appear in the resource tree + +let crypt = require("crypto"); + +context("Emulator - deleteDatabase", () => { + beforeEach(() => { + const dbId = `TestDatabase${crypt.randomBytes(8).toString("hex")}`; + const collectionId = `TestCollection${crypt.randomBytes(8).toString("hex")}`; + let db_rid = ""; + const date = new Date().toUTCString(); + let authToken = ""; + cy.visit("http://localhost:1234/explorer.html"); + + // Creating auth token for collection creation + cy.request({ + method: "GET", + url: "https://localhost:8081/_explorer/authorization/post/dbs/", + headers: { + "x-ms-date": date, + authorization: "-" + } + }) + .then(response => { + authToken = response.body.Token; // Getting auth token for collection creation + return new Cypress.Promise((resolve, reject) => { + return resolve(); + }); + }) + .then(() => { + cy.request({ + method: "POST", + url: "https://localhost:8081/dbs", + headers: { + "x-ms-date": date, + authorization: authToken, + "x-ms-version": "2018-12-31" + }, + body: { + id: dbId + } + }).then(response => { + cy.log("Response", response); + db_rid = response.body._rid; + return new Cypress.Promise((resolve, reject) => { + cy.log("Rid", db_rid); + return resolve(); + }); + }); + }); + }); + + it("Delete a database", () => { + cy.get('span[data-test="refreshTree"]').click(); + + cy.get(".databaseId") + .last() + .then($id => { + const dbId = $id.text(); + + cy.get('span[data-test="databaseEllipsisMenu"]').should("exist"); + + cy.get('span[data-test="databaseEllipsisMenu"]') + .invoke("show") + .last() + .click(); + + cy.get('div[data-test="databaseContextMenu"]') + .contains("Delete Database") + .click({ force: true }); + + cy.get('input[data-test="confirmDatabaseId"]').type(dbId.trim()); + + cy.get('input[data-test="deleteDatabase"]').click(); + + cy.get('div[data-test="databaseList"]').should("not.contain", dbId); + }); + }); +}); diff --git a/cypress/integration/notebook/README.md b/cypress/integration/notebook/README.md new file mode 100644 index 000000000..23a2b85d4 --- /dev/null +++ b/cypress/integration/notebook/README.md @@ -0,0 +1,35 @@ +# Notebook end-to-end tests +This describes how to run the tests locally + +## Stand up a local notebook container instance: +Instructions on how to build and run the container [here](https://microsoft.sharepoint.com/teams/DocDB/_layouts/OneNote.aspx?id=%2Fteams%2FDocDB%2FSiteAssets%2FDocDB%20Team%20Notebook&wd=target%28Tools%20_%20SDK%2FPortal%2FDevelopment.one%7CF800BE8E-1E31-48FE-90D7-EF698EF88112%2FHow%20to%20build%20notebook%20service%7C4BAA153B-422C-41E2-B997-F3FCE02CD743%2F%29) + +## Run a local data explorer +Instructions are in [`DataExplorer/README.md`](https://msdata.visualstudio.com/CosmosDB/_git/cosmosdb-dataexplorer?path=%2FProduct%2FPortal%2FDataExplorer%2FREADME.md&_a=preview). + +Make sure you can run Data Explorer locally from the web browser. + +## Run cypress tests +1. Edit the URL for your DataExplorer in the `.spec.ts` file +2. Run the test: +```bash +cd DataExplorer/cypress +npm i + npm t -- --spec 'integration/notebook/newNotebook.spec.ts' +``` + +To run in Debug mode: +``` +npm run test:debug +``` +This opens Cypress UI + +## Troubleshooting +* The tests are recorded in the `videos` folder. +* Cypress does not support hover: workarounds [here](https://docs.cypress.io/api/commands/hover.html#Workarounds). + + +## References +* [Cypress API](https://docs.cypress.io/api/api/table-of-contents.html) +* [Cypress cookbook](https://docs.cypress.io/faq/questions/using-cypress-faq.html#How-do-I-get-an-element%E2%80%99s-text-contents) +* [Cypress best practices](https://docs.cypress.io/guides/references/best-practices.html#Selecting-Elements) \ No newline at end of file diff --git a/cypress/integration/notebook/newNotebook.spec.ts b/cypress/integration/notebook/newNotebook.spec.ts new file mode 100644 index 000000000..329ff801c --- /dev/null +++ b/cypress/integration/notebook/newNotebook.spec.ts @@ -0,0 +1,93 @@ +// THIS ADDS A NEW NOTEBOOK TO YOUR NOTEBOOKS +context("New Notebook smoke test", () => { + const timeout = 15000; // in ms + const explorerUrl = + "https://localhost:1234/explorer.html?feature.notebookserverurl=https%3A%2F%2Flocalhost%3A10001%2F12345%2Fnotebook&feature.notebookServerToken=token&feature.enablenotebooks=true"; + + /** + * Wait for UI to be ready + */ + const waitForReady = () => { + cy.get(".splashScreenContainer", { timeout }).should("be.visible"); + }; + + beforeEach(() => { + cy.visit(explorerUrl); + waitForReady(); + }); + + it("Create a new notebook and run some code", () => { + // Create new notebook + cy.contains("New Notebook").click(); + + // Check tab name + cy.get("li.tabList .tabNavText").should($span => { + const text = $span.text(); + expect(text).to.match(/^Untitled.*\.ipynb$/); + }); + + // Wait for python3 | idle status + cy.get('[data-test="notebookStatusBar"] [data-test="kernelStatus"]', { timeout }).should($p => { + const text = $p.text(); + expect(text).to.match(/^python3.*idle$/); + }); + + // Click on a cell + cy.get(".cell-container") + .as("cellContainer") + .click(); + + // Type in some code + cy.get("@cellContainer").type("2+4"); + + // Execute + cy.get('[data-test="Run"]') + .first() + .click(); + + // Verify results + cy.get("@cellContainer").within(() => { + cy.get("pre code span").should("contain", "6"); + }); + + // Restart kernel + cy.get('[data-test="Run"] button') + .eq(-1) + .click(); + cy.get("li") + .contains("Restart Kernel") + .click(); + + // Wait for python3 | restarting status + cy.get('[data-test="notebookStatusBar"] [data-test="kernelStatus"]', { timeout }).should($p => { + const text = $p.text(); + expect(text).to.match(/^python3.*restarting$/); + }); + + // Wait for python3 | idle status + cy.get('[data-test="notebookStatusBar"] [data-test="kernelStatus"]', { timeout }).should($p => { + const text = $p.text(); + expect(text).to.match(/^python3.*idle$/); + }); + + // Click on a cell + cy.get(".cell-container") + .as("cellContainer") + .find(".input") + .as("codeInput") + .click(); + + // Type in some code + cy.get("@codeInput").type("{backspace}{backspace}{backspace}4+5"); + + // Execute + cy.get('[data-test="Run"]') + .first() + .click(); + + // Verify results + cy.get("@cellContainer").within(() => { + cy.get("pre code span").should("contain", "9"); + }); + }); +}); diff --git a/cypress/integration/notebook/resourceTree.spec.ts b/cypress/integration/notebook/resourceTree.spec.ts new file mode 100644 index 000000000..46af2d23e --- /dev/null +++ b/cypress/integration/notebook/resourceTree.spec.ts @@ -0,0 +1,172 @@ +context("Resource tree notebook file manipulation", () => { + const timeout = 15000; // in ms + const explorerUrl = + "https://localhost:1234/explorer.html?feature.notebookserverurl=https%3A%2F%2Flocalhost%3A10001%2F12345%2Fnotebook&feature.notebookServerToken=token&feature.enablenotebooks=true"; + + /** + * Wait for UI to be ready + */ + const waitForReady = () => { + cy.get(".splashScreenContainer", { timeout }).should("be.visible"); + }; + + const clickContextMenuAndSelectOption = (nodeLabel, option) => { + cy.get(`.treeNodeHeader[data-test="${nodeLabel}"]`) + .find("button.treeMenuEllipsis") + .click(); + cy.get('[data-test="treeComponentMenuItemContainer"]') + .contains(option) + .click(); + }; + + const createFolder = folder => { + clickContextMenuAndSelectOption("My Notebooks/", "New Directory"); + + cy.get("#stringInputPane").within(() => { + cy.get('input[name="collectionIdConfirmation"]').type(folder); + cy.get("form").submit(); + }); + }; + + const deleteItem = nodeName => { + clickContextMenuAndSelectOption(`${nodeName}`, "Delete"); + cy.get(".ms-Dialog-main") + .contains("Delete") + .click(); + }; + + beforeEach(() => { + cy.visit(explorerUrl); + waitForReady(); + }); + + it("Create and remove a directory", () => { + const folder = "e2etest_folder1"; + createFolder(folder); + cy.get(`.treeNodeHeader[data-test="${folder}/"]`).should("exist"); + deleteItem(`${folder}/`); + cy.get(`.treeNodeHeader[data-test="${folder}/"]`).should("not.exist"); + }); + + it("Create and rename a directory", () => { + const folder = "e2etest_folder2"; + const renamedFolder = "e2etest_folder2_renamed"; + createFolder(folder); + + // Rename + clickContextMenuAndSelectOption(`${folder}/`, "Rename"); + cy.get("#stringInputPane").within(() => { + cy.get('input[name="collectionIdConfirmation"]') + .clear() + .type(renamedFolder); + cy.get("form").submit(); + }); + cy.get(`.treeNodeHeader[data-test="${renamedFolder}/"]`).should("exist"); + cy.get(`.treeNodeHeader[data-test="${folder}/"]`).should("not.exist"); + + deleteItem(`${renamedFolder}/`); + cy.get(`.treeNodeHeader[data-test="${renamedFolder}/"]`).should("not.exist"); + }); + + it("Create a notebook inside a directory", () => { + const folder = "e2etest_folder3"; + const newNotebookName = "Untitled.ipynb"; + createFolder(folder); + clickContextMenuAndSelectOption(`${folder}/`, "New Notebook"); + + // Verify tab is open + cy.get(".tabList") + .contains(newNotebookName) + .should("exist"); + + // Close tab + cy.get(`.tabList[title="notebooks/${folder}/${newNotebookName}"]`) + .find(".cancelButton") + .click(); + // When running from command line, closing the tab is too fast + cy.get("body").then($body => { + if ($body.find(".ms-Dialog-main").length) { + // For some reason, this does not work + // cy.get(".ms-Dialog-main").contains("Close").click(); + cy.get(".ms-Dialog-main .ms-Button--primary").click(); + } + }); + + // Expand folder node + cy.get(`.treeNodeHeader[data-test="${folder}/"]`).click(); + cy.get(`.nodeChildren[data-test="${folder}/"] .treeNodeHeader[data-test="${newNotebookName}"]`).should("exist"); + + // Delete notebook + cy.get(`.nodeChildren[data-test="${folder}/"] .treeNodeHeader[data-test="${newNotebookName}"]`) + .find("button.treeMenuEllipsis") + .click(); + cy.get('[data-test="treeComponentMenuItemContainer"]') + .contains("Delete") + .click(); + + // Confirm + cy.get(".ms-Dialog-main") + .contains("Delete") + .click(); + cy.get(`.nodeChildren[data-test="${folder}/"] .treeNodeHeader[data-test="${newNotebookName}"]`).should("not.exist"); + + deleteItem(`${folder}/`); + }); + + it("Create and rename a notebook inside a directory", () => { + const folder = "e2etest_folder4"; + const newNotebookName = "Untitled.ipynb"; + const renamedNotebookName = "mynotebook.ipynb"; + createFolder(folder); + clickContextMenuAndSelectOption(`${folder}/`, "New Notebook"); + + // Close tab + cy.get(`.tabList[title="notebooks/${folder}/${newNotebookName}"]`) + .find(".cancelButton") + .click(); + cy.get("body").then($body => { + if ($body.find(".ms-Dialog-main").length) { + // For some reason, this does not work + // cy.get(".ms-Dialog-main").contains("Close").click(); + cy.get(".ms-Dialog-main .ms-Button--primary").click(); + } + }); + + // Expand folder node + cy.get(`.treeNodeHeader[data-test="${folder}/"]`).click(); + cy.get(`.nodeChildren[data-test="${folder}/"] .treeNodeHeader[data-test="${newNotebookName}"]`).should("exist"); + + // Rename notebook + cy.get(`.nodeChildren[data-test="${folder}/"] .treeNodeHeader[data-test="${newNotebookName}"]`) + .find("button.treeMenuEllipsis") + .click(); + cy.get('[data-test="treeComponentMenuItemContainer"]') + .contains("Rename") + .click(); + + cy.get("#stringInputPane").within(() => { + cy.get('input[name="collectionIdConfirmation"]') + .clear() + .type(renamedNotebookName); + cy.get("form").submit(); + }); + cy.get(`.nodeChildren[data-test="${folder}/"] .treeNodeHeader[data-test="${newNotebookName}"]`).should("not.exist"); + cy.get(`.nodeChildren[data-test="${folder}/"] .treeNodeHeader[data-test="${renamedNotebookName}"]`).should("exist"); + + // Delete notebook + cy.get(`.nodeChildren[data-test="${folder}/"] .treeNodeHeader[data-test="${renamedNotebookName}"]`) + .find("button.treeMenuEllipsis") + .click(); + cy.get('[data-test="treeComponentMenuItemContainer"]') + .contains("Delete") + .click(); + + // Confirm + cy.get(".ms-Dialog-main") + .contains("Delete") + .click(); + // Give it time to settle + cy.wait(1000); + deleteItem(`${folder}/`); + }); +}); diff --git a/cypress/package-lock.json b/cypress/package-lock.json new file mode 100644 index 000000000..5398ee8d5 --- /dev/null +++ b/cypress/package-lock.json @@ -0,0 +1,3148 @@ +{ + "name": "cosmos-explorer-cypress", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@cypress/listr-verbose-renderer": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@cypress/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz", + "integrity": "sha1-p3SS9LEdzHxEajSz4ochr9M8ZCo=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "cli-cursor": "^1.0.2", + "date-fns": "^1.27.2", + "figures": "^1.7.0" + }, + "dependencies": { + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "@cypress/request": { + "version": "2.88.5", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.5.tgz", + "integrity": "sha512-TzEC1XMi1hJkywWpRfD2clreTa/Z+lOrXDCxxBTBPEcY5azdPi56A6Xw+O4tWJnaJH3iIE7G5aDXZC6JgRZLcA==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "@cypress/xvfb": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", + "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "lodash.once": "^4.1.1" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "@hapi/address": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@hapi/address/-/address-4.0.1.tgz", + "integrity": "sha512-0oEP5UiyV4f3d6cBL8F3Z5S7iWSX39Knnl0lY8i+6gfmmIBj44JCBNtcMgwyS+5v7j3VYavNay0NFHDS+UGQcw==", + "dev": true, + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@hapi/formula": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@hapi/formula/-/formula-2.0.0.tgz", + "integrity": "sha512-V87P8fv7PI0LH7LiVi8Lkf3x+KCO7pQozXRssAHNXXL9L1K+uyu4XypLXwxqVDKgyQai6qj3/KteNlrqDx4W5A==", + "dev": true + }, + "@hapi/hoek": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.0.4.tgz", + "integrity": "sha512-EwaJS7RjoXUZ2cXXKZZxZqieGtc7RbvQhUy8FwDoMQtxWVi14tFjeFCYPZAM1mBCpOpiBpyaZbb9NeHc7eGKgw==", + "dev": true + }, + "@hapi/joi": { + "version": "17.1.1", + "resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-17.1.1.tgz", + "integrity": "sha512-p4DKeZAoeZW4g3u7ZeRo+vCDuSDgSvtsB/NpfjXEHTUjSeINAi/RrVOWiVQ1isaoLzMvFEhe8n5065mQq1AdQg==", + "dev": true, + "requires": { + "@hapi/address": "^4.0.1", + "@hapi/formula": "^2.0.0", + "@hapi/hoek": "^9.0.0", + "@hapi/pinpoint": "^2.0.0", + "@hapi/topo": "^5.0.0" + } + }, + "@hapi/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@hapi/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-vzXR5MY7n4XeIvLpfl3HtE3coZYO4raKXW766R6DZw/6aLqR26iuZ109K7a0NtF2Db0jxqh7xz2AxkUwpUFybw==", + "dev": true + }, + "@hapi/topo": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.0.0.tgz", + "integrity": "sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw==", + "dev": true, + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@microsoft/applicationinsights-analytics-js": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-analytics-js/-/applicationinsights-analytics-js-2.5.2.tgz", + "integrity": "sha512-Y/lG/7NkZtRJN4s5NWD5W8sulx8aYJ9mO7Q6kJRNVyvNvj3Le3b4EL57H5FIPjBkn/rRRZOSu9kCMc/S3UnHKA==", + "requires": { + "@microsoft/applicationinsights-common": "2.5.2", + "@microsoft/applicationinsights-core-js": "2.5.2", + "@microsoft/dynamicproto-js": "^0.5.1", + "tslib": "1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "@microsoft/applicationinsights-channel-js": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-2.5.2.tgz", + "integrity": "sha512-j+/2Cuht5yVMeaJ4XGc+itpLTMtsC3AMjIVrIbmnMo/QZxuHElA2DkqWgx+3XPDcWSZ562NNqrU2jxFsU9bnBQ==", + "requires": { + "@microsoft/applicationinsights-common": "2.5.2", + "@microsoft/applicationinsights-core-js": "2.5.2", + "tslib": "1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "@microsoft/applicationinsights-common": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-common/-/applicationinsights-common-2.5.2.tgz", + "integrity": "sha512-92hFZSO/QJ9+hfwfn9z9ZHfOZrQhUG46Y1uQL0yC5jYoYbV5o80SH3ZGMEPnTFmkW3Hynlov0JY+HB9pNjZJ6w==", + "requires": { + "@microsoft/applicationinsights-core-js": "2.5.2", + "tslib": "1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "@microsoft/applicationinsights-core-js": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.5.2.tgz", + "integrity": "sha512-gWqrUXuwiRzerA2cNDngEak9OjWNZ+mDcQmRh1OIMJhIHc+DVnqFPURmlD0EDsZpEoHi8K3Rk0P6xef4TzVtVQ==", + "requires": { + "@microsoft/dynamicproto-js": "^0.5.1", + "tslib": "1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "@microsoft/applicationinsights-dependencies-js": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-dependencies-js/-/applicationinsights-dependencies-js-2.5.2.tgz", + "integrity": "sha512-P5ozKgZpbIZOwLBG00Fav3UwfCrKMI9jxo6VtZimaAtdEgAx3kSCmIrNNVuO2VREcCJY9rJYVpS+8ofLIcgeag==", + "requires": { + "@microsoft/applicationinsights-common": "2.5.2", + "@microsoft/applicationinsights-core-js": "2.5.2", + "@microsoft/dynamicproto-js": "^0.5.1", + "tslib": "1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "@microsoft/applicationinsights-properties-js": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-properties-js/-/applicationinsights-properties-js-2.5.2.tgz", + "integrity": "sha512-FnNenvQ8UCFFuECnzPGIm06CMW5azgFLYrvnFgo518vfJJc5lTsGjmTgunyOBNA+yb75BKkoKSL8gFY6YjQMng==", + "requires": { + "@microsoft/applicationinsights-common": "2.5.2", + "@microsoft/applicationinsights-core-js": "2.5.2", + "tslib": "1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "@microsoft/applicationinsights-web": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-web/-/applicationinsights-web-2.5.2.tgz", + "integrity": "sha512-EMwkdqL1X4t4vGx/j3XTrcu0z0twtdrfni4LsvVNFFKdhrQFhCbGGFbGik5AoUv4xjzKFM1LcatwUNHqlXSYMg==", + "requires": { + "@microsoft/applicationinsights-analytics-js": "2.5.2", + "@microsoft/applicationinsights-channel-js": "2.5.2", + "@microsoft/applicationinsights-common": "2.5.2", + "@microsoft/applicationinsights-core-js": "2.5.2", + "@microsoft/applicationinsights-dependencies-js": "2.5.2", + "@microsoft/applicationinsights-properties-js": "2.5.2", + "@microsoft/dynamicproto-js": "^0.5.1", + "tslib": "1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + } + } + }, + "@microsoft/dynamicproto-js": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-0.5.1.tgz", + "integrity": "sha512-Umt5dUMnycNOFMdu0yZUAtFRVH2I31IjBKivEw3ancVE09rACrHsUVqJnPxYjTFH28QxHQKg/PBv3sPS1a748A==" + }, + "@samverschueren/stream-to-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", + "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", + "dev": true, + "requires": { + "any-observable": "^0.3.0" + } + }, + "@types/blob-util": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@types/blob-util/-/blob-util-1.3.3.tgz", + "integrity": "sha512-4ahcL/QDnpjWA2Qs16ZMQif7HjGP2cw3AGjHabybjw7Vm1EKu+cfQN1D78BaZbS1WJNa1opSMF5HNMztx7lR0w==", + "dev": true + }, + "@types/bluebird": { + "version": "3.5.29", + "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.29.tgz", + "integrity": "sha512-kmVtnxTuUuhCET669irqQmPAez4KFnFVKvpleVRyfC3g+SHD1hIkFZcWLim9BVcwUBLO59o8VZE4yGCmTif8Yw==", + "dev": true + }, + "@types/chai": { + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.7.tgz", + "integrity": "sha512-luq8meHGYwvky0O7u0eQZdA7B4Wd9owUCqvbw2m3XCrCU8mplYOujMBbvyS547AxJkC+pGnd0Cm15eNxEUNU8g==", + "dev": true + }, + "@types/chai-jquery": { + "version": "1.1.40", + "resolved": "https://registry.npmjs.org/@types/chai-jquery/-/chai-jquery-1.1.40.tgz", + "integrity": "sha512-mCNEZ3GKP7T7kftKeIs7QmfZZQM7hslGSpYzKbOlR2a2HCFf9ph4nlMRA9UnuOETeOQYJVhJQK7MwGqNZVyUtQ==", + "dev": true, + "requires": { + "@types/chai": "*", + "@types/jquery": "*" + } + }, + "@types/jquery": { + "version": "3.3.31", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.3.31.tgz", + "integrity": "sha512-Lz4BAJihoFw5nRzKvg4nawXPzutkv7wmfQ5121avptaSIXlDNJCUuxZxX/G+9EVidZGuO0UBlk+YjKbwRKJigg==", + "dev": true, + "requires": { + "@types/sizzle": "*" + } + }, + "@types/lodash": { + "version": "4.14.149", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", + "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==", + "dev": true + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@types/mocha": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz", + "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==", + "dev": true + }, + "@types/sinon": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-7.5.1.tgz", + "integrity": "sha512-EZQUP3hSZQyTQRfiLqelC9NMWd1kqLcmQE0dMiklxBkgi84T+cHOhnKpgk4NnOWpGX863yE6+IaGnOXUNFqDnQ==", + "dev": true + }, + "@types/sinon-chai": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@types/sinon-chai/-/sinon-chai-3.2.3.tgz", + "integrity": "sha512-TOUFS6vqS0PVL1I8NGVSNcFaNJtFoyZPXZ5zur+qlhDfOmQECZZM4H4kKgca6O8L+QceX/ymODZASfUfn+y4yQ==", + "dev": true, + "requires": { + "@types/chai": "*", + "@types/sinon": "*" + } + }, + "@types/sizzle": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz", + "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==", + "dev": true + }, + "ajv": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", + "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "any-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", + "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", + "dev": true + }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "arch": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.1.1.tgz", + "integrity": "sha512-BLM56aPo9vLLFVa8+/+pJLnrZ7QGGTVHWsCwieAWT9o9K8UeGaQbzZbGoabWLOo2ksBCztoXdqBZBplqLDDCSg==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "async": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", + "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "binary-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "dev": true + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "cachedir": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", + "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA=", + "dev": true + }, + "chokidar": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", + "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" + } + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "^1.0.1" + } + }, + "cli-table3": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", + "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==", + "dev": true, + "requires": { + "colors": "^1.1.2", + "object-assign": "^4.1.0", + "string-width": "^2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "dev": true, + "requires": { + "slice-ansi": "0.0.4", + "string-width": "^1.0.1" + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + } + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "optional": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.0.tgz", + "integrity": "sha512-NIQrwvv9V39FHgGFm36+U9SMQzbiHvU79k+iADraJTpmrFFfx7Ds0IvDoAdZsDrknlkRk14OYoWXb57uTh7/sw==", + "dev": true + }, + "common-tags": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", + "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "cypress": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-4.5.0.tgz", + "integrity": "sha512-2A4g5FW5d2fHzq8HKUGAMVTnW6P8nlWYQALiCoGN4bqBLvgwhYM/oG9oKc2CS6LnvgHFiKivKzpm9sfk3uU3zQ==", + "dev": true, + "requires": { + "@cypress/listr-verbose-renderer": "0.4.1", + "@cypress/request": "2.88.5", + "@cypress/xvfb": "1.2.4", + "@types/blob-util": "1.3.3", + "@types/bluebird": "3.5.29", + "@types/chai": "4.2.7", + "@types/chai-jquery": "1.1.40", + "@types/jquery": "3.3.31", + "@types/lodash": "4.14.149", + "@types/minimatch": "3.0.3", + "@types/mocha": "5.2.7", + "@types/sinon": "7.5.1", + "@types/sinon-chai": "3.2.3", + "@types/sizzle": "2.3.2", + "arch": "2.1.1", + "bluebird": "3.7.2", + "cachedir": "2.3.0", + "chalk": "2.4.2", + "check-more-types": "2.24.0", + "cli-table3": "0.5.1", + "commander": "4.1.0", + "common-tags": "1.8.0", + "debug": "4.1.1", + "eventemitter2": "4.1.2", + "execa": "1.0.0", + "executable": "4.1.1", + "extract-zip": "1.7.0", + "fs-extra": "8.1.0", + "getos": "3.1.4", + "is-ci": "2.0.0", + "is-installed-globally": "0.1.0", + "lazy-ass": "1.6.0", + "listr": "0.14.3", + "lodash": "4.17.15", + "log-symbols": "3.0.0", + "minimist": "1.2.5", + "moment": "2.24.0", + "ospath": "1.2.2", + "pretty-bytes": "5.3.0", + "ramda": "0.26.1", + "request-progress": "3.0.0", + "supports-color": "7.1.0", + "tmp": "0.1.0", + "untildify": "4.0.0", + "url": "0.11.0", + "yauzl": "2.10.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + } + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", + "dev": true + }, + "dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "es-abstract": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "eventemitter2": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-4.1.2.tgz", + "integrity": "sha1-DhqEd6+CGm7zmVsxG/dMI6UkfxU=", + "dev": true + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "executable": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", + "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "dev": true, + "requires": { + "pify": "^2.2.0" + } + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extract-zip": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", + "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", + "dev": true, + "requires": { + "concat-stream": "^1.6.2", + "debug": "^2.6.9", + "mkdirp": "^0.5.4", + "yauzl": "^2.10.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "flat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", + "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", + "dev": true, + "requires": { + "is-buffer": "~2.0.3" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "dev": true, + "optional": true + }, + "fsu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fsu/-/fsu-1.1.1.tgz", + "integrity": "sha512-xQVsnjJ/5pQtcKh+KjUoZGzVWn4uNkchxTF6Lwjr4Gf7nQr8fmUfhKJ62zE77+xQg9xnxi5KUps7XGs+VC986A==", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "getos": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/getos/-/getos-3.1.4.tgz", + "integrity": "sha512-UORPzguEB/7UG5hqiZai8f0vQ7hzynMQyJLxStoQ8dPGAcmgsfXOPA4iE/fGtweHYkK+z4zc9V0g+CIFRf5HYw==", + "dev": true, + "requires": { + "async": "^3.1.0" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "dev": true, + "requires": { + "ini": "^1.3.4" + } + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-buffer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-installed-globally": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "dev": true, + "requires": { + "global-dirs": "^0.1.0", + "is-path-inside": "^1.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-observable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", + "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", + "dev": true, + "requires": { + "symbol-observable": "^1.1.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha1-eZllXoZGwX8In90YfRUNMyTVRRM=", + "dev": true + }, + "listr": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", + "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", + "dev": true, + "requires": { + "@samverschueren/stream-to-observable": "^0.3.0", + "is-observable": "^1.1.0", + "is-promise": "^2.1.0", + "is-stream": "^1.1.0", + "listr-silent-renderer": "^1.1.1", + "listr-update-renderer": "^0.5.0", + "listr-verbose-renderer": "^0.5.0", + "p-map": "^2.0.0", + "rxjs": "^6.3.3" + } + }, + "listr-silent-renderer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", + "dev": true + }, + "listr-update-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", + "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "cli-truncate": "^0.2.1", + "elegant-spinner": "^1.0.1", + "figures": "^1.7.0", + "indent-string": "^3.0.0", + "log-symbols": "^1.0.2", + "log-update": "^2.3.0", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "dev": true, + "requires": { + "chalk": "^1.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "listr-verbose-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", + "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "cli-cursor": "^2.1.0", + "date-fns": "^1.27.2", + "figures": "^2.0.0" + }, + "dependencies": { + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + } + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "lodash.isempty": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", + "integrity": "sha1-b4bL7di+TsmHvpqvM8loTbGzHn4=", + "dev": true + }, + "lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==", + "dev": true + }, + "lodash.isobject": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", + "integrity": "sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0=", + "dev": true + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", + "dev": true + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=", + "dev": true + }, + "log-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", + "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2" + } + }, + "log-update": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", + "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "cli-cursor": "^2.0.0", + "wrap-ansi": "^3.0.1" + }, + "dependencies": { + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + } + } + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "requires": { + "mime-db": "1.44.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "mocha": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.0.1.tgz", + "integrity": "sha512-9eWmWTdHLXh72rGrdZjNbG3aa1/3NRPpul1z0D979QpEnFdCG0Q5tv834N+94QEN2cysfV72YocQ3fn87s70fg==", + "dev": true, + "requires": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "chokidar": "3.3.0", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "2.2.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "ms": "2.1.1", + "node-environment-flags": "1.0.6", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.0", + "yargs-parser": "13.1.1", + "yargs-unparser": "1.6.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "mochawesome": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mochawesome/-/mochawesome-4.1.0.tgz", + "integrity": "sha512-U23K19mLqmuBqFyIBl7FVkcIuG/2JYStCj+91WmxK1/psLgHlWBEZsNe25U0x4t1Eqgu55aHv+0utLwzfhnupw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "diff": "^4.0.1", + "json-stringify-safe": "^5.0.1", + "lodash.isempty": "^4.4.0", + "lodash.isfunction": "^3.0.9", + "lodash.isobject": "^3.0.2", + "lodash.isstring": "^4.0.1", + "mochawesome-report-generator": "^4.0.0", + "strip-ansi": "^5.0.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "mochawesome-merge": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/mochawesome-merge/-/mochawesome-merge-4.0.1.tgz", + "integrity": "sha512-ABQm41lq2Gnyg616P7g5MYi3u2e2GhF+soqMVhP/hnGLAu68q0i+fNawLNb9wW9M73AiQ1ST+kr2XWuEMqb7iw==", + "dev": true, + "requires": { + "fs-extra": "^7.0.1", + "glob": "^7.1.6", + "uuid": "^3.3.2" + }, + "dependencies": { + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + } + } + }, + "mochawesome-report-generator": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mochawesome-report-generator/-/mochawesome-report-generator-4.1.0.tgz", + "integrity": "sha512-8diUnfzLqMPybIsq3aw3Zc4Npw9W2ZCx8/fMR0ShAXfDTtPH4t2mRykXEWBhsBA5+jM74mjWpwEqY6Pmz+pCsw==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "dateformat": "^3.0.2", + "fs-extra": "^7.0.0", + "fsu": "^1.0.2", + "lodash.isfunction": "^3.0.8", + "opener": "^1.4.2", + "prop-types": "^15.7.2", + "react": "^16.8.5", + "react-dom": "^16.8.5", + "tcomb": "^3.2.17", + "tcomb-validation": "^3.3.0", + "validator": "^10.11.0", + "yargs": "^13.2.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "moment": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node-environment-flags": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", + "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "opener": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz", + "integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==", + "dev": true + }, + "ospath": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", + "integrity": "sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", + "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "picomatch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz", + "integrity": "sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA==", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pretty-bytes": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.3.0.tgz", + "integrity": "sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "ramda": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz", + "integrity": "sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ==", + "dev": true + }, + "react": { + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.12.0.tgz", + "integrity": "sha512-fglqy3k5E+81pA8s+7K0/T3DBCF0ZDOher1elBFzF7O6arXJgzyu/FW+COxFvAWXJoJN9KIZbT2LXlukwphYTA==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + } + }, + "react-dom": { + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.12.0.tgz", + "integrity": "sha512-LMxFfAGrcS3kETtQaCkTKjMiifahaMySFDn71fZUNpPHZQEzmk/GiAeIT8JSOrHB23fnuCOMruL2a8NYlw+8Gw==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.18.0" + } + }, + "react-is": { + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz", + "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", + "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "dev": true, + "requires": { + "picomatch": "^2.0.4" + } + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "request-progress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", + "integrity": "sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4=", + "dev": true, + "requires": { + "throttleit": "^1.0.0" + } + }, + "request-promise-core": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz", + "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, + "request-promise-native": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz", + "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==", + "dev": true, + "requires": { + "request-promise-core": "1.1.3", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "rxjs": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz", + "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "scheduler": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.18.0.tgz", + "integrity": "sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string.prototype.trimleft": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + } + } + }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", + "dev": true + }, + "tcomb": { + "version": "3.2.29", + "resolved": "https://registry.npmjs.org/tcomb/-/tcomb-3.2.29.tgz", + "integrity": "sha512-di2Hd1DB2Zfw6StGv861JoAF5h/uQVu/QJp2g8KVbtfKnoHdBQl5M32YWq6mnSYBQ1vFFrns5B1haWJL7rKaOQ==", + "dev": true + }, + "tcomb-validation": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/tcomb-validation/-/tcomb-validation-3.4.1.tgz", + "integrity": "sha512-urVVMQOma4RXwiVCa2nM2eqrAomHROHvWPuj6UkDGz/eb5kcy0x6P0dVt6kzpUZtYMNoAqJLWmz1BPtxrtjtrA==", + "dev": true, + "requires": { + "tcomb": "^3.0.0" + } + }, + "throttleit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", + "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", + "dev": true + }, + "tmp": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz", + "integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==", + "dev": true, + "requires": { + "rimraf": "^2.6.3" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tslib": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.0.tgz", + "integrity": "sha512-BmndXUtiTn/VDDrJzQE7Mm22Ix3PxgLltW9bSNLoeCY31gnG2OPx0QqJnuc9oMIKioYrz487i6K9o4Pdn0j+Kg==", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typescript": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.3.tgz", + "integrity": "sha512-FFgHdPt4T/duxx6Ndf7hwgMZZjZpB+U0nMNGVCYPq0rEzWKjEDobm4J6yb3CS7naZ0yURFqdw9Gwc7UOh/P9oQ==", + "dev": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "validator": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", + "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "wait-on": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-4.0.2.tgz", + "integrity": "sha512-Qpmgm3Hw/sXm7xK68FBsYy5r+Uid94/QymwnEjn9GTpfiWTUVYm0bccivVwY/BXGYO2r+5Cd8S/DzrRZqHK/9w==", + "dev": true, + "requires": { + "@hapi/joi": "^17.1.1", + "lodash": "^4.17.15", + "minimist": "^1.2.5", + "request": "^2.88.2", + "request-promise-native": "^1.0.8", + "rxjs": "^6.5.5" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + } + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrap-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", + "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yargs-unparser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "dev": true, + "requires": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" + } + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + } + } +} diff --git a/cypress/package.json b/cypress/package.json new file mode 100644 index 000000000..ee6097c02 --- /dev/null +++ b/cypress/package.json @@ -0,0 +1,23 @@ +{ + "name": "cosmos-explorer-cypress", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "cypress run", + "test:ci": "wait-on -t 240000 -i 5000 -v https-get://0.0.0.0:1234/ https-get://0.0.0.0:8081/_explorer/index.html && cypress run --browser chrome --headless", + "test:debug": "cypress open" + }, + "devDependencies": { + "cypress": "^4.5.0", + "mocha": "^7.0.1", + "mochawesome": "^4.1.0", + "mochawesome-merge": "^4.0.1", + "mochawesome-report-generator": "^4.1.0", + "typescript": "3.4.3", + "wait-on": "^4.0.2" + }, + "dependencies": { + "@microsoft/applicationinsights-web": "^2.5.2" + } +} diff --git a/cypress/support/index.js b/cypress/support/index.js new file mode 100644 index 000000000..55845109d --- /dev/null +++ b/cypress/support/index.js @@ -0,0 +1,23 @@ +let appInsightsLib = require("@microsoft/applicationinsights-web"); + +const appInsights = new appInsightsLib.ApplicationInsights({ + config: { + instrumentationKey: "fe61c39f-7d32-4488-a191-b13621965315" + /* ...Other Configuration Options... */ + } +}); + +appInsights.loadAppInsights(); + +Cypress.on("fail", (error, runnable) => { + // App Insights will record the fail tests for Create Collection + let message = JSON.stringify(runnable.title); + appInsights.trackTrace({ + message: `${message}`, + properties: { + passed: false, + error: error + } + }); + throw error; // throw error to have test still fail +}); \ No newline at end of file diff --git a/cypress/tsconfig.json b/cypress/tsconfig.json new file mode 100644 index 000000000..30cdfa6a6 --- /dev/null +++ b/cypress/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "strict": true, + "noEmit": true, + "module": "commonjs", + "target": "es5", + "lib": ["es5", "dom", "es6"], + "types": ["cypress", "node"] + }, + "include": ["**/*.ts", "**/*.spec.ts"] +} diff --git a/cypress/utilities/connectionString.js b/cypress/utilities/connectionString.js new file mode 100644 index 000000000..a823a74ee --- /dev/null +++ b/cypress/utilities/connectionString.js @@ -0,0 +1,56 @@ +module.exports = { + loginUsingConnectionString: function (api) { + + + const prodUrl = "https://cosmos.azure.com/"; + const timeout = 15000; + + cy.visit(prodUrl); + cy.get('iframe[id="explorerMenu"]').should("be.visible"); + + cy.get("iframe").then($element => { + const $body = $element.contents().find("body"); + + cy.wrap($body) + .find("#connectExplorer") + .should("exist") + .find("div[class='connectExplorer']") + .should("exist") + .find("p[class='welcomeText']") + .should("exist"); + + cy.wrap($body.find("div > p.switchConnectTypeText")) + .should("exist") + .last() + .click({ force: true }); + + const secret = Cypress.env('connectionString')[api]; + + cy.wrap($body) + .find("input[class='inputToken']") + .should("exist") + .type(secret, { + force: true + }); + + cy.wrap($body.find("input[value='Connect']"), { timeout }) + .first() + .click({ force: true }); + + cy.wait(15000); + + cy.wrap($body) + .find(".connectExplorer > p:nth-child(3)") + .should("be.visible"); + + }); + }, + constants:{ + sql: "sql", + mongo: "mongo", + table: "table", + graph: "graph", + cassandra: "cassandra" + } + +} \ No newline at end of file diff --git a/cypress/utilities/cosmosClient.js b/cypress/utilities/cosmosClient.js new file mode 100644 index 000000000..47b353f24 --- /dev/null +++ b/cypress/utilities/cosmosClient.js @@ -0,0 +1,6 @@ +const { CosmosClient } = require("@azure/cosmos"); + +module.exports = new CosmosClient({ + endpoint: "https://0.0.0.0:8081", + key: "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==" +}); diff --git a/externals/adal.js b/externals/adal.js new file mode 100644 index 000000000..e0cae17cb --- /dev/null +++ b/externals/adal.js @@ -0,0 +1,1963 @@ +//---------------------------------------------------------------------- +// AdalJS v1.0.17.1 +// @preserve Copyright (c) Microsoft Open Technologies, Inc. +// All Rights Reserved +// Apache License 2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//---------------------------------------------------------------------- + +/** + * This is a customized version of adal on top of version 1.0.17 which does not support multi tenant + * Customized version add tenantId to stored tokens so when tenant change, adal will refetch instead of read from sessionStorage + */ +var AuthenticationContext = (function () { + + 'use strict'; + + /** + * Configuration options for Authentication Context. + * @class config + * @property {string} tenant - Your target tenant. + * @property {string} clientId - Client ID assigned to your app by Azure Active Directory. + * @property {string} redirectUri - Endpoint at which you expect to receive tokens.Defaults to `window.location.href`. + * @property {string} instance - Azure Active Directory Instance.Defaults to `https://login.microsoftonline.com/`. + * @property {Array} endpoints - Collection of {Endpoint-ResourceId} used for automatically attaching tokens in webApi calls. + * @property {Boolean} popUp - Set this to true to enable login in a popup winodow instead of a full redirect.Defaults to `false`. + * @property {string} localLoginUrl - Set this to redirect the user to a custom login page. + * @property {function} displayCall - User defined function of handling the navigation to Azure AD authorization endpoint in case of login. Defaults to 'null'. + * @property {string} postLogoutRedirectUri - Redirects the user to postLogoutRedirectUri after logout. Defaults is 'redirectUri'. + * @property {string} cacheLocation - Sets browser storage to either 'localStorage' or sessionStorage'. Defaults to 'sessionStorage'. + * @property {Array.} anonymousEndpoints Array of keywords or URI's. Adal will not attach a token to outgoing requests that have these keywords or uri. Defaults to 'null'. + * @property {number} expireOffsetSeconds If the cached token is about to be expired in the expireOffsetSeconds (in seconds), Adal will renew the token instead of using the cached token. Defaults to 300 seconds. + * @property {string} correlationId Unique identifier used to map the request with the response. Defaults to RFC4122 version 4 guid (128 bits). + * @property {number} loadFrameTimeout The number of milliseconds of inactivity before a token renewal response from AAD should be considered timed out. + */ + + /** + * Creates a new AuthenticationContext object. + * @constructor + * @param {config} config Configuration options for AuthenticationContext + */ + + AuthenticationContext = function (config) { + /** + * Enum for request type + * @enum {string} + */ + this.REQUEST_TYPE = { + LOGIN: 'LOGIN', + RENEW_TOKEN: 'RENEW_TOKEN', + UNKNOWN: 'UNKNOWN' + }; + + this.RESPONSE_TYPE = { + ID_TOKEN_TOKEN: 'id_token token', + TOKEN: 'token' + }; + + /** + * Enum for storage constants + * @enum {string} + */ + this.CONSTANTS = { + ACCESS_TOKEN: 'access_token', + EXPIRES_IN: 'expires_in', + ID_TOKEN: 'id_token', + ERROR_DESCRIPTION: 'error_description', + SESSION_STATE: 'session_state', + ERROR: 'error', + STORAGE: { + TOKEN_KEYS: 'adal.token.keys', + ACCESS_TOKEN_KEY: 'adal.access.token.key', + EXPIRATION_KEY: 'adal.expiration.key', + STATE_LOGIN: 'adal.state.login', + STATE_RENEW: 'adal.state.renew', + NONCE_IDTOKEN: 'adal.nonce.idtoken', + SESSION_STATE: 'adal.session.state', + USERNAME: 'adal.username', + IDTOKEN: 'adal.idtoken', + ERROR: 'adal.error', + ERROR_DESCRIPTION: 'adal.error.description', + LOGIN_REQUEST: 'adal.login.request', + LOGIN_ERROR: 'adal.login.error', + RENEW_STATUS: 'adal.token.renew.status', + ANGULAR_LOGIN_REQUEST: 'adal.angular.login.request' + }, + RESOURCE_DELIMETER: '|', + CACHE_DELIMETER: '||', + LOADFRAME_TIMEOUT: 6000, + TOKEN_RENEW_STATUS_CANCELED: 'Canceled', + TOKEN_RENEW_STATUS_COMPLETED: 'Completed', + TOKEN_RENEW_STATUS_IN_PROGRESS: 'In Progress', + LOGGING_LEVEL: { + ERROR: 0, + WARN: 1, + INFO: 2, + VERBOSE: 3 + }, + LEVEL_STRING_MAP: { + 0: 'ERROR:', + 1: 'WARNING:', + 2: 'INFO:', + 3: 'VERBOSE:' + }, + POPUP_WIDTH: 483, + POPUP_HEIGHT: 600 + }; + + if (AuthenticationContext.prototype._singletonInstance) { + return AuthenticationContext.prototype._singletonInstance; + } + AuthenticationContext.prototype._singletonInstance = this; + + // public + this.instance = 'https://login.microsoftonline.com/'; + this.config = {}; + this.callback = null; + this.popUp = false; + this.isAngular = false; + + // private + this._user = null; + this._activeRenewals = {}; + this._loginInProgress = false; + this._acquireTokenInProgress = false; + this._renewStates = []; + this._callBackMappedToRenewStates = {}; + this._callBacksMappedToRenewStates = {}; + this._openedWindows = []; + this._requestType = this.REQUEST_TYPE.LOGIN; + window._adalInstance = this; + + // validate before constructor assignments + if (config.displayCall && typeof config.displayCall !== 'function') { + throw new Error('displayCall is not a function'); + } + + if (!config.clientId) { + throw new Error('clientId is required'); + } + + this.config = this._cloneConfig(config); + + if (this.config.navigateToLoginRequestUrl === undefined) + this.config.navigateToLoginRequestUrl = true; + + if (this.config.popUp) + this.popUp = true; + + if (this.config.callback && typeof this.config.callback === 'function') + this.callback = this.config.callback; + + if (this.config.instance) { + this.instance = this.config.instance; + } + + // App can request idtoken for itself using clientid as resource + if (!this.config.loginResource) { + this.config.loginResource = this.config.clientId; + } + + // redirect and logout_redirect are set to current location by default + if (!this.config.redirectUri) { + // strip off query parameters or hashes from the redirect uri as AAD does not allow those. + this.config.redirectUri = window.location.href.split("?")[0].split("#")[0]; + } + + if (!this.config.postLogoutRedirectUri) { + // strip off query parameters or hashes from the post logout redirect uri as AAD does not allow those. + this.config.postLogoutRedirectUri = window.location.href.split("?")[0].split("#")[0]; + } + + if (!this.config.anonymousEndpoints) { + this.config.anonymousEndpoints = []; + } + + if (this.config.isAngular) { + this.isAngular = this.config.isAngular; + } + + if (this.config.loadFrameTimeout) { + this.CONSTANTS.LOADFRAME_TIMEOUT = this.config.loadFrameTimeout; + } + }; + + if (typeof window !== 'undefined') { + window.Logging = { + piiLoggingEnabled: false, + level: 0, + log: function (message) { } + }; + } + + /** + * Initiates the login process by redirecting the user to Azure AD authorization endpoint. + */ + AuthenticationContext.prototype.login = function () { + if (this._loginInProgress) { + this.info("Login in progress"); + return; + } + + this._loginInProgress = true; + + // Token is not present and user needs to login + var expectedState = this._guid(); + this.config.state = expectedState; + this._idTokenNonce = this._guid(); + var loginStartPage = this._getItem(this.CONSTANTS.STORAGE.ANGULAR_LOGIN_REQUEST); + + if (!loginStartPage || loginStartPage === "") { + loginStartPage = window.location.href; + } + else { + this._saveItem(this.CONSTANTS.STORAGE.ANGULAR_LOGIN_REQUEST, "") + } + + this.verbose('Expected state: ' + expectedState + ' startPage:' + loginStartPage); + this._saveItem(this.CONSTANTS.STORAGE.LOGIN_REQUEST, loginStartPage); + this._saveItem(this.CONSTANTS.STORAGE.LOGIN_ERROR, ''); + this._saveItem(this.CONSTANTS.STORAGE.STATE_LOGIN, expectedState, true); + this._saveItem(this.CONSTANTS.STORAGE.NONCE_IDTOKEN, this._idTokenNonce, true); + this._saveItem(this.CONSTANTS.STORAGE.ERROR, ''); + this._saveItem(this.CONSTANTS.STORAGE.ERROR_DESCRIPTION, ''); + var urlNavigate = this._getNavigateUrl('id_token', null, null) + '&nonce=' + encodeURIComponent(this._idTokenNonce); + + if (this.config.displayCall) { + // User defined way of handling the navigation + this.config.displayCall(urlNavigate); + } + else if (this.popUp) { + this._saveItem(this.CONSTANTS.STORAGE.STATE_LOGIN, '');// so requestInfo does not match redirect case + this._renewStates.push(expectedState); + this.registerCallback(expectedState, this.config.clientId, this.callback, ''); + this._loginPopup(urlNavigate); + } + else { + this.promptUser(urlNavigate); + } + }; + + /** + * Configures popup window for login. + * @ignore + */ + AuthenticationContext.prototype._openPopup = function (urlNavigate, title, popUpWidth, popUpHeight) { + try { + /** + * adding winLeft and winTop to account for dual monitor + * using screenLeft and screenTop for IE8 and earlier + */ + var winLeft = window.screenLeft ? window.screenLeft : window.screenX; + var winTop = window.screenTop ? window.screenTop : window.screenY; + /** + * window.innerWidth displays browser window's height and width excluding toolbars + * using document.documentElement.clientWidth for IE8 and earlier + */ + var width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; + var height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; + var left = ((width / 2) - (popUpWidth / 2)) + winLeft; + var top = ((height / 2) - (popUpHeight / 2)) + winTop; + + var popupWindow = window.open(urlNavigate, title, 'width=' + popUpWidth + ', height=' + popUpHeight + ', top=' + top + ', left=' + left); + + if (popupWindow.focus) { + popupWindow.focus(); + } + + return popupWindow; + } catch (e) { + this.warn('Error opening popup, ' + e.message); + this._loginInProgress = false; + this._acquireTokenInProgress = false; + return null; + } + } + + AuthenticationContext.prototype._handlePopupError = function (loginCallback, resource, error, errorDesc, loginError) { + this.warn(errorDesc); + this._saveItem(this.CONSTANTS.STORAGE.ERROR, error); + this._saveItem(this.CONSTANTS.STORAGE.ERROR_DESCRIPTION, errorDesc); + this._saveItem(this.CONSTANTS.STORAGE.LOGIN_ERROR, loginError); + + if (resource && this._activeRenewals[resource]) { + this._activeRenewals[resource] = null; + } + + this._loginInProgress = false; + this._acquireTokenInProgress = false; + + if (loginCallback) { + loginCallback(errorDesc, null, error); + } + } + + /** + * After authorization, the user will be sent to your specified redirect_uri with the user's bearer token + * attached to the URI fragment as an id_token field. It closes popup window after redirection. + * @ignore + */ + AuthenticationContext.prototype._loginPopup = function (urlNavigate, resource, callback) { + var popupWindow = this._openPopup(urlNavigate, "login", this.CONSTANTS.POPUP_WIDTH, this.CONSTANTS.POPUP_HEIGHT); + var loginCallback = callback || this.callback; + + if (popupWindow == null) { + var error = 'Error opening popup'; + var errorDesc = 'Popup Window is null. This can happen if you are using IE'; + this._handlePopupError(loginCallback, resource, error, errorDesc, errorDesc); + return; + } + + this._openedWindows.push(popupWindow); + + if (this.config.redirectUri.indexOf('#') != -1) { + var registeredRedirectUri = this.config.redirectUri.split("#")[0]; + } + + else { + var registeredRedirectUri = this.config.redirectUri; + } + + var that = this; + + var pollTimer = window.setInterval(function () { + if (!popupWindow || popupWindow.closed || popupWindow.closed === undefined) { + var error = 'Popup Window closed'; + var errorDesc = 'Popup Window closed by UI action/ Popup Window handle destroyed due to cross zone navigation in IE/Edge' + + if (that.isAngular) { + that._broadcast('adal:popUpClosed', errorDesc + that.CONSTANTS.RESOURCE_DELIMETER + error); + } + + that._handlePopupError(loginCallback, resource, error, errorDesc, errorDesc); + window.clearInterval(pollTimer); + return; + } + try { + var popUpWindowLocation = popupWindow.location; + if (encodeURI(popUpWindowLocation.href).indexOf(encodeURI(registeredRedirectUri)) != -1) { + if (that.isAngular) { + that._broadcast('adal:popUpHashChanged', popUpWindowLocation.hash); + } + else { + that.handleWindowCallback(popUpWindowLocation.hash); + } + + window.clearInterval(pollTimer); + that._loginInProgress = false; + that._acquireTokenInProgress = false; + that.info("Closing popup window"); + that._openedWindows = []; + popupWindow.close(); + return; + } + } catch (e) { + } + }, 1); + }; + + AuthenticationContext.prototype._broadcast = function (eventName, data) { + // Custom Event is not supported in IE, below IIFE will polyfill the CustomEvent() constructor functionality in Internet Explorer 9 and higher + (function () { + + if (typeof window.CustomEvent === "function") { + return false; + } + + function CustomEvent(event, params) { + params = params || { bubbles: false, cancelable: false, detail: undefined }; + var evt = document.createEvent('CustomEvent'); + evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); + return evt; + } + + CustomEvent.prototype = window.Event.prototype; + window.CustomEvent = CustomEvent; + })(); + + var evt = new CustomEvent(eventName, { detail: data }); + window.dispatchEvent(evt); + }; + + AuthenticationContext.prototype.loginInProgress = function () { + return this._loginInProgress; + }; + + /** + * Checks for the resource in the cache. By default, cache location is Session Storage + * @ignore + * @returns {Boolean} 'true' if login is in progress, else returns 'false'. + */ + AuthenticationContext.prototype._hasResource = function (key) { + var keys = this._getItem(this.CONSTANTS.STORAGE.TOKEN_KEYS); + return keys && !this._isEmpty(keys) && (keys.indexOf(key + this.CONSTANTS.RESOURCE_DELIMETER) > -1); + }; + + /** + * Gets token for the specified resource from the cache. + * @param {string} resource A URI that identifies the resource for which the token is requested. + * @returns {string} token if if it exists and not expired, otherwise null. + */ + AuthenticationContext.prototype.getCachedToken = function (resource, tenantId) { + if (!this._hasResource(resource)) { + return null; + } + + var token = this._getItem(this.CONSTANTS.STORAGE.ACCESS_TOKEN_KEY + resource + tenantId); + var expiry = this._getItem(this.CONSTANTS.STORAGE.EXPIRATION_KEY + resource + tenantId); + + // If expiration is within offset, it will force renew + var offset = this.config.expireOffsetSeconds || 300; + + if (expiry && (expiry > this._now() + offset)) { + return token; + } else { + this._saveItem(this.CONSTANTS.STORAGE.ACCESS_TOKEN_KEY + resource + tenantId, ''); + this._saveItem(this.CONSTANTS.STORAGE.EXPIRATION_KEY + resource + tenantId, 0); + return null; + } + }; + + /** + * User information from idtoken. + * @class User + * @property {string} userName - username assigned from upn or email. + * @property {object} profile - properties parsed from idtoken. + */ + + /** + * If user object exists, returns it. Else creates a new user object by decoding id_token from the cache. + * @returns {User} user object + */ + AuthenticationContext.prototype.getCachedUser = function () { + if (this._user) { + return this._user; + } + + var idtoken = this._getItem(this.CONSTANTS.STORAGE.IDTOKEN); + this._user = this._createUser(idtoken); + return this._user; + }; + + /** + * Adds the passed callback to the array of callbacks for the specified resource and puts the array on the window object. + * @param {string} resource A URI that identifies the resource for which the token is requested. + * @param {string} expectedState A unique identifier (guid). + * @param {tokenCallback} callback - The callback provided by the caller. It will be called with token or error. + */ + AuthenticationContext.prototype.registerCallback = function (expectedState, resource, callback, tenantId) { + this._activeRenewals[resource + tenantId] = expectedState; + + if (!this._callBacksMappedToRenewStates[expectedState]) { + this._callBacksMappedToRenewStates[expectedState] = []; + } + + var self = this; + this._callBacksMappedToRenewStates[expectedState].push(callback); + + if (!this._callBackMappedToRenewStates[expectedState]) { + this._callBackMappedToRenewStates[expectedState] = function (errorDesc, token, error, tokenType) { + self._activeRenewals[resource + tenantId] = null; + + for (var i = 0; i < self._callBacksMappedToRenewStates[expectedState].length; ++i) { + try { + self._callBacksMappedToRenewStates[expectedState][i](errorDesc, token, error, tokenType); + } + catch (error) { + self.warn(error); + } + } + + self._callBacksMappedToRenewStates[expectedState] = null; + self._callBackMappedToRenewStates[expectedState] = null; + }; + } + }; + + // var errorResponse = {error:'', error_description:''}; + // var token = 'string token'; + // callback(errorResponse, token) + // with callback + /** + * Acquires access token with hidden iframe + * @ignore + */ + AuthenticationContext.prototype._renewToken = function (resource, tenantId, callback, responseType) { + // use iframe to try to renew token + // use given resource to create new authz url + this.info('renewToken is called for resource:' + resource); + var frameHandle = this._addAdalFrame('adalRenewFrame' + resource + tenantId); + var expectedState = this._guid() + '|' + resource + '|' + tenantId; + this.config.state = expectedState; + // renew happens in iframe, so it keeps javascript context + this._renewStates.push(expectedState); + this.verbose('Renew token Expected state: ' + expectedState); + // remove the existing prompt=... query parameter and add prompt=none + responseType = responseType || 'token'; + var urlNavigate = this._urlRemoveQueryStringParameter(this._getNavigateUrl(responseType, resource, tenantId), 'prompt'); + + if (responseType === this.RESPONSE_TYPE.ID_TOKEN_TOKEN) { + this._idTokenNonce = this._guid(); + this._saveItem(this.CONSTANTS.STORAGE.NONCE_IDTOKEN, this._idTokenNonce, true); + urlNavigate += '&nonce=' + encodeURIComponent(this._idTokenNonce); + } + + urlNavigate = urlNavigate + '&prompt=none'; + urlNavigate = this._addHintParameters(urlNavigate, !tenantId); + this.registerCallback(expectedState, resource, callback, tenantId); + this.verbosePii('Navigate to:' + urlNavigate); + frameHandle.src = 'about:blank'; + this._loadFrameTimeout(urlNavigate, 'adalRenewFrame' + resource + tenantId, resource, tenantId); + + }; + + /** + * Renews idtoken for app's own backend when resource is clientId and calls the callback with token/error + * @ignore + */ + AuthenticationContext.prototype._renewIdToken = function (callback, responseType) { + // use iframe to try to renew token + this.info('renewIdToken is called'); + var frameHandle = this._addAdalFrame('adalIdTokenFrame'); + var expectedState = this._guid() + '|' + this.config.clientId; + this._idTokenNonce = this._guid(); + this._saveItem(this.CONSTANTS.STORAGE.NONCE_IDTOKEN, this._idTokenNonce, true); + this.config.state = expectedState; + // renew happens in iframe, so it keeps javascript context + this._renewStates.push(expectedState); + this.verbose('Renew Idtoken Expected state: ' + expectedState); + // remove the existing prompt=... query parameter and add prompt=none + var resource = responseType === null || typeof (responseType) === "undefined" ? null : this.config.clientId; + var responseType = responseType || 'id_token'; + var urlNavigate = this._urlRemoveQueryStringParameter(this._getNavigateUrl(responseType, resource, null), 'prompt'); + urlNavigate = urlNavigate + '&prompt=none'; + urlNavigate = this._addHintParameters(urlNavigate, true); + urlNavigate += '&nonce=' + encodeURIComponent(this._idTokenNonce); + this.registerCallback(expectedState, this.config.clientId, callback, undefined); + this.verbosePii('Navigate to:' + urlNavigate); + frameHandle.src = 'about:blank'; + this._loadFrameTimeout(urlNavigate, 'adalIdTokenFrame', this.config.clientId, ''); + }; + + /** + * Checks if the authorization endpoint URL contains query string parameters + * @ignore + */ + AuthenticationContext.prototype._urlContainsQueryStringParameter = function (name, url) { + // regex to detect pattern of a ? or & followed by the name parameter and an equals character + var regex = new RegExp("[\\?&]" + name + "="); + return regex.test(url); + } + + /** + * Removes the query string parameter from the authorization endpoint URL if it exists + * @ignore + */ + AuthenticationContext.prototype._urlRemoveQueryStringParameter = function (url, name) { + // we remove &name=value, name=value& and name=value + // &name=value + var regex = new RegExp('(\\&' + name + '=)[^\&]+'); + url = url.replace(regex, ''); + // name=value& + regex = new RegExp('(' + name + '=)[^\&]+&'); + url = url.replace(regex, ''); + // name=value + regex = new RegExp('(' + name + '=)[^\&]+'); + url = url.replace(regex, ''); + return url; + } + + // Calling _loadFrame but with a timeout to signal failure in loadframeStatus. Callbacks are left + // registered when network errors occur and subsequent token requests for same resource are registered to the pending request + /** + * @ignore + */ + AuthenticationContext.prototype._loadFrameTimeout = function (urlNavigation, frameName, resource, tenantId) { + //set iframe session to pending + this.verbose('Set loading state to pending for: ' + resource + tenantId); + this._saveItem(this.CONSTANTS.STORAGE.RENEW_STATUS + resource + tenantId, this.CONSTANTS.TOKEN_RENEW_STATUS_IN_PROGRESS); + this._loadFrame(urlNavigation, frameName); + var self = this; + + setTimeout(function () { + if (self._getItem(self.CONSTANTS.STORAGE.RENEW_STATUS + resource + tenantId) === self.CONSTANTS.TOKEN_RENEW_STATUS_IN_PROGRESS) { + // fail the iframe session if it's in pending state + self.verbose('Loading frame has timed out after: ' + (self.CONSTANTS.LOADFRAME_TIMEOUT / 1000) + ' seconds for resource ' + resource); + var expectedState = self._activeRenewals[resource + tenantId]; + + if (expectedState && self._callBackMappedToRenewStates[expectedState]) { + self._callBackMappedToRenewStates[expectedState]('Token renewal operation failed due to timeout', null, 'Token Renewal Failed'); + } + + self._saveItem(self.CONSTANTS.STORAGE.RENEW_STATUS + resource + tenantId, self.CONSTANTS.TOKEN_RENEW_STATUS_CANCELED); + } + }, self.CONSTANTS.LOADFRAME_TIMEOUT); + } + + /** + * Loads iframe with authorization endpoint URL + * @ignore + */ + AuthenticationContext.prototype._loadFrame = function (urlNavigate, frameName) { + // This trick overcomes iframe navigation in IE + // IE does not load the page consistently in iframe + var self = this; + self.info('LoadFrame: ' + frameName); + var frameCheck = frameName; + setTimeout(function () { + var frameHandle = self._addAdalFrame(frameCheck); + + if (frameHandle.src === '' || frameHandle.src === 'about:blank') { + frameHandle.src = urlNavigate; + self._loadFrame(urlNavigate, frameCheck); + } + + }, 500); + }; + + /** + * @callback tokenCallback + * @param {string} error_description error description returned from AAD if token request fails. + * @param {string} token token returned from AAD if token request is successful. + * @param {string} error error message returned from AAD if token request fails. + */ + + /** + * Acquires token from the cache if it is not expired. Otherwise sends request to AAD to obtain a new token. + * @param {string} resource ResourceUri identifying the target resource + * @param {tokenCallback} callback - The callback provided by the caller. It will be called with token or error. + */ + AuthenticationContext.prototype.acquireToken = function (resource, tenantId, callback) { + if (this._isEmpty(resource)) { + this.warn('resource is required'); + callback('resource is required', null, 'resource is required'); + return; + } + + var token = this.getCachedToken(resource, tenantId); + + if (token) { + this.info('Token is already in cache for resource:' + resource); + callback(null, token, null); + return; + } + + if (!this._user && !(this.config.extraQueryParameter && this.config.extraQueryParameter.indexOf('login_hint') !== -1)) { + this.warn('User login is required'); + callback('User login is required', null, 'login required'); + return; + } + + // renew attempt with iframe + // Already renewing for this resource, callback when we get the token. + if (this._activeRenewals[resource + tenantId]) { + // Active renewals contains the state for each renewal. + this.registerCallback(this._activeRenewals[resource + tenantId], resource, callback, tenantId); + } + else { + this._requestType = this.REQUEST_TYPE.RENEW_TOKEN; + if (resource === this.config.clientId && !tenantId) { + // App uses idtoken to send to api endpoints + // Default resource is tracked as clientid to store this token + if (this._user) { + this.verbose('renewing idtoken'); + this._renewIdToken(callback); + } + else { + this.verbose('renewing idtoken and access_token'); + this._renewIdToken(callback, this.RESPONSE_TYPE.ID_TOKEN_TOKEN); + } + } else { + if (this._user) { + this.verbose('renewing access_token'); + this._renewToken(resource, tenantId, callback); + } + else { + this.verbose('renewing idtoken and access_token'); + this._renewToken(resource, tenantId, callback, this.RESPONSE_TYPE.ID_TOKEN_TOKEN); + } + } + } + }; + + /** + * Acquires token (interactive flow using a popUp window) by sending request to AAD to obtain a new token. + * @param {string} resource ResourceUri identifying the target resource + * @param {string} extraQueryParameters extraQueryParameters to add to the authentication request + * @param {tokenCallback} callback - The callback provided by the caller. It will be called with token or error. + */ + AuthenticationContext.prototype.acquireTokenPopup = function (resource, tenantId, extraQueryParameters, claims, callback) { + if (this._isEmpty(resource)) { + this.warn('resource is required'); + callback('resource is required', null, 'resource is required'); + return; + } + + if (!this._user) { + this.warn('User login is required'); + callback('User login is required', null, 'login required'); + return; + } + + if (this._acquireTokenInProgress) { + this.warn("Acquire token interactive is already in progress") + callback("Acquire token interactive is already in progress", null, "Acquire token interactive is already in progress"); + return; + } + + var expectedState = this._guid() + '|' + resource + '|' + tenantId; + this.config.state = expectedState; + this._renewStates.push(expectedState); + this._requestType = this.REQUEST_TYPE.RENEW_TOKEN; + this.verbose('Renew token Expected state: ' + expectedState); + // remove the existing prompt=... query parameter and add prompt=select_account + var urlNavigate = this._urlRemoveQueryStringParameter(this._getNavigateUrl('token', resource, tenantId), 'prompt'); + urlNavigate = urlNavigate + '&prompt=select_account'; + + if (extraQueryParameters) { + urlNavigate += extraQueryParameters; + } + + if (claims && (urlNavigate.indexOf("&claims") === -1)) { + urlNavigate += '&claims=' + encodeURIComponent(claims); + } + else if (claims && (urlNavigate.indexOf("&claims") !== -1)) { + throw new Error('Claims cannot be passed as an extraQueryParameter'); + } + + urlNavigate = this._addHintParameters(urlNavigate, !tenantId); + this._acquireTokenInProgress = true; + this.info('acquireToken interactive is called for the resource ' + resource); + this.registerCallback(expectedState, resource, callback, tenantId); + this._loginPopup(urlNavigate, resource, callback); + + }; + + /** + * Acquires token (interactive flow using a redirect) by sending request to AAD to obtain a new token. In this case the callback passed in the Authentication + * request constructor will be called. + * @param {string} resource ResourceUri identifying the target resource + * @param {string} extraQueryParameters extraQueryParameters to add to the authentication request + */ + AuthenticationContext.prototype.acquireTokenRedirect = function (resource, tenantId, extraQueryParameters, claims) { + if (this._isEmpty(resource)) { + this.warn('resource is required'); + callback('resource is required', null, 'resource is required'); + return; + } + + var callback = this.callback; + + if (!this._user) { + this.warn('User login is required'); + callback('User login is required', null, 'login required'); + return; + } + + if (this._acquireTokenInProgress) { + this.warn("Acquire token interactive is already in progress") + callback("Acquire token interactive is already in progress", null, "Acquire token interactive is already in progress"); + return; + } + + var expectedState = this._guid() + '|' + resource + '|' + tenantId; + this.config.state = expectedState; + this.verbose('Renew token Expected state: ' + expectedState); + + // remove the existing prompt=... query parameter and add prompt=select_account + var urlNavigate = this._urlRemoveQueryStringParameter(this._getNavigateUrl('token', resource, tenantId), 'prompt'); + urlNavigate = urlNavigate + '&prompt=select_account'; + if (extraQueryParameters) { + urlNavigate += extraQueryParameters; + } + + if (claims && (urlNavigate.indexOf("&claims") === -1)) { + urlNavigate += '&claims=' + encodeURIComponent(claims); + } + else if (claims && (urlNavigate.indexOf("&claims") !== -1)) { + throw new Error('Claims cannot be passed as an extraQueryParameter'); + } + + urlNavigate = this._addHintParameters(urlNavigate, !tenantId); + this._acquireTokenInProgress = true; + this.info('acquireToken interactive is called for the resource ' + resource); + this._saveItem(this.CONSTANTS.STORAGE.LOGIN_REQUEST, window.location.href); + this._saveItem(this.CONSTANTS.STORAGE.STATE_RENEW, expectedState, true); + this.promptUser(urlNavigate); + }; + /** + * Redirects the browser to Azure AD authorization endpoint. + * @param {string} urlNavigate Url of the authorization endpoint. + */ + AuthenticationContext.prototype.promptUser = function (urlNavigate) { + if (urlNavigate) { + this.infoPii('Navigate to:' + urlNavigate); + window.location.replace(urlNavigate); + } else { + this.info('Navigate url is empty'); + } + }; + + /** + * Clears cache items. + */ + AuthenticationContext.prototype.clearCache = function () { + this._saveItem(this.CONSTANTS.STORAGE.LOGIN_REQUEST, ''); + this._saveItem(this.CONSTANTS.STORAGE.ANGULAR_LOGIN_REQUEST, ''); + this._saveItem(this.CONSTANTS.STORAGE.SESSION_STATE, ''); + this._saveItem(this.CONSTANTS.STORAGE.STATE_LOGIN, ''); + this._saveItem(this.CONSTANTS.STORAGE.STATE_RENEW, ''); + this._renewStates = []; + this._saveItem(this.CONSTANTS.STORAGE.NONCE_IDTOKEN, ''); + this._saveItem(this.CONSTANTS.STORAGE.IDTOKEN, ''); + this._saveItem(this.CONSTANTS.STORAGE.ERROR, ''); + this._saveItem(this.CONSTANTS.STORAGE.ERROR_DESCRIPTION, ''); + this._saveItem(this.CONSTANTS.STORAGE.LOGIN_ERROR, ''); + this._saveItem(this.CONSTANTS.STORAGE.LOGIN_ERROR, ''); + var keys = this._getItem(this.CONSTANTS.STORAGE.TOKEN_KEYS); + + if (!this._isEmpty(keys)) { + keys = keys.split(this.CONSTANTS.RESOURCE_DELIMETER); + for (var i = 0; i < keys.length && keys[i] !== ""; i++) { + this._saveItem(this.CONSTANTS.STORAGE.ACCESS_TOKEN_KEY + keys[i], ''); + this._saveItem(this.CONSTANTS.STORAGE.EXPIRATION_KEY + keys[i], 0); + } + } + + this._saveItem(this.CONSTANTS.STORAGE.TOKEN_KEYS, ''); + }; + + /** + * Clears cache items for a given resource. + * @param {string} resource a URI that identifies the resource. + */ + AuthenticationContext.prototype.clearCacheForResource = function (resource) { + this._saveItem(this.CONSTANTS.STORAGE.STATE_RENEW, ''); + this._saveItem(this.CONSTANTS.STORAGE.ERROR, ''); + this._saveItem(this.CONSTANTS.STORAGE.ERROR_DESCRIPTION, ''); + + if (this._hasResource(resource)) { + this._saveItem(this.CONSTANTS.STORAGE.ACCESS_TOKEN_KEY + resource, ''); + this._saveItem(this.CONSTANTS.STORAGE.EXPIRATION_KEY + resource, 0); + } + }; + + /** + * Redirects user to logout endpoint. + * After logout, it will redirect to postLogoutRedirectUri if added as a property on the config object. + */ + AuthenticationContext.prototype.logOut = function () { + this.clearCache(); + this._user = null; + var urlNavigate; + + if (this.config.logOutUri) { + urlNavigate = this.config.logOutUri; + } else { + var tenant = 'common'; + var logout = ''; + + if (this.config.tenant) { + tenant = this.config.tenant; + } + + if (this.config.postLogoutRedirectUri) { + logout = 'post_logout_redirect_uri=' + encodeURIComponent(this.config.postLogoutRedirectUri); + } + + urlNavigate = this.instance + tenant + '/oauth2/logout?' + logout; + } + + this.infoPii('Logout navigate to: ' + urlNavigate); + this.promptUser(urlNavigate); + }; + + AuthenticationContext.prototype._isEmpty = function (str) { + return (typeof str === 'undefined' || !str || 0 === str.length); + }; + + /** + * @callback userCallback + * @param {string} error error message if user info is not available. + * @param {User} user user object retrieved from the cache. + */ + + /** + * Calls the passed in callback with the user object or error message related to the user. + * @param {userCallback} callback - The callback provided by the caller. It will be called with user or error. + */ + AuthenticationContext.prototype.getUser = function (callback) { + // IDToken is first call + if (typeof callback !== 'function') { + throw new Error('callback is not a function'); + } + + // user in memory + if (this._user) { + callback(null, this._user); + return; + } + + // frame is used to get idtoken + var idtoken = this._getItem(this.CONSTANTS.STORAGE.IDTOKEN); + + if (!this._isEmpty(idtoken)) { + this.info('User exists in cache: '); + this._user = this._createUser(idtoken); + callback(null, this._user); + } else { + this.warn('User information is not available'); + callback('User information is not available', null); + } + }; + + /** + * Adds login_hint to authorization URL which is used to pre-fill the username field of sign in page for the user if known ahead of time. + * domain_hint can be one of users/organisations which when added skips the email based discovery process of the user. + * @ignore + */ + AuthenticationContext.prototype._addHintParameters = function (urlNavigate, addDomainHint) { + //If you don�t use prompt=none, then if the session does not exist, there will be a failure. + //If sid is sent alongside domain or login hints, there will be a failure since request is ambiguous. + //If sid is sent with a prompt value other than none or attempt_none, there will be a failure since the request is ambiguous. + + if (this._user && this._user.profile) { + if (this._user.profile.sid && urlNavigate.indexOf('&prompt=none') !== -1) { + // don't add sid twice if user provided it in the extraQueryParameter value + if (!this._urlContainsQueryStringParameter("sid", urlNavigate)) { + // add sid + urlNavigate += '&sid=' + encodeURIComponent(this._user.profile.sid); + } + } + else if (this._user.profile.upn) { + // don't add login_hint twice if user provided it in the extraQueryParameter value + if (!this._urlContainsQueryStringParameter("login_hint", urlNavigate)) { + // add login_hint + urlNavigate += '&login_hint=' + encodeURIComponent(this._user.profile.upn); + } + // don't add domain_hint twice if user provided it in the extraQueryParameter value + if (addDomainHint && !this._urlContainsQueryStringParameter("domain_hint", urlNavigate) && this._user.profile.upn.indexOf('@') > -1) { + var parts = this._user.profile.upn.split('@'); + // local part can include @ in quotes. Sending last part handles that. + urlNavigate += '&domain_hint=' + encodeURIComponent(parts[parts.length - 1]); + } + } + + } + + return urlNavigate; + } + + /** + * Creates a user object by decoding the id_token + * @ignore + */ + AuthenticationContext.prototype._createUser = function (idToken) { + var user = null; + var parsedJson = this._extractIdToken(idToken); + if (parsedJson && parsedJson.hasOwnProperty('aud')) { + if (parsedJson.aud.toLowerCase() === this.config.clientId.toLowerCase()) { + + user = { + userName: '', + profile: parsedJson + }; + + if (parsedJson.hasOwnProperty('upn')) { + user.userName = parsedJson.upn; + } else if (parsedJson.hasOwnProperty('email')) { + user.userName = parsedJson.email; + } + } else { + this.warn('IdToken has invalid aud field'); + } + + } + + return user; + }; + + /** + * Returns the anchor part(#) of the URL + * @ignore + */ + AuthenticationContext.prototype._getHash = function (hash) { + if (hash.indexOf('#/') > -1) { + hash = hash.substring(hash.indexOf('#/') + 2); + } else if (hash.indexOf('#') > -1) { + hash = hash.substring(1); + } + + return hash; + }; + + /** + * Checks if the URL fragment contains access token, id token or error_description. + * @param {string} hash - Hash passed from redirect page + * @returns {Boolean} true if response contains id_token, access_token or error, false otherwise. + */ + AuthenticationContext.prototype.isCallback = function (hash) { + hash = this._getHash(hash); + var parameters = this._deserialize(hash); + return ( + parameters.hasOwnProperty(this.CONSTANTS.ERROR_DESCRIPTION) || + parameters.hasOwnProperty(this.CONSTANTS.ACCESS_TOKEN) || + parameters.hasOwnProperty(this.CONSTANTS.ID_TOKEN) + ); + }; + + /** + * Gets login error + * @returns {string} error message related to login. + */ + AuthenticationContext.prototype.getLoginError = function () { + return this._getItem(this.CONSTANTS.STORAGE.LOGIN_ERROR); + }; + + /** + * Request info object created from the response received from AAD. + * @class RequestInfo + * @property {object} parameters - object comprising of fields such as id_token/error, session_state, state, e.t.c. + * @property {REQUEST_TYPE} requestType - either LOGIN, RENEW_TOKEN or UNKNOWN. + * @property {boolean} stateMatch - true if state is valid, false otherwise. + * @property {string} stateResponse - unique guid used to match the response with the request. + * @property {boolean} valid - true if requestType contains id_token, access_token or error, false otherwise. + */ + + /** + * Creates a requestInfo object from the URL fragment and returns it. + * @returns {RequestInfo} an object created from the redirect response from AAD comprising of the keys - parameters, requestType, stateMatch, stateResponse and valid. + */ + AuthenticationContext.prototype.getRequestInfo = function (hash) { + hash = this._getHash(hash); + var parameters = this._deserialize(hash); + var requestInfo = { + valid: false, + parameters: {}, + stateMatch: false, + stateResponse: '', + requestType: this.REQUEST_TYPE.UNKNOWN, + }; + + if (parameters) { + requestInfo.parameters = parameters; + if (parameters.hasOwnProperty(this.CONSTANTS.ERROR_DESCRIPTION) || + parameters.hasOwnProperty(this.CONSTANTS.ACCESS_TOKEN) || + parameters.hasOwnProperty(this.CONSTANTS.ID_TOKEN)) { + + requestInfo.valid = true; + + // which call + var stateResponse = ''; + if (parameters.hasOwnProperty('state')) { + this.verbose('State: ' + parameters.state); + stateResponse = parameters.state; + } else { + this.warn('No state returned'); + return requestInfo; + } + + requestInfo.stateResponse = stateResponse; + + // async calls can fire iframe and login request at the same time if developer does not use the API as expected + // incoming callback needs to be looked up to find the request type + if (this._matchState(requestInfo)) { // loginRedirect or acquireTokenRedirect + return requestInfo; + } + + // external api requests may have many renewtoken requests for different resource + if (!requestInfo.stateMatch && window.parent) { + requestInfo.requestType = this._requestType; + var statesInParentContext = this._renewStates; + for (var i = 0; i < statesInParentContext.length; i++) { + if (statesInParentContext[i] === requestInfo.stateResponse) { + requestInfo.stateMatch = true; + break; + } + } + } + } + } + return requestInfo; + }; + + /** + * Matches nonce from the request with the response. + * @ignore + */ + AuthenticationContext.prototype._matchNonce = function (user) { + var requestNonce = this._getItem(this.CONSTANTS.STORAGE.NONCE_IDTOKEN); + + if (requestNonce) { + requestNonce = requestNonce.split(this.CONSTANTS.CACHE_DELIMETER); + for (var i = 0; i < requestNonce.length; i++) { + if (requestNonce[i] === user.profile.nonce) { + return true; + } + } + } + + return false; + }; + + /** + * Matches state from the request with the response. + * @ignore + */ + AuthenticationContext.prototype._matchState = function (requestInfo) { + var loginStates = this._getItem(this.CONSTANTS.STORAGE.STATE_LOGIN); + + if (loginStates) { + loginStates = loginStates.split(this.CONSTANTS.CACHE_DELIMETER); + for (var i = 0; i < loginStates.length; i++) { + if (loginStates[i] === requestInfo.stateResponse) { + requestInfo.requestType = this.REQUEST_TYPE.LOGIN; + requestInfo.stateMatch = true; + return true; + } + } + } + + var acquireTokenStates = this._getItem(this.CONSTANTS.STORAGE.STATE_RENEW); + + if (acquireTokenStates) { + acquireTokenStates = acquireTokenStates.split(this.CONSTANTS.CACHE_DELIMETER); + for (var i = 0; i < acquireTokenStates.length; i++) { + if (acquireTokenStates[i] === requestInfo.stateResponse) { + requestInfo.requestType = this.REQUEST_TYPE.RENEW_TOKEN; + requestInfo.stateMatch = true; + return true; + } + } + } + + return false; + + }; + + /** + * Extracts resource value from state. + * @ignore + */ + AuthenticationContext.prototype._getResourceFromState = function (state) { + if (state) { + var splitIndex = state.indexOf('|'); + + if (splitIndex > -1 && splitIndex + 1 < state.length) { + let resourceWithTenant = state.substring(splitIndex + 1); + splitIndex = resourceWithTenant.indexOf('|'); + if (splitIndex > -1) { + let resource = resourceWithTenant.substring(0, splitIndex); + return resource; + } + return resourceWithTenant; + } + } + + return ''; + }; + + AuthenticationContext.prototype._getTenantFromState = function (state) { + if (state) { + var splits = state.split('|'); + if (splits.length === 3) { + return splits[splits.length - 1]; + } + } + + return ''; + }; + + /** + * Saves token or error received in the response from AAD in the cache. In case of id_token, it also creates the user object. + */ + AuthenticationContext.prototype.saveTokenFromHash = function (requestInfo) { + this.info('State status:' + requestInfo.stateMatch + '; Request type:' + requestInfo.requestType); + this._saveItem(this.CONSTANTS.STORAGE.ERROR, ''); + this._saveItem(this.CONSTANTS.STORAGE.ERROR_DESCRIPTION, ''); + + var resource = this._getResourceFromState(requestInfo.stateResponse); + var tenant = this._getTenantFromState(requestInfo.stateResponse); + + // Record error + if (requestInfo.parameters.hasOwnProperty(this.CONSTANTS.ERROR_DESCRIPTION)) { + this.infoPii('Error :' + requestInfo.parameters.error + '; Error description:' + requestInfo.parameters[this.CONSTANTS.ERROR_DESCRIPTION]); + this._saveItem(this.CONSTANTS.STORAGE.ERROR, requestInfo.parameters.error); + this._saveItem(this.CONSTANTS.STORAGE.ERROR_DESCRIPTION, requestInfo.parameters[this.CONSTANTS.ERROR_DESCRIPTION]); + + if (requestInfo.requestType === this.REQUEST_TYPE.LOGIN) { + this._loginInProgress = false; + this._saveItem(this.CONSTANTS.STORAGE.LOGIN_ERROR, requestInfo.parameters.error_description); + } + } else { + // It must verify the state from redirect + if (requestInfo.stateMatch) { + // record tokens to storage if exists + this.info('State is right'); + if (requestInfo.parameters.hasOwnProperty(this.CONSTANTS.SESSION_STATE)) { + this._saveItem(this.CONSTANTS.STORAGE.SESSION_STATE, requestInfo.parameters[this.CONSTANTS.SESSION_STATE]); + } + + var keys; + + if (requestInfo.parameters.hasOwnProperty(this.CONSTANTS.ACCESS_TOKEN)) { + this.info('Fragment has access token'); + + if (!this._hasResource(resource)) { + keys = this._getItem(this.CONSTANTS.STORAGE.TOKEN_KEYS) || ''; + this._saveItem(this.CONSTANTS.STORAGE.TOKEN_KEYS, keys + resource + this.CONSTANTS.RESOURCE_DELIMETER); + } + + // save token with related resource + this._saveItem(this.CONSTANTS.STORAGE.ACCESS_TOKEN_KEY + resource + tenant, requestInfo.parameters[this.CONSTANTS.ACCESS_TOKEN]); + this._saveItem(this.CONSTANTS.STORAGE.EXPIRATION_KEY + resource + tenant, this._expiresIn(requestInfo.parameters[this.CONSTANTS.EXPIRES_IN])); + } + + if (requestInfo.parameters.hasOwnProperty(this.CONSTANTS.ID_TOKEN)) { + this.info('Fragment has id token'); + this._loginInProgress = false; + this._user = this._createUser(requestInfo.parameters[this.CONSTANTS.ID_TOKEN]); + if (this._user && this._user.profile) { + if (!this._matchNonce(this._user)) { + this._saveItem(this.CONSTANTS.STORAGE.LOGIN_ERROR, 'Nonce received: ' + this._user.profile.nonce + ' is not same as requested: ' + + this._getItem(this.CONSTANTS.STORAGE.NONCE_IDTOKEN)); + this._user = null; + } else { + this._saveItem(this.CONSTANTS.STORAGE.IDTOKEN, requestInfo.parameters[this.CONSTANTS.ID_TOKEN]); + + // Save idtoken as access token for app itself + resource = this.config.loginResource ? this.config.loginResource : this.config.clientId; + + if (!this._hasResource(resource)) { + keys = this._getItem(this.CONSTANTS.STORAGE.TOKEN_KEYS) || ''; + this._saveItem(this.CONSTANTS.STORAGE.TOKEN_KEYS, keys + resource + this.CONSTANTS.RESOURCE_DELIMETER); + } + + this._saveItem(this.CONSTANTS.STORAGE.ACCESS_TOKEN_KEY + resource + tenant, requestInfo.parameters[this.CONSTANTS.ID_TOKEN]); + this._saveItem(this.CONSTANTS.STORAGE.EXPIRATION_KEY + resource + tenant, this._user.profile.exp); + } + } + else { + requestInfo.parameters['error'] = 'invalid id_token'; + requestInfo.parameters['error_description'] = 'Invalid id_token. id_token: ' + requestInfo.parameters[this.CONSTANTS.ID_TOKEN]; + this._saveItem(this.CONSTANTS.STORAGE.ERROR, 'invalid id_token'); + this._saveItem(this.CONSTANTS.STORAGE.ERROR_DESCRIPTION, 'Invalid id_token. id_token: ' + requestInfo.parameters[this.CONSTANTS.ID_TOKEN]); + } + } + } else { + requestInfo.parameters['error'] = 'Invalid_state'; + requestInfo.parameters['error_description'] = 'Invalid_state. state: ' + requestInfo.stateResponse; + this._saveItem(this.CONSTANTS.STORAGE.ERROR, 'Invalid_state'); + this._saveItem(this.CONSTANTS.STORAGE.ERROR_DESCRIPTION, 'Invalid_state. state: ' + requestInfo.stateResponse); + } + } + + this._saveItem(this.CONSTANTS.STORAGE.RENEW_STATUS + resource + tenant, this.CONSTANTS.TOKEN_RENEW_STATUS_COMPLETED); + }; + + /** + * Gets resource for given endpoint if mapping is provided with config. + * @param {string} endpoint - The URI for which the resource Id is requested. + * @returns {string} resource for this API endpoint. + */ + AuthenticationContext.prototype.getResourceForEndpoint = function (endpoint) { + + // if user specified list of anonymous endpoints, no need to send token to these endpoints, return null. + if (this.config && this.config.anonymousEndpoints) { + for (var i = 0; i < this.config.anonymousEndpoints.length; i++) { + if (endpoint.indexOf(this.config.anonymousEndpoints[i]) > -1) { + return null; + } + } + } + + if (this.config && this.config.endpoints) { + for (var configEndpoint in this.config.endpoints) { + // configEndpoint is like /api/Todo requested endpoint can be /api/Todo/1 + if (endpoint.indexOf(configEndpoint) > -1) { + return this.config.endpoints[configEndpoint]; + } + } + } + + // default resource will be clientid if nothing specified + // App will use idtoken for calls to itself + // check if it's staring from http or https, needs to match with app host + if (endpoint.indexOf('http://') > -1 || endpoint.indexOf('https://') > -1) { + if (this._getHostFromUri(endpoint) === this._getHostFromUri(this.config.redirectUri)) { + return this.config.loginResource; + } + } + else { + // in angular level, the url for $http interceptor call could be relative url, + // if it's relative call, we'll treat it as app backend call. + return this.config.loginResource; + } + + // if not the app's own backend or not a domain listed in the endpoints structure + return null; + }; + + /** + * Strips the protocol part of the URL and returns it. + * @ignore + */ + AuthenticationContext.prototype._getHostFromUri = function (uri) { + // remove http:// or https:// from uri + var extractedUri = String(uri).replace(/^(https?:)\/\//, ''); + extractedUri = extractedUri.split('/')[0]; + return extractedUri; + }; + + /** + * This method must be called for processing the response received from AAD. It extracts the hash, processes the token or error, saves it in the cache and calls the registered callbacks with the result. + * @param {string} [hash=window.location.hash] - Hash fragment of Url. + */ + AuthenticationContext.prototype.handleWindowCallback = function (hash) { + // This is for regular javascript usage for redirect handling + // need to make sure this is for callback + if (hash == null) { + hash = window.location.hash; + } + + if (this.isCallback(hash)) { + var self = null; + var isPopup = false; + + if (this._openedWindows.length > 0 && this._openedWindows[this._openedWindows.length - 1].opener + && this._openedWindows[this._openedWindows.length - 1].opener._adalInstance) { + self = this._openedWindows[this._openedWindows.length - 1].opener._adalInstance; + isPopup = true; + } + else if (window.parent && window.parent._adalInstance) { + self = window.parent._adalInstance; + } + + var requestInfo = self.getRequestInfo(hash); + var token, tokenReceivedCallback, tokenType = null; + + if (isPopup || window.parent !== window) { + tokenReceivedCallback = self._callBackMappedToRenewStates[requestInfo.stateResponse]; + } + else { + tokenReceivedCallback = self.callback; + } + + self.info("Returned from redirect url"); + self.saveTokenFromHash(requestInfo); + + if ((requestInfo.requestType === this.REQUEST_TYPE.RENEW_TOKEN) && window.parent) { + if (window.parent !== window) { + self.verbose("Window is in iframe, acquiring token silently"); + } else { + self.verbose("acquiring token interactive in progress"); + } + + token = requestInfo.parameters[self.CONSTANTS.ACCESS_TOKEN] || requestInfo.parameters[self.CONSTANTS.ID_TOKEN]; + tokenType = self.CONSTANTS.ACCESS_TOKEN; + } else if (requestInfo.requestType === this.REQUEST_TYPE.LOGIN) { + token = requestInfo.parameters[self.CONSTANTS.ID_TOKEN]; + tokenType = self.CONSTANTS.ID_TOKEN; + } + + var errorDesc = requestInfo.parameters[self.CONSTANTS.ERROR_DESCRIPTION]; + var error = requestInfo.parameters[self.CONSTANTS.ERROR]; + try { + if (tokenReceivedCallback) { + tokenReceivedCallback(errorDesc, token, error, tokenType); + } + + } catch (err) { + self.error("Error occurred in user defined callback function: " + err); + } + + if (window.parent === window && !isPopup) { + if (self.config.navigateToLoginRequestUrl) { + window.location.href = self._getItem(self.CONSTANTS.STORAGE.LOGIN_REQUEST); + } else window.location.hash = ''; + } + } + }; + + /** + * Constructs the authorization endpoint URL and returns it. + * @ignore + */ + AuthenticationContext.prototype._getNavigateUrl = function (responseType, resource, overrideTenant) { + var tenant = 'common'; + if (overrideTenant || this.config.tenant) { + tenant = overrideTenant || this.config.tenant; + } + + var urlNavigate = this.instance + tenant + '/oauth2/authorize' + this._serialize(responseType, this.config, resource) + this._addLibMetadata(); + this.info('Navigate url:' + urlNavigate); + return urlNavigate; + }; + + /** + * Returns the decoded id_token. + * @ignore + */ + AuthenticationContext.prototype._extractIdToken = function (encodedIdToken) { + // id token will be decoded to get the username + var decodedToken = this._decodeJwt(encodedIdToken); + + if (!decodedToken) { + return null; + } + + try { + var base64IdToken = decodedToken.JWSPayload; + var base64Decoded = this._base64DecodeStringUrlSafe(base64IdToken); + + if (!base64Decoded) { + this.info('The returned id_token could not be base64 url safe decoded.'); + return null; + } + + // ECMA script has JSON built-in support + return JSON.parse(base64Decoded); + } catch (err) { + this.error('The returned id_token could not be decoded', err); + } + + return null; + }; + + /** + * Decodes a string of data which has been encoded using base-64 encoding. + * @ignore + */ + AuthenticationContext.prototype._base64DecodeStringUrlSafe = function (base64IdToken) { + // html5 should support atob function for decoding + base64IdToken = base64IdToken.replace(/-/g, '+').replace(/_/g, '/'); + + if (window.atob) { + return decodeURIComponent(escape(window.atob(base64IdToken))); // jshint ignore:line + } + else { + return decodeURIComponent(escape(this._decode(base64IdToken))); + } + }; + + //Take https://cdnjs.cloudflare.com/ajax/libs/Base64/0.3.0/base64.js and https://en.wikipedia.org/wiki/Base64 as reference. + AuthenticationContext.prototype._decode = function (base64IdToken) { + var codes = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + base64IdToken = String(base64IdToken).replace(/=+$/, ''); + + var length = base64IdToken.length; + + if (length % 4 === 1) { + throw new Error('The token to be decoded is not correctly encoded.'); + } + + var h1, h2, h3, h4, bits, c1, c2, c3, decoded = ''; + + for (var i = 0; i < length; i += 4) { + //Every 4 base64 encoded character will be converted to 3 byte string, which is 24 bits + // then 6 bits per base64 encoded character + h1 = codes.indexOf(base64IdToken.charAt(i)); + h2 = codes.indexOf(base64IdToken.charAt(i + 1)); + h3 = codes.indexOf(base64IdToken.charAt(i + 2)); + h4 = codes.indexOf(base64IdToken.charAt(i + 3)); + + // For padding, if last two are '=' + if (i + 2 === length - 1) { + bits = h1 << 18 | h2 << 12 | h3 << 6; + c1 = bits >> 16 & 255; + c2 = bits >> 8 & 255; + decoded += String.fromCharCode(c1, c2); + break; + } + // if last one is '=' + else if (i + 1 === length - 1) { + bits = h1 << 18 | h2 << 12 + c1 = bits >> 16 & 255; + decoded += String.fromCharCode(c1); + break; + } + + bits = h1 << 18 | h2 << 12 | h3 << 6 | h4; + + // then convert to 3 byte chars + c1 = bits >> 16 & 255; + c2 = bits >> 8 & 255; + c3 = bits & 255; + + decoded += String.fromCharCode(c1, c2, c3); + } + + return decoded; + }; + + /** + * Decodes an id token into an object with header, payload and signature fields. + * @ignore + */ + // Adal.node js crack function + AuthenticationContext.prototype._decodeJwt = function (jwtToken) { + if (this._isEmpty(jwtToken)) { + return null; + }; + + var idTokenPartsRegex = /^([^\.\s]*)\.([^\.\s]+)\.([^\.\s]*)$/; + + var matches = idTokenPartsRegex.exec(jwtToken); + + if (!matches || matches.length < 4) { + this.warn('The returned id_token is not parseable.'); + return null; + } + + var crackedToken = { + header: matches[1], + JWSPayload: matches[2], + JWSSig: matches[3] + }; + + return crackedToken; + }; + + /** + * Converts string to represent binary data in ASCII string format by translating it into a radix-64 representation and returns it + * @ignore + */ + AuthenticationContext.prototype._convertUrlSafeToRegularBase64EncodedString = function (str) { + return str.replace('-', '+').replace('_', '/'); + }; + + /** + * Serializes the parameters for the authorization endpoint URL and returns the serialized uri string. + * @ignore + */ + AuthenticationContext.prototype._serialize = function (responseType, obj, resource) { + var str = []; + + if (obj !== null) { + str.push('?response_type=' + responseType); + str.push('client_id=' + encodeURIComponent(obj.clientId)); + if (resource) { + str.push('resource=' + encodeURIComponent(resource)); + } + + str.push('redirect_uri=' + encodeURIComponent(obj.redirectUri)); + str.push('state=' + encodeURIComponent(obj.state)); + + if (obj.hasOwnProperty('slice')) { + str.push('slice=' + encodeURIComponent(obj.slice)); + } + + if (obj.hasOwnProperty('extraQueryParameter')) { + str.push(obj.extraQueryParameter); + } + + var correlationId = obj.correlationId ? obj.correlationId : this._guid(); + str.push('client-request-id=' + encodeURIComponent(correlationId)); + } + + return str.join('&'); + }; + + /** + * Parses the query string parameters into a key-value pair object. + * @ignore + */ + AuthenticationContext.prototype._deserialize = function (query) { + var match, + pl = /\+/g, // Regex for replacing addition symbol with a space + search = /([^&=]+)=([^&]*)/g, + decode = function (s) { + return decodeURIComponent(s.replace(pl, ' ')); + }, + obj = {}; + match = search.exec(query); + + while (match) { + obj[decode(match[1])] = decode(match[2]); + match = search.exec(query); + } + + return obj; + }; + + /** + * Converts decimal value to hex equivalent + * @ignore + */ + AuthenticationContext.prototype._decimalToHex = function (number) { + var hex = number.toString(16); + + while (hex.length < 2) { + hex = '0' + hex; + } + return hex; + } + + /** + * Generates RFC4122 version 4 guid (128 bits) + * @ignore + */ + /* jshint ignore:start */ + AuthenticationContext.prototype._guid = function () { + // RFC4122: The version 4 UUID is meant for generating UUIDs from truly-random or + // pseudo-random numbers. + // The algorithm is as follows: + // Set the two most significant bits (bits 6 and 7) of the + // clock_seq_hi_and_reserved to zero and one, respectively. + // Set the four most significant bits (bits 12 through 15) of the + // time_hi_and_version field to the 4-bit version number from + // Section 4.1.3. Version4 + // Set all the other bits to randomly (or pseudo-randomly) chosen + // values. + // UUID = time-low "-" time-mid "-"time-high-and-version "-"clock-seq-reserved and low(2hexOctet)"-" node + // time-low = 4hexOctet + // time-mid = 2hexOctet + // time-high-and-version = 2hexOctet + // clock-seq-and-reserved = hexOctet: + // clock-seq-low = hexOctet + // node = 6hexOctet + // Format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx + // y could be 1000, 1001, 1010, 1011 since most significant two bits needs to be 10 + // y values are 8, 9, A, B + var cryptoObj = window.crypto || window.msCrypto; // for IE 11 + if (cryptoObj && cryptoObj.getRandomValues) { + var buffer = new Uint8Array(16); + cryptoObj.getRandomValues(buffer); + //buffer[6] and buffer[7] represents the time_hi_and_version field. We will set the four most significant bits (4 through 7) of buffer[6] to represent decimal number 4 (UUID version number). + buffer[6] |= 0x40; //buffer[6] | 01000000 will set the 6 bit to 1. + buffer[6] &= 0x4f; //buffer[6] & 01001111 will set the 4, 5, and 7 bit to 0 such that bits 4-7 == 0100 = "4". + //buffer[8] represents the clock_seq_hi_and_reserved field. We will set the two most significant bits (6 and 7) of the clock_seq_hi_and_reserved to zero and one, respectively. + buffer[8] |= 0x80; //buffer[8] | 10000000 will set the 7 bit to 1. + buffer[8] &= 0xbf; //buffer[8] & 10111111 will set the 6 bit to 0. + return this._decimalToHex(buffer[0]) + this._decimalToHex(buffer[1]) + this._decimalToHex(buffer[2]) + this._decimalToHex(buffer[3]) + '-' + this._decimalToHex(buffer[4]) + this._decimalToHex(buffer[5]) + '-' + this._decimalToHex(buffer[6]) + this._decimalToHex(buffer[7]) + '-' + + this._decimalToHex(buffer[8]) + this._decimalToHex(buffer[9]) + '-' + this._decimalToHex(buffer[10]) + this._decimalToHex(buffer[11]) + this._decimalToHex(buffer[12]) + this._decimalToHex(buffer[13]) + this._decimalToHex(buffer[14]) + this._decimalToHex(buffer[15]); + } + else { + var guidHolder = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'; + var hex = '0123456789abcdef'; + var r = 0; + var guidResponse = ""; + for (var i = 0; i < 36; i++) { + if (guidHolder[i] !== '-' && guidHolder[i] !== '4') { + // each x and y needs to be random + r = Math.random() * 16 | 0; + } + if (guidHolder[i] === 'x') { + guidResponse += hex[r]; + } else if (guidHolder[i] === 'y') { + // clock-seq-and-reserved first hex is filtered and remaining hex values are random + r &= 0x3; // bit and with 0011 to set pos 2 to zero ?0?? + r |= 0x8; // set pos 3 to 1 as 1??? + guidResponse += hex[r]; + } else { + guidResponse += guidHolder[i]; + } + } + return guidResponse; + } + }; + /* jshint ignore:end */ + + /** + * Calculates the expires in value in milliseconds for the acquired token + * @ignore + */ + AuthenticationContext.prototype._expiresIn = function (expires) { + // if AAD did not send "expires_in" property, use default expiration of 3599 seconds, for some reason AAD sends 3599 as "expires_in" value instead of 3600 + if (!expires) expires = 3599; + return this._now() + parseInt(expires, 10); + }; + + /** + * Return the number of milliseconds since 1970/01/01 + * @ignore + */ + AuthenticationContext.prototype._now = function () { + return Math.round(new Date().getTime() / 1000.0); + }; + + /** + * Adds the hidden iframe for silent token renewal + * @ignore + */ + AuthenticationContext.prototype._addAdalFrame = function (iframeId) { + if (typeof iframeId === 'undefined') { + return; + } + + this.info('Add adal frame to document:' + iframeId); + var adalFrame = document.getElementById(iframeId); + + if (!adalFrame) { + if (document.createElement && document.documentElement && + (window.opera || window.navigator.userAgent.indexOf('MSIE 5.0') === -1)) { + var ifr = document.createElement('iframe'); + ifr.setAttribute('id', iframeId); + ifr.setAttribute('aria-hidden', 'true'); + ifr.style.visibility = 'hidden'; + ifr.style.position = 'absolute'; + ifr.style.width = ifr.style.height = ifr.borderWidth = '0px'; + + adalFrame = document.getElementsByTagName('body')[0].appendChild(ifr); + } + else if (document.body && document.body.insertAdjacentHTML) { + document.body.insertAdjacentHTML('beforeEnd', ''); + } + if (window.frames && window.frames[iframeId]) { + adalFrame = window.frames[iframeId]; + } + } + + return adalFrame; + }; + + /** + * Saves the key-value pair in the cache + * @ignore + */ + AuthenticationContext.prototype._saveItem = function (key, obj, preserve) { + + if (this.config && this.config.cacheLocation && this.config.cacheLocation === 'localStorage') { + + if (!this._supportsLocalStorage()) { + this.info('Local storage is not supported'); + return false; + } + + if (preserve) { + var value = this._getItem(key) || ''; + localStorage.setItem(key, value + obj + this.CONSTANTS.CACHE_DELIMETER); + } + else { + localStorage.setItem(key, obj); + } + + return true; + } + + // Default as session storage + if (!this._supportsSessionStorage()) { + this.info('Session storage is not supported'); + return false; + } + + sessionStorage.setItem(key, obj); + return true; + }; + + /** + * Searches the value for the given key in the cache + * @ignore + */ + AuthenticationContext.prototype._getItem = function (key) { + + if (this.config && this.config.cacheLocation && this.config.cacheLocation === 'localStorage') { + + if (!this._supportsLocalStorage()) { + this.info('Local storage is not supported'); + return null; + } + + return localStorage.getItem(key); + } + + // Default as session storage + if (!this._supportsSessionStorage()) { + this.info('Session storage is not supported'); + return null; + } + + return sessionStorage.getItem(key); + }; + + /** + * Returns true if browser supports localStorage, false otherwise. + * @ignore + */ + AuthenticationContext.prototype._supportsLocalStorage = function () { + try { + if (!window.localStorage) return false; // Test availability + window.localStorage.setItem('storageTest', 'A'); // Try write + if (window.localStorage.getItem('storageTest') != 'A') return false; // Test read/write + window.localStorage.removeItem('storageTest'); // Try delete + if (window.localStorage.getItem('storageTest')) return false; // Test delete + return true; // Success + } catch (e) { + return false; + } + }; + + /** + * Returns true if browser supports sessionStorage, false otherwise. + * @ignore + */ + AuthenticationContext.prototype._supportsSessionStorage = function () { + try { + if (!window.sessionStorage) return false; // Test availability + window.sessionStorage.setItem('storageTest', 'A'); // Try write + if (window.sessionStorage.getItem('storageTest') != 'A') return false; // Test read/write + window.sessionStorage.removeItem('storageTest'); // Try delete + if (window.sessionStorage.getItem('storageTest')) return false; // Test delete + return true; // Success + } catch (e) { + return false; + } + }; + + /** + * Returns a cloned copy of the passed object. + * @ignore + */ + AuthenticationContext.prototype._cloneConfig = function (obj) { + if (null === obj || 'object' !== typeof obj) { + return obj; + } + + var copy = {}; + for (var attr in obj) { + if (obj.hasOwnProperty(attr)) { + copy[attr] = obj[attr]; + } + } + return copy; + }; + + /** + * Adds the library version and returns it. + * @ignore + */ + AuthenticationContext.prototype._addLibMetadata = function () { + // x-client-SKU + // x-client-Ver + return '&x-client-SKU=Js&x-client-Ver=' + this._libVersion(); + }; + + /** + * Checks the Logging Level, constructs the Log message and logs it. Users need to implement/override this method to turn on Logging. + * @param {number} level - Level can be set 0,1,2 and 3 which turns on 'error', 'warning', 'info' or 'verbose' level logging respectively. + * @param {string} message - Message to log. + * @param {string} error - Error to log. + */ + AuthenticationContext.prototype.log = function (level, message, error, containsPii) { + + if (level <= Logging.level) { + + if (!Logging.piiLoggingEnabled && containsPii) + return; + + var timestamp = new Date().toUTCString(); + var formattedMessage = ''; + + if (this.config.correlationId) + formattedMessage = timestamp + ':' + this.config.correlationId + '-' + this._libVersion() + '-' + this.CONSTANTS.LEVEL_STRING_MAP[level] + ' ' + message; + else + formattedMessage = timestamp + ':' + this._libVersion() + '-' + this.CONSTANTS.LEVEL_STRING_MAP[level] + ' ' + message; + + if (error) { + formattedMessage += '\nstack:\n' + error.stack; + } + + Logging.log(formattedMessage); + } + }; + + /** + * Logs messages when Logging Level is set to 0. + * @param {string} message - Message to log. + * @param {string} error - Error to log. + */ + AuthenticationContext.prototype.error = function (message, error) { + this.log(this.CONSTANTS.LOGGING_LEVEL.ERROR, message, error); + }; + + /** + * Logs messages when Logging Level is set to 1. + * @param {string} message - Message to log. + */ + AuthenticationContext.prototype.warn = function (message) { + this.log(this.CONSTANTS.LOGGING_LEVEL.WARN, message, null); + }; + + /** + * Logs messages when Logging Level is set to 2. + * @param {string} message - Message to log. + */ + AuthenticationContext.prototype.info = function (message) { + this.log(this.CONSTANTS.LOGGING_LEVEL.INFO, message, null); + }; + + /** + * Logs messages when Logging Level is set to 3. + * @param {string} message - Message to log. + */ + AuthenticationContext.prototype.verbose = function (message) { + this.log(this.CONSTANTS.LOGGING_LEVEL.VERBOSE, message, null); + }; + + /** + * Logs Pii messages when Logging Level is set to 0 and window.piiLoggingEnabled is set to true. + * @param {string} message - Message to log. + * @param {string} error - Error to log. + */ + AuthenticationContext.prototype.errorPii = function (message, error) { + this.log(this.CONSTANTS.LOGGING_LEVEL.ERROR, message, error, true); + }; + + /** + * Logs Pii messages when Logging Level is set to 1 and window.piiLoggingEnabled is set to true. + * @param {string} message - Message to log. + */ + AuthenticationContext.prototype.warnPii = function (message) { + this.log(this.CONSTANTS.LOGGING_LEVEL.WARN, message, null, true); + }; + + /** + * Logs messages when Logging Level is set to 2 and window.piiLoggingEnabled is set to true. + * @param {string} message - Message to log. + */ + AuthenticationContext.prototype.infoPii = function (message) { + this.log(this.CONSTANTS.LOGGING_LEVEL.INFO, message, null, true); + }; + + /** + * Logs messages when Logging Level is set to 3 and window.piiLoggingEnabled is set to true. + * @param {string} message - Message to log. + */ + AuthenticationContext.prototype.verbosePii = function (message) { + this.log(this.CONSTANTS.LOGGING_LEVEL.VERBOSE, message, null, true); + }; + /** + * Returns the library version. + * @ignore + */ + AuthenticationContext.prototype._libVersion = function () { + return '1.0.17.1'; + }; + + /** + * Returns a reference of Authentication Context as a result of a require call. + * @ignore + */ + if (typeof module !== 'undefined' && module.exports) { + module.exports = AuthenticationContext; + module.exports.inject = function (conf) { + return new AuthenticationContext(conf); + }; + // workaround jest didn't recognize AuthenticationContext issue. Not ideal + window.AuthenticationContext = AuthenticationContext; + } + + return AuthenticationContext; + +}()); \ No newline at end of file diff --git a/externals/bootstrap.js b/externals/bootstrap.js new file mode 100644 index 000000000..e1cd129bb --- /dev/null +++ b/externals/bootstrap.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under the MIT license + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file diff --git a/externals/bootstrap.min.js b/externals/bootstrap.min.js new file mode 100644 index 000000000..e1cd129bb --- /dev/null +++ b/externals/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under the MIT license + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file diff --git a/externals/bootstrap_ase.css b/externals/bootstrap_ase.css new file mode 100644 index 000000000..9688340b9 --- /dev/null +++ b/externals/bootstrap_ase.css @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{text-decoration:none}a:focus,a:hover{text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}@media (min-width:768px){}@media (min-width:992px){}@media (min-width:1200px){}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} +/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/externals/bops.js b/externals/bops.js new file mode 100644 index 000000000..abc25a9ae --- /dev/null +++ b/externals/bops.js @@ -0,0 +1,595 @@ +"use strict"; + +(function(e){if("function"==typeof bootstrap)bootstrap("bops",e);else if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeBops=e}else"undefined"!=typeof window?window.bops=e():global.bops=e()})(function(){var define,ses,bootstrap,module,exports; +return (function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s source.length) { + source_end = source.length + } + + if(target.length - target_start < source_end - source_start) { + source_end = target.length - target_start + start + } + + if(source.buffer !== target.buffer) { + return fast_copy(source, target, target_start, source_start, source_end) + } + return slow_copy(source, target, target_start, source_start, source_end) +} + +function fast_copy(source, target, target_start, source_start, source_end) { + var len = (source_end - source_start) + target_start + + for(var i = target_start, j = source_start; + i < len; + ++i, + ++j) { + target[i] = source[j] + } +} + +function slow_copy(from, to, j, i, jend) { + // the buffers could overlap. + var iend = jend + i + , tmp = new Uint8Array(slice.call(from, i, iend)) + , x = 0 + + for(; i < iend; ++i, ++x) { + to[j++] = tmp[x] + } +} + +},{}],8:[function(require,module,exports){ +module.exports = function(size) { + return new Uint8Array(size) +} + +},{}],9:[function(require,module,exports){ +module.exports = { + readUInt8: read_uint8 + , readInt8: read_int8 + , readUInt16LE: read_uint16_le + , readUInt32LE: read_uint32_le + , readInt16LE: read_int16_le + , readInt32LE: read_int32_le + , readFloatLE: read_float_le + , readDoubleLE: read_double_le + , readUInt16BE: read_uint16_be + , readUInt32BE: read_uint32_be + , readInt16BE: read_int16_be + , readInt32BE: read_int32_be + , readFloatBE: read_float_be + , readDoubleBE: read_double_be +} + +var map = require('./mapped.js') + +function read_uint8(target, at) { + return target[at] +} + +function read_int8(target, at) { + var v = target[at]; + return v < 0x80 ? v : v - 0x100 +} + +function read_uint16_le(target, at) { + var dv = map.get(target); + return dv.getUint16(at + target.byteOffset, true) +} + +function read_uint32_le(target, at) { + var dv = map.get(target); + return dv.getUint32(at + target.byteOffset, true) +} + +function read_int16_le(target, at) { + var dv = map.get(target); + return dv.getInt16(at + target.byteOffset, true) +} + +function read_int32_le(target, at) { + var dv = map.get(target); + return dv.getInt32(at + target.byteOffset, true) +} + +function read_float_le(target, at) { + var dv = map.get(target); + return dv.getFloat32(at + target.byteOffset, true) +} + +function read_double_le(target, at) { + var dv = map.get(target); + return dv.getFloat64(at + target.byteOffset, true) +} + +function read_uint16_be(target, at) { + var dv = map.get(target); + return dv.getUint16(at + target.byteOffset, false) +} + +function read_uint32_be(target, at) { + var dv = map.get(target); + return dv.getUint32(at + target.byteOffset, false) +} + +function read_int16_be(target, at) { + var dv = map.get(target); + return dv.getInt16(at + target.byteOffset, false) +} + +function read_int32_be(target, at) { + var dv = map.get(target); + return dv.getInt32(at + target.byteOffset, false) +} + +function read_float_be(target, at) { + var dv = map.get(target); + return dv.getFloat32(at + target.byteOffset, false) +} + +function read_double_be(target, at) { + var dv = map.get(target); + return dv.getFloat64(at + target.byteOffset, false) +} + +},{"./mapped.js":11}],10:[function(require,module,exports){ +module.exports = { + writeUInt8: write_uint8 + , writeInt8: write_int8 + , writeUInt16LE: write_uint16_le + , writeUInt32LE: write_uint32_le + , writeInt16LE: write_int16_le + , writeInt32LE: write_int32_le + , writeFloatLE: write_float_le + , writeDoubleLE: write_double_le + , writeUInt16BE: write_uint16_be + , writeUInt32BE: write_uint32_be + , writeInt16BE: write_int16_be + , writeInt32BE: write_int32_be + , writeFloatBE: write_float_be + , writeDoubleBE: write_double_be +} + +var map = require('./mapped.js') + +function write_uint8(target, value, at) { + return target[at] = value +} + +function write_int8(target, value, at) { + return target[at] = value < 0 ? value + 0x100 : value +} + +function write_uint16_le(target, value, at) { + var dv = map.get(target); + return dv.setUint16(at + target.byteOffset, value, true) +} + +function write_uint32_le(target, value, at) { + var dv = map.get(target); + return dv.setUint32(at + target.byteOffset, value, true) +} + +function write_int16_le(target, value, at) { + var dv = map.get(target); + return dv.setInt16(at + target.byteOffset, value, true) +} + +function write_int32_le(target, value, at) { + var dv = map.get(target); + return dv.setInt32(at + target.byteOffset, value, true) +} + +function write_float_le(target, value, at) { + var dv = map.get(target); + return dv.setFloat32(at + target.byteOffset, value, true) +} + +function write_double_le(target, value, at) { + var dv = map.get(target); + return dv.setFloat64(at + target.byteOffset, value, true) +} + +function write_uint16_be(target, value, at) { + var dv = map.get(target); + return dv.setUint16(at + target.byteOffset, value, false) +} + +function write_uint32_be(target, value, at) { + var dv = map.get(target); + return dv.setUint32(at + target.byteOffset, value, false) +} + +function write_int16_be(target, value, at) { + var dv = map.get(target); + return dv.setInt16(at + target.byteOffset, value, false) +} + +function write_int32_be(target, value, at) { + var dv = map.get(target); + return dv.setInt32(at + target.byteOffset, value, false) +} + +function write_float_be(target, value, at) { + var dv = map.get(target); + return dv.setFloat32(at + target.byteOffset, value, false) +} + +function write_double_be(target, value, at) { + var dv = map.get(target); + return dv.setFloat64(at + target.byteOffset, value, false) +} + +},{"./mapped.js":11}],11:[function(require,module,exports){ +var proto + , map + +module.exports = proto = {} + +map = typeof WeakMap === 'undefined' ? null : new WeakMap + +proto.get = !map ? no_weakmap_get : get + +function no_weakmap_get(target) { + return new DataView(target.buffer, 0) +} + +function get(target) { + var out = map.get(target.buffer) + if(!out) { + map.set(target.buffer, out = new DataView(target.buffer, 0)) + } + return out +} + +},{}],2:[function(require,module,exports){ +module.exports = from + +var base64 = require('base64-js') + +var decoders = { + hex: from_hex + , utf8: from_utf + , base64: from_base64 +} + +function from(source, encoding) { + if(Array.isArray(source)) { + return new Uint8Array(source) + } + + return decoders[encoding || 'utf8'](source) +} + +function from_hex(str) { + var size = str.length / 2 + , buf = new Uint8Array(size) + , character = '' + + for(var i = 0, len = str.length; i < len; ++i) { + character += str.charAt(i) + + if(i > 0 && (i % 2) === 1) { + buf[i>>>1] = parseInt(character, 16) + character = '' + } + } + + return buf +} + +function from_utf(str) { + var bytes = [] + , tmp + , ch + + for(var i = 0, len = str.length; i < len; ++i) { + ch = str.charCodeAt(i) + if(ch & 0x80) { + tmp = encodeURIComponent(str.charAt(i)).substr(1).split('%') + for(var j = 0, jlen = tmp.length; j < jlen; ++j) { + bytes[bytes.length] = parseInt(tmp[j], 16) + } + } else { + bytes[bytes.length] = ch + } + } + + return new Uint8Array(bytes) +} + +function from_base64(str) { + return new Uint8Array(base64.toByteArray(str)) +} + +},{"base64-js":12}],3:[function(require,module,exports){ +module.exports = to + +var base64 = require('base64-js') + , toutf8 = require('to-utf8') + +var encoders = { + hex: to_hex + , utf8: to_utf + , base64: to_base64 +} + +function to(buf, encoding) { + return encoders[encoding || 'utf8'](buf) +} + +function to_hex(buf) { + var str = '' + , byt + + for(var i = 0, len = buf.length; i < len; ++i) { + byt = buf[i] + str += ((byt & 0xF0) >>> 4).toString(16) + str += (byt & 0x0F).toString(16) + } + + return str +} + +function to_utf(buf) { + return toutf8(buf) +} + +function to_base64(buf) { + return base64.fromByteArray(buf) +} + + +},{"base64-js":12,"to-utf8":13}],12:[function(require,module,exports){ +(function (exports) { + 'use strict'; + + var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + + function b64ToByteArray(b64) { + var i, j, l, tmp, placeHolders, arr; + + if (b64.length % 4 > 0) { + throw 'Invalid string. Length must be a multiple of 4'; + } + + // the number of equal signs (place holders) + // if there are two placeholders, than the two characters before it + // represent one byte + // if there is only one, then the three characters before it represent 2 bytes + // this is just a cheap hack to not do indexOf twice + placeHolders = b64.indexOf('='); + placeHolders = placeHolders > 0 ? b64.length - placeHolders : 0; + + // base64 is 4/3 + up to two characters of the original data + arr = [];//new Uint8Array(b64.length * 3 / 4 - placeHolders); + + // if there are placeholders, only get up to the last complete 4 chars + l = placeHolders > 0 ? b64.length - 4 : b64.length; + + for (i = 0, j = 0; i < l; i += 4, j += 3) { + tmp = (lookup.indexOf(b64[i]) << 18) | (lookup.indexOf(b64[i + 1]) << 12) | (lookup.indexOf(b64[i + 2]) << 6) | lookup.indexOf(b64[i + 3]); + arr.push((tmp & 0xFF0000) >> 16); + arr.push((tmp & 0xFF00) >> 8); + arr.push(tmp & 0xFF); + } + + if (placeHolders === 2) { + tmp = (lookup.indexOf(b64[i]) << 2) | (lookup.indexOf(b64[i + 1]) >> 4); + arr.push(tmp & 0xFF); + } else if (placeHolders === 1) { + tmp = (lookup.indexOf(b64[i]) << 10) | (lookup.indexOf(b64[i + 1]) << 4) | (lookup.indexOf(b64[i + 2]) >> 2); + arr.push((tmp >> 8) & 0xFF); + arr.push(tmp & 0xFF); + } + + return arr; + } + + function uint8ToBase64(uint8) { + var i, + extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes + output = "", + temp, length; + + function tripletToBase64 (num) { + return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]; + }; + + // go through the array every three bytes, we'll deal with trailing stuff later + for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { + temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]); + output += tripletToBase64(temp); + } + + // pad the end with zeros, but make sure to not forget the extra bytes + switch (extraBytes) { + case 1: + temp = uint8[uint8.length - 1]; + output += lookup[temp >> 2]; + output += lookup[(temp << 4) & 0x3F]; + output += '=='; + break; + case 2: + temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]); + output += lookup[temp >> 10]; + output += lookup[(temp >> 4) & 0x3F]; + output += lookup[(temp << 2) & 0x3F]; + output += '='; + break; + } + + return output; + } + + module.exports.toByteArray = b64ToByteArray; + module.exports.fromByteArray = uint8ToBase64; +}()); + +},{}],13:[function(require,module,exports){ +module.exports = to_utf8 + +var out = [] + , col = [] + , fcc = String.fromCharCode + , mask = [0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01] + , unmask = [ + 0x00 + , 0x01 + , 0x02 | 0x01 + , 0x04 | 0x02 | 0x01 + , 0x08 | 0x04 | 0x02 | 0x01 + , 0x10 | 0x08 | 0x04 | 0x02 | 0x01 + , 0x20 | 0x10 | 0x08 | 0x04 | 0x02 | 0x01 + , 0x40 | 0x20 | 0x10 | 0x08 | 0x04 | 0x02 | 0x01 + ] + +function to_utf8(bytes, start, end) { + start = start === undefined ? 0 : start + end = end === undefined ? bytes.length : end + + var idx = 0 + , hi = 0x80 + , collecting = 0 + , pos + , by + + col.length = + out.length = 0 + + while(idx < bytes.length) { + by = bytes[idx] + if(!collecting && by & hi) { + pos = find_pad_position(by) + collecting += pos + if(pos < 8) { + col[col.length] = by & unmask[6 - pos] + } + } else if(collecting) { + col[col.length] = by & unmask[6] + --collecting + if(!collecting && col.length) { + out[out.length] = fcc(reduced(col, pos)) + col.length = 0 + } + } else { + out[out.length] = fcc(by) + } + ++idx + } + if(col.length && !collecting) { + out[out.length] = fcc(reduced(col, pos)) + col.length = 0 + } + return out.join('') +} + +function find_pad_position(byt) { + for(var i = 0; i < 7; ++i) { + if(!(byt & mask[i])) { + break + } + } + return i +} + +function reduced(list) { + var out = 0 + for(var i = 0, len = list.length; i < len; ++i) { + out |= list[i] << ((len - i - 1) * 6) + } + return out +} + +},{}]},{},[1])(1) +}); +; \ No newline at end of file diff --git a/externals/crossroads.js b/externals/crossroads.js new file mode 100644 index 000000000..ee9330088 --- /dev/null +++ b/externals/crossroads.js @@ -0,0 +1,723 @@ +/** @license + * crossroads + * Author: Miller Medeiros | MIT License + * v0.12.2 (2015/07/31 18:37) + */ + +(function () { +var factory = function (signals) { + + var crossroads, + _hasOptionalGroupBug, + UNDEF; + + // Helpers ----------- + //==================== + + // IE 7-8 capture optional groups as empty strings while other browsers + // capture as `undefined` + _hasOptionalGroupBug = (/t(.+)?/).exec('t')[1] === ''; + + function arrayIndexOf(arr, val) { + if (arr.indexOf) { + return arr.indexOf(val); + } else { + //Array.indexOf doesn't work on IE 6-7 + var n = arr.length; + while (n--) { + if (arr[n] === val) { + return n; + } + } + return -1; + } + } + + function arrayRemove(arr, item) { + var i = arrayIndexOf(arr, item); + if (i !== -1) { + arr.splice(i, 1); + } + } + + function isKind(val, kind) { + return '[object '+ kind +']' === Object.prototype.toString.call(val); + } + + function isRegExp(val) { + return isKind(val, 'RegExp'); + } + + function isArray(val) { + return isKind(val, 'Array'); + } + + function isFunction(val) { + return typeof val === 'function'; + } + + //borrowed from AMD-utils + function typecastValue(val) { + var r; + if (val === null || val === 'null') { + r = null; + } else if (val === 'true') { + r = true; + } else if (val === 'false') { + r = false; + } else if (val === UNDEF || val === 'undefined') { + r = UNDEF; + } else if (val === '' || isNaN(val)) { + r = val; + } else { + r = parseFloat(val); + } + return r; + } + + function typecastArrayValues(values) { + var n = values.length, + result = []; + while (n--) { + result[n] = typecastValue(values[n]); + } + return result; + } + + // borrowed from MOUT + function decodeQueryString(queryStr, shouldTypecast) { + var queryArr = (queryStr || '').replace('?', '').split('&'), + reg = /([^=]+)=(.+)/, + i = -1, + obj = {}, + equalIndex, cur, pValue, pName; + + while ((cur = queryArr[++i])) { + equalIndex = cur.indexOf('='); + pName = cur.substring(0, equalIndex); + pValue = decodeURIComponent(cur.substring(equalIndex + 1)); + if (shouldTypecast !== false) { + pValue = typecastValue(pValue); + } + if (pName in obj){ + if(isArray(obj[pName])){ + obj[pName].push(pValue); + } else { + obj[pName] = [obj[pName], pValue]; + } + } else { + obj[pName] = pValue; + } + } + return obj; + } + + + // Crossroads -------- + //==================== + + /** + * @constructor + */ + function Crossroads() { + this.bypassed = new signals.Signal(); + this.routed = new signals.Signal(); + this._routes = []; + this._prevRoutes = []; + this._piped = []; + this.resetState(); + } + + Crossroads.prototype = { + + greedy : false, + + greedyEnabled : true, + + ignoreCase : true, + + ignoreState : false, + + shouldTypecast : false, + + normalizeFn : null, + + resetState : function(){ + this._prevRoutes.length = 0; + this._prevMatchedRequest = null; + this._prevBypassedRequest = null; + }, + + create : function () { + return new Crossroads(); + }, + + addRoute : function (pattern, callback, priority) { + var route = new Route(pattern, callback, priority, this); + this._sortedInsert(route); + return route; + }, + + removeRoute : function (route) { + arrayRemove(this._routes, route); + route._destroy(); + }, + + removeAllRoutes : function () { + var n = this.getNumRoutes(); + while (n--) { + this._routes[n]._destroy(); + } + this._routes.length = 0; + }, + + parse : function (request, defaultArgs) { + request = request || ''; + defaultArgs = defaultArgs || []; + + // should only care about different requests if ignoreState isn't true + if ( !this.ignoreState && + (request === this._prevMatchedRequest || + request === this._prevBypassedRequest) ) { + return; + } + + var routes = this._getMatchedRoutes(request), + i = 0, + n = routes.length, + cur; + + if (n) { + this._prevMatchedRequest = request; + + this._notifyPrevRoutes(routes, request); + this._prevRoutes = routes; + //should be incremental loop, execute routes in order + while (i < n) { + cur = routes[i]; + cur.route.matched.dispatch.apply(cur.route.matched, defaultArgs.concat(cur.params)); + cur.isFirst = !i; + this.routed.dispatch.apply(this.routed, defaultArgs.concat([request, cur])); + i += 1; + } + } else { + this._prevBypassedRequest = request; + this.bypassed.dispatch.apply(this.bypassed, defaultArgs.concat([request])); + } + + this._pipeParse(request, defaultArgs); + }, + + _notifyPrevRoutes : function(matchedRoutes, request) { + var i = 0, prev; + while (prev = this._prevRoutes[i++]) { + //check if switched exist since route may be disposed + if(prev.route.switched && this._didSwitch(prev.route, matchedRoutes)) { + prev.route.switched.dispatch(request); + } + } + }, + + _didSwitch : function (route, matchedRoutes){ + var matched, + i = 0; + while (matched = matchedRoutes[i++]) { + // only dispatch switched if it is going to a different route + if (matched.route === route) { + return false; + } + } + return true; + }, + + _pipeParse : function(request, defaultArgs) { + var i = 0, route; + while (route = this._piped[i++]) { + route.parse(request, defaultArgs); + } + }, + + getNumRoutes : function () { + return this._routes.length; + }, + + _sortedInsert : function (route) { + //simplified insertion sort + var routes = this._routes, + n = routes.length; + do { --n; } while (routes[n] && route._priority <= routes[n]._priority); + routes.splice(n+1, 0, route); + }, + + _getMatchedRoutes : function (request) { + var res = [], + routes = this._routes, + n = routes.length, + route; + //should be decrement loop since higher priorities are added at the end of array + while (route = routes[--n]) { + if ((!res.length || this.greedy || route.greedy) && route.match(request)) { + res.push({ + route : route, + params : route._getParamsArray(request) + }); + } + if (!this.greedyEnabled && res.length) { + break; + } + } + return res; + }, + + pipe : function (otherRouter) { + this._piped.push(otherRouter); + }, + + unpipe : function (otherRouter) { + arrayRemove(this._piped, otherRouter); + }, + + toString : function () { + return '[crossroads numRoutes:'+ this.getNumRoutes() +']'; + } + }; + + //"static" instance + crossroads = new Crossroads(); + crossroads.VERSION = '0.12.2'; + + crossroads.NORM_AS_ARRAY = function (req, vals) { + return [vals.vals_]; + }; + + crossroads.NORM_AS_OBJECT = function (req, vals) { + return [vals]; + }; + + + // Route -------------- + //===================== + + /** + * @constructor + */ + function Route(pattern, callback, priority, router) { + var isRegexPattern = isRegExp(pattern), + patternLexer = router.patternLexer; + this._router = router; + this._pattern = pattern; + this._paramsIds = isRegexPattern? null : patternLexer.getParamIds(pattern); + this._optionalParamsIds = isRegexPattern? null : patternLexer.getOptionalParamsIds(pattern); + this._matchRegexp = isRegexPattern? pattern : patternLexer.compilePattern(pattern, router.ignoreCase); + this.matched = new signals.Signal(); + this.switched = new signals.Signal(); + if (callback) { + this.matched.add(callback); + } + this._priority = priority || 0; + } + + Route.prototype = { + + greedy : false, + + rules : void(0), + + match : function (request) { + request = request || ''; + return this._matchRegexp.test(request) && this._validateParams(request); //validate params even if regexp because of `request_` rule. + }, + + _validateParams : function (request) { + var rules = this.rules, + values = this._getParamsObject(request), + key; + for (key in rules) { + // normalize_ isn't a validation rule... (#39) + if(key !== 'normalize_' && rules.hasOwnProperty(key) && ! this._isValidParam(request, key, values)){ + return false; + } + } + return true; + }, + + _isValidParam : function (request, prop, values) { + var validationRule = this.rules[prop], + val = values[prop], + isValid = false, + isQuery = (prop.indexOf('?') === 0); + + if (val == null && this._optionalParamsIds && arrayIndexOf(this._optionalParamsIds, prop) !== -1) { + isValid = true; + } + else if (isRegExp(validationRule)) { + if (isQuery) { + val = values[prop +'_']; //use raw string + } + isValid = validationRule.test(val); + } + else if (isArray(validationRule)) { + if (isQuery) { + val = values[prop +'_']; //use raw string + } + isValid = this._isValidArrayRule(validationRule, val); + } + else if (isFunction(validationRule)) { + isValid = validationRule(val, request, values); + } + + return isValid; //fail silently if validationRule is from an unsupported type + }, + + _isValidArrayRule : function (arr, val) { + if (! this._router.ignoreCase) { + return arrayIndexOf(arr, val) !== -1; + } + + if (typeof val === 'string') { + val = val.toLowerCase(); + } + + var n = arr.length, + item, + compareVal; + + while (n--) { + item = arr[n]; + compareVal = (typeof item === 'string')? item.toLowerCase() : item; + if (compareVal === val) { + return true; + } + } + return false; + }, + + _getParamsObject : function (request) { + var shouldTypecast = this._router.shouldTypecast, + values = this._router.patternLexer.getParamValues(request, this._matchRegexp, shouldTypecast), + o = {}, + n = values.length, + param, val; + while (n--) { + val = values[n]; + if (this._paramsIds) { + param = this._paramsIds[n]; + if (param.indexOf('?') === 0 && val) { + //make a copy of the original string so array and + //RegExp validation can be applied properly + o[param +'_'] = val; + //update vals_ array as well since it will be used + //during dispatch + val = decodeQueryString(val, shouldTypecast); + values[n] = val; + } + // IE will capture optional groups as empty strings while other + // browsers will capture `undefined` so normalize behavior. + // see: #gh-58, #gh-59, #gh-60 + if ( _hasOptionalGroupBug && val === '' && arrayIndexOf(this._optionalParamsIds, param) !== -1 ) { + val = void(0); + values[n] = val; + } + o[param] = val; + } + //alias to paths and for RegExp pattern + o[n] = val; + } + o.request_ = shouldTypecast? typecastValue(request) : request; + o.vals_ = values; + return o; + }, + + _getParamsArray : function (request) { + var norm = this.rules? this.rules.normalize_ : null, + params; + norm = norm || this._router.normalizeFn; // default normalize + if (norm && isFunction(norm)) { + params = norm(request, this._getParamsObject(request)); + } else { + params = this._getParamsObject(request).vals_; + } + return params; + }, + + interpolate : function(replacements) { + var str = this._router.patternLexer.interpolate(this._pattern, replacements); + if (! this._validateParams(str) ) { + throw new Error('Generated string doesn\'t validate against `Route.rules`.'); + } + return str; + }, + + dispose : function () { + this._router.removeRoute(this); + }, + + _destroy : function () { + this.matched.dispose(); + this.switched.dispose(); + this.matched = this.switched = this._pattern = this._matchRegexp = null; + }, + + toString : function () { + return '[Route pattern:"'+ this._pattern +'", numListeners:'+ this.matched.getNumListeners() +']'; + } + + }; + + + + // Pattern Lexer ------ + //===================== + + Crossroads.prototype.patternLexer = (function () { + + var + //match chars that should be escaped on string regexp + ESCAPE_CHARS_REGEXP = /[\\.+*?\^$\[\](){}\/'#]/g, + + //trailing slashes (begin/end of string) + LOOSE_SLASHES_REGEXP = /^\/|\/$/g, + LEGACY_SLASHES_REGEXP = /\/$/g, + + //params - everything between `{ }` or `: :` + PARAMS_REGEXP = /(?:\{|:)([^}:]+)(?:\}|:)/g, + + //used to save params during compile (avoid escaping things that + //shouldn't be escaped). + TOKENS = { + 'OS' : { + //optional slashes + //slash between `::` or `}:` or `\w:` or `:{?` or `}{?` or `\w{?` + rgx : /([:}]|\w(?=\/))\/?(:|(?:\{\?))/g, + save : '$1{{id}}$2', + res : '\\/?' + }, + 'RS' : { + //required slashes + //used to insert slash between `:{` and `}{` + rgx : /([:}])\/?(\{)/g, + save : '$1{{id}}$2', + res : '\\/' + }, + 'RQ' : { + //required query string - everything in between `{? }` + rgx : /\{\?([^}]+)\}/g, + //everything from `?` till `#` or end of string + res : '\\?([^#]+)' + }, + 'OQ' : { + //optional query string - everything in between `:? :` + rgx : /:\?([^:]+):/g, + //everything from `?` till `#` or end of string + res : '(?:\\?([^#]*))?' + }, + 'OR' : { + //optional rest - everything in between `: *:` + rgx : /:([^:]+)\*:/g, + res : '(.*)?' // optional group to avoid passing empty string as captured + }, + 'RR' : { + //rest param - everything in between `{ *}` + rgx : /\{([^}]+)\*\}/g, + res : '(.+)' + }, + // required/optional params should come after rest segments + 'RP' : { + //required params - everything between `{ }` + rgx : /\{([^}]+)\}/g, + res : '([^\\/?]+)' + }, + 'OP' : { + //optional params - everything between `: :` + rgx : /:([^:]+):/g, + res : '([^\\/?]+)?\/?' + } + }, + + LOOSE_SLASH = 1, + STRICT_SLASH = 2, + LEGACY_SLASH = 3, + + _slashMode = LOOSE_SLASH; + + + function precompileTokens(){ + var key, cur; + for (key in TOKENS) { + if (TOKENS.hasOwnProperty(key)) { + cur = TOKENS[key]; + cur.id = '__CR_'+ key +'__'; + cur.save = ('save' in cur)? cur.save.replace('{{id}}', cur.id) : cur.id; + cur.rRestore = new RegExp(cur.id, 'g'); + } + } + } + precompileTokens(); + + + function captureVals(regex, pattern) { + var vals = [], match; + // very important to reset lastIndex since RegExp can have "g" flag + // and multiple runs might affect the result, specially if matching + // same string multiple times on IE 7-8 + regex.lastIndex = 0; + while (match = regex.exec(pattern)) { + vals.push(match[1]); + } + return vals; + } + + function getParamIds(pattern) { + return captureVals(PARAMS_REGEXP, pattern); + } + + function getOptionalParamsIds(pattern) { + return captureVals(TOKENS.OP.rgx, pattern); + } + + function compilePattern(pattern, ignoreCase) { + pattern = pattern || ''; + + if(pattern){ + if (_slashMode === LOOSE_SLASH) { + pattern = pattern.replace(LOOSE_SLASHES_REGEXP, ''); + } + else if (_slashMode === LEGACY_SLASH) { + pattern = pattern.replace(LEGACY_SLASHES_REGEXP, ''); + } + + //save tokens + pattern = replaceTokens(pattern, 'rgx', 'save'); + //regexp escape + pattern = pattern.replace(ESCAPE_CHARS_REGEXP, '\\$&'); + //restore tokens + pattern = replaceTokens(pattern, 'rRestore', 'res'); + + if (_slashMode === LOOSE_SLASH) { + pattern = '\\/?'+ pattern; + } + } + + if (_slashMode !== STRICT_SLASH) { + //single slash is treated as empty and end slash is optional + pattern += '\\/?'; + } + return new RegExp('^'+ pattern + '$', ignoreCase? 'i' : ''); + } + + function replaceTokens(pattern, regexpName, replaceName) { + var cur, key; + for (key in TOKENS) { + if (TOKENS.hasOwnProperty(key)) { + cur = TOKENS[key]; + pattern = pattern.replace(cur[regexpName], cur[replaceName]); + } + } + return pattern; + } + + function getParamValues(request, regexp, shouldTypecast) { + var vals = regexp.exec(request); + if (vals) { + vals.shift(); + if (shouldTypecast) { + vals = typecastArrayValues(vals); + } + } + return vals; + } + + function interpolate(pattern, replacements) { + // default to an empty object because pattern might have just + // optional arguments + replacements = replacements || {}; + if (typeof pattern !== 'string') { + throw new Error('Route pattern should be a string.'); + } + + var replaceFn = function(match, prop){ + var val; + prop = (prop.substr(0, 1) === '?')? prop.substr(1) : prop; + if (replacements[prop] != null) { + if (typeof replacements[prop] === 'object') { + var queryParts = [], rep; + for(var key in replacements[prop]) { + rep = replacements[prop][key]; + if (isArray(rep)) { + for (var k in rep) { + if ( key.slice(-2) == '[]' ) { + queryParts.push(encodeURI(key.slice(0, -2)) + '[]=' + encodeURI(rep[k])); + } else { + queryParts.push(encodeURI(key + '=' + rep[k])); + } + } + } + else { + queryParts.push(encodeURI(key + '=' + rep)); + } + } + val = '?' + queryParts.join('&'); + } else { + // make sure value is a string see #gh-54 + val = String(replacements[prop]); + } + + if (match.indexOf('*') === -1 && val.indexOf('/') !== -1) { + throw new Error('Invalid value "'+ val +'" for segment "'+ match +'".'); + } + } + else if (match.indexOf('{') !== -1) { + throw new Error('The segment '+ match +' is required.'); + } + else { + val = ''; + } + return val; + }; + + if (! TOKENS.OS.trail) { + TOKENS.OS.trail = new RegExp('(?:'+ TOKENS.OS.id +')+$'); + } + + return pattern + .replace(TOKENS.OS.rgx, TOKENS.OS.save) + .replace(PARAMS_REGEXP, replaceFn) + .replace(TOKENS.OS.trail, '') // remove trailing + .replace(TOKENS.OS.rRestore, '/'); // add slash between segments + } + + //API + return { + strict : function(){ + _slashMode = STRICT_SLASH; + }, + loose : function(){ + _slashMode = LOOSE_SLASH; + }, + legacy : function(){ + _slashMode = LEGACY_SLASH; + }, + getParamIds : getParamIds, + getOptionalParamsIds : getOptionalParamsIds, + getParamValues : getParamValues, + compilePattern : compilePattern, + interpolate : interpolate + }; + + }()); + + + return crossroads; +}; + +if (typeof define === 'function' && define.amd) { + define(['signals'], factory); +} else if (typeof module !== 'undefined' && module.exports) { //Node + module.exports = factory(require('signals')); +} else { + /*jshint sub:true */ + window['crossroads'] = factory(window['signals']); +} + +}()); + diff --git a/externals/dataTables.colReorder.js b/externals/dataTables.colReorder.js new file mode 100644 index 000000000..e282189da --- /dev/null +++ b/externals/dataTables.colReorder.js @@ -0,0 +1,1254 @@ +/*! ColReorder 1.2.0 + * ©2010-2014 SpryMedia Ltd - datatables.net/license + */ + +/** + * @summary ColReorder + * @description Provide the ability to reorder columns in a DataTable + * @version 1.2.0 + * @file dataTables.colReorder.js + * @author SpryMedia Ltd (www.sprymedia.co.uk) + * @contact www.sprymedia.co.uk/contact + * @copyright Copyright 2010-2014 SpryMedia Ltd. + * + * This source file is free software, available under the following license: + * MIT license - http://datatables.net/license/mit + * + * This source file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details. + * + * For details please refer to: http://www.datatables.net + */ + +(function(window, document, undefined) { + + +/** + * Switch the key value pairing of an index array to be value key (i.e. the old value is now the + * key). For example consider [ 2, 0, 1 ] this would be returned as [ 1, 2, 0 ]. + * @method fnInvertKeyValues + * @param array aIn Array to switch around + * @returns array + */ +function fnInvertKeyValues( aIn ) +{ + var aRet=[]; + for ( var i=0, iLen=aIn.length ; i= iCols ) + { + this.oApi._fnLog( oSettings, 1, "ColReorder 'from' index is out of bounds: "+iFrom ); + return; + } + + if ( iTo < 0 || iTo >= iCols ) + { + this.oApi._fnLog( oSettings, 1, "ColReorder 'to' index is out of bounds: "+iTo ); + return; + } + + /* + * Calculate the new column array index, so we have a mapping between the old and new + */ + var aiMapping = []; + for ( i=0, iLen=iCols ; i this.s.fixed-1 && i < iLen - this.s.fixedRight ) + { + this._fnMouseListener( i, this.s.dt.aoColumns[i].nTh ); + } + + /* Mark the original column order for later reference */ + this.s.dt.aoColumns[i]._ColReorder_iOrigCol = i; + } + + /* State saving */ + this.s.dt.oApi._fnCallbackReg( this.s.dt, 'aoStateSaveParams', function (oS, oData) { + that._fnStateSave.call( that, oData ); + }, "ColReorder_State" ); + + /* An initial column order has been specified */ + var aiOrder = null; + if ( this.s.init.aiOrder ) + { + aiOrder = this.s.init.aiOrder.slice(); + } + + /* State loading, overrides the column order given */ + if ( this.s.dt.oLoadedState && typeof this.s.dt.oLoadedState.ColReorder != 'undefined' && + this.s.dt.oLoadedState.ColReorder.length == this.s.dt.aoColumns.length ) + { + aiOrder = this.s.dt.oLoadedState.ColReorder; + } + + /* If we have an order to apply - do so */ + if ( aiOrder ) + { + /* We might be called during or after the DataTables initialisation. If before, then we need + * to wait until the draw is done, if after, then do what we need to do right away + */ + if ( !that.s.dt._bInitComplete ) + { + var bDone = false; + $(table).on( 'draw.dt.colReorder', function () { + if ( !that.s.dt._bInitComplete && !bDone ) + { + bDone = true; + var resort = fnInvertKeyValues( aiOrder ); + that._fnOrderColumns.call( that, resort ); + } + } ); + } + else + { + var resort = fnInvertKeyValues( aiOrder ); + that._fnOrderColumns.call( that, resort ); + } + } + else { + this._fnSetColumnIndexes(); + } + + // Destroy clean up + $(table).on( 'destroy.dt.colReorder', function () { + $(table).off( 'destroy.dt.colReorder draw.dt.colReorder' ); + $(that.s.dt.nTHead).find( '*' ).off( '.ColReorder' ); + + $.each( that.s.dt.aoColumns, function (i, column) { + $(column.nTh).removeAttr('data-column-index'); + } ); + + that.s.dt._colReorder = null; + that.s = null; + } ); + }, + + + /** + * Set the column order from an array + * @method _fnOrderColumns + * @param array a An array of integers which dictate the column order that should be applied + * @returns void + * @private + */ + "_fnOrderColumns": function ( a ) + { + if ( a.length != this.s.dt.aoColumns.length ) + { + this.s.dt.oInstance.oApi._fnLog( this.s.dt, 1, "ColReorder - array reorder does not "+ + "match known number of columns. Skipping." ); + return; + } + + for ( var i=0, iLen=a.length ; i') + .addClass( 'DTCR_pointer' ) + .css( { + position: 'absolute', + top: scrolling ? + $('div.dataTables_scroll', this.s.dt.nTableWrapper).offset().top : + $(this.s.dt.nTable).offset().top, + height : scrolling ? + $('div.dataTables_scroll', this.s.dt.nTableWrapper).height() : + $(this.s.dt.nTable).height() + } ) + .appendTo( 'body' ); + }, + + + /** + * Add a data attribute to the column headers, so we know the index of + * the row to be reordered. This allows fast detection of the index, and + * for this plug-in to work with FixedHeader which clones the nodes. + * @private + */ + "_fnSetColumnIndexes": function () + { + $.each( this.s.dt.aoColumns, function (i, column) { + $(column.nTh).attr('data-column-index', i); + } ); + } +}; + + + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Static parameters + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + +/** + * ColReorder default settings for initialisation + * @namespace + * @static + */ +ColReorder.defaults = { + /** + * Predefined ordering for the columns that will be applied automatically + * on initialisation. If not specified then the order that the columns are + * found to be in the HTML is the order used. + * @type array + * @default null + * @static + */ + aiOrder: null, + + /** + * Redraw the table's column ordering as the end user draws the column + * (`true`) or wait until the mouse is released (`false` - default). Note + * that this will perform a redraw on each reordering, which involves an + * Ajax request each time if you are using server-side processing in + * DataTables. + * @type boolean + * @default false + * @static + */ + bRealtime: true, + + /** + * Indicate how many columns should be fixed in position (counting from the + * left). This will typically be 1 if used, but can be as high as you like. + * @type int + * @default 0 + * @static + */ + iFixedColumnsLeft: 0, + + /** + * As `iFixedColumnsRight` but counting from the right. + * @type int + * @default 0 + * @static + */ + iFixedColumnsRight: 0, + + /** + * Callback function that is fired when columns are reordered. The `column- + * reorder` event is preferred over this callback + * @type function():void + * @default null + * @static + */ + fnReorderCallback: null +}; + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Constants + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/** + * ColReorder version + * @constant version + * @type String + * @default As code + */ +ColReorder.version = "1.2.0"; + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables interfaces + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +// Expose +$.fn.dataTable.ColReorder = ColReorder; +$.fn.DataTable.ColReorder = ColReorder; + + +// Register a new feature with DataTables +if ( typeof $.fn.dataTable == "function" && + typeof $.fn.dataTableExt.fnVersionCheck == "function" && + $.fn.dataTableExt.fnVersionCheck('1.10.8') ) +{ + $.fn.dataTableExt.aoFeatures.push( { + "fnInit": function( settings ) { + var table = settings.oInstance; + + if ( ! settings._colReorder ) { + var dtInit = settings.oInit; + var opts = dtInit.colReorder || dtInit.oColReorder || {}; + + new ColReorder( settings, opts ); + } + else { + table.oApi._fnLog( settings, 1, "ColReorder attempted to initialise twice. Ignoring second" ); + } + + return null; /* No node for DataTables to insert */ + }, + "cFeature": "R", + "sFeature": "ColReorder" + } ); +} +else { + alert( "Warning: ColReorder requires DataTables 1.10.8 or greater - www.datatables.net/download"); +} + + +// Attach a listener to the document which listens for DataTables initialisation +// events so we can automatically initialise +$(document).on( 'preInit.dt.colReorder', function (e, settings) { + if ( e.namespace !== 'dt' ) { + return; + } + + var init = settings.oInit.colReorder; + var defaults = DataTable.defaults.colReorder; + + if ( init || defaults ) { + var opts = $.extend( {}, init, defaults ); + + if ( init !== false ) { + new ColReorder( settings, opts ); + } + } +} ); + + +// API augmentation +$.fn.dataTable.Api.register( 'colReorder.reset()', function () { + return this.iterator( 'table', function ( ctx ) { + ctx._colReorder.fnReset(); + } ); +} ); + +$.fn.dataTable.Api.register( 'colReorder.order()', function ( set ) { + if ( set ) { + return this.iterator( 'table', function ( ctx ) { + ctx._colReorder.fnOrder( set ); + } ); + } + + return this.context.length ? + this.context[0]._colReorder.fnOrder() : + null; +} ); + + +return ColReorder; +}; // /factory + + +// Define as an AMD module if possible +if ( typeof define === 'function' && define.amd ) { + define( ['jquery', 'datatables'], factory ); +} +else if ( typeof exports === 'object' ) { + // Node/CommonJS + factory( require('jquery'), require('datatables') ); +} +else if ( jQuery && !jQuery.fn.dataTable.ColReorder ) { + // Otherwise simply initialise as normal, stopping multiple evaluation + factory( jQuery, jQuery.fn.dataTable ); +} + + +})(window, document); diff --git a/externals/dataTables.colResize.js b/externals/dataTables.colResize.js new file mode 100644 index 000000000..052c67927 --- /dev/null +++ b/externals/dataTables.colResize.js @@ -0,0 +1,846 @@ +/*! ColResize 0.0.10 + */ + +/** + * @summary ColResize + * @description Provide the ability to resize columns in a DataTable + * @version 0.0.10 + * @file dataTables.colResize.js + * @author Silvacom Ltd. + * + * For details please refer to: http://www.datatables.net + * + * Special thank to everyone who has contributed to this plug in + * - dykstrad + * - tdillan (for 0.0.3 and 0.0.5 bug fixes) + * - kylealonius (for 0.0.8 bug fix) + * - the86freak (for 0.0.9 bug fix) + */ + +(function (window, document, undefined) { + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables plug-in API functions test + * + * This are required by ColResize in order to perform the tasks required, and also keep this + * code portable, to be used for other column resize projects with DataTables, if needed. + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + var factory = function ($, DataTable) { + "use strict"; + + /** + * Plug-in for DataTables which will resize the columns depending on the handle clicked + * @method $.fn.dataTableExt.oApi.fnColResize + * @param object oSettings DataTables settings object - automatically added by DataTables! + * @param int iCol Take the column to be resized + * @returns void + */ + $.fn.dataTableExt.oApi.fnColResize = function (oSettings, iCol) { + var v110 = $.fn.dataTable.Api ? true : false; + + /* + * Update DataTables' event handlers + */ + + /* Fire an event so other plug-ins can update */ + $(oSettings.oInstance).trigger('column-resize', [ oSettings, { + "iCol": iCol + } ]); + }; + + /** + * ColResize provides column resize control for DataTables + * @class ColResize + * @constructor + * @param {object} dt DataTables settings object + * @param {object} opts ColResize options + */ + var ColResize = function (dt, opts) { + var oDTSettings; + + if ($.fn.dataTable.Api) { + oDTSettings = new $.fn.dataTable.Api(dt).settings()[0]; + } + // 1.9 compatibility + else if (dt.fnSettings) { + // DataTables object, convert to the settings object + oDTSettings = dt.fnSettings(); + } + else if (typeof dt === 'string') { + // jQuery selector + if ($.fn.dataTable.fnIsDataTable($(dt)[0])) { + oDTSettings = $(dt).eq(0).dataTable().fnSettings(); + } + } + else if (dt.nodeName && dt.nodeName.toLowerCase() === 'table') { + // Table node + if ($.fn.dataTable.fnIsDataTable(dt.nodeName)) { + oDTSettings = $(dt.nodeName).dataTable().fnSettings(); + } + } + else if (dt instanceof jQuery) { + // jQuery object + if ($.fn.dataTable.fnIsDataTable(dt[0])) { + oDTSettings = dt.eq(0).dataTable().fnSettings(); + } + } + else { + // DataTables settings object + oDTSettings = dt; + } + + // Convert from camelCase to Hungarian, just as DataTables does + if ($.fn.dataTable.camelToHungarian) { + $.fn.dataTable.camelToHungarian(ColResize.defaults, opts || {}); + } + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Public class variables + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + /** + * @namespace Settings object which contains customizable information for ColResize instance + */ + this.s = { + /** + * DataTables settings object + * @property dt + * @type Object + * @default null + */ + "dt": null, + + /** + * Initialisation object used for this instance + * @property init + * @type object + * @default {} + */ + "init": $.extend(true, {}, ColResize.defaults, opts), + + /** + * @namespace Information used for the mouse drag + */ + "mouse": { + "startX": -1, + "startY": -1, + "targetIndex": -1, + "targetColumn": -1, + "neighbourIndex": -1, + "neighbourColumn": -1 + }, + + /** + * Status variable keeping track of mouse down status + * @property isMousedown + * @type boolean + * @default false + */ + "isMousedown": false + }; + + + /** + * @namespace Common and useful DOM elements for the class instance + */ + this.dom = { + /** + * Resizing element (the one the mouse is resizing) + * @property resize + * @type element + * @default null + */ + "resizeCol": null, + + /** + * Resizing element neighbour (the column next to the one the mouse is resizing) + * This is for fixed table resizing. + * @property resize + * @type element + * @default null + */ + "resizeColNeighbour": null, + + /** + * Array of events to be restored, used for overriding existing events from other plugins for a time. + * @property restoreEvents + * @type array + * @default [] + */ + "restoreEvents": [] + }; + + + /* Constructor logic */ + this.s.dt = oDTSettings.oInstance.fnSettings(); + this.s.dt._colResize = this; + this._fnConstruct(); + + /* Add destroy callback */ + oDTSettings.oApi._fnCallbackReg(oDTSettings, 'aoDestroyCallback', $.proxy(this._fnDestroy, this), 'ColResize'); + + return this; + }; + + + ColResize.prototype = { + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Public methods + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + /** + * Reset the column widths to the original widths that was detected on + * start up. + * @return {this} Returns `this` for chaining. + * + * @example + * // DataTables initialisation with ColResize + * var table = $('#example').dataTable( { + * "sDom": 'Zlfrtip' + * } ); + * + * // Add click event to a button to reset the ordering + * $('#resetOrdering').click( function (e) { + * e.preventDefault(); + * $.fn.dataTable.ColResize( table ).fnReset(); + * } ); + */ + "fnReset": function () { + var a = []; + for (var i = 0, iLen = this.s.dt.aoColumns.length; i < iLen; i++) { + this.s.dt.aoColumns[i].width = this.s.dt.aoColumns[i]._ColResize_iOrigWidth; + } + + this.s.dt.adjust().draw(); + + return this; + }, + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Private methods (they are of course public in JS, but recommended as private) + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + /** + * Constructor logic + * @method _fnConstruct + * @returns void + * @private + */ + "_fnConstruct": function () { + var that = this; + var iLen = that.s.dt.aoColumns.length; + var i; + + that._fnSetupMouseListeners(); + + /* Add event handlers for the resize handles */ + for (i = 0; i < iLen; i++) { + /* Mark the original column width for later reference */ + this.s.dt.aoColumns[i]._ColResize_iOrigWidth = this.s.dt.aoColumns[i].width; + } + + this._fnSetColumnIndexes(); + + /* State saving */ + this.s.dt.oApi._fnCallbackReg( this.s.dt, 'aoStateSaveParams', function (oS, oData) { + that._fnStateSave.call(that, oData); + }, "ColResize_State" ); + + // State loading + this._fnStateLoad(); + }, + + /** + * @method _fnStateSave + * @param object oState DataTables state + * @private + */ + "_fnStateSave": function (oState) { + this.s.dt.aoColumns.forEach(function(col, index) { + oState.columns[index].width = col.sWidthOrig; + }); + }, + + /** + * If state has been loaded, apply the saved widths to the columns + * @method _fnStateLoad + * @private + */ + "_fnStateLoad": function() { + var that = this, + loadedState = this.s.dt.oLoadedState; + if (loadedState && loadedState.columns) { + var colStates = loadedState.columns, + currCols = this.s.dt.aoColumns; + // Only apply the saved widths if the number of columns is the same. + // Otherwise, we don't know if we're applying the width to the correct column. + if (colStates.length > 0 && colStates.length === currCols.length) { + colStates.forEach(function(state, index) { + var col = that.s.dt.aoColumns[index]; + if (state.width) { + col.sWidthOrig = col.sWidth = state.width; + } + }); + } + } + }, + + /** + * Remove events of type from obj add it to restoreEvents array to be restored at a later time + * @param until string flag when to restore the event + * @param obj Object to remove events from + * @param type type of event to remove + * @param namespace namespace of the event being removed + */ + "_fnDelayEvents": function (until, obj, type, namespace) { + var that = this; + //Get the events for the object + var events = $._data($(obj).get(0), 'events'); + $.each(events, function (i, o) { + //If the event type matches + if (i == type) { + //Loop through the possible many events with that type + $.each(o, function (k, v) { + //Somehow it is possible for the event to be undefined make sure it is defined first + if (v) { + if (namespace) { + //Add the event to the array of events to be restored later + that.dom.restoreEvents.push({"until": until, "obj": obj, "type": v.type, "namespace": v.namespace, "handler": v.handler}); + //If the namespace matches + if (v.namespace == namespace) { + //Turn off/unbind the event + $(obj).off(type + "." + namespace); + } + } else { + //Add the event to the array of events to be restored later + that.dom.restoreEvents.push({"until": until, "obj": obj, "type": v.type, "namespace": null, "handler": v.handler}); + //Turn off/unbind the event + $(obj).off(type); + } + } + }); + } + }); + }, + + /** + * Loop through restoreEvents array and restore the events on the elements provided + */ + "_fnRestoreEvents": function (until) { + var that = this; + //Loop through the events to be restored + var i; + for (i = that.dom.restoreEvents.length; i--;) { + if (that.dom.restoreEvents[i].until == undefined || that.dom.restoreEvents[i].until == null || that.dom.restoreEvents[i].until == until) { + if (that.dom.restoreEvents[i].namespace) { + //Turn on the event for the object provided + $(that.dom.restoreEvents[i].obj).off(that.dom.restoreEvents[i].type + "." + that.dom.restoreEvents[i].namespace).on(that.dom.restoreEvents[i].type + "." + that.dom.restoreEvents[i].namespace, that.dom.restoreEvents[i].handler); + that.dom.restoreEvents.splice(i, 1); + } else { + //Turn on the event for the object provided + $(that.dom.restoreEvents[i].obj).off(that.dom.restoreEvents[i].type).on(that.dom.restoreEvents[i].type, that.dom.restoreEvents[i].handler); + that.dom.restoreEvents.splice(i, 1); + } + } + } + }, + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mouse drop and drag + */ + + "_fnSetupMouseListeners":function() { + var that = this; + $(that.s.dt.nTableWrapper).off("mouseenter.ColResize").on("mouseenter.ColResize","th",function(e) { + e.preventDefault(); + that._fnMouseEnter.call(that, e, this); + }); + $(that.s.dt.nTableWrapper).off("mouseleave.ColResize").on("mouseleave.ColResize","th",function(e) { + e.preventDefault(); + that._fnMouseLeave.call(that, e, this); + }); + }, + + /** + * Add mouse listeners to the resize handle on TH element + * @method _fnMouseListener + * @param i Column index + * @param nTh TH resize handle element clicked on + * @returns void + * @private + */ + "_fnMouseListener": function (i, nTh) { + var that = this; + $(nTh).off('mouseenter.ColResize').on('mouseenter.ColResize', function (e) { + e.preventDefault(); + that._fnMouseEnter.call(that, e, nTh); + }); + $(nTh).off('mouseleave.ColResize').on('mouseleave.ColResize', function (e) { + e.preventDefault(); + that._fnMouseLeave.call(that, e, nTh); + }); + }, + + /** + * + * @param e Mouse event + * @param nTh TH element that the mouse is over + */ + "_fnMouseEnter": function (e, nTh) { + var that = this; + if(!that.s.isMousedown) { + //Once the mouse has entered the cell add mouse move event to see if the mouse is over resize handle + $(nTh).off('mousemove.ColResizeHandle').on('mousemove.ColResizeHandle', function (e) { + e.preventDefault(); + that._fnResizeHandleCheck.call(that, e, nTh); + }); + } + }, + + /** + * Clear mouse events when the mouse has left the th + * @param e Mouse event + * @param nTh TH element that the mouse has just left + */ + "_fnMouseLeave": function (e, nTh) { + //Once the mouse has left the TH make suure to remove the mouse move listener + $(nTh).off('mousemove.ColResizeHandle'); + }, + + /** + * Mouse down on a TH element in the table header + * @method _fnMouseDown + * @param event e Mouse event + * @param element nTh TH element to be resized + * @returns void + * @private + */ + "_fnMouseDown": function (e, nTh) { + var that = this; + + that.s.isMousedown = true; + + /* Store information about the mouse position */ + var target = $(e.target).closest('th, td'); + var offset = target.offset(); + + /* Store information about the mouse position for resize calculations in mouse move function */ + this.s.mouse.startX = e.pageX; + this.s.mouse.startY = e.pageY; + + //Store the indexes of the columns the mouse is down on + var idx = that.dom.resizeCol[0].cellIndex; + + // the last column has no 'right-side' neighbour + // with fixed this can make the table smaller + if (that.dom.resizeColNeighbour[0] === undefined){ + var idxNeighbour = 0; + } else { + var idxNeighbour = that.dom.resizeColNeighbour[0].cellIndex; + } + + + + if (idx === undefined) { + return; + } + + this.s.mouse.targetIndex = idx; + this.s.mouse.targetColumn = this.s.dt.aoColumns[ idx ]; + + this.s.mouse.neighbourIndex = idxNeighbour; + this.s.mouse.neighbourColumn = this.s.dt.aoColumns[ idxNeighbour ]; + + /* Add event handlers to the document */ + $(document) + .off('mousemove.ColResize').on('mousemove.ColResize', function (e) { + that._fnMouseMove.call(that, e); + }) + .off('mouseup.ColResize').on('mouseup.ColResize', function (e) { + that._fnMouseUp.call(that, e); + }); + }, + + /** + * Deal with a mouse move event while dragging to resize a column + * @method _fnMouseMove + * @param e Mouse event + * @returns void + * @private + */ + "_fnMouseMove": function (e) { + var that = this; + + var offset = $(that.s.mouse.targetColumn.nTh).offset(); + var relativeX = (e.pageX - offset.left); + var distFromLeft = relativeX; + var distFromRight = $(that.s.mouse.targetColumn.nTh).outerWidth() - relativeX - 1; + + //Change in mouse x position + var dx = e.pageX - that.s.mouse.startX; + //Get the minimum width of the column (default minimum 10px) + var minColumnWidth = Math.max(parseInt($(that.s.mouse.targetColumn.nTh).css('min-width')), 10); + //Store the previous width of the column + var prevWidth = $(that.s.mouse.targetColumn.nTh).width(); + //As long as the cursor is past the handle, resize the columns + if ((dx > 0 && distFromRight <= 0) || (dx < 0 && distFromRight >= 0)) { + if (!that.s.init.tableWidthFixed) { + //As long as the width is larger than the minimum + var newColWidth = Math.max(minColumnWidth, prevWidth + dx); + //Get the width difference (take into account the columns minimum width) + var widthDiff = newColWidth - prevWidth; + var colResizeIdx = parseInt(that.dom.resizeCol.attr("data-column-index")); + //Set datatable column widths + that.s.mouse.targetColumn.sWidthOrig = that.s.mouse.targetColumn.sWidth = that.s.mouse.targetColumn.width = newColWidth + "px"; + var domCols = $(that.s.dt.nTableWrapper).find("th[data-column-index='"+colResizeIdx+"']"); + //For each table expand the width by the same amount as the column + //This accounts for other datatable plugins like FixedColumns + domCols.parents("table").each(function() { + if(!$(this).parent().hasClass("DTFC_LeftBodyLiner")) { + var newWidth = $(this).width() + widthDiff; + $(this).width(newWidth); + } else { + var newWidth =$(that.s.dt.nTableWrapper).find(".DTFC_LeftHeadWrapper").children("table").width(); + $(this).parents(".DTFC_LeftWrapper").width(newWidth); + $(this).parent().width(newWidth+15); + $(this).width(newWidth); + } + }); + //Apply the new width to the columns after the table has been resized + domCols.width(that.s.mouse.targetColumn.width); + } else { + //A neighbour column must exist in order to resize a column in a table with a fixed width + if (that.s.mouse.neighbourColumn) { + //Get the minimum width of the neighbor column (default minimum 10px) + var minColumnNeighbourWidth = Math.max(parseInt($(that.s.mouse.neighbourColumn.nTh).css('min-width')), 10); + //Store the previous width of the neighbour column + var prevNeighbourWidth = $(that.s.mouse.neighbourColumn.nTh).width(); + //As long as the width is larger than the minimum + var newColWidth = Math.max(minColumnWidth, prevWidth + dx); + var newColNeighbourWidth = Math.max(minColumnNeighbourWidth, prevNeighbourWidth - dx); + //Get the width difference (take into account the columns minimum width) + var widthDiff = newColWidth - prevWidth; + var widthDiffNeighbour = newColNeighbourWidth - prevNeighbourWidth; + //Get the column index for the column being changed + var colResizeIdx = parseInt(that.dom.resizeCol.attr("data-column-index")); + var neighbourColResizeIdx = parseInt(that.dom.resizeColNeighbour.attr("data-column-index")); + //Set datatable column widths + that.s.mouse.neighbourColumn.sWidthOrig = that.s.mouse.neighbourColumn.sWidth = that.s.mouse.neighbourColumn.width = newColNeighbourWidth + "px"; + that.s.mouse.targetColumn.sWidthOrig = that.s.mouse.targetColumn.sWidth = that.s.mouse.targetColumn.width = newColWidth + "px"; + //Get list of columns based on column index in all affected tables tables. This accounts for other plugins like FixedColumns + var domNeighbourCols = $(that.s.dt.nTableWrapper).find("th[data-column-index='" + neighbourColResizeIdx + "']"); + var domCols = $(that.s.dt.nTableWrapper).find("th[data-column-index='" + colResizeIdx + "']"); + //If dx if positive (the width is getting larger) shrink the neighbour columns first + if(dx>0) { + domNeighbourCols.width(that.s.mouse.neighbourColumn.width); + domCols.width(that.s.mouse.targetColumn.width); + } else { + //Apply the new width to the columns then to the neighbour columns + domCols.width(that.s.mouse.targetColumn.width); + domNeighbourCols.width(that.s.mouse.neighbourColumn.width); + } + } + } + } + that.s.mouse.startX = e.pageX; + }, + + /** + * Check to see if the mouse is over the resize handle area + * @param e + * @param nTh + */ + "_fnResizeHandleCheck": function (e, nTh) { + var that = this; + + var offset = $(nTh).offset(); + var relativeX = (e.pageX - offset.left); + var relativeY = (e.pageY - offset.top); + var distFromLeft = relativeX; + var distFromRight = $(nTh).outerWidth() - relativeX - 1; + + var handleBuffer = this.s.init.handleWidth / 2; + var leftHandleOn = distFromLeft < handleBuffer; + var rightHandleOn = distFromRight < handleBuffer; + + //If this is the first table cell + if ($(nTh).prev("th").length == 0) { + if(this.s.init.rtl) + rightHandleOn = false; + else + leftHandleOn = false; + } + //If this is the last cell and the table is fixed width don't let them expand the last cell directly + if ($(nTh).next("th").length == 0 && this.s.init.tableWidthFixed) { + if(this.s.init.rtl) + leftHandleOn = false; + else + rightHandleOn = false; + } + + var resizeAvailable = leftHandleOn||rightHandleOn; + + //If table is in right to left mode flip which TH is being resized + if (that.s.init.rtl) { + //Handle is to the left + if (leftHandleOn) { + that.dom.resizeCol = $(nTh); + that.dom.resizeColNeighbour = $(nTh).next(); + } else if (rightHandleOn) { + that.dom.resizeCol = $(nTh).prev(); + that.dom.resizeColNeighbour = $(nTh); + } + } else { + //Handle is to the right + if (rightHandleOn) { + that.dom.resizeCol = $(nTh); + that.dom.resizeColNeighbour = $(nTh).next(); + } else if (leftHandleOn) { + that.dom.resizeCol = $(nTh).prev(); + that.dom.resizeColNeighbour = $(nTh); + } + } + + //If table width is fixed make sure both columns are resizable else just check the one. + if(this.s.init.tableWidthFixed) + resizeAvailable &= this.s.init.exclude.indexOf(parseInt($(that.dom.resizeCol).attr("data-column-index"))) == -1 && this.s.init.exclude.indexOf(parseInt($(that.dom.resizeColNeighbour).attr("data-column-index"))) == -1; + else + resizeAvailable &= this.s.init.exclude.indexOf(parseInt($(that.dom.resizeCol).attr("data-column-index"))) == -1; + + $(nTh).off('mousedown.ColResize'); + if (resizeAvailable) { + $(nTh).css("cursor", "ew-resize"); + + //Delay other mousedown events from the Reorder plugin + that._fnDelayEvents(null, nTh, "mousedown", "ColReorder"); + that._fnDelayEvents("click", nTh, "click", "DT"); + + $(nTh).off('mousedown.ColResize').on('mousedown.ColResize', function (e) { + e.preventDefault(); + that._fnMouseDown.call(that, e, nTh); + }) + .off('click.ColResize').on('click.ColResize', function (e) { + that._fnClick.call(that, e); + }); + } else { + $(nTh).css("cursor", "pointer"); + $(nTh).off('mousedown.ColResize click.ColResize'); + //Restore any events that were removed + that._fnRestoreEvents(); + //This is to restore column sorting on click functionality + if (!that.s.isMousedown) + //Restore click event if mouse is not down + this._fnRestoreEvents("click"); + } + }, + + "_fnClick": function (e) { + var that = this; + that.s.isMousedown = false; + e.stopImmediatePropagation(); + }, + + /** + * Finish off the mouse drag + * @method _fnMouseUp + * @param e Mouse event + * @returns void + * @private + */ + "_fnMouseUp": function (e) { + var that = this; + that.s.isMousedown = false; + + //Fix width of column to be the size the dom is limited to (for when user sets min-width on a column) + that.s.mouse.targetColumn.width = that.dom.resizeCol.width(); + + $(document).off('mousemove.ColResize mouseup.ColResize'); + this.s.dt.oInstance.fnAdjustColumnSizing(); + //Table width fix, prevents extra gaps between tables + var LeftWrapper = $(that.s.dt.nTableWrapper).find(".DTFC_LeftWrapper"); + var DTFC_LeftWidth = LeftWrapper.width(); + LeftWrapper.children(".DTFC_LeftHeadWrapper").children("table").width(DTFC_LeftWidth); + + if (that.s.init.resizeCallback) { + that.s.init.resizeCallback.call(that, that.s.mouse.targetColumn); + } + }, + + /** + * Clean up ColResize memory references and event handlers + * @method _fnDestroy + * @returns void + * @private + */ + "_fnDestroy": function () { + var i, iLen; + + for (i = 0, iLen = this.s.dt.aoDrawCallback.length; i < iLen; i++) { + if (this.s.dt.aoDrawCallback[i].sName === 'ColResize_Pre') { + this.s.dt.aoDrawCallback.splice(i, 1); + break; + } + } + + $(this.s.dt.nTHead).find('*').off('.ColResize'); + + $.each(this.s.dt.aoColumns, function (i, column) { + $(column.nTh).removeAttr('data-column-index'); + }); + + this.s.dt._colResize = null; + this.s = null; + }, + + + /** + * Add a data attribute to the column headers, so we know the index of + * the row to be reordered. This allows fast detection of the index, and + * for this plug-in to work with FixedHeader which clones the nodes. + * @private + */ + "_fnSetColumnIndexes": function () { + $.each(this.s.dt.aoColumns, function (i, column) { + $(column.nTh).attr('data-column-index', i); + }); + } + }; + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Static parameters + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + + /** + * ColResize default settings for initialisation + * @namespace + * @static + */ + ColResize.defaults = { + /** + * Callback function that is fired when columns are resized + * @type function():void + * @default null + * @static + */ + "resizeCallback": null, + + /** + * Exclude array for columns that are not resizable + * @property exclude + * @type array of indexes that are excluded from resizing + * @default [] + */ + "exclude": [], + + /** + * Check to see if user is using a fixed table width or dynamic + * if true: + * -Columns will resize themselves and their neighbour + * -If neighbour is excluded resize will not occur + * if false: + * -Columns will resize themselves and increase or decrease the width of the table accordingly + */ + "tableWidthFixed": true, + + /** + * Width of the resize handle in pixels + * @property handleWidth + * @type int (pixels) + * @default 10 + */ + "handleWidth": 10, + + /** + * Right to left support, when true flips which column they are resizing on mouse down + * @property rtl + * @type bool + * @default false + */ + "rtl": false + }; + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Constants + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + /** + * ColResize version + * @constant version + * @type String + * @default As code + */ + ColResize.version = "0.0.10"; + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables interfaces + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + // Expose + $.fn.dataTable.ColResize = ColResize; + $.fn.DataTable.ColResize = ColResize; + + + // Register a new feature with DataTables + if (typeof $.fn.dataTable == "function" && + typeof $.fn.dataTableExt.fnVersionCheck == "function" && + $.fn.dataTableExt.fnVersionCheck('1.9.3')) { + $.fn.dataTableExt.aoFeatures.push({ + "fnInit": function (settings) { + var table = settings.oInstance; + + if (!settings._colResize) { + var dtInit = settings.oInit; + var opts = dtInit.colResize || dtInit.oColResize || {}; + + new ColResize(settings, opts); + } + else { + table.oApi._fnLog(settings, 1, "ColResize attempted to initialise twice. Ignoring second"); + } + + return null; + /* No node for DataTables to insert */ + }, + "cFeature": "Z", + "sFeature": "ColResize" + }); + } else { + alert("Warning: ColResize requires DataTables 1.9.3 or greater - www.datatables.net/download"); + } + + +// API augmentation + if ($.fn.dataTable.Api) { + $.fn.dataTable.Api.register('colResize.reset()', function () { + return this.iterator('table', function (ctx) { + ctx._colResize.fnReset(); + }); + }); + } + + return ColResize; + }; // /factory + + +// Define as an AMD module if possible +if ( typeof define === 'function' && define.amd ) { + define( ['jquery', 'datatables'], factory ); +} +else if ( typeof exports === 'object' ) { + // Node/CommonJS + factory( require('jquery'), require('datatables') ); +} +else if (jQuery && !jQuery.fn.dataTable.ColResize) { + // Otherwise simply initialise as normal, stopping multiple evaluation + factory(jQuery, jQuery.fn.dataTable); +} + + +})(window, document); diff --git a/externals/datatables.js b/externals/datatables.js new file mode 100644 index 000000000..bef80f9c5 --- /dev/null +++ b/externals/datatables.js @@ -0,0 +1,15321 @@ +/* + * This combined file was created by the DataTables downloader builder: + * https://datatables.net/download + * + * To rebuild or modify this file with the latest versions of the included + * software please visit: + * https://datatables.net/download/#dt/dt-1.10.13 + * + * Included libraries: + * DataTables 1.10.13 + */ + +/*! DataTables 1.10.13 + * ©2008-2016 SpryMedia Ltd - datatables.net/license + */ + +/** + * @summary DataTables + * @description Paginate, search and order HTML tables + * @version 1.10.13 + * @file jquery.dataTables.js + * @author SpryMedia Ltd + * @contact www.datatables.net + * @copyright Copyright 2008-2016 SpryMedia Ltd. + * + * This source file is free software, available under the following license: + * MIT license - http://datatables.net/license + * + * This source file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details. + * + * For details please refer to: http://www.datatables.net + */ + +/*jslint evil: true, undef: true, browser: true */ +/*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/ + +(function( factory ) { + "use strict"; + + if ( typeof define === 'function' && define.amd ) { + // AMD + define( ['jquery'], function ( $ ) { + return factory( $, window, document ); + } ); + } + else if ( typeof exports === 'object' ) { + // CommonJS + module.exports = function (root, $) { + if ( ! root ) { + // CommonJS environments without a window global must pass a + // root. This will give an error otherwise + root = window; + } + + if ( ! $ ) { + $ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window + require('jquery') : + require('jquery')( root ); + } + + return factory( $, root, root.document ); + }; + } + else { + // Browser + factory( jQuery, window, document ); + } +} +(function( $, window, document, undefined ) { + "use strict"; + + /** + * DataTables is a plug-in for the jQuery Javascript library. It is a highly + * flexible tool, based upon the foundations of progressive enhancement, + * which will add advanced interaction controls to any HTML table. For a + * full list of features please refer to + * [DataTables.net](href="http://datatables.net). + * + * Note that the `DataTable` object is not a global variable but is aliased + * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may + * be accessed. + * + * @class + * @param {object} [init={}] Configuration object for DataTables. Options + * are defined by {@link DataTable.defaults} + * @requires jQuery 1.7+ + * + * @example + * // Basic initialisation + * $(document).ready( function { + * $('#example').dataTable(); + * } ); + * + * @example + * // Initialisation with configuration options - in this case, disable + * // pagination and sorting. + * $(document).ready( function { + * $('#example').dataTable( { + * "paginate": false, + * "sort": false + * } ); + * } ); + */ + var DataTable = function ( options ) + { + /** + * Perform a jQuery selector action on the table's TR elements (from the tbody) and + * return the resulting jQuery object. + * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on + * @param {object} [oOpts] Optional parameters for modifying the rows to be included + * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter + * criterion ("applied") or all TR elements (i.e. no filter). + * @param {string} [oOpts.order=current] Order of the TR elements in the processed array. + * Can be either 'current', whereby the current sorting of the table is used, or + * 'original' whereby the original order the data was read into the table is used. + * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page + * ("current") or not ("all"). If 'current' is given, then order is assumed to be + * 'current' and filter is 'applied', regardless of what they might be given as. + * @returns {object} jQuery object, filtered by the given selector. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Highlight every second row + * oTable.$('tr:odd').css('backgroundColor', 'blue'); + * } ); + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Filter to rows with 'Webkit' in them, add a background colour and then + * // remove the filter, thus highlighting the 'Webkit' rows only. + * oTable.fnFilter('Webkit'); + * oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue'); + * oTable.fnFilter(''); + * } ); + */ + this.$ = function ( sSelector, oOpts ) + { + return this.api(true).$( sSelector, oOpts ); + }; + + + /** + * Almost identical to $ in operation, but in this case returns the data for the matched + * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes + * rather than any descendants, so the data can be obtained for the row/cell. If matching + * rows are found, the data returned is the original data array/object that was used to + * create the row (or a generated array if from a DOM source). + * + * This method is often useful in-combination with $ where both functions are given the + * same parameters and the array indexes will match identically. + * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on + * @param {object} [oOpts] Optional parameters for modifying the rows to be included + * @param {string} [oOpts.filter=none] Select elements that meet the current filter + * criterion ("applied") or all elements (i.e. no filter). + * @param {string} [oOpts.order=current] Order of the data in the processed array. + * Can be either 'current', whereby the current sorting of the table is used, or + * 'original' whereby the original order the data was read into the table is used. + * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page + * ("current") or not ("all"). If 'current' is given, then order is assumed to be + * 'current' and filter is 'applied', regardless of what they might be given as. + * @returns {array} Data for the matched elements. If any elements, as a result of the + * selector, were not TR, TD or TH elements in the DataTable, they will have a null + * entry in the array. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Get the data from the first row in the table + * var data = oTable._('tr:first'); + * + * // Do something useful with the data + * alert( "First cell is: "+data[0] ); + * } ); + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Filter to 'Webkit' and get all data for + * oTable.fnFilter('Webkit'); + * var data = oTable._('tr', {"search": "applied"}); + * + * // Do something with the data + * alert( data.length+" rows matched the search" ); + * } ); + */ + this._ = function ( sSelector, oOpts ) + { + return this.api(true).rows( sSelector, oOpts ).data(); + }; + + + /** + * Create a DataTables Api instance, with the currently selected tables for + * the Api's context. + * @param {boolean} [traditional=false] Set the API instance's context to be + * only the table referred to by the `DataTable.ext.iApiIndex` option, as was + * used in the API presented by DataTables 1.9- (i.e. the traditional mode), + * or if all tables captured in the jQuery object should be used. + * @return {DataTables.Api} + */ + this.api = function ( traditional ) + { + return traditional ? + new _Api( + _fnSettingsFromNode( this[ _ext.iApiIndex ] ) + ) : + new _Api( this ); + }; + + + /** + * Add a single new row or multiple rows of data to the table. Please note + * that this is suitable for client-side processing only - if you are using + * server-side processing (i.e. "bServerSide": true), then to add data, you + * must add it to the data source, i.e. the server-side, through an Ajax call. + * @param {array|object} data The data to be added to the table. This can be: + *
    + *
  • 1D array of data - add a single row with the data provided
  • + *
  • 2D array of arrays - add multiple rows in a single call
  • + *
  • object - data object when using mData
  • + *
  • array of objects - multiple data objects when using mData
  • + *
+ * @param {bool} [redraw=true] redraw the table or not + * @returns {array} An array of integers, representing the list of indexes in + * aoData ({@link DataTable.models.oSettings}) that have been added to + * the table. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * // Global var for counter + * var giCount = 2; + * + * $(document).ready(function() { + * $('#example').dataTable(); + * } ); + * + * function fnClickAddRow() { + * $('#example').dataTable().fnAddData( [ + * giCount+".1", + * giCount+".2", + * giCount+".3", + * giCount+".4" ] + * ); + * + * giCount++; + * } + */ + this.fnAddData = function( data, redraw ) + { + var api = this.api( true ); + + /* Check if we want to add multiple rows or not */ + var rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ? + api.rows.add( data ) : + api.row.add( data ); + + if ( redraw === undefined || redraw ) { + api.draw(); + } + + return rows.flatten().toArray(); + }; + + + /** + * This function will make DataTables recalculate the column sizes, based on the data + * contained in the table and the sizes applied to the columns (in the DOM, CSS or + * through the sWidth parameter). This can be useful when the width of the table's + * parent element changes (for example a window resize). + * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable( { + * "sScrollY": "200px", + * "bPaginate": false + * } ); + * + * $(window).on('resize', function () { + * oTable.fnAdjustColumnSizing(); + * } ); + * } ); + */ + this.fnAdjustColumnSizing = function ( bRedraw ) + { + var api = this.api( true ).columns.adjust(); + var settings = api.settings()[0]; + var scroll = settings.oScroll; + + if ( bRedraw === undefined || bRedraw ) { + api.draw( false ); + } + else if ( scroll.sX !== "" || scroll.sY !== "" ) { + /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */ + _fnScrollDraw( settings ); + } + }; + + + /** + * Quickly and simply clear a table + * @param {bool} [bRedraw=true] redraw the table or not + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...) + * oTable.fnClearTable(); + * } ); + */ + this.fnClearTable = function( bRedraw ) + { + var api = this.api( true ).clear(); + + if ( bRedraw === undefined || bRedraw ) { + api.draw(); + } + }; + + + /** + * The exact opposite of 'opening' a row, this function will close any rows which + * are currently 'open'. + * @param {node} nTr the table row to 'close' + * @returns {int} 0 on success, or 1 if failed (can't find the row) + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable; + * + * // 'open' an information row when a row is clicked on + * $('#example tbody tr').click( function () { + * if ( oTable.fnIsOpen(this) ) { + * oTable.fnClose( this ); + * } else { + * oTable.fnOpen( this, "Temporary row opened", "info_row" ); + * } + * } ); + * + * oTable = $('#example').dataTable(); + * } ); + */ + this.fnClose = function( nTr ) + { + this.api( true ).row( nTr ).child.hide(); + }; + + + /** + * Remove a row for the table + * @param {mixed} target The index of the row from aoData to be deleted, or + * the TR element you want to delete + * @param {function|null} [callBack] Callback function + * @param {bool} [redraw=true] Redraw the table or not + * @returns {array} The row that was deleted + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Immediately remove the first row + * oTable.fnDeleteRow( 0 ); + * } ); + */ + this.fnDeleteRow = function( target, callback, redraw ) + { + var api = this.api( true ); + var rows = api.rows( target ); + var settings = rows.settings()[0]; + var data = settings.aoData[ rows[0][0] ]; + + rows.remove(); + + if ( callback ) { + callback.call( this, settings, data ); + } + + if ( redraw === undefined || redraw ) { + api.draw(); + } + + return data; + }; + + + /** + * Restore the table to it's original state in the DOM by removing all of DataTables + * enhancements, alterations to the DOM structure of the table and event listeners. + * @param {boolean} [remove=false] Completely remove the table from the DOM + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * // This example is fairly pointless in reality, but shows how fnDestroy can be used + * var oTable = $('#example').dataTable(); + * oTable.fnDestroy(); + * } ); + */ + this.fnDestroy = function ( remove ) + { + this.api( true ).destroy( remove ); + }; + + + /** + * Redraw the table + * @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Re-draw the table - you wouldn't want to do it here, but it's an example :-) + * oTable.fnDraw(); + * } ); + */ + this.fnDraw = function( complete ) + { + // Note that this isn't an exact match to the old call to _fnDraw - it takes + // into account the new data, but can hold position. + this.api( true ).draw( complete ); + }; + + + /** + * Filter the input based on data + * @param {string} sInput String to filter the table on + * @param {int|null} [iColumn] Column to limit filtering to + * @param {bool} [bRegex=false] Treat as regular expression or not + * @param {bool} [bSmart=true] Perform smart filtering or not + * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es) + * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false) + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Sometime later - filter... + * oTable.fnFilter( 'test string' ); + * } ); + */ + this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive ) + { + var api = this.api( true ); + + if ( iColumn === null || iColumn === undefined ) { + api.search( sInput, bRegex, bSmart, bCaseInsensitive ); + } + else { + api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive ); + } + + api.draw(); + }; + + + /** + * Get the data for the whole table, an individual row or an individual cell based on the + * provided parameters. + * @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as + * a TR node then the data source for the whole row will be returned. If given as a + * TD/TH cell node then iCol will be automatically calculated and the data for the + * cell returned. If given as an integer, then this is treated as the aoData internal + * data index for the row (see fnGetPosition) and the data for that row used. + * @param {int} [col] Optional column index that you want the data of. + * @returns {array|object|string} If mRow is undefined, then the data for all rows is + * returned. If mRow is defined, just data for that row, and is iCol is + * defined, only data for the designated cell is returned. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * // Row data + * $(document).ready(function() { + * oTable = $('#example').dataTable(); + * + * oTable.$('tr').click( function () { + * var data = oTable.fnGetData( this ); + * // ... do something with the array / object of data for the row + * } ); + * } ); + * + * @example + * // Individual cell data + * $(document).ready(function() { + * oTable = $('#example').dataTable(); + * + * oTable.$('td').click( function () { + * var sData = oTable.fnGetData( this ); + * alert( 'The cell clicked on had the value of '+sData ); + * } ); + * } ); + */ + this.fnGetData = function( src, col ) + { + var api = this.api( true ); + + if ( src !== undefined ) { + var type = src.nodeName ? src.nodeName.toLowerCase() : ''; + + return col !== undefined || type == 'td' || type == 'th' ? + api.cell( src, col ).data() : + api.row( src ).data() || null; + } + + return api.data().toArray(); + }; + + + /** + * Get an array of the TR nodes that are used in the table's body. Note that you will + * typically want to use the '$' API method in preference to this as it is more + * flexible. + * @param {int} [iRow] Optional row index for the TR element you want + * @returns {array|node} If iRow is undefined, returns an array of all TR elements + * in the table's body, or iRow is defined, just the TR element requested. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Get the nodes from the table + * var nNodes = oTable.fnGetNodes( ); + * } ); + */ + this.fnGetNodes = function( iRow ) + { + var api = this.api( true ); + + return iRow !== undefined ? + api.row( iRow ).node() : + api.rows().nodes().flatten().toArray(); + }; + + + /** + * Get the array indexes of a particular cell from it's DOM element + * and column index including hidden columns + * @param {node} node this can either be a TR, TD or TH in the table's body + * @returns {int} If nNode is given as a TR, then a single index is returned, or + * if given as a cell, an array of [row index, column index (visible), + * column index (all)] is given. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * $('#example tbody td').click( function () { + * // Get the position of the current data from the node + * var aPos = oTable.fnGetPosition( this ); + * + * // Get the data array for this row + * var aData = oTable.fnGetData( aPos[0] ); + * + * // Update the data array and return the value + * aData[ aPos[1] ] = 'clicked'; + * this.innerHTML = 'clicked'; + * } ); + * + * // Init DataTables + * oTable = $('#example').dataTable(); + * } ); + */ + this.fnGetPosition = function( node ) + { + var api = this.api( true ); + var nodeName = node.nodeName.toUpperCase(); + + if ( nodeName == 'TR' ) { + return api.row( node ).index(); + } + else if ( nodeName == 'TD' || nodeName == 'TH' ) { + var cell = api.cell( node ).index(); + + return [ + cell.row, + cell.columnVisible, + cell.column + ]; + } + return null; + }; + + + /** + * Check to see if a row is 'open' or not. + * @param {node} nTr the table row to check + * @returns {boolean} true if the row is currently open, false otherwise + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable; + * + * // 'open' an information row when a row is clicked on + * $('#example tbody tr').click( function () { + * if ( oTable.fnIsOpen(this) ) { + * oTable.fnClose( this ); + * } else { + * oTable.fnOpen( this, "Temporary row opened", "info_row" ); + * } + * } ); + * + * oTable = $('#example').dataTable(); + * } ); + */ + this.fnIsOpen = function( nTr ) + { + return this.api( true ).row( nTr ).child.isShown(); + }; + + + /** + * This function will place a new row directly after a row which is currently + * on display on the page, with the HTML contents that is passed into the + * function. This can be used, for example, to ask for confirmation that a + * particular record should be deleted. + * @param {node} nTr The table row to 'open' + * @param {string|node|jQuery} mHtml The HTML to put into the row + * @param {string} sClass Class to give the new TD cell + * @returns {node} The row opened. Note that if the table row passed in as the + * first parameter, is not found in the table, this method will silently + * return. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable; + * + * // 'open' an information row when a row is clicked on + * $('#example tbody tr').click( function () { + * if ( oTable.fnIsOpen(this) ) { + * oTable.fnClose( this ); + * } else { + * oTable.fnOpen( this, "Temporary row opened", "info_row" ); + * } + * } ); + * + * oTable = $('#example').dataTable(); + * } ); + */ + this.fnOpen = function( nTr, mHtml, sClass ) + { + return this.api( true ) + .row( nTr ) + .child( mHtml, sClass ) + .show() + .child()[0]; + }; + + + /** + * Change the pagination - provides the internal logic for pagination in a simple API + * function. With this function you can have a DataTables table go to the next, + * previous, first or last pages. + * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last" + * or page number to jump to (integer), note that page 0 is the first page. + * @param {bool} [bRedraw=true] Redraw the table or not + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * oTable.fnPageChange( 'next' ); + * } ); + */ + this.fnPageChange = function ( mAction, bRedraw ) + { + var api = this.api( true ).page( mAction ); + + if ( bRedraw === undefined || bRedraw ) { + api.draw(false); + } + }; + + + /** + * Show a particular column + * @param {int} iCol The column whose display should be changed + * @param {bool} bShow Show (true) or hide (false) the column + * @param {bool} [bRedraw=true] Redraw the table or not + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Hide the second column after initialisation + * oTable.fnSetColumnVis( 1, false ); + * } ); + */ + this.fnSetColumnVis = function ( iCol, bShow, bRedraw ) + { + var api = this.api( true ).column( iCol ).visible( bShow ); + + if ( bRedraw === undefined || bRedraw ) { + api.columns.adjust().draw(); + } + }; + + + /** + * Get the settings for a particular table for external manipulation + * @returns {object} DataTables settings object. See + * {@link DataTable.models.oSettings} + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * var oSettings = oTable.fnSettings(); + * + * // Show an example parameter from the settings + * alert( oSettings._iDisplayStart ); + * } ); + */ + this.fnSettings = function() + { + return _fnSettingsFromNode( this[_ext.iApiIndex] ); + }; + + + /** + * Sort the table by a particular column + * @param {int} iCol the data index to sort on. Note that this will not match the + * 'display index' if you have hidden data entries + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Sort immediately with columns 0 and 1 + * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] ); + * } ); + */ + this.fnSort = function( aaSort ) + { + this.api( true ).order( aaSort ).draw(); + }; + + + /** + * Attach a sort listener to an element for a given column + * @param {node} nNode the element to attach the sort listener to + * @param {int} iColumn the column that a click on this node will sort on + * @param {function} [fnCallback] callback function when sort is run + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Sort on column 1, when 'sorter' is clicked on + * oTable.fnSortListener( document.getElementById('sorter'), 1 ); + * } ); + */ + this.fnSortListener = function( nNode, iColumn, fnCallback ) + { + this.api( true ).order.listener( nNode, iColumn, fnCallback ); + }; + + + /** + * Update a table cell or row - this method will accept either a single value to + * update the cell with, an array of values with one element for each column or + * an object in the same format as the original data source. The function is + * self-referencing in order to make the multi column updates easier. + * @param {object|array|string} mData Data to update the cell/row with + * @param {node|int} mRow TR element you want to update or the aoData index + * @param {int} [iColumn] The column to update, give as null or undefined to + * update a whole row. + * @param {bool} [bRedraw=true] Redraw the table or not + * @param {bool} [bAction=true] Perform pre-draw actions or not + * @returns {int} 0 on success, 1 on error + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell + * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row + * } ); + */ + this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction ) + { + var api = this.api( true ); + + if ( iColumn === undefined || iColumn === null ) { + api.row( mRow ).data( mData ); + } + else { + api.cell( mRow, iColumn ).data( mData ); + } + + if ( bAction === undefined || bAction ) { + api.columns.adjust(); + } + + if ( bRedraw === undefined || bRedraw ) { + api.draw(); + } + return 0; + }; + + + /** + * Provide a common method for plug-ins to check the version of DataTables being used, in order + * to ensure compatibility. + * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the + * formats "X" and "X.Y" are also acceptable. + * @returns {boolean} true if this version of DataTables is greater or equal to the required + * version, or false if this version of DataTales is not suitable + * @method + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * alert( oTable.fnVersionCheck( '1.9.0' ) ); + * } ); + */ + this.fnVersionCheck = _ext.fnVersionCheck; + + + var _that = this; + var emptyInit = options === undefined; + var len = this.length; + + if ( emptyInit ) { + options = {}; + } + + this.oApi = this.internal = _ext.internal; + + // Extend with old style plug-in API methods + for ( var fn in DataTable.ext.internal ) { + if ( fn ) { + this[fn] = _fnExternApiFunc(fn); + } + } + + this.each(function() { + // For each initialisation we want to give it a clean initialisation + // object that can be bashed around + var o = {}; + var oInit = len > 1 ? // optimisation for single table case + _fnExtend( o, options, true ) : + options; + + /*global oInit,_that,emptyInit*/ + var i=0, iLen, j, jLen, k, kLen; + var sId = this.getAttribute( 'id' ); + var bInitHandedOff = false; + var defaults = DataTable.defaults; + var $this = $(this); + + + /* Sanity check */ + if ( this.nodeName.toLowerCase() != 'table' ) + { + _fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 ); + return; + } + + /* Backwards compatibility for the defaults */ + _fnCompatOpts( defaults ); + _fnCompatCols( defaults.column ); + + /* Convert the camel-case defaults to Hungarian */ + _fnCamelToHungarian( defaults, defaults, true ); + _fnCamelToHungarian( defaults.column, defaults.column, true ); + + /* Setting up the initialisation object */ + _fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) ); + + + + /* Check to see if we are re-initialising a table */ + var allSettings = DataTable.settings; + for ( i=0, iLen=allSettings.length ; i').appendTo($this); + } + oSettings.nTHead = thead[0]; + + var tbody = $this.children('tbody'); + if ( tbody.length === 0 ) { + tbody = $('').appendTo($this); + } + oSettings.nTBody = tbody[0]; + + var tfoot = $this.children('tfoot'); + if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) { + // If we are a scrolling table, and no footer has been given, then we need to create + // a tfoot element for the caption element to be appended to + tfoot = $('').appendTo($this); + } + + if ( tfoot.length === 0 || tfoot.children().length === 0 ) { + $this.addClass( oClasses.sNoFooter ); + } + else if ( tfoot.length > 0 ) { + oSettings.nTFoot = tfoot[0]; + _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot ); + } + + /* Check if there is data passing into the constructor */ + if ( oInit.aaData ) { + for ( i=0 ; i/g; + + // This is not strict ISO8601 - Date.parse() is quite lax, although + // implementations differ between browsers. + var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/; + + // Escape regular expression special characters + var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' ); + + // http://en.wikipedia.org/wiki/Foreign_exchange_market + // - \u20BD - Russian ruble. + // - \u20a9 - South Korean Won + // - \u20BA - Turkish Lira + // - \u20B9 - Indian Rupee + // - R - Brazil (R$) and South Africa + // - fr - Swiss Franc + // - kr - Swedish krona, Norwegian krone and Danish krone + // - \u2009 is thin space and \u202F is narrow no-break space, both used in many + // standards as thousands separators. + var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi; + + + var _empty = function ( d ) { + return !d || d === true || d === '-' ? true : false; + }; + + + var _intVal = function ( s ) { + var integer = parseInt( s, 10 ); + return !isNaN(integer) && isFinite(s) ? integer : null; + }; + + // Convert from a formatted number with characters other than `.` as the + // decimal place, to a Javascript number + var _numToDecimal = function ( num, decimalPoint ) { + // Cache created regular expressions for speed as this function is called often + if ( ! _re_dic[ decimalPoint ] ) { + _re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' ); + } + return typeof num === 'string' && decimalPoint !== '.' ? + num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) : + num; + }; + + + var _isNumber = function ( d, decimalPoint, formatted ) { + var strType = typeof d === 'string'; + + // If empty return immediately so there must be a number if it is a + // formatted string (this stops the string "k", or "kr", etc being detected + // as a formatted number for currency + if ( _empty( d ) ) { + return true; + } + + if ( decimalPoint && strType ) { + d = _numToDecimal( d, decimalPoint ); + } + + if ( formatted && strType ) { + d = d.replace( _re_formatted_numeric, '' ); + } + + return !isNaN( parseFloat(d) ) && isFinite( d ); + }; + + + // A string without HTML in it can be considered to be HTML still + var _isHtml = function ( d ) { + return _empty( d ) || typeof d === 'string'; + }; + + + var _htmlNumeric = function ( d, decimalPoint, formatted ) { + if ( _empty( d ) ) { + return true; + } + + var html = _isHtml( d ); + return ! html ? + null : + _isNumber( _stripHtml( d ), decimalPoint, formatted ) ? + true : + null; + }; + + + var _pluck = function ( a, prop, prop2 ) { + var out = []; + var i=0, ien=a.length; + + // Could have the test in the loop for slightly smaller code, but speed + // is essential here + if ( prop2 !== undefined ) { + for ( ; i') + .css( { + position: 'fixed', + top: 0, + left: $(window).scrollLeft()*-1, // allow for scrolling + height: 1, + width: 1, + overflow: 'hidden' + } ) + .append( + $('
') + .css( { + position: 'absolute', + top: 1, + left: 1, + width: 100, + overflow: 'scroll' + } ) + .append( + $('
') + .css( { + width: '100%', + height: 10 + } ) + ) + ) + .appendTo( 'body' ); + + var outer = n.children(); + var inner = outer.children(); + + // Numbers below, in order, are: + // inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth + // + // IE6 XP: 100 100 100 83 + // IE7 Vista: 100 100 100 83 + // IE 8+ Windows: 83 83 100 83 + // Evergreen Windows: 83 83 100 83 + // Evergreen Mac with scrollbars: 85 85 100 85 + // Evergreen Mac without scrollbars: 100 100 100 100 + + // Get scrollbar width + browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth; + + // IE6/7 will oversize a width 100% element inside a scrolling element, to + // include the width of the scrollbar, while other browsers ensure the inner + // element is contained without forcing scrolling + browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100; + + // In rtl text layout, some browsers (most, but not all) will place the + // scrollbar on the left, rather than the right. + browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1; + + // IE8- don't provide height and width for getBoundingClientRect + browser.bBounding = n[0].getBoundingClientRect().width ? true : false; + + n.remove(); + } + + $.extend( settings.oBrowser, DataTable.__browser ); + settings.oScroll.iBarWidth = DataTable.__browser.barWidth; + } + + + /** + * Array.prototype reduce[Right] method, used for browsers which don't support + * JS 1.6. Done this way to reduce code size, since we iterate either way + * @param {object} settings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnReduce ( that, fn, init, start, end, inc ) + { + var + i = start, + value, + isSet = false; + + if ( init !== undefined ) { + value = init; + isSet = true; + } + + while ( i !== end ) { + if ( ! that.hasOwnProperty(i) ) { + continue; + } + + value = isSet ? + fn( value, that[i], i, that ) : + that[i]; + + isSet = true; + i += inc; + } + + return value; + } + + /** + * Add a column to the list used for the table with default values + * @param {object} oSettings dataTables settings object + * @param {node} nTh The th element for this column + * @memberof DataTable#oApi + */ + function _fnAddColumn( oSettings, nTh ) + { + // Add column to aoColumns array + var oDefaults = DataTable.defaults.column; + var iCol = oSettings.aoColumns.length; + var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, { + "nTh": nTh ? nTh : document.createElement('th'), + "sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '', + "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol], + "mData": oDefaults.mData ? oDefaults.mData : iCol, + idx: iCol + } ); + oSettings.aoColumns.push( oCol ); + + // Add search object for column specific search. Note that the `searchCols[ iCol ]` + // passed into extend can be undefined. This allows the user to give a default + // with only some of the parameters defined, and also not give a default + var searchCols = oSettings.aoPreSearchCols; + searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] ); + + // Use the default column options function to initialise classes etc + _fnColumnOptions( oSettings, iCol, $(nTh).data() ); + } + + + /** + * Apply options for a column + * @param {object} oSettings dataTables settings object + * @param {int} iCol column index to consider + * @param {object} oOptions object with sType, bVisible and bSearchable etc + * @memberof DataTable#oApi + */ + function _fnColumnOptions( oSettings, iCol, oOptions ) + { + var oCol = oSettings.aoColumns[ iCol ]; + var oClasses = oSettings.oClasses; + var th = $(oCol.nTh); + + // Try to get width information from the DOM. We can't get it from CSS + // as we'd need to parse the CSS stylesheet. `width` option can override + if ( ! oCol.sWidthOrig ) { + // Width attribute + oCol.sWidthOrig = th.attr('width') || null; + + // Style attribute + var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/); + if ( t ) { + oCol.sWidthOrig = t[1]; + } + } + + /* User specified column options */ + if ( oOptions !== undefined && oOptions !== null ) + { + // Backwards compatibility + _fnCompatCols( oOptions ); + + // Map camel case parameters to their Hungarian counterparts + _fnCamelToHungarian( DataTable.defaults.column, oOptions ); + + /* Backwards compatibility for mDataProp */ + if ( oOptions.mDataProp !== undefined && !oOptions.mData ) + { + oOptions.mData = oOptions.mDataProp; + } + + if ( oOptions.sType ) + { + oCol._sManualType = oOptions.sType; + } + + // `class` is a reserved word in Javascript, so we need to provide + // the ability to use a valid name for the camel case input + if ( oOptions.className && ! oOptions.sClass ) + { + oOptions.sClass = oOptions.className; + } + + $.extend( oCol, oOptions ); + _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" ); + + /* iDataSort to be applied (backwards compatibility), but aDataSort will take + * priority if defined + */ + if ( oOptions.iDataSort !== undefined ) + { + oCol.aDataSort = [ oOptions.iDataSort ]; + } + _fnMap( oCol, oOptions, "aDataSort" ); + } + + /* Cache the data get and set functions for speed */ + var mDataSrc = oCol.mData; + var mData = _fnGetObjectDataFn( mDataSrc ); + var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null; + + var attrTest = function( src ) { + return typeof src === 'string' && src.indexOf('@') !== -1; + }; + oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && ( + attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter) + ); + oCol._setter = null; + + oCol.fnGetData = function (rowData, type, meta) { + var innerData = mData( rowData, type, undefined, meta ); + + return mRender && type ? + mRender( innerData, type, rowData, meta ) : + innerData; + }; + oCol.fnSetData = function ( rowData, val, meta ) { + return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta ); + }; + + // Indicate if DataTables should read DOM data as an object or array + // Used in _fnGetRowElements + if ( typeof mDataSrc !== 'number' ) { + oSettings._rowReadObject = true; + } + + /* Feature sorting overrides column specific when off */ + if ( !oSettings.oFeatures.bSort ) + { + oCol.bSortable = false; + th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called + } + + /* Check that the class assignment is correct for sorting */ + var bAsc = $.inArray('asc', oCol.asSorting) !== -1; + var bDesc = $.inArray('desc', oCol.asSorting) !== -1; + if ( !oCol.bSortable || (!bAsc && !bDesc) ) + { + oCol.sSortingClass = oClasses.sSortableNone; + oCol.sSortingClassJUI = ""; + } + else if ( bAsc && !bDesc ) + { + oCol.sSortingClass = oClasses.sSortableAsc; + oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed; + } + else if ( !bAsc && bDesc ) + { + oCol.sSortingClass = oClasses.sSortableDesc; + oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed; + } + else + { + oCol.sSortingClass = oClasses.sSortable; + oCol.sSortingClassJUI = oClasses.sSortJUI; + } + } + + + /** + * Adjust the table column widths for new data. Note: you would probably want to + * do a redraw after calling this function! + * @param {object} settings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnAdjustColumnSizing ( settings ) + { + /* Not interested in doing column width calculation if auto-width is disabled */ + if ( settings.oFeatures.bAutoWidth !== false ) + { + var columns = settings.aoColumns; + + _fnCalculateColumnWidths( settings ); + for ( var i=0 , iLen=columns.length ; i