@mirrormedia/lilith-draft-editor 1.0.0-beta → 1.0.0-beta2

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.
Files changed (191) hide show
  1. package/lib/draft-js/block-renderer/background-image-block.js +123 -0
  2. package/lib/draft-js/block-renderer/background-video-block.js +133 -0
  3. package/lib/draft-js/block-renderer/color-box-block.js +92 -0
  4. package/lib/draft-js/block-renderer/divider-block.js +24 -0
  5. package/lib/draft-js/block-renderer/embedded-code-block.js +63 -0
  6. package/lib/draft-js/block-renderer/image-block.js +47 -0
  7. package/lib/draft-js/block-renderer/info-box-block.js +89 -0
  8. package/lib/draft-js/block-renderer/media-block.js +65 -0
  9. package/lib/draft-js/block-renderer/related-post-block.js +51 -0
  10. package/lib/draft-js/block-renderer/side-index-block.js +103 -0
  11. package/lib/draft-js/block-renderer/slideshow-block.js +71 -0
  12. package/lib/draft-js/block-renderer/table-block.js +408 -0
  13. package/lib/draft-js/buttons/annotation.js +117 -0
  14. package/lib/draft-js/buttons/background-color.js +123 -0
  15. package/lib/draft-js/buttons/background-image.js +222 -0
  16. package/lib/draft-js/buttons/background-video.js +222 -0
  17. package/lib/draft-js/buttons/color-box.js +172 -0
  18. package/lib/draft-js/buttons/divider.js +63 -0
  19. package/lib/draft-js/buttons/embedded-code.js +134 -0
  20. package/lib/draft-js/buttons/enlarge.js +24 -0
  21. package/lib/draft-js/buttons/font-color.js +116 -0
  22. package/lib/draft-js/buttons/image.js +68 -0
  23. package/lib/draft-js/buttons/info-box.js +147 -0
  24. package/lib/draft-js/buttons/link.js +107 -0
  25. package/lib/draft-js/buttons/media.js +121 -0
  26. package/lib/draft-js/buttons/related-post.js +71 -0
  27. package/lib/draft-js/buttons/selector/align-selector.js +71 -0
  28. package/lib/draft-js/buttons/selector/image-selector.js +428 -0
  29. package/lib/draft-js/buttons/selector/pagination.js +82 -0
  30. package/lib/draft-js/buttons/selector/post-selector.js +317 -0
  31. package/lib/draft-js/buttons/selector/search-box.js +46 -0
  32. package/lib/draft-js/buttons/selector/video-selector.js +284 -0
  33. package/lib/draft-js/buttons/side-index.js +200 -0
  34. package/lib/draft-js/buttons/slideshow.js +71 -0
  35. package/lib/draft-js/buttons/table.js +67 -0
  36. package/lib/draft-js/buttons/text-align.js +88 -0
  37. package/lib/draft-js/editor/basic-editor.js +366 -0
  38. package/lib/draft-js/editor/block-renderer-fn.js +117 -0
  39. package/lib/draft-js/editor/entity-decorator.js +16 -0
  40. package/lib/draft-js/editor/modifier.js +68 -0
  41. package/lib/draft-js/entity-decorator/annotation-decorator.js +86 -0
  42. package/lib/draft-js/entity-decorator/link-decorator.js +39 -0
  43. package/lib/website/mirrormedia/custom/block-renderer/background-image-block.js +138 -0
  44. package/lib/website/mirrormedia/custom/block-renderer/background-video-block.js +148 -0
  45. package/lib/website/mirrormedia/custom/block-renderer/color-box-block.js +106 -0
  46. package/lib/website/mirrormedia/custom/block-renderer/divider-block.js +24 -0
  47. package/lib/website/mirrormedia/custom/block-renderer/embedded-code-block.js +63 -0
  48. package/lib/website/mirrormedia/custom/block-renderer/image-block.js +47 -0
  49. package/lib/website/mirrormedia/custom/block-renderer/info-box-block.js +103 -0
  50. package/lib/website/mirrormedia/custom/block-renderer/media-block.js +65 -0
  51. package/lib/website/mirrormedia/custom/block-renderer/related-post-block.js +51 -0
  52. package/lib/website/mirrormedia/custom/block-renderer/side-index-block.js +119 -0
  53. package/lib/website/mirrormedia/custom/block-renderer/slideshow-block.js +71 -0
  54. package/lib/website/mirrormedia/custom/block-renderer/table-block.js +455 -0
  55. package/lib/website/mirrormedia/custom/entity-decorator/annotation-decorator.js +86 -0
  56. package/lib/website/mirrormedia/custom/entity-decorator/link-decorator.js +39 -0
  57. package/lib/website/mirrormedia/custom/selector/align-selector.js +71 -0
  58. package/lib/website/mirrormedia/custom/selector/image-selector.js +427 -0
  59. package/lib/website/mirrormedia/custom/selector/pagination.js +82 -0
  60. package/lib/website/mirrormedia/custom/selector/post-selector.js +318 -0
  61. package/lib/website/mirrormedia/custom/selector/search-box.js +46 -0
  62. package/lib/website/mirrormedia/custom/selector/video-selector.js +282 -0
  63. package/lib/website/mirrormedia/draft-editor/block-renderer-fn.js +117 -0
  64. package/lib/website/mirrormedia/draft-editor/entity-decorator.js +16 -0
  65. package/lib/website/mirrormedia/draft-editor/index.js +799 -0
  66. package/lib/website/mirrormedia/draft-renderer/block-renderer-fn.js +117 -0
  67. package/lib/website/mirrormedia/draft-renderer/entity-decorator.js +16 -0
  68. package/lib/website/mirrormedia/draft-renderer/index.js +160 -0
  69. package/lib/website/readr/custom/block-renderer/background-image-block.js +138 -0
  70. package/lib/website/readr/custom/block-renderer/background-video-block.js +148 -0
  71. package/lib/website/readr/custom/block-renderer/color-box-block.js +106 -0
  72. package/lib/website/readr/custom/block-renderer/divider-block.js +24 -0
  73. package/lib/website/readr/custom/block-renderer/embedded-code-block.js +63 -0
  74. package/lib/website/readr/custom/block-renderer/image-block.js +47 -0
  75. package/lib/website/readr/custom/block-renderer/info-box-block.js +103 -0
  76. package/lib/website/readr/custom/block-renderer/media-block.js +65 -0
  77. package/lib/website/readr/custom/block-renderer/related-post-block.js +51 -0
  78. package/lib/website/readr/custom/block-renderer/side-index-block.js +119 -0
  79. package/lib/website/readr/custom/block-renderer/slideshow-block.js +71 -0
  80. package/lib/website/readr/custom/block-renderer/table-block.js +455 -0
  81. package/lib/website/readr/custom/entity-decorator/annotation-decorator.js +86 -0
  82. package/lib/website/readr/custom/entity-decorator/link-decorator.js +39 -0
  83. package/lib/website/readr/custom/selector/align-selector.js +71 -0
  84. package/lib/website/readr/custom/selector/image-selector.js +427 -0
  85. package/lib/website/readr/custom/selector/pagination.js +82 -0
  86. package/lib/website/readr/custom/selector/post-selector.js +318 -0
  87. package/lib/website/readr/custom/selector/search-box.js +46 -0
  88. package/lib/website/readr/custom/selector/video-selector.js +282 -0
  89. package/lib/website/readr/draft-editor/block-renderer-fn.js +117 -0
  90. package/lib/website/readr/draft-editor/entity-decorator.js +16 -0
  91. package/lib/website/readr/draft-editor/index.js +799 -0
  92. package/lib/website/readr/draft-renderer/block-renderer-fn.js +117 -0
  93. package/lib/website/readr/draft-renderer/entity-decorator.js +16 -0
  94. package/lib/website/readr/draft-renderer/index.js +160 -0
  95. package/package.json +1 -1
  96. package/lib/draft-js/block-renderer/background-image-block.tsx +0 -113
  97. package/lib/draft-js/block-renderer/background-video-block.tsx +0 -120
  98. package/lib/draft-js/block-renderer/color-box-block.tsx +0 -85
  99. package/lib/draft-js/block-renderer/divider-block.tsx +0 -12
  100. package/lib/draft-js/block-renderer/embedded-code-block.tsx +0 -65
  101. package/lib/draft-js/block-renderer/image-block.tsx +0 -41
  102. package/lib/draft-js/block-renderer/info-box-block.tsx +0 -85
  103. package/lib/draft-js/block-renderer/media-block.tsx +0 -36
  104. package/lib/draft-js/block-renderer/related-post-block.tsx +0 -47
  105. package/lib/draft-js/block-renderer/side-index-block.tsx +0 -113
  106. package/lib/draft-js/block-renderer/slideshow-block.tsx +0 -62
  107. package/lib/draft-js/block-renderer/table-block.tsx +0 -488
  108. package/lib/draft-js/buttons/annotation.tsx +0 -113
  109. package/lib/draft-js/buttons/background-color.tsx +0 -125
  110. package/lib/draft-js/buttons/background-image.tsx +0 -276
  111. package/lib/draft-js/buttons/background-video.tsx +0 -275
  112. package/lib/draft-js/buttons/color-box.tsx +0 -207
  113. package/lib/draft-js/buttons/divider.tsx +0 -56
  114. package/lib/draft-js/buttons/embedded-code.tsx +0 -126
  115. package/lib/draft-js/buttons/enlarge.tsx +0 -11
  116. package/lib/draft-js/buttons/font-color.tsx +0 -113
  117. package/lib/draft-js/buttons/image.tsx +0 -71
  118. package/lib/draft-js/buttons/info-box.tsx +0 -170
  119. package/lib/draft-js/buttons/link.tsx +0 -103
  120. package/lib/draft-js/buttons/media.tsx +0 -120
  121. package/lib/draft-js/buttons/related-post.tsx +0 -81
  122. package/lib/draft-js/buttons/selector/align-selector.tsx +0 -65
  123. package/lib/draft-js/buttons/selector/image-selector.tsx +0 -485
  124. package/lib/draft-js/buttons/selector/pagination.tsx +0 -83
  125. package/lib/draft-js/buttons/selector/post-selector.tsx +0 -367
  126. package/lib/draft-js/buttons/selector/search-box.tsx +0 -39
  127. package/lib/draft-js/buttons/selector/video-selector.tsx +0 -312
  128. package/lib/draft-js/buttons/side-index.tsx +0 -257
  129. package/lib/draft-js/buttons/slideshow.tsx +0 -81
  130. package/lib/draft-js/buttons/table.tsx +0 -63
  131. package/lib/draft-js/buttons/text-align.tsx +0 -88
  132. package/lib/draft-js/editor/basic-editor.tsx +0 -384
  133. package/lib/draft-js/editor/block-redender-fn.tsx +0 -77
  134. package/lib/draft-js/editor/entity-decorator.tsx +0 -7
  135. package/lib/draft-js/editor/modifier.tsx +0 -71
  136. package/lib/draft-js/entity-decorator/annotation-decorator.tsx +0 -81
  137. package/lib/draft-js/entity-decorator/link-decorator.tsx +0 -27
  138. package/lib/website/mirrormedia/custom/block-renderer/background-image-block.tsx +0 -128
  139. package/lib/website/mirrormedia/custom/block-renderer/background-video-block.tsx +0 -135
  140. package/lib/website/mirrormedia/custom/block-renderer/color-box-block.tsx +0 -98
  141. package/lib/website/mirrormedia/custom/block-renderer/divider-block.tsx +0 -12
  142. package/lib/website/mirrormedia/custom/block-renderer/embedded-code-block.tsx +0 -65
  143. package/lib/website/mirrormedia/custom/block-renderer/image-block.tsx +0 -41
  144. package/lib/website/mirrormedia/custom/block-renderer/info-box-block.tsx +0 -98
  145. package/lib/website/mirrormedia/custom/block-renderer/media-block.tsx +0 -36
  146. package/lib/website/mirrormedia/custom/block-renderer/related-post-block.tsx +0 -47
  147. package/lib/website/mirrormedia/custom/block-renderer/side-index-block.tsx +0 -125
  148. package/lib/website/mirrormedia/custom/block-renderer/slideshow-block.tsx +0 -62
  149. package/lib/website/mirrormedia/custom/block-renderer/table-block.tsx +0 -537
  150. package/lib/website/mirrormedia/custom/entity-decorator/annotation-decorator.tsx +0 -81
  151. package/lib/website/mirrormedia/custom/entity-decorator/link-decorator.tsx +0 -27
  152. package/lib/website/mirrormedia/custom/selector/align-selector.tsx +0 -65
  153. package/lib/website/mirrormedia/custom/selector/image-selector.tsx +0 -485
  154. package/lib/website/mirrormedia/custom/selector/pagination.tsx +0 -83
  155. package/lib/website/mirrormedia/custom/selector/post-selector.tsx +0 -367
  156. package/lib/website/mirrormedia/custom/selector/search-box.tsx +0 -39
  157. package/lib/website/mirrormedia/custom/selector/video-selector.tsx +0 -310
  158. package/lib/website/mirrormedia/draft-editor/block-redender-fn.tsx +0 -77
  159. package/lib/website/mirrormedia/draft-editor/entity-decorator.tsx +0 -7
  160. package/lib/website/mirrormedia/draft-editor/index.tsx +0 -909
  161. package/lib/website/mirrormedia/draft-renderer/block-redender-fn.tsx +0 -77
  162. package/lib/website/mirrormedia/draft-renderer/entity-decorator.tsx +0 -7
  163. package/lib/website/mirrormedia/draft-renderer/index-deprecated.tsx +0 -43
  164. package/lib/website/mirrormedia/draft-renderer/index.tsx +0 -150
  165. package/lib/website/readr/custom/block-renderer/background-image-block.tsx +0 -128
  166. package/lib/website/readr/custom/block-renderer/background-video-block.tsx +0 -135
  167. package/lib/website/readr/custom/block-renderer/color-box-block.tsx +0 -98
  168. package/lib/website/readr/custom/block-renderer/divider-block.tsx +0 -12
  169. package/lib/website/readr/custom/block-renderer/embedded-code-block.tsx +0 -65
  170. package/lib/website/readr/custom/block-renderer/image-block.tsx +0 -41
  171. package/lib/website/readr/custom/block-renderer/info-box-block.tsx +0 -98
  172. package/lib/website/readr/custom/block-renderer/media-block.tsx +0 -36
  173. package/lib/website/readr/custom/block-renderer/related-post-block.tsx +0 -47
  174. package/lib/website/readr/custom/block-renderer/side-index-block.tsx +0 -125
  175. package/lib/website/readr/custom/block-renderer/slideshow-block.tsx +0 -62
  176. package/lib/website/readr/custom/block-renderer/table-block.tsx +0 -537
  177. package/lib/website/readr/custom/entity-decorator/annotation-decorator.tsx +0 -81
  178. package/lib/website/readr/custom/entity-decorator/link-decorator.tsx +0 -27
  179. package/lib/website/readr/custom/selector/align-selector.tsx +0 -65
  180. package/lib/website/readr/custom/selector/image-selector.tsx +0 -485
  181. package/lib/website/readr/custom/selector/pagination.tsx +0 -83
  182. package/lib/website/readr/custom/selector/post-selector.tsx +0 -367
  183. package/lib/website/readr/custom/selector/search-box.tsx +0 -39
  184. package/lib/website/readr/custom/selector/video-selector.tsx +0 -310
  185. package/lib/website/readr/draft-editor/block-redender-fn.tsx +0 -77
  186. package/lib/website/readr/draft-editor/entity-decorator.tsx +0 -7
  187. package/lib/website/readr/draft-editor/index.tsx +0 -909
  188. package/lib/website/readr/draft-renderer/block-redender-fn.tsx +0 -77
  189. package/lib/website/readr/draft-renderer/entity-decorator.tsx +0 -7
  190. package/lib/website/readr/draft-renderer/index-deprecated.tsx +0 -43
  191. package/lib/website/readr/draft-renderer/index.tsx +0 -150
