lodash#sample TypeScript Examples
The following examples show how to use
lodash#sample.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: SearchTip.tsx From hub with Apache License 2.0 | 6 votes |
SearchTip = () => {
const [activeTip] = useState<SearchTipItem | undefined>(sample(SEARH_TIPS));
if (isUndefined(activeTip)) return null;
return (
<div className="d-none d-md-inline w-50 mx-auto text-center position-relative">
<div
className={`d-flex mt-2 pt-1 flex-row align-items-center justify-content-center textLight ${styles.tipText}`}
>
<FaRegLightbulb className="me-1" />
<div>
<span className="fw-semibold me-1">Tip:</span>
{activeTip.content} Example:{' '}
<Link
className="fw-bold textLighter p-0"
to={{
pathname: '/packages/search',
search: prepareQueryString({
pageNumber: 1,
tsQueryWeb: activeTip.example,
}),
}}
>
{activeTip.example}
</Link>
</div>
</div>
</div>
);
}
Example #2
Source File: DataDocLoading.tsx From querybook with Apache License 2.0 | 6 votes |
DataDocLoading: React.FC = () => {
const hint = sample(loadingHints);
return (
<div className="datadoc-loading flex-center">
<div className="flex-column">
<LoadingIcon className="mb16" />
<Title color="light">Loading DataDoc</Title>
<Icon name="Zap" className="mt16 mb8" color="accent" />
<Subtitle>Did you know?</Subtitle>
<div className="mt8">{hint}</div>
</div>
</div>
);
}
Example #3
Source File: getRandomTask.ts From vscode-todo-md with MIT License | 6 votes |
export async function getRandomTask() {
await updateState();
const tasks = $state.tasks.filter(t => !t.done);
if (!tasks.length) {
window.showInformationMessage('No tasks');
return;
}
const randomTask = sample(tasks)!;
showTaskInNotification(randomTask);
}
Example #4
Source File: index.tsx From fishbowl with MIT License | 5 votes |
export function LetterInput(props: { value: string }) {
const { t } = useTranslation()
const currentPlayer = React.useContext(CurrentPlayerContext)
const currentGame = React.useContext(CurrentGameContext)
const [updateGameSettings] = useUpdateGameSettingsMutation()
const [textFieldValue, setTextFieldValue] = React.useState(props.value)
const canConfigureSettings = currentPlayer.role === PlayerRole.Host
React.useEffect(() => {
setTextFieldValue(props.value)
}, [props.value])
const debouncedUpdateGameSettings = React.useRef(
debounce((value: string) => {
updateGameSettings({
variables: {
id: currentGame.id,
input: { starting_letter: value },
},
})
}, DEBOUNCE_SECONDS)
).current
return (
<TextField
label={t("settings.cards.letter.label", "Letter")}
variant="outlined"
size="medium"
helperText={
<HelperText>
{currentPlayer.role === PlayerRole.Host ? (
<>
<span>
{t(
"settings.cards.letter.helper",
"One style of play is that all words or phrases must start with the same letter."
)}{" "}
{t("settings.cards.letter.helperHost", "Ask your group!")}
</span>
<br />
<Link
href=""
onClick={(e: React.MouseEvent<HTMLElement>) => {
e.preventDefault()
const randomLetter =
sample(Array.from("ABCDEFGHIJKLMNOPQRSTUVWXYZ")) || "A"
setTextFieldValue(randomLetter)
debouncedUpdateGameSettings(randomLetter)
}}
>
{t(
"settings.cards.letter.generateRandom",
"Generate random letter"
)}
</Link>
</>
) : (
<span>
{t(
"settings.cards.letter.helper",
"One style of play is that all words or phrases must start with the same letter."
)}{" "}
{t(
"settings.cards.letter.helperPlayers",
"If none is chosen, any word or phrase is fair game!"
)}
</span>
)}
</HelperText>
}
value={textFieldValue}
inputProps={{ maxLength: 1, style: { textTransform: "uppercase" } }}
disabled={!canConfigureSettings}
onChange={({ target: { value } }) => {
setTextFieldValue(value)
debouncedUpdateGameSettings(value)
}}
/>
)
}
Example #5
Source File: index.ts From template-based-generator-template with GNU General Public License v3.0 | 5 votes |
/**
* 从模板里定义的多个大纲里随机抽取一个出来用
*/
export function getRandomOutline(outlines: ITemplateData['outlines'] | undefined): string[] {
return sample((outlines ?? []).filter((outline) => outline.length > 0)) ?? [];
}
Example #6
Source File: YourTurnContent.tsx From fishbowl with MIT License | 4 votes |
function YourTurnContent(props: {
yourTeamPlayers: CurrentGameSubscription["games"][0]["players"]
cardsInBowl: CurrentGameSubscription["games"][0]["cards"]
activePlayer: CurrentGameSubscription["games"][0]["players"][0]
activeTurn: CurrentGameSubscription["games"][0]["turns"][0]
activeTurnPlayState: ActiveTurnPlayState
secondsLeft: number
currentRoundId: Rounds["id"]
nextRoundId?: Rounds["id"]
onStart: () => void
onOutOfCards: () => void
}) {
const { t } = useTranslation()
const { serverTimeOffset } = React.useContext(CurrentPlayerContext)
const currentGame = React.useContext(CurrentGameContext)
const [startTurn] = useStartTurnMutation()
const [endTurn] = useEndCurrentTurnAndStartNextTurnMutation()
const [startingTurn, setStartingTurn] = React.useState(false)
const [endingTurn, setEndingTurn] = React.useState(false)
const [skippingTurn, setSkippingTurn] = React.useState(false)
const [activeCard, setActiveCard] = React.useState<
CurrentGameSubscription["games"][0]["cards"][0] | null
>(null)
const [shownCardsInActiveTurn, setShownCardsInActiveTurn] = React.useState<
Map<number, { status: ShownCardStatus; startedAt: Date; endedAt: Date }>
>(new Map())
// Attach keyboard shortcuts to the Correct and Skip actions
const SHORTCUTS_COMPLETE = [" ", "c"]
const SHORTCUTS_SKIP = ["s"]
const upHandler = (event: KeyboardEvent) => {
if (includes(SHORTCUTS_COMPLETE, event.key)) {
onNextCardClick(ShownCardStatus.Complete)
} else if (
currentGame.allow_card_skips &&
includes(SHORTCUTS_SKIP, event.key)
) {
onNextCardClick(ShownCardStatus.Skipped)
}
}
React.useEffect(() => {
window.addEventListener("keyup", upHandler)
return () => {
window.removeEventListener("keyup", upHandler)
}
}, [activeCard])
React.useEffect(() => {
if (activeCard && props.secondsLeft <= 0) {
const shownCard = shownCardsInActiveTurn.get(activeCard.id)
if (shownCard) {
setShownCardsInActiveTurn(
new Map(
shownCardsInActiveTurn.set(activeCard.id, {
...shownCard,
endedAt: new Date(),
})
)
)
}
}
}, [props.secondsLeft, activeCard])
const [play] = useSound(bell)
React.useEffect(() => {
if (props.secondsLeft === 0) {
play()
}
}, [props.secondsLeft])
const onNextCardClick = (status: ShownCardStatus) => {
if (activeCard) {
// mark the active card as "complete" or "skipped"
const shownCard = shownCardsInActiveTurn.get(activeCard.id)
if (shownCard) {
setShownCardsInActiveTurn(
new Map(
shownCardsInActiveTurn.set(activeCard.id, {
...shownCard,
status: status,
endedAt: new Date(),
})
)
)
}
const nextSet = drawableCardsWithoutCompletedCardsInActiveTurn(
props.cardsInBowl,
[...shownCardsInActiveTurn.keys()]
)
const outOfCards = nextSet.length === 0
if (outOfCards) {
props.onOutOfCards()
} else {
const nextActiveCard = sample(nextSet) || null
if (nextActiveCard) {
setActiveCard(nextActiveCard)
setShownCardsInActiveTurn(
new Map(
shownCardsInActiveTurn.set(nextActiveCard.id, {
status: ShownCardStatus.Incomplete,
startedAt: new Date(),
endedAt: new Date(),
})
)
)
}
}
}
}
const yourTeammates = React.useMemo(
() =>
reject(
props.yourTeamPlayers,
(player) => player.id === props.activePlayer.id
),
[props.activePlayer.id, props.yourTeamPlayers]
)
return (
<Box p={2}>
<Grid container direction="column" spacing={4} alignItems="center">
{props.activeTurnPlayState === ActiveTurnPlayState.Reviewing &&
props.secondsLeft >= 0 ? (
<Grid item>
{t(
"play.yourTurn.leftoverSeconds",
"You'll be starting the next round with {{ count }} second leftover from this turn!",
{
count: props.secondsLeft,
defaultValue_plural:
"You'll be starting the next round with {{ count }} seconds leftover from this turn!",
}
)}
</Grid>
) : null}
{/* Cards */}
{[ActiveTurnPlayState.Waiting, ActiveTurnPlayState.Playing].includes(
props.activeTurnPlayState
) && (
<>
{!!yourTeammates.length && (
<Grid item>
<Trans
t={t}
i18nKey="play.yourTurn.context"
count={yourTeammates.length}
tOptions={{
defaultValue_plural:
"<0>{{playerUsernames}}</0> from your team are guessing!",
}}
>
<PlayerChipList players={yourTeammates}>
{{ playerUsernames: null }}
</PlayerChipList>
{" from your team is guessing!"}
</Trans>
</Grid>
)}
<Grid item>
<BowlCard>
{activeCard ? (
<Typography variant="h5">{activeCard.word}</Typography>
) : (
<div style={{ textAlign: "center", color: grey[600] }}>
{t("play.yourTurn.emptyCard", "You'll see cards here!")}
</div>
)}
</BowlCard>
</Grid>
</>
)}
{props.activeTurnPlayState === ActiveTurnPlayState.Reviewing && (
<>
<Grid item>
{t(
"play.yourTurn.reviewHelper.default",
"Review the cards you went through this turn."
)}{" "}
{currentGame.allow_card_skips
? t(
"play.yourTurn.reviewHelper.withSkips",
"If you skipped or missed any, just uncheck them."
)
: t(
"play.yourTurn.reviewHelper.withoutSkips",
"If you missed any, just uncheck them."
)}
</Grid>
<Grid item container direction="column" spacing={2}>
{[...shownCardsInActiveTurn.keys()].map((cardId) => {
return (
<Grid
key={cardId}
item
container
direction="row"
justify="center"
alignItems="center"
spacing={2}
>
<Grid item>
<Box>
<GreenCheckbox
checked={
shownCardsInActiveTurn.get(cardId)?.status ===
ShownCardStatus.Complete
}
onChange={({ target: { checked } }) => {
const shownCard = shownCardsInActiveTurn.get(cardId)
if (shownCard) {
setShownCardsInActiveTurn(
new Map(
shownCardsInActiveTurn.set(cardId, {
...shownCard,
status: checked
? ShownCardStatus.Complete
: ShownCardStatus.Incomplete,
})
)
)
}
}}
></GreenCheckbox>
</Box>
{shownCardsInActiveTurn.get(cardId)?.status ===
ShownCardStatus.Skipped && (
<Box color={grey[600]}>
(
{t(
"play.yourTurn.cardButton.skip",
"Skip"
).toLocaleLowerCase()}
)
</Box>
)}
</Grid>
<Grid item>
<BowlCard>
{
props.cardsInBowl.find((card) => card.id === cardId)
?.word
}
</BowlCard>
</Grid>
</Grid>
)
})}
</Grid>
</>
)}
{/* Controls */}
<Grid item container justify="space-around">
{props.activeTurnPlayState === ActiveTurnPlayState.Playing && (
<>
{currentGame.allow_card_skips && (
<Grid item>
<Button
color="default"
onClick={async () => {
onNextCardClick(ShownCardStatus.Skipped)
}}
>
{t("play.yourTurn.cardButton.skip", "Skip")}
</Button>
</Grid>
)}
<Grid item>
<Button
variant="contained"
color="primary"
onClick={async () => {
onNextCardClick(ShownCardStatus.Complete)
}}
>
{t("play.yourTurn.cardButton.correct", "Correct")}
</Button>
</Grid>
</>
)}
{props.activeTurnPlayState === ActiveTurnPlayState.Waiting && (
<Grid item>
<Button
disabled={skippingTurn}
onClick={async () => {
setSkippingTurn(true)
if (
window.confirm(
t(
"play.yourTurn.skipTurnConfirmation",
"Are you sure you want to skip your turn?"
)
)
) {
const response = await endTurn({
variables: {
currentTurnId: props.activeTurn.id,
completedCardIds: [],
gameId: currentGame.id,
currentTurnScorings: [],
nextTurnplayerId: nextPlayerForSameTeam(
props.activePlayer,
currentGame.players
).id,
roundId: props.currentRoundId,
},
})
if (response.errors) {
setSkippingTurn(false)
}
} else {
setSkippingTurn(false)
}
}}
>
{t("play.yourTurn.skipTurnButton", "Skip turn")}
</Button>
</Grid>
)}
{props.activeTurnPlayState === ActiveTurnPlayState.Reviewing && (
<Grid item>
<Button
variant="contained"
color="primary"
disabled={endingTurn}
onClick={async () => {
setEndingTurn(true)
const shownCardIds = [...shownCardsInActiveTurn.keys()]
const completedCardIds = filter(shownCardIds, (cardId) => {
return (
shownCardsInActiveTurn.get(cardId)?.status ===
ShownCardStatus.Complete
)
})
const continueTurnIntoNewRound =
completedCardIds.length === shownCardIds.length &&
drawableCardsWithoutCompletedCardsInActiveTurn(
props.cardsInBowl,
[...shownCardsInActiveTurn.keys()]
).length === 0 &&
props.secondsLeft !== 0
const scorings = compact(
shownCardIds.map<TurnScoringsInsertInput | null>(
(cardId) => {
const card = shownCardsInActiveTurn.get(cardId)
if (card) {
return {
turn_id: props.activeTurn.id,
card_id: cardId,
score:
card.status === ShownCardStatus.Complete ? 1 : 0,
status: card.status,
started_at: new Date(
card.startedAt.getTime() + serverTimeOffset
),
ended_at: new Date(
card.endedAt.getTime() + serverTimeOffset
),
}
} else {
return null
}
}
)
)
const response = await endTurn({
variables: {
currentTurnId: props.activeTurn.id,
completedCardIds: completedCardIds,
gameId: currentGame.id,
currentTurnScorings: scorings,
roundId: continueTurnIntoNewRound
? props.nextRoundId
: props.currentRoundId,
nextTurnplayerId: continueTurnIntoNewRound
? props.activePlayer.id
: nextPlayerForNextTeam(
props.activePlayer,
currentGame.turns,
currentGame.players
).id,
nextTurnSecondsPerTurnOverride: continueTurnIntoNewRound
? Math.round(Number(props.secondsLeft))
: null,
},
})
if (response.errors) {
setEndingTurn(false)
} else if (continueTurnIntoNewRound) {
window.location.reload()
}
}}
>
{t("play.yourTurn.endTurnButton", "End turn")}
</Button>
</Grid>
)}
{props.activeTurnPlayState === ActiveTurnPlayState.Waiting && (
<Grid item>
<Button
variant="contained"
size="large"
color="primary"
disabled={startingTurn}
onClick={async () => {
setStartingTurn(true)
const response = await startTurn({
variables: {
currentTurnId: props.activeTurn.id,
},
})
if (response.errors) {
setStartingTurn(false)
} else {
const firstActiveCard = sample(
drawableCardsWithoutCompletedCardsInActiveTurn(
props.cardsInBowl,
[...shownCardsInActiveTurn.keys()]
)
)
if (firstActiveCard) {
setActiveCard(firstActiveCard)
setShownCardsInActiveTurn(
new Map([
[
firstActiveCard.id,
{
status: ShownCardStatus.Incomplete,
startedAt: new Date(),
endedAt: new Date(),
},
],
])
)
}
props.onStart()
}
}}
>
{t("play.yourTurn.startTurnButton", "Start Turn")}
</Button>
</Grid>
)}
</Grid>
{!isMobile &&
props.activeTurnPlayState === ActiveTurnPlayState.Playing && (
<Grid item style={{ color: grey[600] }}>
{currentGame.allow_card_skips
? t(
"play.yourTurn.shortcutHelper.withSkips",
'Hint: Press the spacebar for "{{ correctButton }}", and S for "{{ skipButton }}"',
{
correctButton: t(
"play.yourTurn.cardButton.correct",
"Correct"
),
skipButton: t("play.yourTurn.cardButton.skip", "Skip"),
}
)
: t(
"play.yourTurn.shortcutHelper.withoutSkips",
'Hint: Press the spacebar for "{{ correctButton }}"',
{
correctButton: t(
"play.yourTurn.cardButton.correct",
"Correct"
),
}
)}
</Grid>
)}
</Grid>
</Box>
)
}
Example #7
Source File: syncdb.ts From crossfeed with Creative Commons Zero v1.0 Universal | 4 votes |
handler: Handler = async (event) => {
const connection = await connectToDatabase(false);
const type = event?.type || event;
const dangerouslyforce = type === 'dangerouslyforce';
if (connection) {
await connection.synchronize(dangerouslyforce);
} else {
console.error('Error: could not sync');
}
if (process.env.NODE_ENV !== 'test') {
// Create indices on elasticsearch only when not using tests.
const client = new ESClient();
if (dangerouslyforce) {
console.log('Deleting all data in elasticsearch...');
await client.deleteAll();
console.log('Done.');
}
await client.syncDomainsIndex();
}
if (type === 'populate') {
console.log('Populating the database with some sample data...');
Sentencer.configure({
nounList: nouns,
adjectiveList: adjectives,
actions: {
entity: () => sample(['city', 'county', 'agency', 'department'])
}
});
const organizationIds: string[] = [];
let tag = await OrganizationTag.findOne(
{ name: SAMPLE_TAG_NAME },
{ relations: ['organizations'] }
);
if (tag) {
await Organization.delete({
id: In(tag.organizations.map((e) => e.id))
});
} else {
tag = await OrganizationTag.create({
name: SAMPLE_TAG_NAME
}).save();
}
for (let i = 0; i <= NUM_SAMPLE_ORGS; i++) {
const organization = await Organization.create({
name: Sentencer.make('{{ adjective }} {{ entity }}').replace(
/\b\w/g,
(l) => l.toUpperCase()
), // Capitalize organization names
rootDomains: ['crossfeed.local'],
ipBlocks: [],
isPassive: false,
tags: [tag]
}).save();
console.log(organization.name);
organizationIds.push(organization.id);
for (let i = 0; i <= NUM_SAMPLE_DOMAINS; i++) {
const randomNum = () => Math.floor(Math.random() * 256);
const domain = await Domain.create({
name: Sentencer.make('{{ adjective }}-{{ noun }}.crossfeed.local'),
ip: ['127', randomNum(), randomNum(), randomNum()].join('.'), // Create random loopback addresses
fromRootDomain: 'crossfeed.local',
subdomainSource: 'findomain',
organization
}).save();
console.log(`\t${domain.name}`);
let service;
for (const serviceData of services) {
if (service && Math.random() < PROB_SAMPLE_SERVICES) continue;
service = await Service.create({
domain,
port: serviceData.port,
service: serviceData.service,
serviceSource: 'shodan',
wappalyzerResults: [
{
technology: {
cpe: sample(cpes)
},
version: ''
}
]
}).save();
}
// Create a bunch of vulnerabilities for the first service
for (const vulnData of vulnerabilities) {
// Sample CVE vulnerabilities, but always add a single instance of other
// vulnerabilities (hibp / dnstwist)
if (
vulnData.title.startsWith('CVE-') &&
Math.random() < PROB_SAMPLE_VULNERABILITIES
)
continue;
await Vulnerability.create({
...vulnData,
domain,
service
} as object).save();
}
}
}
console.log('Done. Running search sync...');
for (const organizationId of organizationIds) {
await searchSync({
organizationId,
scanId: 'scanId',
scanName: 'scanName',
organizationName: 'organizationName',
scanTaskId: 'scanTaskId'
});
}
console.log('Done.');
}
}
Example #8
Source File: search-renderers.spec.ts From js-client with MIT License | 4 votes |
describe('search renderer types', () => {
// Make function to subscript to a search
const subscribeToOneSearch = makeSubscribeToOneSearch(TEST_BASE_API_CONTEXT);
// Use a randomly generated tag, so that we know exactly what we're going to query
const tag = uuidv4();
// The number of entries to generate
const count = 1000;
// The start date for generated queries
const start = new Date(2010, 0, 0);
// The end date for generated queries; one minute between each entry
const end = addMinutes(start, count);
const originalData: Array<Entry> = [];
beforeAll(async () => {
jasmine.addMatchers(myCustomMatchers);
// Generate and ingest some entries
const ingestMultiLineEntry = makeIngestMultiLineEntry(TEST_BASE_API_CONTEXT);
const values: Array<string> = [];
for (let i = 0; i < count; i++) {
const value: Entry = {
category: sample<Entry['category']>(['red', 'blue', 'green']) ?? 'red',
value: random(0, 100),
fixed: 10,
ip: randomIp(),
location: randomCoordinate(),
srclocation: randomCoordinate(),
dstlocation: randomCoordinate(),
timestamp: addMinutes(start, i).toISOString(),
};
originalData.push(value);
values.push(JSON.stringify(value));
}
const data: string = values.join('\n');
await ingestMultiLineEntry({ data, tag, assumeLocalTimezone: false });
// Check the list of tags until our new tag appears
const getAllTags = makeGetAllTags(TEST_BASE_API_CONTEXT);
while (!(await getAllTags()).includes(tag)) {
// Give the backend a moment to catch up
await sleep(1000);
}
await sleep(5000);
}, 25000);
it(
'should search using the point2point renderer',
integrationTest(async () => {
// Perform a query, rendering it as point2point
const query = `tag=${tag} json srclocation.lat as slat srclocation.lon as slon dstlocation.lat as dlat dstlocation.lon as dlon | point2point -srclat slat -srclong slon -dstlat dlat -dstlong dlon`;
const filter: SearchFilter = { entriesOffset: { index: 0, count: count }, dateRange: { start, end } };
const search = await subscribeToOneSearch(query, { filter });
// Wait on the entries to come back
const entries = await lastValueFrom(search.entries$.pipe(takeWhile(e => !e.finished, true)));
// Check the type
expect(entries.type).toEqual('point2point');
// Assert type and make some basic sanity checks
const point2PointEntries = entries as PointToPointSearchEntries;
expect(point2PointEntries.finished).toBeTrue();
expect(point2PointEntries.data.length).toEqual(count);
}),
25000,
);
it(
'should work with queries using the hex renderer, which behaves like the raw renderer',
integrationTest(async () => {
// Perform a query, rendering it as hex
const query = `tag=${tag} hex`;
const filter: SearchFilter = { entriesOffset: { index: 0, count: count }, dateRange: { start, end } };
const search = await subscribeToOneSearch(query, { filter });
// Wait on the entries to come back
const entries = await lastValueFrom(search.entries$.pipe(takeWhile(e => !e.finished, true)));
// Check the type
expect(entries.type).toEqual('hex');
// Assert type and make some basic sanity checks
const hexEntries = entries as HexSearchEntries;
expect(hexEntries.finished).toBeTrue();
expect(hexEntries.data.length).toEqual(count);
}),
25000,
);
it(
'should work with queries using the pcap renderer, which behaves like the text renderer',
integrationTest(async () => {
// Perform a query, rendering it as pcap
const query = `tag=${tag} pcap`;
const filter: SearchFilter = { entriesOffset: { index: 0, count: count }, dateRange: { start, end } };
const search = await subscribeToOneSearch(query, { filter });
// Wait on the entries to come back
const entries = await lastValueFrom(search.entries$.pipe(takeWhile(e => !e.finished, true)));
// Check the type
expect(entries.type).toEqual('pcap');
// Assert type and make some basic sanity checks
const pcapEntries = entries as PcapSearchEntries;
expect(pcapEntries.finished).toBeTrue();
expect(pcapEntries.data.length).toEqual(count);
}),
25000,
);
it(
'should work with queries using the stackgraph renderer',
integrationTest(async () => {
// Perform a query, rendering it as a stackgraph
const query = `tag=${tag} json category fixed value | sum value by category,fixed | stackgraph category fixed sum`;
const filter: SearchFilter = { dateRange: { start, end } };
const search = await subscribeToOneSearch(query, { filter });
// Wait on the entries to come back
const entries = await lastValueFrom(search.entries$.pipe(takeWhile(e => !e.finished, true)));
// Check the type
expect(entries.type).toEqual('stackgraph');
// Assert type and make some basic sanity checks
const stackGraphEntries = entries as StackGraphSearchEntries;
expect(stackGraphEntries.finished).toBeTrue();
expect(stackGraphEntries.data.length).toEqual(3); // the three categories: red, green, blue
}),
25000,
);
});
Example #9
Source File: Landing.tsx From querybook with Apache License 2.0 | 4 votes |
DefaultLanding: React.FC = ({ children }) => {
const {
userInfo,
recentDataDocs,
favoriteDataDocs,
environment,
} = useShallowSelector((state: IStoreState) => {
const recentDataDocsFromState = recentDataDocsSelector(state);
const favoriteDataDocsFromState = favoriteDataDocsSelector(state).slice(
0,
5
);
return {
userInfo: state.user.userInfoById[state.user.myUserInfo.uid],
recentDataDocs: recentDataDocsFromState,
favoriteDataDocs: favoriteDataDocsFromState,
environment: currentEnvironmentSelector(state),
};
});
const dispatch = useDispatch();
React.useEffect(() => {
dispatch(fetchDataDocs('favorite'));
dispatch(fetchDataDocs('recent'));
}, [environment.id]);
const onDataDocClick = React.useCallback((docId) => {
navigateWithinEnv(`/datadoc/${docId}/`);
}, []);
const getRecentDOM = () =>
recentDataDocs.map((dataDoc) => (
<div
className="Landing-data-doc"
onClick={() => onDataDocClick(dataDoc.id)}
key={dataDoc.id}
>
{dataDoc.title || 'Untitled'}
</div>
));
const getFavoriteDOM = () =>
favoriteDataDocs.map((dataDoc) => (
<div
className="Landing-data-doc"
onClick={() => onDataDocClick(dataDoc.id)}
key={dataDoc.id}
>
{dataDoc.title || 'Untitled'}
</div>
));
const [hint] = React.useState(sample(querybookHints));
const LandingHeader = (
<div className="Landing-top horizontal-space-between">
<div>
<div className="Landing-greeting">
Hi {titleize(userInfo.fullname || userInfo.username)},
</div>
<div className="Landing-subtitle">
Welcome back to Querybook
</div>
</div>
<QuerybookSidebarUIGuide />
</div>
);
const LandingFooter = (
<div className="Landing-bottom">
<Columns>
<Column>
<div className="Landing-section-title">Did you know?</div>
<p>{hint}</p>
</Column>
</Columns>
<Columns>
<Column>
<div className="Landing-section-title">Recent DataDocs</div>
<div className="Landing-list">{getRecentDOM()}</div>
</Column>
<Column>
<div className="Landing-section-title">
Favorite DataDocs
</div>
<div className="Landing-list">{getFavoriteDOM()}</div>
</Column>
</Columns>
</div>
);
return (
<div className="Landing flex-column">
{LandingHeader}
<div className="Landing-middle">{children}</div>
{LandingFooter}
</div>
);
}