diff --git a/app/controllers/api/control/track_cards_controller.rb b/app/controllers/api/control/track_cards_controller.rb index fc45bc8..193bf3d 100644 --- a/app/controllers/api/control/track_cards_controller.rb +++ b/app/controllers/api/control/track_cards_controller.rb @@ -13,20 +13,24 @@ def index .where('activation_at <= ?', ts) .limit(10) .order(activation_at: :desc) - .map(&:as_json) else cards = [ - TrackCard.current_for(params[:track_slug])&.as_json, - *TrackCard.where(track: params[:track_slug]).candidate.map(&:as_json), + TrackCard.current_for(params[:track_slug]), + *TrackCard.where(track: params[:track_slug]).candidate.to_a, ] end render(json: { - track_cards: cards.compact, + track_cards: cards.compact.map { |_| _.as_json(control: true) }, }) end def create - TrackCard.create!(track_card_params) + track_card = TrackCard.new(track_card_params) + + now = Time.now + track_card.activation_at = now if track_card.activation_at < now + + track_card.save! EmitIvsMetadataJob.perform_now render(json: {ok: true}.to_json) end diff --git a/app/javascript/Api.ts b/app/javascript/Api.ts index 4bf51fd..40f3601 100644 --- a/app/javascript/Api.ts +++ b/app/javascript/Api.ts @@ -316,7 +316,7 @@ export type Attendee = { export type Conference = { default_track: string; track_order: TrackSlug[]; - tracks: { [key: string]: Track }; + tracks: { [key: TrackSlug]: Track }; }; export type TrackSlug = string; @@ -329,11 +329,11 @@ export type Track = { card: TrackCard | null; card_candidate: TrackCard | null; spotlights: ChatSpotlight[]; - presences: { [key: string]: StreamPresence }; // key:kind + presences: { [key in TrackStreamKind]: StreamPresence }; // key:kind viewerCount?: ViewerCount; }; -export interface TrackCard extends TrackCardHeader, TrackCardContent {} +export type TrackCard = TrackCardHeader & TrackCardContent; export type TrackCardHeader = { track: TrackSlug; @@ -430,7 +430,7 @@ export type GetAppVersionResponse = { release: string; }; -export type ChatSessionTracksBag = { [key: string]: TrackChatInfo | null }; +export type ChatSessionTracksBag = { [key: TrackSlug]: TrackChatInfo | null }; export type GetChatSessionResponse = { expiry: number; diff --git a/app/javascript/ContentCopyIcon.tsx b/app/javascript/ContentCopyIcon.tsx new file mode 100644 index 0000000..84be91f --- /dev/null +++ b/app/javascript/ContentCopyIcon.tsx @@ -0,0 +1,13 @@ +// Material Icon: content-copy +import { createIcon } from "@chakra-ui/icons"; + +export const ContentCopyIcon = createIcon({ + displayName: "ContentCopy", + viewBox: "0 0 24 24", + path: ( + <> + + + + ), +}); diff --git a/app/javascript/ControlApi.tsx b/app/javascript/ControlApi.tsx index b461fb1..9636c4d 100644 --- a/app/javascript/ControlApi.tsx +++ b/app/javascript/ControlApi.tsx @@ -45,8 +45,10 @@ export type ControlGetConferenceResponse = { speakers: { [key: string]: ConferenceSpeaker }; }; +export type ControlTrackCard = TrackCard & { id: number }; + export type ControlGetTrackCardsResponse = { - track_cards: TrackCard[]; + track_cards: ControlTrackCard[]; }; export type ControlListAttendeesResponse = { @@ -121,6 +123,13 @@ export const ControlApi = { return resp.json(); }, + async deleteTrackCard(card: ControlTrackCard) { + const url = `/api/control/tracks/${encodeURIComponent(card.track)}/cards/${encodeURIComponent(card.id)}`; + const resp = await request(url, "DELETE", null, {}); + mutate(`/api/control/tracks/${encodeURIComponent(card.track)}/cards`); + return resp.json(); + }, + useAttendeeList(query: string | null) { return useSWR( query !== null ? `/api/control/attendees?query=${encodeURIComponent(query)}` : null, diff --git a/app/javascript/ControlStreamPresence.tsx b/app/javascript/ControlStreamPresence.tsx index cc9b86c..81054f2 100644 --- a/app/javascript/ControlStreamPresence.tsx +++ b/app/javascript/ControlStreamPresence.tsx @@ -23,7 +23,7 @@ const ControlTrackCardForm = loadable(() => import("./ControlTrackCardForm")); export type Props = { track: Track; -} +}; export const ControlStreamPresence: React.FC = ({ track }) => { // const { data: controlConferenceData } = ControlApi.useConference(); @@ -114,7 +114,8 @@ export const StreamPresenceBox: React.FC<{ } - if (!controlConferenceData) { - return

Loading

; - } + + + + Compose TrackCard + + + + + + + +