diff --git a/src/api/clearlyDefined.js b/src/api/clearlyDefined.js index 8da2f9e1..affa6e83 100644 --- a/src/api/clearlyDefined.js +++ b/src/api/clearlyDefined.js @@ -17,6 +17,7 @@ export const BROWSE = 'browse' export const ORIGINS_GITHUB = 'origins/github' export const ORIGINS_NPM = 'origins/npm' export const ORIGINS_NUGET = 'origins/nuget' +export const ORIGINS_CONDA = 'origins/conda' export const ORIGINS_CRATE = 'origins/crate' export const ORIGINS_MAVEN = 'origins/maven' export const ORIGINS_PYPI = 'origins/pypi' @@ -28,6 +29,7 @@ export const ORIGINS = { github: { git: ORIGINS_GITHUB }, npmjs: { npm: ORIGINS_NPM }, nuget: { nuget: ORIGINS_NUGET }, + conda: { conda: ORIGINS_CONDA, condasource: ORIGINS_CONDA }, cratesio: { crate: ORIGINS_CRATE }, mavencentral: { maven: ORIGINS_MAVEN, sourcearchive: ORIGINS_MAVEN }, pypi: { pypi: ORIGINS_PYPI }, @@ -188,6 +190,14 @@ export function getRubyGemsRevisions(token, path) { return get(url(`${ORIGINS_RUBYGEMS}/${path}/revisions`), token) } +export function getCondaSearch(token, path) { + return get(url(`${ORIGINS_CONDA}/${path}`), token) +} + +export function getCondaRevisions(token, path) { + return get(url(`${ORIGINS_CONDA}/${path}/revisions`), token) +} + export function getCrateSearch(token, path) { return get(url(`${ORIGINS_CRATE}/${path}`), token) } diff --git a/src/components/DefinitionEntry.js b/src/components/DefinitionEntry.js index c4bd4646..f01655a8 100644 --- a/src/components/DefinitionEntry.js +++ b/src/components/DefinitionEntry.js @@ -11,6 +11,7 @@ import git from '../images/Git-Logo-2Color.png' import npm from '../images/n-large.png' import pypi from '../images/pypi.png' import gem from '../images/gem.png' +import conda from '../images/conda.svg' import cargo from '../images/cargo.png' import nuget from '../images/nuget.svg' import debian from '../images/debian.png' @@ -453,6 +454,7 @@ class DefinitionEntry extends React.Component { getImage(definition) { if (definition.coordinates.type === 'git') return git if (definition.coordinates.type === 'npm') return npm + if (definition.coordinates.type === 'conda') return conda if (definition.coordinates.type === 'crate') return cargo if (definition.coordinates.type === 'pypi') return pypi if (definition.coordinates.type === 'gem') return gem diff --git a/src/components/FilterBar.js b/src/components/FilterBar.js index f3c28585..8fd535f3 100644 --- a/src/components/FilterBar.js +++ b/src/components/FilterBar.js @@ -10,6 +10,7 @@ import maven from '../images/maven.png' import nuget from '../images/nuget.png' import pod from '../images/pod.png' import git from '../images/Git-Logo-2Color.png' +import conda from '../images/conda.svg' import crate from '../images/cargo.png' import gem from '../images/gem.png' import pypi from '../images/pypi.png' @@ -23,6 +24,7 @@ const types = { maven: maven, nuget: nuget, git: git, + conda: conda, crate: crate, pod: pod, deb: debian, diff --git a/src/components/HarvestQueueList.js b/src/components/HarvestQueueList.js index a2f62ae4..47af160c 100644 --- a/src/components/HarvestQueueList.js +++ b/src/components/HarvestQueueList.js @@ -11,6 +11,7 @@ import { NpmVersionPicker, MavenVersionPicker, PyPiVersionPicker, + CondaVersionPicker, CrateVersionPicker, DebianVersionPicker, NuGetVersionPicker, @@ -25,6 +26,9 @@ import npm from '../images/n-large.png' import pypi from '../images/pypi.png' import debian from '../images/debian.png' import gem from '../images/gem.png' +import anaconda_main from '../images/anaconda-main.svg' +import anaconda_r from '../images/anaconda-r.png' +import conda_forge from '../images/conda-forge.png' import cargo from '../images/cargo.png' import maven from '../images/maven.png' import nuget from '../images/nuget.png' @@ -84,6 +88,15 @@ class HarvestQueueList extends React.Component { onChange={this.commitChanged.bind(this, request)} /> )} + {request.provider === 'anaconda-main' && ( + + )} + {request.provider === 'anaconda-r' && ( + + )} + {request.provider === 'cratesio' && ( + + )} {request.provider === 'npmjs' && ( )} @@ -96,6 +109,9 @@ class HarvestQueueList extends React.Component { {request.provider === 'rubygems' && ( )} + {request.provider === 'conda-forge' && ( + + )} {request.provider === 'cratesio' && ( )} @@ -150,6 +166,9 @@ class HarvestQueueList extends React.Component { if (request.provider === 'npmjs') return npm if (request.provider === 'pypi') return pypi if (request.provider === 'rubygems') return gem + if (request.provider === 'anaconda-main') return anaconda_main + if (request.provider === 'anaconda-r') return anaconda_r + if (request.provider === 'conda-forge') return conda_forge if (request.provider === 'cratesio') return cargo if (request.provider === 'mavencentral') return maven if (request.provider === 'nuget') return nuget diff --git a/src/components/Navigation/Pages/PageHarvest/PageHarvest.js b/src/components/Navigation/Pages/PageHarvest/PageHarvest.js index 0cf346e1..c7c5edfd 100644 --- a/src/components/Navigation/Pages/PageHarvest/PageHarvest.js +++ b/src/components/Navigation/Pages/PageHarvest/PageHarvest.js @@ -12,6 +12,7 @@ import { NpmSelector, MavenSelector, NuGetSelector, + CondaSelector, CrateSelector, DebianSelector, ComposerSelector, @@ -114,11 +115,14 @@ class PageHarvest extends Component { {this.renderProviderButtons()} + {activeProvider.value === 'anaconda-main' && } + {activeProvider.value === 'anaconda-r' && } {activeProvider.value === 'github' && } {activeProvider.value === 'mavencentral' && } {activeProvider.value === 'npmjs' && } {activeProvider.value === 'nuget' && } {activeProvider.value === 'cratesio' && } + {activeProvider.value === 'conda-forge' && } {activeProvider.value === 'packagist' && } {activeProvider.value === 'pypi' && } {activeProvider.value === 'rubygems' && } diff --git a/src/components/Navigation/Pages/PageStats/PageStats.js b/src/components/Navigation/Pages/PageStats/PageStats.js index 599db4f4..fbb3c968 100644 --- a/src/components/Navigation/Pages/PageStats/PageStats.js +++ b/src/components/Navigation/Pages/PageStats/PageStats.js @@ -13,6 +13,7 @@ import maven from '../../../../images/maven.png' import nuget from '../../../../images/nuget.png' import pod from '../../../../images/pod.png' import git from '../../../../images/Git-Logo-2Color.png' +import conda from '../../../../images/conda.svg' import crate from '../../../../images/cargo.png' import composer from '../../../../images/packagist.png' import gem from '../../../../images/gem.png' @@ -34,6 +35,7 @@ const types = { maven: maven, nuget: nuget, git: git, + conda: conda, crate: crate, deb: debian, debsrc: debian, diff --git a/src/components/Providers/Selectors/CondaSelector.js b/src/components/Providers/Selectors/CondaSelector.js new file mode 100644 index 00000000..4dafeb1a --- /dev/null +++ b/src/components/Providers/Selectors/CondaSelector.js @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation and others. Licensed under the MIT license. +// SPDX-License-Identifier: MIT + +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import { getCondaSearch } from '../../../api/clearlyDefined' +import { AsyncTypeahead } from 'react-bootstrap-typeahead' +import searchSvg from '../../../images/icons/searchSvg.svg' + +export default class CondaSelector extends Component { + static propTypes = { + onChange: PropTypes.func + } + + constructor(props) { + super(props) + this.state = { isLoading: false, options: [], focus: false } + this.getOptions = this.getOptions.bind(this) + this.onChange = this.onChange.bind(this) + } + + onChange(values) { + const { onChange } = this.props + const value = values.length === 0 ? null : values[0] + value && onChange && onChange({ type: 'conda', provider: this.props.provider, name: value.id }, 'package') + } + + async getOptions(value) { + try { + this.setState({ ...this.state, isLoading: true }) + console.log(`value: ${value}, provider: ${this.props.provider}`) + const options = await getCondaSearch(this.props.token, `${value}/${this.props.provider}`) + this.setState({ ...this.state, options, isLoading: false }) + } catch (error) { + this.setState({ ...this.state, options: [], isLoading: false }) + } + } + + render() { + const { options, isLoading, focus } = this.state + return ( +
+
+ search +
+ this.setState({ ...this.state, focus: true })} + onBlur={() => this.setState({ ...this.state, focus: false })} + clearButton + highlightOnlyResult + emptyLabel="" + selectHintOnEnter + isLoading={isLoading} + onSearch={this.getOptions} + /> +
+ ) + } +} diff --git a/src/components/Providers/VersionPickers/CondaVersionPicker.js b/src/components/Providers/VersionPickers/CondaVersionPicker.js new file mode 100644 index 00000000..6aaf7ff1 --- /dev/null +++ b/src/components/Providers/VersionPickers/CondaVersionPicker.js @@ -0,0 +1,77 @@ +// Copyright (c) Microsoft Corporation and others. Licensed under the MIT license. +// SPDX-License-Identifier: MIT + +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import { getCondaRevisions } from '../../../api/clearlyDefined' +import Autocomplete from '../../Navigation/Ui/Autocomplete' + +export default class CondaVersionPicker extends Component { + static propTypes = { + onChange: PropTypes.func, + request: PropTypes.object.isRequired, + defaultInputValue: PropTypes.string + } + + constructor(props) { + super(props) + this.state = { customValues: [], options: [] } + this.onChange = this.onChange.bind(this) + this.filter = this.filter.bind(this) + } + + componentDidMount() { + this.getOptions('') + } + + async getOptions(value) { + try { + console.log(`request: ${this.props.request}`) + const { name, provider } = this.props.request + console.log(`name: ${name}, provider: ${provider}`) + const options = await getCondaRevisions(this.props.token, `${name}/${provider}`) + this.setState({ ...this.state, options }) + } catch (error) { + this.setState({ ...this.state, options: [] }) + } + } + + onChange(values) { + const { onChange } = this.props + if (!onChange) return + let value = values.length === 0 ? null : values[0] + if (!value) return onChange(value) + if (value.customOption) { + value = value.label + this.setState({ ...this.state, customValues: [...this.state.customValues, value] }) + } + onChange(value) + } + + filter(option, props) { + if (this.props.request.revision) return true + return option.toLowerCase().indexOf(props.text.toLowerCase()) !== -1 + } + + render() { + const { defaultInputValue } = this.props + const { customValues, options } = this.state + const list = customValues.concat(options) + return ( + + ) + } +} diff --git a/src/components/index.js b/src/components/index.js index d4bd0136..42f3994e 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -2,92 +2,96 @@ // SPDX-License-Identifier: MIT export { default as App } -from './App' + from './App' export { default as Clearly } -from './Clearly' + from './Clearly' export { default as ComponentList } -from './ComponentList' + from './ComponentList' export { default as ContributePrompt } -from './ContributePrompt' + from './ContributePrompt' export { default as CopyUrlButton } -from './CopyUrlButton' + from './CopyUrlButton' +export { default as CondaSelector } + from './Providers/Selectors/CondaSelector' +export { default as CondaVersionPicker } + from './Providers/VersionPickers/CondaVersionPicker' export { default as CrateSelector } -from './Providers/Selectors/CrateSelector' + from './Providers/Selectors/CrateSelector' export { default as CrateVersionPicker } -from './Providers/VersionPickers/CrateVersionPicker' + from './Providers/VersionPickers/CrateVersionPicker' export { default as DebianSelector } -from './Providers/Selectors/DebianSelector' + from './Providers/Selectors/DebianSelector' export { default as DebianVersionPicker } -from './Providers/VersionPickers/DebianVersionPicker' + from './Providers/VersionPickers/DebianVersionPicker' export { default as ComposerSelector } -from './Providers/Selectors/ComposerSelector' + from './Providers/Selectors/ComposerSelector' export { default as ComposerVersionPicker } -from './Providers/VersionPickers/ComposerVersionPicker' + from './Providers/VersionPickers/ComposerVersionPicker' export { default as DefinitionEntry } -from './DefinitionEntry' + from './DefinitionEntry' export { default as FieldGroup } -from './FieldGroup' + from './FieldGroup' export { default as FileCountRenderer } -from './FileCountRenderer' + from './FileCountRenderer' export { default as FilterBar } -from './FilterBar' + from './FilterBar' export { default as Footer } -from './Footer' + from './Footer' export { default as GitHubCommitPicker } -from './Providers/VersionPickers/GitHubCommitPicker' + from './Providers/VersionPickers/GitHubCommitPicker' export { default as GitHubSelector } -from './Providers/Selectors/GitHubSelector' + from './Providers/Selectors/GitHubSelector' export { default as HarvestQueueList } -from './HarvestQueueList' + from './HarvestQueueList' export { default as Header } -from './Header' + from './Header' export { default as InfiniteList } -from './InfiniteList' + from './InfiniteList' export { default as InlineEditor } -from './InlineEditor' + from './InlineEditor' export { default as ModalEditor } -from './ModalEditor' + from './ModalEditor' export { default as SourcePicker } -from './SourcePicker' + from './SourcePicker' export { default as MavenSelector } -from './Providers/Selectors/MavenSelector' + from './Providers/Selectors/MavenSelector' export { default as MavenVersionPicker } -from './Providers/VersionPickers/MavenVersionPicker' + from './Providers/VersionPickers/MavenVersionPicker' export { default as NotificationList } -from './NotificationList' + from './NotificationList' export { default as NpmSelector } -from './Providers/Selectors/NpmSelector' + from './Providers/Selectors/NpmSelector' export { default as NpmVersionPicker } -from './Providers/VersionPickers/NpmVersionPicker' + from './Providers/VersionPickers/NpmVersionPicker' export { default as NuGetSelector } -from './Providers/Selectors/NuGetSelector' + from './Providers/Selectors/NuGetSelector' export { default as NuGetVersionPicker } -from './Providers/VersionPickers/NuGetVersionPicker' + from './Providers/VersionPickers/NuGetVersionPicker' export { default as PyPiSelector } -from './Providers/Selectors/PyPiSelector' + from './Providers/Selectors/PyPiSelector' export { default as PyPiVersionPicker } -from './Providers/VersionPickers/PyPiVersionPicker' + from './Providers/VersionPickers/PyPiVersionPicker' export { default as RubyGemsSelector } -from './Providers/Selectors/RubyGemsSelector' + from './Providers/Selectors/RubyGemsSelector' export { default as RubyGemsVersionPicker } -from './Providers/VersionPickers/RubyGemsVersionPicker' + from './Providers/VersionPickers/RubyGemsVersionPicker' export { default as CocoaPodsSelector } -from './Providers/Selectors/CocoaPodsSelector' + from './Providers/Selectors/CocoaPodsSelector' export { default as CocoaPodsVersionPicker } -from './Providers/VersionPickers/CocoaPodsVersionPicker' + from './Providers/VersionPickers/CocoaPodsVersionPicker' export { default as PageAbout } -from './PageAbout' + from './PageAbout' export { default as RehydrationProvider } -from './RehydrationProvider' + from './RehydrationProvider' export { default as RowEntityList } -from './RowEntityList' + from './RowEntityList' export { default as Section } -from './Section' + from './Section' export { default as SocialIcons } -from './SocialIcons' + from './SocialIcons' export { default as SpdxPicker } -from './SpdxPicker' + from './SpdxPicker' export { default as TwoLineEntry } -from './TwoLineEntry' + from './TwoLineEntry' export { default as QuickEditModel } -from './QuickEditModel' + from './QuickEditModel' diff --git a/src/images/anaconda-main.svg b/src/images/anaconda-main.svg new file mode 100644 index 00000000..aea6b8cc --- /dev/null +++ b/src/images/anaconda-main.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/images/anaconda-r.png b/src/images/anaconda-r.png new file mode 100644 index 00000000..2f720fd5 Binary files /dev/null and b/src/images/anaconda-r.png differ diff --git a/src/images/conda-forge.png b/src/images/conda-forge.png new file mode 100644 index 00000000..25619488 Binary files /dev/null and b/src/images/conda-forge.png differ diff --git a/src/images/conda.svg b/src/images/conda.svg new file mode 100644 index 00000000..3ad2de74 --- /dev/null +++ b/src/images/conda.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/utils/contribution.js b/src/utils/contribution.js index e2c79631..bda79b2f 100644 --- a/src/utils/contribution.js +++ b/src/utils/contribution.js @@ -15,6 +15,9 @@ import github from '../images/GitHub-Mark-120px-plus.png' import npm from '../images/n-large.png' import pypi from '../images/pypi.png' import gem from '../images/gem.png' +import anaconda_r from '../images/anaconda-r.png' +import anaconda_main from '../images/anaconda-main.svg' +import conda_forge from '../images/conda-forge.png' import cargo from '../images/cargo.png' import nuget from '../images/nuget.svg' import debian from '../images/debian.png' @@ -208,6 +211,10 @@ export default class Contribution { */ static getImage(item) { switch (item.coordinates.provider) { + case 'anaconda-main': + return anaconda_main + case 'anaconda-r': + return anaconda_r case 'github': return github case 'npmjs': @@ -216,6 +223,8 @@ export default class Contribution { return pypi case 'rubygems': return gem + case 'conda-forge': + return conda_forge case 'cratesio': return cargo case 'packagist': diff --git a/src/utils/utils.js b/src/utils/utils.js index 30c0b923..42fe1b60 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -1,11 +1,14 @@ // Copyright (c) Microsoft Corporation and others. Licensed under the MIT license. // SPDX-License-Identifier: MIT +import anacondaMainImage from '../images/anaconda-main.svg' +import anacondaRImage from '../images/anaconda-r.png' import deepDiff from 'deep-diff' import npmImage from '../images/n-large.png' import mavenImage from '../images/maven.png' import nugetImage from '../images/nuget.svg' import podImage from '../images/pod.png' import gitImage from '../images/Git-Logo-2Color.png' +import condaForgeImage from '../images/conda-forge.png' import crateImage from '../images/cargo.png' import gemImage from '../images/gem.png' import pypiImage from '../images/pypi.png' @@ -108,6 +111,7 @@ const curateFilters = [ const types = [ { value: 'composer', label: 'Composer', provider: 'packagist' }, { value: 'pod', label: 'Pod', provider: 'cocoapods' }, + { value: 'conda', label: 'Conda', provider: 'conda-forge' }, { value: 'crate', label: 'Crate', provider: 'cratesio' }, { value: 'git', label: 'Git', provider: 'github' }, { value: 'maven', label: 'Maven', provider: 'mavencentral' }, @@ -121,6 +125,8 @@ const types = [ ] const providers = [ + { value: 'anaconda-main', label: 'Anaconda /main', image: anacondaMainImage, type: 'conda' }, + { value: 'anaconda-r', label: 'Anaconda /r', image: anacondaRImage, type: 'conda' }, { value: 'npmjs', label: 'NpmJS', image: npmImage, type: 'npm' }, { value: 'github', label: 'GitHub', image: gitImage, type: 'git' }, { value: 'mavencentral', label: 'MavenCentral', image: mavenImage, type: 'maven' }, @@ -128,6 +134,7 @@ const providers = [ { value: 'pypi', label: 'PyPI', image: pypiImage, type: 'pypi' }, { value: 'rubygems', label: 'RubyGems', image: gemImage, type: 'gem' }, { value: 'cocoapods', label: 'CocoaPods', image: podImage, type: 'pod' }, + { value: 'conda-forge', label: 'Conda-Forge', image: condaForgeImage, type: 'conda' }, { value: 'cratesio', label: 'Crates.io', image: crateImage, type: 'crate' }, { value: 'debian', label: 'Debian', image: debianImage, type: 'deb' }, { value: 'packagist', label: 'Packagist', image: composerImage, type: 'composer' }