@@ -1,367 +0,0 @@
1
- import React, { useEffect, useState } from 'react'
2
- import styled from 'styled-components'
3
- import { Drawer, DrawerController } from '@keystone-ui/modals'
4
- import { gql, useLazyQuery } from '@keystone-6/core/admin-ui/apollo'
5
- import { ImageEntity } from './image-selector'
6
- import { SearchBox, SearchBoxOnChangeFn } from './search-box'
7
- import { Pagination } from './pagination'
8
-
9
- const postsQuery = gql`
10
- query Posts($searchText: String!, $take: Int, $skip: Int) {
11
- postsCount(where: { name: { contains: $searchText } })
12
- posts(
13
- where: { name: { contains: $searchText } }
14
- take: $take
15
- skip: $skip
16
- ) {
17
- id
18
- name
19
- type
20
- heroImage {
21
- id
22
- name
23
- imageFile {
24
- url
25
- }
26
- resized {
27
- original
28
- }
29
- }
30
- ogImage {
31
- id
32
- name
33
- imageFile {
34
- url
35
- }
36
- resized {
37
- original
38
- }
39
- }
40
- }
41
- }
42
- `
43
-
44
- const PostSearchBox = styled(SearchBox)`
45
- margin-top: 10px;
46
- `
47
-
48
- const PostSelectionWrapper = styled.div`
49
- overflow: auto;
50
- margin-top: 10px;
51
- `
52
-
53
- const PostGridsWrapper = styled.div`
54
- display: flex;
55
- flex-wrap: wrap;
56
- overflow: auto;
57
- `
58
-
59
- const PostGridWrapper = styled.div`
60
- flex: 0 0 33.3333%;
61
- cursor: pointer;
62
- padding: 0 10px 10px;
63
- `
64
-
65
- const PostMetaGridsWrapper = styled.div`
66
- display: flex;
67
- flex-wrap: wrap;
68
- overflow: auto;
69
- `
70
-
71
- const PostMetaGridWrapper = styled.div`
72
- flex: 0 0 33.3333%;
73
- cursor: pointer;
74
- padding: 0 10px 10px;
75
- `
76
-
77
- const Post = styled.div`
78
- width: 100%;
79
- `
80
-
81
- const SeparationLine = styled.div`
82
- border: #e1e5e9 1px solid;
83
- margin-top: 10px;
84
- margin-bottom: 10px;
85
- `
86
-
87
- const ErrorHint = styled.span`
88
- color: red;
89
- `
90
-
91
- const PostSelected = styled.div`
92
- height: 1.4rem;
93
- `
94
-
95
- const PostImage = styled.img`
96
- display: block;
97
- width: 100%;
98
- aspect-ratio: 2;
99
- object-fit: cover;
100
- `
101
-
102
- const PostTitle = styled.div`
103
- padding: 0 5px;
104
- `
105
-
106
- const ErrorWrapper = styled.div`
107
- & * {
108
- margin: 0;
109
- }
110
- `
111
-
112
- type ID = string
113
-
114
- export type PostEntity = {
115
- id: ID
116
- slug: string
117
- name: string
118
- type: string
119
- heroImage: ImageEntity
120
- ogImage: ImageEntity
121
- }
122
-
123
- export type PostEntityWithMeta = {
124
- post: PostEntity
125
- }
126
-
127
- type PostEntityOnSelectFn = (param: PostEntity) => void
128
-
129
- function PostGrids(props: {
130
- posts: PostEntity[]
131
- selected: PostEntity[]
132
- onSelect: PostEntityOnSelectFn
133
- }): React.ReactElement {
134
- const { posts, selected, onSelect } = props
135
-
136
- return (
137
- <PostGridsWrapper>
138
- {posts.map((post) => {
139
- return (
140
- <PostGrid
141
- key={post.id}
142
- isSelected={selected?.includes(post)}
143
- onSelect={() => onSelect(post)}
144
- post={post}
145
- />
146
- )
147
- })}
148
- </PostGridsWrapper>
149
- )
150
- }
151
-
152
- function PostGrid(props: {
153
- post: PostEntity
154
- isSelected: boolean
155
- onSelect: PostEntityOnSelectFn
156
- }) {
157
- const { post, onSelect, isSelected } = props
158
- return (
159
- <PostGridWrapper key={post?.id} onClick={() => onSelect(post)}>
160
- <PostSelected>
161
- {isSelected ? <i className="fas fa-check-circle"></i> : null}
162
- </PostSelected>
163
- <Post>
164
- <PostImage
165
- src={post.heroImage?.resized?.original}
166
- onError={(e) =>
167
- (e.currentTarget.src = post.heroImage?.imageFile?.url)
168
- }
169
- />
170
- <PostTitle>{post.name}</PostTitle>
171
- </Post>
172
- </PostGridWrapper>
173
- )
174
- }
175
-
176
- function PostMetaGrids(props: { postMetas: PostEntityWithMeta[] }) {
177
- const { postMetas } = props
178
- return (
179
- <PostMetaGridsWrapper>
180
- {postMetas.map((postMetas) => (
181
- <PostMetaGrid key={postMetas?.post?.id} postMeta={postMetas} />
182
- ))}
183
- </PostMetaGridsWrapper>
184
- )
185
- }
186
-
187
- function PostMetaGrid(props: {
188
- postMeta: PostEntityWithMeta
189
- }): React.ReactElement {
190
- const { postMeta } = props
191
- const { post } = postMeta
192
-
193
- return (
194
- <PostMetaGridWrapper>
195
- <Post>
196
- <PostImage
197
- src={post?.heroImage?.resized?.original}
198
- onError={(e) =>
199
- (e.currentTarget.src = post?.heroImage?.imageFile?.url)
200
- }
201
- />
202
- <PostTitle>{post?.name}</PostTitle>
203
- </Post>
204
- </PostMetaGridWrapper>
205
- )
206
- }
207
-
208
- type PostSelectorOnChangeFn = (params: PostEntityWithMeta[]) => void
209
-
210
- export function PostSelector(props: {
211
- onChange: PostSelectorOnChangeFn
212
- enableMultiSelect?: boolean
213
- minSelectCount?: number
214
- maxSelectCount?: number
215
- }) {
216
- const [
217
- queryPosts,
218
- { loading, error, data: { posts = [], postsCount = 0 } = {} },
219
- ] = useLazyQuery(postsQuery, { fetchPolicy: 'no-cache' })
220
- const [currentPage, setCurrentPage] = useState(0) // page starts with 1, 0 is used to detect initialization
221
- const [searchText, setSearchText] = useState('')
222
- const [selected, setSelected] = useState<PostEntityWithMeta[]>([])
223
- const [showErrorHint, setShowErrorHint] = useState(false)
224
-
225
- const pageSize = 6
226
-
227
- const {
228
- onChange,
229
- enableMultiSelect = false,
230
- minSelectCount = 1,
231
- maxSelectCount = 3,
232
- } = props
233
-
234
- const onSave = () => {
235
- if (
236
- enableMultiSelect &&
237
- minSelectCount &&
238
- selected.length < minSelectCount
239
- ) {
240
- setShowErrorHint(true)
241
- return
242
- }
243
-
244
- onChange(selected)
245
- }
246
-
247
- const onCancel = () => {
248
- onChange([])
249
- }
250
-
251
- const onSearchBoxChange: SearchBoxOnChangeFn = async (searchInput) => {
252
- setSearchText(searchInput)
253
- setCurrentPage(1)
254
- }
255
-
256
- const onPostsGridSelect: PostEntityOnSelectFn = (postEntity) => {
257
- setSelected((selected) => {
258
- const filterdSelected = selected.filter(
259
- (ele) => ele.post?.id !== postEntity.id
260
- )
261
-
262
- // deselect the post
263
- if (filterdSelected.length !== selected.length) {
264
- return filterdSelected
265
- }
266
-
267
- // add new selected one and check shrink the array if there is a limit
268
- if (enableMultiSelect) {
269
- let newSelected = selected.concat([{ post: postEntity }])
270
-
271
- if (maxSelectCount && newSelected.length >= maxSelectCount) {
272
- newSelected = newSelected.slice(-maxSelectCount)
273
- }
274
-
275
- return newSelected
276
- }
277
-
278
- // single select
279
- return [{ post: postEntity }]
280
- })
281
- }
282
-
283
- const selectedPosts = selected.map((ele: PostEntityWithMeta) => {
284
- return ele.post
285
- })
286
-
287
- useEffect(() => {
288
- if (currentPage !== 0) {
289
- queryPosts({
290
- variables: {
291
- searchText: searchText,
292
- skip: (currentPage - 1) * pageSize,
293
- take: pageSize,
294
- },
295
- })
296
- }
297
- }, [currentPage, searchText])
298
-
299
- let searchResult = (
300
- <React.Fragment>
301
- <PostGrids
302
- posts={posts}
303
- selected={selectedPosts}
304
- onSelect={onPostsGridSelect}
305
- />
306
- <Pagination
307
- currentPage={currentPage}
308
- total={postsCount}
309
- pageSize={pageSize}
310
- onChange={(pageIndex) => {
311
- setCurrentPage(pageIndex)
312
- }}
313
- />
314
- </React.Fragment>
315
- )
316
- if (loading) {
317
- searchResult = <p>searching...</p>
318
- }
319
- if (error) {
320
- searchResult = (
321
- <ErrorWrapper>
322
- <h3>Errors occurs in the `posts` query</h3>
323
- <div>
324
- <br />
325
- <b>Message:</b>
326
- <div>{error.message}</div>
327
- <br />
328
- <b>Stack:</b>
329
- <div>{error.stack}</div>
330
- <br />
331
- <b>Query:</b>
332
- <pre>{postsQuery.loc.source.body}</pre>
333
- </div>
334
- </ErrorWrapper>
335
- )
336
- }
337
-
338
- return (
339
- <DrawerController isOpen={true}>
340
- <Drawer
341
- title="Select post"
342
- actions={{
343
- cancel: {
344
- label: 'Cancel',
345
- action: onCancel,
346
- },
347
- confirm: {
348
- label: 'Confirm',
349
- action: onSave,
350
- },
351
- }}
352
- >
353
- <div>
354
- <PostSearchBox onChange={onSearchBoxChange} />
355
- <PostSelectionWrapper>
356
- <div>{searchResult} </div>
357
- {!!selected.length && <SeparationLine />}
358
- <PostMetaGrids postMetas={selected} />
359
- {showErrorHint && (
360
- <ErrorHint>請至少選擇{minSelectCount}則文章</ErrorHint>
361
- )}
362
- </PostSelectionWrapper>
363
- </div>
364
- </Drawer>
365
- </DrawerController>
366
- )
367
- }
@@ -1,39 +0,0 @@
1
- import React, { useState } from 'react'
2
- import styled from 'styled-components'
3
- import { Button } from '@keystone-ui/button'
4
- import { TextInput } from '@keystone-ui/fields'
5
-
6
- const SearchBoxWrapper = styled.div`
7
- display: flex;
8
- `
9
-
10
- export type SearchBoxOnChangeFn = (param: string) => void
11
-
12
- export function SearchBox(props: {
13
- onChange: SearchBoxOnChangeFn
14
- className: string
15
- }): React.ReactElement {
16
- const { onChange, className } = props
17
- const [searchInput, setSearchInput] = useState('')
18
-
19
- return (
20
- <SearchBoxWrapper className={className}>
21
- <TextInput
22
- type="text"
23
- placeholder="請輸入關鍵字搜尋"
24
- value={searchInput}
25
- onChange={(e) => {
26
- setSearchInput(e.target.value)
27
- }}
28
- ></TextInput>
29
-
30
- <Button
31
- onClick={() => {
32
- onChange(searchInput)
33
- }}
34
- >
35
- Search
36
- </Button>
37
- </SearchBoxWrapper>
38
- )
39
- }
@@ -1,312 +0,0 @@
1
- import React, { useEffect, useState } from 'react'
2
- import styled from 'styled-components'
3
- import { Drawer, DrawerController } from '@keystone-ui/modals'
4
- import { gql, useLazyQuery } from '@keystone-6/core/admin-ui/apollo'
5
- import { ImageEntity } from './image-selector'
6
- import { SearchBox, SearchBoxOnChangeFn } from './search-box'
7
- import { Pagination } from './pagination'
8
-
9
- const VideoSearchBox = styled(SearchBox)`
10
- margin-top: 10px;
11
- `
12
-
13
- const VideoSelectionWrapper = styled.div`
14
- overflow: auto;
15
- margin-top: 10px;
16
- `
17
-
18
- const VideoGridsWrapper = styled.div`
19
- display: flex;
20
- flex-wrap: wrap;
21
- overflow: auto;
22
- `
23
-
24
- const VideoGridWrapper = styled.div`
25
- flex: 0 0 33.3333%;
26
- cursor: pointer;
27
- padding: 0 10px 10px;
28
- `
29
-
30
- const VideoMetaGridsWrapper = styled.div`
31
- display: flex;
32
- flex-wrap: wrap;
33
- overflow: auto;
34
- `
35
-
36
- const VideoMetaGridWrapper = styled.div`
37
- flex: 0 0 33.3333%;
38
- cursor: pointer;
39
- padding: 0 10px 10px;
40
- `
41
-
42
- const Video = styled.video`
43
- display: block;
44
- width: 100%;
45
- aspect-ratio: 2;
46
- object-fit: cover;
47
- `
48
-
49
- const SeparationLine = styled.div`
50
- border: #e1e5e9 1px solid;
51
- margin-top: 10px;
52
- margin-bottom: 10px;
53
- `
54
-
55
- const VideoSelected = styled.div`
56
- height: 1.4rem;
57
- `
58
-
59
- const ErrorWrapper = styled.div`
60
- & * {
61
- margin: 0;
62
- }
63
- `
64
-
65
- type ID = string
66
-
67
- export type VideoEntity = {
68
- id: ID
69
- name?: string
70
- videoSrc: string
71
- youtubeUrl?: string
72
- description?: string
73
- videoFile: {
74
- filename?: string
75
- filesize: number
76
- url: string
77
- }
78
- coverPhoto: ImageEntity
79
- }
80
-
81
- export type VideoEntityWithMeta = {
82
- video: VideoEntity
83
- }
84
-
85
- type VideoEntityOnSelectFn = (param: VideoEntity) => void
86
-
87
- function VideosGrids(props: {
88
- videos: VideoEntity[]
89
- selected: VideoEntity[]
90
- onSelect: VideoEntityOnSelectFn
91
- }): React.ReactElement {
92
- const { videos, selected, onSelect } = props
93
-
94
- return (
95
- <VideoGridsWrapper>
96
- {videos.map((video) => {
97
- return (
98
- <VideoGrid
99
- key={video.id}
100
- isSelected={selected?.includes(video)}
101
- onSelect={() => onSelect(video)}
102
- video={video}
103
- />
104
- )
105
- })}
106
- </VideoGridsWrapper>
107
- )
108
- }
109
-
110
- function VideoGrid(props: {
111
- video: VideoEntity
112
- isSelected: boolean
113
- onSelect: VideoEntityOnSelectFn
114
- }) {
115
- const { video, onSelect, isSelected } = props
116
- return (
117
- <VideoGridWrapper key={video?.id} onClick={() => onSelect(video)}>
118
- <VideoSelected>
119
- {isSelected ? <i className="fas fa-check-circle"></i> : null}
120
- </VideoSelected>
121
- <Video muted loop>
122
- <source src={video?.videoSrc} />
123
- <source src={video?.videoFile?.url} />
124
- </Video>
125
- </VideoGridWrapper>
126
- )
127
- }
128
-
129
- function VideoMetaGrids(props: { videoMetas: VideoEntityWithMeta[] }) {
130
- const { videoMetas } = props
131
- return (
132
- <VideoMetaGridsWrapper>
133
- {videoMetas.map((videoMeta) => (
134
- <VideoMetaGrid key={videoMeta?.video?.id} videoMeta={videoMeta} />
135
- ))}
136
- </VideoMetaGridsWrapper>
137
- )
138
- }
139
-
140
- function VideoMetaGrid(props: {
141
- videoMeta: VideoEntityWithMeta
142
- }): React.ReactElement {
143
- const { videoMeta } = props
144
- const { video } = videoMeta
145
-
146
- return (
147
- <VideoMetaGridWrapper>
148
- <Video muted autoPlay loop>
149
- <source src={video?.videoSrc} />
150
- <source src={video?.videoFile?.url} />
151
- </Video>
152
- </VideoMetaGridWrapper>
153
- )
154
- }
155
-
156
- const videosQuery = gql`
157
- query Videos($searchText: String!, $take: Int, $skip: Int) {
158
- videosCount(where: { name: { contains: $searchText } })
159
- videos(
160
- where: { name: { contains: $searchText } }
161
- take: $take
162
- skip: $skip
163
- ) {
164
- id
165
- name
166
- videoSrc
167
- description
168
- videoFile {
169
- filename
170
- filesize
171
- url
172
- }
173
- coverPhoto {
174
- id
175
- name
176
- imageFile {
177
- url
178
- }
179
- resized {
180
- original
181
- }
182
- }
183
- }
184
- }
185
- `
186
-
187
- type VideoSelectorOnChangeFn = (params: VideoEntityWithMeta[]) => void
188
-
189
- export function VideoSelector(props: { onChange: VideoSelectorOnChangeFn }) {
190
- const [
191
- queryVideos,
192
- { loading, error, data: { videos = [], videosCount = 0 } = {} },
193
- ] = useLazyQuery(videosQuery, { fetchPolicy: 'no-cache' })
194
- const [currentPage, setCurrentPage] = useState(0) // page starts with 1, 0 is used to detect initialization
195
- const [searchText, setSearchText] = useState('')
196
- const [selected, setSelected] = useState<VideoEntityWithMeta[]>([])
197
-
198
- const pageSize = 6
199
-
200
- const { onChange } = props
201
-
202
- const onSave = () => {
203
- onChange(selected)
204
- }
205
-
206
- const onCancel = () => {
207
- onChange([])
208
- }
209
-
210
- const onSearchBoxChange: SearchBoxOnChangeFn = async (searchInput) => {
211
- setSearchText(searchInput)
212
- setCurrentPage(1)
213
- }
214
-
215
- const onVideosGridSelect: VideoEntityOnSelectFn = (videoEntity) => {
216
- setSelected((selected) => {
217
- const filterdSelected = selected.filter(
218
- (ele) => ele.video?.id !== videoEntity.id
219
- )
220
-
221
- // deselect the video
222
- if (filterdSelected.length !== selected.length) {
223
- return filterdSelected
224
- }
225
-
226
- // single select
227
- return [{ video: videoEntity }]
228
- })
229
- }
230
-
231
- const selectedVideos = selected.map((ele: VideoEntityWithMeta) => {
232
- return ele.video
233
- })
234
-
235
- useEffect(() => {
236
- if (currentPage !== 0) {
237
- queryVideos({
238
- variables: {
239
- searchText: searchText,
240
- skip: (currentPage - 1) * pageSize,
241
- take: pageSize,
242
- },
243
- })
244
- }
245
- }, [currentPage, searchText])
246
-
247
- let searchResult = (
248
- <React.Fragment>
249
- <VideosGrids
250
- videos={videos}
251
- selected={selectedVideos}
252
- onSelect={onVideosGridSelect}
253
- />
254
- <Pagination
255
- currentPage={currentPage}
256
- total={videosCount}
257
- pageSize={pageSize}
258
- onChange={(pageIndex) => {
259
- setCurrentPage(pageIndex)
260
- }}
261
- />
262
- </React.Fragment>
263
- )
264
- if (loading) {
265
- searchResult = <p>searching...</p>
266
- }
267
- if (error) {
268
- searchResult = (
269
- <ErrorWrapper>
270
- <h3>Errors occurs in the `videos` query</h3>
271
- <div>
272
- <br />
273
- <b>Message:</b>
274
- <div>{error.message}</div>
275
- <br />
276
- <b>Stack:</b>
277
- <div>{error.stack}</div>
278
- <br />
279
- <b>Query:</b>
280
- <pre>{videosQuery.loc.source.body}</pre>
281
- </div>
282
- </ErrorWrapper>
283
- )
284
- }
285
-
286
- return (
287
- <DrawerController isOpen={true}>
288
- <Drawer
289
- title="Select video"
290
- actions={{
291
- cancel: {
292
- label: 'Cancel',
293
- action: onCancel,
294
- },
295
- confirm: {
296
- label: 'Confirm',
297
- action: onSave,
298
- },
299
- }}
300
- >
301
- <div>
302
- <VideoSearchBox onChange={onSearchBoxChange} />
303
- <VideoSelectionWrapper>
304
- <div>{searchResult}</div>
305
- {!!selected.length && <SeparationLine />}
306
- <VideoMetaGrids videoMetas={selected} />
307
- </VideoSelectionWrapper>
308
- </div>
309
- </Drawer>
310
- </DrawerController>
311
- )
312
- }