PluginProbe ʕ •ᴥ•ʔ
Presto Player / 2.3.0
Presto Player v2.3.0
4.3.1 4.3.0 4.2.4 4.2.3 4.2.2 4.2.0 4.2.1 trunk 1.10.0 1.10.1 1.10.2 1.11.0 1.12.0 1.13.0 1.14.0 1.14.1 1.5.10 1.5.11 1.5.12 1.5.13 1.5.14 1.5.15 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.10 1.6.11 1.6.12 1.6.13 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.13 2.0.14 2.0.15 2.0.16 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.2.0 2.2.1 2.2.2 2.2.3 2.2.3-beta1 2.3.0 2.3.1 2.3.2 2.3.3 3.0.0 3.0.0-beta1 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.1.0 3.1.1 3.1.2 3.1.3 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4
presto-player / src / admin / blocks / shared / components / SelectMediaDropdown.js
presto-player / src / admin / blocks / shared / components Last commit date
ColorPopup.js 2 years ago EntitySearchDropdown.js 2 years ago LoadSelect.js 5 years ago ProBadge.js 5 years ago SelectMediaDropdown.js 2 years ago UrlSelect.js 2 years ago VideoIcon.js 2 years ago
SelectMediaDropdown.js
151 lines
1 import { useState, useEffect } from "@wordpress/element";
2 import { __ } from "@wordpress/i18n";
3 import { addQueryArgs } from "@wordpress/url";
4 import { store as noticesStore } from "@wordpress/notices";
5 import { store as coreStore } from "@wordpress/core-data";
6 import apiFetch from "@wordpress/api-fetch";
7 import { select, useDispatch } from "@wordpress/data";
8 import debounce from "debounce-promise";
9 import EntitySearchDropdown from "./EntitySearchDropdown";
10 import VideoIcon from "./VideoIcon";
11 import { Button, MenuItem } from "@wordpress/components";
12 import { capitalize } from "../../util";
13
14 const SelectMediaDropdown = ({ onSelect, value, ...props }) => {
15 const [search, setSearch] = useState("");
16 const [page, setPage] = useState(1);
17 const [isLoading, setIsLoading] = useState(false);
18 const [videoList, setVideoList] = useState([]);
19 const [totalPages, setTotalPages] = useState(0);
20 const { createErrorNotice } = useDispatch(noticesStore);
21 const { receiveEntityRecords } = useDispatch(coreStore);
22
23 // handle the selection of a video.
24 const handleSelection = async (video) => {
25 if (!video?.id) return;
26 const item = await select(coreStore).getEntityRecord(
27 "postType",
28 "pp_video_block",
29 video?.id
30 );
31 onSelect(item);
32 };
33
34 // debounce the search.
35 const debounceSearch = debounce(
36 () => {
37 setPage(1); // reset the page.
38 setVideoList(null); // clear the videos.
39 doFetch(); // fetch the videos.
40 },
41 500,
42 {
43 leading: true,
44 }
45 );
46
47 // when the search term changes, do a debounce search.
48 useEffect(() => {
49 debounceSearch(search);
50 }, [search]);
51
52 // when the page changes, fetch the videos.
53 useEffect(() => {
54 doFetch();
55 }, [page]);
56
57 // check if there are more pages.
58 const hasMore = page < totalPages;
59
60 // set the next page.
61 const nextPage = () => {
62 let newPage = page + 1;
63 newPage = newPage > totalPages ? totalPages : newPage;
64 setPage(newPage);
65 };
66
67 // Fetch videos from the server.
68 const doFetch = async () => {
69 try {
70 setIsLoading(true);
71
72 const baseURL = select(coreStore).getEntityConfig(
73 "postType",
74 "pp_video_block"
75 ).baseURL;
76
77 const res = await apiFetch({
78 path: addQueryArgs(baseURL, {
79 search,
80 page,
81 per_page: 10,
82 _embed: 1,
83 }),
84 parse: false,
85 });
86
87 const videos = await res.json();
88
89 setTotalPages(parseInt(res.headers.get("X-WP-TotalPages")));
90 receiveEntityRecords("postType", "pp_video_block", videos);
91
92 if (!search && page > 1) {
93 setVideoList([...videoList, ...videos]);
94 } else {
95 setVideoList(videos);
96 }
97 } catch (error) {
98 createErrorNotice(
99 error?.message || __("Something went wrong", "presto-player"),
100 { type: "snackbar" }
101 );
102 } finally {
103 setIsLoading(false);
104 }
105 };
106
107 // convert single value to array.
108 const disabledItems = !Array.isArray(value) ? [value] : value;
109
110 return (
111 <EntitySearchDropdown
112 popoverProps={{ placement: "bottom-end" }}
113 isLoading={isLoading}
114 options={videoList || []}
115 search={search}
116 onSearch={setSearch}
117 onSelect={handleSelection}
118 hasMore={hasMore && !search}
119 onNextPage={nextPage}
120 renderToggle={({ isOpen, onToggle }) => (
121 <Button variant="primary" onClick={onToggle} aria-expanded={isOpen}>
122 {__("Create or select media", "presto-player")}
123 </Button>
124 )}
125 renderItem={({ item, onSelect }) => {
126 const { id, title, details } = item;
127 const { type } = details || {};
128 const thumbnail =
129 item?._embedded?.["wp:featuredmedia"]?.[0]?.source_url || "";
130 return (
131 <MenuItem
132 icon={<VideoIcon thumbnail={thumbnail} type={type} />}
133 iconPosition="left"
134 suffix={
135 type ? capitalize(type) : __("Choose media", "presto-player")
136 }
137 onClick={() => onSelect(item)}
138 disabled={(disabledItems || []).includes(id)}
139 key={id}
140 >
141 {title?.raw || __("Untitled", "presto-player")}
142 </MenuItem>
143 );
144 }}
145 {...props}
146 />
147 );
148 };
149
150 export default SelectMediaDropdown;
151