This commit is contained in:
Kurt Hutten
2021-09-18 16:47:17 +10:00
parent d94645d381
commit f3201cfd97
7 changed files with 183 additions and 164 deletions

View File

@@ -76,8 +76,8 @@ function Gooey() {
const z = randomSign(Math.random() * 2) const z = randomSign(Math.random() * 2)
const position: [number, number, number] = [x, z, y] const position: [number, number, number] = [x, z, y]
const size = Math.random() * 0.8 + 0.1 const size = Math.random() * 0.8 + 0.1
const distort = (size > .1) ? Math.random() * .6 * size + 0.2 : 0 const distort = size > 0.1 ? Math.random() * 0.6 * size + 0.2 : 0
const speed = (size > .1) ? (Math.random() * 0.8) / size / size + 0.1 : 0 const speed = size > 0.1 ? (Math.random() * 0.8) / size / size + 0.1 : 0
return { position, size, distort, speed } return { position, size, distort, speed }
}) })
const secondSet = Array.from({ length: 5 }).map((_, index) => { const secondSet = Array.from({ length: 5 }).map((_, index) => {
@@ -87,8 +87,8 @@ function Gooey() {
const z = randomSign(Math.random() * 2) const z = randomSign(Math.random() * 2)
const position: [number, number, number] = [x, z, y] const position: [number, number, number] = [x, z, y]
const size = Math.random() * 0.2 + 0.05 const size = Math.random() * 0.2 + 0.05
const distort = (size > .1) ? Math.random() * .8 * size + 0.2 : 0 const distort = size > 0.1 ? Math.random() * 0.8 * size + 0.2 : 0
const speed = (size > .1) ? (Math.random() * 0.5) / size / size + 0.1 : 0 const speed = size > 0.1 ? (Math.random() * 0.5) / size / size + 0.1 : 0
return { position, size, distort, speed } return { position, size, distort, speed }
}) })
return [...firstSet, ...secondSet] return [...firstSet, ...secondSet]

View File

@@ -53,13 +53,14 @@ export const sidebarTopConfig: SidebarConfigType[] = [
] ]
const DiscordLink = () => ( const DiscordLink = () => (
<a className="underline text-ch-pink-300" <a
href="https://discord.gg/SD7zFRNjGH" className="underline text-ch-pink-300"
target="_blank" href="https://discord.gg/SD7zFRNjGH"
rel="noreferrer" target="_blank"
> rel="noreferrer"
Discord >
</a> Discord
</a>
) )
const settingsConfig = [ const settingsConfig = [
@@ -74,7 +75,8 @@ const settingsConfig = [
</p> </p>
<hr className="my-2" /> <hr className="my-2" />
<p className="p-2"> <p className="p-2">
We're building configuration settings for the Viewer pane now. Join us on <DiscordLink/> if you want to lend a hand! We're building configuration settings for the Viewer pane now. Join us
on <DiscordLink /> if you want to lend a hand!
</p> </p>
</div> </div>
), ),
@@ -90,7 +92,8 @@ const settingsConfig = [
</p> </p>
<hr className="my-2" /> <hr className="my-2" />
<p className="p-2"> <p className="p-2">
We're building configuration settings for the Viewer pane now. Join us on <DiscordLink/> if you want to lend a hand! We're building configuration settings for the Viewer pane now. Join us
on <DiscordLink /> if you want to lend a hand!
</p> </p>
</div> </div>
), ),
@@ -106,7 +109,8 @@ const settingsConfig = [
</p> </p>
<hr className="my-2" /> <hr className="my-2" />
<p className="p-2"> <p className="p-2">
We're building configuration settings for the Viewer pane now. Join us on <DiscordLink/> if you want to lend a hand! We're building configuration settings for the Viewer pane now. Join us
on <DiscordLink /> if you want to lend a hand!
</p> </p>
</div> </div>
), ),

View File

