PluginProbe ʕ •ᴥ•ʔ
Presto Player / 3.0.0-beta1
Presto Player v3.0.0-beta1
4.5.0 4.4.1 4.4.0 4.3.3 4.3.2 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
154 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 { css, jsx } from "@emotion/core";
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 css={css`
135 .components-menu-item__item {
136 white-space: nowrap;
137 overflow: hidden;
138 text-overflow: ellipsis;
139 display: inline-block;
140 text-align: left;
141 }
142 `}
143 >
144 {title || __("Untitled", "presto-player")}
145 </MenuItem>
146 );
147 }}
148 {...props}
149 />
150 );
151 };
152
153 export default SelectMediaDropdown;
154