Skip to content

Commit dc39d37

Browse files
author
Alex Patterson
committed
youtube code flow working
1 parent 7813e62 commit dc39d37

File tree

7 files changed

+185
-6
lines changed

7 files changed

+185
-6
lines changed

frontend/admin/src/components/Admin/EditPost.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import {
1717
postDataObservable,
1818
postHistoriesDataObservable,
1919
postHistoryCreate,
20-
postHistoryPublish,
2120
postHistoryUpdate,
2221
} from '@/services/api';
2322

@@ -39,6 +38,8 @@ import VideoFormModal from '@/components/Admin/VideoFormModal';
3938
import ImageModal from '@/components/Admin/ImageModal';
4039
import VideoModal from '@/components/Admin/VideoModal';
4140
import PublishModal from '@/components/Admin/PublishModal';
41+
import { NextRouter } from 'next/router';
42+
import YouTubeUpload from '@/components/YouTube/YouTubeUpload';
4243

4344
enum TabType {
4445
edit = 'edit',
@@ -78,9 +79,9 @@ export default function EditPost({
7879
router,
7980
type,
8081
}: {
81-
router: any;
82+
router: NextRouter;
8283
type: PostType;
83-
}) {
84+
}): JSX.Element {
8485
const [postFound, setPostFound] = useState(false);
8586
const [postHistories, setPostHistories] = useState<Post[] | Course[]>([]);
8687
const [history, setHistory] = useState<Post | Course>();
@@ -320,6 +321,7 @@ export default function EditPost({
320321
setHistory={setHistory}
321322
post={history}
322323
/>
324+
<YouTubeUpload />
323325
</Box>
324326
)}
325327
</Box>

frontend/admin/src/components/Admin/VideoFormModal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ export default function VideoFormModal({
154154
paddingRight: '0.5rem',
155155
}}
156156
>
157-
Add Video Cover
157+
Add Video From URL
158158
</Box>
159159
<VideoIcon />
160160
</Button>
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { makeStyles, createStyles, Button, Box } from '@material-ui/core';
2+
import { red } from '@material-ui/core/colors';
3+
4+
import YouTubeIcon from '@material-ui/icons/YouTube';
5+
import { getAuthURL } from '@/services/api';
6+
import { take } from 'rxjs/operators';
7+
import { UserInfoExtended } from '@/models/user.model';
8+
import { useUser } from '@/utils/auth/useUser';
9+
10+
const useStyles = makeStyles(() =>
11+
createStyles({
12+
video: {
13+
backgroundColor: red[500],
14+
'&:hover': {
15+
backgroundColor: red[300],
16+
},
17+
},
18+
})
19+
);
20+
21+
export default function YouTubeUpload(): JSX.Element {
22+
const { user }: { user: UserInfoExtended | null | undefined } = useUser();
23+
24+
const classes = useStyles();
25+
return (
26+
<>
27+
<Button
28+
variant="contained"
29+
className={classes.video}
30+
onClick={() =>
31+
getAuthURL({
32+
redirectUri: 'http://localhost:3001/auth/youtube',
33+
})
34+
.pipe(take(1))
35+
.subscribe((r) => {
36+
window.location.href = r as string;
37+
})
38+
}
39+
>
40+
<Box
41+
sx={{
42+
paddingRight: '0.5rem',
43+
}}
44+
>
45+
Authorize YouTube
46+
</Box>
47+
<YouTubeIcon />
48+
</Button>
49+
</>
50+
);
51+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import firebase from 'firebase/app';
2+
3+
export interface UserInfoExtended extends firebase.UserInfo {
4+
memberships?: UserMembership[];
5+
token?: string;
6+
}
7+
8+
export interface UserMembership {
9+
membership: boolean;
10+
membershipType: MembershipType;
11+
subscriptionId: string;
12+
}
13+
14+
export enum MembershipType {
15+
supporter = 'supporter',
16+
monthly = 'monthly',
17+
yearly = 'yearly',
18+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import Head from 'next/head';
2+
import { NextRouter, withRouter } from 'next/router';
3+
import Layout from '@/layout/Layout';
4+
import { take } from 'rxjs/operators';
5+
import { makeStyles, createStyles, Button, Box } from '@material-ui/core';
6+
import YouTubeIcon from '@material-ui/icons/YouTube';
7+
import { red } from '@material-ui/core/colors';
8+
import { createAndSaveTokens } from '@/services/api';
9+
import { UserInfoExtended } from '@/models/user.model';
10+
import { useUser } from '@/utils/auth/useUser';
11+
12+
const useStyles = makeStyles(() =>
13+
createStyles({
14+
video: {
15+
backgroundColor: red[500],
16+
'&:hover': {
17+
backgroundColor: red[300],
18+
},
19+
},
20+
})
21+
);
22+
23+
function AdminDashboard({
24+
router,
25+
handleThemeChange,
26+
darkMode,
27+
}: {
28+
router: NextRouter;
29+
handleThemeChange: any;
30+
darkMode: boolean;
31+
}) {
32+
const { user }: { user: UserInfoExtended | null | undefined } = useUser();
33+
const code = router.query.code;
34+
const classes = useStyles();
35+
return (
36+
<Layout handleThemeChange={handleThemeChange} darkMode={darkMode}>
37+
<Head>
38+
<title>YouTube Auth | CodingCatDev</title>
39+
<meta name="robots" content="noindex" />
40+
</Head>
41+
42+
<div>
43+
{user && user.uid && code ? (
44+
<div>
45+
<h1>Store YouTube Authorization</h1>
46+
<p>{code}</p>
47+
<>
48+
<Button
49+
variant="contained"
50+
className={classes.video}
51+
onClick={() =>
52+
createAndSaveTokens({
53+
code,
54+
redirectUri: 'http://localhost:3001/auth/youtube',
55+
})
56+
.pipe(take(1))
57+
.subscribe()
58+
}
59+
>
60+
<Box
61+
sx={{
62+
paddingRight: '0.5rem',
63+
}}
64+
>
65+
Authorize YouTube
66+
</Box>
67+
<YouTubeIcon />
68+
</Button>
69+
</>
70+
</div>
71+
) : (
72+
<div>
73+
<h2>
74+
You must be logged in and receiving a YouTube code for this page.
75+
</h2>
76+
</div>
77+
)}
78+
</div>
79+
</Layout>
80+
);
81+
}
82+
83+
export default withRouter(AdminDashboard);

frontend/admin/src/services/api.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,3 +392,26 @@ export function cleanTimestamp(data: FirebaseFirestore.DocumentData) {
392392
});
393393
return docData;
394394
}
395+
396+
/* YouTube Upload */
397+
export const getAuthURL = (params: any) => {
398+
return functions$.pipe(
399+
switchMap((functions) =>
400+
httpsCallable(
401+
functions,
402+
'ext-ccd-extension-youtube-upload-getAuthURL'
403+
).call('params', params)
404+
)
405+
);
406+
};
407+
408+
export const createAndSaveTokens = (params: any) => {
409+
return functions$.pipe(
410+
switchMap((functions) =>
411+
httpsCallable(
412+
functions,
413+
'ext-ccd-extension-youtube-upload-createAndSaveTokens'
414+
).call('params', params)
415+
)
416+
);
417+
};

frontend/admin/src/utils/auth/useUser.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ import { Observable } from 'rxjs';
1212
import { authState } from 'rxfire/auth';
1313
import { filter, map, switchMap, takeWhile } from 'rxjs/operators';
1414
import firebase from 'firebase/app';
15+
import { UserInfoExtended } from '@/models/user.model';
16+
1517
const useUser = () => {
1618
const [app, setApp] = useState<firebase.app.App>();
17-
const [user, setUser] = useState<firebase.UserInfo | null>();
19+
const [user, setUser] = useState<UserInfoExtended | null>();
1820
const [
1921
userProfile,
2022
setUserProfile,
21-
] = useState<Observable<firebase.UserInfo> | null>(null);
23+
] = useState<Observable<UserInfoExtended> | null>(null);
2224
const router = useRouter();
2325

2426
const signout = async () => {

0 commit comments

Comments
 (0)