Repository navigation
feat(tasks): edit task proerties from task preview #6217
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
Changes from all commits
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 |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| import { InlinePropertyValue } from '@block-md/component/InlinePropertyValue'; | ||
| import { | ||
| getPermissions, | ||
| hasPermissions, | ||
| Permissions, | ||
| } from '@core/component/SharePermissions'; | ||
| import { Modals } from '@property/component/modal'; | ||
| import { SYSTEM_PROPERTY_IDS } from '@property/constants'; | ||
| import { | ||
| PropertiesProvider, | ||
| type PropertySaveHandler, | ||
| } from '@property/context/PropertiesContext'; | ||
| import { useEntityProperties } from '@property/hooks'; | ||
| import type { Property, PropertyApiValues } from '@property/types'; | ||
| import { useBulkSaveEntityPropertiesMutation } from '@queries/properties/entity'; | ||
| import { useDocumentAccessLevelQuery } from '@queries/storage/document-metadata'; | ||
| import { createMemo, For, Show } from 'solid-js'; | ||
|
|
||
| const TASK_PREVIEW_PROPERTIES = [ | ||
| SYSTEM_PROPERTY_IDS.STATUS, | ||
| SYSTEM_PROPERTY_IDS.PRIORITY, | ||
| SYSTEM_PROPERTY_IDS.ASSIGNEES, | ||
| ]; | ||
|
|
||
| /** Status, priority, and assignee editors for a task preview card. */ | ||
| export function TaskPropertiesPreview(props: { | ||
| taskId: string; | ||
| taskName?: string; | ||
| }) { | ||
| const { properties, isLoading, refetch } = useEntityProperties( | ||
| props.taskId, | ||
| 'TASK', | ||
| false | ||
| ); | ||
| const accessQuery = useDocumentAccessLevelQuery(() => props.taskId); | ||
| const saveMutation = useBulkSaveEntityPropertiesMutation(); | ||
|
|
||
| const previewProperties = createMemo(() => | ||
| TASK_PREVIEW_PROPERTIES.flatMap((id) => { | ||
| const property = properties().find( | ||
| (candidate) => candidate.propertyDefinitionId === id | ||
| ); | ||
| return property ? [property] : []; | ||
| }) | ||
| ); | ||
|
|
||
| const canEdit = () => | ||
| accessQuery.isSuccess && | ||
| hasPermissions(getPermissions(accessQuery.data), Permissions.CAN_EDIT); | ||
|
|
||
| const saveOne = (property: Property, apiValues: PropertyApiValues) => | ||
| saveMutation.mutateAsync({ | ||
| properties: [ | ||
| { entityId: props.taskId, entityType: 'TASK', property, apiValues }, | ||
| ], | ||
| }); | ||
|
|
||
| const saveHandler: PropertySaveHandler = { | ||
| saveProperty: (property, value) => saveOne(property, value), | ||
| saveDate: (property, date) => | ||
| saveOne(property, { valueType: 'DATE', value: date }), | ||
| }; | ||
|
|
||
| return ( | ||
| <Show when={!isLoading() && previewProperties().length > 0}> | ||
| <PropertiesProvider | ||
| entityId={props.taskId} | ||
| entityType="TASK" | ||
| canEdit={canEdit()} | ||
| documentName={props.taskName} | ||
| properties={previewProperties} | ||
| onRefresh={refetch} | ||
| onPropertyAdded={refetch} | ||
| onPropertyDeleted={refetch} | ||
| saveHandler={saveHandler} | ||
| > | ||
| <div class="px-2 pb-2 flex flex-row flex-wrap gap-1 text-xs justify-start"> | ||
| <For each={previewProperties()}> | ||
| {(property) => ( | ||
| <InlinePropertyValue | ||
| property={property} | ||
| entityId={props.taskId} | ||
| class="bg-surface-2 border border-edge" | ||
| /> | ||
| )} | ||
| </For> | ||
| </div> | ||
| <Modals /> | ||
| </PropertiesProvider> | ||
| </Show> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -67,6 +67,9 @@ export const entityKeys = createQueryKeys('entity', { | |
| documentMetadata: (documentId: string) => ({ | ||
| queryKey: [documentId], | ||
| }), | ||
| documentAccessLevel: (documentId: string) => ({ | ||
| queryKey: [documentId, 'accessLevel'], | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -e
printf '%s\n' '--- keys.ts ---'
sed -n '1,130p' apps/web/src/lib/queries/storage/keys.ts
printf '%s\n' '--- accessLevel references ---'
rg -n -C 3 "documentAccessLevel|accessLevel" apps/web/src --glob '*.{ts,tsx}'
printf '%s\n' '--- query cache lifecycle references ---'
rg -n -C 3 "removeQueries|resetQueries|clear\\(|invalidateQueries|setQueryData|queryClient" apps/web/src --glob '*.{ts,tsx}' | head -n 300Repository: macro-inc/macro Length of output: 50372 🤖 get_repo_knowledge executed:
Length of output: 47878 🏁 Script executed: #!/bin/bash
set -e
log=/tmp/coderabbit-shell-logs/shell-output-5x5ilh
printf '%s\n' '--- initial source output ---'
sed -n '1,180p' "$log"
printf '%s\n' '--- relevant non-generated references ---'
rg -n -C 4 "documentAccessLevel|userAccessLevel" apps/web/src \
-g '!**/generated/**' -g '!**/*.generated.*' -g '!**/node_modules/**'
printf '%s\n' '--- access-level consumers and key definitions ---'
rg -n -C 5 "accessLevel|entityKeys\\.documentAccessLevel" apps/web/src/lib apps/web/src/features \
-g '!**/generated/**' -g '!**/*.generated.*' -g '!**/node_modules/**' | head -n 240
printf '%s\n' '--- identity transition and query-client lifecycle ---'
rg -n -C 4 "signOut|logout|logOut|onLogout|removeQueries|resetQueries|queryClient\\.clear|queryClient\\.remove|QueryClientProvider" apps/web/src \
-g '!**/generated/**' -g '!**/*.generated.*' -g '!**/node_modules/**' | head -n 360Repository: macro-inc/macro Length of output: 50371 🤖 get_repo_knowledge executed:
Length of output: 47771 🏁 Script executed: #!/bin/bash
set -e
printf '%s\n' '--- access-level query implementation ---'
sed -n '1,90p' apps/web/src/lib/queries/storage/document-metadata.ts
printf '%s\n' '--- access-level query consumers ---'
rg -n -C 6 "useDocumentAccessLevelQuery|documentAccessLevel" apps/web/src \
-g '!**/generated/**' -g '!**/*.generated.*' -g '!**/node_modules/**'
printf '%s\n' '--- query client files ---'
fd -i 'client|query' apps/web/src/lib/queries apps/web/src/lib/core/context -t f \
| rg 'query|client|user'
printf '%s\n' '--- auth context and query client lifecycle ---'
for f in apps/web/src/lib/core/context/user.ts apps/web/src/lib/queries/client.ts; do
if test -f "$f"; then
echo "--- $f ---"
sed -n '1,260p' "$f"
fi
done
printf '%s\n' '--- all QueryClient lifecycle calls, excluding generated files ---'
rg -n -C 5 "QueryClient|queryClient\\.(clear|removeQueries|resetQueries|invalidateQueries)|removeQueries\\(|resetQueries\\(|\\.clear\\(" apps/web/src \
-g '!**/generated/**' -g '!**/*.generated.*' -g '!**/node_modules/**' \
| head -n 500Repository: macro-inc/macro Length of output: 50371 🤖 get_repo_knowledge executed:
Length of output: 40924 🏁 Script executed: #!/bin/bash
set -e
printf '%s\n' '--- direct permission consumer ---'
sed -n '1,130p' apps/web/src/lib/core/component/TaskPropertiesPreview.tsx
printf '%s\n' '--- persistence scope and hydration ---'
for f in apps/web/src/lib/queries/persistence-scopes.ts apps/web/src/lib/queries/persistence/index.ts; do
if test -f "$f"; then
echo "--- $f ---"
sed -n '1,280p' "$f"
fi
done
printf '%s\n' '--- authentication transition entry points ---'
rg -l -i "logout|log out|sign out|signout|clearLocalAuthSession|login.*success|session.*clear" apps/web/src \
-g '!**/generated/**' -g '!**/*.generated.*' -g '!**/node_modules/**' \
| head -n 120
printf '%s\n' '--- likely transition implementations ---'
rg -n -C 8 -i "clearLocalAuthSession|logout|signOut|signout|logOut" apps/web/src/features apps/web/src/lib apps/web/src/routes \
-g '!**/generated/**' -g '!**/*.generated.*' -g '!**/node_modules/**' \
| head -n 320Repository: macro-inc/macro Length of output: 32176 🤖 get_repo_knowledge executed:
Length of output: 47834 🏁 Script executed: #!/bin/bash
set -e
printf '%s\n' '--- local auth cleanup ---'
sed -n '1,260p' apps/web/src/lib/core/auth/logout.ts
printf '%s\n' '--- account logout callers ---'
rg -n -C 10 "clearLocalAuthSession|logout\\(" apps/web/src/features/settings apps/web/src/components/app apps/web/src/lib/core/auth \
-g '!**/generated/**' -g '!**/*.generated.*' -g '!**/node_modules/**'
printf '%s\n' '--- query cache references in auth lifecycle ---'
rg -n -C 8 "queryClient|clearRegisteredCaches|rotateCacheScope|invalidateUserInfo" apps/web/src/lib/core/auth apps/web/src/features/settings apps/web/src/routes \
-g '!**/generated/**' -g '!**/*.generated.*' -g '!**/node_modules/**'Repository: macro-inc/macro Length of output: 32389 🤖 get_repo_knowledge executed:
Length of output: 47849 🏁 Script executed: #!/bin/bash
set -e
printf '%s\n' '--- document query cache cleanup ---'
sed -n '1,260p' apps/web/src/lib/queries/storage/document-cache.ts
printf '%s\n' '--- all callers and implementation references ---'
rg -n -C 8 "clearDocumentQueryCache|documentKeys|entityKeys\\._def|entityKeys" apps/web/src/lib/queries apps/web/src/lib/core/auth apps/web/src/routes \
-g '!**/generated/**' -g '!**/*.generated.*' -g '!**/node_modules/**'Repository: macro-inc/macro Length of output: 22223 🏁 Script executed: #!/bin/bash
set -e
printf '%s\n' '--- property mutation and authorization boundary ---'
rg -n -C 8 "useBulkSaveEntityPropertiesMutation|bulkSaveEntityProperties|saveEntityProperties|update.*propert" apps/web/src/lib/queries apps/web/src/lib/service-clients \
-g '!**/generated/**' -g '!**/*.generated.*' -g '!**/node_modules/**' | head -n 260
printf '%s\n' '--- server-side property mutation definitions ---'
rg -n -C 6 "bulk_save.*propert|save.*propert|update.*propert|properties.*mutation" crates services \
-g '*.rs' -g '!**/target/**' | head -n 260Repository: macro-inc/macro Length of output: 47385 Prevent stale access levels from enabling edit controls.
🤖 Prompt for AI Agents |
||
| }), | ||
| projectData: (projectId: string) => ({ | ||
| queryKey: [projectId], | ||
| }), | ||
|
|
||
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.
Preview stays open after edit
Medium Severity
useHoldParentHoverCardOpenkeeps the task preview mounted by ignoring hover-card close while the property editor is open. That close is not retried after the portaled picker dismisses, so if the pointer is already outside the preview it can stay on screen until scroll, another hover card, or a later re-hover.Additional Locations (2)
apps/web/src/features/property/core/Root.tsx#L37-L38apps/web/src/lib/core/component/HoverCard.tsx#L269-L280Reviewed by Cursor Bugbot for commit f16e7f7. Configure here.