-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add themes #126
Merged
Merged
feat: add themes #126
Changes from 17 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
c5caf52
feat: add themes
UnbearableBear 7ee74b7
refactor: remove artifact
UnbearableBear fb71c9b
fix wrong argument management
UnbearableBear 6f7ad32
polishing
UnbearableBear fb3e01d
fix lockfile
UnbearableBear b087e21
feedbacks first pass
UnbearableBear 7372eb4
remove unused variable
UnbearableBear fd51583
feedbacks first pass
UnbearableBear 51f2541
feedback
UnbearableBear 758c622
add setDebounceState hook
UnbearableBear 713ea1c
feedbacks
UnbearableBear 9c25483
refactor icon size into theme
UnbearableBear 3793e01
forgot to remove a file
UnbearableBear aa7af18
adding id-generator package.json to www image
UnbearableBear ac746f8
tatoning
UnbearableBear 41e9e96
clean mistakes
UnbearableBear c354028
fix mistake
UnbearableBear 9c89a09
remove memoizee from deps
UnbearableBear File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"name": "@shared/id-generator", | ||
"version": "1.0.0", | ||
"dependencies": { | ||
"uuid": "^8.3.0", | ||
"xxhashjs": "^0.2.2" | ||
}, | ||
"main": "src/index.js", | ||
"module": "src/index.js", | ||
"types": "src/index.d.ts", | ||
"private": true, | ||
"scripts": {}, | ||
"devDependencies": { | ||
"@types/uuid": "^8.3.0", | ||
"@types/xxhashjs": "^0.2.2" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export as namespace idGenerator | ||
|
||
export type generatedId = { | ||
cdtn_id: string | ||
initial_id: string | ||
}; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { v4 as uuidv4 } from "uuid"; | ||
import * as XXH from "xxhashjs"; | ||
|
||
const H = XXH.h64(0x1e7f); | ||
|
||
|
||
export const MAX_ID_LENGTH = 10; | ||
|
||
// use xxhash to hash source + newly generated UUID | ||
/** | ||
* | ||
* @param {string} content | ||
* @param {number} maxIdLength | ||
* @returns {string} | ||
*/ | ||
export const generateCdtnId = (content, maxIdLength = MAX_ID_LENGTH) => | ||
// save 64bits hash as Hexa string up to maxIdLength chars (can be changed later in case of collision) | ||
// as the xxhash function ensure distribution property | ||
H.update(content).digest().toString(16).slice(0, maxIdLength); | ||
|
||
export const generateInitialId = uuidv4; | ||
|
||
// Beware, you might be generating an already existing cdtn_id | ||
/** | ||
* @param {string} source | ||
* @param {number} maxIdLength | ||
* @returns {idGenerator.generatedId} | ||
*/ | ||
export const generateIds = (source, maxIdLength = MAX_ID_LENGTH) => { | ||
const uuid = uuidv4(); | ||
return { | ||
cdtn_id: generateCdtnId(source + uuid, maxIdLength), | ||
initial_id: generateInitialId(), | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"compilerOptions": { | ||
"allowJs": true, | ||
"checkJs": true, | ||
"downlevelIteration": true, | ||
"esModuleInterop": true, | ||
"forceConsistentCasingInFileNames": true, | ||
"noEmit": true, | ||
"resolveJsonModule": true, | ||
"skipLibCheck": true, | ||
"strict": true, | ||
"lib": ["es2019"], | ||
"baseUrl": ".", | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
201 changes: 201 additions & 0 deletions
201
targets/frontend/src/components/forms/ContentPicker/ContentSearch.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
/** @jsx jsx */ | ||
|
||
import { getLabelBySource, SOURCES } from "@socialgouv/cdtn-sources"; | ||
import PropTypes from "prop-types"; | ||
import { useEffect, useState } from "react"; | ||
import Autosuggest from "react-autosuggest"; | ||
import { useDebouncedState } from "src/hooks/index"; | ||
import { Input, jsx } from "theme-ui"; | ||
import { useQuery } from "urql"; | ||
|
||
const sources = [ | ||
SOURCES.SHEET_MT_PAGE, | ||
SOURCES.SHEET_SP, | ||
SOURCES.LETTERS, | ||
SOURCES.TOOLS, | ||
SOURCES.CONTRIBUTIONS, | ||
SOURCES.EXTERNALS, | ||
SOURCES.THEMATIC_FILES, | ||
SOURCES.EDITORIAL_CONTENT, | ||
SOURCES.CDT, | ||
SOURCES.THEMES, | ||
]; | ||
|
||
const AUTOSUGGEST_MAX_RESULTS = 15; | ||
|
||
const searchDocumentsQuery = ` | ||
query searchDocuments($sources: [String!]! = "", $search: String = "") { | ||
UnbearableBear marked this conversation as resolved.
Show resolved
Hide resolved
|
||
documents(where: {title: {_ilike: $search}, source: {_in: $sources}}, limit: ${AUTOSUGGEST_MAX_RESULTS}) { | ||
source | ||
title | ||
cdtnId: cdtn_id | ||
} | ||
} | ||
`; | ||
|
||
export const ContentSearch = ({ contents = [], onChange }) => { | ||
const [suggestions, setSuggestions] = useState([]); | ||
const [inputSearchValue, setInputSearchValue] = useState(""); | ||
const [searchValue, , setDebouncedSearchValue] = useDebouncedState("", 500); | ||
|
||
const [results] = useQuery({ | ||
pause: searchValue.length < 3, | ||
query: searchDocumentsQuery, | ||
variables: { | ||
search: `%${searchValue}%`, | ||
sources, | ||
}, | ||
}); | ||
|
||
useEffect(() => { | ||
const allDocuments = results.data?.documents || []; | ||
const documents = allDocuments.filter( | ||
(document) => | ||
document.source !== SOURCES.THEMES && document.source !== SOURCES.CDT | ||
); | ||
documents.forEach((document) => { | ||
document.category = "document"; | ||
}); | ||
const themes = allDocuments.filter( | ||
(document) => document.source === SOURCES.THEMES | ||
); | ||
const articles = allDocuments.filter( | ||
(document) => document.source === SOURCES.CDT | ||
); | ||
setSuggestions([ | ||
{ | ||
suggestions: documents, | ||
title: "Documents", | ||
}, | ||
{ suggestions: articles, title: "Articles" }, | ||
{ suggestions: themes, title: "Thèmes" }, | ||
]); | ||
}, [results.data]); | ||
|
||
const onSearchValueChange = (event, { newValue }) => { | ||
setInputSearchValue(newValue); | ||
setDebouncedSearchValue(newValue); | ||
}; | ||
const onSuggestionSelected = ( | ||
event, | ||
{ suggestion: { cdtnId, source, title = null } } | ||
) => { | ||
if (contents.find((content) => content.cdtnId === cdtnId)) { | ||
return; | ||
} | ||
onChange(contents.concat([{ cdtnId, source, title }])); | ||
setInputSearchValue(""); | ||
setSuggestions([]); | ||
}; | ||
|
||
const onSuggestionsFetchRequested = async ({ value }) => { | ||
setInputSearchValue(value); | ||
setDebouncedSearchValue(value); | ||
}; | ||
|
||
const onSuggestionsClearRequested = () => { | ||
setSuggestions([]); | ||
}; | ||
|
||
const inputProps = { | ||
onChange: onSearchValueChange, | ||
placeholder: "Rechercher et ajouter un contenu", | ||
value: inputSearchValue, | ||
}; | ||
|
||
return ( | ||
<Autosuggest | ||
suggestions={suggestions} | ||
onSuggestionsFetchRequested={onSuggestionsFetchRequested} | ||
onSuggestionsClearRequested={onSuggestionsClearRequested} | ||
onSuggestionSelected={onSuggestionSelected} | ||
getSuggestionValue={getSuggestionValue} | ||
getSectionSuggestions={getSectionSuggestions} | ||
multiSection={true} | ||
shouldRenderSuggestions={shouldRenderSuggestions} | ||
renderInputComponent={renderInputComponent} | ||
renderSuggestion={renderSuggestion} | ||
renderSuggestionsContainer={renderSuggestionsContainer} | ||
renderSectionTitle={renderSectionTitle} | ||
inputProps={inputProps} | ||
/> | ||
); | ||
}; | ||
|
||
ContentSearch.propTypes = { | ||
contents: PropTypes.array, | ||
onChange: PropTypes.func.isRequired, | ||
}; | ||
|
||
const renderInputComponent = (inputProps) => ( | ||
<Input {...inputProps} ref={inputProps.ref} /> | ||
); | ||
|
||
function shouldRenderSuggestions(value) { | ||
return value.trim().length > 2; | ||
} | ||
function renderSectionTitle(section) { | ||
return section.suggestions.length ? ( | ||
<div | ||
sx={{ | ||
bg: "neutral", | ||
fontWeight: "bold", | ||
p: "xxsmall", | ||
}} | ||
> | ||
{section.title} | ||
</div> | ||
) : null; | ||
} | ||
|
||
function getSectionSuggestions(section) { | ||
return section.suggestions; | ||
} | ||
|
||
const getSuggestionValue = (content) => content.title; | ||
|
||
const renderSuggestion = (content) => ( | ||
<div> | ||
{content.title} | ||
{content.category === "document" && ( | ||
<strong> | {getLabelBySource(content.source)}</strong> | ||
)} | ||
</div> | ||
); | ||
|
||
const renderSuggestionsContainer = ({ containerProps, children }) => ( | ||
<div | ||
sx={{ | ||
'&[class*="container--open"]': { | ||
border: "1px solid #ddd", | ||
borderRadius: "4px", | ||
maxHeight: "300px", | ||
overflow: "scroll", | ||
position: "relative", | ||
top: "4px", | ||
}, | ||
li: { | ||
'&[role="option"]:hover': { | ||
bg: "#dde", | ||
}, | ||
":nth-of-type(2n + 1)": { | ||
bg: "highlight", | ||
}, | ||
bg: "white", | ||
cursor: "pointer", | ||
m: "0", | ||
p: "xxsmall", | ||
zIndex: 2, | ||
}, | ||
ul: { | ||
listStyleType: "none", | ||
m: "0", | ||
p: "0", | ||
width: "100%", | ||
}, | ||
}} | ||
{...containerProps} | ||
> | ||
{children} | ||
</div> | ||
); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this import is not used, we can remove it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a tool you use to detect unused packages ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, indeed, it's called memory :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Arf, mine never really worked :/