PluginProbe ʕ •ᴥ•ʔ
Presto Player / trunk
Presto Player vtrunk
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 weeks ago ColorPopup.scss 2 weeks ago EntitySearchDropdown.js 2 weeks ago EntitySearchDropdown.scss 2 weeks ago LoadSelect.js 5 years ago ProBadge.js 5 years ago SelectMediaDropdown.js 2 weeks ago SelectMediaDropdown.scss 2 weeks ago Tag.js 2 weeks ago Tag.scss 2 weeks ago TranscriptionLanguageSelect.js 2 weeks ago UrlSelect.js 2 weeks ago UrlSelect.scss 2 weeks ago VideoIcon.js 2 weeks ago VideoIcon.scss 2 weeks ago
SelectMediaDropdown.js
146 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 "./SelectMediaDropdown.scss";
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 const [dropdownOpen, setDropdownOpen] = useState(false);
23
24 const handleSelection = (video) => {
25 if (!video) return;
26 onSelect(video);
27 };
28
29 // debounce the search.
30 const debounceSearch = debounce(
31 () => {
32 setPage(1); // reset the page.
33 setVideoList(null); // clear the videos.
34 doFetch() // fetch the videos.
35 },
36 500,
37 {
38 leading: true,
39 }
40 );
41
42 // when the search term changes, do a debounce search.
43 useEffect(() => {
44 if (!dropdownOpen) return;
45 debounceSearch(search);
46 }, [search, dropdownOpen]);
47
48 // when the page changes, fetch the videos.
49 useEffect(() => {
50 if (!dropdownOpen) return;
51 doFetch();
52 }, [page, dropdownOpen]);
53
54 // check if there are more pages.
55 const hasMore = page < totalPages;
56
57 // set the next page.
58 const nextPage = () => {
59 let newPage = page + 1;
60 newPage = newPage > totalPages ? totalPages : newPage;
61 setPage(newPage);
62 };
63
64 // Fetch videos from the server.
65 const doFetch = async () => {
66 try {
67 setIsLoading(true);
68
69 const baseURL = select(coreStore).getEntityConfig(
70 "postType",
71 "pp_video_block"
72 ).baseURL;
73
74 const res = await apiFetch({
75 path: addQueryArgs(baseURL, {
76 search,
77 page,
78 per_page: 5,
79 _embed: 1,
80 }),
81 parse: false,
82 });
83
84 const videos = await res.json();
85
86 setTotalPages(parseInt(res.headers.get("X-WP-TotalPages")));
87 receiveEntityRecords("postType", "pp_video_block", videos);
88
89 if (!search && page > 1) {
90 setVideoList([...videoList, ...videos]);
91 } else {
92 setVideoList(videos);
93 }
94 } catch (error) {
95 createErrorNotice(
96 error?.message || __("Something went wrong", "presto-player"),
97 { type: "snackbar" }
98 );
99 } finally {
100 setIsLoading(false);
101 }
102 };
103
104 // convert single value to array.
105 const disabledItems = !Array.isArray(value) ? [value] : value;
106 return (
107 <EntitySearchDropdown
108 isLoading={isLoading}
109 options={videoList || []}
110 search={search}
111 onSearch={setSearch}
112 onSelect={handleSelection}
113 hasMore={hasMore && !search}
114 onNextPage={nextPage}
115 onOpen={setDropdownOpen}
116 renderToggle={({ isOpen, onToggle }) => (
117 <Button variant="primary" onClick={onToggle} aria-expanded={isOpen}>
118 {__("Create or select media", "presto-player")}
119 </Button>
120 )}
121 renderItem={({ item, onSelect }) => {
122 const { id, title, details } = item;
123 const { type, name } = details || {};
124 const thumbnail =
125 item?._embedded?.["wp:featuredmedia"]?.[0]?.source_url || "";
126 return (
127 <MenuItem
128 icon={<VideoIcon thumbnail={thumbnail} type={type} />}
129 iconPosition="left"
130 suffix={type ? name : __("Choose media", "presto-player")}
131 onClick={() => onSelect(item)}
132 disabled={(disabledItems || []).includes(id)}
133 key={id}
134 className="presto-select-media-dropdown__item"
135 >
136 {title || __("Untitled", "presto-player")}
137 </MenuItem>
138 );
139 }}
140 {...props}
141 />
142 );
143 };
144
145 export default SelectMediaDropdown;
146