feat: youtube changes

This commit is contained in:
Nevo David 2024-06-12 15:29:42 +07:00
parent 97bd36bacc
commit 004ffcabb0
7 changed files with 151 additions and 97 deletions

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 234.67 165.33" height="32" width="45"><path d="M229.763 25.817c-2.699-10.162-10.65-18.165-20.748-20.881C190.716 0 117.333 0 117.333 0S43.951 0 25.651 4.936C15.553 7.652 7.6 15.655 4.903 25.817 0 44.236 0 82.667 0 82.667s0 38.429 4.903 56.85C7.6 149.68 15.553 157.681 25.65 160.4c18.3 4.934 91.682 4.934 91.682 4.934s73.383 0 91.682-4.934c10.098-2.718 18.049-10.72 20.748-20.882 4.904-18.421 4.904-56.85 4.904-56.85s0-38.431-4.904-56.85" fill="red" /><path d="M93.333 117.559l61.333-34.89-61.333-34.894z" fill="#fff" /></svg>

After

Width:  |  Height:  |  Size: 577 B

View File

@ -195,13 +195,21 @@ export const AddProviderComponent: FC<{
<div
key={item.identifier}
onClick={getSocialLink(item.identifier)}
className="w-[120px] h-[100px] bg-input text-white justify-center items-center flex flex-col gap-[10px] cursor-pointer"
className={
'w-[120px] h-[100px] bg-input text-white justify-center items-center flex flex-col gap-[10px] cursor-pointer'
}
>
<div>
<img
className="w-[32px] h-[32px] rounded-full"
src={`/icons/platforms/${item.identifier}.png`}
/>
{item.identifier === 'youtube' ? (
<img
src={`/icons/platforms/youtube.svg`}
/>
) : (
<img
className="w-[32px] h-[32px] rounded-full"
src={`/icons/platforms/${item.identifier}.png`}
/>
)}
</div>
<div>{item.name}</div>
</div>

View File

@ -56,15 +56,17 @@ export const PickPlatforms: FC<{
checkLeftRight();
}, [selectedIntegrations, integrations]);
useMoveToIntegrationListener([integrations], props.singleSelect, (identifier) => {
const findIntegration = integrations.find(
(p) => p.id === identifier
);
useMoveToIntegrationListener(
[integrations],
props.singleSelect,
(identifier) => {
const findIntegration = integrations.find((p) => p.id === identifier);
if (findIntegration) {
addPlatform(findIntegration)();
if (findIntegration) {
addPlatform(findIntegration)();
}
}
});
);
const addPlatform = useCallback(
(integration: Integrations) => async () => {
@ -102,7 +104,9 @@ export const PickPlatforms: FC<{
}
return (
<div className={clsx('flex select-none', props.singleSelect && 'gap-[10px]')}>
<div
className={clsx('flex select-none', props.singleSelect && 'gap-[10px]')}
>
{props.singleSelect && (
<div className="flex items-center">
{isLeft && (
@ -138,75 +142,81 @@ export const PickPlatforms: FC<{
>
<div className="innerComponent">
<div className="flex">
{integrations.filter(f => !f.inBetweenSteps).map((integration) =>
!props.singleSelect ? (
<div
key={integration.id}
className="flex gap-[8px] items-center mr-[10px]"
>
{integrations
.filter((f) => !f.inBetweenSteps)
.map((integration) =>
!props.singleSelect ? (
<div
onClick={addPlatform(integration)}
className={clsx(
'cursor-pointer relative w-[34px] h-[34px] rounded-full flex justify-center items-center bg-fifth filter transition-all duration-500',
selectedAccounts.findIndex(
(p) => p.id === integration.id
) === -1
? 'opacity-40'
: ''
)}
key={integration.id}
className="flex gap-[8px] items-center mr-[10px]"
>
<img
src={integration.picture}
className="rounded-full"
alt={integration.identifier}
width={32}
height={32}
/>
<Image
src={`/icons/platforms/${integration.identifier}.png`}
className="rounded-full absolute z-10 -bottom-[5px] -right-[5px] border border-fifth"
alt={integration.identifier}
width={20}
height={20}
/>
</div>
</div>
) : (
<div key={integration.id} className="">
<div
onClick={addPlatform(integration)}
className={clsx(
'cursor-pointer rounded-[50px] w-[200px] relative h-[40px] flex justify-center items-center bg-fifth filter transition-all duration-500',
selectedAccounts.findIndex(
(p) => p.id === integration.id
) === -1
? 'bg-third border border-third'
: 'bg-[#291259] border border-[#5826C2]'
)}
>
<div className="flex items-center justify-center gap-[10px]">
<div className="relative">
<img
src={integration.picture}
className="rounded-full"
alt={integration.identifier}
width={24}
height={24}
/>
<div
onClick={addPlatform(integration)}
className={clsx(
'cursor-pointer relative w-[34px] h-[34px] rounded-full flex justify-center items-center bg-fifth filter transition-all duration-500',
selectedAccounts.findIndex(
(p) => p.id === integration.id
) === -1
? 'opacity-40'
: ''
)}
>
<Image
src={integration.picture}
className="rounded-full"
alt={integration.identifier}
width={32}
height={32}
/>
{integration.identifier === 'youtube' ? (
<img src="/icons/platforms/youtube.svg" className="absolute z-10 -bottom-[5px] -right-[5px]" width={20} />
) : (
<Image
src={`/icons/platforms/${integration.identifier}.png`}
className="rounded-full absolute z-10 -bottom-[5px] -right-[5px] border border-fifth"
alt={integration.identifier}
width={15}
height={15}
width={20}
height={20}
/>
</div>
<div>{integration.name}</div>
)}
</div>
</div>
</div>
)
)}
) : (
<div key={integration.id} className="">
<div
onClick={addPlatform(integration)}
className={clsx(
'cursor-pointer rounded-[50px] w-[200px] relative h-[40px] flex justify-center items-center bg-fifth filter transition-all duration-500',
selectedAccounts.findIndex(
(p) => p.id === integration.id
) === -1
? 'bg-third border border-third'
: 'bg-[#291259] border border-[#5826C2]'
)}
>
<div className="flex items-center justify-center gap-[10px]">
<div className="relative">
<img
src={integration.picture}
className="rounded-full"
alt={integration.identifier}
width={24}
height={24}
/>
<Image
src={`/icons/platforms/${integration.identifier}.png`}
className="rounded-full absolute z-10 -bottom-[5px] -right-[5px] border border-fifth"
alt={integration.identifier}
width={15}
height={15}
/>
</div>
<div>{integration.name}</div>
</div>
</div>
</div>
)
)}
</div>
</div>
</div>

View File

@ -148,13 +148,21 @@ export const LaunchesComponent = () => {
width={32}
height={32}
/>
<Image
src={`/icons/platforms/${integration.identifier}.png`}
className="rounded-full absolute z-10 -bottom-[5px] -right-[5px] border border-fifth"
alt={integration.identifier}
width={20}
height={20}
/>
{integration.identifier === 'youtube' ? (
<img
src="/icons/platforms/youtube.svg"
className="absolute z-10 -bottom-[5px] -right-[5px]"
width={20}
/>
) : (
<Image
src={`/icons/platforms/${integration.identifier}.png`}
className="rounded-full absolute z-10 -bottom-[5px] -right-[5px] border border-fifth"
alt={integration.identifier}
width={20}
height={20}
/>
)}
</div>
<div
{...(integration.disabled &&

View File

@ -13,12 +13,26 @@ import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.v
import { Input } from '@gitroom/react/form/input';
import { MediumTags } from '@gitroom/frontend/components/launches/providers/medium/medium.tags';
import { MediaComponent } from '@gitroom/frontend/components/media/media.component';
import { Select } from '@gitroom/react/form/select';
const type = [
{ label: 'Public', value: 'public' },
{ label: 'Private', value: 'private' },
{ label: 'Unlisted', value: 'unlisted' },
];
const YoutubeSettings: FC = () => {
const { register, control } = useSettings();
return (
<div className="flex flex-col">
<Input label="Title" {...register('title')} />
<Select label="Type" {...register('type', {value: 'public'})}>
{type.map((t) => (
<option key={t.value} value={t.value}>
{t.label}
</option>
))}
</Select>
<MediumTags label="Tags" {...register('tags')} />
<div className="mt-[20px]">
<MediaComponent
@ -137,7 +151,9 @@ export default withProvider(
YoutubePreview,
YoutubeSettingsDto,
async (items) => {
if (items.length === 1) {
const [firstItems] = items;
if (items.length !== 1) {
return 'Youtube items should be one';
}
@ -145,6 +161,10 @@ export default withProvider(
return 'You need one item';
}
if (firstItems[0].path.indexOf('mp4') === -1) {
return 'Item must be a video';
}
return true;
}
);

View File

@ -1,10 +1,5 @@
import {
IsArray,
IsDefined,
IsOptional,
IsString,
MinLength,
ValidateNested,
IsArray, IsDefined, IsIn, IsOptional, IsString, MinLength, ValidateNested
} from 'class-validator';
import { MediaDto } from '@gitroom/nestjs-libraries/dtos/media/media.dto';
import { Type } from 'class-transformer';
@ -23,6 +18,10 @@ export class YoutubeSettingsDto {
@IsDefined()
title: string;
@IsIn(['public', 'private', 'unlisted'])
@IsDefined()
type: string;
@IsOptional()
@ValidateNested()
@Type(() => MediaDto)

View File

@ -8,8 +8,7 @@ import {
import { makeId } from '@gitroom/nestjs-libraries/services/make.is';
import { google } from 'googleapis';
import { OAuth2Client } from 'google-auth-library/build/src/auth/oauth2client';
import * as console from 'node:console';
import axios, { all } from 'axios';
import axios from 'axios';
import { YoutubeSettingsDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/youtube.settings.dto';
import { SocialAbstract } from '@gitroom/nestjs-libraries/integrations/social.abstract';
import * as process from 'node:process';
@ -45,7 +44,7 @@ const clientAndYoutube = () => {
export class YoutubeProvider extends SocialAbstract implements SocialProvider {
identifier = 'youtube';
name = 'Youtube';
name = 'YouTube';
isBetweenSteps = false;
async refreshToken(refresh_token: string): Promise<AuthTokenDetails> {
@ -152,14 +151,18 @@ export class YoutubeProvider extends SocialAbstract implements SocialProvider {
title: settings.title,
description: firstPost?.message,
tags: settings.tags.map((p) => p.label),
thumbnails: {
default: {
url: settings?.thumbnail?.path,
},
},
...(settings?.thumbnail?.path
? {
thumbnails: {
default: {
url: settings?.thumbnail?.path,
},
},
}
: {}),
},
status: {
privacyStatus: 'public',
privacyStatus: settings.type,
},
},
media: {
@ -167,7 +170,12 @@ export class YoutubeProvider extends SocialAbstract implements SocialProvider {
},
});
console.log(all);
return [{
id: firstPost.id,
releaseURL: `https://www.youtube.com/watch?v=${all.data.id}`,
postId: all?.data?.id!,
status: 'success',
}];
} catch (err) {
console.log(err);
}