Skip to content

Commit

Permalink
Merge branch 'stage' into production
Browse files Browse the repository at this point in the history
  • Loading branch information
moz-rotimib committed Apr 4, 2024
2 parents 6b8bc3f + 7eb659a commit 1654aaf
Show file tree
Hide file tree
Showing 20 changed files with 565 additions and 145 deletions.
4 changes: 1 addition & 3 deletions common/sentences.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { SentenceDomain } from './taxonomies'

export type SentenceSubmission = {
sentence: string
source: string
localeId: number
localeName: string
domain?: SentenceDomain
domains: string[]
}

export enum SentenceSubmissionError {
Expand Down
2 changes: 1 addition & 1 deletion common/taxonomies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ export const taxonomies: { [key in TaxonomyToken]: TaxonomyType } = {
}

export const sentenceDomains = [
'general',
'agriculture',
'automotive',
'finance',
'food_service_retail',
'general',
'healthcare',
'history_law_government',
'language_fundamentals',
Expand Down
4 changes: 3 additions & 1 deletion web/cypress/actions/single-submission-write-page.action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ export const typeSingleSubmission = ({
cy.get('[data-testid=sentence-textarea]').type(sentence)

if (shouldSelectDomain) {
cy.get('[data-testid=sentence-domain-select]').select('general')
cy.get('[data-testid=sentence-domain-select]').click()
// Select "General" as domain
cy.get('[data-testid=general]').click()
}

if (shouldTypeCitation) {
Expand Down
1 change: 1 addition & 0 deletions web/locales/en/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -1773,6 +1773,7 @@ single-sentence = Single Sentence
bulk-sentences = Bulk Sentences
sentence-domain-select =
.label = Sentence Domain
sentence-domain-select-placeholder = Select up to three domains
# Sentence Domain dropdown option
agriculture = Agriculture
# Sentence Domain dropdown option
Expand Down
3 changes: 3 additions & 0 deletions web/locales/fr/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -787,6 +787,8 @@ subscribe = S’abonner
get-started-speech = S’initier à la reconnaissance vocale
other-datasets = Autres jeux de données vocales
feedback-q = Vous avez des suggestions ?
# This indicates that there is no data to display
no-information = Aucune information
resource-nemo-info = <githubLink>NVIDIA NeMo</githubLink>™ est une <docsLink>boîte à outils open source</docsLink> pour les chercheurs développant des modèles d’IA conversationnelle de pointe.
resource-deepspeech-info = Le moteur open source de reconnaissance vocale de Mozilla, Deep Speech, peut être utilisé pour créer des applications de reconnaissance vocale. Consultez notre <githubLink>aperçu sur GitHub</githubLink> ou rejoignez le <discourseLink>Discourse de DeepSpeech</discourseLink> pour bien commencer.
resource-coqui-info = <coquiLink>Coqui</coquiLink> est dédié à la technologie de la parole ouverte. Parmi leurs projets figurent des moteurs STT et TTS basés sur l’apprentissage en profondeur.
Expand Down Expand Up @@ -1744,6 +1746,7 @@ single-sentence = Phrase unique
bulk-sentences = Plusieurs phrases
sentence-domain-select =
.label = Domaine de la phrase
sentence-domain-select-placeholder = Sélectionnez jusqu’à trois domaines
# Sentence Domain dropdown option
agriculture = Agriculture
# Sentence Domain dropdown option
Expand Down
3 changes: 3 additions & 0 deletions web/locales/it/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,8 @@ subscribe = Iscriviti
get-started-speech = Inizia con il riconoscimento vocale
other-datasets = Altri dataset vocali
feedback-q = Hai suggerimenti?
# This indicates that there is no data to display
no-information = Nessuna informazione
resource-nemo-info = <githubLink>NVIDIA NeMo</githubLink>™ è un <docsLink>toolkit open-source</docsLink> per i ricercatori che sviluppano modelli conversazionali di intelligenza artificiale all’avanguardia.
resource-deepspeech-info = Il motore di riconoscimento vocale open source di Mozilla, Deep Speech, può essere utilizzato per creare applicazioni di riconoscimento vocale. Leggi la <githubLink>panoramica su GitHub</githubLink> o partecipa a <discourseLink>DeepSpeech su Discourse</discourseLink> per scoprire come cominciare.
resource-coqui-info = <coquiLink>Coqui</coquiLink> è un’organizzazione che si occupa di tecnologia aperta in ambito vocale. Alcuni dei loro progetti includono motori STT e TTS basati su deep learning.
Expand Down Expand Up @@ -1739,6 +1741,7 @@ single-sentence = Singola frase
bulk-sentences = Frasi in blocco
sentence-domain-select =
.label = Dominio della frase
sentence-domain-select-placeholder = Scegli fino a 3 domini
# Sentence Domain dropdown option
agriculture = Agricoltura
# Sentence Domain dropdown option
Expand Down
4 changes: 2 additions & 2 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"audio-recorder-polyfill": "0.4.1",
"classnames": "2.3.2",
"date-fns": "^2.30.0",
"downshift": "3.4.8",
"downshift": "9.0.0",
"filesize": "^10.0.7",
"focus-visible": "5.2.0",
"intersection-observer": "0.12.0",
Expand Down Expand Up @@ -73,7 +73,7 @@
"html-webpack-plugin": "5.5.0",
"identity-obj-proxy": "3.0.0",
"jest": "27.5.1",
"jest-axe": "6.0.1",
"jest-axe": "8.0.0",
"jest-canvas-mock": "^2.4.0",
"jest-matcher-utils": "27.5.1",
"jest-svg-transformer": "1.0.0",
Expand Down
153 changes: 153 additions & 0 deletions web/src/components/multiple-combobox/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import * as React from 'react'
import { useCombobox, useMultipleSelection } from 'downshift'
import { Localized, useLocalization } from '@fluent/react'

import { LabeledInput } from '../ui/ui'
import { SelectedItemsList } from './selected-items-list'

import './multiple-combobox.css'

const Input = LabeledInput

type Props = {
items: string[]
maxNumberOfSelectedElements?: number
selectedItems: string[]
setInputValue: React.Dispatch<React.SetStateAction<string>>
setSelectedItems: (items: string[]) => void
inputValue: string
}

export const MultipleCombobox: React.FC<Props> = ({
items,
selectedItems,
setSelectedItems,
maxNumberOfSelectedElements,
inputValue,
setInputValue,
}) => {
const { l10n } = useLocalization()

const { getDropdownProps, removeSelectedItem } = useMultipleSelection({
selectedItems,
onStateChange({ selectedItems: newSelectedItems, type }) {
switch (type) {
case useMultipleSelection.stateChangeTypes.SelectedItemKeyDownBackspace:
case useMultipleSelection.stateChangeTypes.SelectedItemKeyDownDelete:
case useMultipleSelection.stateChangeTypes.DropdownKeyDownBackspace:
case useMultipleSelection.stateChangeTypes.FunctionRemoveSelectedItem:
setSelectedItems(newSelectedItems)
break
default:
break
}
},
})

const {
isOpen,
getMenuProps,
getInputProps,
highlightedIndex,
getItemProps,
openMenu,
} = useCombobox({
items,
inputValue,
selectedItem: null,
stateReducer(_, actionAndChanges) {
const { changes, type } = actionAndChanges

switch (type) {
case useCombobox.stateChangeTypes.InputKeyDownEnter:
case useCombobox.stateChangeTypes.ItemClick:
case useCombobox.stateChangeTypes.InputBlur:
return {
...changes,
inputValue: '',
}
case useCombobox.stateChangeTypes.InputClick:
return {
...changes,
isOpen: true,
}
default:
return changes
}
},
onStateChange({
inputValue: newInputValue,
type,
selectedItem: newSelectedItem,
}) {
switch (type) {
case useCombobox.stateChangeTypes.InputKeyDownEnter:
case useCombobox.stateChangeTypes.ItemClick:
case useCombobox.stateChangeTypes.InputBlur:
if (newSelectedItem) {
setSelectedItems([...selectedItems, newSelectedItem])
setInputValue('')
}
break
case useCombobox.stateChangeTypes.InputChange:
setInputValue(newInputValue)
break
default:
break
}
},
})

const handleFocus: React.FocusEventHandler<HTMLInputElement> = () => {
openMenu()
}

const handleClick: React.MouseEventHandler<HTMLInputElement> = () => {
openMenu()
}

return (
<div className="multiple-sentence-domain-select">
<div>
<Localized id="sentence-domain-select" attrs={{ label: true }}>
<Input
{...getInputProps(
getDropdownProps({
preventKeyAction: isOpen,
onFocus: handleFocus,
onClick: handleClick,
disabled: selectedItems.length === maxNumberOfSelectedElements,
})
)}
placeholder={l10n.getString('sentence-domain-select-placeholder')}
dataTestId="sentence-domain-select"
/>
</Localized>
</div>

<ul {...getMenuProps()} className={isOpen ? 'downshift-open' : ''}>
{isOpen &&
items.map((item, index) => (
<li
style={
highlightedIndex === index
? { backgroundColor: 'var(--light-grey)' }
: {}
}
key={`${item}${index}`}
{...getItemProps({ item, index })}
data-testid={item}>
{l10n.getString(item)}
</li>
))}
</ul>

{selectedItems && (
<SelectedItemsList
selectedItems={selectedItems}
removeItem={removeSelectedItem}
/>
)}
</div>
)
}
70 changes: 70 additions & 0 deletions web/src/components/multiple-combobox/multiple-combobox.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
@import url('../media.css');

.multiple-sentence-domain-select {
ul {
background: #fff;
margin: 0px 0 30px;
position: absolute;
z-index: var(--override-z-index);

@media (--xl-up) {
width: 700px;
}

@media (--md-down) {
width: 90vw;
}

&.downshift-open {
border: 1px solid var(--light-grey);
box-shadow: 0 2px 5px 0 var(--light-grey);
overflow: auto;
max-height: 500px;
}

li {
border-bottom: 1px solid var(--dark-grey);
cursor: pointer;
list-style: none;
padding: 15px;

&:last-of-type {
border-bottom: none;
}
}

@media (--xs-down) {
font-size: var(--font-size-xs);
}
}

input[type='text'] {
@media (--xs-down) {
font-size: var(--font-size-xs);

&::placeholder {
font-size: var(--font-size-xs);
}
}
}
}

.selected-domains-list {
margin-block-start: 30px;

.selected-domain {
display: inline-flex;
align-items: center;
padding-inline-start: 1.5rem;
margin-inline-end: 1rem;
margin-bottom: 1.5rem;
background: var(--light-grey);
border-radius: 15rem;
}

.selected-domain--button {
border: none;
padding: 0.8rem 1.5rem;
padding-inline-start: 1rem;
}
}
34 changes: 34 additions & 0 deletions web/src/components/multiple-combobox/selected-items-list.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import * as React from 'react'
import { useLocalization } from '@fluent/react'

import { CloseIcon } from '../ui/icons'
import VisuallyHidden from '../visually-hidden/visually-hidden'

type Props = {
selectedItems: string[]
removeItem: (item: string) => void
}

export const SelectedItemsList: React.FC<Props> = ({
selectedItems,
removeItem,
}) => {
const { l10n } = useLocalization()

return (
<div className="selected-domains-list">
{selectedItems.map(item => (
<span key={`domain-${item}`} className="selected-domain">
{l10n.getString(item)}
<button
className="selected-domain--button"
onClick={() => removeItem(item)}
type="button">
<VisuallyHidden>Remove {l10n.getString(item)}</VisuallyHidden>
<CloseIcon black />
</button>
</span>
))}
</div>
)
}
42 changes: 42 additions & 0 deletions web/src/components/multiple-combobox/use-multiple-combox.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useMemo, useState } from 'react'

type UseMultipleComboBoxParams = {
items: readonly string[]
selectedItems: string[]
}

export const useMultipleComboBox = ({
items,
selectedItems,
}: UseMultipleComboBoxParams) => {
const [inputValue, setInputValue] = useState('')

const getFilteredItems = ({
elements,
selectedItems,
inputValue,
}: {
elements: readonly string[]
selectedItems: string[]
inputValue: string
}) => {
const lowerCasedInputValue = inputValue.toLowerCase()

return elements.filter(
element =>
!selectedItems.includes(element) &&
element.toLowerCase().startsWith(lowerCasedInputValue)
)
}

const multipleComboBoxItems = useMemo(
() => getFilteredItems({ elements: items, selectedItems, inputValue }),
[selectedItems, inputValue]
)

return {
multipleComboBoxItems,
inputValue,
setInputValue,
}
}
Loading

0 comments on commit 1654aaf

Please sign in to comment.