mirror of https://github.com/Qiskit/qiskit.org.git
Allow filtering events with multiple types (#519)
This commit is contained in:
parent
a7a3c31a5c
commit
7d1c836e1f
|
@ -33,7 +33,7 @@
|
|||
- Randomized Benchmarking
|
||||
- Measuring Quantum Volume
|
||||
### Chapter 6. Investigating Quantum Hardware Using Microwave Pulses
|
||||
- Calibrating Qubits with OpenPulse
|
||||
- Calibrating Qubits with Qiskit Pulse
|
||||
- Accessing Higher Energy States
|
||||
### Chapter 7. Demos
|
||||
- Estimating Pi Using Quantum Phase Estimation Algorithm
|
||||
### Chapter 7. Problem Sets & Exercises
|
||||
### Chapter 8. Games & Demos
|
||||
|
|
|
@ -1,75 +1,85 @@
|
|||
[
|
||||
{
|
||||
"title": "Hackathon @ Harvard",
|
||||
"type": "Hackathon",
|
||||
"image": "/images/events/promo-finland-unconference.jpg",
|
||||
"types": [
|
||||
"Hackathon",
|
||||
"Camp"
|
||||
],
|
||||
"image": "/images/events/no-picture.jpg",
|
||||
"place": "Boston, MA",
|
||||
"location": "America",
|
||||
"location": "Americas",
|
||||
"date": "April 2-3, 2020"
|
||||
},
|
||||
{
|
||||
"title": "Yale YQI Roundtable event",
|
||||
"type": "Conference",
|
||||
"image": "/images/events/promo-asia.jpg",
|
||||
"types": [
|
||||
"Conference",
|
||||
"Hackathon"
|
||||
],
|
||||
"image": "/images/events/no-picture.jpg",
|
||||
"place": "New Haven, CT",
|
||||
"location": "Asia",
|
||||
"date": "April 2, 2020",
|
||||
"to": "/events/asia"
|
||||
"location": "Asia Pacific",
|
||||
"date": "April 2, 2020"
|
||||
},
|
||||
{
|
||||
"title": "CQE Recruiting Forum",
|
||||
"type": "Conference",
|
||||
"image": "/images/events/promo-asia.jpg",
|
||||
"types": [
|
||||
"Conference"
|
||||
],
|
||||
"image": "/images/events/no-picture.jpg",
|
||||
"place": "Chicago, IL",
|
||||
"location": "Africa",
|
||||
"location": "Online",
|
||||
"date": "April 1, 2020"
|
||||
},
|
||||
{
|
||||
"title": "Hackathon @ Uni College Dublin",
|
||||
"type": "Hackathon",
|
||||
"image": "/images/events/promo-finland-unconference.jpg",
|
||||
"types": [
|
||||
"Hackathon"
|
||||
],
|
||||
"image": "/images/events/no-picture.jpg",
|
||||
"place": "Dublin, Ireland",
|
||||
"location": "Asia Pacific",
|
||||
"location": "Online",
|
||||
"date": "March 28, 2020"
|
||||
},
|
||||
{
|
||||
"title": "Q Meetup in Bangkok",
|
||||
"type": "Conference",
|
||||
"image": "/images/events/promo-finland-unconference.jpg",
|
||||
"types": [
|
||||
"Conference"
|
||||
],
|
||||
"image": "/images/events/no-picture.jpg",
|
||||
"place": "Bangkok, Thailand",
|
||||
"location": "Europe",
|
||||
"location": "Asia Pacific",
|
||||
"date": "March 26-31, 2020"
|
||||
},
|
||||
{
|
||||
"title": "NSBE Annual Convention",
|
||||
"type": "Conference",
|
||||
"image": "/images/events/promo-vermont.jpg",
|
||||
"types": [
|
||||
"Conference"
|
||||
],
|
||||
"image": "/images/events/no-picture.jpg",
|
||||
"place": "San Antonio, TX",
|
||||
"location": "Africa",
|
||||
"location": "Americas",
|
||||
"date": "March 25-29, 2020",
|
||||
"to": "http://convention.nsbe.org"
|
||||
},
|
||||
{
|
||||
"title": "Hack-Q-Thon (NYC High School Hackathon)",
|
||||
"type": "Hackathon",
|
||||
"image": "/images/events/promo-finland-unconference.jpg",
|
||||
"types": [
|
||||
"Hackathon"
|
||||
],
|
||||
"image": "/images/events/no-picture.jpg",
|
||||
"place": "NYU Campus, NY",
|
||||
"location": "Europe",
|
||||
"location": "Asia Pacific",
|
||||
"date": "March 21, 2020"
|
||||
},
|
||||
{
|
||||
"title": "Hackathon @ Uni College London",
|
||||
"type": "Hackathon",
|
||||
"image": "/images/events/promo-vermont.jpg",
|
||||
"types": [
|
||||
"Hackathon"
|
||||
],
|
||||
"image": "/images/events/no-picture.jpg",
|
||||
"place": "London, England",
|
||||
"location": "Africa",
|
||||
"location": "Online",
|
||||
"date": "March 19-20, 2020"
|
||||
},
|
||||
{
|
||||
"title": "Qiskit Camp 2020 (NY)",
|
||||
"type": "Camp",
|
||||
"image": "/images/events/promo-finland-unconference.jpg",
|
||||
"location": "Europe",
|
||||
"date": "March 10-13, 2020"
|
||||
}
|
||||
]
|
|
@ -1,16 +1,20 @@
|
|||
[
|
||||
{
|
||||
"title": "Hackathon @ Princeton",
|
||||
"type": "Hackathon",
|
||||
"image": "/images/events/promo-vermont.jpg",
|
||||
"types": [
|
||||
"Hackathon"
|
||||
],
|
||||
"image": "/images/events/no-picture.jpg",
|
||||
"place": "Princeton, NJ",
|
||||
"location": "Africa",
|
||||
"location": "Europe",
|
||||
"date": "April 18-19, 2020"
|
||||
},
|
||||
{
|
||||
"title": "Hackathon @ Stanford",
|
||||
"type": "Hackathon",
|
||||
"image": "/images/events/promo-finland-unconference.jpg",
|
||||
"types": [
|
||||
"Hackathon"
|
||||
],
|
||||
"image": "/images/events/no-picture.jpg",
|
||||
"place": "Stanford, CA",
|
||||
"location": "Online",
|
||||
"date": "May 1-2, 2020"
|
||||
|
|
|
@ -5,7 +5,8 @@ import {
|
|||
CommunityEvent,
|
||||
CommunityEventType,
|
||||
WorldLocation,
|
||||
LOCATION_CATEGORIES
|
||||
LOCATION_CATEGORIES,
|
||||
TYPE_CATEGORIES
|
||||
} from '../store/modules/events'
|
||||
|
||||
const RECORD_FIELDS = {
|
||||
|
@ -42,7 +43,7 @@ async function fetchCommunityEvents (apiKey: string, { days }): Promise<Communit
|
|||
function convertToCommunityEvent (record: any): CommunityEvent {
|
||||
return {
|
||||
title: getName(record),
|
||||
type: getType(record),
|
||||
types: getTypes(record),
|
||||
image: getImage(record),
|
||||
place: getPlace(record),
|
||||
location: getLocation(record),
|
||||
|
@ -55,17 +56,16 @@ function getName (record: any): string {
|
|||
return record.get(RECORD_FIELDS.name)
|
||||
}
|
||||
|
||||
function getType (record: any): CommunityEventType {
|
||||
if (record.get(RECORD_FIELDS.name).toLowerCase().includes('qiskit camp')) {
|
||||
return 'Camp'
|
||||
}
|
||||
if ((record.get(RECORD_FIELDS.typeOfEvent) || []).includes('Hackathon')) {
|
||||
return 'Hackathon'
|
||||
}
|
||||
if ((record.get(RECORD_FIELDS.typeOfEvent) || []).includes('Unconference')) {
|
||||
return 'Unconference'
|
||||
}
|
||||
return 'Conference'
|
||||
function getTypes (record: any): CommunityEventType[] {
|
||||
const value = record.get(RECORD_FIELDS.typeOfEvent) || []
|
||||
const valueList = (Array.isArray(value) ? value : [value]) as string[]
|
||||
const communityEventTypes = filterWithWhitelist(valueList, TYPE_CATEGORIES)
|
||||
const noTypes = communityEventTypes.length === 0
|
||||
return noTypes ? ['Conference'] : communityEventTypes
|
||||
}
|
||||
|
||||
function filterWithWhitelist<W> (list: any[], whitelist: W[]): W[] {
|
||||
return list.filter((type): type is W => whitelist.includes(type))
|
||||
}
|
||||
|
||||
function getImage (record: any): string {
|
||||
|
@ -151,11 +151,12 @@ export {
|
|||
fetchCommunityEvents,
|
||||
convertToCommunityEvent,
|
||||
getName,
|
||||
getType,
|
||||
getTypes,
|
||||
getImage,
|
||||
getPlace,
|
||||
getLocation,
|
||||
getWebsite,
|
||||
getDates,
|
||||
formatDates
|
||||
formatDates,
|
||||
filterWithWhitelist
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// https://github.com/Al-un/learn-nuxt-ts/blob/master/docs/06.test.md
|
||||
|
||||
module.exports = {
|
||||
preset: 'ts-jest/presets/js-with-ts',
|
||||
moduleNameMapper: {
|
||||
'^@/(.*)$': '<rootDir>/$1',
|
||||
'^~/(.*)$': '<rootDir>/$1'
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<EventCard
|
||||
v-for="event in filteredEvents"
|
||||
:key="`${event.place}-${event.date}`"
|
||||
:type="event.type"
|
||||
:type="formatType(event.types)"
|
||||
:title="event.title"
|
||||
:image="event.image"
|
||||
:place="event.place"
|
||||
|
@ -187,6 +187,10 @@ export default class extends QiskitPage {
|
|||
|
||||
this.$store.commit('setActiveSet', activeSet)
|
||||
}
|
||||
|
||||
formatType (types: CommunityEvent[]): string {
|
||||
return types.join(', ')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ type WorldLocation = 'Americas'|'Asia Pacific'|'Europe'|'Africa'|'TBD'|'Online'
|
|||
type CommunityEventType = 'Hackathon'|'Camp'|'Unconference'|'Conference'
|
||||
|
||||
type CommunityEvent = {
|
||||
type: CommunityEventType,
|
||||
types: CommunityEventType[],
|
||||
title: string,
|
||||
image: string,
|
||||
place: string,
|
||||
|
@ -13,16 +13,25 @@ type CommunityEvent = {
|
|||
}
|
||||
|
||||
const LOCATION_CATEGORIES: WorldLocation[] = ['Americas', 'Asia Pacific', 'Europe', 'Africa', 'Online']
|
||||
const TYPE_CATEGORIES: CommunityEventType[] = ['Hackathon', 'Camp', 'Unconference']
|
||||
|
||||
export { CommunityEvent, CommunityEventType, WorldLocation, LOCATION_CATEGORIES }
|
||||
export {
|
||||
CommunityEvent,
|
||||
CommunityEventType,
|
||||
WorldLocation,
|
||||
LOCATION_CATEGORIES,
|
||||
TYPE_CATEGORIES
|
||||
}
|
||||
|
||||
export default {
|
||||
state: {
|
||||
activeSet: 'upcoming',
|
||||
upcomingCommunityEvents: [],
|
||||
pastCommunityEvents: [],
|
||||
typeFilters: [],
|
||||
locationFilters: []
|
||||
state () {
|
||||
return {
|
||||
activeSet: 'upcoming',
|
||||
upcomingCommunityEvents: [],
|
||||
pastCommunityEvents: [],
|
||||
typeFilters: [],
|
||||
locationFilters: []
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
typeFilters (state) {
|
||||
|
@ -46,16 +55,20 @@ export default {
|
|||
|
||||
if (noTypeFilters && noLocationFilters) { return events }
|
||||
|
||||
const eventsAfterApplyTypeFilter = filterBy(events, typeFilters, 'type')
|
||||
const eventsAfterApplyTypeFilter = filterBy(events, typeFilters, 'types')
|
||||
|
||||
return filterBy(eventsAfterApplyTypeFilter, locationFilters, 'location')
|
||||
|
||||
function filterBy (allEvents, selectedFilters, propToFilter) {
|
||||
function filterBy (allEvents: CommunityEvent[], selectedFilters: string[], propToFilter: keyof CommunityEvent) {
|
||||
const noFilters = selectedFilters.length === 0
|
||||
|
||||
if (noFilters) { return allEvents }
|
||||
|
||||
return allEvents.filter(event => selectedFilters.includes(event[propToFilter]))
|
||||
return allEvents.filter((event) => {
|
||||
const propValue = event[propToFilter]
|
||||
const valueArray = Array.isArray(propValue) ? propValue : [propValue]
|
||||
return valueArray.some(value => selectedFilters.includes(value))
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import {
|
||||
RECORD_FIELDS,
|
||||
formatDates,
|
||||
filterWithWhitelist,
|
||||
convertToCommunityEvent,
|
||||
getType,
|
||||
getTypes,
|
||||
getDates,
|
||||
getImage
|
||||
} from '~/hooks/event-conversion-utils'
|
||||
|
@ -10,7 +11,7 @@ import {
|
|||
type RecordFields = {
|
||||
name: string,
|
||||
picture?: object[],
|
||||
types?: string[],
|
||||
types?: string[]|string,
|
||||
location?: string,
|
||||
startDate?: string,
|
||||
endDate?: string,
|
||||
|
@ -47,12 +48,12 @@ describe('convertToCommunityEvent', () => {
|
|||
website: 'https://qiskit.org/events'
|
||||
})
|
||||
|
||||
it('extract and format information from the record', () => {
|
||||
it('extracts and format information from the record', () => {
|
||||
// TODO: Now ignoring image and location since they are random. Add them once implemented.
|
||||
const { title, type, place, date, to } = convertToCommunityEvent(fakeRecord)
|
||||
expect({ title, type, place, date, to }).toEqual({
|
||||
const { title, types, place, date, to } = convertToCommunityEvent(fakeRecord)
|
||||
expect({ title, types, place, date, to }).toEqual({
|
||||
title: 'Fake conference',
|
||||
type: 'Hackathon',
|
||||
types: ['Hackathon'],
|
||||
place: 'Someplace',
|
||||
date: 'January 1-2, 2020',
|
||||
to: 'https://qiskit.org/events'
|
||||
|
@ -61,59 +62,42 @@ describe('convertToCommunityEvent', () => {
|
|||
})
|
||||
|
||||
describe('getType', () => {
|
||||
it('checks the name contains the "qiskit camp" pattern regardless the capitalization', () => {
|
||||
it('filters the values so only those in the whitelist gets into the event', () => {
|
||||
const camp = new FakeRecord({
|
||||
name: 'qisKit CamP Oceania',
|
||||
types: ['Hackathon', 'Community']
|
||||
name: 'Fake Camp',
|
||||
types: ['Hackathon', 'Community', 'Unknown']
|
||||
})
|
||||
expect(getType(camp)).toBe('Camp')
|
||||
expect(getTypes(camp)).toEqual(['Hackathon'])
|
||||
})
|
||||
|
||||
it('defaults in "Conference" if there is no type', () => {
|
||||
it('gets the default type if there is no type', () => {
|
||||
const camp = new FakeRecord({
|
||||
name: 'Fake Conference'
|
||||
name: 'Fake Camp'
|
||||
})
|
||||
expect(getType(camp)).toBe('Conference')
|
||||
expect(getTypes(camp)).toEqual(['Conference'])
|
||||
})
|
||||
|
||||
it('defaults in "Conference" if cannot infer the type', () => {
|
||||
it('gets the default type if no type is in the whitelist', () => {
|
||||
const camp = new FakeRecord({
|
||||
name: 'Fake Camp',
|
||||
types: ['A', 'B', 'C']
|
||||
})
|
||||
expect(getTypes(camp)).toEqual(['Conference'])
|
||||
})
|
||||
|
||||
it('gets an array of one value if the type is not an array but one value', () => {
|
||||
const camp = new FakeRecord({
|
||||
name: 'Fake Conference',
|
||||
types: ['xxxx', 'yyyy']
|
||||
types: 'Hackathon'
|
||||
})
|
||||
expect(getType(camp)).toBe('Conference')
|
||||
expect(getTypes(camp)).toEqual(['Hackathon'])
|
||||
})
|
||||
})
|
||||
|
||||
it('infers "Hackathon" if "Hackathon" is among the tags', () => {
|
||||
const camp = new FakeRecord({
|
||||
name: 'Fake Conference',
|
||||
types: ['Hackathon', 'Education']
|
||||
})
|
||||
expect(getType(camp)).toBe('Hackathon')
|
||||
})
|
||||
|
||||
it('infers "Unconference" if "Unconference" is among the types', () => {
|
||||
const event = new FakeRecord({
|
||||
name: 'Fake Conference',
|
||||
types: ['Unconference', 'Education']
|
||||
})
|
||||
expect(getType(event)).toBe('Unconference')
|
||||
})
|
||||
|
||||
it('gives "Hackathon" preference over "Unconference"', () => {
|
||||
const event = new FakeRecord({
|
||||
name: 'Fake Conference',
|
||||
types: ['Hackathon', 'Unconference']
|
||||
})
|
||||
expect(getType(event)).toBe('Hackathon')
|
||||
})
|
||||
|
||||
it('gives "Camp" preference over "Hackathon"', () => {
|
||||
const event = new FakeRecord({
|
||||
name: 'Qiskit Camp Oceania',
|
||||
types: ['Hackathon', 'Unconference']
|
||||
})
|
||||
expect(getType(event)).toBe('Camp')
|
||||
describe('filterByWhitelist', () => {
|
||||
it('creates a new list, from an input one, only with the values in a whitelist', () => {
|
||||
const list = ['a', 'x', 'b', 'y', 'c', 'z', 'a', 'x', 'b', 'y']
|
||||
expect(filterWithWhitelist(list, ['a', 'b', 'c'])).toEqual(['a', 'b', 'c', 'a', 'b'])
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -236,11 +220,11 @@ describe('formatDates', () => {
|
|||
expect(formatDates(start, endNextYear)).toBe('January 1, 2020 - January 1, 2021')
|
||||
})
|
||||
|
||||
it('factor out the year when years are equal', () => {
|
||||
it('factors out the year when years are equal', () => {
|
||||
expect(formatDates(start, endNextMonth)).toBe('January 1 - February 1, 2020')
|
||||
})
|
||||
|
||||
it('factour out year and month when the event falls into the same month', () => {
|
||||
it('factors out year and month when the event falls into the same month', () => {
|
||||
expect(formatDates(start, endNextDay)).toBe('January 1-2, 2020')
|
||||
})
|
||||
})
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
import createStore from '~/store'
|
||||
|
||||
describe('module events', () => {
|
||||
let store: any
|
||||
|
||||
const unconferenceCampInAsia = {
|
||||
title: 'Fake event A',
|
||||
types: ['Unconference', 'Camp'],
|
||||
location: 'Asia Pacific'
|
||||
}
|
||||
const hackathonInEurope = {
|
||||
title: 'Fake event B',
|
||||
types: ['Unconference', 'Hackathon'],
|
||||
location: 'Europe'
|
||||
}
|
||||
const campInAfrica = {
|
||||
title: 'Fake event C',
|
||||
types: ['Camp'],
|
||||
location: 'Africa'
|
||||
}
|
||||
const hackathonInAmericas = {
|
||||
title: 'Fake event D',
|
||||
types: ['Camp', 'Hackathon'],
|
||||
location: 'Americas'
|
||||
}
|
||||
const unconferenceOnline = {
|
||||
title: 'Fake event E',
|
||||
types: ['Unconference'],
|
||||
location: 'Online'
|
||||
}
|
||||
|
||||
const futureEvents = [unconferenceCampInAsia, hackathonInEurope, campInAfrica]
|
||||
const pastEvents = [hackathonInAmericas, unconferenceOnline]
|
||||
|
||||
beforeEach(() => {
|
||||
store = createStore()
|
||||
store.commit('setEvents', {
|
||||
events: 'upcomingCommunityEvents',
|
||||
eventsSet: futureEvents
|
||||
})
|
||||
store.commit('setEvents', {
|
||||
events: 'pastCommunityEvents',
|
||||
eventsSet: pastEvents
|
||||
})
|
||||
})
|
||||
|
||||
describe('filteredEvents', () => {
|
||||
it('gets future events by default', () => {
|
||||
expect(store.getters.filteredEvents).toEqual(futureEvents)
|
||||
})
|
||||
|
||||
it('gets past events after setting the the active set to past', () => {
|
||||
store.commit('setActiveSet', 'past')
|
||||
expect(store.getters.filteredEvents).toEqual(pastEvents)
|
||||
})
|
||||
|
||||
it('gets active-set filtered by location', () => {
|
||||
store.commit('addFilter', {
|
||||
filter: 'locationFilters',
|
||||
filterValue: 'Asia Pacific'
|
||||
})
|
||||
expect(store.getters.filteredEvents).toEqual([unconferenceCampInAsia])
|
||||
})
|
||||
|
||||
it('gets active-set filtered by type', () => {
|
||||
store.commit('addFilter', {
|
||||
filter: 'typeFilters',
|
||||
filterValue: 'Hackathon'
|
||||
})
|
||||
expect(store.getters.filteredEvents).toEqual([hackathonInEurope])
|
||||
})
|
||||
|
||||
it('gets active-set filtered by type, considering events with several types', () => {
|
||||
store.commit('addFilter', {
|
||||
filter: 'typeFilters',
|
||||
filterValue: 'Camp'
|
||||
})
|
||||
expect(store.getters.filteredEvents).toEqual([unconferenceCampInAsia, campInAfrica])
|
||||
})
|
||||
|
||||
it('gets active-set filtered by type and location', () => {
|
||||
store.commit('addFilter', {
|
||||
filter: 'typeFilters',
|
||||
filterValue: 'Camp'
|
||||
})
|
||||
store.commit('addFilter', {
|
||||
filter: 'locationFilters',
|
||||
filterValue: 'Africa'
|
||||
})
|
||||
expect(store.getters.filteredEvents).toEqual([campInAfrica])
|
||||
})
|
||||
})
|
||||
})
|
Loading…
Reference in New Issue