webhooks #1
@@ -756,6 +756,8 @@ interface EditChannelSheetProps {
|
|||||||
logo?: string | null;
|
logo?: string | null;
|
||||||
logo_position?: LogoPosition;
|
logo_position?: LogoPosition;
|
||||||
logo_opacity?: number;
|
logo_opacity?: number;
|
||||||
|
webhook_url?: string | null;
|
||||||
|
webhook_poll_interval_secs?: number;
|
||||||
},
|
},
|
||||||
) => void;
|
) => void;
|
||||||
isPending: boolean;
|
isPending: boolean;
|
||||||
@@ -787,6 +789,8 @@ export function EditChannelSheet({
|
|||||||
const [logo, setLogo] = useState<string | null>(null);
|
const [logo, setLogo] = useState<string | null>(null);
|
||||||
const [logoPosition, setLogoPosition] = useState<LogoPosition>("top_right");
|
const [logoPosition, setLogoPosition] = useState<LogoPosition>("top_right");
|
||||||
const [logoOpacity, setLogoOpacity] = useState(100);
|
const [logoOpacity, setLogoOpacity] = useState(100);
|
||||||
|
const [webhookUrl, setWebhookUrl] = useState("");
|
||||||
|
const [webhookPollInterval, setWebhookPollInterval] = useState<number | "">(5);
|
||||||
const [selectedBlockId, setSelectedBlockId] = useState<string | null>(null);
|
const [selectedBlockId, setSelectedBlockId] = useState<string | null>(null);
|
||||||
const [fieldErrors, setFieldErrors] = useState<FieldErrors>({});
|
const [fieldErrors, setFieldErrors] = useState<FieldErrors>({});
|
||||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||||
@@ -804,6 +808,8 @@ export function EditChannelSheet({
|
|||||||
setLogo(channel.logo ?? null);
|
setLogo(channel.logo ?? null);
|
||||||
setLogoPosition(channel.logo_position ?? "top_right");
|
setLogoPosition(channel.logo_position ?? "top_right");
|
||||||
setLogoOpacity(Math.round((channel.logo_opacity ?? 1) * 100));
|
setLogoOpacity(Math.round((channel.logo_opacity ?? 1) * 100));
|
||||||
|
setWebhookUrl(channel.webhook_url ?? "");
|
||||||
|
setWebhookPollInterval(channel.webhook_poll_interval_secs ?? 5);
|
||||||
setSelectedBlockId(null);
|
setSelectedBlockId(null);
|
||||||
setFieldErrors({});
|
setFieldErrors({});
|
||||||
}
|
}
|
||||||
@@ -836,6 +842,10 @@ export function EditChannelSheet({
|
|||||||
logo: logo,
|
logo: logo,
|
||||||
logo_position: logoPosition,
|
logo_position: logoPosition,
|
||||||
logo_opacity: logoOpacity / 100,
|
logo_opacity: logoOpacity / 100,
|
||||||
|
webhook_url: webhookUrl || null,
|
||||||
|
...(webhookUrl
|
||||||
|
? { webhook_poll_interval_secs: webhookPollInterval === "" ? 5 : webhookPollInterval }
|
||||||
|
: {}),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1085,6 +1095,28 @@ export function EditChannelSheet({
|
|||||||
onChange={setRecyclePolicy}
|
onChange={setRecyclePolicy}
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
{/* Webhook */}
|
||||||
|
<section className="space-y-3">
|
||||||
|
<h3 className="text-xs font-semibold uppercase tracking-wider text-zinc-500">Webhook</h3>
|
||||||
|
<Field label="Webhook URL" hint="POST events to this URL on broadcast changes">
|
||||||
|
<TextInput
|
||||||
|
value={webhookUrl}
|
||||||
|
onChange={setWebhookUrl}
|
||||||
|
placeholder="https://example.com/webhook"
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
{webhookUrl && (
|
||||||
|
<Field label="Poll interval (seconds)" hint="How often to check for broadcast changes">
|
||||||
|
<NumberInput
|
||||||
|
value={webhookPollInterval}
|
||||||
|
onChange={setWebhookPollInterval}
|
||||||
|
min={1}
|
||||||
|
placeholder="5"
|
||||||
|
/>
|
||||||
|
</Field>
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Footer */}
|
{/* Footer */}
|
||||||
|
|||||||
@@ -147,6 +147,8 @@ export interface ChannelResponse {
|
|||||||
logo?: string | null;
|
logo?: string | null;
|
||||||
logo_position: LogoPosition;
|
logo_position: LogoPosition;
|
||||||
logo_opacity: number;
|
logo_opacity: number;
|
||||||
|
webhook_url?: string | null;
|
||||||
|
webhook_poll_interval_secs?: number;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
updated_at: string;
|
updated_at: string;
|
||||||
}
|
}
|
||||||
@@ -157,6 +159,8 @@ export interface CreateChannelRequest {
|
|||||||
description?: string;
|
description?: string;
|
||||||
access_mode?: AccessMode;
|
access_mode?: AccessMode;
|
||||||
access_password?: string;
|
access_password?: string;
|
||||||
|
webhook_url?: string;
|
||||||
|
webhook_poll_interval_secs?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateChannelRequest {
|
export interface UpdateChannelRequest {
|
||||||
@@ -173,6 +177,9 @@ export interface UpdateChannelRequest {
|
|||||||
logo?: string | null;
|
logo?: string | null;
|
||||||
logo_position?: LogoPosition;
|
logo_position?: LogoPosition;
|
||||||
logo_opacity?: number;
|
logo_opacity?: number;
|
||||||
|
/** null = clear webhook */
|
||||||
|
webhook_url?: string | null;
|
||||||
|
webhook_poll_interval_secs?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Media & Schedule
|
// Media & Schedule
|
||||||
|
|||||||
100
k-tv-frontend/package-lock.json
generated
100
k-tv-frontend/package-lock.json
generated
@@ -16,6 +16,7 @@
|
|||||||
"cmdk": "^1.1.1",
|
"cmdk": "^1.1.1",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"embla-carousel-react": "^8.6.0",
|
"embla-carousel-react": "^8.6.0",
|
||||||
|
"hls.js": "^1.6.15",
|
||||||
"input-otp": "^1.4.2",
|
"input-otp": "^1.4.2",
|
||||||
"lucide-react": "^0.577.0",
|
"lucide-react": "^0.577.0",
|
||||||
"next": "16.1.6",
|
"next": "16.1.6",
|
||||||
@@ -30,17 +31,20 @@
|
|||||||
"sonner": "^2.0.7",
|
"sonner": "^2.0.7",
|
||||||
"tailwind-merge": "^3.5.0",
|
"tailwind-merge": "^3.5.0",
|
||||||
"tw-animate-css": "^1.4.0",
|
"tw-animate-css": "^1.4.0",
|
||||||
"vaul": "^1.1.2"
|
"vaul": "^1.1.2",
|
||||||
|
"zod": "^4.3.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/postcss": "^4",
|
"@tailwindcss/postcss": "^4",
|
||||||
|
"@types/chromecast-caf-sender": "^1.0.11",
|
||||||
|
"@types/hls.js": "^1.0.0",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^19",
|
"@types/react": "^19",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
"eslint": "^9",
|
"eslint": "^9",
|
||||||
"eslint-config-next": "16.1.6",
|
"eslint-config-next": "16.1.6",
|
||||||
"tailwindcss": "^4",
|
"tailwindcss": "^4",
|
||||||
"typescript": "^5"
|
"typescript": "5.9.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@alloc/quick-lru": {
|
"node_modules/@alloc/quick-lru": {
|
||||||
@@ -1493,13 +1497,6 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@modelcontextprotocol/sdk/node_modules/zod": {
|
|
||||||
"version": "4.3.6",
|
|
||||||
"license": "MIT",
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/colinhacks"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@mswjs/interceptors": {
|
"node_modules/@mswjs/interceptors": {
|
||||||
"version": "0.41.3",
|
"version": "0.41.3",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -3551,6 +3548,27 @@
|
|||||||
"tslib": "^2.4.0"
|
"tslib": "^2.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/chrome": {
|
||||||
|
"version": "0.1.37",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.1.37.tgz",
|
||||||
|
"integrity": "sha512-IJE4ceuDO7lrEuua7Pow47zwNcI8E6qqkowRP7aFPaZ0lrjxh6y836OPqqkIZeTX64FTogbw+4RNH0+QrweCTQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/filesystem": "*",
|
||||||
|
"@types/har-format": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/chromecast-caf-sender": {
|
||||||
|
"version": "1.0.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/chromecast-caf-sender/-/chromecast-caf-sender-1.0.11.tgz",
|
||||||
|
"integrity": "sha512-Pv3xvNYtxD/cTM/tKfuZRlLasvpxAm+CFni0GJd6Cp8XgiZS9g9tMZkR1uymsi5fIFv057SZKKAWVFFgy7fJtw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/chrome": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/d3-array": {
|
"node_modules/@types/d3-array": {
|
||||||
"version": "3.2.2",
|
"version": "3.2.2",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
@@ -3601,6 +3619,41 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/filesystem": {
|
||||||
|
"version": "0.0.36",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.36.tgz",
|
||||||
|
"integrity": "sha512-vPDXOZuannb9FZdxgHnqSwAG/jvdGM8Wq+6N4D/d80z+D4HWH+bItqsZaVRQykAn6WEVeEkLm2oQigyHtgb0RA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/filewriter": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/filewriter": {
|
||||||
|
"version": "0.0.33",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.33.tgz",
|
||||||
|
"integrity": "sha512-xFU8ZXTw4gd358lb2jw25nxY9QAgqn2+bKKjKOYfNCzN4DKCFetK7sPtrlpg66Ywe3vWY9FNxprZawAh9wfJ3g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@types/har-format": {
|
||||||
|
"version": "1.2.16",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.16.tgz",
|
||||||
|
"integrity": "sha512-fluxdy7ryD3MV6h8pTfTYpy/xQzCFC7m89nOH9y94cNqJ1mDIDPut7MnRHI3F6qRmh/cT2fUjG1MLdCNb4hE9A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@types/hls.js": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/hls.js/-/hls.js-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-EGY2QJefX+Z9XH4PAxI7RFoNqBlQEk16UpYR3kbr82CIgMX5SlMe0PjFdFV0JytRhyVPQCiwSyONuI6S1KdSag==",
|
||||||
|
"deprecated": "This is a stub types definition. hls.js provides its own type definitions, so you do not need this installed.",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"hls.js": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/json-schema": {
|
"node_modules/@types/json-schema": {
|
||||||
"version": "7.0.15",
|
"version": "7.0.15",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
@@ -5862,14 +5915,6 @@
|
|||||||
"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
|
"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-plugin-react-hooks/node_modules/zod": {
|
|
||||||
"version": "4.3.6",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/colinhacks"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/eslint-plugin-react/node_modules/resolve": {
|
"node_modules/eslint-plugin-react/node_modules/resolve": {
|
||||||
"version": "2.0.0-next.6",
|
"version": "2.0.0-next.6",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
@@ -6654,6 +6699,12 @@
|
|||||||
"hermes-estree": "0.25.1"
|
"hermes-estree": "0.25.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hls.js": {
|
||||||
|
"version": "1.6.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.6.15.tgz",
|
||||||
|
"integrity": "sha512-E3a5VwgXimGHwpRGV+WxRTKeSp2DW5DI5MWv34ulL3t5UNmyJWCQ1KmLEHbYzcfThfXG8amBL+fCYPneGHC4VA==",
|
||||||
|
"license": "Apache-2.0"
|
||||||
|
},
|
||||||
"node_modules/hono": {
|
"node_modules/hono": {
|
||||||
"version": "4.12.7",
|
"version": "4.12.7",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -9321,6 +9372,15 @@
|
|||||||
"shadcn": "dist/index.js"
|
"shadcn": "dist/index.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/shadcn/node_modules/zod": {
|
||||||
|
"version": "3.25.76",
|
||||||
|
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
||||||
|
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/sharp": {
|
"node_modules/sharp": {
|
||||||
"version": "0.34.5",
|
"version": "0.34.5",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
@@ -10005,6 +10065,8 @@
|
|||||||
},
|
},
|
||||||
"node_modules/typescript": {
|
"node_modules/typescript": {
|
||||||
"version": "5.9.3",
|
"version": "5.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
||||||
|
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -10525,7 +10587,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/zod": {
|
"node_modules/zod": {
|
||||||
"version": "3.25.76",
|
"version": "4.3.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz",
|
||||||
|
"integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/colinhacks"
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
"eslint": "^9",
|
"eslint": "^9",
|
||||||
"eslint-config-next": "16.1.6",
|
"eslint-config-next": "16.1.6",
|
||||||
"tailwindcss": "^4",
|
"tailwindcss": "^4",
|
||||||
"typescript": "^5"
|
"typescript": "5.9.3"
|
||||||
},
|
},
|
||||||
"ignoreScripts": [
|
"ignoreScripts": [
|
||||||
"sharp",
|
"sharp",
|
||||||
|
|||||||
Reference in New Issue
Block a user