@@ -7,24 +7,25 @@ interface EditToggleType {
} }
const EditToggle = ({ const EditToggle = ({
onEdit = () => { console.error('Field declared editable without edit action.') }, onEdit = () => {
console.error('Field declared editable without edit action.')
},
isEditing = false, isEditing = false,
} : EditToggleType) => ( }: EditToggleType) =>
(isEditing ? ( isEditing ? (
<button <button
className="font-fira-sans text-ch-gray-300 items-center ml-4 grid grid-flow-col-dense p-px px-2 gap-2 bg-ch-blue-500 bg-opacity-50 hover:bg-opacity-70 rounded-sm" className="font-fira-sans text-ch-gray-300 items-center ml-4 grid grid-flow-col-dense p-px px-2 gap-2 bg-ch-blue-500 bg-opacity-50 hover:bg-opacity-70 rounded-sm"
id="rename-button" id="rename-button"
onClick={onEdit} onClick={onEdit}
> >
<Svg name="check" className="w-6 h-6" strokeWidth={3} /> <Svg name="check" className="w-6 h-6" strokeWidth={3} />
<span>Update</span> <span>Update</span>
</button> </button>
) : ( ) : (
<button onClick={onEdit}> <button onClick={onEdit}>
<Svg name="pencil-solid" className="h-4 w-4 ml-4 mb-2" /> <Svg name="pencil-solid" className="h-4 w-4 ml-4 mb-2" />
</button> </button>
)) )
)
interface KeyValueType { interface KeyValueType {
keyName: string keyName: string
@@ -51,7 +52,7 @@ const KeyValue = ({
} }
> >
<span className={edit ? 'text-ch-blue-300' : ''}>{keyName}</span> <span className={edit ? 'text-ch-blue-300' : ''}>{keyName}</span>
{edit && edit.hasPermissionToEdit && <EditToggle {...edit} /> } {edit && edit.hasPermissionToEdit && <EditToggle {...edit} />}
</div> </div>
<div className={'text-ch-gray-300 ' + (bottom ? 'mb-1' : 'mt-1')}> <div className={'text-ch-gray-300 ' + (bottom ? 'mb-1' : 'mt-1')}>
{children} {children}

View File

@@ -32,10 +32,7 @@ const ProjectCard = ({ title, mainImage, user, Reaction, cadPackage }) => (
</div> </div>
<div className="flex items-center mt-1"> <div className="flex items-center mt-1">
<div className="w-8 h-8 overflow-hidden rounded-full border border-ch-gray-300 shadow"> <div className="w-8 h-8 overflow-hidden rounded-full border border-ch-gray-300 shadow">
<ImageFallback <ImageFallback imageId={user?.image} width={80} />
imageId={user?.image}
width={80}
/>
</div> </div>
<div className="ml-3 text-lg text-ch-gray-300 font-fira-sans"> <div className="ml-3 text-lg text-ch-gray-300 font-fira-sans">
<div className="">{title}</div> <div className="">{title}</div>

View File

@@ -102,41 +102,43 @@ const ProjectProfile = ({
className="px-3 py-2 rounded" className="px-3 py-2 rounded"
/> />
</div> </div>
{ (project?.description || hasPermissionToEdit) && <KeyValue {(project?.description || hasPermissionToEdit) && (
keyName="Description" <KeyValue
edit={{ keyName="Description"
hasPermissionToEdit, edit={{
isEditing, hasPermissionToEdit,
onEdit: () => { isEditing,
if (!isEditing) { onEdit: () => {
setIsEditing(true) if (!isEditing) {
} else { setIsEditing(true)
onEditSaveClick() } else {
setIsEditing(false) onEditSaveClick()
} setIsEditing(false)
}, }
}} },
> }}
<div
id="description-wrap"
name="description"
className={
'markdown-overrides rounded-sm pb-2 mt-2' +
(isEditing ? ' min-h-md' : '')
}
onClick={(e) =>
e?.target?.id === 'description-wrap' &&
editorRef?.current?.focusAtEnd()
}
> >
<Editor <div
ref={editorRef} id="description-wrap"
defaultValue={project?.description || ''} name="description"
readOnly={!isEditing} className={
onChange={onDescriptionChange} 'markdown-overrides rounded-sm pb-2 mt-2' +
/> (isEditing ? ' min-h-md' : '')
</div> }
</KeyValue> } onClick={(e) =>
e?.target?.id === 'description-wrap' &&
editorRef?.current?.focusAtEnd()
}
>
<Editor
ref={editorRef}
defaultValue={project?.description || ''}
readOnly={!isEditing}
onChange={onDescriptionChange}
/>
</div>
</KeyValue>
)}
<div className="grid grid-flow-col-dense gap-6"> <div className="grid grid-flow-col-dense gap-6">
<KeyValue keyName="Created on"> <KeyValue keyName="Created on">
{new Date(project?.createdAt).toDateString()} {new Date(project?.createdAt).toDateString()}
@@ -154,64 +156,68 @@ const ProjectProfile = ({
className="" className=""
/> />
</KeyValue> </KeyValue>
{ currentUser && <KeyValue keyName="Comments"> {currentUser && (
{!isEditing && ( <KeyValue keyName="Comments">
<> {!isEditing && (
{currentUser && ( <>
<> {currentUser && (
<div className="pt-1"> <>
<textarea <div className="pt-1">
className="w-full h-32 rounded shadow-inner outline-none resize-none p-3 bg-ch-gray-600 placeholder-ch-gray-500 font-fira-sans" <textarea
placeholder="Have a question about this model, or a helpful tip about how to improve it? Remember, be nice!" className="w-full h-32 rounded shadow-inner outline-none resize-none p-3 bg-ch-gray-600 placeholder-ch-gray-500 font-fira-sans"
value={comment} placeholder="Have a question about this model, or a helpful tip about how to improve it? Remember, be nice!"
onChange={({ target }) => value={comment}
setComment(target.value) onChange={({ target }) =>
} setComment(target.value)
/> }
</div> />
<Button </div>
className={getActiveClasses( <Button
'ml-auto hover:bg-opacity-100 bg-ch-pink-800 bg-opacity-30 mt-4 mb-6 text-ch-gray-300', className={getActiveClasses(
{ 'bg-indigo-200': currentUser } 'ml-auto hover:bg-opacity-100 bg-ch-pink-800 bg-opacity-30 mt-4 mb-6 text-ch-gray-300',
)} { 'bg-indigo-200': currentUser }
shouldAnimateHover )}
disabled={!currentUser} shouldAnimateHover
iconName={''} disabled={!currentUser}
onClick={onCommentClear} iconName={''}
> onClick={onCommentClear}
Comment >
</Button> Comment
</> </Button>
)} </>
<ul>
{project?.Comment.map(
({ text, user, id, createdAt }) => (
<li key={id} className="mb-5">
<div className="flex justify-between">
<Link
className="flex items-center"
to={routes.user({ userName: user?.userName })}
>
<Gravatar
image={user?.image}
className="w-10 h-10 mr-4"
/>
{user?.userName}
</Link>
<div className="font-fira-code text-ch-blue-400 flex items-center">
{new Date(createdAt).toDateString()}
</div>
</div>
<div className="ml-5 border-l-2 pl-5 my-3 border-ch-gray-300 text-ch-gray-300">
{text}
</div>
</li>
)
)} )}
</ul> <ul>
</> {project?.Comment.map(
)} ({ text, user, id, createdAt }) => (
</KeyValue> } <li key={id} className="mb-5">
<div className="flex justify-between">
<Link
className="flex items-center"
to={routes.user({
userName: user?.userName,
})}
>
<Gravatar
image={user?.image}
className="w-10 h-10 mr-4"
/>
{user?.userName}
</Link>
<div className="font-fira-code text-ch-blue-400 flex items-center">
{new Date(createdAt).toDateString()}
</div>
</div>
<div className="ml-5 border-l-2 pl-5 my-3 border-ch-gray-300 text-ch-gray-300">
{text}
</div>
</li>
)
)}
</ul>
</>
)}
</KeyValue>
)}
{hasPermissionToEdit && ( {hasPermissionToEdit && (
<> <>
<h4 className="mt-10 text-red-600">Danger Zone</h4> <h4 className="mt-10 text-red-600">Danger Zone</h4>

View File

@@ -13,15 +13,18 @@ import {
// This function initializes the state management object for each of the fields // This function initializes the state management object for each of the fields
function buildFieldsConfig(fieldsConfig, user, hasPermissionToEdit) { function buildFieldsConfig(fieldsConfig, user, hasPermissionToEdit) {
return Object.fromEntries(Object.keys(fieldsConfig).map( return Object.fromEntries(
(key: string): [string, FieldType] => ([key, { Object.keys(fieldsConfig).map((key: string): [string, FieldType] => [
name: key, key,
currentValue: user[key], {
newValue: user[key], name: key,
isEditing: false, currentValue: user[key],
hasPermissionToEdit, newValue: user[key],
}]) isEditing: false,
)) hasPermissionToEdit,
},
])
)
} }
const UserProfile = ({ const UserProfile = ({
@@ -39,7 +42,11 @@ const UserProfile = ({
navigate(routes.user({ userName: user.userName })) navigate(routes.user({ userName: user.userName }))
}, [currentUser]) }, [currentUser])
const initializedFields = buildFieldsConfig(fieldComponents, user, hasPermissionToEdit) const initializedFields = buildFieldsConfig(
fieldComponents,
user,
hasPermissionToEdit
)
const [fields, fieldDispatch] = useReducer(fieldReducer, initializedFields) const [fields, fieldDispatch] = useReducer(fieldReducer, initializedFields)
const { const {
name: NameField, name: NameField,

View File

@@ -51,29 +51,32 @@ const ProfileKeyValue = ({
hasPermissionToEdit, hasPermissionToEdit,
children, children,
bottom = false, bottom = false,
} : ProfileKeyValueType) => { }: ProfileKeyValueType) => {
return ( return (
(user[field.name] && hasPermissionToEdit) && <KeyValue user[field.name] &&
keyName={field.name} hasPermissionToEdit && (
edit={{ <KeyValue
hasPermissionToEdit, keyName={field.name}
isEditing: field.isEditing, edit={{
onEdit: () => { hasPermissionToEdit,
if (field.isEditing && field.currentValue !== field.newValue) { isEditing: field.isEditing,
save(user.userName, { [field.name]: field.newValue }) onEdit: () => {
} if (field.isEditing && field.currentValue !== field.newValue) {
dispatch({ save(user.userName, { [field.name]: field.newValue })
type: 'SET_CURRENT_VALUE', }
payload: { field: field.name, value: field.newValue }, dispatch({
}) type: 'SET_CURRENT_VALUE',
dispatch({ type: 'TOGGLE_EDITING', payload: field.name }) payload: { field: field.name, value: field.newValue },
}, })
}} dispatch({ type: 'TOGGLE_EDITING', payload: field.name })
bottom={bottom} },
className="mb-4" }}
> bottom={bottom}
{children} className="mb-4"
</KeyValue> >
{children}
</KeyValue>
)
) )
} }
@@ -110,7 +113,7 @@ function BioField(props) {
) )
} }
function MemberSinceField(props : FieldComponentPropsType) { function MemberSinceField(props: FieldComponentPropsType) {
return ( return (
<KeyValue keyName="Member Since"> <KeyValue keyName="Member Since">
<p className="text-ch-gray-300"> <p className="text-ch-gray-300">
@@ -120,7 +123,7 @@ function MemberSinceField(props : FieldComponentPropsType) {
) )
} }
function ImageField(props : FieldComponentPropsType) { function ImageField(props: FieldComponentPropsType) {
const { field, user, save, hasPermissionToEdit } = props const { field, user, save, hasPermissionToEdit } = props
return ( return (
<ImageUploader <ImageUploader
@@ -138,7 +141,7 @@ function ImageField(props : FieldComponentPropsType) {
) )
} }
function NameField(props : FieldComponentPropsType) { function NameField(props: FieldComponentPropsType) {
const { user, dispatch, field } = props const { user, dispatch, field } = props
return ( return (
@@ -162,7 +165,7 @@ function NameField(props : FieldComponentPropsType) {
) )
} }
function UserNameField(props : FieldComponentPropsType) { function UserNameField(props: FieldComponentPropsType) {
const { dispatch, field } = props const { dispatch, field } = props
return ( return (
@@ -196,7 +199,8 @@ export function fieldReducer(state, action) {
[action.payload]: { [action.payload]: {
...state[action.payload], ...state[action.payload],
isEditing: isEditing:
state[action.payload].hasPermissionToEdit && !state[action.payload].isEditing state[action.payload].hasPermissionToEdit &&
!state[action.payload].isEditing
? true ? true
: false, : false,
}, },