sanity-plugin-workflow 1.0.6 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -17
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1647 -0
- package/dist/index.js.map +1 -0
- package/package.json +30 -69
- package/lib/index.d.ts +0 -20
- package/lib/index.esm.js +0 -2135
- package/lib/index.esm.js.map +0 -1
- package/lib/index.js +0 -2147
- package/lib/index.js.map +0 -1
- package/sanity.json +0 -8
- package/src/actions/AssignWorkflow.tsx +0 -47
- package/src/actions/BeginWorkflow.tsx +0 -63
- package/src/actions/CompleteWorkflow.tsx +0 -64
- package/src/actions/UpdateWorkflow.tsx +0 -126
- package/src/badges/AssigneesBadge.tsx +0 -53
- package/src/badges/StateBadge.tsx +0 -28
- package/src/components/DocumentCard/AvatarGroup.tsx +0 -43
- package/src/components/DocumentCard/CompleteButton.tsx +0 -56
- package/src/components/DocumentCard/EditButton.tsx +0 -28
- package/src/components/DocumentCard/Field.tsx +0 -38
- package/src/components/DocumentCard/Validate.tsx +0 -21
- package/src/components/DocumentCard/ValidationStatus.tsx +0 -37
- package/src/components/DocumentCard/core/DraftStatus.tsx +0 -32
- package/src/components/DocumentCard/core/PublishedStatus.tsx +0 -39
- package/src/components/DocumentCard/core/TimeAgo.tsx +0 -11
- package/src/components/DocumentCard/index.tsx +0 -200
- package/src/components/DocumentList.tsx +0 -169
- package/src/components/Filters.tsx +0 -174
- package/src/components/FloatingCard.tsx +0 -36
- package/src/components/StateTitle/Status.tsx +0 -27
- package/src/components/StateTitle/index.tsx +0 -78
- package/src/components/UserAssignment.tsx +0 -121
- package/src/components/UserAssignmentInput.tsx +0 -27
- package/src/components/UserDisplay.tsx +0 -57
- package/src/components/Verify.tsx +0 -297
- package/src/components/WorkflowContext.tsx +0 -71
- package/src/components/WorkflowSignal.tsx +0 -30
- package/src/components/WorkflowTool.tsx +0 -437
- package/src/constants/index.ts +0 -31
- package/src/helpers/arraysContainMatchingString.ts +0 -6
- package/src/helpers/filterItemsAndSort.ts +0 -41
- package/src/helpers/generateMultipleOrderRanks.ts +0 -80
- package/src/helpers/initialRank.ts +0 -13
- package/src/hooks/useWorkflowDocuments.tsx +0 -167
- package/src/hooks/useWorkflowMetadata.tsx +0 -49
- package/src/index.ts +0 -97
- package/src/schema/workflow/workflow.metadata.ts +0 -68
- package/src/tools/index.ts +0 -15
- package/src/types/index.ts +0 -71
- package/v2-incompatible.js +0 -11
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
/* eslint-disable react/prop-types */
|
|
2
|
-
import {DragHandleIcon} from '@sanity/icons'
|
|
3
|
-
import {Box, Card, CardTone, Flex, Stack, useTheme} from '@sanity/ui'
|
|
4
|
-
import {useCallback, useEffect, useMemo, useState} from 'react'
|
|
5
|
-
import {
|
|
6
|
-
SchemaType,
|
|
7
|
-
useSchema,
|
|
8
|
-
ValidationStatus as ValidationStatusType,
|
|
9
|
-
} from 'sanity'
|
|
10
|
-
import {Preview} from 'sanity'
|
|
11
|
-
|
|
12
|
-
import {SanityDocumentWithMetadata, State, User} from '../../types'
|
|
13
|
-
import UserDisplay from '../UserDisplay'
|
|
14
|
-
import CompleteButton from './CompleteButton'
|
|
15
|
-
import {DraftStatus} from './core/DraftStatus'
|
|
16
|
-
import {PublishedStatus} from './core/PublishedStatus'
|
|
17
|
-
import EditButton from './EditButton'
|
|
18
|
-
import Validate from './Validate'
|
|
19
|
-
import {ValidationStatus} from './ValidationStatus'
|
|
20
|
-
|
|
21
|
-
type DocumentCardProps = {
|
|
22
|
-
isDragDisabled: boolean
|
|
23
|
-
isPatching: boolean
|
|
24
|
-
userRoleCanDrop: boolean
|
|
25
|
-
isDragging: boolean
|
|
26
|
-
item: SanityDocumentWithMetadata
|
|
27
|
-
states: State[]
|
|
28
|
-
toggleInvalidDocumentId: (
|
|
29
|
-
documentId: string,
|
|
30
|
-
action: 'ADD' | 'REMOVE'
|
|
31
|
-
) => void
|
|
32
|
-
userList: User[]
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function DocumentCard(props: DocumentCardProps) {
|
|
36
|
-
const {
|
|
37
|
-
isDragDisabled,
|
|
38
|
-
isPatching,
|
|
39
|
-
userRoleCanDrop,
|
|
40
|
-
isDragging,
|
|
41
|
-
item,
|
|
42
|
-
states,
|
|
43
|
-
toggleInvalidDocumentId,
|
|
44
|
-
userList,
|
|
45
|
-
} = props
|
|
46
|
-
const {assignees = [], documentId} = item._metadata ?? {}
|
|
47
|
-
const schema = useSchema()
|
|
48
|
-
const state = states.find((s) => s.id === item._metadata?.state)
|
|
49
|
-
|
|
50
|
-
const isDarkMode = useTheme().sanity.color.dark
|
|
51
|
-
const defaultCardTone = isDarkMode ? `transparent` : `default`
|
|
52
|
-
|
|
53
|
-
// Validation only runs if the state requests it
|
|
54
|
-
// Because it's not performant to run it on many documents simultaneously
|
|
55
|
-
// So we fake it here, and maybe set it inside <Validate />
|
|
56
|
-
const [optimisticValidation, setOptimisticValidation] =
|
|
57
|
-
useState<ValidationStatusType>({
|
|
58
|
-
isValidating: state?.requireValidation ?? false,
|
|
59
|
-
validation: [],
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
const {isValidating, validation} = optimisticValidation
|
|
63
|
-
|
|
64
|
-
const handleValidation = useCallback((updates: ValidationStatusType) => {
|
|
65
|
-
setOptimisticValidation(updates)
|
|
66
|
-
}, [])
|
|
67
|
-
|
|
68
|
-
const cardTone = useMemo(() => {
|
|
69
|
-
let tone: CardTone = defaultCardTone
|
|
70
|
-
|
|
71
|
-
if (!userRoleCanDrop) return isDarkMode ? `default` : `transparent`
|
|
72
|
-
if (!documentId) return tone
|
|
73
|
-
if (isPatching) tone = isDarkMode ? `default` : `transparent`
|
|
74
|
-
if (isDragging) tone = `positive`
|
|
75
|
-
|
|
76
|
-
if (state?.requireValidation && !isValidating && validation.length > 0) {
|
|
77
|
-
if (validation.some((v) => v.level === 'error')) {
|
|
78
|
-
tone = `critical`
|
|
79
|
-
} else {
|
|
80
|
-
tone = `caution`
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return tone
|
|
85
|
-
}, [
|
|
86
|
-
defaultCardTone,
|
|
87
|
-
userRoleCanDrop,
|
|
88
|
-
isPatching,
|
|
89
|
-
isDarkMode,
|
|
90
|
-
documentId,
|
|
91
|
-
isDragging,
|
|
92
|
-
isValidating,
|
|
93
|
-
validation,
|
|
94
|
-
state?.requireValidation,
|
|
95
|
-
])
|
|
96
|
-
|
|
97
|
-
// Update validation status
|
|
98
|
-
// Cannot be done in the above memo because it would set state during render
|
|
99
|
-
useEffect(() => {
|
|
100
|
-
if (!isValidating && validation.length > 0) {
|
|
101
|
-
if (validation.some((v) => v.level === 'error')) {
|
|
102
|
-
toggleInvalidDocumentId(documentId, 'ADD')
|
|
103
|
-
} else {
|
|
104
|
-
toggleInvalidDocumentId(documentId, 'REMOVE')
|
|
105
|
-
}
|
|
106
|
-
} else {
|
|
107
|
-
toggleInvalidDocumentId(documentId, 'REMOVE')
|
|
108
|
-
}
|
|
109
|
-
}, [documentId, isValidating, toggleInvalidDocumentId, validation])
|
|
110
|
-
|
|
111
|
-
const hasError = useMemo(
|
|
112
|
-
() => (isValidating ? false : validation.some((v) => v.level === 'error')),
|
|
113
|
-
[isValidating, validation]
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
const isLastState = useMemo(
|
|
117
|
-
() => states[states.length - 1].id === item._metadata?.state,
|
|
118
|
-
[states, item._metadata.state]
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
return (
|
|
122
|
-
<>
|
|
123
|
-
{state?.requireValidation ? (
|
|
124
|
-
<Validate
|
|
125
|
-
documentId={documentId}
|
|
126
|
-
type={item._type}
|
|
127
|
-
onChange={handleValidation}
|
|
128
|
-
/>
|
|
129
|
-
) : null}
|
|
130
|
-
<Box paddingBottom={3} paddingX={3}>
|
|
131
|
-
<Card radius={2} shadow={isDragging ? 3 : 1} tone={cardTone}>
|
|
132
|
-
<Stack>
|
|
133
|
-
<Card
|
|
134
|
-
borderBottom
|
|
135
|
-
radius={2}
|
|
136
|
-
paddingRight={2}
|
|
137
|
-
tone={cardTone}
|
|
138
|
-
style={{pointerEvents: 'none'}}
|
|
139
|
-
>
|
|
140
|
-
<Flex align="center" justify="space-between" gap={1}>
|
|
141
|
-
<Box flex={1}>
|
|
142
|
-
<Preview
|
|
143
|
-
layout="default"
|
|
144
|
-
skipVisibilityCheck
|
|
145
|
-
value={item}
|
|
146
|
-
schemaType={schema.get(item._type) as SchemaType}
|
|
147
|
-
/>
|
|
148
|
-
</Box>
|
|
149
|
-
<Box style={{flexShrink: 0}}>
|
|
150
|
-
{hasError || isDragDisabled || isPatching ? null : (
|
|
151
|
-
<DragHandleIcon />
|
|
152
|
-
)}
|
|
153
|
-
</Box>
|
|
154
|
-
</Flex>
|
|
155
|
-
</Card>
|
|
156
|
-
|
|
157
|
-
<Card padding={2} radius={2} tone="inherit">
|
|
158
|
-
<Flex align="center" justify="space-between" gap={3}>
|
|
159
|
-
<Box flex={1}>
|
|
160
|
-
{documentId && (
|
|
161
|
-
<UserDisplay
|
|
162
|
-
userList={userList}
|
|
163
|
-
assignees={assignees}
|
|
164
|
-
documentId={documentId}
|
|
165
|
-
disabled={!userRoleCanDrop}
|
|
166
|
-
/>
|
|
167
|
-
)}
|
|
168
|
-
</Box>
|
|
169
|
-
{validation.length > 0 ? (
|
|
170
|
-
<ValidationStatus validation={validation} />
|
|
171
|
-
) : null}
|
|
172
|
-
<DraftStatus document={item} />
|
|
173
|
-
<PublishedStatus document={item} />
|
|
174
|
-
<EditButton
|
|
175
|
-
id={item._id}
|
|
176
|
-
type={item._type}
|
|
177
|
-
disabled={!userRoleCanDrop}
|
|
178
|
-
/>
|
|
179
|
-
{isLastState && states.length <= 3 ? (
|
|
180
|
-
<CompleteButton
|
|
181
|
-
documentId={documentId}
|
|
182
|
-
disabled={!userRoleCanDrop}
|
|
183
|
-
/>
|
|
184
|
-
) : null}
|
|
185
|
-
</Flex>
|
|
186
|
-
{isLastState && states.length > 3 ? (
|
|
187
|
-
<Stack paddingTop={2}>
|
|
188
|
-
<CompleteButton
|
|
189
|
-
documentId={documentId}
|
|
190
|
-
disabled={!userRoleCanDrop}
|
|
191
|
-
/>
|
|
192
|
-
</Stack>
|
|
193
|
-
) : null}
|
|
194
|
-
</Card>
|
|
195
|
-
</Stack>
|
|
196
|
-
</Card>
|
|
197
|
-
</Box>
|
|
198
|
-
</>
|
|
199
|
-
)
|
|
200
|
-
}
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import {Draggable, DraggableStyle} from '@hello-pangea/dnd'
|
|
2
|
-
import {useVirtualizer, VirtualItem} from '@tanstack/react-virtual'
|
|
3
|
-
import {CSSProperties, useMemo, useRef} from 'react'
|
|
4
|
-
import {CurrentUser} from 'sanity'
|
|
5
|
-
import {UserExtended} from 'sanity-plugin-utils'
|
|
6
|
-
|
|
7
|
-
import {filterItemsAndSort} from '../helpers/filterItemsAndSort'
|
|
8
|
-
import {SanityDocumentWithMetadata, State} from '../types'
|
|
9
|
-
import {DocumentCard} from './DocumentCard'
|
|
10
|
-
|
|
11
|
-
type DocumentListProps = {
|
|
12
|
-
data: SanityDocumentWithMetadata[]
|
|
13
|
-
invalidDocumentIds: string[]
|
|
14
|
-
patchingIds: string[]
|
|
15
|
-
selectedSchemaTypes: string[]
|
|
16
|
-
selectedUserIds: string[]
|
|
17
|
-
state: State
|
|
18
|
-
states: State[]
|
|
19
|
-
toggleInvalidDocumentId: (
|
|
20
|
-
documentId: string,
|
|
21
|
-
action: 'ADD' | 'REMOVE'
|
|
22
|
-
) => void
|
|
23
|
-
user: CurrentUser | null
|
|
24
|
-
userList: UserExtended[]
|
|
25
|
-
userRoleCanDrop: boolean
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function getStyle(
|
|
29
|
-
draggableStyle: DraggableStyle | undefined,
|
|
30
|
-
virtualItem: VirtualItem
|
|
31
|
-
): CSSProperties {
|
|
32
|
-
// Default transform required by tanstack virtual for positioning
|
|
33
|
-
let transform = `translateY(${virtualItem.start}px)`
|
|
34
|
-
|
|
35
|
-
// If a card is being dragged over, this card needs to move up or down
|
|
36
|
-
if (draggableStyle && draggableStyle.transform) {
|
|
37
|
-
// So get the transform value from beautiful-dnd
|
|
38
|
-
const draggableTransformY = parseInt(
|
|
39
|
-
draggableStyle.transform.split(',')[1].split('px')[0],
|
|
40
|
-
10
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
// And apply it to the card
|
|
44
|
-
transform = `translateY(${virtualItem.start + draggableTransformY}px)`
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return {
|
|
48
|
-
position: 'absolute',
|
|
49
|
-
top: 0,
|
|
50
|
-
left: 0,
|
|
51
|
-
width: '100%',
|
|
52
|
-
height: `${virtualItem.size}px`,
|
|
53
|
-
transform,
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export default function DocumentList(props: DocumentListProps) {
|
|
58
|
-
const {
|
|
59
|
-
data = [],
|
|
60
|
-
invalidDocumentIds,
|
|
61
|
-
patchingIds,
|
|
62
|
-
selectedSchemaTypes,
|
|
63
|
-
selectedUserIds,
|
|
64
|
-
state,
|
|
65
|
-
states,
|
|
66
|
-
toggleInvalidDocumentId,
|
|
67
|
-
user,
|
|
68
|
-
userList,
|
|
69
|
-
userRoleCanDrop,
|
|
70
|
-
} = props
|
|
71
|
-
|
|
72
|
-
const dataFiltered = useMemo(() => {
|
|
73
|
-
return data.length
|
|
74
|
-
? filterItemsAndSort(data, state.id, selectedUserIds, selectedSchemaTypes)
|
|
75
|
-
: []
|
|
76
|
-
}, [data, selectedSchemaTypes, selectedUserIds, state.id])
|
|
77
|
-
|
|
78
|
-
const parentRef = useRef(null)
|
|
79
|
-
|
|
80
|
-
const virtualizer = useVirtualizer({
|
|
81
|
-
count: dataFiltered.length,
|
|
82
|
-
getScrollElement: () => parentRef.current,
|
|
83
|
-
getItemKey: (index) => dataFiltered[index]?._metadata?.documentId ?? index,
|
|
84
|
-
estimateSize: () => 115,
|
|
85
|
-
overscan: 7,
|
|
86
|
-
measureElement: (element) => {
|
|
87
|
-
return element.getBoundingClientRect().height || 115
|
|
88
|
-
},
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
if (!data.length || !dataFiltered.length) {
|
|
92
|
-
return null
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return (
|
|
96
|
-
<div
|
|
97
|
-
ref={parentRef}
|
|
98
|
-
style={{
|
|
99
|
-
height: `100%`,
|
|
100
|
-
overflow: 'auto',
|
|
101
|
-
// Smooths scrollbar behaviour
|
|
102
|
-
overflowAnchor: 'none',
|
|
103
|
-
scrollBehavior: 'auto',
|
|
104
|
-
paddingTop: 1,
|
|
105
|
-
}}
|
|
106
|
-
>
|
|
107
|
-
<div
|
|
108
|
-
style={{
|
|
109
|
-
height: `${virtualizer.getTotalSize()}px`,
|
|
110
|
-
width: '100%',
|
|
111
|
-
position: 'relative',
|
|
112
|
-
}}
|
|
113
|
-
>
|
|
114
|
-
{virtualizer.getVirtualItems().map((virtualItem) => {
|
|
115
|
-
const item = dataFiltered[virtualItem.index]
|
|
116
|
-
|
|
117
|
-
const {documentId, assignees} = item?._metadata ?? {}
|
|
118
|
-
|
|
119
|
-
const isInvalid = invalidDocumentIds.includes(documentId)
|
|
120
|
-
const meInAssignees = user?.id ? assignees?.includes(user.id) : false
|
|
121
|
-
const isDragDisabled =
|
|
122
|
-
patchingIds.includes(documentId) ||
|
|
123
|
-
!userRoleCanDrop ||
|
|
124
|
-
isInvalid ||
|
|
125
|
-
!(state.requireAssignment
|
|
126
|
-
? state.requireAssignment && meInAssignees
|
|
127
|
-
: true)
|
|
128
|
-
|
|
129
|
-
return (
|
|
130
|
-
<Draggable
|
|
131
|
-
key={virtualItem.key}
|
|
132
|
-
draggableId={documentId}
|
|
133
|
-
index={virtualItem.index}
|
|
134
|
-
isDragDisabled={isDragDisabled}
|
|
135
|
-
>
|
|
136
|
-
{(draggableProvided, draggableSnapshot) => (
|
|
137
|
-
<div
|
|
138
|
-
ref={draggableProvided.innerRef}
|
|
139
|
-
{...draggableProvided.draggableProps}
|
|
140
|
-
{...draggableProvided.dragHandleProps}
|
|
141
|
-
style={getStyle(
|
|
142
|
-
draggableProvided.draggableProps.style,
|
|
143
|
-
virtualItem
|
|
144
|
-
)}
|
|
145
|
-
>
|
|
146
|
-
<div
|
|
147
|
-
ref={virtualizer.measureElement}
|
|
148
|
-
data-index={virtualItem.index}
|
|
149
|
-
>
|
|
150
|
-
<DocumentCard
|
|
151
|
-
userRoleCanDrop={userRoleCanDrop}
|
|
152
|
-
isDragDisabled={isDragDisabled}
|
|
153
|
-
isPatching={patchingIds.includes(documentId)}
|
|
154
|
-
isDragging={draggableSnapshot.isDragging}
|
|
155
|
-
item={item}
|
|
156
|
-
toggleInvalidDocumentId={toggleInvalidDocumentId}
|
|
157
|
-
userList={userList}
|
|
158
|
-
states={states}
|
|
159
|
-
/>
|
|
160
|
-
</div>
|
|
161
|
-
</div>
|
|
162
|
-
)}
|
|
163
|
-
</Draggable>
|
|
164
|
-
)
|
|
165
|
-
})}
|
|
166
|
-
</div>
|
|
167
|
-
</div>
|
|
168
|
-
)
|
|
169
|
-
}
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import {ResetIcon, UserIcon} from '@sanity/icons'
|
|
2
|
-
import {Button, Card, Flex, Menu, MenuButton} from '@sanity/ui'
|
|
3
|
-
import {useCallback} from 'react'
|
|
4
|
-
import {useCurrentUser, UserAvatar, useSchema} from 'sanity'
|
|
5
|
-
import {UserExtended, UserSelectMenu} from 'sanity-plugin-utils'
|
|
6
|
-
|
|
7
|
-
type FiltersProps = {
|
|
8
|
-
uniqueAssignedUsers: UserExtended[]
|
|
9
|
-
selectedUserIds: string[]
|
|
10
|
-
schemaTypes: string[]
|
|
11
|
-
selectedSchemaTypes: string[]
|
|
12
|
-
toggleSelectedUser: (userId: string) => void
|
|
13
|
-
resetSelectedUsers: () => void
|
|
14
|
-
toggleSelectedSchemaType: (schemaType: string) => void
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export default function Filters(props: FiltersProps) {
|
|
18
|
-
const {
|
|
19
|
-
uniqueAssignedUsers = [],
|
|
20
|
-
selectedUserIds,
|
|
21
|
-
schemaTypes,
|
|
22
|
-
selectedSchemaTypes,
|
|
23
|
-
toggleSelectedUser,
|
|
24
|
-
resetSelectedUsers,
|
|
25
|
-
toggleSelectedSchemaType,
|
|
26
|
-
} = props
|
|
27
|
-
|
|
28
|
-
const currentUser = useCurrentUser()
|
|
29
|
-
const schema = useSchema()
|
|
30
|
-
|
|
31
|
-
const onAdd = useCallback(
|
|
32
|
-
(id: string) => {
|
|
33
|
-
if (!selectedUserIds.includes(id)) {
|
|
34
|
-
toggleSelectedUser(id)
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
[selectedUserIds, toggleSelectedUser]
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
const onRemove = useCallback(
|
|
41
|
-
(id: string) => {
|
|
42
|
-
if (selectedUserIds.includes(id)) {
|
|
43
|
-
toggleSelectedUser(id)
|
|
44
|
-
}
|
|
45
|
-
},
|
|
46
|
-
[selectedUserIds, toggleSelectedUser]
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
const onClear = useCallback(() => {
|
|
50
|
-
resetSelectedUsers()
|
|
51
|
-
}, [resetSelectedUsers])
|
|
52
|
-
|
|
53
|
-
if (uniqueAssignedUsers.length === 0 && schemaTypes.length < 2) {
|
|
54
|
-
return null
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const meInUniqueAssignees =
|
|
58
|
-
currentUser?.id && uniqueAssignedUsers.find((u) => u.id === currentUser.id)
|
|
59
|
-
const uniqueAssigneesNotMe = uniqueAssignedUsers.filter(
|
|
60
|
-
(u) => u.id !== currentUser?.id
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
return (
|
|
64
|
-
<Card tone="primary" padding={2} borderBottom style={{overflowX: 'hidden'}}>
|
|
65
|
-
<Flex align="center">
|
|
66
|
-
<Flex align="center" gap={1} flex={1}>
|
|
67
|
-
{uniqueAssignedUsers.length > 5 ? (
|
|
68
|
-
<Card tone="default">
|
|
69
|
-
<MenuButton
|
|
70
|
-
button={
|
|
71
|
-
<Button
|
|
72
|
-
padding={3}
|
|
73
|
-
fontSize={1}
|
|
74
|
-
text="Filter Assignees"
|
|
75
|
-
tone="primary"
|
|
76
|
-
icon={UserIcon}
|
|
77
|
-
/>
|
|
78
|
-
}
|
|
79
|
-
id="user-filters"
|
|
80
|
-
menu={
|
|
81
|
-
<Menu>
|
|
82
|
-
<UserSelectMenu
|
|
83
|
-
value={selectedUserIds}
|
|
84
|
-
userList={uniqueAssignedUsers}
|
|
85
|
-
onAdd={onAdd}
|
|
86
|
-
onRemove={onRemove}
|
|
87
|
-
onClear={onClear}
|
|
88
|
-
labels={{
|
|
89
|
-
addMe: 'Filter mine',
|
|
90
|
-
removeMe: 'Clear mine',
|
|
91
|
-
clear: 'Clear filters',
|
|
92
|
-
}}
|
|
93
|
-
/>
|
|
94
|
-
</Menu>
|
|
95
|
-
}
|
|
96
|
-
popover={{portal: true}}
|
|
97
|
-
/>
|
|
98
|
-
</Card>
|
|
99
|
-
) : (
|
|
100
|
-
<>
|
|
101
|
-
{meInUniqueAssignees ? (
|
|
102
|
-
<>
|
|
103
|
-
<Button
|
|
104
|
-
padding={0}
|
|
105
|
-
mode={
|
|
106
|
-
selectedUserIds.includes(currentUser.id)
|
|
107
|
-
? `default`
|
|
108
|
-
: `bleed`
|
|
109
|
-
}
|
|
110
|
-
onClick={() => toggleSelectedUser(currentUser.id)}
|
|
111
|
-
>
|
|
112
|
-
<Flex padding={1} align="center" justify="center">
|
|
113
|
-
<UserAvatar user={currentUser.id} size={1} withTooltip />
|
|
114
|
-
</Flex>
|
|
115
|
-
</Button>
|
|
116
|
-
<Card borderRight style={{height: 30}} tone="inherit" />
|
|
117
|
-
</>
|
|
118
|
-
) : null}
|
|
119
|
-
{uniqueAssigneesNotMe.map((user) => (
|
|
120
|
-
<Button
|
|
121
|
-
key={user.id}
|
|
122
|
-
padding={0}
|
|
123
|
-
mode={selectedUserIds.includes(user.id) ? `default` : `bleed`}
|
|
124
|
-
onClick={() => toggleSelectedUser(user.id)}
|
|
125
|
-
>
|
|
126
|
-
<Flex padding={1} align="center" justify="center">
|
|
127
|
-
<UserAvatar user={user} size={1} withTooltip />
|
|
128
|
-
</Flex>
|
|
129
|
-
</Button>
|
|
130
|
-
))}
|
|
131
|
-
|
|
132
|
-
{selectedUserIds.length > 0 ? (
|
|
133
|
-
<Button
|
|
134
|
-
padding={3}
|
|
135
|
-
fontSize={1}
|
|
136
|
-
text="Clear"
|
|
137
|
-
onClick={resetSelectedUsers}
|
|
138
|
-
mode="ghost"
|
|
139
|
-
icon={ResetIcon}
|
|
140
|
-
/>
|
|
141
|
-
) : null}
|
|
142
|
-
</>
|
|
143
|
-
)}
|
|
144
|
-
</Flex>
|
|
145
|
-
|
|
146
|
-
{schemaTypes.length > 1 ? (
|
|
147
|
-
<Flex align="center" gap={1}>
|
|
148
|
-
{schemaTypes.map((typeName) => {
|
|
149
|
-
const schemaType = schema.get(typeName)
|
|
150
|
-
|
|
151
|
-
if (!schemaType) {
|
|
152
|
-
return null
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return (
|
|
156
|
-
<Button
|
|
157
|
-
padding={3}
|
|
158
|
-
fontSize={1}
|
|
159
|
-
key={typeName}
|
|
160
|
-
text={schemaType?.title ?? typeName}
|
|
161
|
-
icon={schemaType?.icon ?? undefined}
|
|
162
|
-
mode={
|
|
163
|
-
selectedSchemaTypes.includes(typeName) ? `default` : `ghost`
|
|
164
|
-
}
|
|
165
|
-
onClick={() => toggleSelectedSchemaType(typeName)}
|
|
166
|
-
/>
|
|
167
|
-
)
|
|
168
|
-
})}
|
|
169
|
-
</Flex>
|
|
170
|
-
) : null}
|
|
171
|
-
</Flex>
|
|
172
|
-
</Card>
|
|
173
|
-
)
|
|
174
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import {Card, Grid} from '@sanity/ui'
|
|
2
|
-
import {AnimatePresence, motion} from 'framer-motion'
|
|
3
|
-
import {PropsWithChildren} from 'react'
|
|
4
|
-
import {css, styled} from 'styled-components'
|
|
5
|
-
|
|
6
|
-
const StyledFloatingCard = styled(Card)(
|
|
7
|
-
() => css`
|
|
8
|
-
position: fixed;
|
|
9
|
-
bottom: 0;
|
|
10
|
-
left: 0;
|
|
11
|
-
z-index: 1000;
|
|
12
|
-
`
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
export default function FloatingCard({children}: PropsWithChildren) {
|
|
16
|
-
const childrenHaveValues = Array.isArray(children)
|
|
17
|
-
? children.some(Boolean)
|
|
18
|
-
: Boolean(children)
|
|
19
|
-
|
|
20
|
-
return (
|
|
21
|
-
<AnimatePresence>
|
|
22
|
-
{childrenHaveValues ? (
|
|
23
|
-
<motion.div
|
|
24
|
-
key="floater"
|
|
25
|
-
initial={{opacity: 0}}
|
|
26
|
-
animate={{opacity: 1}}
|
|
27
|
-
exit={{opacity: 0}}
|
|
28
|
-
>
|
|
29
|
-
<StyledFloatingCard shadow={3} padding={3} margin={3} radius={3}>
|
|
30
|
-
<Grid gap={2}>{children}</Grid>
|
|
31
|
-
</StyledFloatingCard>
|
|
32
|
-
</motion.div>
|
|
33
|
-
) : null}
|
|
34
|
-
</AnimatePresence>
|
|
35
|
-
)
|
|
36
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import {Box, Text, Tooltip} from '@sanity/ui'
|
|
3
|
-
|
|
4
|
-
type StatusProps = {
|
|
5
|
-
text: string
|
|
6
|
-
icon: React.ComponentType
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function Status(props: StatusProps) {
|
|
10
|
-
const {text, icon} = props
|
|
11
|
-
const Icon = icon
|
|
12
|
-
|
|
13
|
-
return (
|
|
14
|
-
<Tooltip
|
|
15
|
-
portal
|
|
16
|
-
content={
|
|
17
|
-
<Box padding={2}>
|
|
18
|
-
<Text size={1}>{text}</Text>
|
|
19
|
-
</Box>
|
|
20
|
-
}
|
|
21
|
-
>
|
|
22
|
-
<Text size={1}>
|
|
23
|
-
<Icon />
|
|
24
|
-
</Text>
|
|
25
|
-
</Tooltip>
|
|
26
|
-
)
|
|
27
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import {InfoOutlineIcon, UserIcon} from '@sanity/icons'
|
|
2
|
-
import {Badge, BadgeTone, Box, Card, Flex, Text} from '@sanity/ui'
|
|
3
|
-
import {css, styled} from 'styled-components'
|
|
4
|
-
|
|
5
|
-
import {State} from '../../types'
|
|
6
|
-
import {Status} from './Status'
|
|
7
|
-
|
|
8
|
-
const StyledStickyCard = styled(Card)(
|
|
9
|
-
() => css`
|
|
10
|
-
position: sticky;
|
|
11
|
-
top: 0;
|
|
12
|
-
z-index: 1;
|
|
13
|
-
`
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
type StateTitleProps = {
|
|
17
|
-
state: State
|
|
18
|
-
requireAssignment: boolean
|
|
19
|
-
userRoleCanDrop: boolean
|
|
20
|
-
isDropDisabled: boolean
|
|
21
|
-
draggingFrom: string
|
|
22
|
-
documentCount: number
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export default function StateTitle(props: StateTitleProps) {
|
|
26
|
-
const {
|
|
27
|
-
state,
|
|
28
|
-
requireAssignment,
|
|
29
|
-
userRoleCanDrop,
|
|
30
|
-
isDropDisabled,
|
|
31
|
-
draggingFrom,
|
|
32
|
-
documentCount,
|
|
33
|
-
} = props
|
|
34
|
-
|
|
35
|
-
let tone: BadgeTone = 'default'
|
|
36
|
-
const isSource = draggingFrom === state.id
|
|
37
|
-
|
|
38
|
-
if (draggingFrom) {
|
|
39
|
-
tone = isDropDisabled || isSource ? 'default' : 'positive'
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return (
|
|
43
|
-
<StyledStickyCard paddingY={4} padding={3} tone="inherit">
|
|
44
|
-
<Flex gap={3} align="center">
|
|
45
|
-
<Badge
|
|
46
|
-
mode={
|
|
47
|
-
(draggingFrom && !isDropDisabled) || isSource
|
|
48
|
-
? 'default'
|
|
49
|
-
: 'outline'
|
|
50
|
-
}
|
|
51
|
-
tone={tone}
|
|
52
|
-
muted={!userRoleCanDrop || isDropDisabled}
|
|
53
|
-
>
|
|
54
|
-
{state.title}
|
|
55
|
-
</Badge>
|
|
56
|
-
{userRoleCanDrop ? null : (
|
|
57
|
-
<Status
|
|
58
|
-
text="You do not have permissions to move documents to this State"
|
|
59
|
-
icon={InfoOutlineIcon}
|
|
60
|
-
/>
|
|
61
|
-
)}
|
|
62
|
-
{requireAssignment ? (
|
|
63
|
-
<Status
|
|
64
|
-
text="You must be assigned to the document to move documents to this State"
|
|
65
|
-
icon={UserIcon}
|
|
66
|
-
/>
|
|
67
|
-
) : null}
|
|
68
|
-
<Box flex={1}>
|
|
69
|
-
{documentCount > 0 ? (
|
|
70
|
-
<Text weight="semibold" align="right" size={1}>
|
|
71
|
-
{documentCount}
|
|
72
|
-
</Text>
|
|
73
|
-
) : null}
|
|
74
|
-
</Box>
|
|
75
|
-
</Flex>
|
|
76
|
-
</StyledStickyCard>
|
|
77
|
-
)
|
|
78
|
-
}
|