mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2024-11-25 06:56:38 +00:00
Initial transfer from ADO (#13)
This commit is contained in:
parent
ab3486bd05
commit
e9d3160b57
@ -343,7 +343,7 @@ src/Explorer/Controls/LibraryManagement/LibraryManageComponentAdapter.tsx
|
|||||||
src/Explorer/Controls/Notebook/NotebookTerminalComponent.test.tsx
|
src/Explorer/Controls/Notebook/NotebookTerminalComponent.test.tsx
|
||||||
src/Explorer/Controls/Notebook/NotebookTerminalComponent.tsx
|
src/Explorer/Controls/Notebook/NotebookTerminalComponent.tsx
|
||||||
src/Explorer/Controls/NotebookViewer/NotebookMetadataComponent.tsx
|
src/Explorer/Controls/NotebookViewer/NotebookMetadataComponent.tsx
|
||||||
src/Explorer/Controls/NotebookViewer/NotebookViewer.tsx
|
src/NotebookViewer/NotebookViewer.tsx
|
||||||
src/Explorer/Controls/NotebookViewer/NotebookViewerComponent.tsx
|
src/Explorer/Controls/NotebookViewer/NotebookViewerComponent.tsx
|
||||||
src/Explorer/Controls/QueriesGridReactComponent/QueriesGridComponent.tsx
|
src/Explorer/Controls/QueriesGridReactComponent/QueriesGridComponent.tsx
|
||||||
src/Explorer/Controls/QueriesGridReactComponent/QueriesGridComponentAdapter.tsx
|
src/Explorer/Controls/QueriesGridReactComponent/QueriesGridComponentAdapter.tsx
|
||||||
|
209
package-lock.json
generated
209
package-lock.json
generated
@ -1159,11 +1159,6 @@
|
|||||||
"minimist": "^1.2.0"
|
"minimist": "^1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@emotion/hash": {
|
|
||||||
"version": "0.8.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
|
|
||||||
"integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
|
|
||||||
},
|
|
||||||
"@emotion/is-prop-valid": {
|
"@emotion/is-prop-valid": {
|
||||||
"version": "0.8.8",
|
"version": "0.8.8",
|
||||||
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
|
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
|
||||||
@ -1604,96 +1599,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@material-ui/core": {
|
|
||||||
"version": "4.9.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.9.10.tgz",
|
|
||||||
"integrity": "sha512-CQuZU9Y10RkwSdxjn785kw2EPcXhv5GKauuVQufR9LlD37kjfn21Im1yvr6wsUzn81oLhEvVPz727UWC0gbqxg==",
|
|
||||||
"requires": {
|
|
||||||
"@babel/runtime": "^7.4.4",
|
|
||||||
"@material-ui/styles": "^4.9.10",
|
|
||||||
"@material-ui/system": "^4.9.10",
|
|
||||||
"@material-ui/types": "^5.0.1",
|
|
||||||
"@material-ui/utils": "^4.9.6",
|
|
||||||
"@types/react-transition-group": "^4.2.0",
|
|
||||||
"clsx": "^1.0.4",
|
|
||||||
"hoist-non-react-statics": "^3.3.2",
|
|
||||||
"popper.js": "^1.16.1-lts",
|
|
||||||
"prop-types": "^15.7.2",
|
|
||||||
"react-is": "^16.8.0",
|
|
||||||
"react-transition-group": "^4.3.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"dom-helpers": {
|
|
||||||
"version": "5.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.1.4.tgz",
|
|
||||||
"integrity": "sha512-TjMyeVUvNEnOnhzs6uAn9Ya47GmMo3qq7m+Lr/3ON0Rs5kHvb8I+SQYjLUSYn7qhEm0QjW0yrBkvz9yOrwwz1A==",
|
|
||||||
"requires": {
|
|
||||||
"@babel/runtime": "^7.8.7",
|
|
||||||
"csstype": "^2.6.7"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"react-transition-group": {
|
|
||||||
"version": "4.4.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz",
|
|
||||||
"integrity": "sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw==",
|
|
||||||
"requires": {
|
|
||||||
"@babel/runtime": "^7.5.5",
|
|
||||||
"dom-helpers": "^5.0.1",
|
|
||||||
"loose-envify": "^1.4.0",
|
|
||||||
"prop-types": "^15.6.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@material-ui/styles": {
|
|
||||||
"version": "4.9.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.9.14.tgz",
|
|
||||||
"integrity": "sha512-zecwWKgRU2VzdmutNovPB4s5LKI0TWyZKc/AHfPu9iY8tg4UoLjpa4Rn9roYrRfuTbBZHI6b0BXcQ8zkis0nzQ==",
|
|
||||||
"requires": {
|
|
||||||
"@babel/runtime": "^7.4.4",
|
|
||||||
"@emotion/hash": "^0.8.0",
|
|
||||||
"@material-ui/types": "^5.1.0",
|
|
||||||
"@material-ui/utils": "^4.9.6",
|
|
||||||
"clsx": "^1.0.4",
|
|
||||||
"csstype": "^2.5.2",
|
|
||||||
"hoist-non-react-statics": "^3.3.2",
|
|
||||||
"jss": "^10.0.3",
|
|
||||||
"jss-plugin-camel-case": "^10.0.3",
|
|
||||||
"jss-plugin-default-unit": "^10.0.3",
|
|
||||||
"jss-plugin-global": "^10.0.3",
|
|
||||||
"jss-plugin-nested": "^10.0.3",
|
|
||||||
"jss-plugin-props-sort": "^10.0.3",
|
|
||||||
"jss-plugin-rule-value-function": "^10.0.3",
|
|
||||||
"jss-plugin-vendor-prefixer": "^10.0.3",
|
|
||||||
"prop-types": "^15.7.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@material-ui/system": {
|
|
||||||
"version": "4.9.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.9.14.tgz",
|
|
||||||
"integrity": "sha512-oQbaqfSnNlEkXEziDcJDDIy8pbvwUmZXWNqlmIwDqr/ZdCK8FuV3f4nxikUh7hvClKV2gnQ9djh5CZFTHkZj3w==",
|
|
||||||
"requires": {
|
|
||||||
"@babel/runtime": "^7.4.4",
|
|
||||||
"@material-ui/utils": "^4.9.6",
|
|
||||||
"csstype": "^2.5.2",
|
|
||||||
"prop-types": "^15.7.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@material-ui/types": {
|
|
||||||
"version": "5.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz",
|
|
||||||
"integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A=="
|
|
||||||
},
|
|
||||||
"@material-ui/utils": {
|
|
||||||
"version": "4.9.12",
|
|
||||||
"resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.9.12.tgz",
|
|
||||||
"integrity": "sha512-/0rgZPEOcZq5CFA4+4n6Q6zk7fi8skHhH2Bcra8R3epoJEYy5PL55LuMazPtPH1oKeRausDV/Omz4BbgFsn1HQ==",
|
|
||||||
"requires": {
|
|
||||||
"@babel/runtime": "^7.4.4",
|
|
||||||
"prop-types": "^15.7.2",
|
|
||||||
"react-is": "^16.8.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@microsoft/applicationinsights-analytics-js": {
|
"@microsoft/applicationinsights-analytics-js": {
|
||||||
"version": "2.5.4",
|
"version": "2.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-analytics-js/-/applicationinsights-analytics-js-2.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-analytics-js/-/applicationinsights-analytics-js-2.5.4.tgz",
|
||||||
@ -3371,14 +3276,6 @@
|
|||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@types/react-transition-group": {
|
|
||||||
"version": "4.2.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.2.4.tgz",
|
|
||||||
"integrity": "sha512-8DMUaDqh0S70TjkqU0DxOu80tFUiiaS9rxkWip/nb7gtvAsbqOXm02UCmR8zdcjWujgeYPiPNTVpVpKzUDotwA==",
|
|
||||||
"requires": {
|
|
||||||
"@types/react": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@types/shallowequal": {
|
"@types/shallowequal": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/shallowequal/-/shallowequal-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/shallowequal/-/shallowequal-1.1.1.tgz",
|
||||||
@ -5624,11 +5521,6 @@
|
|||||||
"integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
|
"integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"clsx": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.0.tgz",
|
|
||||||
"integrity": "sha512-3avwM37fSK5oP6M5rQ9CNe99lwxhXDOeSWVPAOYF6OazUTgZCMb0yWlJpmdD74REy1gkEaFiub2ULv4fq9GUhA=="
|
|
||||||
},
|
|
||||||
"co": {
|
"co": {
|
||||||
"version": "4.6.0",
|
"version": "4.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||||
@ -6193,15 +6085,6 @@
|
|||||||
"postcss-value-parser": "^3.3.0"
|
"postcss-value-parser": "^3.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"css-vendor": {
|
|
||||||
"version": "2.0.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz",
|
|
||||||
"integrity": "sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==",
|
|
||||||
"requires": {
|
|
||||||
"@babel/runtime": "^7.8.3",
|
|
||||||
"is-in-browser": "^1.0.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"css-what": {
|
"css-what": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz",
|
||||||
@ -9915,11 +9798,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"hyphenate-style-name": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz",
|
|
||||||
"integrity": "sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ=="
|
|
||||||
},
|
|
||||||
"iconv-lite": {
|
"iconv-lite": {
|
||||||
"version": "0.4.24",
|
"version": "0.4.24",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||||
@ -10459,11 +10337,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz",
|
||||||
"integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw=="
|
"integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw=="
|
||||||
},
|
},
|
||||||
"is-in-browser": {
|
|
||||||
"version": "1.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz",
|
|
||||||
"integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU="
|
|
||||||
},
|
|
||||||
"is-number": {
|
"is-number": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
|
||||||
@ -11333,83 +11206,6 @@
|
|||||||
"verror": "1.10.0"
|
"verror": "1.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"jss": {
|
|
||||||
"version": "10.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/jss/-/jss-10.1.1.tgz",
|
|
||||||
"integrity": "sha512-Xz3qgRUFlxbWk1czCZibUJqhVPObrZHxY3FPsjCXhDld4NOj1BgM14Ir5hVm+Qr6OLqVljjGvoMcCdXNOAbdkQ==",
|
|
||||||
"requires": {
|
|
||||||
"@babel/runtime": "^7.3.1",
|
|
||||||
"csstype": "^2.6.5",
|
|
||||||
"is-in-browser": "^1.1.3",
|
|
||||||
"tiny-warning": "^1.0.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"jss-plugin-camel-case": {
|
|
||||||
"version": "10.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.1.1.tgz",
|
|
||||||
"integrity": "sha512-MDIaw8FeD5uFz1seQBKz4pnvDLnj5vIKV5hXSVdMaAVq13xR6SVTVWkIV/keyTs5txxTvzGJ9hXoxgd1WTUlBw==",
|
|
||||||
"requires": {
|
|
||||||
"@babel/runtime": "^7.3.1",
|
|
||||||
"hyphenate-style-name": "^1.0.3",
|
|
||||||
"jss": "10.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"jss-plugin-default-unit": {
|
|
||||||
"version": "10.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.1.1.tgz",
|
|
||||||
"integrity": "sha512-UkeVCA/b3QEA4k0nIKS4uWXDCNmV73WLHdh2oDGZZc3GsQtlOCuiH3EkB/qI60v2MiCq356/SYWsDXt21yjwdg==",
|
|
||||||
"requires": {
|
|
||||||
"@babel/runtime": "^7.3.1",
|
|
||||||
"jss": "10.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"jss-plugin-global": {
|
|
||||||
"version": "10.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.1.1.tgz",
|
|
||||||
"integrity": "sha512-VBG3wRyi3Z8S4kMhm8rZV6caYBegsk+QnQZSVmrWw6GVOT/Z4FA7eyMu5SdkorDlG/HVpHh91oFN56O4R9m2VA==",
|
|
||||||
"requires": {
|
|
||||||
"@babel/runtime": "^7.3.1",
|
|
||||||
"jss": "10.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"jss-plugin-nested": {
|
|
||||||
"version": "10.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.1.1.tgz",
|
|
||||||
"integrity": "sha512-ozEu7ZBSVrMYxSDplPX3H82XHNQk2DQEJ9TEyo7OVTPJ1hEieqjDFiOQOxXEj9z3PMqkylnUbvWIZRDKCFYw5Q==",
|
|
||||||
"requires": {
|
|
||||||
"@babel/runtime": "^7.3.1",
|
|
||||||
"jss": "10.1.1",
|
|
||||||
"tiny-warning": "^1.0.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"jss-plugin-props-sort": {
|
|
||||||
"version": "10.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.1.1.tgz",
|
|
||||||
"integrity": "sha512-g/joK3eTDZB4pkqpZB38257yD4LXB0X15jxtZAGbUzcKAVUHPl9Jb47Y7lYmiGsShiV4YmQRqG1p2DHMYoK91g==",
|
|
||||||
"requires": {
|
|
||||||
"@babel/runtime": "^7.3.1",
|
|
||||||
"jss": "10.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"jss-plugin-rule-value-function": {
|
|
||||||
"version": "10.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.1.1.tgz",
|
|
||||||
"integrity": "sha512-ClV1lvJ3laU9la1CUzaDugEcwnpjPTuJ0yGy2YtcU+gG/w9HMInD5vEv7xKAz53Bk4WiJm5uLOElSEshHyhKNw==",
|
|
||||||
"requires": {
|
|
||||||
"@babel/runtime": "^7.3.1",
|
|
||||||
"jss": "10.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"jss-plugin-vendor-prefixer": {
|
|
||||||
"version": "10.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.1.1.tgz",
|
|
||||||
"integrity": "sha512-09MZpQ6onQrhaVSF6GHC4iYifQ7+4YC/tAP6D4ZWeZotvCMq1mHLqNKRIaqQ2lkgANjlEot2JnVi1ktu4+L4pw==",
|
|
||||||
"requires": {
|
|
||||||
"@babel/runtime": "^7.3.1",
|
|
||||||
"css-vendor": "^2.0.7",
|
|
||||||
"jss": "10.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"jsx-ast-utils": {
|
"jsx-ast-utils": {
|
||||||
"version": "2.2.3",
|
"version": "2.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.2.3.tgz",
|
||||||
@ -16795,11 +16591,6 @@
|
|||||||
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
|
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"tiny-warning": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
|
|
||||||
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
|
|
||||||
},
|
|
||||||
"tinycolor2": {
|
"tinycolor2": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz",
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
"@azure/cosmos-language-service": "0.0.4",
|
"@azure/cosmos-language-service": "0.0.4",
|
||||||
"@jupyterlab/services": "4.2.0",
|
"@jupyterlab/services": "4.2.0",
|
||||||
"@jupyterlab/terminal": "1.2.1",
|
"@jupyterlab/terminal": "1.2.1",
|
||||||
"@material-ui/core": "4.9.10",
|
|
||||||
"@microsoft/applicationinsights-web": "2.5.4",
|
"@microsoft/applicationinsights-web": "2.5.4",
|
||||||
"@nteract/commutable": "7.1.4",
|
"@nteract/commutable": "7.1.4",
|
||||||
"@nteract/connected-components": "6.7.8",
|
"@nteract/connected-components": "6.7.8",
|
||||||
|
@ -738,6 +738,8 @@ export interface GitHubInfoJunoResponse {
|
|||||||
gitUrl: string;
|
gitUrl: string;
|
||||||
htmlUrl: string;
|
htmlUrl: string;
|
||||||
metadata?: NotebookMetadata;
|
metadata?: NotebookMetadata;
|
||||||
|
officialSamplesIndex?: number;
|
||||||
|
isLikedNotebook?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LikedNotebooksJunoResponse {
|
export interface LikedNotebooksJunoResponse {
|
||||||
|
@ -229,7 +229,12 @@ export interface Explorer {
|
|||||||
importAndOpenFromGallery: (path: string, newName: string, content: any) => Promise<boolean>;
|
importAndOpenFromGallery: (path: string, newName: string, content: any) => Promise<boolean>;
|
||||||
openNotebookTerminal: (kind: TerminalKind) => void;
|
openNotebookTerminal: (kind: TerminalKind) => void;
|
||||||
openGallery: () => void;
|
openGallery: () => void;
|
||||||
openNotebookViewer: (notebookUrl: string, notebookMetadata: DataModels.NotebookMetadata) => void;
|
openNotebookViewer: (
|
||||||
|
notebookUrl: string,
|
||||||
|
notebookMetadata: DataModels.NotebookMetadata,
|
||||||
|
onNotebookMetadataChange: (newNotebookMetadata: DataModels.NotebookMetadata) => Promise<void>,
|
||||||
|
isLikedNotebook: boolean
|
||||||
|
) => void;
|
||||||
notebookWorkspaceManager: NotebookWorkspaceManager;
|
notebookWorkspaceManager: NotebookWorkspaceManager;
|
||||||
sparkClusterManager: SparkClusterManager;
|
sparkClusterManager: SparkClusterManager;
|
||||||
notebookContentProvider: IContentProvider;
|
notebookContentProvider: IContentProvider;
|
||||||
@ -887,6 +892,8 @@ export interface NotebookViewerTabOptions extends TabOptions {
|
|||||||
notebookUrl: string;
|
notebookUrl: string;
|
||||||
notebookName: string;
|
notebookName: string;
|
||||||
notebookMetadata: DataModels.NotebookMetadata;
|
notebookMetadata: DataModels.NotebookMetadata;
|
||||||
|
onNotebookMetadataChange: (newNotebookMetadata: DataModels.NotebookMetadata) => Promise<void>;
|
||||||
|
isLikedNotebook: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DocumentsTabOptions extends TabOptions {
|
export interface DocumentsTabOptions extends TabOptions {
|
||||||
|
@ -22,11 +22,28 @@ export const subtleHelpfulTextStyles: ITextStyles = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const iconButtonStyles: IIconStyles = {
|
||||||
|
root: {
|
||||||
|
marginLeft: "10px",
|
||||||
|
color: "#0078D4",
|
||||||
|
backgroundColor: "#FFF",
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeights.regular,
|
||||||
|
display: "inline-block",
|
||||||
|
selectors: {
|
||||||
|
":hover .ms-Button-icon": {
|
||||||
|
color: "#ccc"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const iconStyles: IIconStyles = {
|
export const iconStyles: IIconStyles = {
|
||||||
root: {
|
root: {
|
||||||
marginLeft: "10px",
|
marginLeft: "10px",
|
||||||
color: "#0078D4",
|
color: "#0078D4",
|
||||||
fontSize: 12,
|
backgroundColor: "#FFF",
|
||||||
|
fontSize: 16,
|
||||||
fontWeight: FontWeights.regular,
|
fontWeight: FontWeights.regular,
|
||||||
display: "inline-block"
|
display: "inline-block"
|
||||||
}
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { shallow } from "enzyme";
|
||||||
|
import { GalleryCardComponent, GalleryCardComponentProps } from "./GalleryCardComponent";
|
||||||
|
|
||||||
|
describe("GalleryCardComponent", () => {
|
||||||
|
it("renders", () => {
|
||||||
|
const props: GalleryCardComponentProps = {
|
||||||
|
name: "mycard",
|
||||||
|
url: "url",
|
||||||
|
notebookMetadata: undefined,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
|
onClick: () => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
const wrapper = shallow(<GalleryCardComponent {...props} />);
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
@ -1,5 +1,5 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import * as DataModels from "../../Contracts/DataModels";
|
import * as DataModels from "../../../../Contracts/DataModels";
|
||||||
import { Card, ICardTokens, ICardSectionTokens } from "@uifabric/react-cards";
|
import { Card, ICardTokens, ICardSectionTokens } from "@uifabric/react-cards";
|
||||||
import { Icon, Image, Persona, Text } from "office-ui-fabric-react";
|
import { Icon, Image, Persona, Text } from "office-ui-fabric-react";
|
||||||
import {
|
import {
|
||||||
@ -10,7 +10,7 @@ import {
|
|||||||
subtleIconStyles
|
subtleIconStyles
|
||||||
} from "./CardStyleConstants";
|
} from "./CardStyleConstants";
|
||||||
|
|
||||||
interface GalleryCardComponentProps {
|
export interface GalleryCardComponentProps {
|
||||||
name: string;
|
name: string;
|
||||||
url: string;
|
url: string;
|
||||||
notebookMetadata: DataModels.NotebookMetadata;
|
notebookMetadata: DataModels.NotebookMetadata;
|
@ -0,0 +1,28 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`GalleryCardComponent renders 1`] = `
|
||||||
|
<Card
|
||||||
|
aria-label="Notebook Card"
|
||||||
|
onClick={[Function]}
|
||||||
|
tokens={
|
||||||
|
Object {
|
||||||
|
"childrenMargin": 12,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<CardSection>
|
||||||
|
<Text
|
||||||
|
styles={
|
||||||
|
Object {
|
||||||
|
"root": Object {
|
||||||
|
"color": "#333333",
|
||||||
|
"fontWeight": 600,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
mycard
|
||||||
|
</Text>
|
||||||
|
</CardSection>
|
||||||
|
</Card>
|
||||||
|
`;
|
@ -0,0 +1,9 @@
|
|||||||
|
@import "../../../../less/Common/Constants";
|
||||||
|
|
||||||
|
.galleryContainer {
|
||||||
|
padding: @LargeSpace @LargeSpace 30px @LargeSpace;
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
width: 100%;
|
||||||
|
font-family: @DataExplorerFont;
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { shallow } from "enzyme";
|
||||||
|
import {
|
||||||
|
GalleryViewerContainerComponent,
|
||||||
|
GalleryViewerContainerComponentProps,
|
||||||
|
FullWidthTabs,
|
||||||
|
FullWidthTabsProps,
|
||||||
|
GalleryCardsComponent,
|
||||||
|
GalleryCardsComponentProps,
|
||||||
|
GalleryViewerComponent,
|
||||||
|
GalleryViewerComponentProps
|
||||||
|
} from "./GalleryViewerComponent";
|
||||||
|
import * as DataModels from "../../../Contracts/DataModels";
|
||||||
|
|
||||||
|
describe("GalleryCardsComponent", () => {
|
||||||
|
it("renders", () => {
|
||||||
|
// TODO Mock this
|
||||||
|
const props: GalleryCardsComponentProps = {
|
||||||
|
data: [],
|
||||||
|
userMetadata: undefined,
|
||||||
|
onNotebookMetadataChange: (officialSamplesIndex: number, notebookMetadata: DataModels.NotebookMetadata) =>
|
||||||
|
Promise.resolve(),
|
||||||
|
onClick: (
|
||||||
|
url: string,
|
||||||
|
notebookMetadata: DataModels.NotebookMetadata,
|
||||||
|
onNotebookMetadataChange: (newNotebookMetadata: DataModels.NotebookMetadata) => Promise<void>,
|
||||||
|
isLikedNotebook: boolean
|
||||||
|
) => Promise.resolve()
|
||||||
|
};
|
||||||
|
|
||||||
|
const wrapper = shallow(<GalleryCardsComponent {...props} />);
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("FullWidthTabs", () => {
|
||||||
|
it("renders", () => {
|
||||||
|
const props: FullWidthTabsProps = {
|
||||||
|
officialSamplesContent: [],
|
||||||
|
likedNotebooksContent: [],
|
||||||
|
userMetadata: undefined,
|
||||||
|
onClick: (
|
||||||
|
url: string,
|
||||||
|
notebookMetadata: DataModels.NotebookMetadata,
|
||||||
|
onNotebookMetadataChange: (newNotebookMetadata: DataModels.NotebookMetadata) => Promise<void>,
|
||||||
|
isLikedNotebook: boolean
|
||||||
|
) => Promise.resolve()
|
||||||
|
};
|
||||||
|
|
||||||
|
const wrapper = shallow(<FullWidthTabs {...props} />);
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("GalleryViewerContainerComponent", () => {
|
||||||
|
it("renders", () => {
|
||||||
|
const props: GalleryViewerContainerComponentProps = {
|
||||||
|
container: undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
const wrapper = shallow(<GalleryViewerContainerComponent {...props} />);
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("GalleryCardComponent", () => {
|
||||||
|
it("renders", () => {
|
||||||
|
const props: GalleryViewerComponentProps = {
|
||||||
|
container: undefined,
|
||||||
|
officialSamplesData: [],
|
||||||
|
likedNotebookData: undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
const wrapper = shallow(<GalleryViewerComponent {...props} />);
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
356
src/Explorer/Controls/NotebookGallery/GalleryViewerComponent.tsx
Normal file
356
src/Explorer/Controls/NotebookGallery/GalleryViewerComponent.tsx
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
/**
|
||||||
|
* Gallery Viewer
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as React from "react";
|
||||||
|
import * as DataModels from "../../../Contracts/DataModels";
|
||||||
|
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||||
|
import { GalleryCardComponent } from "./Cards/GalleryCardComponent";
|
||||||
|
import { Stack, IStackTokens } from "office-ui-fabric-react";
|
||||||
|
import { JunoUtils } from "../../../Utils/JunoUtils";
|
||||||
|
import { CosmosClient } from "../../../Common/CosmosClient";
|
||||||
|
import { config } from "../../../Config";
|
||||||
|
import path from "path";
|
||||||
|
import { SessionStorageUtility, StorageKey } from "../../../Shared/StorageUtility";
|
||||||
|
import { NotificationConsoleUtils } from "../../../Utils/NotificationConsoleUtils";
|
||||||
|
import { ConsoleDataType } from "../../Menus/NotificationConsole/NotificationConsoleComponent";
|
||||||
|
import * as TabComponent from "../Tabs/TabComponent";
|
||||||
|
|
||||||
|
import "./GalleryViewerComponent.less";
|
||||||
|
|
||||||
|
export interface GalleryCardsComponentProps {
|
||||||
|
data: DataModels.GitHubInfoJunoResponse[];
|
||||||
|
userMetadata: DataModels.UserMetadata;
|
||||||
|
onNotebookMetadataChange: (
|
||||||
|
officialSamplesIndex: number,
|
||||||
|
notebookMetadata: DataModels.NotebookMetadata
|
||||||
|
) => Promise<void>;
|
||||||
|
onClick: (
|
||||||
|
url: string,
|
||||||
|
notebookMetadata: DataModels.NotebookMetadata,
|
||||||
|
onNotebookMetadataChange: (newNotebookMetadata: DataModels.NotebookMetadata) => Promise<void>,
|
||||||
|
isLikedNotebook: boolean
|
||||||
|
) => Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class GalleryCardsComponent extends React.Component<GalleryCardsComponentProps> {
|
||||||
|
private sectionStackTokens: IStackTokens = { childrenGap: 30 };
|
||||||
|
|
||||||
|
public render(): JSX.Element {
|
||||||
|
return (
|
||||||
|
<Stack horizontal wrap tokens={this.sectionStackTokens}>
|
||||||
|
{this.props.data.map((githubInfo: DataModels.GitHubInfoJunoResponse, index: any) => {
|
||||||
|
const name = githubInfo.name;
|
||||||
|
const url = githubInfo.downloadUrl;
|
||||||
|
const notebookMetadata = githubInfo.metadata || {
|
||||||
|
date: "2008-12-01",
|
||||||
|
description: "Great notebook",
|
||||||
|
tags: ["favorite", "sample"],
|
||||||
|
author: "Laurent Nguyen",
|
||||||
|
views: 432,
|
||||||
|
likes: 123,
|
||||||
|
downloads: 56,
|
||||||
|
imageUrl:
|
||||||
|
"https://media.magazine.ferrari.com/images/2019/02/27/170304506-c1bcf028-b513-45f6-9f27-0cadac619c3d.jpg"
|
||||||
|
};
|
||||||
|
const officialSamplesIndex = githubInfo.officialSamplesIndex;
|
||||||
|
const isLikedNotebook = githubInfo.isLikedNotebook;
|
||||||
|
const updateTabsStatePerNotebook = this.props.onNotebookMetadataChange
|
||||||
|
? (notebookMetadata: DataModels.NotebookMetadata) =>
|
||||||
|
this.props.onNotebookMetadataChange(officialSamplesIndex, notebookMetadata)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
return (
|
||||||
|
name !== ".gitignore" &&
|
||||||
|
url && (
|
||||||
|
<GalleryCardComponent
|
||||||
|
key={url}
|
||||||
|
name={name}
|
||||||
|
url={url}
|
||||||
|
notebookMetadata={notebookMetadata}
|
||||||
|
onClick={() => this.props.onClick(url, notebookMetadata, updateTabsStatePerNotebook, isLikedNotebook)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FullWidthTabsProps {
|
||||||
|
officialSamplesContent: DataModels.GitHubInfoJunoResponse[];
|
||||||
|
likedNotebooksContent: DataModels.GitHubInfoJunoResponse[];
|
||||||
|
userMetadata: DataModels.UserMetadata;
|
||||||
|
onClick: (
|
||||||
|
url: string,
|
||||||
|
notebookMetadata: DataModels.NotebookMetadata,
|
||||||
|
onNotebookMetadataChange: (newNotebookMetadata: DataModels.NotebookMetadata) => Promise<void>,
|
||||||
|
isLikedNotebook: boolean
|
||||||
|
) => Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FullWidthTabsState {
|
||||||
|
activeTabIndex: number;
|
||||||
|
officialSamplesContent: DataModels.GitHubInfoJunoResponse[];
|
||||||
|
likedNotebooksContent: DataModels.GitHubInfoJunoResponse[];
|
||||||
|
userMetadata: DataModels.UserMetadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class FullWidthTabs extends React.Component<FullWidthTabsProps, FullWidthTabsState> {
|
||||||
|
private authorizationToken = CosmosClient.authorizationToken();
|
||||||
|
private appTabs: TabComponent.Tab[];
|
||||||
|
|
||||||
|
constructor(props: FullWidthTabsProps) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
activeTabIndex: 0,
|
||||||
|
officialSamplesContent: this.props.officialSamplesContent,
|
||||||
|
likedNotebooksContent: this.props.likedNotebooksContent,
|
||||||
|
userMetadata: this.props.userMetadata
|
||||||
|
};
|
||||||
|
|
||||||
|
this.appTabs = [
|
||||||
|
{
|
||||||
|
title: "Official Samples",
|
||||||
|
content: {
|
||||||
|
className: "",
|
||||||
|
render: () => (
|
||||||
|
<GalleryCardsComponent
|
||||||
|
data={this.state.officialSamplesContent}
|
||||||
|
onClick={this.props.onClick}
|
||||||
|
userMetadata={this.state.userMetadata}
|
||||||
|
onNotebookMetadataChange={this.updateTabsState}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
isVisible: () => true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Liked Notebooks",
|
||||||
|
content: {
|
||||||
|
className: "",
|
||||||
|
render: () => (
|
||||||
|
<GalleryCardsComponent
|
||||||
|
data={this.state.likedNotebooksContent}
|
||||||
|
onClick={this.props.onClick}
|
||||||
|
userMetadata={this.state.userMetadata}
|
||||||
|
onNotebookMetadataChange={this.updateTabsState}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
isVisible: () => true
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public updateTabsState = async (officialSamplesIndex: number, notebookMetadata: DataModels.NotebookMetadata) => {
|
||||||
|
let currentLikedNotebooksContent = [...this.state.likedNotebooksContent];
|
||||||
|
let currentUserMetadata = { ...this.state.userMetadata };
|
||||||
|
let currentLikedNotebooks = [...currentUserMetadata.likedNotebooks];
|
||||||
|
|
||||||
|
const currentOfficialSamplesContent = [...this.state.officialSamplesContent];
|
||||||
|
const currentOfficialSamplesObject = { ...currentOfficialSamplesContent[officialSamplesIndex] };
|
||||||
|
const metadata = { ...currentOfficialSamplesObject.metadata };
|
||||||
|
const metadataLikesUpdates = metadata.likes - notebookMetadata.likes;
|
||||||
|
|
||||||
|
metadata.views = notebookMetadata.views;
|
||||||
|
metadata.downloads = notebookMetadata.downloads;
|
||||||
|
metadata.likes = notebookMetadata.likes;
|
||||||
|
currentOfficialSamplesObject.metadata = metadata;
|
||||||
|
|
||||||
|
// Notebook has been liked. Add To likedNotebooksContent, update isLikedNotebook flag
|
||||||
|
if (metadataLikesUpdates < 0) {
|
||||||
|
currentOfficialSamplesObject.isLikedNotebook = true;
|
||||||
|
currentLikedNotebooksContent = currentLikedNotebooksContent.concat(currentOfficialSamplesObject);
|
||||||
|
currentLikedNotebooks = currentLikedNotebooks.concat(currentOfficialSamplesObject.path);
|
||||||
|
currentUserMetadata = { likedNotebooks: currentLikedNotebooks };
|
||||||
|
} else if (metadataLikesUpdates > 0) {
|
||||||
|
// Notebook has been unliked. Remove from likedNotebooksContent after matching the path, update isLikedNotebook flag
|
||||||
|
|
||||||
|
currentOfficialSamplesObject.isLikedNotebook = false;
|
||||||
|
const likedNotebookIndex = currentLikedNotebooks.findIndex((path: string) => {
|
||||||
|
return path === currentOfficialSamplesObject.path;
|
||||||
|
});
|
||||||
|
currentLikedNotebooksContent.splice(likedNotebookIndex, 1);
|
||||||
|
currentLikedNotebooks.splice(likedNotebookIndex, 1);
|
||||||
|
currentUserMetadata = { likedNotebooks: currentLikedNotebooks };
|
||||||
|
}
|
||||||
|
|
||||||
|
currentOfficialSamplesContent[officialSamplesIndex] = currentOfficialSamplesObject;
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
activeTabIndex: 0,
|
||||||
|
userMetadata: currentUserMetadata,
|
||||||
|
likedNotebooksContent: currentLikedNotebooksContent,
|
||||||
|
officialSamplesContent: currentOfficialSamplesContent
|
||||||
|
});
|
||||||
|
|
||||||
|
JunoUtils.updateNotebookMetadata(this.authorizationToken, notebookMetadata).then(
|
||||||
|
async returnedNotebookMetadata => {
|
||||||
|
if (metadataLikesUpdates !== 0) {
|
||||||
|
JunoUtils.updateUserMetadata(this.authorizationToken, currentUserMetadata);
|
||||||
|
// TODO: update state here?
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
NotificationConsoleUtils.logConsoleMessage(
|
||||||
|
ConsoleDataType.Error,
|
||||||
|
`Error updating notebook metadata: ${JSON.stringify(error)}`
|
||||||
|
);
|
||||||
|
// TODO add telemetry
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
private onTabIndexChange = (activeTabIndex: number) => this.setState({ activeTabIndex });
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
return (
|
||||||
|
<TabComponent.TabComponent
|
||||||
|
tabs={this.appTabs}
|
||||||
|
onTabIndexChange={this.onTabIndexChange.bind(this)}
|
||||||
|
currentTabIndex={this.state.activeTabIndex}
|
||||||
|
hideHeader={false}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GalleryViewerContainerComponentProps {
|
||||||
|
container: ViewModels.Explorer;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GalleryViewerContainerComponentState {
|
||||||
|
officialSamplesData: DataModels.GitHubInfoJunoResponse[];
|
||||||
|
likedNotebooksData: DataModels.LikedNotebooksJunoResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class GalleryViewerContainerComponent extends React.Component<
|
||||||
|
GalleryViewerContainerComponentProps,
|
||||||
|
GalleryViewerContainerComponentState
|
||||||
|
> {
|
||||||
|
constructor(props: GalleryViewerContainerComponentProps) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
officialSamplesData: undefined,
|
||||||
|
likedNotebooksData: undefined
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const authToken = CosmosClient.authorizationToken();
|
||||||
|
JunoUtils.getOfficialSampleNotebooks(authToken).then(
|
||||||
|
(data1: DataModels.GitHubInfoJunoResponse[]) => {
|
||||||
|
const officialSamplesData = data1;
|
||||||
|
|
||||||
|
JunoUtils.getLikedNotebooks(authToken).then(
|
||||||
|
(data2: DataModels.LikedNotebooksJunoResponse) => {
|
||||||
|
const likedNotebooksData = data2;
|
||||||
|
|
||||||
|
officialSamplesData.map((value: DataModels.GitHubInfoJunoResponse, index: number) => {
|
||||||
|
value.officialSamplesIndex = index;
|
||||||
|
value.isLikedNotebook = likedNotebooksData.userMetadata.likedNotebooks.includes(value.path);
|
||||||
|
});
|
||||||
|
|
||||||
|
likedNotebooksData.likedNotebooksContent.map((value: DataModels.GitHubInfoJunoResponse) => {
|
||||||
|
value.isLikedNotebook = true;
|
||||||
|
value.officialSamplesIndex = officialSamplesData.findIndex(
|
||||||
|
(officialSample: DataModels.GitHubInfoJunoResponse) => {
|
||||||
|
return officialSample.path === value.path;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
officialSamplesData: officialSamplesData,
|
||||||
|
likedNotebooksData: likedNotebooksData
|
||||||
|
});
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
NotificationConsoleUtils.logConsoleMessage(
|
||||||
|
ConsoleDataType.Error,
|
||||||
|
`Error fetching liked notebooks: ${JSON.stringify(error)}`
|
||||||
|
);
|
||||||
|
// TODO Add telemetry
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
NotificationConsoleUtils.logConsoleMessage(
|
||||||
|
ConsoleDataType.Error,
|
||||||
|
`Error fetching sample notebooks: ${JSON.stringify(error)}`
|
||||||
|
);
|
||||||
|
// TODO Add telemetry
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public render(): JSX.Element {
|
||||||
|
return this.state.officialSamplesData && this.state.likedNotebooksData ? (
|
||||||
|
<GalleryViewerComponent
|
||||||
|
container={this.props.container}
|
||||||
|
officialSamplesData={this.state.officialSamplesData}
|
||||||
|
likedNotebookData={this.state.likedNotebooksData}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GalleryViewerComponentProps {
|
||||||
|
container: ViewModels.Explorer;
|
||||||
|
officialSamplesData: DataModels.GitHubInfoJunoResponse[];
|
||||||
|
likedNotebookData: DataModels.LikedNotebooksJunoResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class GalleryViewerComponent extends React.Component<GalleryViewerComponentProps> {
|
||||||
|
public render(): JSX.Element {
|
||||||
|
return this.props.container ? (
|
||||||
|
<div className="galleryContainer">
|
||||||
|
<FullWidthTabs
|
||||||
|
officialSamplesContent={this.props.officialSamplesData}
|
||||||
|
likedNotebooksContent={this.props.likedNotebookData.likedNotebooksContent}
|
||||||
|
userMetadata={this.props.likedNotebookData.userMetadata}
|
||||||
|
onClick={this.openNotebookViewer}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="galleryContainer">
|
||||||
|
<GalleryCardsComponent
|
||||||
|
data={this.props.officialSamplesData}
|
||||||
|
onClick={this.openNotebookViewer}
|
||||||
|
userMetadata={undefined}
|
||||||
|
onNotebookMetadataChange={undefined}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getOfficialSamplesData(): DataModels.GitHubInfoJunoResponse[] {
|
||||||
|
return this.props.officialSamplesData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getLikedNotebookData(): DataModels.LikedNotebooksJunoResponse {
|
||||||
|
return this.props.likedNotebookData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public openNotebookViewer = async (
|
||||||
|
url: string,
|
||||||
|
notebookMetadata: DataModels.NotebookMetadata,
|
||||||
|
onNotebookMetadataChange: (newNotebookMetadata: DataModels.NotebookMetadata) => Promise<void>,
|
||||||
|
isLikedNotebook: boolean
|
||||||
|
) => {
|
||||||
|
if (!this.props.container) {
|
||||||
|
SessionStorageUtility.setEntryString(
|
||||||
|
StorageKey.NotebookMetadata,
|
||||||
|
notebookMetadata ? JSON.stringify(notebookMetadata) : null
|
||||||
|
);
|
||||||
|
SessionStorageUtility.setEntryString(StorageKey.NotebookName, path.basename(url));
|
||||||
|
window.open(`${config.hostedExplorerURL}notebookViewer.html?notebookurl=${url}`, "_blank");
|
||||||
|
} else {
|
||||||
|
this.props.container.openNotebookViewer(url, notebookMetadata, onNotebookMetadataChange, isLikedNotebook);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`FullWidthTabs renders 1`] = `
|
||||||
|
<TabComponent
|
||||||
|
currentTabIndex={0}
|
||||||
|
hideHeader={false}
|
||||||
|
onTabIndexChange={[Function]}
|
||||||
|
tabs={
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"content": Object {
|
||||||
|
"className": "",
|
||||||
|
"render": [Function],
|
||||||
|
},
|
||||||
|
"isVisible": [Function],
|
||||||
|
"title": "Official Samples",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"content": Object {
|
||||||
|
"className": "",
|
||||||
|
"render": [Function],
|
||||||
|
},
|
||||||
|
"isVisible": [Function],
|
||||||
|
"title": "Liked Notebooks",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`GalleryCardComponent renders 1`] = `
|
||||||
|
<div
|
||||||
|
className="galleryContainer"
|
||||||
|
>
|
||||||
|
<GalleryCardsComponent
|
||||||
|
data={Array []}
|
||||||
|
onClick={[Function]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`GalleryCardsComponent renders 1`] = `
|
||||||
|
<Stack
|
||||||
|
horizontal={true}
|
||||||
|
tokens={
|
||||||
|
Object {
|
||||||
|
"childrenGap": 30,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wrap={true}
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`GalleryViewerContainerComponent renders 1`] = `<Fragment />`;
|
@ -0,0 +1,11 @@
|
|||||||
|
.notebookViewerMetadataContainer {
|
||||||
|
margin: 0px 10px;
|
||||||
|
|
||||||
|
.title, .decoration, .persona {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.extras {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { shallow } from "enzyme";
|
||||||
|
import { NotebookMetadataComponentProps, NotebookMetadataComponent } from "./NotebookMetadataComponent";
|
||||||
|
import { NotebookMetadata } from "../../../Contracts/DataModels";
|
||||||
|
|
||||||
|
describe("NotebookMetadataComponent", () => {
|
||||||
|
it("renders un-liked notebook", () => {
|
||||||
|
const props: NotebookMetadataComponentProps = {
|
||||||
|
notebookName: "My notebook",
|
||||||
|
container: undefined,
|
||||||
|
notebookMetadata: undefined,
|
||||||
|
notebookContent: {},
|
||||||
|
onNotebookMetadataChange: (newNotebookMetadata: NotebookMetadata) => Promise.resolve(),
|
||||||
|
isLikedNotebook: false
|
||||||
|
};
|
||||||
|
|
||||||
|
const wrapper = shallow(<NotebookMetadataComponent {...props} />);
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders liked notebook", () => {
|
||||||
|
const props: NotebookMetadataComponentProps = {
|
||||||
|
notebookName: "My notebook",
|
||||||
|
container: undefined,
|
||||||
|
notebookMetadata: undefined,
|
||||||
|
notebookContent: {},
|
||||||
|
onNotebookMetadataChange: (newNotebookMetadata: NotebookMetadata) => Promise.resolve(),
|
||||||
|
isLikedNotebook: true
|
||||||
|
};
|
||||||
|
|
||||||
|
const wrapper = shallow(<NotebookMetadataComponent {...props} />);
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO Add test for metadata display
|
||||||
|
});
|
@ -6,47 +6,97 @@ import * as React from "react";
|
|||||||
import * as ViewModels from "../../../Contracts/ViewModels";
|
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||||
import { NotebookMetadata } from "../../../Contracts/DataModels";
|
import { NotebookMetadata } from "../../../Contracts/DataModels";
|
||||||
import { initializeIcons } from "office-ui-fabric-react/lib/Icons";
|
import { initializeIcons } from "office-ui-fabric-react/lib/Icons";
|
||||||
import { Icon, Persona, Text } from "office-ui-fabric-react";
|
import { Icon, Persona, Text, IconButton } from "office-ui-fabric-react";
|
||||||
import CSS from "csstype";
|
|
||||||
import {
|
import {
|
||||||
siteTextStyles,
|
siteTextStyles,
|
||||||
subtleIconStyles,
|
subtleIconStyles,
|
||||||
iconStyles,
|
iconStyles,
|
||||||
|
iconButtonStyles,
|
||||||
mainHelpfulTextStyles,
|
mainHelpfulTextStyles,
|
||||||
subtleHelpfulTextStyles,
|
subtleHelpfulTextStyles,
|
||||||
helpfulTextStyles
|
helpfulTextStyles
|
||||||
} from "../../../GalleryViewer/Cards/CardStyleConstants";
|
} from "../NotebookGallery/Cards/CardStyleConstants";
|
||||||
|
|
||||||
|
import "./NotebookViewerComponent.less";
|
||||||
|
|
||||||
initializeIcons();
|
initializeIcons();
|
||||||
|
|
||||||
interface NotebookMetadataComponentProps {
|
export interface NotebookMetadataComponentProps {
|
||||||
notebookName: string;
|
notebookName: string;
|
||||||
container: ViewModels.Explorer;
|
container: ViewModels.Explorer;
|
||||||
notebookMetadata: NotebookMetadata;
|
notebookMetadata: NotebookMetadata;
|
||||||
notebookContent: any;
|
notebookContent: any;
|
||||||
|
onNotebookMetadataChange: (newNotebookMetadata: NotebookMetadata) => Promise<void>;
|
||||||
|
isLikedNotebook: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NotebookMetadataComponent extends React.Component<NotebookMetadataComponentProps> {
|
interface NotebookMetadatComponentState {
|
||||||
private inlineBlockStyle: CSS.Properties = {
|
liked: boolean;
|
||||||
display: "inline-block"
|
notebookMetadata: NotebookMetadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NotebookMetadataComponent extends React.Component<
|
||||||
|
NotebookMetadataComponentProps,
|
||||||
|
NotebookMetadatComponentState
|
||||||
|
> {
|
||||||
|
constructor(props: NotebookMetadataComponentProps) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
liked: this.props.isLikedNotebook,
|
||||||
|
notebookMetadata: this.props.notebookMetadata
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private onDownloadClick = (newNotebookName: string) => {
|
||||||
|
this.props.container
|
||||||
|
.importAndOpenFromGallery(this.props.notebookName, newNotebookName, JSON.stringify(this.props.notebookContent))
|
||||||
|
.then(() => {
|
||||||
|
if (this.props.notebookMetadata) {
|
||||||
|
if (this.props.onNotebookMetadataChange) {
|
||||||
|
const notebookMetadata = { ...this.state.notebookMetadata };
|
||||||
|
notebookMetadata.downloads += 1;
|
||||||
|
this.props.onNotebookMetadataChange(notebookMetadata).then(() => {
|
||||||
|
this.setState({ notebookMetadata: notebookMetadata });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
private marginTopStyle: CSS.Properties = {
|
componentDidMount() {
|
||||||
marginTop: "5px"
|
if (this.props.onNotebookMetadataChange) {
|
||||||
|
const notebookMetadata = { ...this.state.notebookMetadata };
|
||||||
|
if (this.props.notebookMetadata) {
|
||||||
|
notebookMetadata.views += 1;
|
||||||
|
this.props.onNotebookMetadataChange(notebookMetadata).then(() => {
|
||||||
|
this.setState({ notebookMetadata: notebookMetadata });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private onLike = (): void => {
|
||||||
|
if (this.props.onNotebookMetadataChange) {
|
||||||
|
const notebookMetadata = { ...this.state.notebookMetadata };
|
||||||
|
let liked: boolean;
|
||||||
|
if (this.state.liked) {
|
||||||
|
liked = false;
|
||||||
|
notebookMetadata.likes -= 1;
|
||||||
|
} else {
|
||||||
|
liked = true;
|
||||||
|
notebookMetadata.likes += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.props.onNotebookMetadataChange(notebookMetadata).then(() => {
|
||||||
|
this.setState({ liked: liked, notebookMetadata: notebookMetadata });
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private onDownloadClick: (newNotebookName: string) => void = (newNotebookName: string) => {
|
private onDownload = (): void => {
|
||||||
this.props.container.importAndOpenFromGallery(
|
|
||||||
this.props.notebookName,
|
|
||||||
newNotebookName,
|
|
||||||
JSON.stringify(this.props.notebookContent)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
public render(): JSX.Element {
|
|
||||||
const promptForNotebookName = () => {
|
const promptForNotebookName = () => {
|
||||||
return new Promise<string>((resolve, reject) => {
|
return new Promise<string>((resolve, reject) => {
|
||||||
var newNotebookName = this.props.notebookName;
|
let newNotebookName = this.props.notebookName;
|
||||||
this.props.container.showOkCancelTextFieldModalDialog(
|
this.props.container.showOkCancelTextFieldModalDialog(
|
||||||
"Save notebook as",
|
"Save notebook as",
|
||||||
undefined,
|
undefined,
|
||||||
@ -68,27 +118,35 @@ export class NotebookMetadataComponent extends React.Component<NotebookMetadataC
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
promptForNotebookName().then((newNotebookName: string) => {
|
||||||
|
this.onDownloadClick(newNotebookName);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
public render(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div className="notebookViewerMetadataContainer">
|
<div className="notebookViewerMetadataContainer">
|
||||||
<h3 style={this.inlineBlockStyle}>{this.props.notebookName}</h3>
|
<h3 className="title">{this.props.notebookName}</h3>
|
||||||
|
|
||||||
{this.props.notebookMetadata && (
|
{this.props.notebookMetadata && (
|
||||||
<div style={this.inlineBlockStyle}>
|
<div className="decoration">
|
||||||
|
{this.props.container ? (
|
||||||
|
<IconButton
|
||||||
|
iconProps={{ iconName: this.state.liked ? "HeartFill" : "Heart" }}
|
||||||
|
styles={iconButtonStyles}
|
||||||
|
onClick={this.onLike}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
<Icon iconName="Heart" styles={iconStyles} />
|
<Icon iconName="Heart" styles={iconStyles} />
|
||||||
<Text variant="medium" styles={mainHelpfulTextStyles}>
|
)}
|
||||||
{this.props.notebookMetadata.likes} likes
|
<Text variant="large" styles={mainHelpfulTextStyles}>
|
||||||
|
{this.state.notebookMetadata.likes} likes
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{this.props.container && (
|
{this.props.container && (
|
||||||
<button
|
<button aria-label="downloadButton" className="downloadButton" onClick={this.onDownload}>
|
||||||
aria-label="downloadButton"
|
|
||||||
className="downloadButton"
|
|
||||||
onClick={async () => {
|
|
||||||
promptForNotebookName().then(this.onDownloadClick);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Download Notebook
|
Download Notebook
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
@ -97,20 +155,20 @@ export class NotebookMetadataComponent extends React.Component<NotebookMetadataC
|
|||||||
<>
|
<>
|
||||||
<div>
|
<div>
|
||||||
<Persona
|
<Persona
|
||||||
style={this.inlineBlockStyle}
|
className="persona"
|
||||||
text={this.props.notebookMetadata.author}
|
text={this.props.notebookMetadata.author}
|
||||||
secondaryText={this.props.notebookMetadata.date}
|
secondaryText={this.props.notebookMetadata.date}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div style={this.marginTopStyle}>
|
<div className="extras">
|
||||||
<Icon iconName="RedEye" styles={subtleIconStyles} />
|
<Icon iconName="RedEye" styles={subtleIconStyles} />
|
||||||
<Text variant="small" styles={subtleHelpfulTextStyles}>
|
<Text variant="small" styles={subtleHelpfulTextStyles}>
|
||||||
{this.props.notebookMetadata.views}
|
{this.state.notebookMetadata.views}
|
||||||
</Text>
|
</Text>
|
||||||
<Icon iconName="Download" styles={subtleIconStyles} />
|
<Icon iconName="Download" styles={subtleIconStyles} />
|
||||||
<Text variant="small" styles={subtleHelpfulTextStyles}>
|
<Text variant="small" styles={subtleHelpfulTextStyles}>
|
||||||
{this.props.notebookMetadata.downloads}
|
{this.state.notebookMetadata.downloads}
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
<Text variant="small" styles={siteTextStyles}>
|
<Text variant="small" styles={siteTextStyles}>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
padding: @DefaultSpace;
|
padding: @DefaultSpace;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow-y: scroll;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.downloadButton {
|
.downloadButton {
|
||||||
|
@ -16,12 +16,14 @@ import "./NotebookViewerComponent.less";
|
|||||||
export interface NotebookViewerComponentProps {
|
export interface NotebookViewerComponentProps {
|
||||||
notebookName: string;
|
notebookName: string;
|
||||||
notebookUrl: string;
|
notebookUrl: string;
|
||||||
container: ViewModels.Explorer;
|
container?: ViewModels.Explorer;
|
||||||
notebookMetadata: NotebookMetadata;
|
notebookMetadata: NotebookMetadata;
|
||||||
|
onNotebookMetadataChange?: (newNotebookMetadata: NotebookMetadata) => Promise<void>;
|
||||||
|
isLikedNotebook?: boolean;
|
||||||
|
hideInputs?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface NotebookViewerComponentState {
|
interface NotebookViewerComponentState {
|
||||||
element: JSX.Element;
|
|
||||||
content: any;
|
content: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +52,7 @@ export class NotebookViewerComponent extends React.Component<
|
|||||||
contentRef: createContentRef()
|
contentRef: createContentRef()
|
||||||
});
|
});
|
||||||
|
|
||||||
this.state = { element: undefined, content: undefined };
|
this.state = { content: undefined };
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getJsonNotebookContent(): Promise<any> {
|
private async getJsonNotebookContent(): Promise<any> {
|
||||||
@ -65,24 +67,25 @@ export class NotebookViewerComponent extends React.Component<
|
|||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.getJsonNotebookContent().then((jsonContent: any) => {
|
this.getJsonNotebookContent().then((jsonContent: any) => {
|
||||||
this.notebookComponentBootstrapper.setContent("json", jsonContent);
|
this.notebookComponentBootstrapper.setContent("json", jsonContent);
|
||||||
const notebookReadonlyComponent = this.notebookComponentBootstrapper.renderComponent(NotebookReadOnlyRenderer);
|
this.setState({ content: jsonContent });
|
||||||
this.setState({ element: notebookReadonlyComponent, content: jsonContent });
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(): JSX.Element {
|
public render(): JSX.Element {
|
||||||
return this.state != null ? (
|
return (
|
||||||
<div className="notebookViewerContainer">
|
<div className="notebookViewerContainer">
|
||||||
<NotebookMetadataComponent
|
<NotebookMetadataComponent
|
||||||
notebookMetadata={this.props.notebookMetadata}
|
notebookMetadata={this.props.notebookMetadata}
|
||||||
notebookName={this.props.notebookName}
|
notebookName={this.props.notebookName}
|
||||||
container={this.props.container}
|
container={this.props.container}
|
||||||
notebookContent={this.state.content}
|
notebookContent={this.state.content}
|
||||||
|
onNotebookMetadataChange={this.props.onNotebookMetadataChange}
|
||||||
|
isLikedNotebook={this.props.isLikedNotebook}
|
||||||
/>
|
/>
|
||||||
{this.state.element}
|
{this.notebookComponentBootstrapper.renderComponent(NotebookReadOnlyRenderer, {
|
||||||
|
hideInputs: this.props.hideInputs
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`NotebookMetadataComponent renders liked notebook 1`] = `
|
||||||
|
<div
|
||||||
|
className="notebookViewerMetadataContainer"
|
||||||
|
>
|
||||||
|
<h3
|
||||||
|
className="title"
|
||||||
|
>
|
||||||
|
My notebook
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`NotebookMetadataComponent renders un-liked notebook 1`] = `
|
||||||
|
<div
|
||||||
|
className="notebookViewerMetadataContainer"
|
||||||
|
>
|
||||||
|
<h3
|
||||||
|
className="title"
|
||||||
|
>
|
||||||
|
My notebook
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
`;
|
@ -1,6 +1,11 @@
|
|||||||
@import "../../../../less/Common/Constants";
|
@import "../../../../less/Common/Constants";
|
||||||
|
|
||||||
.tabSwitch {
|
.tabComponentContainer {
|
||||||
|
height: 100%;
|
||||||
|
.flex-display();
|
||||||
|
.flex-direction();
|
||||||
|
|
||||||
|
.tabSwitch {
|
||||||
margin-left: @LargeSpace;
|
margin-left: @LargeSpace;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
|
||||||
@ -19,9 +24,5 @@
|
|||||||
.unselectedToggle {
|
.unselectedToggle {
|
||||||
.unselectedToggle();
|
.unselectedToggle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabComponentContent {
|
|
||||||
height: calc(100% - 20px);
|
|
||||||
.flex-display();
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { AccessibleElement } from "../../Controls/AccessibleElement/AccessibleElement";
|
import { AccessibleElement } from "../../Controls/AccessibleElement/AccessibleElement";
|
||||||
|
import "./TabComponent.less";
|
||||||
|
|
||||||
export interface TabContent {
|
export interface TabContent {
|
||||||
render: () => JSX.Element;
|
render: () => JSX.Element;
|
||||||
@ -75,10 +76,10 @@ export class TabComponent extends React.Component<TabComponentProps> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<div className="tabComponentContainer">
|
||||||
{!this.props.hideHeader && <div className="tabs tabSwitch">{this.renderTabTitles()}</div>}
|
{!this.props.hideHeader && <div className="tabs tabSwitch">{this.renderTabTitles()}</div>}
|
||||||
<div className={className}>{currentTabContent.render()}</div>
|
<div className={className}>{currentTabContent.render()}</div>
|
||||||
</React.Fragment>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3278,7 +3278,12 @@ export default class Explorer implements ViewModels.Explorer {
|
|||||||
newTab.onTabClick();
|
newTab.onTabClick();
|
||||||
}
|
}
|
||||||
|
|
||||||
public openNotebookViewer(notebookUrl: string, notebookMetadata: DataModels.NotebookMetadata) {
|
public openNotebookViewer(
|
||||||
|
notebookUrl: string,
|
||||||
|
notebookMetadata: DataModels.NotebookMetadata,
|
||||||
|
onNotebookMetadataChange: (newNotebookMetadata: DataModels.NotebookMetadata) => Promise<void>,
|
||||||
|
isLikedNotebook: boolean
|
||||||
|
) {
|
||||||
const notebookName = path.basename(notebookUrl);
|
const notebookName = path.basename(notebookUrl);
|
||||||
const title = notebookName;
|
const title = notebookName;
|
||||||
const hashLocation = notebookUrl;
|
const hashLocation = notebookUrl;
|
||||||
@ -3320,7 +3325,9 @@ export default class Explorer implements ViewModels.Explorer {
|
|||||||
openedTabs: this.openedTabs(),
|
openedTabs: this.openedTabs(),
|
||||||
notebookUrl: notebookUrl,
|
notebookUrl: notebookUrl,
|
||||||
notebookName: notebookName,
|
notebookName: notebookName,
|
||||||
notebookMetadata: notebookMetadata
|
notebookMetadata: notebookMetadata,
|
||||||
|
onNotebookMetadataChange: onNotebookMetadataChange,
|
||||||
|
isLikedNotebook: isLikedNotebook
|
||||||
});
|
});
|
||||||
|
|
||||||
this.openedTabs.push(newTab);
|
this.openedTabs.push(newTab);
|
||||||
|
@ -9,11 +9,12 @@ import { connect } from "react-redux";
|
|||||||
import { Dispatch } from "redux";
|
import { Dispatch } from "redux";
|
||||||
import { actions, ContentRef } from "@nteract/core";
|
import { actions, ContentRef } from "@nteract/core";
|
||||||
import loadTransform from "../NotebookComponent/loadTransform";
|
import loadTransform from "../NotebookComponent/loadTransform";
|
||||||
import CodeMirrorEditor from "@nteract/editor";
|
import CodeMirrorEditor from "@nteract/stateful-components/lib/inputs/connected-editors/codemirror";
|
||||||
import "./NotebookReadOnlyRenderer.less";
|
import "./NotebookReadOnlyRenderer.less";
|
||||||
|
|
||||||
export interface NotebookRendererProps {
|
export interface NotebookRendererProps {
|
||||||
contentRef: any;
|
contentRef: any;
|
||||||
|
hideInputs?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PassedEditorProps {
|
interface PassedEditorProps {
|
||||||
@ -46,7 +47,8 @@ class NotebookReadOnlyRenderer extends React.Component<NotebookRendererProps> {
|
|||||||
<CodeCell id={id} contentRef={contentRef}>
|
<CodeCell id={id} contentRef={contentRef}>
|
||||||
{{
|
{{
|
||||||
editor: {
|
editor: {
|
||||||
codemirror: (props: PassedEditorProps) => <CodeMirrorEditor {...props} readOnly={"nocursor"} />
|
codemirror: (props: PassedEditorProps) =>
|
||||||
|
this.props.hideInputs ? <></> : <CodeMirrorEditor {...props} readOnly={"nocursor"} />
|
||||||
},
|
},
|
||||||
prompt: ({ id, contentRef }) => <></>
|
prompt: ({ id, contentRef }) => <></>
|
||||||
}}
|
}}
|
||||||
@ -63,7 +65,8 @@ class NotebookReadOnlyRenderer extends React.Component<NotebookRendererProps> {
|
|||||||
<RawCell id={id} contentRef={contentRef} cell_type="raw">
|
<RawCell id={id} contentRef={contentRef} cell_type="raw">
|
||||||
{{
|
{{
|
||||||
editor: {
|
editor: {
|
||||||
codemirror: (props: PassedEditorProps) => <CodeMirrorEditor {...props} readOnly={"nocursor"} />
|
codemirror: (props: PassedEditorProps) =>
|
||||||
|
this.props.hideInputs ? <></> : <CodeMirrorEditor {...props} readOnly={"nocursor"} />
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
</RawCell>
|
</RawCell>
|
||||||
|
@ -3,7 +3,7 @@ import * as ViewModels from "../../Contracts/ViewModels";
|
|||||||
import TabsBase from "./TabsBase";
|
import TabsBase from "./TabsBase";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { ReactAdapter } from "../../Bindings/ReactBindingHandler";
|
import { ReactAdapter } from "../../Bindings/ReactBindingHandler";
|
||||||
import { GalleryViewerContainerComponent } from "../../GalleryViewer/GalleryViewerComponent";
|
import { GalleryViewerContainerComponent } from "../Controls/NotebookGallery/GalleryViewerComponent";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notebook gallery tab
|
* Notebook gallery tab
|
||||||
|
@ -16,7 +16,9 @@ class NotebookViewerComponentAdapter implements ReactAdapter {
|
|||||||
private notebookUrl: string,
|
private notebookUrl: string,
|
||||||
private notebookName: string,
|
private notebookName: string,
|
||||||
private container: ViewModels.Explorer,
|
private container: ViewModels.Explorer,
|
||||||
private notebookMetadata: DataModels.NotebookMetadata
|
private notebookMetadata: DataModels.NotebookMetadata,
|
||||||
|
private onNotebookMetadataChange: (newNotebookMetadata: DataModels.NotebookMetadata) => Promise<void>,
|
||||||
|
private isLikedNotebook: boolean
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public renderComponent(): JSX.Element {
|
public renderComponent(): JSX.Element {
|
||||||
@ -26,6 +28,8 @@ class NotebookViewerComponentAdapter implements ReactAdapter {
|
|||||||
notebookMetadata={this.notebookMetadata}
|
notebookMetadata={this.notebookMetadata}
|
||||||
notebookName={this.notebookName}
|
notebookName={this.notebookName}
|
||||||
container={this.container}
|
container={this.container}
|
||||||
|
onNotebookMetadataChange={this.onNotebookMetadataChange}
|
||||||
|
isLikedNotebook={this.isLikedNotebook}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
@ -46,7 +50,9 @@ export default class NotebookViewerTab extends TabsBase implements ViewModels.Ta
|
|||||||
options.notebookUrl,
|
options.notebookUrl,
|
||||||
options.notebookName,
|
options.notebookName,
|
||||||
options.container,
|
options.container,
|
||||||
options.notebookMetadata
|
options.notebookMetadata,
|
||||||
|
options.onNotebookMetadataChange,
|
||||||
|
options.isLikedNotebook
|
||||||
);
|
);
|
||||||
|
|
||||||
this.notebookViewerComponentAdapter.parameters = ko.computed<boolean>(() => {
|
this.notebookViewerComponentAdapter.parameters = ko.computed<boolean>(() => {
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
@import "../../less/Common/Constants";
|
|
||||||
|
|
||||||
.galleryContainer {
|
|
||||||
padding: @DefaultSpace;
|
|
||||||
height: 100%;
|
|
||||||
overflow-y: scroll;
|
|
||||||
width: 100%;
|
|
||||||
font-family: @DataExplorerFont;
|
|
||||||
}
|
|
@ -1,13 +1,13 @@
|
|||||||
import * as ReactDOM from "react-dom";
|
import * as ReactDOM from "react-dom";
|
||||||
import "bootstrap/dist/css/bootstrap.css";
|
import "bootstrap/dist/css/bootstrap.css";
|
||||||
import "./GalleryViewer.less";
|
import { CosmosClient } from "../Common/CosmosClient";
|
||||||
import { GalleryViewerComponent } from "./GalleryViewerComponent";
|
import { GalleryViewerComponent } from "../Explorer/Controls/NotebookGallery/GalleryViewerComponent";
|
||||||
import { JunoUtils } from "../Utils/JunoUtils";
|
import { JunoUtils } from "../Utils/JunoUtils";
|
||||||
import { initializeIcons } from "office-ui-fabric-react/lib/Icons";
|
import { initializeIcons } from "office-ui-fabric-react/lib/Icons";
|
||||||
|
|
||||||
const onInit = async () => {
|
const onInit = async () => {
|
||||||
initializeIcons();
|
initializeIcons();
|
||||||
const officialSamplesData = await JunoUtils.getOfficialSampleNotebooks();
|
const officialSamplesData = await JunoUtils.getOfficialSampleNotebooks(CosmosClient.authorizationToken());
|
||||||
const galleryViewerComponent = new GalleryViewerComponent({
|
const galleryViewerComponent = new GalleryViewerComponent({
|
||||||
officialSamplesData: officialSamplesData,
|
officialSamplesData: officialSamplesData,
|
||||||
likedNotebookData: undefined,
|
likedNotebookData: undefined,
|
||||||
|
@ -1,207 +0,0 @@
|
|||||||
/**
|
|
||||||
* Gallery Viewer
|
|
||||||
*/
|
|
||||||
|
|
||||||
import * as React from "react";
|
|
||||||
import * as DataModels from "../Contracts/DataModels";
|
|
||||||
import * as ViewModels from "../Contracts/ViewModels";
|
|
||||||
import { GalleryCardComponent } from "./Cards/GalleryCardComponent";
|
|
||||||
import { Stack, IStackTokens } from "office-ui-fabric-react";
|
|
||||||
import AppBar from "@material-ui/core/AppBar";
|
|
||||||
import Tabs from "@material-ui/core/Tabs";
|
|
||||||
import Tab from "@material-ui/core/Tab";
|
|
||||||
import Typography from "@material-ui/core/Typography";
|
|
||||||
import Box from "@material-ui/core/Box";
|
|
||||||
import { JunoUtils } from "../Utils/JunoUtils";
|
|
||||||
import { CosmosClient } from "../Common/CosmosClient";
|
|
||||||
import { config } from "../Config";
|
|
||||||
import path from "path";
|
|
||||||
import { SessionStorageUtility, StorageKey } from "../Shared/StorageUtility";
|
|
||||||
import "./GalleryViewer.less";
|
|
||||||
|
|
||||||
interface GalleryCardsComponentProps {
|
|
||||||
data: DataModels.GitHubInfoJunoResponse[];
|
|
||||||
onClick: (url: string, notebookMetadata: DataModels.NotebookMetadata) => Promise<void>;
|
|
||||||
}
|
|
||||||
|
|
||||||
class GalleryCardsComponent extends React.Component<GalleryCardsComponentProps> {
|
|
||||||
private sectionStackTokens: IStackTokens = { childrenGap: 30 };
|
|
||||||
public render(): JSX.Element {
|
|
||||||
return (
|
|
||||||
<Stack horizontal wrap tokens={this.sectionStackTokens}>
|
|
||||||
{this.props.data.map((githubInfo: DataModels.GitHubInfoJunoResponse, index: any) => {
|
|
||||||
const name = githubInfo.name;
|
|
||||||
const url = githubInfo.downloadUrl;
|
|
||||||
const notebookMetadata = githubInfo.metadata;
|
|
||||||
|
|
||||||
return (
|
|
||||||
name !== ".gitignore" &&
|
|
||||||
url && (
|
|
||||||
<GalleryCardComponent
|
|
||||||
key={url}
|
|
||||||
name={name}
|
|
||||||
url={url}
|
|
||||||
notebookMetadata={notebookMetadata}
|
|
||||||
onClick={() => this.props.onClick(url, notebookMetadata)}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Stack>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const TabPanel = (props: any) => (
|
|
||||||
<Typography
|
|
||||||
component="div"
|
|
||||||
role="tabpanel"
|
|
||||||
hidden={props.value !== props.index}
|
|
||||||
id={`full-width-tabpanel-${props.index}`}
|
|
||||||
aria-labelledby={`full-width-tab-${props.index}`}
|
|
||||||
>
|
|
||||||
{props.value === props.index && <Box p={2}>{props.children}</Box>}
|
|
||||||
</Typography>
|
|
||||||
);
|
|
||||||
|
|
||||||
const a11yProps = (index: number) => {
|
|
||||||
return {
|
|
||||||
id: `full-width-tab-${index}`,
|
|
||||||
"aria-controls": `full-width-tabpanel-${index}`
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
interface FullWidthTabsProps {
|
|
||||||
officialSamplesContent: DataModels.GitHubInfoJunoResponse[];
|
|
||||||
likedNotebooksContent: DataModels.GitHubInfoJunoResponse[];
|
|
||||||
onClick: (url: string, notebookMetadata: DataModels.NotebookMetadata) => Promise<void>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const FullWidthTabs = (props: FullWidthTabsProps) => {
|
|
||||||
const [value, setValue] = React.useState(0);
|
|
||||||
|
|
||||||
const handleChange = ({}, newValue: any) => {
|
|
||||||
setValue(newValue);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<AppBar position="static" color="transparent" style={{ background: "transparent", boxShadow: "none" }}>
|
|
||||||
<Tabs
|
|
||||||
value={value}
|
|
||||||
onChange={handleChange}
|
|
||||||
indicatorColor="primary"
|
|
||||||
textColor="primary"
|
|
||||||
aria-label="gallery tabs"
|
|
||||||
>
|
|
||||||
<Tab label="Official Samples" {...a11yProps(0)} />
|
|
||||||
<Tab label="Liked Notebooks" {...a11yProps(1)} />
|
|
||||||
</Tabs>
|
|
||||||
</AppBar>
|
|
||||||
<TabPanel value={value} index={0}>
|
|
||||||
<GalleryCardsComponent data={props.officialSamplesContent} onClick={props.onClick} />
|
|
||||||
</TabPanel>
|
|
||||||
<TabPanel value={value} index={1}>
|
|
||||||
<GalleryCardsComponent data={props.likedNotebooksContent} onClick={props.onClick} />
|
|
||||||
</TabPanel>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface GalleryViewerContainerComponentProps {
|
|
||||||
container: ViewModels.Explorer;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GalleryViewerContainerComponentState {
|
|
||||||
officialSamplesData: DataModels.GitHubInfoJunoResponse[];
|
|
||||||
likedNotebooksData: DataModels.LikedNotebooksJunoResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class GalleryViewerContainerComponent extends React.Component<
|
|
||||||
GalleryViewerContainerComponentProps,
|
|
||||||
GalleryViewerContainerComponentState
|
|
||||||
> {
|
|
||||||
constructor(props: GalleryViewerContainerComponentProps) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
officialSamplesData: undefined,
|
|
||||||
likedNotebooksData: undefined
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
JunoUtils.getOfficialSampleNotebooks().then((data1: DataModels.GitHubInfoJunoResponse[]) => {
|
|
||||||
const officialSamplesData = data1;
|
|
||||||
|
|
||||||
JunoUtils.getLikedNotebooks(CosmosClient.authorizationToken()).then(
|
|
||||||
(data2: DataModels.LikedNotebooksJunoResponse) => {
|
|
||||||
const likedNotebooksData = data2;
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
officialSamplesData: officialSamplesData,
|
|
||||||
likedNotebooksData: likedNotebooksData
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public render(): JSX.Element {
|
|
||||||
return this.state.officialSamplesData && this.state.likedNotebooksData ? (
|
|
||||||
<GalleryViewerComponent
|
|
||||||
container={this.props.container}
|
|
||||||
officialSamplesData={this.state.officialSamplesData}
|
|
||||||
likedNotebookData={this.state.likedNotebooksData}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GalleryViewerComponentProps {
|
|
||||||
container: ViewModels.Explorer;
|
|
||||||
officialSamplesData: DataModels.GitHubInfoJunoResponse[];
|
|
||||||
likedNotebookData: DataModels.LikedNotebooksJunoResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class GalleryViewerComponent extends React.Component<GalleryViewerComponentProps> {
|
|
||||||
private authorizationToken = CosmosClient.authorizationToken();
|
|
||||||
|
|
||||||
public render(): JSX.Element {
|
|
||||||
return this.props.container ? (
|
|
||||||
<div className="galleryContainer">
|
|
||||||
<FullWidthTabs
|
|
||||||
officialSamplesContent={this.props.officialSamplesData}
|
|
||||||
likedNotebooksContent={this.props.likedNotebookData.likedNotebooksContent}
|
|
||||||
onClick={this.openNotebookViewer}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="galleryContainer">
|
|
||||||
<GalleryCardsComponent data={this.props.officialSamplesData} onClick={this.openNotebookViewer} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getOfficialSamplesData(): DataModels.GitHubInfoJunoResponse[] {
|
|
||||||
return this.props.officialSamplesData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getLikedNotebookData(): DataModels.LikedNotebooksJunoResponse {
|
|
||||||
return this.props.likedNotebookData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public openNotebookViewer = async (url: string, notebookMetadata: DataModels.NotebookMetadata) => {
|
|
||||||
if (!this.props.container) {
|
|
||||||
SessionStorageUtility.setEntryString(
|
|
||||||
StorageKey.NotebookMetadata,
|
|
||||||
notebookMetadata ? JSON.stringify(notebookMetadata) : null
|
|
||||||
);
|
|
||||||
SessionStorageUtility.setEntryString(StorageKey.NotebookName, path.basename(url));
|
|
||||||
window.open(`${config.hostedExplorerURL}notebookViewer.html?notebookurl=${url}`, "_blank");
|
|
||||||
} else {
|
|
||||||
this.props.container.openNotebookViewer(url, notebookMetadata);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
@ -15,7 +15,6 @@ import "./Explorer/Menus/CommandBar/MemoryTrackerComponent.less";
|
|||||||
import "./Explorer/Controls/CollapsiblePanel/CollapsiblePanelComponent.less";
|
import "./Explorer/Controls/CollapsiblePanel/CollapsiblePanelComponent.less";
|
||||||
import "./Explorer/Controls/DynamicList/DynamicListComponent.less";
|
import "./Explorer/Controls/DynamicList/DynamicListComponent.less";
|
||||||
import "./Explorer/Controls/JsonEditor/JsonEditorComponent.less";
|
import "./Explorer/Controls/JsonEditor/JsonEditorComponent.less";
|
||||||
import "./Explorer/Controls/Tabs/TabComponent.less";
|
|
||||||
import "./Explorer/Graph/GraphExplorerComponent/graphExplorer.less";
|
import "./Explorer/Graph/GraphExplorerComponent/graphExplorer.less";
|
||||||
import "../less/TableStyles/queryBuilder.less";
|
import "../less/TableStyles/queryBuilder.less";
|
||||||
import "../externals/jquery.dataTables.min.css";
|
import "../externals/jquery.dataTables.min.css";
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import * as ReactDOM from "react-dom";
|
import * as ReactDOM from "react-dom";
|
||||||
import "bootstrap/dist/css/bootstrap.css";
|
import "bootstrap/dist/css/bootstrap.css";
|
||||||
import { NotebookMetadata } from "../../../Contracts/DataModels";
|
import { NotebookMetadata } from "../Contracts/DataModels";
|
||||||
import { NotebookViewerComponent } from "./NotebookViewerComponent";
|
import { NotebookViewerComponent } from "../Explorer/Controls/NotebookViewer/NotebookViewerComponent";
|
||||||
import { SessionStorageUtility, StorageKey } from "../../../Shared/StorageUtility";
|
import { SessionStorageUtility, StorageKey } from "../Shared/StorageUtility";
|
||||||
|
|
||||||
const getNotebookUrl = (): string => {
|
const getNotebookUrl = (): string => {
|
||||||
const regex: RegExp = new RegExp("[?&]notebookurl=([^&#]*)|&|#|$");
|
const regex: RegExp = new RegExp("[?&]notebookurl=([^&#]*)|&|#|$");
|
||||||
@ -26,12 +26,14 @@ const onInit = async () => {
|
|||||||
SessionStorageUtility.removeEntry(StorageKey.NotebookName);
|
SessionStorageUtility.removeEntry(StorageKey.NotebookName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
|
||||||
const notebookViewerComponent = (
|
const notebookViewerComponent = (
|
||||||
<NotebookViewerComponent
|
<NotebookViewerComponent
|
||||||
notebookMetadata={notebookMetadata}
|
notebookMetadata={notebookMetadata}
|
||||||
notebookName={notebookName}
|
notebookName={notebookName}
|
||||||
notebookUrl={getNotebookUrl()}
|
notebookUrl={getNotebookUrl()}
|
||||||
container={null}
|
hideInputs={urlParams.get("hideinputs") === "true"}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
ReactDOM.render(notebookViewerComponent, document.getElementById("notebookContent"));
|
ReactDOM.render(notebookViewerComponent, document.getElementById("notebookContent"));
|
@ -8,17 +8,22 @@ export class JunoUtils {
|
|||||||
public static async getLikedNotebooks(authorizationToken: string): Promise<DataModels.LikedNotebooksJunoResponse> {
|
public static async getLikedNotebooks(authorizationToken: string): Promise<DataModels.LikedNotebooksJunoResponse> {
|
||||||
//TODO: Add Get method once juno has it implemented
|
//TODO: Add Get method once juno has it implemented
|
||||||
return {
|
return {
|
||||||
likedNotebooksContent: await JunoUtils.getOfficialSampleNotebooks(),
|
likedNotebooksContent: [],
|
||||||
userMetadata: {
|
userMetadata: {
|
||||||
likedNotebooks: []
|
likedNotebooks: []
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async getOfficialSampleNotebooks(): Promise<DataModels.GitHubInfoJunoResponse[]> {
|
public static async getOfficialSampleNotebooks(
|
||||||
|
authorizationToken: string
|
||||||
|
): Promise<DataModels.GitHubInfoJunoResponse[]> {
|
||||||
try {
|
try {
|
||||||
const response = await window.fetch(config.JUNO_ENDPOINT + "/api/galleries/notebooks", {
|
const response = await window.fetch(config.JUNO_ENDPOINT + "/api/notebooks/galleries", {
|
||||||
method: "GET"
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
authorization: authorizationToken
|
||||||
|
}
|
||||||
});
|
});
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error("Status code:" + response.status);
|
throw new Error("Status code:" + response.status);
|
||||||
@ -35,14 +40,16 @@ export class JunoUtils {
|
|||||||
): Promise<DataModels.UserMetadata> {
|
): Promise<DataModels.UserMetadata> {
|
||||||
return undefined;
|
return undefined;
|
||||||
//TODO: add userMetadata updation code
|
//TODO: add userMetadata updation code
|
||||||
|
// TODO: Make sure to throw error if failed
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async updateNotebookMetadata(
|
public static async updateNotebookMetadata(
|
||||||
authorizationToken: string,
|
authorizationToken: string,
|
||||||
userMetadata: DataModels.NotebookMetadata
|
notebookMetadata: DataModels.NotebookMetadata
|
||||||
): Promise<DataModels.NotebookMetadata> {
|
): Promise<DataModels.NotebookMetadata> {
|
||||||
return undefined;
|
return undefined;
|
||||||
//TODO: add notebookMetadata updation code
|
//TODO: add notebookMetadata updation code
|
||||||
|
// TODO: Make sure to throw error if failed
|
||||||
}
|
}
|
||||||
|
|
||||||
public static toPinnedRepo(item: RepoListItem): IPinnedRepo {
|
public static toPinnedRepo(item: RepoListItem): IPinnedRepo {
|
||||||
|
@ -144,7 +144,7 @@ module.exports = function(env = {}, argv = {}) {
|
|||||||
}),
|
}),
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
filename: "notebookViewer.html",
|
filename: "notebookViewer.html",
|
||||||
template: "src/Explorer/Controls/NotebookViewer/notebookViewer.html",
|
template: "src/NotebookViewer/notebookViewer.html",
|
||||||
chunks: ["notebookViewer"]
|
chunks: ["notebookViewer"]
|
||||||
}),
|
}),
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
@ -175,7 +175,7 @@ module.exports = function(env = {}, argv = {}) {
|
|||||||
hostedExplorer: "./src/HostedExplorer.ts",
|
hostedExplorer: "./src/HostedExplorer.ts",
|
||||||
heatmap: "./src/Controls/Heatmap/Heatmap.ts",
|
heatmap: "./src/Controls/Heatmap/Heatmap.ts",
|
||||||
terminal: "./src/Terminal/index.ts",
|
terminal: "./src/Terminal/index.ts",
|
||||||
notebookViewer: "./src/Explorer/Controls/NotebookViewer/NotebookViewer.tsx",
|
notebookViewer: "./src/NotebookViewer/NotebookViewer.tsx",
|
||||||
galleryViewer: "./src/GalleryViewer/GalleryViewer.tsx",
|
galleryViewer: "./src/GalleryViewer/GalleryViewer.tsx",
|
||||||
connectToGitHub: "./src/GitHub/GitHubConnector.ts"
|
connectToGitHub: "./src/GitHub/GitHubConnector.ts"
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user