-
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
/explore #55
base: main
Are you sure you want to change the base?
/explore #55
Changes from 250 commits
34f9922
5b6fa0b
50b1154
56c60c0
072f76e
7eb19a6
287eb7d
e01f11d
8030bca
0f6dab6
9fd0636
a9cf1cd
7fd6cf3
2b8559f
59c03f4
ca10a4f
513ff26
11c033e
daac211
4c622a0
4ac94db
77b03d1
a49dc3b
1355a4b
dbe2cea
62b1e3b
fef17c1
50978cc
ec3276e
eddd6b6
c75e802
2fcbca1
25742f4
f876a14
b48e981
2f29f87
796dc6a
883320c
7f5daca
4f253f3
6bfb761
895c31e
6abb904
0e68fff
3a2ac6e
6bbb59c
dc21fbe
f29ef28
140e322
c3b62ec
d161e55
923a27c
3287d23
7fc4ba7
1466fcb
c93d340
99ff217
9ef2609
85b9dc5
e1599fc
c8e1232
fc82ff6
2e65e6e
9214ad1
0b82df1
4a86a82
0a19d5f
bb0d231
64399bb
8024f0e
a2196db
546bb71
245a296
baa179a
ad39a47
9c99e90
2ca4aae
5148559
f38d9e1
fe2fdc4
513cba9
5131654
4b6a867
95ece2c
11802cd
5b549e0
e4255f4
487e096
460f9c5
3305365
c93ffe7
d8a7e70
52a4332
f24984c
a2177a5
b3d964a
4646019
65d9e57
2eb5415
f6dfa73
afd4770
6573d71
9599bac
66dca56
5de8766
dd83606
cd78f11
4b92c56
c604f42
6f2e158
819d8d8
32e7209
3ee245c
781276b
502e567
3e13144
413225c
4a28a44
4bcaade
3ab0181
276403c
9d87528
16b48c0
fd28f18
acbb9ff
5ad10af
b138b28
d135ab8
a370848
ee5f43b
f5f8dc4
ca48a03
df8e7a5
832a3a1
447becd
ea1e463
b21c8ae
d4875a7
d47d2d3
f13c8bb
b17bbaa
8619619
9d896a3
ac0711c
295ccfb
74f51fe
e7caf64
b432244
1b6ed07
72d1c40
0890787
9b59502
bcccfd4
424e696
547e1f4
67304cd
3b9e812
9e256f2
3f16657
3ff980a
c7558c6
0df129c
6ddd15c
2234ccc
1458410
90fc724
e75e3bf
65b29fb
fd86991
f67187a
d2f407d
0871a92
d5addeb
3a19e8f
122b585
aae5b7a
620a4da
132df44
f7bb492
238c9f7
864e4e9
7e2aab5
3d78c41
f6e13fc
82396d9
4b6bbe1
72f0f09
8563e2d
263b6d7
046ee9b
b22d327
73a565b
69fcae2
2f95437
3f5563b
ff74c4b
c6a8c79
0a9edc7
cfd7f3f
fea1abd
f1c8a08
490a05d
079e532
e3a64ca
9877b9b
fcaf67f
a3468c0
4f17de8
e649f30
3bc9f1f
0458f23
3399474
fb24102
e64a885
308f9b0
48ea80e
1959e98
44646d7
1c74c8b
1029915
083e2c7
b64d902
01aa3cf
5284563
5d366e5
d7a6a36
8b8be3f
4a057a9
4e340df
169af08
bd6cee1
8739f9b
8e675ac
65aeeea
f9bfbf2
6383554
e3b16ba
45d65af
75ce702
02f9ae3
2e2a882
e430f3b
9dd04e7
bd015c7
cfed0e3
23bea27
309be36
f4b7866
07dfd45
af7c7cd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,4 +32,5 @@ yarn-error.log* | |
# vercel | ||
.vercel | ||
|
||
#vs code workspace files | ||
*.code-workspace |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
|
||
import React, { useCallback, useEffect, useState } from 'react'; | ||
import _ from 'lodash'; | ||
|
||
import { useAuth } from '../lib/Auth'; | ||
import { useMatrix } from '../lib/Matrix'; | ||
import LoadingSpinnerInline from './UI/LoadingSpinnerInline'; | ||
|
||
const CachedContextMultiLevelSelectSingleLevel = ({ parentSpaceRoomId, selectedContextRoomId, onSelect, onFetchedChildren, templatePlaceholderMapping, templatePrefixFilter, sortAlphabetically, showTopics }) => { | ||
const auth = useAuth(); | ||
const matrixClient = auth.getAuthenticationProvider('matrix').getMatrixClient(); | ||
const matrix = useMatrix(auth.getAuthenticationProvider('matrix')); | ||
const [isLoading, setIsLoading] = useState(true); | ||
const [parentSpaceMetaEvent, setParentSpaceMetaEvent] = useState(); | ||
const [childContexts, setChildContexts] = useState(); | ||
|
||
useEffect(() => { | ||
let isSubscribed = true; | ||
|
||
// Fetch all child contexts from our storage | ||
const fetchChildContexts = async () => { | ||
let newChildContexts = []; | ||
const spaceCache = await matrix.spaces.get(parentSpaceRoomId) || await matrix.rooms.get(parentSpaceRoomId); | ||
if (!spaceCache) return; | ||
setParentSpaceMetaEvent(spaceCache.meta); | ||
for (const room of spaceCache.children) { | ||
const roomObject = matrix.spaces.get(room) || matrix.rooms.get(room); | ||
// // If this is not a context, ignore this space child | ||
// if (metaEvent && metaEvent.type !== 'context') continue; | ||
// // If we only want to show specific contexts, ignore this space child if its template doesn't have the given prefix | ||
if (templatePrefixFilter && roomObject.meta && !_.startsWith(roomObject.meta.template, templatePrefixFilter)) continue; | ||
// // ... otherwise show this space child: | ||
newChildContexts.push(roomObject); | ||
} | ||
Check failure Code scanning / ESLint Require or disallow padding lines between statements Error
Expected blank line before this statement.
|
||
if (sortAlphabetically) { | ||
newChildContexts = _.sortBy(newChildContexts, 'name'); | ||
} | ||
Check failure Code scanning / ESLint Require or disallow padding lines between statements Error
Expected blank line before this statement.
|
||
if (!isSubscribed) return; | ||
Check failure Code scanning / ESLint Require or disallow padding lines between statements Error
Expected blank line before this statement.
|
||
onFetchedChildren(newChildContexts.length > 0); | ||
setChildContexts(newChildContexts); | ||
}; | ||
|
||
const fetch = async () => { | ||
setIsLoading(true); | ||
await fetchChildContexts(); | ||
setIsLoading(false); | ||
}; | ||
|
||
fetch(); | ||
|
||
return () => { | ||
isSubscribed = false; | ||
}; | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [matrixClient, parentSpaceRoomId, sortAlphabetically, templatePlaceholderMapping, templatePrefixFilter]); | ||
|
||
if (isLoading) { | ||
return <select key="loading" disabled><option><LoadingSpinnerInline /></option></select>; | ||
} | ||
|
||
if (!childContexts || childContexts.length < 1) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<select | ||
value={selectedContextRoomId} | ||
onChange={(e) => { | ||
onSelect(parentSpaceRoomId, e.target.value); | ||
}} | ||
> | ||
{ | ||
(templatePlaceholderMapping && parentSpaceMetaEvent && templatePlaceholderMapping[parentSpaceMetaEvent.template] | ||
// If we have a template-specific placeholder, show that... | ||
? <option disabled value="">{ templatePlaceholderMapping[parentSpaceMetaEvent.template] }</option> | ||
// ... otherwise just show an empty placeholder | ||
: <option disabled value="">-- select --</option> | ||
) | ||
} | ||
{ Object.entries(childContexts).map(([key, room]) => { | ||
// if room is undefined we jumop to the next one | ||
// this can happen when for example a room was not removed as a space child from its parent but is already deleted | ||
if (!room) return; | ||
|
||
return <option key={key} value={room.roomId}> | ||
{ room.name } | ||
{ showTopics && room.topic && (` (${room.topic})`) } | ||
</option>; | ||
}) } | ||
</select> | ||
); | ||
}; | ||
|
||
/** | ||
* This component renders a multi-level <select> UI for an arbitrary set of contexts in the sense of Matrix spaces. | ||
* `activeContexts` is the array of room IDs for the currently set context spaces. | ||
* | ||
* @param {Array} activeContexts | ||
* @param {function} onChange (newActiveContexts, isLeaf) | ||
* @param {boolean} showTopics - If the contents of m.room.topic should be displayed in parentheses next to the name | ||
* @param {boolean} sortAlphabetically - If entries should be ordered alphabetically | ||
* @param {Object} templatePlaceholderMapping - Optional object containing placeholders for each <select> based on the `dev.medienhaus.meta.template` of the parent context | ||
* @param {string} templatePrefixFilter - Optional prefix to filter contexts by their templates | ||
* | ||
* @return {React.ReactElement} | ||
*/ | ||
const CachedContextMultiLevelSelect = ({ activeContexts, onChange, showTopics, sortAlphabetically, templatePlaceholderMapping, templatePrefixFilter }) => { | ||
const onSelect = useCallback((parentContextRoomId, selectedChildContextRoomId) => { | ||
const newActiveContexts = [...activeContexts.splice(0, activeContexts.findIndex((contextRoomId) => contextRoomId === parentContextRoomId) + 1)]; | ||
if (selectedChildContextRoomId) newActiveContexts.push(selectedChildContextRoomId); | ||
onChange(newActiveContexts, undefined); | ||
}, [activeContexts, onChange]); | ||
|
||
const onFinishedFetchingChildren = useCallback((hasChildren) => { | ||
if (onChange.length > 1) { | ||
onChange(activeContexts, !hasChildren); | ||
} | ||
}, [activeContexts, onChange]); | ||
|
||
return ( | ||
<> | ||
{ activeContexts && activeContexts.map((contextRoomId, i) => ( | ||
<CachedContextMultiLevelSelectSingleLevel | ||
key={contextRoomId} | ||
onSelect={onSelect} | ||
onFetchedChildren={onFinishedFetchingChildren} | ||
parentSpaceRoomId={contextRoomId} | ||
selectedContextRoomId={activeContexts[i + 1] ?? ''} | ||
showTopics={showTopics} | ||
sortAlphabetically={sortAlphabetically} | ||
templatePlaceholderMapping={templatePlaceholderMapping} | ||
templatePrefixFilter={templatePrefixFilter} | ||
/> | ||
)) } | ||
</> | ||
); | ||
}; | ||
|
||
export default CachedContextMultiLevelSelect; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import styled from 'styled-components'; | ||
import { useTranslation } from 'react-i18next'; | ||
|
||
|
||
const PreviousNextButtonsWrapper = styled.div` | ||
display: grid; | ||
grid-template-columns: repeat(2, 1fr); | ||
grid-gap: var(--margin); | ||
|
||
&:not(:first-child) { | ||
margin-top: var(--margin); | ||
} | ||
`; | ||
|
||
const NextButton = styled.button` | ||
|
||
color: var(--color-background); | ||
background-color: ${props => props.warning ? 'var(--color-notification)' :'var(--color-foreground)'}; | ||
border-color: ${props => props.warning && 'var(--color-notification)'}; | ||
|
||
&:disabled { | ||
color: var(--color-background); | ||
background-color: var(--color-disabled); | ||
} | ||
`; | ||
|
||
const PreviousButton = styled.button` | ||
|
||
color: var(--color-foreground); | ||
background-color: var(--color-background); | ||
|
||
&:disabled { | ||
color: var(--color-disabled); | ||
background-color: var(--color-background); | ||
} | ||
`; | ||
|
||
/** | ||
* React Component which returns | ||
* | ||
* @param {Boolean} disabled disables both buttons if true | ||
* @param {function} onClick onClick function to execute when clicking 'next' | ||
* @param {function} onCancel function to execute when clicking 'previous' | ||
* @param {Boolean} disableNext disables 'next' button if true | ||
* @param {Boolean} disablePrev disables 'previous' button if true | ||
* @returns {React.JSX} two inline buttons. 'previous' and 'next' | ||
*/ | ||
const PreviousNextButtons = ({ children, disabled, onCancel, disableNext, disablePrev, warning }) => { | ||
const { t } = useTranslation(); | ||
|
||
const handlePrevious = (e) => { | ||
//@TODO check type submit thing | ||
e.preventDefault(); | ||
onCancel(); | ||
}; | ||
|
||
return ( | ||
<PreviousNextButtonsWrapper> | ||
<PreviousButton type="button" disabled={disabled || disablePrev} onClick={handlePrevious}>{ t('Previous') }</PreviousButton> | ||
<NextButton type="submit" disabled={disabled || disableNext} warning={warning}> { children || t('Next') }</NextButton> | ||
</PreviousNextButtonsWrapper> | ||
); | ||
}; | ||
|
||
export default PreviousNextButtons; |
Check failure
Code scanning / ESLint
verifies the list of dependencies for Hooks like useEffect and similar Error