├── .babelrc
├── .eslintignore
├── .eslintrc
├── .eslintrc-node
├── .gitignore
├── .nvmrc
├── .travis.yml
├── LICENSE
├── README.md
├── __mocks__
├── ace.js
├── browser-mocks.js
├── generic-stub.js
├── ipc.js
└── storage.js
├── build
├── background.png
├── icon.icns
├── icon.ico
├── icon.png
└── install-spinner.gif
├── contributing.md
├── gulpfile.js
├── karma.node.conf.js
├── package.json
├── scripts
├── osx
│ ├── build.sh
│ ├── create-test-postgresql-tables.sh
│ ├── dist-linux.sh
│ ├── dist-osx.sh
│ ├── dist-win.sh
│ ├── docker-compose.yml
│ ├── install-deps.sh
│ ├── install-dist-linux-deps.sh
│ ├── install-dist-win-deps.sh
│ ├── install-test-deps.sh
│ ├── sign.sh
│ ├── test-postgresql.sh
│ ├── update-info-plist.py
│ └── verify-sign.sh
└── win
│ └── setup_conda.bat
├── server.js
├── src
├── ace
│ ├── ace.js
│ ├── ext-language_tools.js
│ ├── ext-searchbox.js
│ ├── ext-settings_menu.js
│ ├── keybinding-emacs.js
│ ├── keybinding-vim.js
│ ├── mode-json.js
│ ├── mode-jula.js
│ ├── mode-latex.js
│ ├── mode-markdown.js
│ ├── mode-mysql.js
│ ├── mode-pgsql.js
│ ├── mode-plain_text.js
│ ├── mode-python.js
│ ├── mode-r.js
│ ├── mode-scala.js
│ ├── mode-sql.js
│ ├── mode-sqlserver.js
│ ├── mode-yaml.js
│ ├── readme.md
│ ├── snippets
│ │ ├── mysql.js
│ │ ├── pgsql.js
│ │ ├── python.js
│ │ ├── r.js
│ │ ├── rdoc.js
│ │ ├── rhtml.js
│ │ ├── sql.js
│ │ └── sqlserver.js
│ ├── theme-ambiance.js
│ ├── theme-chaos.js
│ ├── theme-chrome.js
│ ├── theme-clouds.js
│ ├── theme-clouds_midnight.js
│ ├── theme-cobalt.js
│ ├── theme-crimson_editor.js
│ ├── theme-dawn.js
│ ├── theme-dreamweaver.js
│ ├── theme-eclipse.js
│ ├── theme-github.js
│ ├── theme-idle_fingers.js
│ ├── theme-katzenmilch.js
│ ├── theme-kr_theme.js
│ ├── theme-kuroir.js
│ ├── theme-merbivore.js
│ ├── theme-merbivore_soft.js
│ ├── theme-mono_industrial.js
│ ├── theme-monokai.js
│ ├── theme-pastel_on_dark.js
│ ├── theme-solarized_dark.js
│ ├── theme-solarized_light.js
│ ├── theme-terminal.js
│ ├── theme-textmate.js
│ ├── theme-tomorrow.js
│ ├── theme-tomorrow_night.js
│ ├── theme-tomorrow_night_blue.js
│ ├── theme-tomorrow_night_bright.js
│ ├── theme-tomorrow_night_eighties.js
│ ├── theme-twilight.js
│ ├── theme-vibrant_ink.js
│ └── theme-xcode.js
├── browser
│ ├── actions
│ │ ├── application.js
│ │ ├── database-connection.js
│ │ ├── dialogs.js
│ │ ├── iopub.js
│ │ ├── kernel.js
│ │ └── preferences.js
│ ├── components
│ │ ├── ace-pane
│ │ │ ├── ace-pane.css
│ │ │ ├── ace-pane.js
│ │ │ └── ace-pane.test.js
│ │ ├── action-button.js
│ │ ├── actionest
│ │ │ ├── actionest-button.js
│ │ │ └── actionest.css
│ │ ├── block-history
│ │ │ ├── block-history.css
│ │ │ ├── block-history.js
│ │ │ ├── expand-block-button.css
│ │ │ ├── expand-block-button.js
│ │ │ ├── history-blocks
│ │ │ │ ├── error-block.css
│ │ │ │ ├── error-block.js
│ │ │ │ ├── execution-result-block.css
│ │ │ │ ├── execution-result-block.js
│ │ │ │ ├── image-block.css
│ │ │ │ ├── image-block.js
│ │ │ │ ├── input-stream-block.css
│ │ │ │ ├── input-stream-block.js
│ │ │ │ ├── jupyter-response-block.css
│ │ │ │ ├── jupyter-response-block.js
│ │ │ │ ├── postgresql-response-block.css
│ │ │ │ ├── postgresql-response-block.js
│ │ │ │ ├── python-error-block.css
│ │ │ │ ├── python-error-block.js
│ │ │ │ ├── text-stream-block.css
│ │ │ │ └── text-stream-block.js
│ │ │ ├── history-list.js
│ │ │ ├── history-viewer.css
│ │ │ └── history-viewer.js
│ │ ├── brand-splashes
│ │ │ ├── brand-splashes.css
│ │ │ ├── logo-rodeo-grey-text.sketch
│ │ │ ├── logo-rodeo-grey-text.svg
│ │ │ ├── logo-rodeo-large.jsx
│ │ │ ├── logo-rodeo-square-large.jsx
│ │ │ ├── logo-rodeo-square-large.svg
│ │ │ └── logo-rodeo-white-text.svg
│ │ ├── data-frame
│ │ │ ├── data-frame-loading-icon.jsx
│ │ │ ├── data-frame-loading-icon.test.js
│ │ │ ├── data-frame.css
│ │ │ └── data-frame.jsx
│ │ ├── databases
│ │ │ ├── database-explorer-tree-header.css
│ │ │ ├── database-explorer-tree-header.jsx
│ │ │ ├── database-explorer-tree.css
│ │ │ └── database-explorer-tree.jsx
│ │ ├── dialogs
│ │ │ ├── about-rodeo.css
│ │ │ ├── about-rodeo.js
│ │ │ ├── acknowledgements.css
│ │ │ ├── acknowledgements.js
│ │ │ ├── acknowledgements.md
│ │ │ ├── ask-quit.css
│ │ │ ├── ask-quit.js
│ │ │ ├── environment-variables-dialog.css
│ │ │ ├── environment-variables-dialog.js
│ │ │ ├── modal-dialog-container.css
│ │ │ ├── modal-dialog-container.js
│ │ │ ├── modal-dialog.css
│ │ │ ├── modal-dialog.js
│ │ │ ├── rodeo-text-dark.png
│ │ │ ├── stickers-pane.css
│ │ │ └── stickers-pane.js
│ │ ├── document-terminal
│ │ │ ├── document-terminal-annotation.css
│ │ │ ├── document-terminal-annotation.js
│ │ │ ├── document-terminal-autocomplete.css
│ │ │ ├── document-terminal-autocomplete.js
│ │ │ ├── document-terminal-error.css
│ │ │ ├── document-terminal-error.js
│ │ │ ├── document-terminal-history.js
│ │ │ ├── document-terminal-page-break.css
│ │ │ ├── document-terminal-page-break.js
│ │ │ ├── document-terminal-python-error.css
│ │ │ ├── document-terminal-python-error.js
│ │ │ ├── document-terminal-text.css
│ │ │ ├── document-terminal-text.js
│ │ │ ├── document-terminal.css
│ │ │ ├── document-terminal.js
│ │ │ ├── sticky-bottom-scroll.css
│ │ │ └── sticky-bottom-scroll.js
│ │ ├── empty
│ │ │ ├── empty-suggestion.css
│ │ │ └── empty-suggestion.js
│ │ ├── files
│ │ │ ├── file-list-item.jsx
│ │ │ ├── file-list.css
│ │ │ ├── file-list.jsx
│ │ │ ├── file-tree-header.css
│ │ │ ├── file-tree-header.jsx
│ │ │ ├── file-tree.css
│ │ │ └── file-tree.jsx
│ │ ├── forms
│ │ │ ├── button-referenced.css
│ │ │ ├── button-referenced.js
│ │ │ ├── form-item-errors.js
│ │ │ ├── form-list.css
│ │ │ ├── form-list.js
│ │ │ ├── input-checkbox.js
│ │ │ ├── input-folder.js
│ │ │ ├── input-key-value-list.css
│ │ │ ├── input-key-value-list.js
│ │ │ ├── input-list.css
│ │ │ ├── input-list.js
│ │ │ ├── input-number.js
│ │ │ ├── input-python-cmd.js
│ │ │ ├── input-select.css
│ │ │ ├── input-select.js
│ │ │ ├── input-text.js
│ │ │ ├── readme.md
│ │ │ ├── rodeo-logo.png
│ │ │ └── save-changes-button-group.js
│ │ ├── gray-info
│ │ │ ├── gray-info-link-list.js
│ │ │ ├── gray-info-link.js
│ │ │ ├── gray-info-select.js
│ │ │ ├── gray-info.css
│ │ │ └── gray-info.js
│ │ ├── label-checkbox.jsx
│ │ ├── label-checklist.jsx
│ │ ├── label-input.jsx
│ │ ├── layout-containers
│ │ │ ├── full-screen.css
│ │ │ └── full-screen.jsx
│ │ ├── manage-connections
│ │ │ ├── connection-button.js
│ │ │ ├── connection-config.js
│ │ │ ├── connection-errors.css
│ │ │ ├── connection-errors.js
│ │ │ ├── connection-list.js
│ │ │ ├── manage-connections.css
│ │ │ ├── manage-connections.js
│ │ │ └── types
│ │ │ │ ├── mysql-settings.js
│ │ │ │ ├── postgresql-settings.js
│ │ │ │ ├── redshift-settings.js
│ │ │ │ └── sqlserver-settings.js
│ │ ├── marked.js
│ │ ├── notifications
│ │ │ ├── chat-alt-flat.svg
│ │ │ ├── download-cloud-flat.svg
│ │ │ ├── info-notification.css
│ │ │ ├── info-notification.jsx
│ │ │ ├── notifications-container.css
│ │ │ ├── notifications-container.jsx
│ │ │ ├── notifications.actions.js
│ │ │ ├── notifications.reducer.js
│ │ │ ├── update-available-notification.css
│ │ │ └── update-available-notification.jsx
│ │ ├── packages
│ │ │ ├── package-search-item-detail.jsx
│ │ │ ├── package-search-item.css
│ │ │ ├── package-search-item.jsx
│ │ │ ├── package-search-list.css
│ │ │ ├── package-search-list.jsx
│ │ │ ├── packages-list.css
│ │ │ └── packages-list.jsx
│ │ ├── plot-preview
│ │ │ ├── background-plot.jsx
│ │ │ ├── document-error-flat.svg
│ │ │ ├── foreground-plot.jsx
│ │ │ ├── html-flat.svg
│ │ │ ├── plot-preview.css
│ │ │ └── plot-preview.jsx
│ │ ├── prompt
│ │ │ ├── prompt.css
│ │ │ └── prompt.js
│ │ ├── register-rodeo
│ │ │ ├── areas-of-interest.yml
│ │ │ ├── explanation.md
│ │ │ ├── register-rodeo.css
│ │ │ └── register-rodeo.jsx
│ │ ├── search-text-box
│ │ │ ├── search-text-box.css
│ │ │ └── search-text-box.jsx
│ │ ├── setup
│ │ │ ├── fake-terminal.css
│ │ │ ├── fake-terminal.jsx
│ │ │ ├── logo-rodeo-grey-text.sketch
│ │ │ ├── logo-rodeo-grey-text.svg
│ │ │ ├── python-test-input.jsx
│ │ │ ├── setup-article-preview.css
│ │ │ ├── setup-article-preview.jsx
│ │ │ ├── setup-initial.jsx
│ │ │ ├── setup-install-anaconda.jsx
│ │ │ ├── setup-install-package.jsx
│ │ │ ├── setup-install-result-buttons.jsx
│ │ │ ├── setup-manual-command.css
│ │ │ ├── setup-manual-command.jsx
│ │ │ ├── setup-no-jupyter.jsx
│ │ │ ├── setup-no-matplotlib.jsx
│ │ │ ├── setup-no-numpy.jsx
│ │ │ ├── setup-no-pandas.jsx
│ │ │ ├── setup-no-python.jsx
│ │ │ ├── setup-no-scipy.jsx
│ │ │ ├── setup-python-error.jsx
│ │ │ ├── setup-ready.jsx
│ │ │ ├── setup-skip-startup.css
│ │ │ ├── setup-skip-startup.js
│ │ │ ├── setup.css
│ │ │ └── setup.jsx
│ │ ├── sidebar
│ │ │ ├── logo-python.svg
│ │ │ ├── logo-scienceops.png
│ │ │ ├── logo-yhat.sketch
│ │ │ ├── logo-yhat.svg
│ │ │ ├── sidebar-item.jsx
│ │ │ ├── sidebar.actions.js
│ │ │ ├── sidebar.css
│ │ │ ├── sidebar.jsx
│ │ │ ├── sidebar.reducer.js
│ │ │ ├── slideout-dialog.css
│ │ │ └── slideout-dialog.jsx
│ │ ├── split-pane
│ │ │ ├── lib
│ │ │ │ ├── jquery.splitter-0.15.0.js
│ │ │ │ └── jquery.splitter.css
│ │ │ └── split-pane.jsx
│ │ ├── tabbed-form-list-dialog
│ │ │ ├── tabbed-form-list-dialog-tab.css
│ │ │ ├── tabbed-form-list-dialog-tab.js
│ │ │ ├── tabbed-form-list-dialog.css
│ │ │ └── tabbed-form-list-dialog.js
│ │ ├── tabs
│ │ │ ├── closeable.css
│ │ │ ├── closeable.js
│ │ │ ├── tab-add.css
│ │ │ ├── tab-add.js
│ │ │ ├── tab-button.css
│ │ │ ├── tab-button.js
│ │ │ ├── tab-content-list.css
│ │ │ ├── tab-content-list.jsx
│ │ │ ├── tab-item.css
│ │ │ ├── tab-item.js
│ │ │ ├── tab-list.css
│ │ │ ├── tab-list.js
│ │ │ ├── tab-list.test.js
│ │ │ ├── tab-overflow-image.css
│ │ │ ├── tab-overflow-image.js
│ │ │ ├── tabbed-pane-item.css
│ │ │ ├── tabbed-pane-item.js
│ │ │ ├── tabbed-pane.css
│ │ │ └── tabbed-pane.js
│ │ ├── tree-view
│ │ │ ├── tree-view-item.js
│ │ │ ├── tree-view.css
│ │ │ └── tree-view.js
│ │ ├── unsafe-html.js
│ │ ├── unsafe-html.test.js
│ │ ├── variable-viewer
│ │ │ ├── variable-table.css
│ │ │ ├── variable-table.jsx
│ │ │ └── variable-viewer.jsx
│ │ └── yhat.js
│ ├── containers
│ │ ├── ask-quit-dialog-viewer
│ │ │ ├── ask-quit-dialog-viewer.jsx
│ │ │ ├── ask-quit-dialog-viewer.reducer.js
│ │ │ └── ask-quit-dialog-viewer.selectors.js
│ │ ├── block-terminal-viewer
│ │ │ ├── block-terminal-viewer.actions.js
│ │ │ ├── block-terminal-viewer.css
│ │ │ ├── block-terminal-viewer.js
│ │ │ └── block-terminal-viewer.reducer.js
│ │ ├── database-viewer
│ │ │ ├── database-viewer.actions.js
│ │ │ ├── database-viewer.js
│ │ │ └── database-viewer.reducer.js
│ │ ├── document-terminal-viewer
│ │ │ ├── document-terminal-viewer.actions.js
│ │ │ ├── document-terminal-viewer.css
│ │ │ ├── document-terminal-viewer.js
│ │ │ ├── document-terminal-viewer.reducer.js
│ │ │ └── features.yml
│ │ ├── editor-tab-group
│ │ │ ├── ace.actions.js
│ │ │ ├── editor-commands.yml
│ │ │ ├── editor-tab-group.actions.js
│ │ │ ├── editor-tab-group.css
│ │ │ ├── editor-tab-group.jsx
│ │ │ ├── editor-tab-group.reducer.js
│ │ │ ├── editor-tab-group.reducer.test.js
│ │ │ ├── initial-story.py
│ │ │ ├── known-file-types.js
│ │ │ ├── known-file-types.yml
│ │ │ └── rodeo-logo
│ │ │ │ ├── rodeo-logo.1x.png
│ │ │ │ ├── rodeo-logo.2x.png
│ │ │ │ └── rodeo-logo.4x.png
│ │ ├── environment-variables-dialog-viewer
│ │ │ ├── environment-variables-dialog-viewer.actions.js
│ │ │ ├── environment-variables-dialog-viewer.css
│ │ │ ├── environment-variables-dialog-viewer.js
│ │ │ ├── environment-variables-dialog-viewer.reducer.js
│ │ │ ├── environment-variables-dialog-viewer.selectors.js
│ │ │ └── layout.yml
│ │ ├── file-viewer
│ │ │ ├── file-viewer.actions.js
│ │ │ ├── file-viewer.jsx
│ │ │ └── file-viewer.reducer.js
│ │ ├── free-tab-group
│ │ │ ├── free-tab-group.actions.js
│ │ │ ├── free-tab-group.jsx
│ │ │ ├── free-tab-group.reducer.js
│ │ │ ├── free-tab-group.reducer.test.js
│ │ │ └── tab-types.js
│ │ ├── free-tabs-only.jsx
│ │ ├── free-tabs-only.reducer.js
│ │ ├── global-history-viewer
│ │ │ ├── global-history-viewer.css
│ │ │ ├── global-history-viewer.js
│ │ │ └── global-history-viewer.reducer.js
│ │ ├── history-viewer
│ │ │ ├── history-viewer.actions.js
│ │ │ ├── history-viewer.js
│ │ │ └── history-viewer.reducer.js
│ │ ├── main.initial.js
│ │ ├── main.jsx
│ │ ├── main.reducer.js
│ │ ├── manage-connections-viewer
│ │ │ ├── definitions.yml
│ │ │ ├── manage-connections-viewer.js
│ │ │ ├── manage-connections.actions.js
│ │ │ ├── manage-connections.reducer.js
│ │ │ └── manage-connections.selectors.js
│ │ ├── modal-dialog-viewer
│ │ │ ├── dialog-types.js
│ │ │ ├── modal-dialog-viewer.jsx
│ │ │ ├── modal-dialog.actions.js
│ │ │ └── modal-dialog.reducer.js
│ │ ├── package-search-viewer
│ │ │ ├── package-search-viewer.actions.js
│ │ │ ├── package-search-viewer.jsx
│ │ │ ├── package-search-viewer.reducer.js
│ │ │ └── recommended.yml
│ │ ├── plot-viewer
│ │ │ ├── plot-viewer.actions.js
│ │ │ ├── plot-viewer.jsx
│ │ │ └── plot-viewer.reducer.js
│ │ ├── preferences-viewer
│ │ │ ├── layout.yml
│ │ │ ├── preferences-viewer.actions.js
│ │ │ ├── preferences-viewer.js
│ │ │ ├── preferences-viewer.reducer.js
│ │ │ ├── preferences-viewer.reducer.test.js
│ │ │ └── preferences-viewer.selectors.js
│ │ ├── prompt-viewer
│ │ │ ├── default-commands.yml
│ │ │ ├── prompt-viewer.actions.js
│ │ │ ├── prompt-viewer.js
│ │ │ ├── prompt-viewer.reducer.js
│ │ │ └── prompt-viewer.test.js
│ │ ├── setup-viewer
│ │ │ ├── articles.yml
│ │ │ ├── setup-viewer.actions.js
│ │ │ ├── setup-viewer.jsx
│ │ │ └── setup-viewer.reducer.js
│ │ ├── startup-text.yml
│ │ ├── startup.jsx
│ │ ├── startup.reducer.js
│ │ ├── studio-layout
│ │ │ ├── rodeo-logo.1x.png
│ │ │ ├── rodeo-logo.2x.png
│ │ │ ├── rodeo-logo.4x.png
│ │ │ └── studio-layout.jsx
│ │ ├── text.yml
│ │ ├── variable-table-viewer.jsx
│ │ └── variable-viewer
│ │ │ └── variable-viewer.reducer.js
│ ├── entry
│ │ ├── free-tabs-only.html
│ │ ├── free-tabs-only.js
│ │ ├── main.html
│ │ ├── main.js
│ │ ├── startup.html
│ │ └── startup.js
│ ├── favicon.ico
│ ├── lib
│ │ ├── ascii-table.min.js
│ │ └── ipc.js
│ └── services
│ │ ├── ace-decorators.js
│ │ ├── ace-python-completer.js
│ │ ├── ace-python-completer.test.js
│ │ ├── ace-settings.js
│ │ ├── ace-shortcuts.js
│ │ ├── api.js
│ │ ├── application-control.js
│ │ ├── cid.js
│ │ ├── common-react.js
│ │ ├── common-react.test.js
│ │ ├── common-tabs-actions.js
│ │ ├── common-tabs-actions.test.js
│ │ ├── common-tabs-reducers.js
│ │ ├── common-tabs-reducers.test.js
│ │ ├── database-connections.js
│ │ ├── dom.js
│ │ ├── env.js
│ │ ├── errors
│ │ ├── index.js
│ │ └── validation-error.js
│ │ ├── files.js
│ │ ├── global-observer.js
│ │ ├── guid.js
│ │ ├── immutable-util.js
│ │ ├── ipc-dispatcher.js
│ │ ├── jupyter
│ │ ├── client-discovery.js
│ │ ├── client.js
│ │ ├── conda.js
│ │ ├── history.js
│ │ ├── python-language.js
│ │ └── response.js
│ │ ├── layout-mapper.js
│ │ ├── log.js
│ │ ├── map-reducers.js
│ │ ├── map-reducers.test.js
│ │ ├── prompt-actions.js
│ │ ├── prompt-actions.test.js
│ │ ├── pypi.js
│ │ ├── react-performance.js
│ │ ├── redux-store.js
│ │ ├── redux-util.js
│ │ ├── registration.js
│ │ ├── selection-util.js
│ │ ├── store.js
│ │ ├── store.test.js
│ │ ├── terminal-shortcuts.js
│ │ ├── text-util.js
│ │ ├── text-util.test.js
│ │ ├── track.js
│ │ ├── util
│ │ ├── prompt-util.js
│ │ └── prompt-util.test.js
│ │ ├── validation.js
│ │ └── xmlrpc.js
├── fonts
│ ├── NotoMono-hinted
│ │ ├── LICENSE_OFL.txt
│ │ └── NotoMono-Regular.ttf
│ ├── NotoSans-unhinted
│ │ ├── LICENSE_OFL.txt
│ │ ├── NotoSans-Bold.ttf
│ │ ├── NotoSans-BoldItalic.ttf
│ │ ├── NotoSans-Italic.ttf
│ │ └── NotoSans-Regular.ttf
│ ├── NotoSerif-unhinted
│ │ ├── LICENSE_OFL.txt
│ │ ├── NotoSerif-Bold.ttf
│ │ ├── NotoSerif-BoldItalic.ttf
│ │ ├── NotoSerif-Italic.ttf
│ │ └── NotoSerif-Regular.ttf
│ ├── fonts.css
│ ├── lato
│ │ ├── DESCRIPTION.en_us.html
│ │ ├── FONTLOG.txt
│ │ ├── Lato-Black.ttf
│ │ ├── Lato-BlackItalic.ttf
│ │ ├── Lato-Bold.ttf
│ │ ├── Lato-BoldItalic.ttf
│ │ ├── Lato-Hairline.ttf
│ │ ├── Lato-HairlineItalic.ttf
│ │ ├── Lato-Italic.ttf
│ │ ├── Lato-Light.ttf
│ │ ├── Lato-LightItalic.ttf
│ │ ├── Lato-Regular.ttf
│ │ ├── METADATA.pb
│ │ └── OFL.txt
│ └── roboto
│ │ ├── COPYRIGHT.txt
│ │ ├── DESCRIPTION.en_us.html
│ │ ├── LICENSE.txt
│ │ ├── METADATA.pb
│ │ ├── Roboto-Black.ttf
│ │ ├── Roboto-BlackItalic.ttf
│ │ ├── Roboto-Bold.ttf
│ │ ├── Roboto-BoldItalic.ttf
│ │ ├── Roboto-Italic.ttf
│ │ ├── Roboto-Light.ttf
│ │ ├── Roboto-LightItalic.ttf
│ │ ├── Roboto-Medium.ttf
│ │ ├── Roboto-MediumItalic.ttf
│ │ ├── Roboto-Regular.ttf
│ │ ├── Roboto-Thin.ttf
│ │ └── Roboto-ThinItalic.ttf
├── node
│ ├── application-menu.yml
│ ├── index.js
│ ├── index.test.js
│ ├── kernels
│ │ └── python
│ │ │ ├── check.py
│ │ │ ├── client-response.js
│ │ │ ├── client-response.test.js
│ │ │ ├── client.js
│ │ │ ├── client.test.js
│ │ │ ├── language.js
│ │ │ ├── language.test.js
│ │ │ ├── listen.py
│ │ │ └── patch.py
│ └── services
│ │ ├── args.js
│ │ ├── assert.js
│ │ ├── assert.test.js
│ │ ├── browser-windows.js
│ │ ├── chromium-errors.yml
│ │ ├── clone.js
│ │ ├── db
│ │ ├── index.js
│ │ ├── index.test.js
│ │ ├── option-sanitization.js
│ │ └── postgresql
│ │ │ ├── get-columns-by-schema-and-table.sql
│ │ │ ├── get-schemas.sql
│ │ │ ├── get-tables-by-schema.sql
│ │ │ └── index.js
│ │ ├── electron-winston-transport.js
│ │ ├── env.js
│ │ ├── errors
│ │ └── process-error.js
│ │ ├── files.js
│ │ ├── files.test.js
│ │ ├── installer
│ │ ├── commands.js
│ │ ├── commands.test.js
│ │ ├── context-menu.js
│ │ ├── context-menu.test.js
│ │ ├── index.js
│ │ ├── shortcuts.js
│ │ └── shortcuts.test.js
│ │ ├── ipc-promises.js
│ │ ├── log.js
│ │ ├── md.hbs
│ │ ├── md.js
│ │ ├── md.test.js
│ │ ├── menu-definitions.js
│ │ ├── plot-server.js
│ │ ├── processes.js
│ │ ├── processes.test.js
│ │ ├── promises.js
│ │ ├── promises.test.js
│ │ ├── rest.js
│ │ ├── survey.js
│ │ ├── updater.js
│ │ └── win32
│ │ ├── registry.js
│ │ ├── system.js
│ │ └── system.test.js
├── readme.md
├── shared
│ ├── dateUtil.js
│ └── env.js
└── themes
│ ├── cobalt.less
│ ├── dark.less
│ ├── default.less
│ ├── imported
│ ├── cobalt.less
│ ├── dark.less
│ ├── default.less
│ ├── presentation.less
│ └── unk.less
│ ├── lib
│ ├── bootstrap-variables.less
│ ├── bootswatch.less
│ ├── jquery.dataTables.less
│ └── misc.less
│ ├── presentation.less
│ └── structure
│ ├── fixed-data-table.less
│ ├── forms.less
│ ├── global.less
│ └── jqconsole.less
├── test
├── browser
│ ├── index.js
│ ├── mocks
│ │ ├── ace.js
│ │ ├── ipc.js
│ │ └── storage.js
│ └── services
│ │ └── text-util.js
├── fixtures
│ └── windows-registry-commands
│ │ ├── install-context-menu.yml
│ │ └── uninstall-context-menu.yml
├── mocks
│ ├── classes
│ │ └── child-process.js
│ └── jupyter_examples
│ │ ├── create_svg_1.py
│ │ ├── create_svg_2.py
│ │ ├── example_1.py
│ │ ├── example_2.py
│ │ ├── example_3.py
│ │ ├── example_4.py
│ │ ├── example_5.py
│ │ ├── example_6.py
│ │ ├── example_7.py
│ │ └── example_8.py
└── node
│ └── index.js
├── watch.sh
├── webpack.config.js
├── webpack.dev.config.js
└── webpack.main.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": ["lodash"],
3 | "presets": ["es2015", "react"]
4 | }
5 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | **/lib/*.js
2 | node_modules/*
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .DS_Store
3 | cache
4 | *.pyc
5 | *.log
6 | BETA.md
7 | .vagrant
8 | *.swp
9 | npm-debug.log*
10 | .tmp
11 |
12 | app
13 | dist
14 | node_modules
15 | coverage
16 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 6.4
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "6.4"
4 | cache:
5 | directories:
6 | - node_modules
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Rodeo, An IDE for data science
2 | Copyright (C) 2015 Yhat, Inc.
3 |
4 | This program is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU Affero General Public License as
6 | published by the Free Software Foundation, either version 3 of the
7 | License, or (at your option) any later version.
8 |
9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU Affero General Public License for more details.
13 |
14 | You should have received a copy of the GNU Affero General Public License
15 | along with this program. If not, see .
16 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Rodeo
2 |
3 | ## [Rodeo Desktop](https://www.yhat.com/products/rodeo)
4 | 
5 |
6 | 
7 |
8 | ## Install
9 | Check [bareback.s.yhat.com](http://bareback.s.yhat.com) for the latest release. Download it!
10 |
11 |
12 | [Contributing](https://github.com/yhat/rodeo/blob/master/contributing.md)
13 |
--------------------------------------------------------------------------------
/__mocks__/ace.js:
--------------------------------------------------------------------------------
1 | const dict = {
2 | 'ace/autocomplete': {
3 | AutoComplete: {startCommand: {exec: function () {}}}
4 | }
5 | };
6 |
7 | function require(key) {
8 | return dict[key];
9 | }
10 |
11 | function edit() {
12 | return {
13 | getSession: function () {
14 | return {
15 | setValue: function () {
16 |
17 | }
18 | };
19 | }
20 | };
21 | }
22 |
23 | export default {
24 | require,
25 | edit
26 | };
27 |
--------------------------------------------------------------------------------
/__mocks__/browser-mocks.js:
--------------------------------------------------------------------------------
1 |
2 | function getSelection() {
3 | return {
4 | containsNode: function () { return false; }
5 | };
6 | }
7 |
8 | Object.defineProperty(window, 'getSelection', {
9 | value: getSelection
10 | });
11 |
--------------------------------------------------------------------------------
/__mocks__/generic-stub.js:
--------------------------------------------------------------------------------
1 | module.exports = {};
2 |
--------------------------------------------------------------------------------
/__mocks__/ipc.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 |
3 | export default {
4 | send: _.noop
5 | };
6 |
--------------------------------------------------------------------------------
/__mocks__/storage.js:
--------------------------------------------------------------------------------
1 | class MockStorage {
2 | constructor() {
3 | this.store = {};
4 | }
5 |
6 | getItem(key) {
7 | return this.store[key] || null;
8 | }
9 |
10 | setItem(key, value) {
11 | this.store[key] = value.toString();
12 | }
13 |
14 | clear() {
15 | this.store = {};
16 | }
17 |
18 | setStore(value) {
19 | this.store = value;
20 | }
21 |
22 | getStore() {
23 | return this.store;
24 | }
25 | }
26 |
27 | export default MockStorage;
28 |
--------------------------------------------------------------------------------
/build/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/build/background.png
--------------------------------------------------------------------------------
/build/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/build/icon.icns
--------------------------------------------------------------------------------
/build/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/build/icon.ico
--------------------------------------------------------------------------------
/build/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/build/icon.png
--------------------------------------------------------------------------------
/build/install-spinner.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/build/install-spinner.gif
--------------------------------------------------------------------------------
/karma.node.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function (karma) {
4 | karma.set({
5 | autoWatch: false,
6 | browsers: ['CustomElectron'],
7 | browserDisconnectTimeout: 1000 * 60 * 2,
8 | browserNoActivityTimeout: 1000 * 60 * 5,
9 | colors: true,
10 | singleRun: true,
11 | // logLevel: karma.LOG_DEBUG,
12 | reporters: [
13 | 'mocha'
14 | ],
15 | specReporter: {
16 | suppressErrorSummary: false, // do not print error summary
17 | suppressFailed: false, // do not print information about failed tests
18 | suppressPassed: false, // do not print information about passed tests
19 | suppressSkipped: false, // do not print information about skipped tests
20 | showSpecTiming: true // print the time elapsed for each spec
21 | },
22 | mochaReporter: {
23 | showDiff: true
24 | },
25 | customLaunchers: {
26 | CustomElectron: {
27 | base: 'Electron',
28 | flags: ['--enable-logging']
29 | }
30 | },
31 | files: [
32 | 'test/node/**/*.js',
33 | 'src/node/**/*.js'
34 | ],
35 | frameworks: ['mocha', 'chai'],
36 | preprocessors: {
37 | '**/*.js': ['electron']
38 | },
39 | plugins: [
40 | 'karma-mocha-reporter',
41 | 'karma-electron',
42 | 'karma-mocha',
43 | 'karma-chai'
44 | ]
45 | });
46 | };
47 |
--------------------------------------------------------------------------------
/scripts/osx/build.sh:
--------------------------------------------------------------------------------
1 | STARTING_DIR=$(pwd)
2 | TARGET_DIR=~/Projects/yhat/rodeo
3 | CACHE_MIN=999999999
4 |
5 | #guarantee nvm
6 | echo '#guarantee nvm'
7 | if ! brew list --versions | grep -q nvm; then
8 | brew install nvm
9 | fi
10 | source $(brew --prefix nvm)/nvm.sh
11 |
12 | #install script dependencies
13 | echo '#install script dependencies'
14 | npm install -q --cache-min $CACHE_MIN -g gulp-cli electron-prebuilt
15 |
16 | #build application (production and dev dependnencies)
17 | cd $TARGET_DIR
18 | echo '#build application (production and dev dependnencies)'
19 | rm -rf app dist
20 | npm install -q --cache-min $CACHE_MIN
21 | npm run build
22 | cd $STARTING_DIR
23 |
24 | #install application including production dependencies only (no dev)
25 | echo '#install application including production dependencies only (no dev)'
26 | cd "$TARGET_DIR/app"
27 | npm install -q --production --no-bin-links --cache-min $CACHE_MIN
28 | npm -q dedupe
29 | cd $STARTING_DIR
30 |
--------------------------------------------------------------------------------
/scripts/osx/create-test-postgresql-tables.sh:
--------------------------------------------------------------------------------
1 | sleep 5; psql -h localhost --username postgres -c "CREATE TABLE distributors ( \
2 | did integer, \
3 | name varchar(40), \
4 | UNIQUE(name) \
5 | );"
6 |
--------------------------------------------------------------------------------
/scripts/osx/dist-linux.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | STARTING_DIR=$(pwd)
3 | TARGET_DIR=~/Projects/yhat/rodeo
4 |
5 | cd $TARGET_DIR
6 |
7 | rm -rf dist
8 |
9 | #dependencies
10 | ./scripts/osx/install-deps.sh
11 | ./scripts/osx/install-dist-linux-deps.sh
12 |
13 | #remember nvm
14 | echo '#guarantee nvm'
15 | source $(brew --prefix nvm)/nvm.sh
16 | nvm use
17 |
18 | #build distributable
19 | node_modules/.bin/build --linux --x64
20 |
21 | #list created files
22 | echo '#list created files'
23 | git ls-files dist -o -x node_modules --directory
24 |
25 | cd $STARTING_DIR
26 |
--------------------------------------------------------------------------------
/scripts/osx/dist-osx.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | STARTING_DIR=$(pwd)
3 | TARGET_DIR=~/Projects/yhat/rodeo
4 |
5 | cd $TARGET_DIR
6 |
7 | rm -rf dist
8 |
9 | #dependencies
10 | ./scripts/osx/install-deps.sh
11 |
12 | #remember nvm
13 | echo '#remember nvm'
14 | source $(brew --prefix nvm)/nvm.sh
15 | nvm use
16 |
17 | #build distributable
18 | node_modules/.bin/build --osx --x64
19 |
20 | #list created files
21 | echo '#list created files:'
22 | git ls-files dist -o -x node_modules --directory
23 |
24 | cd $STARTING_DIR
25 |
--------------------------------------------------------------------------------
/scripts/osx/dist-win.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | STARTING_DIR=$(pwd)
3 | TARGET_DIR=~/Projects/yhat/rodeo
4 |
5 | cd $TARGET_DIR
6 |
7 | rm -rf dist
8 |
9 | #dependencies
10 | ./scripts/osx/install-deps.sh
11 | ./scripts/osx/install-dist-win-deps.sh
12 |
13 | #remember nvm
14 | echo '#guarantee nvm'
15 | source $(brew --prefix nvm)/nvm.sh
16 | nvm use
17 |
18 | #build distributable
19 | DEBUG=electron-windows-installer:* node_modules/.bin/build --win --x64
20 |
21 | #list created files
22 | echo '#list created files'
23 | git ls-files dist -o -x node_modules --directory
24 |
25 | cd $STARTING_DIR
26 |
--------------------------------------------------------------------------------
/scripts/osx/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '2'
2 | services:
3 | postgres1:
4 | image: postgres
5 | ports:
6 | - "5432:5432"
7 | environment:
8 | POSTGRES_DB: postgres
9 | POSTGRES_USER: postgres
10 | POSTGRES_PASSWORD: mysecretpassword
11 |
--------------------------------------------------------------------------------
/scripts/osx/install-deps.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # see https://github.com/electron-userland/electron-builder/wiki/Multi-Platform-Build
3 |
4 | STARTING_DIR=$(pwd)
5 | TARGET_DIR=~/Projects/yhat/rodeo
6 | CACHE_MIN=999999999
7 |
8 | #check brew
9 | echo '#check brew'
10 | brew doctor
11 | brew update
12 | brew --version
13 |
14 | # install testing dependencies (osx specific)
15 | echo '#install testing dependencies (osx specific)'
16 | brew tap homebrew/dupes
17 |
18 | if ! brew list --versions | grep -q libjpeg; then
19 | brew install libjpeg
20 | fi
21 |
22 | if ! brew list --versions | grep -q zlib; then
23 | brew install zlib
24 | brew link zlib --force
25 | fi
26 |
--------------------------------------------------------------------------------
/scripts/osx/install-dist-linux-deps.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #see https://github.com/electron-userland/electron-builder/wiki/Multi-Platform-Build
3 |
4 | #so we can build linux on mac
5 | echo '#so we can build linux on mac'
6 |
7 | if ! brew list --versions | grep -q gnu-tar; then
8 | brew install gnu-tar
9 | fi
10 |
11 | if ! brew list --versions | grep -q libicns; then
12 | brew install libicns
13 | fi
14 |
15 | if ! brew list --versions | grep -q graphicsmagick; then
16 | brew install graphicsmagick
17 | fi
18 |
19 | if ! brew list --versions | grep -q rpm; then
20 | brew install rpm
21 | fi
22 |
--------------------------------------------------------------------------------
/scripts/osx/install-dist-win-deps.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #see https://github.com/electron-userland/electron-builder/wiki/Multi-Platform-Build
3 |
4 | #so we can build windows on mac
5 | echo '#so we can build windows on mac'
6 |
7 | if ! brew list --versions | grep -q xquartz; then
8 | brew install Caskroom/cask/xquartz
9 | fi
10 |
11 | if ! brew list --versions | grep -q wine; then
12 | brew install wine
13 | fi
14 |
15 | if ! brew list --versions | grep -q mono; then
16 | brew install mono
17 | fi
18 |
--------------------------------------------------------------------------------
/scripts/osx/install-test-deps.sh:
--------------------------------------------------------------------------------
1 | . ~/.nvm/nvm.sh
2 | export PYENV_ROOT="$HOME/.pyenv"
3 | export PATH="$PYENV_ROOT/bin:$PATH"
4 | export PATH="$PYENV_ROOT/shims:$PATH"
5 |
--------------------------------------------------------------------------------
/scripts/osx/sign.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # codesign for OSX
4 | if [ -d dist/Rodeo-darwin-x64/Rodeo.app ]; then
5 | echo 'These are the valid codesigning ids:'
6 | security find-identity -vvvv -p codesigning
7 |
8 | echo 'This is the deep inspection of the current signature of the app:'
9 | codesign --deep --display -vvvv Rodeo.app
10 |
11 | echo 'These are the available Developer IDs:'
12 | certtool y | grep Developer\ ID
13 |
14 | # --sign the action to take
15 | # --deep sign all the things inside
16 | # --force replace any existing signatures
17 | codesign -vvvv --deep --force --sign "5D0C1D5ED6B38D0F63D63D0159422EA1544E8AE1" dist/Rodeo-darwin-x64/Rodeo-1.3.2.dmg
18 | # --verify the action to take
19 | codesign --verify -vvvv dist/Rodeo-darwin-x64/Rodeo.app
20 | spctl -a -vvvv --ignore-cache --no-cache dist/Rodeo-darwin-x64/Rodeo.app/
21 | fi
22 |
--------------------------------------------------------------------------------
/scripts/osx/test-postgresql.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | STARTING_DIR=$(pwd)
4 | TARGET_DIR=~/Projects/yhat/rodeo/scripts/osx
5 |
6 | cd $TARGET_DIR
7 |
8 | docker-compose up
9 |
10 | cd $STARTING_DIR
11 |
--------------------------------------------------------------------------------
/scripts/osx/update-info-plist.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | plist = open("dist/Rodeo-darwin-x64/Rodeo.app/Contents/Info.plist").read()
3 | find = """
4 | """
5 | idx = plist.index(find)
6 | doctypes = """ CFBundleDocumentTypes
7 |
8 |
9 | CFBundleTypeExtensions
10 |
11 | py
12 | rpy
13 | cpy
14 | python
15 |
16 | CFBundleTypeIconFile
17 | file.icns
18 | CFBundleTypeName
19 | Python source
20 | CFBundleTypeRole
21 | Editor
22 | LSHandlerRank
23 | Alternate
24 |
25 |
26 | """
27 |
28 | with open("dist/Rodeo-darwin-x64/Rodeo.app/Contents/Info.plist", "wb") as f:
29 | f.write(plist[:idx] + doctypes + plist[idx:])
30 |
--------------------------------------------------------------------------------
/scripts/osx/verify-sign.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # codesign for OSX
4 | if [ -d dist/Rodeo-darwin-x64/Rodeo.app ]; then
5 | echo 'These are the valid codesigning ids:'
6 | security find-identity -vvvv -p codesigning
7 |
8 | echo 'This is the deep inspection of the current signature of the app:'
9 | codesign --deep --display -vvvv Rodeo.app
10 |
11 | echo 'These are the available Developer IDs:'
12 | certtool y | grep Developer\ ID
13 |
14 | # --sign the action to take
15 | # --deep sign all the things inside
16 | # --force replace any existing signatures
17 | # --verify the action to take
18 | codesign --verify -vvvv dist/Rodeo-darwin-x64/Rodeo.app
19 | spctl -a -vvvv --ignore-cache --no-cache dist/Rodeo-darwin-x64/Rodeo.app
20 | fi
21 |
--------------------------------------------------------------------------------
/scripts/win/setup_conda.bat:
--------------------------------------------------------------------------------
1 | // install script to set windows right
2 |
3 | pip install jupyter_client ipykernel matplotlib numpy pandas
4 | jupyter install --user
5 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | import express from 'express';
2 | import webpack from 'webpack';
3 | import webpackDevMiddleware from 'webpack-dev-middleware';
4 | import webpackHotMiddleware from 'webpack-hot-middleware';
5 | import config from './webpack.dev.config.js';
6 |
7 | const app = express(),
8 | compiler = webpack(config),
9 | PORT = 3001;
10 |
11 | app.use(webpackDevMiddleware(compiler, {
12 | publicPath: config.output.publicPath,
13 | hot: true,
14 | historyApiFallback: true,
15 | stats: {
16 | colors: true
17 | }
18 | }));
19 |
20 | app.use(webpackHotMiddleware(compiler, {
21 | log: console.log,
22 | path: '/__webpack_hmr',
23 | heartbeat: 10 * 1000
24 | }));
25 |
26 | app.listen(PORT, 'localhost', err => {
27 | if (err) {
28 | console.error(err);
29 | return;
30 | }
31 |
32 | console.log(`Listening at http://localhost:${PORT}`);
33 | });
34 |
--------------------------------------------------------------------------------
/src/ace/mode-plain_text.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/mode/plain_text",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/text_highlight_rules","ace/mode/behaviour"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./text_highlight_rules").TextHighlightRules,o=e("./behaviour").Behaviour,u=function(){this.HighlightRules=s,this.$behaviour=new o};r.inherits(u,i),function(){this.type="text",this.getNextLineIndent=function(e,t,n){return""},this.$id="ace/mode/plain_text"}.call(u.prototype),t.Mode=u})
2 |
--------------------------------------------------------------------------------
/src/ace/readme.md:
--------------------------------------------------------------------------------
1 | ACE
2 | ===
3 |
4 | There is so much code here that compiling it with the rest of the jsx is a waste, so we put it into its own output file.
--------------------------------------------------------------------------------
/src/ace/snippets/mysql.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/mysql",["require","exports","module"],function(e,t,n){"use strict";t.snippetText=undefined,t.scope="mysql"})
2 |
--------------------------------------------------------------------------------
/src/ace/snippets/pgsql.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/pgsql",["require","exports","module"],function(e,t,n){"use strict";t.snippetText=undefined,t.scope="pgsql"})
2 |
--------------------------------------------------------------------------------
/src/ace/snippets/rdoc.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/rdoc",["require","exports","module"],function(e,t,n){"use strict";t.snippetText=undefined,t.scope="rdoc"})
--------------------------------------------------------------------------------
/src/ace/snippets/rhtml.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/rhtml",["require","exports","module"],function(e,t,n){"use strict";t.snippetText=undefined,t.scope="rhtml"})
--------------------------------------------------------------------------------
/src/ace/snippets/sql.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/sql",["require","exports","module"],function(e,t,n){"use strict";t.snippetText="snippet tbl\n create table ${1:table} (\n ${2:columns}\n );\nsnippet col\n ${1:name} ${2:type} ${3:default ''} ${4:not null}\nsnippet ccol\n ${1:name} varchar2(${2:size}) ${3:default ''} ${4:not null}\nsnippet ncol\n ${1:name} number ${3:default 0} ${4:not null}\nsnippet dcol\n ${1:name} date ${3:default sysdate} ${4:not null}\nsnippet ind\n create index ${3:$1_$2} on ${1:table}(${2:column});\nsnippet uind\n create unique index ${1:name} on ${2:table}(${3:column});\nsnippet tblcom\n comment on table ${1:table} is '${2:comment}';\nsnippet colcom\n comment on column ${1:table}.${2:column} is '${3:comment}';\nsnippet addcol\n alter table ${1:table} add (${2:column} ${3:type});\nsnippet seq\n create sequence ${1:name} start with ${2:1} increment by ${3:1} minvalue ${4:1};\nsnippet s*\n select * from ${1:table}\n",t.scope="sql"})
2 |
--------------------------------------------------------------------------------
/src/browser/actions/dialogs.js:
--------------------------------------------------------------------------------
1 | import applicationActions from '../actions/application';
2 | import {local} from '../services/store';
3 | import registration from '../services/registration';
4 | import modalDialogActions from '../containers/modal-dialog-viewer/modal-dialog.actions';
5 |
6 | function showAboutRodeo() {
7 | return modalDialogActions.add('aboutRodeo');
8 | }
9 |
10 | function showAboutStickers() {
11 | return modalDialogActions.add('aboutStickers');
12 | }
13 |
14 | function showPreferences() {
15 | return modalDialogActions.add('preferences');
16 | }
17 |
18 | function showAcknowledgements() {
19 | return modalDialogActions.add('acknowledgements');
20 | }
21 |
22 | function showRegisterRodeo() {
23 | return function (dispatch) {
24 | if (registration.shouldShowDialog()) {
25 | registration.rememberShowedDialog();
26 | dispatch(modalDialogActions.add('registerRodeo'));
27 | }
28 | };
29 | }
30 |
31 | function showAskQuit() {
32 | if (local.get('askQuit') === false) {
33 | return applicationActions.quit();
34 | }
35 |
36 | return modalDialogActions.add('askQuit');
37 | }
38 |
39 | export default {
40 | showAboutRodeo,
41 | showAboutStickers,
42 | showAcknowledgements,
43 | showAskQuit,
44 | showPreferences,
45 | showRegisterRodeo
46 | };
47 |
--------------------------------------------------------------------------------
/src/browser/actions/preferences.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import kernel from './kernel';
3 | import {local} from '../services/store';
4 |
5 | /**
6 | * @param {[object]} changes
7 | * @returns {function}
8 | */
9 | function savePreferenceChanges(changes) {
10 | // save the actual changes _immediately_ to ban race conditions
11 | _.each(changes, change => local.set(change.key, change.value));
12 |
13 | return function (dispatch) {
14 | // notify everyone of the changes that have _already happened_
15 | _.each(changes, change => dispatch({type: 'PREFERENCE_CHANGE_SAVED', change, meta: {track: true}}));
16 |
17 | // restart kernel only after all changes were announced, and only once
18 | if (_.some(changes, change => _.includes(['pythonCmd', 'workingDirectory'], change.key))) {
19 | dispatch(kernel.restart());
20 | }
21 | };
22 | }
23 |
24 | export default {
25 | savePreferenceChanges
26 | };
27 |
--------------------------------------------------------------------------------
/src/browser/components/ace-pane/ace-pane.css:
--------------------------------------------------------------------------------
1 | .ace-pane {
2 | height: 100%;
3 | }
4 |
5 | div.ace_tooltip {
6 | background: initial;
7 | border: 0;
8 | padding: 0;
9 | margin: 0;
10 | box-shadow: none;
11 | max-height: 30%;
12 | overflow-x: auto;
13 | }
14 |
15 | div.ace_editor.ace_autocomplete {
16 | width: 320px;
17 | }
18 |
19 | .rodeo-ace-pane-docstring {
20 | background: #f3f9ff;
21 | border: 1px solid #cde7fe;
22 | padding: 3px;
23 | margin-left: 3px;
24 | box-shadow: 2px 5px 10px #aaafb3;
25 | transition: opacity 0.2s;
26 | white-space: pre-wrap;
27 | font-size: smaller;
28 | }
29 |
--------------------------------------------------------------------------------
/src/browser/components/ace-pane/ace-pane.test.js:
--------------------------------------------------------------------------------
1 | /* globals describe, it, expect, jest */
2 |
3 | jest.mock('ace');
4 | jest.mock('../../services/ace-shortcuts');
5 | jest.mock('../../services/ace-settings');
6 |
7 | import React from 'react';
8 | import ReactDOM from 'react-dom';
9 | import TestUtils from 'react-addons-test-utils';
10 | import AcePane from './ace-pane';
11 |
12 | describe(__filename, () => {
13 | it('renders', () => {
14 | const reactDocument = TestUtils.renderIntoDocument( ),
15 | el = ReactDOM.findDOMNode(reactDocument);
16 |
17 | expect(el.className).toEqual('ace-pane font-monospaced');
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/src/browser/components/action-button.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import commonReact from '../services/common-react';
3 |
4 | export default React.createClass({
5 | displayName: 'ActionButton',
6 | propTypes: {
7 | action: React.PropTypes.oneOfType([React.PropTypes.func, React.PropTypes.object])
8 | },
9 | contextTypes: {
10 | store: React.PropTypes.object
11 | },
12 | shouldComponentUpdate() {
13 | // assume correct the first time
14 | return false;
15 | },
16 | handleClick: function () {
17 | this.context.store.dispatch(this.props.action);
18 | },
19 | render: function () {
20 | const props = this.props,
21 | className = commonReact.getClassNameList(this);
22 |
23 | return {props.children} ;
24 | }
25 | });
26 |
--------------------------------------------------------------------------------
/src/browser/components/actionest/actionest-button.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import React from 'react';
3 | import commonReact from '../../services/common-react';
4 | import './actionest.css';
5 |
6 | export default React.createClass({
7 | displayName: 'ActionestButton',
8 | propTypes: {
9 | icon: React.PropTypes.string.isRequired,
10 | onClick: React.PropTypes.func.isRequired
11 | },
12 | getDefaultProps: function () {
13 | return {onClick: _.noop};
14 | },
15 | shouldComponentUpdate: function (nextProps) {
16 | return commonReact.shouldComponentUpdate(this, nextProps);
17 | },
18 | render: function () {
19 | const props = this.props,
20 | className = commonReact.getClassNameList(this);
21 |
22 | className.push('actionest');
23 | className.push('fa', 'fa-' + props.icon);
24 |
25 | return
;
26 | }
27 | });
28 |
--------------------------------------------------------------------------------
/src/browser/components/block-history/block-history.css:
--------------------------------------------------------------------------------
1 | .block-history--empty {
2 | height: 100%;
3 | }
4 |
5 |
--------------------------------------------------------------------------------
/src/browser/components/block-history/expand-block-button.css:
--------------------------------------------------------------------------------
1 | .expand-block-button {
2 | height: 15px;
3 | text-align: center;
4 | position: absolute;
5 | bottom: 0;
6 | left: 0;
7 | right: 0;
8 | cursor: pointer;
9 | border-bottom-left-radius: 5px;
10 | border-bottom-right-radius: 5px;
11 | transition: all 0.2s;
12 | box-shadow: none;
13 | }
14 |
15 | .expand-block-button:hover {
16 | box-shadow: inset 0 -6px 5px -2px #ccc;
17 | }
18 |
--------------------------------------------------------------------------------
/src/browser/components/block-history/expand-block-button.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import commonReact from '../../services/common-react';
3 | import './expand-block-button.css';
4 |
5 | export default React.createClass({
6 | displayName: 'ExpandBlockButton',
7 | propTypes: {
8 | direction: React.PropTypes.string,
9 | onClick: React.PropTypes.func
10 | },
11 | shouldComponentUpdate: function (nextProps) {
12 | return commonReact.shouldComponentUpdate(this, nextProps);
13 | },
14 | render: function () {
15 | const props = this.props,
16 | className = commonReact.getClassNameList(this);
17 | let content;
18 |
19 | if (props.direction === 'up') {
20 | content = ;
21 | } else {
22 | content = ;
23 | }
24 |
25 | return {content}
;
26 | }
27 | });
28 | /**
29 | * Created by danestuckel on 10/11/16.
30 | */
31 |
--------------------------------------------------------------------------------
/src/browser/components/block-history/history-blocks/error-block.css:
--------------------------------------------------------------------------------
1 | .error-block {
2 | background-color: #feebeb;
3 | margin: 10px 4px 10px 2px;
4 | border-radius: 5px;
5 | padding: 6px;
6 | padding-top: 2px;
7 | border: 1px solid #d69fa0;
8 | box-shadow: 1px 2px 3px #feebeb;
9 | color: #b32327;
10 | white-space: pre;
11 | overflow-x: auto;
12 | position: relative;
13 | transition: all 0.2s;
14 | }
15 |
16 | .error-block:focus {
17 | box-shadow: 0 2px 15px #ffb2b2, 1px 2px 3px #999;
18 | outline: none;
19 | }
20 |
21 | .error-block > header {
22 | font-size: 10px;
23 | font-weight: bold;
24 | color: #d69fa0;
25 | text-transform: lowercase;
26 | display: flex;
27 | flex-direction: row;
28 | align-content: space-between;
29 | align-items: center;
30 | justify-content: space-between;
31 | border-bottom: 1px solid #d69fa0;
32 | }
33 |
34 | .error-block--compressed {
35 | overflow: hidden;
36 | }
37 |
38 | .error-block__contents-outer {
39 | overflow: hidden;
40 | margin-left:10px;
41 | margin-top: 7px;
42 | }
43 |
44 | .error-block__contents {
45 | overflow-x: auto;
46 | }
47 |
48 | .error-block__suggestions {
49 | text-align: right;
50 | }
51 |
--------------------------------------------------------------------------------
/src/browser/components/block-history/history-blocks/execution-result-block.css:
--------------------------------------------------------------------------------
1 | .execution-result-block {
2 | margin: 10px 4px 10px 2px;
3 | border-radius: 5px;
4 | padding: 6px;
5 | padding-top: 2px;
6 | border: 1px solid #ddd;
7 | box-shadow: 1px 2px 3px #999;
8 | color: #333;
9 | position: relative;
10 | transition: all 0.2s;
11 | }
12 |
13 | .execution-result-block:focus {
14 | box-shadow: 0 2px 10px #cce6ff, 1px 2px 3px #999;
15 | outline: none;
16 | }
17 |
18 | .execution-result-block--compressed {
19 | max-height: 45px;
20 | overflow: hidden;
21 | }
22 |
23 | .execution-result-block > header {
24 | font-size: 10px;
25 | font-weight: bold;
26 | color: #aaa;
27 | text-transform: lowercase;
28 | display: flex;
29 | flex-direction: row;
30 | align-content: space-between;
31 | align-items: center;
32 | justify-content: space-between;
33 | }
34 |
35 | .execution-result-block .dataframe {
36 | border: 1px solid #ccc;
37 | margin: 10px;
38 | }
39 |
40 | .execution-result-block .dataframe td,
41 | .execution-result-block .dataframe th {
42 | padding: 0 5px;
43 | }
44 |
--------------------------------------------------------------------------------
/src/browser/components/block-history/history-blocks/image-block.css:
--------------------------------------------------------------------------------
1 | .image-block {
2 | margin: 10px 4px 10px 2px;
3 | border-radius: 5px;
4 | padding: 6px;
5 | padding-top: 2px;
6 | border: 1px solid #ddd;
7 | box-shadow: 1px 2px 3px #999;
8 | color: #333;
9 | position: relative;
10 | transition: all 0.2s;
11 | }
12 |
13 | .image-block:focus {
14 | box-shadow: 0 2px 10px #cce6ff, 1px 2px 3px #999;
15 | outline: none;
16 | }
17 |
18 | .image-block--expanded {
19 | overflow: auto;
20 | }
21 |
22 | .image-block--compressed {
23 | overflow: hidden;
24 | }
25 |
26 | .image-block__contents-outer {
27 | overflow: hidden;
28 | margin-left: 10px;
29 | }
30 |
31 | .image-block > header {
32 | font-size: 10px;
33 | font-weight: bold;
34 | color: #aaa;
35 | text-transform: lowercase;
36 | display: flex;
37 | flex-direction: row;
38 | align-content: space-between;
39 | align-items: center;
40 | justify-content: space-between;
41 | border-bottom: 1px solid #ccc;
42 | }
43 |
44 | .image-block img {
45 | width: 100%;
46 | }
47 |
--------------------------------------------------------------------------------
/src/browser/components/block-history/history-blocks/input-stream-block.css:
--------------------------------------------------------------------------------
1 | .input-stream-block {
2 | margin: 10px 4px 10px 2px;
3 | border-radius: 5px;
4 | padding: 6px;
5 | padding-top: 2px;
6 | border: 1px solid #ddd;
7 | box-shadow: 1px 2px 3px #999;
8 | color: #333;
9 | position: relative;
10 | transition: all 0.2s;
11 | }
12 |
13 | .input-stream-block:focus {
14 | box-shadow: 0 2px 10px #cce6ff, 1px 2px 3px #999;
15 | outline: none;
16 | }
17 |
18 | .input-stream-block--expanded {
19 | overflow: auto;
20 | }
21 |
22 | .input-stream-block--compressed {
23 | overflow: hidden;
24 | }
25 |
26 | .input-stream-block__contents-outer {
27 | overflow: hidden;
28 | margin-left: 10px;
29 | }
30 |
31 | .input-stream-block__contents {
32 | white-space: pre-wrap;
33 | }
34 |
35 | .input-stream-block > header {
36 | font-size: 10px;
37 | font-weight: bold;
38 | color: #aaa;
39 | text-transform: lowercase;
40 | display: flex;
41 | flex-direction: row;
42 | align-content: space-between;
43 | align-items: center;
44 | justify-content: space-between;
45 | border-bottom: 1px solid #ccc;
46 | }
47 |
48 | .input-stream-block__menu .fa {
49 | margin-left: 5px;
50 | }
51 |
--------------------------------------------------------------------------------
/src/browser/components/block-history/history-blocks/jupyter-response-block.css:
--------------------------------------------------------------------------------
1 | .jupyter-response-block {
2 | margin: 15px;
3 | border-radius: 5px;
4 | padding: 0 5px 5px;
5 | border: 1px solid #ddd;
6 | box-shadow: 0 0 15px #e4f1fd, inset -1px -2px 3px #ccc;
7 | position: relative;
8 | transition: all 0.2s;
9 | }
10 |
11 | .jupyter-response-block__menu {
12 | text-align: right;
13 | }
14 |
15 | .jupyter-response-block-items > *:first-child {
16 | margin-top: 0;
17 | padding-top: 0;
18 | }
19 |
20 | .jupyter-response-block-items > *:last-child {
21 | margin-bottom: 5px;
22 | }
23 |
--------------------------------------------------------------------------------
/src/browser/components/block-history/history-blocks/postgresql-response-block.css:
--------------------------------------------------------------------------------
1 | .postgresql-response-block {
2 | margin: 15px;
3 | border-radius: 5px;
4 | padding: 0 5px 5px;
5 | border: 1px solid #ddd;
6 | box-shadow: 0 0 15px #e4f1fd, inset -1px -2px 3px #ccc;
7 | position: relative;
8 | transition: all 0.2s;
9 | }
10 |
11 | .postgresql-response-block__menu {
12 | text-align: right;
13 | }
14 |
15 | .postgresql-response-block__items > *:first-child {
16 | margin-top: 0;
17 | padding-top: 0;
18 | }
19 |
20 | .postgresql-response-block__items > *:last-child {
21 | margin-bottom: 5px;
22 | }
23 |
--------------------------------------------------------------------------------
/src/browser/components/block-history/history-blocks/python-error-block.css:
--------------------------------------------------------------------------------
1 | .python-error-block {
2 | background-color: #feebeb;
3 | margin: 10px 4px 10px 2px;
4 | border-radius: 5px;
5 | padding: 6px;
6 | padding-top: 2px;
7 | border: 1px solid #d69fa0;
8 | box-shadow: 1px 2px 3px #feebeb;
9 | color: #b32327;
10 | white-space: pre;
11 | overflow-x: auto;
12 | position: relative;
13 | transition: all 0.2s;
14 | }
15 |
16 | .python-error-block:focus {
17 | box-shadow: 0 2px 15px #ffb2b2, 1px 2px 3px #999;
18 | outline: none;
19 | }
20 |
21 | .python-error-block > header {
22 | font-size: 10px;
23 | font-weight: bold;
24 | color: #d69fa0;
25 | text-transform: lowercase;
26 | display: flex;
27 | flex-direction: row;
28 | align-content: space-between;
29 | align-items: center;
30 | justify-content: space-between;
31 | border-bottom: 1px solid #d69fa0;
32 | }
33 |
34 | .python-error-block--compressed {
35 | overflow: hidden;
36 | }
37 |
38 | .python-error-block__contents-outer {
39 | overflow: hidden;
40 | margin-left:10px;
41 | margin-top: 7px;
42 | }
43 |
44 | .python-error-block__contents {
45 | overflow-x: auto;
46 | }
47 |
48 | .python-error-block__suggestions {
49 | text-align: right;
50 | }
51 |
--------------------------------------------------------------------------------
/src/browser/components/block-history/history-blocks/text-stream-block.css:
--------------------------------------------------------------------------------
1 | .text-stream-block {
2 | margin: 10px 4px 10px 2px;
3 | border-radius: 5px;
4 | padding: 6px;
5 | padding-top: 2px;
6 | border: 1px solid #ddd;
7 | box-shadow: 1px 2px 3px #999;
8 | color: #333;
9 | position: relative;
10 | transition: all 0.2s;
11 | }
12 |
13 | .text-stream-block:focus {
14 | box-shadow: 0 2px 10px #cce6ff, 1px 2px 3px #999;
15 | outline: none;
16 | }
17 |
18 | .text-stream-block--expanded {
19 | overflow-y: auto;
20 | overflow-x: inherit;
21 | }
22 |
23 | .text-stream-block--compressed {
24 | overflow: hidden;
25 | }
26 |
27 | .text-stream-block__contents-outer {
28 | overflow: hidden;
29 | margin-left:10px;
30 | }
31 |
32 | .text-stream-block__contents {
33 | overflow: hidden;
34 | white-space: pre-wrap;
35 | }
36 |
37 | .text-stream-block > header {
38 | font-size: 10px;
39 | font-weight: bold;
40 | color: #aaa;
41 | text-transform: lowercase;
42 | display: flex;
43 | flex-direction: row;
44 | align-content: space-between;
45 | align-items: center;
46 | justify-content: space-between;
47 | border-bottom: 1px solid #ccc;
48 | }
49 |
--------------------------------------------------------------------------------
/src/browser/components/block-history/history-list.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import React from 'react';
3 | import commonReact from '../../services/common-react';
4 |
5 | /**
6 | * @class PackagesViewer
7 | * @extends ReactComponent
8 | */
9 | export default React.createClass({
10 | displayName: 'HistoryList',
11 | propTypes: {
12 | filter: React.PropTypes.string.isRequired,
13 | history: React.PropTypes.array.isRequired
14 | },
15 | shouldComponentUpdate: function (nextProps) {
16 | return commonReact.shouldComponentUpdate(this, nextProps);
17 | },
18 | render: function () {
19 | const props = this.props,
20 | className = commonReact.getClassNameList(this),
21 | history = _.filter(props.history, item => !props.filter || item.text.indexOf(props.filter) > -1);
22 |
23 | return (
24 |
25 |
26 |
27 | {_.map(history, (item, index) => {item.text} )}
28 |
29 |
30 |
31 | );
32 | }
33 | });
34 |
--------------------------------------------------------------------------------
/src/browser/components/block-history/history-viewer.css:
--------------------------------------------------------------------------------
1 | .rodeo .history-viewer {
2 | height: 100%;
3 | overflow: auto;
4 | }
5 |
6 | .rodeo .history-viewer td {
7 | border: 0
8 | }
9 |
--------------------------------------------------------------------------------
/src/browser/components/block-history/history-viewer.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import React from 'react';
3 | import commonReact from '../../services/common-react';
4 | import './history-viewer.css';
5 | import EmptySuggestion from '../empty/empty-suggestion';
6 | import HistoryList from './history-list';
7 |
8 | /**
9 | * @class PackagesViewer
10 | * @extends ReactComponent
11 | */
12 | export default React.createClass({
13 | displayName: 'HistoryViewer',
14 | propTypes: {
15 | filter: React.PropTypes.string.isRequired,
16 | history: React.PropTypes.array.isRequired
17 | },
18 | shouldComponentUpdate: function (nextProps) {
19 | return commonReact.shouldComponentUpdate(this, nextProps);
20 | },
21 | render: function () {
22 | const props = this.props,
23 | className = commonReact.getClassNameList(this),
24 | contents = [];
25 |
26 | if (props.history && props.history.length) {
27 | contents.push( );
28 | } else {
29 | contents.push( );
30 | }
31 |
32 | return {contents}
;
33 | }
34 | });
35 |
--------------------------------------------------------------------------------
/src/browser/components/brand-splashes/brand-splashes.css:
--------------------------------------------------------------------------------
1 | img.brand-splash {
2 | width: 100%;
3 | }
4 |
--------------------------------------------------------------------------------
/src/browser/components/brand-splashes/logo-rodeo-grey-text.sketch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/browser/components/brand-splashes/logo-rodeo-grey-text.sketch
--------------------------------------------------------------------------------
/src/browser/components/brand-splashes/logo-rodeo-large.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import logo from './logo-rodeo-grey-text.svg';
3 | import './brand-splashes.css';
4 |
5 | /**
6 | * @class BrandSplash
7 | * @extends ReactComponent
8 | */
9 | export default React.createClass({
10 | displayName: 'BrandSplash',
11 | render: function () {
12 | return ;
13 | }
14 | });
15 |
--------------------------------------------------------------------------------
/src/browser/components/brand-splashes/logo-rodeo-square-large.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import logo from './logo-rodeo-square-large.svg';
3 | import './brand-splashes.css';
4 |
5 | /**
6 | * @class BrandSplash
7 | * @extends ReactComponent
8 | */
9 | export default React.createClass({
10 | displayName: 'BrandSplash',
11 | render: function () {
12 | return ;
13 | }
14 | });
15 |
--------------------------------------------------------------------------------
/src/browser/components/data-frame/data-frame-loading-icon.jsx:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import React from 'react';
3 |
4 | /**
5 | * @class DataFrameLoadingIcon
6 | * @extends ReactComponent
7 | */
8 | export default React.createClass({
9 | displayName: 'DataFrameLoadingIcon',
10 | propTypes: {
11 | isLoading: React.PropTypes.bool.isRequired,
12 | label: React.PropTypes.string.isRequired
13 | },
14 | getInitialState: function () {
15 | return {};
16 | },
17 | componentDidMount: function () {
18 | _.defer(() => this.setState({
19 | hasRendered: true
20 | }));
21 | },
22 | hasRendered: function () {
23 | this.setState({
24 | hasRendered: true
25 | });
26 | },
27 | render: function () {
28 | const props = this.props,
29 | state = this.state,
30 | style = {
31 | opacity: props.isLoading && state.hasRendered ? 1 : 0
32 | };
33 |
34 | return (
35 |
36 |
37 |
{props.label}
38 |
39 | );
40 | }
41 | });
42 |
--------------------------------------------------------------------------------
/src/browser/components/data-frame/data-frame-loading-icon.test.js:
--------------------------------------------------------------------------------
1 | /* globals describe, it, expect, jest */
2 |
3 | import React from 'react';
4 | import ReactDOM from 'react-dom';
5 | import TestUtils from 'react-addons-test-utils';
6 | import DataFrameLoadingIcon from './data-frame-loading-icon.jsx';
7 |
8 | jest.useFakeTimers()
9 |
10 | describe('UnsafeHtml', () => {
11 |
12 | it('renders html with opacity 0 at first', () => {
13 | const reactDocument = TestUtils.renderIntoDocument( ),
14 | el = ReactDOM.findDOMNode(reactDocument);
15 |
16 | expect(el.style.getPropertyValue('opacity')).toEqual('0');
17 | });
18 |
19 | it('renders html with opacity 1 right after', () => {
20 | const reactDocument = TestUtils.renderIntoDocument( ),
21 | el = ReactDOM.findDOMNode(reactDocument);
22 |
23 | jest.runAllTimers();
24 |
25 | expect(el.style.getPropertyValue('opacity')).toEqual('1');
26 | });
27 | });
28 |
--------------------------------------------------------------------------------
/src/browser/components/data-frame/data-frame.css:
--------------------------------------------------------------------------------
1 | .data-frame-container {
2 | overflow: hidden;
3 | }
4 |
5 | .data-frame-container .data-frame-loading-icon {
6 | position: absolute;
7 | top: calc(50% - 20px);
8 | left: calc(50% - 65px);
9 | text-align: center;
10 | transition: opacity 0.2s;
11 | }
12 |
13 | .data-frame-container .public_fixedDataTableCell_cellContent {
14 | white-space: nowrap;
15 | }
16 |
17 |
--------------------------------------------------------------------------------
/src/browser/components/databases/database-explorer-tree-header.css:
--------------------------------------------------------------------------------
1 | .file-tree-header {
2 | padding: 2px;
3 | border-bottom: 1px solid #ccc;
4 | }
5 |
6 | .file-tree-header .item {
7 | cursor: pointer;
8 | color: #999;
9 | transition: all 0.2s;
10 | display: inline-block;
11 | margin-left: 8px;
12 | margin-right: 8px;
13 | }
14 |
15 | .file-tree-header .item:first-child {
16 | margin-left: 6px;
17 | }
18 |
19 | .file-tree-header .item:hover {
20 | color: #333;
21 | }
22 |
23 | .file-tree-header .item .fa {
24 | padding-right: 5px;
25 | }
26 |
--------------------------------------------------------------------------------
/src/browser/components/databases/database-explorer-tree-header.jsx:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import React from 'react';
3 | import commonReact from '../../services/common-react';
4 | import './database-explorer-tree-header.css';
5 |
6 | /**
7 | * @class FileList
8 | * @description Visual representation of the chrome around a list of files. Can show parent, sorts files by directory/file.
9 | * @extends ReactComponent
10 | * @property props
11 | */
12 | export default React.createClass({
13 | displayName: 'FileTreeHeader',
14 | propTypes: {
15 |
16 | },
17 | render: function () {
18 | const props = this.props,
19 | className = commonReact.getClassNameList(this);
20 |
21 | return (
22 |
23 |
{'Parent'}
24 |
{'Home'}
25 |
{'Working Directory'}
26 |
27 | );
28 | }
29 | });
30 |
--------------------------------------------------------------------------------
/src/browser/components/databases/database-explorer-tree.css:
--------------------------------------------------------------------------------
1 | .file-tree {
2 | position: relative;
3 | overflow: auto;
4 | height: 100%;
5 | }
6 |
--------------------------------------------------------------------------------
/src/browser/components/dialogs/about-rodeo.css:
--------------------------------------------------------------------------------
1 | .about-rodeo {
2 | padding: 20px;
3 | max-width: 600px;
4 | position: relative;
5 | }
6 |
7 | .about-rodeo img {
8 | max-height: 200px;
9 | width: 90%;
10 | }
11 |
12 | .about-rodeo button {
13 | margin: 10px auto 10px auto;
14 | display: block;
15 | }
16 |
17 | .about-rodeo .version {
18 | top: 0;
19 | right: 0;
20 | position: absolute;
21 | margin: 10px 16px;
22 | }
23 |
--------------------------------------------------------------------------------
/src/browser/components/dialogs/about-rodeo.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Marked from '../marked';
3 | import ActionButton from '../action-button';
4 | import dialogActions from '../../actions/dialogs';
5 | import rodeoTextDarkImage from './rodeo-text-dark.png';
6 | import commonReact from '../../services/common-react';
7 | import './about-rodeo.css';
8 |
9 | export default React.createClass({
10 | displayName: 'AboutRodeo',
11 | contextTypes: {
12 | text: React.PropTypes.object
13 | },
14 | shouldComponentUpdate(nextProps) {
15 | return commonReact.shouldComponentUpdate(this, nextProps);
16 | },
17 | render() {
18 | const className = commonReact.getClassNameList(this),
19 | text = this.context.text;
20 |
21 | return (
22 |
23 |
24 |
{__VERSION__}
25 |
{text.builtByYhat}
26 |
{text.includesOpenSource}
27 |
28 | {text.acknowledgements}
29 |
30 |
{text.usageMetrics}
31 |
32 | );
33 | }
34 | });
35 |
--------------------------------------------------------------------------------
/src/browser/components/dialogs/acknowledgements.css:
--------------------------------------------------------------------------------
1 | .acknowledgements {
2 | display: flex;
3 | flex-direction: column;
4 | padding: 20px;
5 | max-width: 600px;
6 | position: relative;
7 | }
8 |
9 | .acknowledgements img {
10 | max-height: 200px;
11 | width: 90%;
12 | }
13 |
14 | .acknowledgements .scrollable {
15 | overflow-y: scroll;
16 | }
17 |
--------------------------------------------------------------------------------
/src/browser/components/dialogs/acknowledgements.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Marked from '../marked';
3 | import acknowledgementsText from './acknowledgements.md';
4 | import './acknowledgements.css';
5 | import rodeoTextDarkImage from './rodeo-text-dark.png';
6 |
7 | export default React.createClass({
8 | displayName: 'Acknowledgements',
9 | render: function () {
10 | return (
11 |
12 |
13 |
14 | {acknowledgementsText}
15 |
16 |
17 | );
18 | }
19 | });
20 |
--------------------------------------------------------------------------------
/src/browser/components/dialogs/ask-quit.css:
--------------------------------------------------------------------------------
1 | .ask-quit__question {
2 | display: flex;
3 | justify-content: center;
4 | margin: 20px;
5 | font-size: large;
6 | }
7 |
8 | .ask-quit__item {
9 | display: flex;
10 | justify-content: center;
11 | margin: 20px;
12 | }
13 |
14 | .ask-quit__small-item {
15 | display: flex;
16 | justify-content: center;
17 | margin: 10px;
18 | transform: scale(0.8);
19 | }
20 |
--------------------------------------------------------------------------------
/src/browser/components/dialogs/environment-variables-dialog.css:
--------------------------------------------------------------------------------
1 | .environment-variables-dialog {
2 | position: relative;
3 | min-height: 400px;
4 | height: 100%;
5 | }
6 |
7 | .environment-variables-dialog > footer {
8 | bottom: 0;
9 | right: 0;
10 | padding: 7px 20px;
11 | height: 50px;
12 | text-align: right;
13 | position: relative;
14 | }
15 |
16 | .environment-variables-dialog__content {
17 | padding: 20px;
18 | overflow-y: scroll;
19 | position: relative;
20 | display: flex;
21 | flex-direction: row;
22 | align-content: stretch;
23 | align-items: stretch;
24 | height: calc(100% - 50px);
25 | }
26 |
--------------------------------------------------------------------------------
/src/browser/components/dialogs/modal-dialog-container.css:
--------------------------------------------------------------------------------
1 | .modal-dialog-container {
2 | position: absolute;
3 | display: none;
4 | top: 0;
5 | bottom: 0;
6 | left: 0;
7 | right: 0;
8 | z-index: 1000; /* higher than split-panes */
9 | }
10 |
11 | .modal-dialog-container .inner-container {
12 | position: absolute;
13 | display: flex;
14 | top: 0;
15 | bottom: 0;
16 | left: 0;
17 | right: 0;
18 | justify-content: center;
19 | flex-direction: column;
20 | }
21 |
22 | .modal-dialog-container .inner-container:last-child {
23 | background-color: rgba(50, 50, 100, 0.5);
24 | z-index: 11;
25 | }
26 |
27 | .modal-dialog-container.modal-dialog-container--active {
28 | display: block;
29 | }
30 |
--------------------------------------------------------------------------------
/src/browser/components/dialogs/modal-dialog.css:
--------------------------------------------------------------------------------
1 | .modal-dialog-instance {
2 | margin-left: auto;
3 | margin-right: auto;
4 | display: flex;
5 | flex-direction: column;
6 | min-width: 400px;
7 | max-width: 1000px;
8 | max-height: 90%;
9 | z-index: 11;
10 | background-color: white;
11 | box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.4);
12 | transition: all 0.8s;
13 | opacity: 0;
14 | border-radius: 2px;
15 | }
16 |
17 | .modal-dialog-instance.modal-dialog-instance--small {
18 | width: 100px;
19 | }
20 |
21 | .modal-dialog-instance.modal-dialog-instance--full {
22 | width: 100%;
23 | height: 100%;
24 | }
25 |
26 | .modal-dialog-instance.modal-dialog-instance--visible {
27 | opacity: 1;
28 | }
29 |
30 | .modal-dialog-instance > header {
31 | flex: 0 0 10px;
32 | position: relative;
33 | background-color: #337ab7;
34 | color: #fff;
35 | padding: 2px 12px;
36 | border-top-left-radius: 2px;
37 | border-top-right-radius: 2px;
38 | font-weight: bold;
39 | }
40 |
41 | .modal-dialog-instance > footer {
42 | flex: 0 0 40px;
43 | position: relative;
44 | }
45 |
46 | .modal-dialog-instance button {
47 | margin-left: 10px;
48 | }
49 |
--------------------------------------------------------------------------------
/src/browser/components/dialogs/modal-dialog.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import React from 'react';
3 | import ReactDOM from 'react-dom';
4 | import commonReact from '../../services/common-react';
5 | import './modal-dialog.css';
6 |
7 | export default React.createClass({
8 | displayName: 'ModalDialog',
9 | propTypes: {
10 | buttons: React.PropTypes.array,
11 | onApply: React.PropTypes.func,
12 | onCancel: React.PropTypes.func,
13 | onOK: React.PropTypes.func,
14 | title: React.PropTypes.string
15 | },
16 | contextTypes: {
17 | text: React.PropTypes.object.isRequired
18 | },
19 | componentDidMount() {
20 | const el = ReactDOM.findDOMNode(this);
21 |
22 | _.defer(() => el.classList.add('modal-dialog-instance--visible'));
23 | },
24 | shouldComponentUpdate(nextProps) {
25 | return commonReact.shouldComponentUpdate(this, nextProps);
26 | },
27 | render() {
28 | const props = this.props,
29 | className = commonReact.getClassNameList(this);
30 | let header;
31 |
32 | className.push('modal-dialog-instance');
33 |
34 | if (props.title) {
35 | header = ;
36 | }
37 |
38 | return (
39 |
40 | {header}
41 | {props.children}
42 |
43 | );
44 | }
45 | });
46 |
--------------------------------------------------------------------------------
/src/browser/components/dialogs/rodeo-text-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/browser/components/dialogs/rodeo-text-dark.png
--------------------------------------------------------------------------------
/src/browser/components/dialogs/stickers-pane.css:
--------------------------------------------------------------------------------
1 | .stickers-pane {
2 | text-align: center;
3 | padding: 20px;
4 | max-width: 600px;
5 | position: relative;
6 | }
7 |
8 | .stickers-pane__logo {
9 | display: block;
10 | margin: 10px;
11 | }
12 |
13 | .stickers-pane__logo img {
14 | height: 100px;
15 | }
16 |
--------------------------------------------------------------------------------
/src/browser/components/document-terminal/document-terminal-annotation.css:
--------------------------------------------------------------------------------
1 | .document-terminal-annotation {
2 | overflow: hidden;
3 | padding: 2px;
4 | margin: 5px;
5 | position: relative;
6 | cursor: pointer;
7 | }
8 |
9 | .document-terminal-annotation img {
10 | width: 100%;
11 | height: auto;
12 | }
13 |
14 | .document-terminal-annotation__image {
15 | display: block;
16 | height: auto;
17 | width: 20%;
18 | min-width: 100px;
19 | max-width: 200px;
20 | overflow: hidden;
21 | padding: 2px;
22 | margin: 5px;
23 | position: relative;
24 | }
25 |
--------------------------------------------------------------------------------
/src/browser/components/document-terminal/document-terminal-autocomplete.css:
--------------------------------------------------------------------------------
1 | .document-terminal-autocomplete {
2 | display: flex;
3 | flex-direction: row;
4 | flex-wrap: wrap;
5 | border: solid 1px rgba(0, 135, 255, 0.2);
6 | background-color: rgba(0, 135, 255, 0.05);
7 | margin: 6px;
8 | padding: 4px;
9 | }
10 |
11 | .document-terminal-autocomplete-item {
12 | white-space: pre;
13 | margin-right: 20px;
14 | margin-left: 10px;
15 | }
16 |
--------------------------------------------------------------------------------
/src/browser/components/document-terminal/document-terminal-autocomplete.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import commonReact from '../../services/common-react';
3 | import textUtil from '../../services/text-util';
4 | import './document-terminal-autocomplete.css';
5 |
6 | export default React.createClass({
7 | displayName: 'DocumentTerminalAutocomplete',
8 | propTypes: {
9 | matches: React.PropTypes.array.isRequired
10 | },
11 | shouldComponentUpdate: function (nextProps) {
12 | return commonReact.shouldComponentUpdate(this, nextProps);
13 | },
14 | render: function () {
15 | const props = this.props,
16 | matches = props.matches,
17 | className = commonReact.getClassNameList(this),
18 | longestLen = textUtil.longestLength(matches),
19 | paddedMatches = matches.map(match => textUtil.padRight(match, longestLen));
20 |
21 | return (
22 |
23 | {paddedMatches.map(match => {match} )}
24 |
25 | );
26 | }
27 | });
28 |
--------------------------------------------------------------------------------
/src/browser/components/document-terminal/document-terminal-error.css:
--------------------------------------------------------------------------------
1 | .document-terminal-error {
2 | padding: 0;
3 | position: relative;
4 | color: #b11e22;
5 | margin: 0 10px;
6 | }
7 |
8 | .document-terminal-error__suggestions {
9 | text-align: right;
10 | }
11 |
--------------------------------------------------------------------------------
/src/browser/components/document-terminal/document-terminal-page-break.css:
--------------------------------------------------------------------------------
1 | .document-terminal-page-break {
2 | clear: both;
3 | border: 0;
4 | margin-top: 0;
5 | margin-bottom: 0;
6 | }
7 |
--------------------------------------------------------------------------------
/src/browser/components/document-terminal/document-terminal-page-break.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import commonReact from '../../services/common-react';
3 | import './document-terminal-page-break.css';
4 |
5 | export default React.createClass({
6 | displayName: 'DocumentTerminalPageBreak',
7 | shouldComponentUpdate: function (nextProps) {
8 | return false;
9 | },
10 | render: function () {
11 | const className = commonReact.getClassNameList(this);
12 |
13 | return ;
14 | }
15 | });
16 | /**
17 | * Created by danestuckel on 10/11/16.
18 | */
19 |
--------------------------------------------------------------------------------
/src/browser/components/document-terminal/document-terminal-python-error.css:
--------------------------------------------------------------------------------
1 | .document-terminal-python-error {
2 | padding: 0;
3 | position: relative;
4 | color: #b11e22;
5 | margin: 0 10px;
6 | }
7 |
8 | .document-terminal-python-error__suggestions {
9 | text-align: right;
10 | }
11 |
--------------------------------------------------------------------------------
/src/browser/components/document-terminal/document-terminal-text.css:
--------------------------------------------------------------------------------
1 | .document-terminal-text {
2 | color: #333;
3 | margin: 0 10px;
4 | white-space: pre-wrap;
5 | word-break: break-all;
6 | }
7 |
--------------------------------------------------------------------------------
/src/browser/components/document-terminal/document-terminal-text.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import commonReact from '../../services/common-react';
3 | import './document-terminal-text.css';
4 |
5 | export default React.createClass({
6 | displayName: 'DocumentTerminalText',
7 | propTypes: {
8 | html: React.PropTypes.string.isRequired,
9 | id: React.PropTypes.string.isRequired
10 | },
11 | shouldComponentUpdate: function (nextProps) {
12 | return commonReact.shouldComponentUpdate(this, nextProps);
13 | },
14 | render: function () {
15 | const props = this.props,
16 | className = commonReact.getClassNameList(this);
17 |
18 | return (
19 |
24 | );
25 | }
26 | });
27 |
--------------------------------------------------------------------------------
/src/browser/components/document-terminal/document-terminal.css:
--------------------------------------------------------------------------------
1 | .document-terminal {
2 | position: relative;
3 | height: 100%;
4 | display: flex;
5 | flex-direction: column;
6 | align-items: stretch;
7 | align-content: stretch;
8 | }
9 |
10 | .document-terminal .sticky-bottom-scroll {
11 | flex-grow: 5;
12 | overflow-y: auto;
13 | white-space: pre-wrap;
14 | }
15 |
16 | .document-terminal .prompt {
17 | flex-grow: 0;
18 | flex-shrink: 0;
19 | }
20 |
--------------------------------------------------------------------------------
/src/browser/components/document-terminal/document-terminal.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import commonReact from '../../services/common-react';
3 | import './document-terminal.css';
4 |
5 | export default React.createClass({
6 | displayName: 'DocumentTerminal',
7 | propTypes: {
8 | onClick: React.PropTypes.func,
9 | onPaste: React.PropTypes.func
10 | },
11 | shouldComponentUpdate: function (nextProps) {
12 | return commonReact.shouldComponentUpdate(this, nextProps);
13 | },
14 | render: function () {
15 | const props = this.props,
16 | className = commonReact.getClassNameList(this),
17 | style = {
18 | fontSize: props.fontSize + 'px'
19 | };
20 |
21 | className.push('font-monospaced');
22 |
23 | return (
24 | {props.children}
30 | );
31 | }
32 | });
33 |
--------------------------------------------------------------------------------
/src/browser/components/document-terminal/sticky-bottom-scroll.css:
--------------------------------------------------------------------------------
1 | .sticky-bottom-scroll {
2 | overflow-y: auto;
3 | display: block;
4 | }
5 |
--------------------------------------------------------------------------------
/src/browser/components/empty/empty-suggestion.css:
--------------------------------------------------------------------------------
1 | .empty-suggestion {
2 | color: #cbcbcb;
3 | display: flex;
4 | align-items: center;
5 | justify-content: center;
6 | height: 100%;
7 | font-size: 14px;
8 | }
9 |
--------------------------------------------------------------------------------
/src/browser/components/empty/empty-suggestion.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import './empty-suggestion.css';
3 | import commonReact from '../../services/common-react';
4 | import Marked from '../marked';
5 |
6 | export default React.createClass({
7 | displayName: 'EmptySuggestion',
8 | propTypes: {
9 | label: React.PropTypes.string.isRequired
10 | },
11 | getDefaultProps() {
12 | return {
13 | label: ''
14 | };
15 | },
16 | shouldComponentUpdate: function (nextProps) {
17 | return commonReact.shouldComponentUpdate(this, nextProps);
18 | },
19 | render: function () {
20 | const props = this.props,
21 | className = commonReact.getClassNameList(this);
22 |
23 | className.push('font-sans');
24 |
25 | return {props.label}
;
26 | }
27 | });
28 |
--------------------------------------------------------------------------------
/src/browser/components/files/file-list.css:
--------------------------------------------------------------------------------
1 | .file-list {
2 | position: relative;
3 | overflow: auto;
4 | height: 100%;
5 | }
6 |
7 | .file-list-item {
8 | color: #808080;
9 | padding: 2px 10px;
10 | display: block;
11 | cursor: pointer;
12 | }
13 |
14 | .file-list-item .fa-before:before {
15 | padding-right: 6px;
16 | }
17 |
18 | .file-list-item:hover {
19 | background-color: #dddddd;
20 | }
21 |
22 | .file-list-item.file-list-item-selected {
23 | background-color: #95d7ff;
24 | }
25 |
26 | .file-list-item.selected:hover {
27 | background-color: #b7e5ff;
28 | }
29 |
--------------------------------------------------------------------------------
/src/browser/components/files/file-list.jsx:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import React from 'react';
3 | import FileListItem from './file-list-item.jsx';
4 | import './file-list.css';
5 |
6 | /**
7 | * @class FileList
8 | * @description Visual representation of the chrome around a list of files. Can show parent, sorts files by directory/file.
9 | * @extends ReactComponent
10 | * @property props
11 | */
12 | export default React.createClass({
13 | displayName: 'FileList',
14 | propTypes: {
15 | id: React.PropTypes.string,
16 | onGoToSpecialDirectory: React.PropTypes.func
17 | },
18 | render: function () {
19 | const props = this.props;
20 | let parent,
21 | files = React.Children.toArray(props.children);
22 |
23 | files = _.filter(files, item => !props.filter || item.props.label.indexOf(props.filter) > -1);
24 |
25 | if (props.onGoToSpecialDirectory) {
26 | parent = (
27 |
33 | );
34 | }
35 |
36 | return (
37 |
38 | {parent}
39 | {files.filter(file => file.props.isDirectory)}
40 | {files.filter(file => !file.props.isDirectory)}
41 |
42 | );
43 | }
44 | });
45 |
--------------------------------------------------------------------------------
/src/browser/components/files/file-tree-header.css:
--------------------------------------------------------------------------------
1 | .file-tree-header {
2 | padding: 2px;
3 | border-bottom: 1px solid #ccc;
4 | }
5 |
6 | .file-tree-header .item {
7 | cursor: pointer;
8 | color: #999;
9 | transition: all 0.2s;
10 | display: inline-block;
11 | margin-left: 8px;
12 | margin-right: 8px;
13 | }
14 |
15 | .file-tree-header .item:first-child {
16 | margin-left: 6px;
17 | }
18 |
19 | .file-tree-header .item:hover {
20 | color: #333;
21 | }
22 |
23 | .file-tree-header .item .fa {
24 | padding-right: 5px;
25 | }
26 |
--------------------------------------------------------------------------------
/src/browser/components/files/file-tree-header.jsx:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import React from 'react';
3 | import commonReact from '../../services/common-react';
4 | import './file-tree-header.css';
5 |
6 | /**
7 | * @class FileList
8 | * @description Visual representation of the chrome around a list of files. Can show parent, sorts files by directory/file.
9 | * @extends ReactComponent
10 | * @property props
11 | */
12 | export default React.createClass({
13 | displayName: 'FileTreeHeader',
14 | propTypes: {
15 | onGoToSpecialDirectory: React.PropTypes.func.isRequired
16 | },
17 | render: function () {
18 | const props = this.props,
19 | className = commonReact.getClassNameList(this);
20 |
21 | return (
22 |
23 |
{'Parent'}
24 |
{'Home'}
25 |
{'Working Directory'}
26 |
27 | );
28 | }
29 | });
30 |
--------------------------------------------------------------------------------
/src/browser/components/files/file-tree.css:
--------------------------------------------------------------------------------
1 | .file-tree {
2 | position: relative;
3 | overflow: auto;
4 | height: 100%;
5 | }
6 |
--------------------------------------------------------------------------------
/src/browser/components/forms/button-referenced.css:
--------------------------------------------------------------------------------
1 | .button-referenced {
2 | margin-left: 0;
3 | }
4 |
--------------------------------------------------------------------------------
/src/browser/components/forms/button-referenced.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import React from 'react';
3 | import commonReact from '../../services/common-react';
4 |
5 | export default React.createClass({
6 | displayName: 'ButtonReferenced',
7 | contextTypes: {
8 | text: React.PropTypes.object
9 | },
10 | shouldComponentUpdate: function (nextProps) {
11 | return commonReact.shouldComponentUpdate(this, nextProps);
12 | },
13 | render: function () {
14 | const props = this.props,
15 | text = this.context.text,
16 | className = commonReact.getClassNameList(this),
17 | handleClick = props.clickHandler && _.isFunction(props[props.clickHandler]) && _.partial(props[props.clickHandler], props.value);
18 | let content;
19 |
20 | if (handleClick) {
21 | content = {text[props.label]} ;
22 | } else {
23 | content = {text[props.label]} ;
24 | }
25 |
26 | return {content}
;
27 | }
28 | });
29 |
--------------------------------------------------------------------------------
/src/browser/components/forms/form-list.css:
--------------------------------------------------------------------------------
1 | .form-list {
2 | width: 100%;
3 | }
4 |
5 | .form-item {
6 | margin: 20px;
7 | }
8 |
9 | .form-item:first-child {
10 | margin-top: 10px;
11 | }
12 |
13 | .form-item .form-input {
14 | margin-left: 20px;
15 | }
16 |
17 | /* input group is a input combined with a button */
18 | .input-group {
19 | position: relative;
20 | display: table;
21 | border-collapse: separate;
22 | margin-left: 20px;
23 | }
24 |
25 | .input-group input.form-input {
26 | display: table-cell;
27 | margin-left: 0;
28 | }
29 |
30 | .input-group select.form-input {
31 | display: table-cell;
32 | }
33 |
34 | .input-group .input-group-container {
35 | vertical-align: top;
36 | display: table-cell;
37 | width: 1%;
38 | }
39 |
--------------------------------------------------------------------------------
/src/browser/components/forms/input-checkbox.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import commonReact from '../../services/common-react';
3 |
4 | export default React.createClass({
5 | displayName: 'InputCheckbox',
6 | propTypes: {
7 | onChange: React.PropTypes.func.isRequired,
8 | originalValue: React.PropTypes.bool,
9 | value: React.PropTypes.bool
10 | },
11 | contextTypes: {
12 | text: React.PropTypes.object
13 | },
14 | shouldComponentUpdate: function (nextProps) {
15 | return commonReact.shouldComponentUpdate(this, nextProps);
16 | },
17 | render: function () {
18 | const props = this.props,
19 | text = this.context.text,
20 | className = commonReact.getClassNameList(this);
21 |
22 | return (
23 |
24 | {text[props.label]}
25 |
26 |
27 | );
28 | }
29 | });
30 |
--------------------------------------------------------------------------------
/src/browser/components/forms/input-number.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import commonReact from '../../services/common-react';
3 |
4 | export default React.createClass({
5 | displayName: 'InputNumber',
6 | propTypes: {
7 | onChange: React.PropTypes.func.isRequired,
8 | originalValue: React.PropTypes.number,
9 | value: React.PropTypes.number
10 | },
11 | contextTypes: {
12 | text: React.PropTypes.object
13 | },
14 | shouldComponentUpdate: function (nextProps) {
15 | return commonReact.shouldComponentUpdate(this, nextProps);
16 | },
17 | render: function () {
18 | const props = this.props,
19 | text = this.context.text,
20 | className = commonReact.getClassNameList(this);
21 |
22 | if (props.originalValue !== props.value) {
23 | className.push('number-input--modified');
24 | }
25 |
26 | return (
27 |
28 | {text[props.label]}
29 |
30 |
31 | );
32 | }
33 | });
34 |
--------------------------------------------------------------------------------
/src/browser/components/forms/input-select.css:
--------------------------------------------------------------------------------
1 | .input-select select {
2 | display: table-cell;
3 | height: 30px;
4 | padding-right: 20px;
5 | padding-left: 5px;
6 | }
7 |
--------------------------------------------------------------------------------
/src/browser/components/forms/input-text.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import commonReact from '../../services/common-react';
3 |
4 | export default React.createClass({
5 | displayName: 'TextInput',
6 | propTypes: {
7 | onChange: React.PropTypes.func.isRequired,
8 | originalValue: React.PropTypes.string,
9 | value: React.PropTypes.string
10 | },
11 | contextTypes: {
12 | text: React.PropTypes.object
13 | },
14 | shouldComponentUpdate: function (nextProps) {
15 | return commonReact.shouldComponentUpdate(this, nextProps);
16 | },
17 | render: function () {
18 | const props = this.props,
19 | text = this.context.text,
20 | className = commonReact.getClassNameList(this);
21 |
22 | if (props.originalValue !== props.value) {
23 | className.push('preferences-text--modified');
24 | }
25 |
26 | return (
27 |
28 | {text[props.label]}
29 |
30 |
31 | );
32 | }
33 | });
34 |
--------------------------------------------------------------------------------
/src/browser/components/forms/readme.md:
--------------------------------------------------------------------------------
1 | # Forms
2 |
3 | A FormList contains form items.
4 |
5 | A FormItem has a value. If the value is different than the originalValue, then the item state is modified.
6 |
7 | If a FormItem has errors, then they have FormItemErrors.
8 |
--------------------------------------------------------------------------------
/src/browser/components/forms/rodeo-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/browser/components/forms/rodeo-logo.png
--------------------------------------------------------------------------------
/src/browser/components/gray-info/gray-info-link-list.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import './gray-info.css';
3 | import commonReact from '../../services/common-react';
4 |
5 | export default React.createClass({
6 | displayName: 'GrayInfoLinkList',
7 | shouldComponentUpdate: function () {
8 | return true;
9 | },
10 | render: function () {
11 | const props = this.props,
12 | className = commonReact.getClassNameList(this);
13 |
14 | return {props.children}
;
15 | }
16 | });
17 |
--------------------------------------------------------------------------------
/src/browser/components/gray-info/gray-info-link.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import './gray-info.css';
3 | import commonReact from '../../services/common-react';
4 |
5 | export default React.createClass({
6 | displayName: 'GrayInfoLink',
7 | propTypes: {
8 | icon: React.PropTypes.string,
9 | label: React.PropTypes.string,
10 | onClick: React.PropTypes.func.isRequired,
11 | title: React.PropTypes.string
12 | },
13 | shouldComponentUpdate: function (nextProps) {
14 | return commonReact.shouldComponentUpdate(this, nextProps);
15 | },
16 | render: function () {
17 | const props = this.props,
18 | className = commonReact.getClassNameList(this);
19 | let icon;
20 |
21 | if (props.icon) {
22 | icon = ;
23 | }
24 |
25 | return (
26 |
27 | {icon}
28 | {props.label}
29 |
30 | );
31 | }
32 | });
33 |
--------------------------------------------------------------------------------
/src/browser/components/gray-info/gray-info.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import './gray-info.css';
3 | import commonReact from '../../services/common-react';
4 |
5 | export default React.createClass({
6 | displayName: 'GrayInfo',
7 | shouldComponentUpdate: function (nextProps) {
8 | return commonReact.shouldComponentUpdate(this, nextProps);
9 | },
10 | render: function () {
11 | const props = this.props,
12 | className = commonReact.getClassNameList(this);
13 |
14 | return {props.children}
;
15 | }
16 | });
17 |
--------------------------------------------------------------------------------
/src/browser/components/layout-containers/full-screen.css:
--------------------------------------------------------------------------------
1 | html,
2 | body,
3 | main,
4 | .full-screen {
5 | height: 100%;
6 | }
7 |
8 | .full-screen--row {
9 | display: flex;
10 | flex-direction: row;
11 | }
12 |
13 | .full-screen--row > * {
14 | flex: 1 1;
15 | }
16 |
17 | .splitter_panel {
18 | height: 100%;
19 | }
20 |
--------------------------------------------------------------------------------
/src/browser/components/layout-containers/full-screen.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import commonReact from '../../services/common-react';
3 | import './full-screen.css';
4 |
5 | export default React.createClass({
6 | displayName: 'FullScreen',
7 | propTypes: {
8 | row: React.PropTypes.bool
9 | },
10 | render: function () {
11 | const props = this.props,
12 | className = commonReact.getClassNameList(this);
13 |
14 | if (props.row) {
15 | className.push('full-screen--row');
16 | }
17 |
18 | return {props.children}
;
19 | }
20 | });
21 |
--------------------------------------------------------------------------------
/src/browser/components/manage-connections/connection-config.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import commonReact from '../../services/common-react';
3 | import PostgresqlSettings from './types/postgresql-settings';
4 | // import MysqlSettings from './types/mysql-settings';
5 | // import RedshiftSettings from './types/redshift-settings';
6 | // import SqlserverSettings from './types/sqlserver-settings';
7 |
8 | export default React.createClass({
9 | displayName: 'ConnectionConfig',
10 | propTypes: {
11 | definitions: React.PropTypes.object.isRequired,
12 | list: React.PropTypes.array, // could be nothing
13 | onChange: React.PropTypes.func.isRequired
14 | },
15 | shouldComponentUpdate: function (nextProps) {
16 | return commonReact.shouldComponentUpdate(this, nextProps);
17 | },
18 | render: function () {
19 | const props = this.props,
20 | className = commonReact.getClassNameList(this),
21 | types = {
22 | postgresql: () =>
23 | },
24 | type = props.type || props.definitions.defaultType; // no item selected, so none.
25 |
26 | return {types[type]()}
;
27 | }
28 | });
29 |
--------------------------------------------------------------------------------
/src/browser/components/manage-connections/connection-errors.css:
--------------------------------------------------------------------------------
1 | .connection-errors {
2 | background-color: #ff8280;
3 | border-radius: 5px;
4 | padding: 5px 10px;
5 | margin: 10px;
6 | }
7 |
--------------------------------------------------------------------------------
/src/browser/components/manage-connections/connection-errors.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import React from 'react';
3 | import commonReact from '../../services/common-react';
4 | import './connection-errors.css';
5 |
6 | function filterErrorMessages(error) {
7 | if (error.message) {
8 | if (_.includes(error.message, 'ECONNREFUSED')) {
9 | return 'Connection refused';
10 | } else if (_.includes(error.message, 'getaddrinfo ENOTFOUND')) {
11 | return 'Address not found';
12 | } else if (/role ".+" does not exist/.test(error.message)) {
13 | return 'User not found';
14 | } else if (/database ".+" does not exist/.test(error.message)) {
15 | return 'Database not found';
16 | } else {
17 | return error.message;
18 | }
19 | } else {
20 | return error.toString();
21 | }
22 | }
23 |
24 | export default React.createClass({
25 | displayName: 'ConnectionErrors',
26 | propTypes: {
27 | },
28 | shouldComponentUpdate: function (nextProps) {
29 | return commonReact.shouldComponentUpdate(this, nextProps);
30 | },
31 | render: function () {
32 | const props = this.props,
33 | className = commonReact.getClassNameList(this);
34 |
35 | return (
36 |
37 | {props.errors.map(error =>
{filterErrorMessages(error)}
)}
38 |
39 | );
40 | }
41 | });
42 |
--------------------------------------------------------------------------------
/src/browser/components/notifications/chat-alt-flat.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
16 |
17 |
18 |
19 |
20 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/browser/components/notifications/download-cloud-flat.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/browser/components/notifications/info-notification.css:
--------------------------------------------------------------------------------
1 | .info-notification {
2 | margin: 7px;
3 | padding: 9px;
4 | display: block;
5 | position: relative;
6 | min-width: 250px;
7 | max-width: 400px;
8 | max-height: 90%;
9 | z-index: 11;
10 | background-color: white;
11 | box-shadow: 4px 4px 16px rgba(0, 0, 0, 0.4);
12 | transition: all 0.8s;
13 | opacity: 0;
14 | border-radius: 5px;
15 | min-height: 50px;
16 | }
17 |
18 | .info-notification .icon-container {
19 | display: block;
20 | text-align: center;
21 | }
22 | .info-notification .icon-container img {
23 | width: 80px;
24 | }
25 |
26 | .info-notification p:first-child {
27 | margin-top: 10px;
28 | }
29 |
30 | .info-notification p:last-child {
31 | margin-bottom: 0;
32 | }
33 |
34 | .info-notification .info-notification-content {
35 | margin-left: 20px;
36 | margin-right: 60px;
37 | min-height: 27px;
38 | }
39 |
40 | .info-notification.notification-show {
41 | opacity: 1;
42 | }
43 |
44 | .info-notification button {
45 | position: absolute;
46 | bottom: 0;
47 | right: 0;
48 | margin: 12px;
49 | }
50 |
--------------------------------------------------------------------------------
/src/browser/components/notifications/info-notification.jsx:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import React from 'react';
3 | import ReactDOM from 'react-dom';
4 | import './info-notification.css';
5 | import negativeMessage from './chat-alt-flat.svg';
6 |
7 | const showClass = 'notification-show';
8 |
9 | /**
10 | * @class InfoNotification
11 | * @extends ReactComponent
12 | * @property props
13 | */
14 | export default React.createClass({
15 | displayName: 'InfoNotification',
16 | propTypes: {
17 | id: React.PropTypes.string.isRequired,
18 | onOK: React.PropTypes.func
19 | },
20 | componentDidMount: function () {
21 | const el = ReactDOM.findDOMNode(this);
22 |
23 | _.defer(() => el.classList.add(showClass));
24 | },
25 | render: function () {
26 | const props = this.props;
27 |
28 | return (
29 |
30 |
31 | {props.children}
32 | {'OK'}
33 |
34 | );
35 | }
36 | });
37 |
--------------------------------------------------------------------------------
/src/browser/components/notifications/notifications-container.css:
--------------------------------------------------------------------------------
1 | .notifications-container {
2 | position: absolute;
3 | display: block;
4 | top: 0;
5 | right: 0;
6 | z-index: 1000; /* higher than split-panes */
7 | }
8 |
--------------------------------------------------------------------------------
/src/browser/components/notifications/notifications.actions.js:
--------------------------------------------------------------------------------
1 | export function add(contentType, title, content) {
2 | return {type: 'ADD_NOTIFICATION', contentType, title, content};
3 | }
4 |
5 | export function close(notification) {
6 | return {type: 'CLOSE_NOTIFICATION', notification};
7 | }
8 |
9 | export function closeAll() {
10 | return {type: 'CLOSE_ALL_NOTIFICATIONS'};
11 | }
12 |
13 | export default {
14 | add,
15 | close,
16 | closeAll
17 | };
18 |
--------------------------------------------------------------------------------
/src/browser/components/notifications/update-available-notification.css:
--------------------------------------------------------------------------------
1 | .update-available-notification {
2 | margin: 7px;
3 | padding: 9px;
4 | display: block;
5 | position: relative;
6 | min-width: 250px;
7 | max-width: 400px;
8 | max-height: 90%;
9 | z-index: 11;
10 | background-color: white;
11 | box-shadow: 4px 4px 16px rgba(0, 0, 0, 0.4);
12 | transition: all 0.8s;
13 | opacity: 0;
14 | border-radius: 5px;
15 | min-height: 50px;
16 | text-align: center;
17 | }
18 |
19 | .update-available-notification .icon-container {
20 | display: block;
21 | }
22 |
23 | .update-available-notification .icon-container img {
24 | width: 80px;
25 | }
26 |
27 | .update-available-notification .info-notification-content {
28 | margin-left: 20px;
29 | margin-right: 20px;
30 | min-height: 27px;
31 | margin-top: 26px;
32 | }
33 |
34 | .update-available-notification.notification-show {
35 | opacity: 1;
36 | }
37 |
38 | .update-available-notification > footer {
39 | display: flex;
40 | justify-content: space-around;
41 | }
42 |
43 | .info-notification button {
44 | margin: 12px;
45 | }
46 |
--------------------------------------------------------------------------------
/src/browser/components/packages/package-search-list.css:
--------------------------------------------------------------------------------
1 | .package-search-list {
2 | padding: 10px;
3 | overflow-y: auto;
4 | height: 100%;
5 | }
6 |
7 | .package-search-list > header {
8 | margin-left: auto;
9 | margin-right: auto;
10 | width: 80%;
11 | display: table;
12 | }
13 |
14 | .package-search-list > header input {
15 | width: 100%;
16 | display: table-cell;
17 | }
18 |
19 | .package-search-list .suggestion {
20 | display: flex;
21 | align-items: center;
22 | justify-content: center;
23 | color: #cbcbcb;
24 | }
25 |
26 | .package-search-list .button-shift {
27 | display: table-cell;
28 | width: 1%;
29 | white-space: nowrap;
30 | vertical-align: middle;
31 | position: relative;
32 | font-size: 0;
33 | padding-left: 10px;
34 | }
35 |
--------------------------------------------------------------------------------
/src/browser/components/packages/packages-list.css:
--------------------------------------------------------------------------------
1 | .packages-list .btn {
2 | margin: 10px;
3 | }
4 |
5 | .packages-list .package-actions {
6 | display: flex;
7 | align-items: center;
8 | justify-content: center;
9 | }
10 |
11 | .packages-list button .fa {
12 | margin-right: 10px;
13 | }
14 |
--------------------------------------------------------------------------------
/src/browser/components/plot-preview/foreground-plot.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import UnsafeHTML from '../unsafe-html.js';
3 | import './plot-preview.css';
4 | import commonReact from '../../services/common-react';
5 |
6 | /**
7 | * @class ForegroundPlot
8 | * @extends ReactComponent
9 | * @property props
10 | */
11 | export default React.createClass({
12 | displayName: 'ForegroundPlot',
13 | propTypes: {
14 | data: React.PropTypes.object.isRequired,
15 | id: React.PropTypes.string.isRequired
16 | },
17 | shouldComponentUpdate(nextProps) {
18 | return commonReact.shouldComponentUpdate(this, nextProps);
19 | },
20 | render: function () {
21 | const props = this.props,
22 | data = props.data;
23 | let plotComponent;
24 |
25 | if (data['image/png']) {
26 | plotComponent = ;
27 | } else if (data['image/svg']) {
28 | plotComponent = ;
29 | } else if (data['text/html']) {
30 | let frameId = 'frame-' + props.id;
31 |
32 | plotComponent = ;
33 | } else {
34 | plotComponent = {'Plot must be png, svg, html or javascript.'}
;
35 | }
36 |
37 | return plotComponent;
38 | }
39 | });
40 |
--------------------------------------------------------------------------------
/src/browser/components/prompt/prompt.css:
--------------------------------------------------------------------------------
1 | .prompt {
2 | color: #999;
3 | display: block;
4 | white-space: pre-wrap;
5 | overflow: auto;
6 | background-color: #fff;
7 | font-family: monospace;
8 | font-size: 12px;
9 | position: relative;
10 | outline: none;
11 | }
12 |
13 | .prompt .prompt-line {
14 | position: relative;
15 | }
16 |
17 | .prompt--prompt,
18 | .prompt--continue {
19 | -webkit-user-select: none;
20 | -moz-user-select: none;
21 | -ms-user-select: none;
22 | -o-user-select: none;
23 | user-select: none;
24 | }
25 |
26 | .prompt__cursor {
27 | background-color: #ccc;
28 | color: transparent;
29 | display: inline;
30 | position: absolute;
31 | z-index: 0;
32 | }
33 |
34 | .prompt:focus {
35 | color: #333;
36 | outline: none;
37 | }
38 |
39 | .prompt:focus .prompt__cursor {
40 | background-color: #111;
41 | }
42 |
43 | .prompt__cursor--thinBlinking {
44 | width: 2px;
45 | }
46 |
47 | .prompt:focus .prompt__cursor--thinBlinking {
48 | animation-name: prompt__cursor__animation;
49 | animation-duration: 1s;
50 | animation-iteration-count: infinite;
51 | animation-timing-function: steps(1, start);
52 | }
53 |
54 | @keyframes prompt__cursor__animation {
55 | 0% { opacity: 1; }
56 | 50% { opacity: 0; }
57 | }
58 |
--------------------------------------------------------------------------------
/src/browser/components/register-rodeo/areas-of-interest.yml:
--------------------------------------------------------------------------------
1 | label: Areas of Interest
2 | items:
3 | - label: Machine Learning
4 | name: interest.machine-learning
5 | - label: Linear Programming
6 | name: interest.linear-programming
7 | - label: Optimization
8 | name: interest.optimization
9 | - label: Neural Networks
10 | name: interest.neural-networks
11 | - label: Risk/Financial Modeling
12 | name: interest.risk-and-finiancial-modeling
13 | - label: Simulation
14 | name: interest.simulation
15 | - label: Cryptozoology
16 | name: interest.cryptozoology
17 | - label: Naval History
18 | name: interest.naval-history
19 | - label: Urban Exploring
20 | name: interest.urban-exploring
21 |
22 |
--------------------------------------------------------------------------------
/src/browser/components/register-rodeo/explanation.md:
--------------------------------------------------------------------------------
1 | Let us recommend relevant blog posts, tutorials and other content!
2 |
3 | By letting us know what is relevant to you, we can
4 | create more content of that kind, and it will help prioritize new features for Rodeo.
5 |
--------------------------------------------------------------------------------
/src/browser/components/search-text-box/search-text-box.css:
--------------------------------------------------------------------------------
1 | .search-text-box {
2 | border-radius: 8px;
3 | box-shadow: 1px 2px 5px 1px #aaa;
4 | white-space: nowrap;
5 | display: inline-block;
6 | margin: 0;
7 | padding: 0;
8 | height: 22px;
9 | }
10 |
11 | .search-text-box .search-text-box-icon {
12 | border-top-left-radius: 10px;
13 | border-bottom-left-radius: 10px;
14 | border: 0;
15 | display: inline-block;
16 | margin: 0;
17 | line-height: 16px;
18 | padding: 3px;
19 | padding-left: 6px;
20 | }
21 |
22 | .search-text-box input {
23 | border-top-right-radius: 10px;
24 | border-bottom-right-radius: 10px;
25 | border: 0;
26 | width: 30px;
27 | transition: width 0.4s;
28 | display: inline-block;
29 | margin: 0;
30 | line-height: 16px;
31 | padding: 3px;
32 | padding-right: 6px;
33 | vertical-align: top;
34 | }
35 |
36 | .search-text-box input:hover {
37 | width: 60px;
38 | }
39 |
40 | .search-text-box input:focus {
41 | width: 160px;
42 | }
43 |
--------------------------------------------------------------------------------
/src/browser/components/search-text-box/search-text-box.jsx:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import React from 'react';
3 | import './search-text-box.css';
4 | import commonReact from '../../services/common-react';
5 |
6 | /**
7 | * @class FilterTextBox
8 | * @extends ReactComponent
9 | * @property props
10 | */
11 | export default React.createClass({
12 | displayName: 'FilterTextBox',
13 | propTypes: {
14 | className: React.PropTypes.string,
15 | onChange: React.PropTypes.func,
16 | placeholder: React.PropTypes.string
17 | },
18 | shouldComponentUpdate(nextProps) {
19 | return commonReact.shouldComponentUpdate(this, nextProps);
20 | },
21 | handleFilterChange: _.debounce(function () {
22 | const value = this.refs.search.value;
23 |
24 | this.props.onChange(value);
25 | }, 300),
26 | render: function () {
27 | const className = ['search-text-box', this.props.className].join(' ');
28 |
29 | return (
30 |
40 | );
41 | }
42 | });
43 |
--------------------------------------------------------------------------------
/src/browser/components/setup/fake-terminal.css:
--------------------------------------------------------------------------------
1 | .fake-terminal {
2 | border: solid 1px #888;
3 | background-color: #FFF;
4 | display: block;
5 | white-space: pre-wrap;
6 | font-family: "Inconsolata","Inconsolata-dz", Monaco, Menlo, Consolas, "Courier New", monospace;
7 | font-size: 14px;
8 | color: #222;
9 | text-align: left;
10 | padding: 5px;
11 | overflow-x: visible;
12 | overflow-y: auto;
13 | box-shadow: inset 2px 2px 50px #acc, 2px 2px 10px #aaa;
14 | transition: all 0.6s;
15 | }
16 |
17 | .fake-terminal .prompt {
18 | padding-right: 10px;
19 | }
20 |
21 | .fake-terminal .errors {
22 | border-radius: 5px;
23 | margin-top: 5px;
24 | padding: 5px 10px;
25 | }
26 |
27 | .fake-terminal .errors .fa {
28 | margin-right: 10px;
29 | }
30 |
31 | .fake-terminal .stderr {
32 | background-color: transparent;
33 | color: #0062ff;
34 | }
35 |
36 | .fake-terminal .exit-code {
37 | background: linear-gradient(0deg, rgba(255, 130, 128, 0.5), rgba(255, 130, 128, 0.3) 30%, rgba(255, 255, 255, 0));
38 | /* border-radius: 5px; */
39 | padding: 5px 10px;
40 | margin: 10px -5px -5px;
41 | }
42 |
--------------------------------------------------------------------------------
/src/browser/components/setup/logo-rodeo-grey-text.sketch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/browser/components/setup/logo-rodeo-grey-text.sketch
--------------------------------------------------------------------------------
/src/browser/components/setup/setup-article-preview.css:
--------------------------------------------------------------------------------
1 | .setup-article-preview {
2 | display: flex;
3 | align-items: center;
4 | justify-content: space-around;
5 | flex-wrap: wrap;
6 | text-align: left;
7 | width: 80%;
8 | margin: 20px auto;
9 | font-size: 14px;
10 | border: 1px solid #eee;
11 | padding: 20px 5px;
12 | box-shadow: 1px 5px 6px #aaa;
13 | cursor: pointer;
14 | }
15 |
16 | .setup-article-preview:hover {
17 | border: 1px solid #ccc;
18 | color: #333;
19 | }
20 |
21 | .setup-article-preview h2 {
22 | margin-top: 0;
23 | font-size: 16px;
24 | }
25 |
26 | .setup-article-preview a {
27 | color: #666;
28 | text-decoration: none;
29 | }
30 |
31 | .setup-article-preview a:hover {
32 | color: #666;
33 | text-decoration: none;
34 | }
35 |
36 | .setup-article-preview .setup-article {
37 | width: 600px;
38 | min-height: 150px;
39 | overflow: hidden;
40 | }
41 |
42 | .setup-article .setup-article-image {
43 | float: left;
44 | width: 40%;
45 | margin: 0 10px 20px;
46 | min-height: 120px;
47 | background-size: cover;
48 | background-position: center;
49 | }
50 |
--------------------------------------------------------------------------------
/src/browser/components/setup/setup-article-preview.jsx:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import React from 'react';
3 | import Marked from '../marked';
4 | import './setup-article-preview.css';
5 | import commonReact from '../../services/common-react';
6 |
7 | export default React.createClass({
8 | displayName: 'SetupArticlePreview',
9 | propTypes: {
10 | articles: React.PropTypes.array.isRequired,
11 | onOpenExternal: React.PropTypes.func.isRequired
12 | },
13 | shouldComponentUpdate: function (nextProps) {
14 | return commonReact.shouldComponentUpdate(this, nextProps);
15 | },
16 | render: function () {
17 | const props = this.props,
18 | className = commonReact.getClassNameList(this);
19 |
20 | return (
21 |
37 | );
38 | }
39 | });
40 |
--------------------------------------------------------------------------------
/src/browser/components/setup/setup-install-package.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import commonReact from '../../services/common-react';
3 | import SetupInstallResultButtons from './setup-install-result-buttons.jsx';
4 |
5 | export default React.createClass({
6 | displayName: 'SetupInstallPackage',
7 | propTypes: {
8 | explanationLabel: React.PropTypes.string.isRequired,
9 | onCancel: React.PropTypes.func.isRequired,
10 | onPackageInstall: React.PropTypes.func.isRequired,
11 | packageName: React.PropTypes.string.isRequired,
12 | terminal: React.PropTypes.object.isRequired
13 | },
14 | componentDidMount: function () {
15 | const props = this.props;
16 |
17 | props.onPackageInstall(props.packageName);
18 | },
19 | shouldComponentUpdate: function (nextProps) {
20 | return commonReact.shouldComponentUpdate(this, nextProps);
21 | },
22 | render: function () {
23 | const props = this.props,
24 | className = commonReact.getClassNameList(this);
25 |
26 | return (
27 |
32 | );
33 | }
34 | });
35 |
--------------------------------------------------------------------------------
/src/browser/components/setup/setup-manual-command.css:
--------------------------------------------------------------------------------
1 | .setup-manual-command .input-python-cmd input {
2 | padding-left: 5px;
3 | }
4 |
--------------------------------------------------------------------------------
/src/browser/components/setup/setup-ready.jsx:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import React from 'react';
3 | import commonReact from '../../services/common-react';
4 |
5 | export default React.createClass({
6 | displayName: 'SetupReady',
7 | propTypes: {
8 | className: React.PropTypes.string,
9 | onCancel: React.PropTypes.func.isRequired,
10 | onFinish: React.PropTypes.func.isRequired
11 | },
12 | contextTypes: {
13 | text: React.PropTypes.object.isRequired
14 | },
15 | shouldComponentUpdate: function (nextProps) {
16 | return commonReact.shouldComponentUpdate(this, nextProps);
17 | },
18 | render: function () {
19 | const props = this.props,
20 | text = this.context.text,
21 | className = commonReact.getClassNameList(this);
22 |
23 | return (
24 |
25 |
26 | {text.readyToRodeo}
27 |
28 |
29 | );
30 | }
31 | });
32 |
--------------------------------------------------------------------------------
/src/browser/components/setup/setup-skip-startup.css:
--------------------------------------------------------------------------------
1 | .setup-skip-startup {
2 | display: inline-block;
3 | position: absolute;
4 | right: 20px;
5 | bottom: 20px;
6 | opacity: 0;
7 | transition: opacity 0.5s;
8 | }
9 |
10 | .setup-skip-startup--visible {
11 | opacity: 0.4;
12 | }
13 |
14 | .setup-skip-startup--visible:hover {
15 | opacity: 1;
16 | }
17 |
--------------------------------------------------------------------------------
/src/browser/components/setup/setup-skip-startup.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import commonReact from '../../services/common-react';
3 | import './setup-skip-startup.css';
4 |
5 | export default React.createClass({
6 | displayName: 'SetupSkipStartup',
7 | propTypes: {
8 | onSkipStartup: React.PropTypes.func
9 | },
10 | contextTypes: {
11 | text: React.PropTypes.object.isRequired
12 | },
13 | shouldComponentUpdate: function (nextProps) {
14 | return commonReact.shouldComponentUpdate(this, nextProps);
15 | },
16 | render: function () {
17 | const props = this.props,
18 | text = this.context.text,
19 | className = ['setup-skip-startup'];
20 |
21 | if (props.isMainWindowReady) {
22 | className.push('setup-skip-startup--visible');
23 | }
24 |
25 | return (
26 |
27 | {text.skip}
28 |
29 | );
30 | }
31 | });
32 |
--------------------------------------------------------------------------------
/src/browser/components/sidebar/logo-scienceops.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/browser/components/sidebar/logo-scienceops.png
--------------------------------------------------------------------------------
/src/browser/components/sidebar/logo-yhat.sketch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/browser/components/sidebar/logo-yhat.sketch
--------------------------------------------------------------------------------
/src/browser/components/sidebar/logo-yhat.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | logo-yhat
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 | ŷ
11 |
12 |
13 | hat
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/browser/components/sidebar/sidebar-item.jsx:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import React from 'react';
3 | import commonReact from '../../services/common-react';
4 |
5 | /**
6 | * @class SidebarItem
7 | * @extends ReactComponent
8 | * @property props
9 | */
10 | export default React.createClass({
11 | displayName: 'SidebarItem',
12 | propTypes: {
13 | icon: React.PropTypes.string,
14 | id: React.PropTypes.string,
15 | label: React.PropTypes.string,
16 | onClick: React.PropTypes.func
17 | },
18 | shouldComponentUpdate(nextProps) {
19 | return commonReact.shouldComponentUpdate(this, nextProps);
20 | },
21 | render: function () {
22 | const props = this.props,
23 | className = commonReact.getClassNameList(this);
24 |
25 | return (
26 | {props.children}
27 | );
28 | }
29 | });
30 |
--------------------------------------------------------------------------------
/src/browser/components/sidebar/sidebar.actions.js:
--------------------------------------------------------------------------------
1 | import track from '../../services/track';
2 |
3 | export function showURL(url) {
4 | track({category: 'sidebar', action: 'show_url', label: url});
5 | return {type: 'SHOW_URL_IN_SIDEBAR', url};
6 | }
7 |
8 | export function openURL(url) {
9 | track({category: 'sidebar', action: 'open_url', label: url});
10 | require('electron').shell.openExternal(url);
11 | return {type: 'OPEN_EXTERNAL_URL', url};
12 | }
13 |
14 | export function hide() {
15 | track({category: 'sidebar', action: 'hide'});
16 | return {type: 'HIDE_URL_IN_SIDEBAR'};
17 | }
18 |
19 | export default {
20 | showURL,
21 | openURL,
22 | hide
23 | };
24 |
--------------------------------------------------------------------------------
/src/browser/components/sidebar/sidebar.css:
--------------------------------------------------------------------------------
1 | .sidebar {
2 | height: 100%;
3 | flex: 0 0 52px;
4 | font-size: 10px;
5 | }
6 |
7 | .sidebar-container {
8 | position: relative;
9 | display: flex;
10 | flex-direction: column;
11 | justify-content: flex-end;
12 | align-items: stretch;
13 | height: 100%;
14 | background-color: #337ab7;
15 | }
16 |
17 | .sidebar-top {
18 | flex: 1 0;
19 | display: flex;
20 | flex-direction: column;
21 | justify-content: flex-start;
22 | align-items: stretch;
23 | }
24 |
25 | .sidebar-item {
26 | cursor: pointer;
27 | flex: 0 0 60px;
28 | transition: all 0.4s;
29 | color: #efefef;
30 | padding: 4px;
31 | text-align: center;
32 | }
33 |
34 | .sidebar-top .sidebar-item {
35 | /* things in the top have bigger names but better images */
36 | font-size: 8px;
37 | }
38 |
39 | .sidebar-item span:first-child {
40 | display: block;
41 | font-size: 28px;
42 | line-height: 28px;
43 | padding-top: 3px;
44 | }
45 |
46 | .sidebar-item img {
47 | max-width: 40px;
48 | max-height: 40px;
49 | }
50 |
51 | .sidebar-item:last-child {
52 | margin-bottom: 15px;
53 | }
54 |
55 | .sidebar-item:hover {
56 | cursor: pointer;
57 | background-color: #8DC8FB;
58 | }
59 |
60 | .sidebar-item:active {
61 | cursor: pointer;
62 | background-color: #D1EAFF;
63 | }
64 |
--------------------------------------------------------------------------------
/src/browser/components/sidebar/sidebar.reducer.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * Modals work on a stack. A modal that triggers another modal is stacking on top, such that cancelling the top modal
4 | * returns to the first.
5 | * @module
6 | */
7 |
8 | import _ from 'lodash';
9 | import mapReducers from '../../services/map-reducers';
10 |
11 | const initialState = {
12 | isExpanded: false
13 | };
14 |
15 | /**
16 | * @param {Array} state
17 | * @param {object} action
18 | * @returns {Array}
19 | */
20 | function showURL(state, action) {
21 | state = _.clone(state);
22 |
23 | if (!state.isExpanded) {
24 | state = _.clone(state);
25 | state.isExpanded = true;
26 | state.url = action.url;
27 | } else if (state.isExpanded && state.url !== action.url) {
28 | state = _.clone(state);
29 | state.url = action.url;
30 | } else if (state.isExpanded && state.url === action.url) {
31 | // close like a toggle
32 | state = _.clone(state);
33 | state.isExpanded = false;
34 | }
35 |
36 | return state;
37 | }
38 |
39 | /**
40 | * @param {Array} state
41 | * @returns {Array}
42 | */
43 | function hide(state) {
44 | state = _.clone(state);
45 | state.isExpanded = false;
46 |
47 | return state;
48 | }
49 |
50 | export default mapReducers({
51 | SHOW_URL_IN_SIDEBAR: showURL,
52 | HIDE_URL_IN_SIDEBAR: hide
53 | }, initialState);
54 |
--------------------------------------------------------------------------------
/src/browser/components/sidebar/slideout-dialog.css:
--------------------------------------------------------------------------------
1 | .slideout-dialog {
2 | position: absolute;
3 | transition: all 0.4s;
4 | background-color: #337ab7;
5 | }
6 |
7 | .slideout-dialog iframe {
8 | width: 100%;
9 | height: 100%;
10 | padding: 10px 0 10px 10px;
11 | }
12 |
13 | .slideout-dialog.slideout-dialog-show {
14 | width: 500px;
15 | height: 100%;
16 | z-index: 9000;
17 | right: 0;
18 | margin-right: 52px;
19 | overflow: hidden;
20 | }
21 |
--------------------------------------------------------------------------------
/src/browser/components/sidebar/slideout-dialog.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import './slideout-dialog.css';
3 | import commonReact from '../../services/common-react';
4 |
5 | const showClass = 'slideout-dialog-show';
6 |
7 | /**
8 | * @class SlideoutDialog
9 | * @extends ReactComponent
10 | * @property props
11 | */
12 | export default React.createClass({
13 | displayName: 'SlideoutDialog',
14 | propTypes: {
15 | isExpanded: React.PropTypes.bool,
16 | url: React.PropTypes.string
17 | },
18 | shouldComponentUpdate(nextProps) {
19 | return commonReact.shouldComponentUpdate(this, nextProps);
20 | },
21 | render: function () {
22 | const props = this.props,
23 | className = commonReact.getClassNameList(this);
24 |
25 | if (props.isExpanded) {
26 | className.push(showClass);
27 | }
28 |
29 | return (
30 |
31 |
32 |
33 | );
34 | }
35 | });
36 |
--------------------------------------------------------------------------------
/src/browser/components/tabbed-form-list-dialog/tabbed-form-list-dialog-tab.css:
--------------------------------------------------------------------------------
1 | .tabbed-form-list-dialog-tab {
2 | cursor: pointer;
3 | padding: 10px 15px;
4 | }
5 |
6 | .tabbed-form-list-dialog-tab:hover {
7 | background-color: #e1e1e1;
8 | }
9 |
10 | .tabbed-form-list-dialog-tab--disabled {
11 | background-color: inherit;
12 | color: grey;
13 | cursor: default;
14 | }
15 |
16 | .tabbed-form-list-dialog-tab--disabled:hover {
17 | background-color: inherit;
18 | }
19 |
20 | .tabbed-form-list-dialog-tab--active {
21 | background-color: #dff0ff;
22 | }
23 |
--------------------------------------------------------------------------------
/src/browser/components/tabbed-form-list-dialog/tabbed-form-list-dialog-tab.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import commonReact from '../../services/common-react';
3 | import './tabbed-form-list-dialog-tab.css';
4 |
5 | export default React.createClass({
6 | displayName: 'TabbedFormListDialogTab',
7 | propTypes: {
8 | active: React.PropTypes.bool,
9 | disabled: React.PropTypes.bool,
10 | id: React.PropTypes.string,
11 | label: React.PropTypes.string.isRequired,
12 | onClick: React.PropTypes.func
13 | },
14 | contextTypes: {
15 | text: React.PropTypes.object.isRequired
16 | },
17 | shouldComponentUpdate: function (nextProps) {
18 | return commonReact.shouldComponentUpdate(this, nextProps);
19 | },
20 | render: function () {
21 | const props = this.props,
22 | text = this.context.text,
23 | className = commonReact.getClassNameList(this);
24 |
25 | if (props.active) {
26 | className.push('tabbed-form-list-dialog--active');
27 | }
28 |
29 | if (props.disabled) {
30 | className.push('tabbed-form-list-dialog--disabled');
31 | }
32 |
33 | return {text[props.label]}
;
34 | }
35 | });
36 |
--------------------------------------------------------------------------------
/src/browser/components/tabbed-form-list-dialog/tabbed-form-list-dialog.css:
--------------------------------------------------------------------------------
1 | .tabbed-form-list-dialog {
2 | position: relative;
3 | min-height: 400px;
4 | height: 100%;
5 | }
6 |
7 | .tabbed-form-list-dialog > footer {
8 | bottom: 0;
9 | right: 0;
10 | padding: 7px 20px;
11 | height: 50px;
12 | text-align: right;
13 | position: relative;
14 | }
15 |
16 | .tabbed-form-list-dialog__content {
17 | position: relative;
18 | display: flex;
19 | flex-direction: row;
20 | align-content: stretch;
21 | align-items: stretch;
22 | height: calc(100% - 50px);
23 | }
24 |
--------------------------------------------------------------------------------
/src/browser/components/tabs/closeable.css:
--------------------------------------------------------------------------------
1 | .closeable {
2 | margin-left: 6px;
3 | cursor: pointer;
4 | color: #cccccc;
5 | font-weight: 400;
6 | transition: all 0.4s;
7 |
8 | -webkit-touch-callout: none; /* iOS Safari */
9 | -webkit-user-select: none; /* Chrome/Safari/Opera */
10 | -moz-user-select: none; /* Firefox */
11 | -ms-user-select: none; /* Internet Explorer/Edge */
12 | user-select: none; /* Non-prefixed version, currently
13 | not supported by any browser */
14 | }
15 |
16 | .closeable:hover {
17 | color: #cc4736;
18 | font-weight: 700;
19 | }
20 |
--------------------------------------------------------------------------------
/src/browser/components/tabs/closeable.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import commonReact from '../../services/common-react';
3 | import './closeable.css';
4 |
5 | const closeTabClass = 'tabbed-pane-close';
6 |
7 | export default React.createClass({
8 | displayName: 'Closeable',
9 | propTypes: {
10 | className: React.PropTypes.string,
11 | onClick: React.PropTypes.func.isRequired
12 | },
13 | shouldComponentUpdate(nextProps) {
14 | return commonReact.shouldComponentUpdate(this, nextProps);
15 | },
16 | render: function () {
17 | const props = this.props,
18 | className = commonReact.getClassNameList(this).concat(['fa', 'fa-times', closeTabClass]);
19 |
20 | return (
21 |
25 | );
26 | }
27 | });
28 |
--------------------------------------------------------------------------------
/src/browser/components/tabs/tab-add.css:
--------------------------------------------------------------------------------
1 | .tab-add {
2 | padding: 6px 8px 0;
3 | }
4 |
--------------------------------------------------------------------------------
/src/browser/components/tabs/tab-add.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import commonReact from '../../services/common-react';
3 | import './tab-add.css';
4 |
5 | export default React.createClass({
6 | displayName: 'TabAdd',
7 | propTypes: {
8 | onClick: React.PropTypes.func.isRequired
9 | },
10 | shouldComponentUpdate() {
11 | return false;
12 | },
13 | render: function () {
14 | const props = this.props,
15 | className = commonReact.getClassNameList(this);
16 |
17 |
18 | return
19 |
20 | ;
21 | }
22 | });
23 |
--------------------------------------------------------------------------------
/src/browser/components/tabs/tab-button.css:
--------------------------------------------------------------------------------
1 | .tab-button button {
2 | white-space: nowrap;
3 | display: inline-block;
4 | height: 29px;
5 | background-color: white;
6 | padding: 1px 10px;
7 | border-style: hidden;
8 | color: #888;
9 | cursor: pointer;
10 | transition: all 0.2s;
11 | }
12 |
13 | .tab-button button:hover {
14 | color: #222
15 | }
16 |
17 | .tab-button button:active {
18 | color: #aaa
19 | }
20 |
21 | .tab-button .fa {
22 | margin-right: 5px;
23 | }
24 |
--------------------------------------------------------------------------------
/src/browser/components/tabs/tab-button.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import React from 'react';
3 | import commonReact from '../../services/common-react';
4 | import './tab-button.css';
5 |
6 | export default React.createClass({
7 | displayName: 'TabButton',
8 | propTypes: {
9 | icon: React.PropTypes.string.isRequired,
10 | label: React.PropTypes.string.isRequired,
11 | onClick: React.PropTypes.func, // not required when disabled
12 | title: React.PropTypes.oneOfType([React.PropTypes.object, React.PropTypes.string])
13 | },
14 | shouldComponentUpdate(nextProps) {
15 | return commonReact.shouldComponentUpdate(this, nextProps);
16 | },
17 | render: function () {
18 | const props = this.props,
19 | className = commonReact.getClassNameList(this),
20 | iconClassName = ['fa', 'fa-' + props.icon];
21 | let title;
22 |
23 | if (props.title) {
24 | if (_.isObject(props.title) && props.title !== null) {
25 | title = props.title[process.platform] || props.title.default;
26 | } else if (_.isString(props.title)) {
27 | title = props.title;
28 | }
29 | }
30 |
31 | return (
32 |
33 |
34 |
35 | {props.label}
36 |
37 |
38 | );
39 | }
40 | });
41 |
--------------------------------------------------------------------------------
/src/browser/components/tabs/tab-content-list.css:
--------------------------------------------------------------------------------
1 | .tab-content-list {
2 | flex: 1 1;
3 | overflow: hidden; /* allow individual components decide if they scroll / take the full space */
4 | }
5 |
6 |
--------------------------------------------------------------------------------
/src/browser/components/tabs/tab-item.css:
--------------------------------------------------------------------------------
1 | .tab-item {
2 | height: 24px;
3 | text-overflow: ellipsis;
4 | white-space: nowrap;
5 | min-width: 50px;
6 | padding: 6px 8px 0;
7 | border-bottom: 1px solid #dddddd;
8 | box-shadow: inset -1px -1px 2px #fff;
9 | cursor: pointer;
10 | transition: all 0.2s;
11 | position: relative;
12 | }
13 |
14 | .tab-item .tab-label {
15 | transition: all 0.2s;
16 | color: #888;
17 | }
18 |
19 | .tab-item.active .tab-label {
20 | transform: translate(0, -2px);
21 | color: #222;
22 | }
23 |
24 | .tab-item .lift {
25 | position: absolute;
26 | bottom: 0;
27 | left: 0;
28 | height: 0;
29 | width: 100%;
30 | transition: height 0.2s;
31 | background-color: #337ab7;
32 | }
33 |
34 | .tab-item.active .lift {
35 | height: 2px;
36 | }
37 |
38 | .tab-item,
39 | .tab-item * {
40 | -webkit-touch-callout: none; /* iOS Safari */
41 | -webkit-user-select: none; /* Chrome/Safari/Opera */
42 | -moz-user-select: none; /* Firefox */
43 | -ms-user-select: none; /* Internet Explorer/Edge */
44 | user-select: none; /* Non-prefixed version, currently
45 | not supported by any browser */
46 | }
47 |
--------------------------------------------------------------------------------
/src/browser/components/tabs/tab-list.css:
--------------------------------------------------------------------------------
1 | ul.tab-list {
2 | list-style: none;
3 | margin: 0;
4 | padding: 0;
5 | position: relative;
6 | flex: 0 0;
7 | border-bottom: 1px solid #dddddd;
8 | }
9 |
10 | ul.tab-list > li {
11 | display: inline-block;
12 | position: relative;
13 | min-height: 30px;
14 | vertical-align: top;
15 | }
16 |
--------------------------------------------------------------------------------
/src/browser/components/tabs/tab-list.test.js:
--------------------------------------------------------------------------------
1 | /* globals describe, it, expect, jest */
2 |
3 | import React from 'react';
4 | import ReactDOM from 'react-dom';
5 | import TestUtils from 'react-addons-test-utils';
6 | import TabList from './tab-list.js';
7 |
8 | describe(__filename, () => {
9 | it('renders', () => {
10 | const reactDocument = TestUtils.renderIntoDocument( ),
11 | el = ReactDOM.findDOMNode(reactDocument);
12 |
13 | expect(el.className).toEqual('tab-list');
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/src/browser/components/tabs/tab-overflow-image.css:
--------------------------------------------------------------------------------
1 | /*noinspection CssOptimizeSimilarProperties*/
2 | .tab-overflow-image a {
3 | background-size: auto 80%;
4 | background-repeat: no-repeat;
5 | background-position: center;
6 | display: block;
7 | width: 30px;
8 | height: 30px;
9 | }
10 |
11 | .tab-overflow-image:first-child {
12 | margin-left: 2px;
13 | }
14 |
--------------------------------------------------------------------------------
/src/browser/components/tabs/tab-overflow-image.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import commonReact from '../../services/common-react';
3 | import './tab-overflow-image.css';
4 |
5 | export default React.createClass({
6 | displayName: 'TabOverflowImage',
7 | propTypes: {
8 | onClick: React.PropTypes.func.isRequired,
9 | src: React.PropTypes.string.isRequired
10 | },
11 | shouldComponentUpdate(nextProps) {
12 | return commonReact.shouldComponentUpdate(this, nextProps);
13 | },
14 | render: function () {
15 | const props = this.props,
16 | className = commonReact.getClassNameList(this),
17 | style = {
18 | backgroundImage: 'url(' + props.src + ')'
19 | };
20 |
21 |
22 | return (
23 | {' '}
24 | );
25 | }
26 | });
27 |
--------------------------------------------------------------------------------
/src/browser/components/tabs/tabbed-pane-item.css:
--------------------------------------------------------------------------------
1 | .tabbed-pane-item {
2 | display: none;
3 | overflow: hidden;
4 | }
5 |
6 | .tabbed-pane-item.active {
7 | display: block;
8 | height: 100%;
9 | }
10 |
--------------------------------------------------------------------------------
/src/browser/components/tabs/tabbed-pane-item.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import './tabbed-pane-item.css';
3 | import commonReact from '../../services/common-react';
4 |
5 | /**
6 | * @class TabbedPaneItem
7 | * @extends ReactComponent
8 | * @property props
9 | */
10 | export default React.createClass({
11 | displayName: 'TabbedPaneItem',
12 | propTypes: {
13 | active: React.PropTypes.bool,
14 | closeable: React.PropTypes.bool,
15 | icon: React.PropTypes.string,
16 | id: React.PropTypes.string,
17 | label: React.PropTypes.string.isRequired
18 | },
19 | shouldComponentUpdate: function (nextProps) {
20 | return commonReact.shouldComponentUpdate(this, nextProps);
21 | },
22 | render: function () {
23 | const props = this.props,
24 | className = commonReact.getClassNameList(this);
25 |
26 | if (props.active) {
27 | className.push('active');
28 | }
29 |
30 | return {props.children}
;
31 | }
32 | });
33 |
--------------------------------------------------------------------------------
/src/browser/components/tabs/tabbed-pane.css:
--------------------------------------------------------------------------------
1 | .full-screen div.tabbed-pane { /* annoyingly specific over vsplitter */
2 | display: flex;
3 | flex-direction: column;
4 | justify-content: flex-start;
5 | align-items: stretch;
6 | overflow: hidden;
7 | align-content: stretch;
8 | }
9 |
10 | .tabbed-pane .left {
11 | float: left;
12 | min-height: 30px;
13 | min-width: 20px;
14 | }
15 |
16 | .tabbed-pane .right {
17 | float: right;
18 | min-height: 30px;
19 | min-width: 20px;
20 | }
21 |
22 | .tabbed-pane .right .search-text-box {
23 | margin-top: 3px;
24 | margin-right: 10px;
25 | }
26 |
27 | .tabbed-pane .fa-before:before {
28 | padding-right: 6px;
29 | }
30 |
31 | .tab-content {
32 | flex: 1 1;
33 | position: relative;
34 | }
35 |
36 | /* override bootstrap... */
37 | .tab-pane {
38 | display: block;
39 | top: 0;
40 | bottom: 0;
41 | left: 0;
42 | right: 0;
43 | position: absolute;
44 | overflow: auto;
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/src/browser/components/tree-view/tree-view.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import commonReact from '../../services/common-react';
3 | import TreeViewItem from './tree-view-item';
4 | import './tree-view.css';
5 |
6 | export default React.createClass({
7 | displayName: 'TreeView',
8 | shouldComponentUpdate: function (nextProps) {
9 | return commonReact.shouldComponentUpdate(this, nextProps);
10 | },
11 | propsTypes: {
12 | height: React.PropTypes.number,
13 | items: React.PropTypes.array.isRequired,
14 | width: React.PropTypes.number
15 | },
16 | render: function () {
17 | const props = this.props,
18 | className = commonReact.getClassNameList(this);
19 |
20 | return ;
21 | }
22 | });
23 |
--------------------------------------------------------------------------------
/src/browser/components/unsafe-html.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import commonReact from '../services/common-react';
4 |
5 | export default React.createClass({
6 | displayName: 'UnsafeHTML',
7 | propTypes: {
8 | id: React.PropTypes.string.isRequired,
9 | onLoad: React.PropTypes.func,
10 | src: React.PropTypes.string.isRequired
11 | },
12 | componentDidMount: function () {
13 | const el = ReactDOM.findDOMNode(this);
14 |
15 | if (el) {
16 | el.setAttribute('src', this.props.src);
17 | }
18 | },
19 | shouldComponentUpdate(nextProps, nextState) {
20 | return commonReact.shouldComponentUpdate(this, nextProps, nextState);
21 | },
22 | render: function () {
23 | const props = this.props,
24 | className = commonReact.getClassNameList(this);
25 |
26 | return (
27 |
34 | );
35 | }
36 | });
37 |
--------------------------------------------------------------------------------
/src/browser/components/unsafe-html.test.js:
--------------------------------------------------------------------------------
1 | /* globals describe, it, expect */
2 |
3 | import React from 'react';
4 | import ReactDOM from 'react-dom';
5 | import TestUtils from 'react-addons-test-utils';
6 | import UnsafeHtml from './unsafe-html.js';
7 |
8 | describe(__filename, () => {
9 | it('renders html', () => {
10 | const reactDocument = TestUtils.renderIntoDocument( ),
11 | el = ReactDOM.findDOMNode(reactDocument);
12 |
13 | expect(el.src).toEqual('abc');
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/src/browser/components/variable-viewer/variable-table.css:
--------------------------------------------------------------------------------
1 | .variable-table {
2 | height: 100%;
3 | }
4 |
5 | .variable-table .public_fixedDataTableCell_cellContent {
6 | white-space: nowrap;
7 | }
8 |
9 | .variable-table .public_fixedDataTableCell_wrap1 {
10 | width: 100%;
11 | }
12 |
--------------------------------------------------------------------------------
/src/browser/components/variable-viewer/variable-viewer.jsx:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import React from 'react';
3 | import commonReact from '../../services/common-react';
4 | import EmptySuggestion from '../empty/empty-suggestion';
5 | import VariableTable from './variable-table.jsx';
6 |
7 | /**
8 | * @class PackagesViewer
9 | * @extends ReactComponent
10 | * @property {object} state
11 | * @property {object} props
12 | */
13 | export default React.createClass({
14 | displayName: 'VariableViewer',
15 | propTypes: {
16 | filter: React.PropTypes.string,
17 | onShowDataFrame: React.PropTypes.func.isRequired,
18 | variables: React.PropTypes.object,
19 | visible: React.PropTypes.bool.isRequired
20 | },
21 | shouldComponentUpdate: function (nextProps, nextState) {
22 | return commonReact.shouldComponentUpdate(this, nextProps, nextState);
23 | },
24 | render: function () {
25 | const props = this.props;
26 | let content;
27 |
28 | if (props.variables && _.some(props.variables, variable => variable.length > 0)) {
29 | content = ;
30 | } else {
31 | content = ;
32 | }
33 |
34 | return content;
35 | }
36 | });
37 |
--------------------------------------------------------------------------------
/src/browser/components/yhat.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {send} from 'ipc';
3 | import commonReact from '../services/common-react';
4 |
5 | export default React.createClass({
6 | displayName: 'Yhat',
7 | shouldComponentUpdate(nextProps, nextState) {
8 | return commonReact.shouldComponentUpdate(this, nextProps, nextState);
9 | },
10 | handleYhat: () => send('openExternal', 'http://yhat.com/').catch(error => console.error(error)),
11 | render: function () {
12 | return (
13 |
14 | {'ŷ'}
15 | {'hat'}
16 |
17 | );
18 | }
19 | });
20 |
--------------------------------------------------------------------------------
/src/browser/containers/ask-quit-dialog-viewer/ask-quit-dialog-viewer.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import commonReact from '../../services/common-react';
3 | import {connect} from 'react-redux';
4 | import AskQuit from '../../components/dialogs/ask-quit';
5 | import selectors from './ask-quit-dialog-viewer.selectors';
6 | import applicationActions from '../../actions/application';
7 | import actions from '../../actions/preferences';
8 |
9 | /**
10 | * @param {function} dispatch
11 | * @returns {object}
12 | */
13 | function mapDispatchToProps(dispatch) {
14 | return {
15 | onAskQuitChange: changes => dispatch(actions.savePreferenceChanges(changes)),
16 | onQuit: () => dispatch(applicationActions.quit())
17 | };
18 | }
19 |
20 | export default connect(selectors.getAskQuit, mapDispatchToProps)(React.createClass({
21 | displayName: 'AskQuitDialogViewer',
22 | propTypes: {
23 | onCancel: React.PropTypes.func.isRequired
24 | },
25 | shouldComponentUpdate(nextProps) {
26 | return commonReact.shouldComponentUpdate(this, nextProps);
27 | },
28 | handleAskQuitChange(event) {
29 | const props = this.props,
30 | oldValue = props.askQuit,
31 | value = event.target.checked;
32 |
33 | if (oldValue !== value) {
34 | props.onAskQuitChange([{key: 'askQuit', value}]);
35 | }
36 | },
37 | render() {
38 | return ;
39 | }
40 | }));
41 |
--------------------------------------------------------------------------------
/src/browser/containers/ask-quit-dialog-viewer/ask-quit-dialog-viewer.reducer.js:
--------------------------------------------------------------------------------
1 | import Immutable from 'seamless-immutable';
2 | import mapReducers from '../../services/map-reducers';
3 | import {local} from '../../services/store';
4 |
5 | export function getInitialState() {
6 |
7 | return Immutable({
8 | askQuit: local.get('askQuit') || true
9 | });
10 | }
11 |
12 | function quiting(state) {
13 | return state.set('state', 'quiting');
14 | }
15 |
16 | function quit(state) {
17 | return state.set('state', 'quit');
18 | }
19 |
20 | function changeSaved(state, action) {
21 | const key = action.change.key;
22 |
23 | if (key === 'askQuit') {
24 | state = state.set('askQuit', action.change.value);
25 | }
26 |
27 | return state;
28 | }
29 |
30 | export default mapReducers({
31 | QUITING: quiting,
32 | QUIT: quit,
33 | PREFERENCE_CHANGE_SAVED: changeSaved
34 | }, {});
35 |
--------------------------------------------------------------------------------
/src/browser/containers/ask-quit-dialog-viewer/ask-quit-dialog-viewer.selectors.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import {createSelector} from 'reselect';
3 |
4 | const contentType = 'askQuit',
5 | modalDialogs = state => state.modalDialogs,
6 | getAskQuit = createSelector(
7 | modalDialogs,
8 | modalDialogs => {
9 | const dialog = _.isObject(modalDialogs) && _.find(modalDialogs.items, {contentType});
10 |
11 | return dialog && dialog.content;
12 | }
13 | );
14 |
15 | export default {
16 | getAskQuit
17 | };
18 |
--------------------------------------------------------------------------------
/src/browser/containers/block-terminal-viewer/block-terminal-viewer.css:
--------------------------------------------------------------------------------
1 | .block-terminal-viewer {
2 | position: relative;
3 | height: 100%;
4 | display: flex;
5 | flex-direction: column;
6 | align-items: stretch;
7 | align-content: stretch;
8 | }
9 |
10 | .block-terminal-viewer .block-history {
11 | flex-grow: 5;
12 | overflow-y: auto;
13 | }
14 |
15 | .block-terminal-viewer .prompt {
16 | flex-grow: 0;
17 | flex-shrink: 0;
18 | }
19 |
--------------------------------------------------------------------------------
/src/browser/containers/document-terminal-viewer/document-terminal-viewer.css:
--------------------------------------------------------------------------------
1 | .document-terminal-viewer {
2 | height: 100%;
3 | position: relative;
4 | }
5 |
6 | .document-terminal-viewer .document-terminal {
7 | height: calc(100% - 20px);
8 | }
9 |
10 | .document-terminal-viewer .gray-info {
11 | height: 20px;
12 | }
13 |
14 | .document-terminal-viewer .prompt {
15 | margin-left: 10px;
16 | margin-right: 10px;
17 | color: #666;
18 | background-color: inherit;
19 | font-family: inherit;
20 | font-size: inherit;
21 | transition: color 1s;
22 | }
23 |
24 | .document-terminal-viewer .empty-suggestion.empty-suggestion--visible {
25 | opacity: 1;
26 | }
27 |
28 | .document-terminal-viewer .empty-suggestion {
29 | position: absolute;
30 | width: 100%;
31 | opacity: 0;
32 | transition: opacity 0.5s;
33 | top: 0;
34 | z-index: -1;
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/src/browser/containers/document-terminal-viewer/features.yml:
--------------------------------------------------------------------------------
1 | - onClick: onClear
2 | icon: trash
3 | label: Clear
4 | title: Ctrl + L
5 | keyboardShortcuts:
6 | - key: l
7 | alt: false
8 | meta: false
9 | shift: false
10 | ctrl: true
11 | selection: false
12 | - key: k
13 | alt: false
14 | meta: false
15 | shift: false
16 | ctrl: true
17 | selection: false
18 | - key: l
19 | alt: false
20 | meta: false
21 | shift: false
22 | ctrl: true
23 | selection: true
24 | - key: k
25 | alt: false
26 | meta: false
27 | shift: false
28 | ctrl: true
29 | selection: true
30 | - onClick: onInterrupt
31 | icon: stop
32 | label: Interrupt
33 | title: Ctrl + C
34 | whenBusy: true
35 | keyboardShortcuts:
36 | - key: c
37 | alt: false
38 | meta: false
39 | shift: false
40 | ctrl: true
41 | selection: false
42 | - onClick: onRestart
43 | icon: refresh
44 | label: Restart
45 | title: "⌘ + R"
46 | keyboardShortcuts:
47 | - key: r
48 | alt: false
49 | meta: true
50 | shift: false
51 | ctrl: false
52 | selection: false
53 |
--------------------------------------------------------------------------------
/src/browser/containers/editor-tab-group/editor-commands.yml:
--------------------------------------------------------------------------------
1 | - name: executeFile
2 | bindKey:
3 | win: shift-ctrl-Enter
4 | mac: Shift-Command-Enter
5 |
6 | - name: executeSelection
7 | scrollIntoView: animate
8 | bindKey:
9 | win: ctrl-Enter
10 | mac: Command-Enter
11 |
12 | - name: selectJupyterBlock
13 | scrollIntoView: animate
14 | bindKey:
15 | win: ctrl-Enter
16 | mac: Command-Enter
17 |
18 | - name: interrupt
19 | bindKey:
20 | win: ctrl-shift-c
21 | mac: ctrl-c
22 |
23 | - name: blockindent
24 | bindKey:
25 | win: ctrl-\]
26 | mac: Command-\]
27 |
28 | - name: blockoutdent
29 | bindKey:
30 | win: ctrl-\[|Shift-Tab
31 | mac: Command-\[|Shift-Tab
32 |
33 | - name: openPreferences
34 | bindKey:
35 | win: ctrl-,
36 | mac: Command-,
37 |
38 | - name: autocomplete
39 | scrollIntoView: animate
40 | bindKey:
41 | win: Tab
42 | mac: Tab
43 |
--------------------------------------------------------------------------------
/src/browser/containers/editor-tab-group/editor-tab-group.css:
--------------------------------------------------------------------------------
1 | .tab-content-list .ace-pane {
2 | /* temporary until moved into own component */
3 | height: calc(100% - 20px);
4 | }
5 |
--------------------------------------------------------------------------------
/src/browser/containers/editor-tab-group/initial-story.py:
--------------------------------------------------------------------------------
1 | # Press CTRL + ENTER to run a single line in the console
2 | print('Welcome to Rodeo!')
3 |
4 | # Press CTRL + ENTER with text selected to run multiple lines
5 | # For example, select the following lines
6 | x = 7
7 | x**2
8 | # and remember to press CTRL + ENTER
9 |
10 | # Here is an example of using Rodeo:
11 |
12 | # Install packages
13 |
14 | ! pip install pandas
15 | ! pip install numpy
16 |
17 | # Import packages
18 |
19 | import numpy as np
20 | import pandas as pd
21 |
22 | N = 100
23 | df = pd.DataFrame({
24 | 'A': pd.date_range(start='2016-01-01',periods=N,freq='D'),
25 | 'x': np.linspace(0,stop=N-1,num=N),
26 | 'y': np.random.rand(N),
27 | 'C': np.random.choice(['Low','Medium','High'],N).tolist(),
28 | 'D': np.random.normal(100, 10, size=(N)).tolist()
29 | })
30 | df.head()
31 |
32 | # Another example of making a plot:
33 |
34 | from matplotlib import pyplot as plt
35 | x=df.x
36 | with plt.style.context('fivethirtyeight'):
37 | plt.plot(x, np.sin(x*5) + x + np.random.randn(N)*15)
38 | plt.plot(x, np.sin(x*5) + 0.5 * x + np.random.randn(N)*5)
39 | plt.plot(x, np.sin(x) + 2 * x + np.random.randn(N)*20)
40 |
41 | plt.title('Random lines')
42 | plt.show()
43 |
--------------------------------------------------------------------------------
/src/browser/containers/editor-tab-group/rodeo-logo/rodeo-logo.1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/browser/containers/editor-tab-group/rodeo-logo/rodeo-logo.1x.png
--------------------------------------------------------------------------------
/src/browser/containers/editor-tab-group/rodeo-logo/rodeo-logo.2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/browser/containers/editor-tab-group/rodeo-logo/rodeo-logo.2x.png
--------------------------------------------------------------------------------
/src/browser/containers/editor-tab-group/rodeo-logo/rodeo-logo.4x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/browser/containers/editor-tab-group/rodeo-logo/rodeo-logo.4x.png
--------------------------------------------------------------------------------
/src/browser/containers/environment-variables-dialog-viewer/environment-variables-dialog-viewer.actions.js:
--------------------------------------------------------------------------------
1 | import reduxUtil from '../../services/redux-util';
2 |
3 | const prefix = reduxUtil.fromFilenameToPrefix(__filename);
4 |
5 | function cancelChanges() {
6 | return {type: prefix + 'CANCEL_CHANGES'};
7 | }
8 |
9 | function saveChanges() {
10 | return {type: prefix + 'SAVE_CHANGES'};
11 | }
12 |
13 | function startEdit(item, container) {
14 | return {type: prefix + 'START_EDIT', payload: {item, container}};
15 | }
16 |
17 | function saveEdit(payload) {
18 | return {type: prefix + 'SAVE_EDIT', payload};
19 | }
20 |
21 | function cancelEdit(payload) {
22 | return {type: prefix + 'CANCEL_EDIT', payload};
23 | }
24 |
25 | function changeEditValue(item, target, value) {
26 | return {type: prefix + 'CHANGE_EDIT_VALUE', payload: {item, target, value}};
27 | }
28 |
29 | function reload() {
30 | return {type: prefix + 'RELOAD'};
31 | }
32 |
33 | function removeKey(item, key) {
34 | return {type: prefix + 'REMOVE_KEY', payload: {item, key}};
35 | }
36 |
37 | export default {
38 | cancelChanges,
39 | saveChanges,
40 | startEdit,
41 | saveEdit,
42 | cancelEdit,
43 | changeEditValue,
44 | reload,
45 | removeKey
46 | };
47 |
--------------------------------------------------------------------------------
/src/browser/containers/environment-variables-dialog-viewer/environment-variables-dialog-viewer.css:
--------------------------------------------------------------------------------
1 | /* environment variables from the system */
2 | .input-list__item--system {
3 | background-color: #eff9ff;
4 | color: #666;
5 | }
6 |
7 | .input-key-value-list__item--system {
8 | background-color: #eff9ff;
9 | color: #666;
10 | }
11 |
--------------------------------------------------------------------------------
/src/browser/containers/environment-variables-dialog-viewer/environment-variables-dialog-viewer.selectors.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import {createSelector} from 'reselect';
3 |
4 | const contentType = 'environmentVariables',
5 | modalDialogs = state => state.modalDialogs,
6 | getEnvironmentVariablesViewer = createSelector(
7 | modalDialogs,
8 | modalDialogs => {
9 | const dialog = _.isObject(modalDialogs) && _.find(modalDialogs.items, {contentType});
10 |
11 | return dialog && dialog.content;
12 | }
13 | );
14 |
15 | export default {
16 | getEnvironmentVariablesViewer
17 | };
18 |
--------------------------------------------------------------------------------
/src/browser/containers/environment-variables-dialog-viewer/layout.yml:
--------------------------------------------------------------------------------
1 | # id: some unique value
2 | # label: key in the i18n text
3 | -
4 | id: environmentVariableExplanation
5 | explanation: environmentVariableExplanation
6 | type: marked
7 |
8 | -
9 | id: environmentVariablePath
10 | key: environmentVariablePath
11 | label: environmentVariablePathExplanation
12 | type: list
13 | listColumnLabel: environmentVariablePath
14 |
15 | -
16 | id: environmentVariablePythonPath
17 | key: environmentVariablePythonPath
18 | label: environmentVariablePythonPathExplanation
19 | type: list
20 | listColumnLabel: environmentVariablePythonPath
21 |
22 | -
23 | id: remainingEnvironmentVariables
24 | key: remainingEnvironmentVariables
25 | label: editingEnvironmentVariableExplanation
26 | type: keyValueList
27 |
--------------------------------------------------------------------------------
/src/browser/containers/free-tabs-only.reducer.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux';
2 | import applicationControl from '../services/application-control';
3 | import freeTabGroups from './free-tab-group/free-tab-group.reducer';
4 |
5 | function broadcast(state, action) {
6 | applicationControl.shareAction(action);
7 |
8 | if (!state) {
9 | return {};
10 | }
11 |
12 | return state;
13 | }
14 |
15 | export default combineReducers({
16 | freeTabGroups,
17 | broadcast
18 | });
19 |
--------------------------------------------------------------------------------
/src/browser/containers/global-history-viewer/global-history-viewer.css:
--------------------------------------------------------------------------------
1 | .global-history-viewer {
2 | overflow: auto;
3 | height: 100%;
4 | }
5 |
--------------------------------------------------------------------------------
/src/browser/containers/history-viewer/history-viewer.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import commonReact from '../../services/common-react';
3 | import BlockHistory from '../../components/block-history/block-history';
4 |
5 | export default React.createClass({
6 | displayName: 'HistoryViewer',
7 | shouldComponentUpdate: function (nextProps) {
8 | return commonReact.shouldComponentUpdate(this, nextProps);
9 | },
10 | render: function () {
11 | return ;
12 | }
13 | });
14 |
--------------------------------------------------------------------------------
/src/browser/containers/manage-connections-viewer/definitions.yml:
--------------------------------------------------------------------------------
1 | defaultType: postgresql
2 | types:
3 | -
4 | name: postgresql
5 | label: Postgresql
6 | knownConfigurationOptions:
7 | host: string
8 | port: number
9 | database: string
10 | username: string
11 | password: string
12 | defaults:
13 | host: localhost
14 | port: 5432
15 | database: postgres
16 | username: postgres
17 | password: mysecretpassword
18 | -
19 | name: redshift
20 | label: Redshift
21 | defaults: {}
22 | -
23 | name: sqlserver
24 | label: SqlServer
25 | defaults: {}
26 | -
27 | name: mysql
28 | label: MySql
29 | defaults: {}
30 |
--------------------------------------------------------------------------------
/src/browser/containers/manage-connections-viewer/manage-connections-viewer.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {connect} from 'react-redux';
3 | import ManageConnections from '../../components/manage-connections/manage-connections';
4 | import actions from './manage-connections.actions';
5 | import definitions from './definitions.yml';
6 | import selectors from './manage-connections.selectors';
7 |
8 | /**
9 | * @param {function} dispatch
10 | * @returns {object}
11 | */
12 | function mapDispatchToProps(dispatch) {
13 | return {
14 | onCancel: id => dispatch(actions.cancel(id)),
15 | onOK: (id, result) => dispatch(actions.ok(id, result)),
16 | onAddConnection: () => dispatch(actions.addConnection()),
17 | onConnect: id => dispatch(actions.connect(id)),
18 | onDisconnect: id => dispatch(actions.disconnect(id)),
19 | onRemoveConnection: id => dispatch(actions.removeConnection(id)),
20 | onChange: change => dispatch(actions.addChange(change)),
21 | onSelectConnection: id => dispatch(actions.selectConnection(id))
22 | };
23 | }
24 |
25 | export default connect(selectors.getConnectionsViewer, mapDispatchToProps)(React.createClass({
26 | displayName: 'ManageConnectionsViewer',
27 | render: function () {
28 | return ;
29 | }
30 | }));
31 |
--------------------------------------------------------------------------------
/src/browser/containers/manage-connections-viewer/manage-connections.selectors.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import {createSelector} from 'reselect';
3 |
4 | const contentType = 'manageConnections',
5 | modalDialogs = state => state.modalDialogs,
6 | getConnectionsViewer = createSelector(
7 | modalDialogs,
8 | modalDialogs => {
9 | const dialog = _.isObject(modalDialogs) && _.find(modalDialogs.items, {contentType});
10 |
11 | return dialog && dialog.content;
12 | }
13 | );
14 |
15 | export default {
16 | getConnectionsViewer
17 | };
18 |
--------------------------------------------------------------------------------
/src/browser/containers/modal-dialog-viewer/modal-dialog-viewer.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {connect} from 'react-redux';
3 | import ModalDialogContainer from '../../components/dialogs/modal-dialog-container';
4 | import actions from './modal-dialog.actions';
5 | import commonReact from '../../services/common-react';
6 |
7 | function mapStateToProps(state) {
8 | return state.modalDialogs;
9 | }
10 |
11 | /**
12 | * @param {function} dispatch
13 | * @returns {object}
14 | */
15 | function mapDispatchToProps(dispatch) {
16 | return {
17 | onCancel: id => dispatch(actions.cancel(id)),
18 | onCancelAll: () => dispatch(actions.cancelAll()),
19 | onOK: (id, result) => dispatch(actions.ok(id, result)),
20 | onRegister: () => dispatch(actions.register())
21 | };
22 | }
23 |
24 | export default connect(mapStateToProps, mapDispatchToProps)(React.createClass({
25 | displayName: 'ModalDialogViewer',
26 | shouldComponentUpdate(nextProps) {
27 | return commonReact.shouldComponentUpdate(this, nextProps);
28 | },
29 | render: function () {
30 | return ;
31 | }
32 | }));
33 |
--------------------------------------------------------------------------------
/src/browser/containers/modal-dialog-viewer/modal-dialog.actions.js:
--------------------------------------------------------------------------------
1 | function add(contentType) {
2 | return {type: 'ADD_MODAL_DIALOG', payload: {contentType}, meta: {sender: 'self', track: true}};
3 | }
4 |
5 | function ok(id, result) {
6 | return {type: 'OK_MODAL_DIALOG', payload: {id, result}, meta: {sender: 'self'}};
7 | }
8 |
9 | function cancel(id) {
10 | return {type: 'CANCEL_MODAL_DIALOG', payload: {id}, meta: {sender: 'self'}};
11 | }
12 |
13 | function cancelAll() {
14 | return {type: 'CANCEL_ALL_MODAL_DIALOGS', meta: {sender: 'self'}};
15 | }
16 |
17 | export default {
18 | add,
19 | ok,
20 | cancel,
21 | cancelAll
22 | };
23 |
--------------------------------------------------------------------------------
/src/browser/containers/package-search-viewer/package-search-viewer.jsx:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import React from 'react';
3 | import PackageSearchList from '../../components/packages/package-search-list.jsx';
4 |
5 | export default React.createClass({
6 | displayName: 'PackageSearchViewer',
7 | render: function () {
8 | return ;
9 | }
10 | });
11 |
--------------------------------------------------------------------------------
/src/browser/containers/plot-viewer/plot-viewer.actions.js:
--------------------------------------------------------------------------------
1 | import reduxUtil from '../../services/redux-util';
2 |
3 | const prefix = reduxUtil.fromFilenameToPrefix(__filename);
4 |
5 | function focus(groupId, id, plot) {
6 | return {type: prefix + 'FOCUS_PLOT', groupId, id, plot};
7 | }
8 |
9 | function remove(groupId, id, plot) {
10 | return {type: prefix + 'REMOVE_PLOT', groupId, id, plot};
11 | }
12 |
13 | export default {
14 | focus,
15 | remove
16 | };
17 |
--------------------------------------------------------------------------------
/src/browser/containers/plot-viewer/plot-viewer.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PlotPreview from '../../components/plot-preview/plot-preview.jsx';
3 | import commonReact from '../../services/common-react';
4 |
5 | /**
6 | * @class PlotViewer
7 | * @extends ReactComponent
8 | * @property props
9 | * @property {Array} props.plots
10 | */
11 | export default React.createClass({
12 | displayName: 'PlotViewer',
13 | shouldComponentUpdate: function (nextProps) {
14 | return commonReact.shouldComponentUpdate(this, nextProps);
15 | },
16 | render: function () {
17 | return ;
18 | }
19 | });
20 |
--------------------------------------------------------------------------------
/src/browser/containers/preferences-viewer/preferences-viewer.selectors.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import {createSelector} from 'reselect';
3 |
4 | const contentType = 'preferences',
5 | modalDialogs = state => state.modalDialogs,
6 | getPreferencesViewer = createSelector(
7 | modalDialogs,
8 | modalDialogs => {
9 | const dialog = _.isObject(modalDialogs) && _.find(modalDialogs.items, {contentType});
10 |
11 | return dialog && dialog.content;
12 | }
13 | );
14 |
15 | export default {
16 | getPreferencesViewer
17 | };
18 |
--------------------------------------------------------------------------------
/src/browser/containers/prompt-viewer/prompt-viewer.actions.js:
--------------------------------------------------------------------------------
1 | import reduxUtil from '../../services/redux-util';
2 |
3 | // Don't share with other windows
4 | // Setting this means these actions will not be broadcast
5 | const sender = 'self',
6 | prefixType = reduxUtil.fromFilenameToPrefix(__filename);
7 |
8 | function autocomplete(groupId, id, payload) {
9 | return {type: prefixType + 'AUTOCOMPLETE', groupId, id, payload, meta: {sender}};
10 | }
11 |
12 | function createCommand(groupId, id, payload) {
13 | return {type: prefixType + 'COMMAND', groupId, id, payload, meta: {sender}};
14 | }
15 |
16 | function copyToPrompt(groupId, id, payload) {
17 | return {type: prefixType + 'COPY_TO_PROMPT', groupId, id, payload, meta: {sender}};
18 | }
19 |
20 | export default {
21 | autocomplete,
22 | createCommand,
23 | copyToPrompt
24 | };
25 |
--------------------------------------------------------------------------------
/src/browser/containers/prompt-viewer/prompt-viewer.reducer.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import mapReducers from '../../services/map-reducers';
3 | import promptActions from '../../services/prompt-actions';
4 | import reduxUtil from '../../services/redux-util';
5 |
6 | const prefixType = reduxUtil.fromFilenameToPrefix(__filename);
7 |
8 | function command(state, action) {
9 | const payload = action.payload,
10 | name = payload.name;
11 |
12 | if (promptActions[name]) {
13 | state = promptActions[name](state, payload);
14 | }
15 |
16 | return state;
17 | }
18 |
19 | function copyToPrompt(state, action) {
20 | const payload = action.payload,
21 | lines = payload.lines;
22 |
23 | // put lines
24 | return _.assign({}, state, {
25 | lines,
26 | cursor: {row: lines.length - 1, column: _.last(lines).length},
27 | historyIndex: -1
28 | });
29 | }
30 |
31 | function autocomplete(state, action) {
32 | const suggestions = action.payload;
33 |
34 | console.log(suggestions);
35 |
36 | return state;
37 | }
38 |
39 | export default mapReducers(reduxUtil.addPrefixToKeys(prefixType, {
40 | AUTOCOMPLETE: autocomplete,
41 | COPY_TO_PROMPT: copyToPrompt,
42 | COMMAND: command
43 | }), {});
44 |
--------------------------------------------------------------------------------
/src/browser/containers/setup-viewer/articles.yml:
--------------------------------------------------------------------------------
1 | %YAML 1.2
2 | ---
3 | -
4 | href: http://blog.yhat.com/posts/moving-from-r-to-python.html
5 | imageSrc: http://blog.yhat.com/static/img/r-to-python.jpg
6 | description: |
7 | ## Moving from R to Python: The Libraries You Need to Know
8 |
9 | Migrating from R to Python? Make sure you know about these packages.
10 |
--------------------------------------------------------------------------------
/src/browser/containers/setup-viewer/setup-viewer.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {connect} from 'react-redux';
3 | import Setup from '../../components/setup/setup.jsx';
4 | import actions from './setup-viewer.actions';
5 | import articles from './articles.yml';
6 |
7 | function mapStateToProps(state) {
8 | return state.setup;
9 | }
10 |
11 | function mapDispatchToProps(dispatch) {
12 | return {
13 | onCancel: () => dispatch(actions.cancel()),
14 | onExecute: () => dispatch(actions.execute()),
15 | onFinish: () => dispatch(actions.finish()),
16 | onInputChange: (key, event) => dispatch(actions.changeInput(key, event)),
17 | onOpenExternal: url => dispatch(actions.openExternal(url)),
18 | onPackageInstall: targetPackage => dispatch(actions.installPackage(targetPackage)),
19 | onRestart: () => dispatch(actions.restart()),
20 | onSkipStartup: () => dispatch(actions.skipStartup()),
21 | onTransition: contentType => dispatch(actions.transition(contentType))
22 | };
23 | }
24 |
25 | export default connect(mapStateToProps, mapDispatchToProps)(React.createClass({
26 | displayName: 'SetupViewer',
27 | render: function () {
28 | return ;
29 | }
30 | }));
31 |
--------------------------------------------------------------------------------
/src/browser/containers/startup.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import SetupViewer from './setup-viewer/setup-viewer.jsx';
3 | import {Provider} from 'react-redux';
4 | import FullScreen from '../components/layout-containers/full-screen.jsx';
5 | import rootReducer from './startup.reducer';
6 | import reduxStore from '../services/redux-store';
7 | import ipcDispatcher from '../services/ipc-dispatcher';
8 | import text from './startup-text.yml';
9 |
10 | const store = reduxStore.create(rootReducer);
11 |
12 | ipcDispatcher(store.dispatch);
13 |
14 | /**
15 | * @class Startup
16 | * @extends ReactComponent
17 | */
18 | export default React.createClass({
19 | displayName: 'Startup',
20 | childContextTypes: {
21 | store: React.PropTypes.object.isRequired,
22 | text: React.PropTypes.object.isRequired
23 | },
24 | getChildContext: function () {
25 | return {store, text};
26 | },
27 | render: function () {
28 | return (
29 |
30 |
31 |
32 |
33 |
34 | );
35 | }
36 | });
37 |
--------------------------------------------------------------------------------
/src/browser/containers/startup.reducer.js:
--------------------------------------------------------------------------------
1 | import applicationControl from '../services/application-control';
2 | import { combineReducers } from 'redux';
3 | import setup from './setup-viewer/setup-viewer.reducer';
4 |
5 | function broadcast(state, action) {
6 | applicationControl.shareAction(action);
7 |
8 | if (!state) {
9 | return {};
10 | }
11 |
12 | return state;
13 | }
14 |
15 | export default combineReducers({
16 | setup,
17 | broadcast
18 | });
19 |
--------------------------------------------------------------------------------
/src/browser/containers/studio-layout/rodeo-logo.1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/browser/containers/studio-layout/rodeo-logo.1x.png
--------------------------------------------------------------------------------
/src/browser/containers/studio-layout/rodeo-logo.2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/browser/containers/studio-layout/rodeo-logo.2x.png
--------------------------------------------------------------------------------
/src/browser/containers/studio-layout/rodeo-logo.4x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/browser/containers/studio-layout/rodeo-logo.4x.png
--------------------------------------------------------------------------------
/src/browser/containers/variable-viewer/variable-viewer.reducer.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import mapReducers from '../../services/map-reducers';
3 |
4 | function variablesChanged(state, action) {
5 | if (!_.isEqual(state.variables, action.payload)) {
6 | state = state.set('variables', action.payload);
7 | }
8 |
9 | return state;
10 | }
11 |
12 | export default mapReducers({
13 | VARIABLES_CHANGED: variablesChanged
14 | }, {});
15 |
--------------------------------------------------------------------------------
/src/browser/entry/free-tabs-only.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Rodeo
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/browser/entry/free-tabs-only.js:
--------------------------------------------------------------------------------
1 | import { AppContainer } from 'react-hot-loader';
2 | import React from 'react';
3 | import ReactDOM from 'react-dom';
4 | import App from '../containers/free-tabs-only.jsx';
5 |
6 | const rootEl = document.querySelector('main');
7 |
8 | ReactDOM.render(
9 |
10 |
11 | ,
12 | rootEl
13 | );
14 |
15 | if (module.hot) {
16 | module.hot.accept('../containers/free-tabs-only.jsx', () => {
17 | // If you use Webpack 2 in ES modules mode, you can
18 | // use here rather than require() a .
19 | const NextApp = require('../containers/free-tabs-only.jsx').default;
20 |
21 | ReactDOM.render(
22 |
23 |
24 | ,
25 | rootEl
26 | );
27 | });
28 | }
29 |
30 | ReactDOM.render(React.createElement(App, null), document.querySelector('main'));
31 |
--------------------------------------------------------------------------------
/src/browser/entry/startup.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Rodeo Startup
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/browser/entry/startup.js:
--------------------------------------------------------------------------------
1 | import { AppContainer } from 'react-hot-loader';
2 | import React from 'react';
3 | import ReactDOM from 'react-dom';
4 | import App from './../containers/startup.jsx';
5 |
6 | /**
7 | * Use #content because is deeper. There should be a header and footer for the page that will be
8 | * consistent in all the setup screens.
9 | */
10 | const rootEl = document.querySelector('main');
11 |
12 | ReactDOM.render(
13 |
14 |
15 | ,
16 | rootEl
17 | );
18 |
19 | if (module.hot) {
20 | module.hot.accept('./../containers/startup.jsx', () => {
21 | // If you use Webpack 2 in ES modules mode, you can
22 | // use here rather than require() a .
23 | const NextApp = require('./../containers/startup.jsx').default;
24 |
25 | ReactDOM.render(
26 |
27 |
28 | ,
29 | rootEl
30 | );
31 | });
32 | }
33 |
--------------------------------------------------------------------------------
/src/browser/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/browser/favicon.ico
--------------------------------------------------------------------------------
/src/browser/services/api.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Currently, we use ipc to communicate to the API. In the future, this will change
3 | * @module
4 | */
5 |
6 | import ipc from 'ipc';
7 | import bluebird from 'bluebird';
8 |
9 | export default {
10 | send: bluebird.method(ipc.send),
11 | on: ipc.on
12 | };
13 |
--------------------------------------------------------------------------------
/src/browser/services/cid.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This has to be unique within a particular client, so simple counting will do.
3 | * @module
4 | */
5 |
6 | import textUtil from './text-util';
7 |
8 | const windowPostfix = textUtil.getRandomCharacters(5);
9 |
10 | /**
11 | * @returns {function}
12 | */
13 | export default (function () {
14 | let i = 0;
15 |
16 | return function () {
17 | if (i == Number.MAX_SAFE_INTEGER) {
18 | i = 0;
19 | }
20 | return 'cid-' + (i++).toString(36) + '-' + windowPostfix;
21 | };
22 | }());
23 |
--------------------------------------------------------------------------------
/src/browser/services/common-react.test.js:
--------------------------------------------------------------------------------
1 | /* globals describe, it, expect */
2 |
3 | import _ from 'lodash';
4 | import lib from './common-react';
5 |
6 | describe(__filename, function () {
7 | describe('shallowCompare', function () {
8 | it('is true when both are equal', function () {
9 | const instance = {props: {}, state: {}};
10 |
11 | expect(lib.shallowEqual(instance, {}, {})).toEqual(true);
12 | });
13 |
14 | it('is true when states are equal', function () {
15 | const instance = {state: {}};
16 |
17 | expect(lib.shallowEqual(instance, undefined, {})).toEqual(true);
18 | });
19 |
20 | it('is true when props are equal', function () {
21 | const instance = {props: {}};
22 |
23 | expect(lib.shallowEqual(instance, {})).toEqual(true);
24 | });
25 |
26 | it('is false when props are not equal', function () {
27 | const instance = {props: {}};
28 |
29 | expect(lib.shallowEqual(instance, {a: 'b'})).toEqual(false);
30 | });
31 |
32 | it('is true when props are equal except for functions', function () {
33 | const instance = {props: {a: _.constant('b')}};
34 |
35 | expect(lib.shallowEqual(instance, {a: _.constant('b')})).toEqual(true);
36 | });
37 | });
38 | });
39 |
--------------------------------------------------------------------------------
/src/browser/services/database-connections.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import api from './api';
3 |
4 | /**
5 | * Any properties that are strings and empty are removed from shallowly cloned object
6 | * @param {object} obj
7 | * @returns {object}
8 | */
9 | function removeEmptyStrings(obj) {
10 | return _.reduce(obj, (obj, value, key) => {
11 | if (typeof value === 'string') {
12 | if (value) {
13 | obj[key] = value;
14 | }
15 | } else {
16 | obj[key] = value;
17 | }
18 |
19 | return obj;
20 | }, {});
21 | }
22 |
23 | function connect(connectionConfig) {
24 | return api.send('databaseConnect', removeEmptyStrings(connectionConfig));
25 | }
26 |
27 | function query(context) {
28 | return api.send('databaseQuery', context.id, context.text);
29 | }
30 |
31 | function getInfo(id) {
32 | return api.send('databaseInfo', id);
33 | }
34 |
35 | function disconnect(id) {
36 | return api.send('databaseDisconnect', id);
37 | }
38 |
39 | export default {
40 | connect,
41 | disconnect,
42 | getInfo,
43 | query
44 | };
45 |
--------------------------------------------------------------------------------
/src/browser/services/dom.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Helper functions for tranversing the dom without jQuery
3 | * @module
4 | */
5 |
6 | /**
7 | * @param {Node} node
8 | * @param {string} nodeName
9 | * @returns {Element|Node|false}
10 | */
11 | export function getParentNodeOf(node, nodeName) {
12 | nodeName = nodeName.toUpperCase();
13 | while (node.parentNode && node.nodeName !== nodeName) {
14 | node = node.parentNode;
15 | }
16 | return node.nodeName === nodeName && node;
17 | }
18 |
19 |
--------------------------------------------------------------------------------
/src/browser/services/errors/index.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 |
3 | function toObject(error) {
4 | const properties = {};
5 |
6 | _.assign(properties, _.pick(error, ['message', 'stack']));
7 | _.each(error, (value, key) => properties[key] = value);
8 |
9 | return properties;
10 | }
11 |
12 | export default {
13 | toObject
14 | };
15 |
--------------------------------------------------------------------------------
/src/browser/services/errors/validation-error.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 |
3 | function ValidationError(message, properties) {
4 | const error = Error.call(this, message);
5 |
6 | this.name = 'ValidationError';
7 | this.message = error.message;
8 | this.stack = error.stack;
9 | _.assign(this, properties);
10 | }
11 | ValidationError.prototype = Object.create(Error.prototype);
12 | ValidationError.prototype.constructor = ValidationError;
13 |
14 | export default ValidationError;
15 |
--------------------------------------------------------------------------------
/src/browser/services/global-observer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @module
3 | */
4 |
5 | import Eventify from 'eventify';
6 |
7 | const observer = {};
8 |
9 | Eventify.enable(observer);
10 |
11 | /**
12 | * Triggers when something in the window resizes, possibly requiring others to resize around them.
13 | *
14 | * Other things that resize should trigger this observer event as well
15 | */
16 | function triggerOnResize() {
17 | window.addEventListener('focus', () => observer.trigger('resize'));
18 | window.addEventListener('resize', () => observer.trigger('resize'));
19 | }
20 |
21 | triggerOnResize();
22 |
23 | export default observer;
24 |
--------------------------------------------------------------------------------
/src/browser/services/guid.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This has to be unique between clients, which is different than the cid.
3 | * @module
4 | */
5 |
6 | /**
7 | * @returns {string}
8 | */
9 | function s4() {
10 | return Math.floor((1 + Math.random()) * 0x10000)
11 | .toString(16)
12 | .substring(1);
13 | }
14 |
15 | export default (function () {
16 | return function () {
17 | return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
18 | s4() + '-' + s4() + s4() + s4();
19 | };
20 | }());
21 |
--------------------------------------------------------------------------------
/src/browser/services/immutable-util.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import Immutable from 'seamless-immutable';
3 |
4 | function unshift(state, item) {
5 | const mutableArray = state.asMutable();
6 |
7 | mutableArray.unshift(item);
8 |
9 | return Immutable(mutableArray);
10 | }
11 |
12 | function unshiftAtPath(state, path, item) {
13 | return state.updateIn(path, array => {
14 | return unshift(array, item);
15 | });
16 | }
17 |
18 | function push(state, item) {
19 | const mutableArray = state.asMutable();
20 |
21 | mutableArray.push(item);
22 |
23 | return Immutable(mutableArray);
24 | }
25 |
26 | function pushAtPath(state, path, item) {
27 | return state.updateIn(path, array => {
28 | return push(array, item);
29 | });
30 | }
31 |
32 | function removeAt(state, index) {
33 | if (_.isArray(state)) {
34 | state = state.asMutable();
35 |
36 | state.splice(index, 1);
37 |
38 | return Immutable(state);
39 | }
40 |
41 | return state.without(index);
42 | }
43 |
44 | function removeAtPath(state, path, index) {
45 | return state.updateIn(path, obj => {
46 | return removeAt(obj, index);
47 | });
48 | }
49 |
50 | export default {
51 | removeAt,
52 | removeAtPath,
53 | push,
54 | pushAtPath,
55 | unshift,
56 | unshiftAtPath
57 | };
58 |
--------------------------------------------------------------------------------
/src/browser/services/jupyter/conda.js:
--------------------------------------------------------------------------------
1 | import api from '../api';
2 |
3 | function copyCondaToHome() {
4 | return api.send('copyCondaToHome');
5 | }
6 |
7 | export default {
8 | copyCondaToHome
9 | };
10 |
--------------------------------------------------------------------------------
/src/browser/services/jupyter/response.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 |
3 | const requests = {}; // track requests so we can resolve their promises later
4 |
5 | /**
6 | * @param {function} dispatch
7 | * @param {JupyterClientResponse} response
8 | */
9 | function handle(dispatch, response) {
10 | let msg_id = _.get(response, 'result.parent_header.msg_id'),
11 | request = requests[msg_id];
12 |
13 | if (request) {
14 | if (request.resolveEvent === _.get(response, 'result.msg_type')) {
15 | request.deferred.resolve({request, response});
16 | delete requests[msg_id];
17 | } else {
18 | request.unmatchedResponses = request.unmatchedResponses || [];
19 | request.unmatchedResponses.push(response);
20 | }
21 | } else {
22 | return dispatch({type: 'JUPYTER_RESPONSE', payload: response});
23 | }
24 | }
25 |
26 | /**
27 | * Add a request to be responded to.
28 | *
29 | * @param {string} id
30 | * @param {object} request
31 | */
32 | function addRequest(id, request) {
33 | requests[id] = request;
34 | }
35 |
36 | export default {
37 | handle,
38 | addRequest
39 | };
40 |
--------------------------------------------------------------------------------
/src/browser/services/log.js:
--------------------------------------------------------------------------------
1 | const types = {
2 | info: true,
3 | debug: true,
4 | warn: true,
5 | error: true
6 | };
7 |
8 | export function log(type) {
9 | if (types[type]) {
10 | /* eslint no-console: 0 */
11 | console[type].apply(console, Array.prototype.slice.call(arguments, 1));
12 | }
13 | }
14 |
15 | export function asInternal(prefix) {
16 | return function (type) {
17 | log.apply(null, [type, prefix].concat(Array.prototype.slice.call(arguments, 1)));
18 | };
19 | }
20 |
21 | export default log;
22 |
--------------------------------------------------------------------------------
/src/browser/services/map-reducers.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @param {object} reducerMap
3 | * @param {*} initialState
4 | * @returns {function}
5 | */
6 | export default function (reducerMap, initialState) {
7 | return function (state, action) {
8 | if (!state) {
9 | state = initialState;
10 | }
11 |
12 | if (reducerMap[action.type]) {
13 | return reducerMap[action.type](state, action) || state;
14 | } else {
15 | return state;
16 | }
17 | };
18 | }
19 |
--------------------------------------------------------------------------------
/src/browser/services/map-reducers.test.js:
--------------------------------------------------------------------------------
1 | /* globals describe, it, expect, jest */
2 |
3 | import lib from './map-reducers';
4 |
5 | describe(__filename, function () {
6 |
7 | it('returns initial state when not given state', function () {
8 | const reducerMap = {},
9 | initialState = {a: 'b'},
10 | state = undefined,
11 | action = {};
12 |
13 | expect(lib(reducerMap, initialState)(state, action)).toEqual(initialState);
14 | });
15 |
16 | it('runs function matching action', function () {
17 | const spy = jest.fn(),
18 | reducerMap = {a: spy},
19 | initialState = {},
20 | state = {},
21 | action = {type: 'a'};
22 |
23 | lib(reducerMap, initialState)(state, action);
24 |
25 | expect(spy).toBeCalledWith(state, action);
26 | });
27 | });
28 |
--------------------------------------------------------------------------------
/src/browser/services/react-performance.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Performance grouping
3 | */
4 |
5 | let events = [];
6 |
7 | function mark(componentInstance, eventName, props) {
8 | events.push([componentInstance.constructor.displayName, eventName, props]);
9 | }
10 |
11 | function report() {
12 | if (events.length) {
13 | const tempEvents = events;
14 |
15 | events = [];
16 |
17 | console.groupCollapsed('performance');
18 | for (let i = 0; i < tempEvents.length; i++) {
19 | console.log.apply(console, tempEvents[i]);
20 | }
21 | console.groupEnd();
22 | }
23 | }
24 |
25 | export default {
26 | mark,
27 | report
28 | };
29 |
--------------------------------------------------------------------------------
/src/browser/services/redux-store.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import {createStore, applyMiddleware} from 'redux';
3 | import thunk from 'redux-thunk';
4 | import reactPerformance from './react-performance';
5 |
6 | /**
7 | * @param {object} reducer
8 | * @param {object} [initialState]
9 | * @returns {*}
10 | */
11 | function create(reducer, initialState) {
12 | const createStoreWithMiddleware = applyMiddleware(thunk)(createStore),
13 | store = createStoreWithMiddleware(reducer, initialState);
14 |
15 | // log every change to the store (this has performance implications, of course).
16 | store.subscribe(_.debounce(() => {
17 | reactPerformance.report();
18 | console.log('store', store.getState());
19 | }, 500));
20 |
21 | return store;
22 | }
23 |
24 | export default {
25 | create
26 | };
27 |
--------------------------------------------------------------------------------
/src/browser/services/registration.js:
--------------------------------------------------------------------------------
1 | import {local} from './store';
2 |
3 | const minute = 1000 * 60,
4 | day = minute * 60 * 24,
5 | hasRegisteredKey = 'hasRegistered',
6 | lastRegisterReminderKey = 'lastRegisterReminder';
7 |
8 | function shouldShowDialog() {
9 | const hasRegistered = local.get(hasRegisteredKey),
10 | lastRegisterReminder = local.get(lastRegisterReminderKey),
11 | timeSince = !!lastRegisterReminder && (Date.now() - new Date(lastRegisterReminder).getTime());
12 |
13 | return !hasRegistered && (!lastRegisterReminder || (timeSince > day));
14 | }
15 |
16 | function rememberShowedDialog() {
17 | local.set(lastRegisterReminderKey, new Date().getTime());
18 | }
19 |
20 | /**
21 | * @param {object} data
22 | * @returns {Promise}
23 | */
24 | function register(data) {
25 | data['rodeoId'] = local.get('userId');
26 |
27 | return fetch('https://www.yhat.com/rodeo/register', {
28 | method: 'POST',
29 | body: JSON.stringify(data),
30 | headers: {'Content-Type':'application/json'}
31 | }).then(function () {
32 | // Use a timestamp so we know _when_ they registered
33 | local.set(hasRegisteredKey, new Date().getTime());
34 | });
35 | }
36 |
37 | export default {
38 | register,
39 | shouldShowDialog,
40 | rememberShowedDialog
41 | };
42 |
--------------------------------------------------------------------------------
/src/browser/services/selection-util.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 |
3 | /**
4 | * @param {Selection} selection
5 | * @returns {boolean}
6 | * @example
7 | * function onClick(event) {
8 | * const isClick = isSelectionClick(window.getSelection());
9 | * }
10 | */
11 | function isSelectionClick(selection) {
12 | return selection.anchorOffset === selection.focusOffset && selection.anchorNode === selection.focusNode;
13 | }
14 |
15 | function copy(el) {
16 | const range = document.createRange(),
17 | prevSelection = [],
18 | selection = window.getSelection();
19 |
20 | for (let i = 0; i < selection.rangeCount; i++) {
21 | prevSelection[i] = selection.getRangeAt(i);
22 | }
23 | selection.removeAllRanges();
24 | range.selectNode(el);
25 | selection.addRange(range);
26 | document.execCommand('copy');
27 | _.defer(() => {
28 | window.getSelection().removeAllRanges();
29 | for (let i = 0; i < prevSelection.length; i++) {
30 | window.getSelection().addRange(prevSelection[i]);
31 | }
32 | });
33 | }
34 |
35 | function selectElement(el) {
36 | const range = document.createRange(),
37 | selection = window.getSelection();
38 |
39 | selection.removeAllRanges();
40 | range.selectNode(el);
41 | selection.addRange(range);
42 | }
43 |
44 | export default {
45 | copy,
46 | isSelectionClick,
47 | selectElement
48 | };
49 |
--------------------------------------------------------------------------------
/src/fonts/NotoMono-hinted/NotoMono-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/NotoMono-hinted/NotoMono-Regular.ttf
--------------------------------------------------------------------------------
/src/fonts/NotoSans-unhinted/NotoSans-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/NotoSans-unhinted/NotoSans-Bold.ttf
--------------------------------------------------------------------------------
/src/fonts/NotoSans-unhinted/NotoSans-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/NotoSans-unhinted/NotoSans-BoldItalic.ttf
--------------------------------------------------------------------------------
/src/fonts/NotoSans-unhinted/NotoSans-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/NotoSans-unhinted/NotoSans-Italic.ttf
--------------------------------------------------------------------------------
/src/fonts/NotoSans-unhinted/NotoSans-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/NotoSans-unhinted/NotoSans-Regular.ttf
--------------------------------------------------------------------------------
/src/fonts/NotoSerif-unhinted/NotoSerif-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/NotoSerif-unhinted/NotoSerif-Bold.ttf
--------------------------------------------------------------------------------
/src/fonts/NotoSerif-unhinted/NotoSerif-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/NotoSerif-unhinted/NotoSerif-BoldItalic.ttf
--------------------------------------------------------------------------------
/src/fonts/NotoSerif-unhinted/NotoSerif-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/NotoSerif-unhinted/NotoSerif-Italic.ttf
--------------------------------------------------------------------------------
/src/fonts/NotoSerif-unhinted/NotoSerif-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/NotoSerif-unhinted/NotoSerif-Regular.ttf
--------------------------------------------------------------------------------
/src/fonts/fonts.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'Lato-Regular';
3 | src: url('Lato-Regular.ttf') format('truetype');
4 | font-weight: normal;
5 | font-style: normal;
6 | }
7 |
8 | @font-face {
9 | font-family: 'NotoSans-Regular';
10 | src: url('NotoSans-Regular.ttf') format('truetype');
11 | font-weight: normal;
12 | font-style: normal;
13 | }
14 |
15 | @font-face {
16 | font-family: 'NotoSerif-Regular';
17 | src: url('NotoSerif-Regular.ttf') format('truetype');
18 | font-weight: normal;
19 | font-style: normal;
20 | }
21 |
22 | @font-face {
23 | font-family: 'NotoMono-Regular';
24 | src: url('NotoMono-Regular.ttf') format('truetype');
25 | font-weight: normal;
26 | font-style: normal;
27 | }
28 |
29 | @font-face {
30 | font-family: 'Roboto-Regular';
31 | src: url('Roboto-Regular.ttf') format('truetype');
32 | font-weight: normal;
33 | font-style: normal;
34 | }
35 |
36 | .font-heading {
37 | font-family: 'Lato-Regular', 'NotoSerif-Regular', 'Helvetica Neue', serif;
38 | }
39 |
40 | .font-monospaced {
41 | font-family: 'Menlo', 'Monaco', 'Consolas', 'NotoMono-Regular', 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace;
42 | }
43 |
44 | .font-serif {
45 | font-family: 'NotoSerif-Regular', serif;
46 | }
47 |
48 | .font-sans {
49 | font-family: 'Helvetica Neue', 'Roboto-Regular', 'NotoSans-Regular', 'Helvetica Neue', sans-serif;
50 | }
51 |
--------------------------------------------------------------------------------
/src/fonts/lato/Lato-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/lato/Lato-Black.ttf
--------------------------------------------------------------------------------
/src/fonts/lato/Lato-BlackItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/lato/Lato-BlackItalic.ttf
--------------------------------------------------------------------------------
/src/fonts/lato/Lato-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/lato/Lato-Bold.ttf
--------------------------------------------------------------------------------
/src/fonts/lato/Lato-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/lato/Lato-BoldItalic.ttf
--------------------------------------------------------------------------------
/src/fonts/lato/Lato-Hairline.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/lato/Lato-Hairline.ttf
--------------------------------------------------------------------------------
/src/fonts/lato/Lato-HairlineItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/lato/Lato-HairlineItalic.ttf
--------------------------------------------------------------------------------
/src/fonts/lato/Lato-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/lato/Lato-Italic.ttf
--------------------------------------------------------------------------------
/src/fonts/lato/Lato-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/lato/Lato-Light.ttf
--------------------------------------------------------------------------------
/src/fonts/lato/Lato-LightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/lato/Lato-LightItalic.ttf
--------------------------------------------------------------------------------
/src/fonts/lato/Lato-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/lato/Lato-Regular.ttf
--------------------------------------------------------------------------------
/src/fonts/roboto/COPYRIGHT.txt:
--------------------------------------------------------------------------------
1 | Copyright 2011 Google Inc. All Rights Reserved.
--------------------------------------------------------------------------------
/src/fonts/roboto/DESCRIPTION.en_us.html:
--------------------------------------------------------------------------------
1 | Roboto has a dual nature. It has a mechanical skeleton and the forms are
2 | largely geometric. At the same time, the font features friendly and open
3 | curves. While some grotesks distort their letterforms to force a rigid rhythm,
4 | Roboto doesn’t compromise, allowing letters to be settled into their natural
5 | width. This makes for a more natural reading rhythm more commonly found in
6 | humanist and serif types.
7 |
8 | This is the normal family, which can be used alongside the
9 | Roboto Condensed family and the
10 | Roboto Slab family.
11 |
12 |
13 | Updated January 14 2015:
14 | Christian Robertson and the Material Design team unveiled the latest version of Roboto at Google I/O last year, and it is now available from Google Fonts.
15 | Existing websites using Roboto via Google Fonts will start using the latest version automatically.
16 | If you have installed the fonts on your computer, please download them again and re-install.
17 |
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/roboto/Roboto-Black.ttf
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-BlackItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/roboto/Roboto-BlackItalic.ttf
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/roboto/Roboto-Bold.ttf
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/roboto/Roboto-BoldItalic.ttf
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/roboto/Roboto-Italic.ttf
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/roboto/Roboto-Light.ttf
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-LightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/roboto/Roboto-LightItalic.ttf
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/roboto/Roboto-Medium.ttf
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-MediumItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/roboto/Roboto-MediumItalic.ttf
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/roboto/Roboto-Regular.ttf
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-Thin.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/roboto/Roboto-Thin.ttf
--------------------------------------------------------------------------------
/src/fonts/roboto/Roboto-ThinItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yhat/rodeo/aa1929b1596d1161cd81c930603636a929462ea3/src/fonts/roboto/Roboto-ThinItalic.ttf
--------------------------------------------------------------------------------
/src/node/kernels/python/check.py:
--------------------------------------------------------------------------------
1 | # Gets information about a python instance, like packages installed and such
2 | import sys
3 | import json
4 | import os
5 | import pip
6 |
7 | try:
8 | import pip
9 | except:
10 | pip = None
11 |
12 | def get_packages():
13 | if not pip:
14 | return []
15 | installed_packages = pip.get_installed_distributions()
16 | packages = [{ "name": i.key, "version": i.version} for i in installed_packages]
17 | installed_packages_list = sorted(packages, key=lambda x: x['name'])
18 | return installed_packages_list
19 |
20 | # check for IPython kernel
21 | has_jupyter_kernel = True
22 | try:
23 | from jupyter_client import manager
24 | except:
25 | try:
26 | from IPython.kernel import manager
27 | except:
28 | #if pip:
29 | # try:
30 | # pip.main(['install', '--disable-pip-version-check', '-qq', 'jupyter'])
31 | # except:
32 | # has_jupyter_kernel = False
33 | #else:
34 | has_jupyter_kernel = False
35 |
36 | # may fail
37 | try:
38 | executable = sys.executable
39 | except:
40 | executable = None
41 |
42 | sys.stdout.write(json.dumps({
43 | "hasJupyterKernel": has_jupyter_kernel,
44 | "cwd": os.getcwd(),
45 | "version": sys.version,
46 | "executable": executable,
47 | "argv": sys.argv,
48 | "packages": get_packages()
49 | }))
50 |
--------------------------------------------------------------------------------
/src/node/kernels/python/language.test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const sinon = require('sinon'),
4 | dirname = __dirname.split('/').pop(),
5 | filename = __filename.split('/').pop().split('.').shift(),
6 | lib = require('./' + filename);
7 |
8 | describe(dirname + '/' + filename, function () {
9 | let sandbox;
10 |
11 | beforeEach(function () {
12 | sandbox = sinon.sandbox.create();
13 | });
14 |
15 | afterEach(function () {
16 | sandbox.restore();
17 | });
18 |
19 | describe('toPythonArgs', function () {
20 | const fn = lib[this.title];
21 |
22 | it('converts', function () {
23 | const data = {a: 'b', cD: 'e', fgHi: 'j'},
24 | expectedResult = {a: 'b', c_d: 'e', fg_hi: 'j'};
25 |
26 | expect(fn(data)).to.deep.equal(expectedResult);
27 | });
28 | });
29 |
30 | describe('setDefaultEnvVars', function () {
31 | const fn = lib[this.title];
32 |
33 | it('removes buffering', function () {
34 | const data = {};
35 |
36 | expect(fn(data)).to.have.property('PYTHONUNBUFFERED');
37 | });
38 | });
39 | });
40 |
--------------------------------------------------------------------------------
/src/node/services/args.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import yargs from 'yargs';
3 |
4 | function getArgv() {
5 | let sliceNum;
6 |
7 | if (_.endsWith(process.argv[0], 'Electron')) {
8 | sliceNum = 2;
9 | } else {
10 | sliceNum = 1;
11 | }
12 |
13 | return yargs
14 | .env('RODEO')
15 | .boolean('dev').default('dev', false)
16 | .option('startup', {
17 | default: true,
18 | type: 'boolean',
19 | describe: 'Show startup screen when not given file or path'
20 | })
21 | .option('dev', {
22 | default: false,
23 | type: 'boolean',
24 | describe: 'Show development tools'
25 | })
26 | .epilogue('RODEO_* environment variables work as well, i.e., RODEO_DEV=true')
27 | .help('h')
28 | .alias('h', 'help')
29 | .version()
30 | .wrap(null)
31 | .parse(process.argv.slice(sliceNum));
32 | }
33 |
34 | export default {
35 | getArgv: _.memoize(getArgv)
36 | };
37 |
--------------------------------------------------------------------------------
/src/node/services/chromium-errors.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # Common errors that might be encountered by users from loading a window
3 | IO_PENDING:
4 | id: -1
5 | FAILED:
6 | id: -2
7 | ABORTED:
8 | id: -3
9 | INVALID_ARGUMENT:
10 | id: -4
11 | INVALID_HANDLE:
12 | id: -5
13 | FILE_NOT_FOUND:
14 | id: -6
15 | TIMED_OUT:
16 | id: -7
17 | FILE_TOO_BIG:
18 | id: -8
19 | UNEXPECTED:
20 | id: -9
21 | ACCESS_DENIED:
22 | id: -10
23 | NOT_IMPLEMENTED:
24 | id: -11
25 | INSUFFICIENT_RESOURCES:
26 | id: -12
27 | OUT_OF_MEMORY:
28 | id: -13
--------------------------------------------------------------------------------
/src/node/services/clone.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 |
3 | function toObject(source) {
4 |
5 | if (_.isError(source)) {
6 | const dest = {},
7 | keys = _.filter(Object.getOwnPropertyNames(source), key => {
8 | // is not a function
9 | // does not start with an underscore
10 | return !_.isFunction(source[key]) && key[0] !== '_';
11 | });
12 |
13 | for (let i = 0; i < keys.length; i++) {
14 | const key = keys[i];
15 |
16 | dest[key] = source[key];
17 | }
18 |
19 | return dest;
20 | }
21 |
22 | return _.clone(source);
23 | }
24 |
25 | export default {
26 | toObject
27 | };
28 |
--------------------------------------------------------------------------------
/src/node/services/db/postgresql/get-schemas.sql:
--------------------------------------------------------------------------------
1 | select schema_name from information_schema.schemata
2 |
--------------------------------------------------------------------------------
/src/node/services/db/postgresql/get-tables-by-schema.sql:
--------------------------------------------------------------------------------
1 | select tablename from pg_tables where schemaname = $1
2 |
--------------------------------------------------------------------------------
/src/node/services/electron-winston-transport.js:
--------------------------------------------------------------------------------
1 | import util from 'util';
2 | import winston from 'winston';
3 |
4 | let ElectronLogger = function (options) {
5 | this.name = 'electronLogger';
6 | this.level = options.level || 'info';
7 | };
8 |
9 | //
10 | // Inherit from `winston.Transport` so you can take advantage
11 | // of the base functionality and `.handleExceptions()`.
12 | //
13 | util.inherits(ElectronLogger, winston.Transport);
14 |
15 | ElectronLogger.prototype.log = function (level, msg, meta, callback) {
16 | const ipcRenderer = require('electron').ipcRenderer;
17 |
18 | if (ipcRenderer) {
19 | ipcRenderer.send('console-log', {level, msg, meta});
20 | }
21 |
22 | //
23 | // Store this message and metadata, maybe use some custom logic
24 | // then callback indicating success.
25 | //
26 | callback(null, true);
27 | };
28 |
29 | export default ElectronLogger;
30 |
--------------------------------------------------------------------------------
/src/node/services/errors/process-error.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 |
3 | /**
4 | * @param {string} message
5 | * @param {object} properties
6 | * @constructor
7 | */
8 | function ProcessError(message, properties) {
9 | const error = Error.call(this, message);
10 |
11 | this.name = 'ProcessError';
12 | this.message = error.message;
13 | this.stack = error.stack;
14 | _.assign(this, properties);
15 | }
16 | ProcessError.prototype = Object.create(Error.prototype);
17 | ProcessError.prototype.constructor = ProcessError;
18 |
19 | export default ProcessError;
20 |
--------------------------------------------------------------------------------
/src/node/services/processes.test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const expect = require('chai').expect,
4 | sinon = require('sinon'),
5 | childProcess = require('child_process'),
6 | MockChildProcess = require('../../../test/mocks/classes/child-process'),
7 | log = require('./log'),
8 | dirname = __dirname.split('/').pop(),
9 | filename = __filename.split('/').pop().split('.').shift(),
10 | lib = require('./' + filename);
11 |
12 | describe(dirname + '/' + filename, function () {
13 | let sandbox;
14 |
15 | beforeEach(function () {
16 | sandbox = sinon.sandbox.create();
17 | sandbox.stub(log);
18 | sandbox.stub(childProcess);
19 | });
20 |
21 | afterEach(function () {
22 | sandbox.restore();
23 | });
24 |
25 | describe('create', function () {
26 | const fn = lib[this.title];
27 |
28 | it('creates', function () {
29 | const cmd = 'some command',
30 | mockChild = new MockChildProcess();
31 |
32 | childProcess.spawn.returns(mockChild);
33 |
34 | expect(fn(cmd)).to.equal(mockChild);
35 | });
36 | });
37 |
38 | describe('kill', function () {
39 | const fn = lib[this.title];
40 |
41 | it('kills', function () {
42 | const mockChild = new MockChildProcess();
43 |
44 | return fn(mockChild).then(function (result) {
45 | expect(result).to.deep.equal({code: 'a', signal: 'b'});
46 | });
47 | });
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/src/node/services/rest.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports.get = require('node-fetch');
--------------------------------------------------------------------------------
/src/node/services/survey.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import bluebird from 'bluebird';
3 | import browserWindows from './browser-windows';
4 |
5 | const log = require('./log').asInternal(__filename);
6 |
7 | function getTabs() {
8 | const windowNames = browserWindows.getWindowNames();
9 |
10 | return bluebird.all(_.map(windowNames, name => {
11 | return browserWindows.send(name, 'getTabs').catch(error => log('error', error));
12 | }));
13 | }
14 |
15 | module.exports.getTabs = getTabs;
16 |
--------------------------------------------------------------------------------
/src/node/services/win32/registry.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import path from 'path';
4 | import processes from '../processes';
5 |
6 | /**
7 | * @param {string} systemRoot
8 | * @returns {string}
9 | * @example setSystemRoot(process.env.SystemRoot);
10 | */
11 | function getRegPath(systemRoot) {
12 | if (systemRoot) {
13 | return path.join(systemRoot, 'System32', 'reg.exe');
14 | }
15 |
16 | return 'reg.exe';
17 | }
18 |
19 | /**
20 | * Add item to registry
21 | * @param {[string]} args
22 | * @param {string} systemRoot
23 | * @returns {Promise.<{errors: Error[], stderr: string, stdout: string}>}
24 | */
25 | function add(args, systemRoot) {
26 | args.unshift('add');
27 | args.push('/f');
28 |
29 | return processes.exec(getRegPath(systemRoot), args);
30 | }
31 |
32 | /**
33 | * Remove item from registry
34 | * @param {string} keyPath
35 | * @param {string} systemRoot
36 | * @returns {Promise.<{errors: Error[], stderr: string, stdout: string}>}
37 | */
38 | function remove(keyPath, systemRoot) {
39 | const args = ['delete', keyPath, '/f'];
40 |
41 | return processes.exec(getRegPath(systemRoot), args);
42 | }
43 |
44 | module.exports.add = add;
45 | module.exports.remove = remove;
46 |
--------------------------------------------------------------------------------
/src/readme.md:
--------------------------------------------------------------------------------
1 | Why two package.json?
2 |
3 | https://github.com/szwacz/electron-boilerplate#omg-but-seriously-why-there-are-two-packagejson
4 |
5 | https://github.com/electron-userland/electron-builder/issues/39
6 |
7 | https://github.com/electron-userland/electron-builder/issues/182
8 |
9 | https://github.com/electron-userland/electron-builder/issues/230
10 |
--------------------------------------------------------------------------------
/src/shared/dateUtil.js:
--------------------------------------------------------------------------------
1 | function getCurrentTime() {
2 | return new Date().getTime();
3 | }
4 |
5 | export default {
6 | getCurrentTime
7 | };
8 |
--------------------------------------------------------------------------------
/src/shared/env.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 |
3 | export function splitList(list) {
4 | if (process.platform === 'win32') {
5 | return list.split(';');
6 | } else {
7 | return list.split(':');
8 | }
9 | }
10 |
11 | export function joinList(list) {
12 | if (process.platform === 'win32') {
13 | return list.join(';');
14 | } else {
15 | return list.join(':');
16 | }
17 | }
18 |
19 | export function getKeyMap(source) {
20 | return _.reduce(source, (obj, value, key) => {
21 | obj[key.toUpperCase()] = key;
22 |
23 | return obj;
24 | }, {});
25 | }
26 |
27 | /**
28 | * @param {object} env
29 | * @param {string} [keyName='PATH']
30 | * @returns {Array}
31 | */
32 | export function getPath(env, keyName) {
33 | keyName = keyName && keyName.toUpperCase() || 'PATH';
34 | const keyMap = getKeyMap(env),
35 | path = env[keyMap[keyName]];
36 |
37 | return path ? splitList(path) : [];
38 | }
39 |
40 | /**
41 | * @param {object} env
42 | * @param {Array} newPath
43 | * @param {string} [keyName='PATH']
44 | * @returns {object}
45 | * @example setPath(process.env, '/usr/local/bin', 'MANPATH')
46 | */
47 | export function setPath(env, newPath, keyName) {
48 | keyName = keyName && keyName.toUpperCase() || 'PATH';
49 | const keyMap = getKeyMap(env);
50 |
51 | if (_.isArray(newPath)) {
52 | let key = keyMap[keyName] || keyName;
53 |
54 | env[key] = joinList(newPath);
55 | }
56 |
57 | return env;
58 | }
59 |
--------------------------------------------------------------------------------
/src/themes/cobalt.less:
--------------------------------------------------------------------------------
1 | // dark theme
2 | @import "default.less";
3 | @import "imported/cobalt.less";
4 |
--------------------------------------------------------------------------------
/src/themes/dark.less:
--------------------------------------------------------------------------------
1 | // presentation theme. this is still light, but looks better on a projector
2 | @import "default.less";
3 | @import "imported/dark.less";
4 |
--------------------------------------------------------------------------------
/src/themes/default.less:
--------------------------------------------------------------------------------
1 | // Core variables and mixins
2 | @import "imported/default.less";
3 | @import "../../node_modules/bootstrap/less/bootstrap.less";
4 | @import "../../node_modules/font-awesome/less/font-awesome.less";
5 |
6 | // structure
7 | @import "structure/global.less";
8 | @import "structure/fixed-data-table.less";
9 | @import "structure/jqconsole.less";
10 | @import "structure/forms.less";
11 | @import "lib/jquery.dataTables.less";
12 |
13 | // misc stuff
14 | @import "lib/misc.less";
15 |
16 | // bootswatch. this overrides certain things w/ default bootstrap
17 | @import "lib/bootswatch.less";
18 |
--------------------------------------------------------------------------------
/src/themes/lib/misc.less:
--------------------------------------------------------------------------------
1 | #bottom-left {
2 | padding: 0 0 0 0;
3 | }
4 |
5 | a {
6 | cursor: pointer;
7 | }
8 |
9 | .editor {
10 | height: 100%;
11 | position: absolute;
12 | }
13 |
14 | .tab-pane {
15 | width: 100%;
16 | overflow-y: scroll;
17 | }
18 |
19 | .navbar {
20 | margin-bottom: 0;
21 | }
22 |
23 | .hat {
24 | position: absolute;
25 | left: 2px;
26 | top: 10px;
27 | width: 35px;
28 | height: auto;
29 | z-index: 100000;
30 | }
31 | .big-hat {
32 | position: relative;
33 | left: 295px;
34 | top: 165px;
35 | width: 200px;
36 | height: auto;
37 | }
38 |
39 | #help-content {
40 | background-color: @body-bg;
41 | color: @text-color;
42 | }
43 |
44 | .selected {
45 | font-size: 20px;
46 | }
47 |
48 | .filename {
49 | text-decoration: none;
50 | }
51 |
52 | .selected:hover {
53 | background-color: @brand-primary;
54 | color: @gray-lighter;
55 | }
56 |
57 | .selected > a:hover {
58 | background-color: @brand-primary;
59 | color: @gray-lighter;
60 | }
61 |
62 | #plots-minimap > .active {
63 | border: medium solid skyblue;
64 | }
65 |
66 |
67 | #history-trail {
68 | > p:nth-child(odd) {
69 | background: @table-bg-accent;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/themes/presentation.less:
--------------------------------------------------------------------------------
1 | // presentation theme. this is still light, but looks better on a projector
2 | @import "default.less";
3 | @import "imported/presentation.less";
4 |
--------------------------------------------------------------------------------
/src/themes/structure/fixed-data-table.less:
--------------------------------------------------------------------------------
1 | .rodeo .public_fixedDataTable_main,
2 | .rodeo .public_fixedDataTable_header,
3 | .rodeo .public_fixedDataTable_hasBottomBorder {
4 | border-color: @table-header-border;
5 | }
6 |
7 | .rodeo .fixedDataTableLayout_main {
8 | border-style: solid;
9 | border-width: 0;
10 | }
11 |
12 | .rodeo .public_fixedDataTableColumnResizerLine_main {
13 | border-color: @action-drag-border;
14 | }
15 |
16 | .rodeo .public_fixedDataTableCell_columnResizerKnob {
17 | background-color: @action-drag-border;
18 | }
19 |
20 | .rodeo .public_fixedDataTableRow_main {
21 | background-color: @body-bg;
22 | }
23 |
24 | .rodeo .public_fixedDataTable_header,
25 | .rodeo .public_fixedDataTable_header .public_fixedDataTableCell_main {
26 | background-image: none;
27 | }
28 |
29 | .rodeo .public_fixedDataTableCell_cellContent {
30 | padding: 4px;
31 | }
32 |
--------------------------------------------------------------------------------
/src/themes/structure/global.less:
--------------------------------------------------------------------------------
1 | html {
2 | height: 100%;
3 | }
4 |
5 | * {
6 | outline: none;
7 | }
8 |
9 | *:focus {
10 | outline: Highlight auto 1px;
11 | transition: outline-offset 0.2s, outline-width 0.2s;
12 | }
13 |
14 | *:focus:hover {
15 | outline: Highlight auto 2px;
16 | }
17 |
18 | body {
19 | height: 100%;
20 | }
21 |
22 | main {
23 | height: 100%;
24 | }
25 |
26 | /* override bootstrap :( to move the tabs tightly together*/
27 | .nav > li > a[data-toggle="tab"] {
28 | padding: 10px
29 | }
30 |
31 | /* override bootstrap :( to stop adding an underline for non-tabs */
32 | .nav-tabs > li > a.not-tab,
33 | .nav-tabs > li > a.not-tab:hover,
34 | .nav-tabs > li > a.not-tab:focus:hover {
35 | box-shadow: none;
36 | }
37 |
38 | /* override bootstrap because negative margins are evil */
39 | main .form-horizontal .form-group {
40 | margin-left: 0;
41 | margin-right: 0;
42 | }
43 |
44 | /* override bootstrap because negative margins are evil (and cause scrollbars in split panes) */
45 | main .row {
46 | margin-left: 0;
47 | margin-right: 0;
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/src/themes/structure/jqconsole.less:
--------------------------------------------------------------------------------
1 | /* The console container element */
2 | #console {
3 | position: relative;
4 | width: 100%;
5 | background-color: @body-bg;
6 | }
7 |
8 | /* The inner console element. */
9 | pre.jqconsole {
10 | background-color: @body-bg;
11 | border: 0;
12 | color: @text-color;
13 | /* Allow us to override the font from the user preferences */
14 | font-size: inherit;
15 | }
16 |
17 | /* The cursor. */
18 | .jqconsole-cursor {
19 | background-color: @text-color;
20 | }
21 |
22 | /* The cursor color when the console looses focus. */
23 | .jqconsole-blurred .jqconsole-cursor {
24 | background-color: #666;
25 | }
26 |
27 | /* The current prompt text color */
28 | .jqconsole-prompt {
29 | color: @text-color;
30 | }
31 |
32 | /* The command history */
33 | .jqconsole-old-prompt {
34 | color: @text-color;
35 | font-weight: normal;
36 | }
37 |
38 | /* The text color when in input mode. */
39 | .jqconsole-input {
40 | color: @text-color;
41 | }
42 |
43 | /* Previously entered input. */
44 | .jqconsole-old-input {
45 | color: @text-color;
46 | font-weight: normal;
47 | }
48 |
49 | /* The text color of the output. */
50 | .jqconsole-output {
51 | color: @text-color;
52 | }
53 |
54 | .jqconsole-error {
55 | color: red;
56 | }
57 |
58 | .jqconsole-header {
59 | color: @text-color;
60 | }
61 |
--------------------------------------------------------------------------------
/test/browser/mocks/ace.js:
--------------------------------------------------------------------------------
1 | export default {};
2 |
--------------------------------------------------------------------------------
/test/browser/mocks/ipc.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 |
3 | export default {
4 | send: _.noop
5 | };
6 |
--------------------------------------------------------------------------------
/test/browser/mocks/storage.js:
--------------------------------------------------------------------------------
1 | class MockStorage {
2 | constructor() {
3 | this.store = {};
4 | }
5 |
6 | getItem(key) {
7 | return this.store[key] || null;
8 | }
9 |
10 | setItem(key, value) {
11 | this.store[key] = value.toString();
12 | }
13 |
14 | clear() {
15 | this.store = {};
16 | }
17 |
18 | setStore(value) {
19 | this.store = value;
20 | }
21 |
22 | getStore() {
23 | return this.store;
24 | }
25 | }
26 |
27 | export default MockStorage;
28 |
--------------------------------------------------------------------------------
/test/fixtures/windows-registry-commands/uninstall-context-menu.yml:
--------------------------------------------------------------------------------
1 | ---
2 | -
3 | - reg.exe
4 | -
5 | - delete
6 | - HKCU\Software\Classes\.py\shell\Rodeo
7 | - "/f"
8 | -
9 | - reg.exe
10 | -
11 | - delete
12 | - HKCU\Software\Classes\directory\shell\Rodeo
13 | - "/f"
14 | -
15 | - reg.exe
16 | -
17 | - delete
18 | - HKCU\Software\Classes\directory\background\shell\Rodeo
19 | - "/f"
20 | -
21 | - reg.exe
22 | -
23 | - delete
24 | - HKCU\Software\Classes\Applications\rodeo.exe
25 | - "/f"
26 |
--------------------------------------------------------------------------------
/test/mocks/classes/child-process.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const EventEmitter = require('events'),
4 | stream = require('stream');
5 |
6 | class MockChildProcess extends EventEmitter {
7 | constructor(options) {
8 | options = options || {};
9 | super();
10 | this.pid = options.pid || '123';
11 | this.stdout = new stream.PassThrough();
12 | this.stderr = new stream.PassThrough();
13 | }
14 | kill() {
15 | this.emit('close', 'a', 'b');
16 | }
17 | }
18 |
19 | module.exports = MockChildProcess;
20 |
--------------------------------------------------------------------------------
/test/mocks/jupyter_examples/create_svg_1.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | import numpy as np
3 |
4 | plt.figure(figsize=[6,6])
5 | x = np.arange(0,100,0.00001)
6 | y = x*np.sin(2*pi*x)
7 | plt.plot(y)
8 | plt.axis('off')
9 | plt.gca().set_position([0, 0, 1, 1])
10 | plt.savefig("test.svg")
11 |
--------------------------------------------------------------------------------
/test/mocks/jupyter_examples/create_svg_2.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | import numpy as np
3 | x = np.arange(0,100,0.00001)
4 | y = x*np.sin(2*np.pi*x)
5 | plt.plot(y)
6 | plt.savefig("test.svg", format="svg")
7 |
8 |
9 |
--------------------------------------------------------------------------------
/test/mocks/jupyter_examples/example_1.py:
--------------------------------------------------------------------------------
1 | %matplotlib inline
2 | import matplotlib.pyplot as plt
3 | from numpy import pi, exp, real, imag, linspace
4 | from ipywidgets import interact
5 |
6 | def f(t,a=1,b=6,c=-14,d=0):
7 | return exp(a*1j*t) - exp(b*1j*t)/2 + 1j*exp(c*1j*t)/3 + exp(d*1j*t)/4
8 |
9 | def plot_swirly(a=1,b=6,c=-14,d=0):
10 | t = linspace(0, 2*pi, 1000)
11 | ft = f(t,a,b,c,d)
12 | plt.plot(real(ft), imag(ft))
13 |
14 | # These two lines make the aspect ratio square
15 | fig = plt.gcf()
16 | fig.set_size_inches(6, 6, forward='True')
17 |
18 | interact(plot_swirly,a=(-20,20),b=(-20,20),c=(-20,20),d=(-20,20));
19 |
--------------------------------------------------------------------------------
/test/mocks/jupyter_examples/example_2.py:
--------------------------------------------------------------------------------
1 | import numpy
2 | import toyplot
3 |
4 | x = numpy.linspace(0, 10)
5 | y = x ** 2
6 |
7 | canvas = toyplot.Canvas(width=300, height=300)
8 | axes = canvas.axes()
9 | mark = axes.plot(x, y)
10 |
--------------------------------------------------------------------------------
/test/mocks/jupyter_examples/example_3.py:
--------------------------------------------------------------------------------
1 | import plotly
2 | import plotly.plotly as py
3 | import plotly.graph_objs as go
4 | from plotly.offline import download_plotlyjs, init_notebook_mode, iplot
5 |
6 | # Create random data with numpy
7 | import numpy as np
8 |
9 | init_notebook_mode()
10 |
11 | N = 1000
12 | random_x = np.random.randn(N)
13 | random_y = np.random.randn(N)
14 |
15 | # Create a trace
16 | trace = go.Scatter(
17 | x = random_x,
18 | y = random_y,
19 | mode = 'markers'
20 | )
21 |
22 | data = [trace]
23 | iplot(data)
--------------------------------------------------------------------------------
/test/mocks/jupyter_examples/example_4.py:
--------------------------------------------------------------------------------
1 | x = raw_input("heeey")
2 | print(x) # should print whatever you input
3 |
--------------------------------------------------------------------------------
/test/mocks/jupyter_examples/example_5.py:
--------------------------------------------------------------------------------
1 | # This should cause a name error
2 | import numpy
3 | import toyplot
4 |
5 | x = numpy.linspace(0, 10)
6 | y = x ** 2
7 |
8 | mark = asdf.plot(x, y)
--------------------------------------------------------------------------------
/test/mocks/jupyter_examples/example_6.py:
--------------------------------------------------------------------------------
1 | from __future__ import unicode_literals
2 | ggplot(mtcars, aes(x='mpg')) + geom_histogram() + xlab("ㅍKorean!")
--------------------------------------------------------------------------------
/test/mocks/jupyter_examples/example_7.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas
3 | columns = ['some', 'column', 'headers']
4 | index = np.arange(103) # array of numbers for the number of samples
5 | df = pandas.DataFrame(columns=columns, index = index)
--------------------------------------------------------------------------------
/test/mocks/jupyter_examples/example_8.py:
--------------------------------------------------------------------------------
1 | import pandas
2 | data = {'height' : [5.6, 7.0, 4.9, 6.7, 5.2, 5.5, 6.1, 5.4],
3 | 'age' : [15, 21, 15, 20, 22, 41, 18, 38]}
4 | z = pandas.DataFrame(data)
5 |
6 | data = {'what' : [5.6, 5.2, 5.5, 6.1, 5.4],
7 | 'where' : [15, 21, 15, 18, 38]}
8 | y = pandas.DataFrame(data)
9 |
--------------------------------------------------------------------------------
/test/node/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const bluebird = require('bluebird'),
4 | chai = require('chai'),
5 | electron = require('electron'),
6 | ipcMainRemote = electron.remote.ipcMain;
7 |
8 | // output the logs to the console when running tests (in karma)
9 | ipcMainRemote.on('console-log', function (event, msg) {
10 | console.log(msg);
11 | });
12 |
13 | bluebird.config({
14 | warnings: true,
15 | longStackTraces: true,
16 | cancellation: true,
17 | monitoring: true
18 | });
19 |
20 | // defaults for chai
21 | chai.config.showDiff = true;
22 | chai.config.truncateThreshold = 0;
23 |
24 | // jquery sees module and thinks it's not a browser
25 | window.$ = window.jQuery = require('../../node_modules/jquery/dist/jquery');
26 |
--------------------------------------------------------------------------------
/watch.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | while [ 1 ]
4 | do
5 | # Every half second attempt to recompile the static assets.
6 | # make will only trigger if something has changed.
7 | sleep '0.5'
8 | make | grep -v 'Nothing to be done for `all.'
9 | done
10 |
--------------------------------------------------------------------------------