mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2025-12-20 20:29:06 +00:00
Zulip auto post
This commit is contained in:
@@ -68,6 +68,9 @@ class RoomController:
|
||||
self,
|
||||
name: str,
|
||||
user_id: str,
|
||||
zulip_auto_post: bool,
|
||||
zulip_stream: str,
|
||||
zulip_topic: str,
|
||||
):
|
||||
"""
|
||||
Add a new room
|
||||
@@ -75,11 +78,24 @@ class RoomController:
|
||||
room = Room(
|
||||
name=name,
|
||||
user_id=user_id,
|
||||
zulip_auto_post=zulip_auto_post,
|
||||
zulip_stream=zulip_stream,
|
||||
zulip_topic=zulip_topic,
|
||||
)
|
||||
query = rooms.insert().values(**room.model_dump())
|
||||
await database.execute(query)
|
||||
return room
|
||||
|
||||
async def update(self, room: Room, values: dict, mutate=True):
|
||||
"""
|
||||
Update a room fields with key/values in values
|
||||
"""
|
||||
query = rooms.update().where(rooms.c.id == room.id).values(**values)
|
||||
await database.execute(query)
|
||||
if mutate:
|
||||
for key, value in values.items():
|
||||
setattr(room, key, value)
|
||||
|
||||
async def get_by_id(self, room_id: str, **kwargs) -> Room | None:
|
||||
"""
|
||||
Get a room by id
|
||||
|
||||
@@ -21,6 +21,9 @@ class Room(BaseModel):
|
||||
name: str
|
||||
user_id: str
|
||||
created_at: datetime
|
||||
zulip_auto_post: bool
|
||||
zulip_stream: str
|
||||
zulip_topic: str
|
||||
|
||||
|
||||
class Meeting(BaseModel):
|
||||
@@ -35,6 +38,16 @@ class Meeting(BaseModel):
|
||||
|
||||
class CreateRoom(BaseModel):
|
||||
name: str
|
||||
zulip_auto_post: bool
|
||||
zulip_stream: str
|
||||
zulip_topic: str
|
||||
|
||||
|
||||
class UpdateRoom(BaseModel):
|
||||
name: str
|
||||
zulip_auto_post: bool
|
||||
zulip_stream: str
|
||||
zulip_topic: str
|
||||
|
||||
|
||||
class DeletionStatus(BaseModel):
|
||||
@@ -69,9 +82,27 @@ async def rooms_create(
|
||||
return await rooms_controller.add(
|
||||
name=room.name,
|
||||
user_id=user_id,
|
||||
zulip_auto_post=room.zulip_auto_post,
|
||||
zulip_stream=room.zulip_stream,
|
||||
zulip_topic=room.zulip_topic,
|
||||
)
|
||||
|
||||
|
||||
@router.patch("/rooms/{room_id}", response_model=Room)
|
||||
async def rooms_update(
|
||||
room_id: str,
|
||||
info: UpdateRoom,
|
||||
user: Annotated[Optional[auth.UserInfo], Depends(auth.current_user_optional)],
|
||||
):
|
||||
user_id = user["sub"] if user else None
|
||||
room = await rooms_controller.get_by_id_for_http(room_id, user_id=user_id)
|
||||
if not room:
|
||||
raise HTTPException(status_code=404, detail="Room not found")
|
||||
values = info.dict(exclude_unset=True)
|
||||
await rooms_controller.update(room, values)
|
||||
return room
|
||||
|
||||
|
||||
@router.delete("/rooms/{room_id}", response_model=DeletionStatus)
|
||||
async def rooms_delete(
|
||||
room_id: str,
|
||||
|
||||
3
www/.gitignore
vendored
3
www/.gitignore
vendored
@@ -41,3 +41,6 @@ next-env.d.ts
|
||||
.sentryclirc
|
||||
|
||||
config.ts
|
||||
|
||||
# openapi logs
|
||||
openapi-ts-error-*.log
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Card,
|
||||
CardBody,
|
||||
@@ -9,7 +8,6 @@ import {
|
||||
FormControl,
|
||||
FormHelperText,
|
||||
FormLabel,
|
||||
Grid,
|
||||
Heading,
|
||||
Input,
|
||||
Link,
|
||||
@@ -29,47 +27,145 @@ import {
|
||||
MenuButton,
|
||||
MenuList,
|
||||
MenuItem,
|
||||
AlertDialog,
|
||||
IconButton,
|
||||
Checkbox,
|
||||
} from "@chakra-ui/react";
|
||||
import NextLink from "next";
|
||||
import React, { ReactNode, useState } from "react";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { Container } from "@chakra-ui/react";
|
||||
import { PlusSquareIcon } from "@chakra-ui/icons";
|
||||
import { FaEllipsisVertical, FaTrash, FaPencil } from "react-icons/fa6";
|
||||
import useApi from "../../lib/useApi";
|
||||
import useRoomList from "./useRoomList";
|
||||
import { FaEllipsisVertical, FaTrash } from "react-icons/fa6";
|
||||
import next from "next";
|
||||
import { DomainContext } from "../domainContext";
|
||||
import { Select, Options, OptionBase } from "chakra-react-select";
|
||||
|
||||
interface Stream {
|
||||
id: number;
|
||||
name: string;
|
||||
topics: string[];
|
||||
}
|
||||
|
||||
interface SelectOption extends OptionBase {
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export default function RoomsList() {
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const [roomName, setRoomName] = useState("");
|
||||
const [room, setRoom] = useState({
|
||||
name: "",
|
||||
zulipAutoPost: false,
|
||||
zulipStream: "",
|
||||
zulipTopic: "",
|
||||
});
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const [editRoomId, setEditRoomId] = useState("");
|
||||
const api = useApi();
|
||||
const [page, setPage] = useState<number>(1);
|
||||
const { loading, response, refetch } = useRoomList(page);
|
||||
const [streams, setStreams] = useState<Stream[]>([]);
|
||||
|
||||
const handleAddRoom = async () => {
|
||||
const { zulip_streams } = useContext(DomainContext);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchZulipStreams = async () => {
|
||||
try {
|
||||
const response = await api?.v1RoomsCreate({
|
||||
requestBody: { name: roomName },
|
||||
const response = await fetch(zulip_streams + "/streams.json");
|
||||
if (!response.ok) {
|
||||
throw new Error("Network response was not ok");
|
||||
}
|
||||
let data = await response.json();
|
||||
data = data.sort((a: Stream, b: Stream) =>
|
||||
a.name.localeCompare(b.name),
|
||||
);
|
||||
setStreams(data);
|
||||
} catch (err) {
|
||||
console.error("Error fetching streams:", err);
|
||||
}
|
||||
};
|
||||
|
||||
if (room.zulipAutoPost) {
|
||||
fetchZulipStreams();
|
||||
}
|
||||
}, [room.zulipAutoPost]);
|
||||
|
||||
const streamOptions: Options<SelectOption> = streams.map((stream) => {
|
||||
return { label: stream.name, value: stream.name };
|
||||
});
|
||||
setRoomName("");
|
||||
|
||||
const topicOptions =
|
||||
streams
|
||||
.find((stream) => stream.name === room.zulipStream)
|
||||
?.topics.map((topic) => ({ label: topic, value: topic })) || [];
|
||||
|
||||
const handleSaveRoom = async () => {
|
||||
try {
|
||||
console.log(room);
|
||||
if (isEditing) {
|
||||
await api?.v1RoomsUpdate({
|
||||
roomId: editRoomId,
|
||||
requestBody: {
|
||||
name: room.name,
|
||||
zulip_auto_post: room.zulipAutoPost,
|
||||
zulip_stream: room.zulipStream,
|
||||
zulip_topic: room.zulipTopic,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
await api?.v1RoomsCreate({
|
||||
requestBody: {
|
||||
name: room.name,
|
||||
zulip_auto_post: room.zulipAutoPost,
|
||||
zulip_stream: room.zulipStream,
|
||||
zulip_topic: room.zulipTopic,
|
||||
},
|
||||
});
|
||||
}
|
||||
setRoom({
|
||||
name: "",
|
||||
zulipAutoPost: false,
|
||||
zulipStream: "",
|
||||
zulipTopic: "",
|
||||
});
|
||||
setIsEditing(false);
|
||||
setEditRoomId("");
|
||||
refetch();
|
||||
} catch (err) {}
|
||||
onClose();
|
||||
};
|
||||
|
||||
const handleEditRoom = (roomId, roomData) => {
|
||||
setRoom({
|
||||
name: roomData.name,
|
||||
zulipAutoPost: roomData.zulip_auto_post,
|
||||
zulipStream: roomData.zulip_stream,
|
||||
zulipTopic: roomData.zulip_topic,
|
||||
});
|
||||
setEditRoomId(roomId);
|
||||
setIsEditing(true);
|
||||
onOpen();
|
||||
};
|
||||
|
||||
const handleDeleteRoom = async (roomId: string) => {
|
||||
try {
|
||||
const response = await api?.v1RoomsDelete({
|
||||
await api?.v1RoomsDelete({
|
||||
roomId,
|
||||
});
|
||||
refetch();
|
||||
} catch (err) {}
|
||||
};
|
||||
|
||||
const handleRoomNameChange = (e) => {
|
||||
setRoomName(e.target.value);
|
||||
const handleRoomChange = (e) => {
|
||||
let { name, value, type, checked } = e.target;
|
||||
if (name === "name") {
|
||||
value = value
|
||||
.replace(/[^a-zA-Z0-9\s-]/g, "")
|
||||
.replace(/\s+/g, "-")
|
||||
.toLowerCase();
|
||||
}
|
||||
setRoom({
|
||||
...room,
|
||||
[name]: type === "checkbox" ? checked : value,
|
||||
});
|
||||
};
|
||||
|
||||
if (loading && !response)
|
||||
@@ -91,23 +187,81 @@ export default function RoomsList() {
|
||||
>
|
||||
<Heading>Rooms</Heading>
|
||||
<Spacer />
|
||||
<Button colorScheme="blue" onClick={onOpen}>
|
||||
<Button
|
||||
colorScheme="blue"
|
||||
onClick={() => {
|
||||
setIsEditing(false);
|
||||
setRoom({
|
||||
name: "",
|
||||
zulipAutoPost: false,
|
||||
zulipStream: "",
|
||||
zulipTopic: "",
|
||||
});
|
||||
onOpen();
|
||||
}}
|
||||
>
|
||||
Add Room
|
||||
</Button>
|
||||
<Modal isOpen={isOpen} onClose={onClose}>
|
||||
<ModalOverlay />
|
||||
<ModalContent>
|
||||
<ModalHeader>Add Room</ModalHeader>
|
||||
<ModalHeader>{isEditing ? "Edit Room" : "Add Room"}</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
<FormControl>
|
||||
<FormLabel>Room name</FormLabel>
|
||||
<Input
|
||||
name="name"
|
||||
placeholder="room-name"
|
||||
value={roomName}
|
||||
onChange={handleRoomNameChange}
|
||||
value={room.name}
|
||||
onChange={handleRoomChange}
|
||||
/>
|
||||
<FormHelperText>
|
||||
No spaces or special characters allowed
|
||||
</FormHelperText>
|
||||
</FormControl>
|
||||
|
||||
<FormControl mt={8}>
|
||||
<Checkbox
|
||||
name="zulipAutoPost"
|
||||
isChecked={room.zulipAutoPost}
|
||||
onChange={handleRoomChange}
|
||||
>
|
||||
Automatically post transcription to Zulip
|
||||
</Checkbox>
|
||||
</FormControl>
|
||||
<FormControl mt={4}>
|
||||
<FormLabel>Zulip stream</FormLabel>
|
||||
<Select
|
||||
name="zulipStream"
|
||||
options={streamOptions}
|
||||
placeholder="Select stream"
|
||||
value={{ label: room.zulipStream, value: room.zulipStream }}
|
||||
onChange={(newValue) =>
|
||||
setRoom({
|
||||
...room,
|
||||
zulipStream: newValue!.value,
|
||||
zulipTopic: "",
|
||||
})
|
||||
}
|
||||
isDisabled={!room.zulipAutoPost}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl mt={4}>
|
||||
<FormLabel>Zulip topic</FormLabel>
|
||||
<Select
|
||||
name="zulipTopic"
|
||||
options={topicOptions}
|
||||
placeholder="Select topic"
|
||||
value={{ label: room.zulipTopic, value: room.zulipTopic }}
|
||||
onChange={(newValue) =>
|
||||
setRoom({
|
||||
...room,
|
||||
zulipTopic: newValue!.value,
|
||||
})
|
||||
}
|
||||
isDisabled={!room.zulipAutoPost}
|
||||
/>
|
||||
<FormHelperText>Please enter room name</FormHelperText>
|
||||
</FormControl>
|
||||
</ModalBody>
|
||||
|
||||
@@ -116,8 +270,14 @@ export default function RoomsList() {
|
||||
Cancel
|
||||
</Button>
|
||||
|
||||
<Button colorScheme="blue" onClick={handleAddRoom}>
|
||||
Add
|
||||
<Button
|
||||
colorScheme="blue"
|
||||
onClick={handleSaveRoom}
|
||||
isDisabled={
|
||||
!room.name || (room.zulipAutoPost && !room.zulipTopic)
|
||||
}
|
||||
>
|
||||
{isEditing ? "Save" : "Add"}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
@@ -126,17 +286,13 @@ export default function RoomsList() {
|
||||
|
||||
<VStack>
|
||||
{response?.items && response.items.length > 0 ? (
|
||||
response.items.map((room) => (
|
||||
<Card w={"full"}>
|
||||
response.items.map((roomData) => (
|
||||
<Card w={"full"} key={roomData.id}>
|
||||
<CardBody>
|
||||
<Flex align={"center"}>
|
||||
<Heading size="md">
|
||||
<Link
|
||||
// as={NextLink}
|
||||
href={`/rooms/${room.name}`}
|
||||
noOfLines={2}
|
||||
>
|
||||
{room.name}
|
||||
<Link href={`/rooms/${roomData.name}`}>
|
||||
{roomData.name}
|
||||
</Link>
|
||||
</Heading>
|
||||
<Spacer />
|
||||
@@ -148,7 +304,13 @@ export default function RoomsList() {
|
||||
/>
|
||||
<MenuList>
|
||||
<MenuItem
|
||||
onClick={() => handleDeleteRoom(room.id)}
|
||||
onClick={() => handleEditRoom(roomData.id, roomData)}
|
||||
icon={<FaPencil />}
|
||||
>
|
||||
Edit
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={() => handleDeleteRoom(roomData.id)}
|
||||
icon={<FaTrash color={"red.500"} />}
|
||||
>
|
||||
Delete
|
||||
|
||||
@@ -59,9 +59,21 @@ export const $CreateRoom = {
|
||||
type: "string",
|
||||
title: "Name",
|
||||
},
|
||||
zulip_auto_post: {
|
||||
type: "boolean",
|
||||
title: "Zulip Auto Post",
|
||||
},
|
||||
zulip_stream: {
|
||||
type: "string",
|
||||
title: "Zulip Stream",
|
||||
},
|
||||
zulip_topic: {
|
||||
type: "string",
|
||||
title: "Zulip Topic",
|
||||
},
|
||||
},
|
||||
type: "object",
|
||||
required: ["name"],
|
||||
required: ["name", "zulip_auto_post", "zulip_stream", "zulip_topic"],
|
||||
title: "CreateRoom",
|
||||
} as const;
|
||||
|
||||
@@ -643,9 +655,29 @@ export const $Room = {
|
||||
format: "date-time",
|
||||
title: "Created At",
|
||||
},
|
||||
zulip_auto_post: {
|
||||
type: "boolean",
|
||||
title: "Zulip Auto Post",
|
||||
},
|
||||
zulip_stream: {
|
||||
type: "string",
|
||||
title: "Zulip Stream",
|
||||
},
|
||||
zulip_topic: {
|
||||
type: "string",
|
||||
title: "Zulip Topic",
|
||||
},
|
||||
},
|
||||
type: "object",
|
||||
required: ["id", "name", "user_id", "created_at"],
|
||||
required: [
|
||||
"id",
|
||||
"name",
|
||||
"user_id",
|
||||
"created_at",
|
||||
"zulip_auto_post",
|
||||
"zulip_stream",
|
||||
"zulip_topic",
|
||||
],
|
||||
title: "Room",
|
||||
} as const;
|
||||
|
||||
@@ -807,6 +839,30 @@ export const $UpdateParticipant = {
|
||||
title: "UpdateParticipant",
|
||||
} as const;
|
||||
|
||||
export const $UpdateRoom = {
|
||||
properties: {
|
||||
name: {
|
||||
type: "string",
|
||||
title: "Name",
|
||||
},
|
||||
zulip_auto_post: {
|
||||
type: "boolean",
|
||||
title: "Zulip Auto Post",
|
||||
},
|
||||
zulip_stream: {
|
||||
type: "string",
|
||||
title: "Zulip Stream",
|
||||
},
|
||||
zulip_topic: {
|
||||
type: "string",
|
||||
title: "Zulip Topic",
|
||||
},
|
||||
},
|
||||
type: "object",
|
||||
required: ["name", "zulip_auto_post", "zulip_stream", "zulip_topic"],
|
||||
title: "UpdateRoom",
|
||||
} as const;
|
||||
|
||||
export const $UpdateTranscript = {
|
||||
properties: {
|
||||
name: {
|
||||
|
||||
@@ -8,6 +8,8 @@ import type {
|
||||
V1RoomsListResponse,
|
||||
V1RoomsCreateData,
|
||||
V1RoomsCreateResponse,
|
||||
V1RoomsUpdateData,
|
||||
V1RoomsUpdateResponse,
|
||||
V1RoomsDeleteData,
|
||||
V1RoomsDeleteResponse,
|
||||
V1RoomsCreateMeetingData,
|
||||
@@ -120,6 +122,31 @@ export class DefaultService {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Rooms Update
|
||||
* @param data The data for the request.
|
||||
* @param data.roomId
|
||||
* @param data.requestBody
|
||||
* @returns Room Successful Response
|
||||
* @throws ApiError
|
||||
*/
|
||||
public v1RoomsUpdate(
|
||||
data: V1RoomsUpdateData,
|
||||
): CancelablePromise<V1RoomsUpdateResponse> {
|
||||
return this.httpRequest.request({
|
||||
method: "PATCH",
|
||||
url: "/v1/rooms/{room_id}",
|
||||
path: {
|
||||
room_id: data.roomId,
|
||||
},
|
||||
body: data.requestBody,
|
||||
mediaType: "application/json",
|
||||
errors: {
|
||||
422: "Validation Error",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Rooms Delete
|
||||
* @param data The data for the request.
|
||||
|
||||
@@ -16,6 +16,9 @@ export type CreateParticipant = {
|
||||
|
||||
export type CreateRoom = {
|
||||
name: string;
|
||||
zulip_auto_post: boolean;
|
||||
zulip_stream: string;
|
||||
zulip_topic: string;
|
||||
};
|
||||
|
||||
export type CreateTranscript = {
|
||||
@@ -126,6 +129,9 @@ export type Room = {
|
||||
name: string;
|
||||
user_id: string;
|
||||
created_at: string;
|
||||
zulip_auto_post: boolean;
|
||||
zulip_stream: string;
|
||||
zulip_topic: string;
|
||||
};
|
||||
|
||||
export type RtcOffer = {
|
||||
@@ -165,6 +171,13 @@ export type UpdateParticipant = {
|
||||
name?: string | null;
|
||||
};
|
||||
|
||||
export type UpdateRoom = {
|
||||
name: string;
|
||||
zulip_auto_post: boolean;
|
||||
zulip_stream: string;
|
||||
zulip_topic: string;
|
||||
};
|
||||
|
||||
export type UpdateTranscript = {
|
||||
name?: string | null;
|
||||
locked?: boolean | null;
|
||||
@@ -216,6 +229,13 @@ export type V1RoomsCreateData = {
|
||||
|
||||
export type V1RoomsCreateResponse = Room;
|
||||
|
||||
export type V1RoomsUpdateData = {
|
||||
requestBody: UpdateRoom;
|
||||
roomId: string;
|
||||
};
|
||||
|
||||
export type V1RoomsUpdateResponse = Room;
|
||||
|
||||
export type V1RoomsDeleteData = {
|
||||
roomId: string;
|
||||
};
|
||||
@@ -426,6 +446,19 @@ export type $OpenApiTs = {
|
||||
};
|
||||
};
|
||||
"/v1/rooms/{room_id}": {
|
||||
patch: {
|
||||
req: V1RoomsUpdateData;
|
||||
res: {
|
||||
/**
|
||||
* Successful Response
|
||||
*/
|
||||
200: Room;
|
||||
/**
|
||||
* Validation Error
|
||||
*/
|
||||
422: HTTPValidationError;
|
||||
};
|
||||
};
|
||||
delete: {
|
||||
req: V1RoomsDeleteData;
|
||||
res: {
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"@whereby.com/browser-sdk": "^3.3.4",
|
||||
"autoprefixer": "10.4.14",
|
||||
"axios": "^1.6.2",
|
||||
"chakra-react-select": "^4.7.6",
|
||||
"chakra-react-select": "^4.9.1",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-next": "^14.0.4",
|
||||
"fontawesome": "^5.6.3",
|
||||
|
||||
@@ -2347,12 +2347,12 @@ caniuse-lite@^1.0.30001406, caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.300015
|
||||
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001572.tgz"
|
||||
integrity sha512-1Pbh5FLmn5y4+QhNyJE9j3/7dK44dGB83/ZMjv/qJk86TvDbjk0LosiZo0i0WB0Vx607qMX9jYrn1VLHCkN4rw==
|
||||
|
||||
chakra-react-select@^4.7.6:
|
||||
version "4.7.6"
|
||||
resolved "https://registry.yarnpkg.com/chakra-react-select/-/chakra-react-select-4.7.6.tgz#3be8ffb314b8e75ef02663fd3e2fdf872b79683b"
|
||||
integrity sha512-ZL43hyXPnWf1g/HjsZDecbeJ4F2Q6tTPYJozlKWkrQ7lIX7ORP0aZYwmc5/Wly4UNzMimj2Vuosl6MmIXH+G2g==
|
||||
chakra-react-select@^4.9.1:
|
||||
version "4.9.1"
|
||||
resolved "https://registry.yarnpkg.com/chakra-react-select/-/chakra-react-select-4.9.1.tgz#38e421a0400c26e7f25d3dd28e6b93a021f08b77"
|
||||
integrity sha512-jmgfN+S/wnTaCp3pW30GYDIZ5J8jWcT1gIbhpw6RdKV+atm/U4/sT+gaHOHHhRL8xeaYip+iI/m8MPGREkve0w==
|
||||
dependencies:
|
||||
react-select "5.7.7"
|
||||
react-select "5.8.0"
|
||||
|
||||
chalk@3.0.0:
|
||||
version "3.0.0"
|
||||
@@ -5116,10 +5116,10 @@ react-select-search@^4.1.7:
|
||||
resolved "https://registry.yarnpkg.com/react-select-search/-/react-select-search-4.1.7.tgz#5662729b9052282bde52e1352006d495d9c5ed6e"
|
||||
integrity sha512-pU7ONAdK+bmz2tbhBWYQv9m5mnXOn8yImuiy+5UhimIG80d5iKv3nSYJIjJWjDbdrrdoXiCRwQm8xbA8llTjmQ==
|
||||
|
||||
react-select@5.7.7:
|
||||
version "5.7.7"
|
||||
resolved "https://registry.yarnpkg.com/react-select/-/react-select-5.7.7.tgz#dbade9dbf711ef2a181970c10f8ab319ac37fbd0"
|
||||
integrity sha512-HhashZZJDRlfF/AKj0a0Lnfs3sRdw/46VJIRd8IbB9/Ovr74+ZIwkAdSBjSPXsFMG+u72c5xShqwLSKIJllzqw==
|
||||
react-select@5.8.0:
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/react-select/-/react-select-5.8.0.tgz#bd5c467a4df223f079dd720be9498076a3f085b5"
|
||||
integrity sha512-TfjLDo58XrhP6VG5M/Mi56Us0Yt8X7xD6cDybC7yoRMUNm7BGO7qk8J0TLQOua/prb8vUOtsfnXZwfm30HGsAA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.0"
|
||||
"@emotion/cache" "^11.4.0"
|
||||
|
||||
Reference in New Issue
Block a user