Skip to content

Commit f8ed3c3

Browse files
Merge pull request #984 from clearlydefined/master
Update prod with latest changes
2 parents 56e3738 + 8ac858f commit f8ed3c3

File tree

15 files changed

+249
-48
lines changed

15 files changed

+249
-48
lines changed

src/api/clearlyDefined.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export const ORIGINS_PYPI = 'origins/pypi'
2323
export const ORIGINS_RUBYGEMS = 'origins/rubygems'
2424
export const ORIGINS_DEBIAN = 'origins/deb'
2525
export const ORIGINS_COMPOSER = 'origins/composer'
26+
export const ORIGINS_POD = 'origins/pod'
2627
export const ORIGINS = {
2728
github: { git: ORIGINS_GITHUB },
2829
npmjs: { npm: ORIGINS_NPM },
@@ -32,7 +33,8 @@ export const ORIGINS = {
3233
pypi: { pypi: ORIGINS_PYPI },
3334
rubygems: { gem: ORIGINS_RUBYGEMS },
3435
debian: { deb: ORIGINS_DEBIAN, debsrc: ORIGINS_DEBIAN },
35-
packagist: { composer: ORIGINS_COMPOSER }
36+
packagist: { composer: ORIGINS_COMPOSER },
37+
cocoapods: { pod: ORIGINS_POD }
3638
}
3739

3840
export function getHarvestResults(token, entity) {
@@ -218,6 +220,14 @@ export function getComposerRevisions(token, path) {
218220
return get(url(`${ORIGINS_COMPOSER}/${path}/revisions`), token)
219221
}
220222

223+
export function getCocoaPodsSearch(token, path) {
224+
return get(url(`${ORIGINS_POD}/${path}`), token)
225+
}
226+
227+
export function getCocoaPodsRevisions(token, path) {
228+
return get(url(`${ORIGINS_POD}/${path}/revisions`), token)
229+
}
230+
221231
export function getRevisions(token, path, type, provider) {
222232
const origin = _.get(ORIGINS, `${provider}.${type}`)
223233
return get(url(`${origin}/${path}/revisions`), token)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// (c) Copyright 2022, SAP SE and ClearlyDefined contributors. Licensed under the MIT license.
2+
// SPDX-License-Identifier: MIT
3+
4+
import React, { Component } from 'react'
5+
import PropTypes from 'prop-types'
6+
import { getCocoaPodsSearch } from '../api/clearlyDefined'
7+
import { AsyncTypeahead } from 'react-bootstrap-typeahead'
8+
import searchSvg from '../images/icons/searchSvg.svg'
9+
import 'react-bootstrap-typeahead/css/Typeahead.css'
10+
11+
export default class CocoaPodsSelector extends Component {
12+
static propTypes = {
13+
onChange: PropTypes.func
14+
}
15+
16+
constructor(props) {
17+
super(props)
18+
this.state = { isLoading: false, options: [], focus: true }
19+
this.getOptions = this.getOptions.bind(this)
20+
this.onChange = this.onChange.bind(this)
21+
}
22+
23+
onChange(values) {
24+
const { onChange } = this.props
25+
const value = values.length === 0 ? null : values[0]
26+
value && onChange && onChange({ type: 'pod', provider: 'cocoapods', name: value.id }, 'package')
27+
}
28+
29+
async getOptions(value) {
30+
try {
31+
this.setState({ ...this.state, isLoading: true })
32+
const options = await getCocoaPodsSearch(this.props.token, value)
33+
this.setState({ ...this.state, options, isLoading: false })
34+
} catch (error) {
35+
this.setState({ ...this.state, options: [], isLoading: false })
36+
}
37+
}
38+
39+
render() {
40+
const { options, isLoading, focus } = this.state
41+
return (
42+
<div className={`harvest-searchbar ${focus ? 'active' : ''}`}>
43+
<div className="search-logo">
44+
<img src={searchSvg} alt="search" />
45+
</div>
46+
<AsyncTypeahead
47+
id="pod-selector"
48+
className="harvest-search"
49+
useCache={false}
50+
options={options}
51+
placeholder={'Pick a CocoaPod to harvest'}
52+
onChange={this.onChange}
53+
labelKey="id"
54+
onFocus={() => this.setState({ ...this.state, focus: true })}
55+
onBlur={() => this.setState({ ...this.state, focus: false })}
56+
clearButton
57+
highlightOnlyResult
58+
emptyLabel=""
59+
selectHintOnEnter
60+
isLoading={isLoading}
61+
onSearch={this.getOptions}
62+
/>
63+
</div>
64+
)
65+
}
66+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// (c) Copyright 2022, SAP SE and ClearlyDefined contributors. Licensed under the MIT license.
2+
// SPDX-License-Identifier: MIT
3+
4+
import React, { Component } from 'react'
5+
import PropTypes from 'prop-types'
6+
import { getCocoaPodsRevisions } from '../api/clearlyDefined'
7+
import Autocomplete from './Navigation/Ui/Autocomplete'
8+
import searchSvg from '../images/icons/searchSvg.svg'
9+
10+
export default class CocoaPodsVersionPicker extends Component {
11+
static propTypes = {
12+
onChange: PropTypes.func,
13+
request: PropTypes.object.isRequired,
14+
defaultInputValue: PropTypes.string
15+
}
16+
17+
constructor(props) {
18+
super(props)
19+
this.state = {
20+
customValues: [],
21+
options: [],
22+
focus: false
23+
}
24+
this.onChange = this.onChange.bind(this)
25+
this.filter = this.filter.bind(this)
26+
}
27+
28+
componentDidMount() {
29+
this.getOptions('')
30+
}
31+
32+
async getOptions(value) {
33+
try {
34+
const { name } = this.props.request
35+
const options = await getCocoaPodsRevisions(this.props.token, name)
36+
this.setState({ ...this.state, options })
37+
} catch (error) {
38+
this.setState({ ...this.state, options: [] })
39+
}
40+
}
41+
42+
onChange(values) {
43+
const { onChange } = this.props
44+
if (!onChange) return
45+
let value = values.length === 0 ? null : values[0]
46+
if (!value) return onChange(value)
47+
if (value.customOption) {
48+
value = value.label
49+
this.setState({ ...this.state, customValues: [...this.state.customValues, value] })
50+
}
51+
onChange(value)
52+
}
53+
54+
filter(option, props) {
55+
if (this.props.request.revision) return true
56+
return option.toLowerCase().indexOf(props.text.toLowerCase()) !== -1
57+
}
58+
59+
render() {
60+
const { defaultInputValue, request } = this.props
61+
const selected = request.revision ? [request.revision] : []
62+
const { customValues, options, focus } = this.state
63+
const list = customValues.concat(options)
64+
return (
65+
<div className={`harvest-searchbar ${focus ? 'active' : ''}`}>
66+
<div className="search-logo">
67+
<img src={searchSvg} alt="search" />
68+
</div>{' '}
69+
<Autocomplete
70+
id="cocoapods-version-picker"
71+
selected={selected}
72+
options={list}
73+
defaultInputValue={defaultInputValue}
74+
placeholder={
75+
options.length === 0 ? 'Could not fetch versions, type a CocoaPod version' : 'Pick a CocoaPod version'
76+
}
77+
onChange={this.onChange}
78+
onFocus={() => this.setState({ ...this.state, focus: true })}
79+
onBlur={() => this.setState({ ...this.state, focus: false })}
80+
positionFixed
81+
clearButton
82+
allowNew
83+
newSelectionPrefix="Version:"
84+
emptyLabel=""
85+
filterBy={this.filter}
86+
selectHintOnEnter
87+
/>
88+
</div>
89+
)
90+
}
91+
}

src/components/DefinitionEntry.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import nuget from '../images/nuget.svg'
1616
import debian from '../images/debian.png'
1717
import maven from '../images/maven.png'
1818
import composer from '../images/packagist.png'
19+
import pod from '../images/pod.png'
1920
import Contribution from '../utils/contribution'
2021
import Definition from '../utils/definition'
2122
import Curation from '../utils/curation'
@@ -425,6 +426,7 @@ class DefinitionEntry extends React.Component {
425426
<OverlayTrigger
426427
trigger="click"
427428
placement="left"
429+
animation={false}
428430
rootClose
429431
overlay={
430432
<Popover title={title} id={title}>
@@ -455,6 +457,7 @@ class DefinitionEntry extends React.Component {
455457
if (definition.coordinates.type === 'nuget') return nuget
456458
if (definition.coordinates.type === 'deb') return debian
457459
if (definition.coordinates.type === 'composer') return composer
460+
if (definition.coordinates.type === 'pod') return pod
458461
return null
459462
}
460463

src/components/FileList/FileList.js

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import FacetsDropdown from '../../components/FacetsDropdown'
1111
import Contribution from '../../utils/contribution'
1212
import FileListSpec from '../../utils/filelist'
1313
import Attachments from '../../utils/attachments'
14+
import ModalEditor from '../ModalEditor'
15+
import EnhancedLicensePicker from '../../utils/EnhancedLicensePicker'
1416
import folderIcon from '../../images/icons/folder.svg'
1517
import fileIcon from '../../images/icons/file.svg'
1618
import FolderOpenIcon from '@material-ui/icons/FolderOpen'
@@ -235,6 +237,16 @@ export default class FileList extends PureComponent {
235237
onChange(`described.facets.${facet}`, newGlobs)
236238
}
237239

240+
onLicenseChange = (record, license) => {
241+
const { onChange, component, previewDefinition } = this.props
242+
const attributions = Contribution.getValue(component.item, previewDefinition, `files[${record.id}].attributions`)
243+
onChange(`files[${record.id}]`, license, null, license => ({
244+
path: record.path,
245+
license,
246+
...(attributions ? { attributions } : {})
247+
}))
248+
}
249+
238250
onDirectorySelect = e => {
239251
let tempdata = this.state.breadcrumbs
240252
tempdata.push(e)
@@ -281,6 +293,25 @@ export default class FileList extends PureComponent {
281293
)
282294
}
283295

296+
renderLicenseCell = (value, record) => {
297+
const { readOnly, component, previewDefinition } = this.props
298+
const field = `files[${record.id}].license`
299+
const editor = EnhancedLicensePicker
300+
return (
301+
!record.children && (
302+
<ModalEditor
303+
revertable={false}
304+
field={field}
305+
readOnly={readOnly}
306+
initialValue={get(component.item, field)}
307+
value={Contribution.getValue(component.item, previewDefinition, field)}
308+
placeholder={'SPDX license'}
309+
editor={editor}
310+
onChange={license => this.onLicenseChange(record, license)} />
311+
)
312+
)
313+
}
314+
284315
render() {
285316
const { definition, component, previewDefinition } = this.props
286317
const { expandedRows, searchText, filteredFiles, files } = this.state
@@ -359,14 +390,8 @@ export default class FileList extends PureComponent {
359390
// }}
360391
// />
361392
// ),
362-
render: (value, record) => {
363-
let license = Contribution.getValue(component.item, previewDefinition, `files[${record.id}].license`)
364-
return (
365-
!record.children &&
366-
(license ? <p className="text-black">{license}</p> : <p className="text-gray">SPDX license</p>)
367-
)
368-
},
369-
width: '15%'
393+
render: this.renderLicenseCell,
394+
width: '20%'
370395
},
371396
{
372397
title: 'Copyrights',
@@ -376,31 +401,6 @@ export default class FileList extends PureComponent {
376401
// ...this.getColumnSearchProps('attributions'),
377402
render: (value, record) => this.renderCopyrightCell(record, component, previewDefinition),
378403
width: '25%'
379-
},
380-
{
381-
title: '',
382-
dataIndex: 'edit',
383-
key: 'edit',
384-
className: 'edit-data',
385-
// ...this.getColumnSearchProps('attributions'),
386-
render: (value, record) =>
387-
!record.children && (
388-
<svg
389-
className="edit-icon"
390-
width="24"
391-
height="24"
392-
viewBox="0 0 24 24"
393-
fill="none"
394-
xmlns="http://www.w3.org/2000/svg"
395-
>
396-
<path d="M22.5 19.5H1.5V21H22.5V19.5Z" fill="#383A43" />
397-
<path
398-
d="M19.05 6.75C19.65 6.15 19.65 5.25 19.05 4.65L16.35 1.95C15.75 1.35 14.85 1.35 14.25 1.95L3 13.2V18H7.8L19.05 6.75ZM15.3 3L18 5.7L15.75 7.95L13.05 5.25L15.3 3ZM4.5 16.5V13.8L12 6.3L14.7 9L7.2 16.5H4.5Z"
399-
fill="#383A43"
400-
/>
401-
</svg>
402-
),
403-
width: '5%'
404404
}
405405
]
406406

src/components/Footer.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,11 @@ export default class Footer extends Component {
3434
<SocialIcons className="clearly-footer-socials pb-2" entity={socials} />
3535
<div className="col-md-8">
3636
<p class="mb-0">
37-
ClearlyDefined was created by
38-
<Link to="/" className="mx-1 highlighted-link-blue">Microsoft</Link>
39-
in partnership with the
40-
<Link to="/" className="mx-1 highlighted-link-blue">Open Source Initiative.</Link>
37+
ClearlyDefined is an
38+
<a href="https://opensource.org" className="mx-1 highlighted-link-blue">OSI</a> incubator project,
39+
originally contributed with ❤️ by
40+
<a href="https://opensource.microsoft.com" className="mx-1 highlighted-link-blue">Microsoft</a>
41+
and maintained by a growing community.
4142
</p>
4243
</div>
4344
<div className="col-md-4 footer-links col-12 ml-md-auto mt-md-0 mt-4">

src/components/HarvestQueueList.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ import {
1515
DebianVersionPicker,
1616
NuGetVersionPicker,
1717
RubyGemsVersionPicker,
18-
ComposerVersionPicker
18+
ComposerVersionPicker,
19+
CocoaPodsVersionPicker
1920
} from './'
2021
import { getGitHubRevisions } from '../api/clearlyDefined'
2122
import { clone } from 'lodash'
@@ -28,6 +29,7 @@ import cargo from '../images/cargo.png'
2829
import maven from '../images/maven.png'
2930
import nuget from '../images/nuget.png'
3031
import composer from '../images/packagist.png'
32+
import pod from '../images/pod.png'
3133

3234
class HarvestQueueList extends React.Component {
3335
static propTypes = {
@@ -39,7 +41,7 @@ class HarvestQueueList extends React.Component {
3941
}
4042

4143
static defaultProps = {
42-
loadMoreRows: () => {}
44+
loadMoreRows: () => { }
4345
}
4446

4547
constructor(props) {
@@ -106,6 +108,9 @@ class HarvestQueueList extends React.Component {
106108
{request.provider === 'packagist' && (
107109
<ComposerVersionPicker request={request} onChange={this.versionChanged.bind(this, request)} />
108110
)}
111+
{request.provider === 'cocoapods' && (
112+
<CocoaPodsVersionPicker request={request} onChange={this.versionChanged.bind(this, request)} />
113+
)}
109114
<i className="fas fa-times list-trash" onClick={this.removeRequest.bind(this, request)} />
110115
</div>
111116
)
@@ -150,6 +155,7 @@ class HarvestQueueList extends React.Component {
150155
if (request.provider === 'nuget') return nuget
151156
if (request.provider === 'debian') return debian
152157
if (request.provider === 'packagist') return composer
158+
if (request.provider === 'cocoapods') return pod
153159
return null
154160
}
155161

@@ -161,7 +167,7 @@ class HarvestQueueList extends React.Component {
161167
renderRow({ index, key, style }) {
162168
const { list } = this.props
163169
const request = list[index]
164-
const clickHandler = () => {}
170+
const clickHandler = () => { }
165171
return (
166172
<div key={key} style={style} className="component-row">
167173
<TwoLineEntry

0 commit comments

Comments
 (0)