From b873599c31274889e4f30edea24db81bb1f1b133 Mon Sep 17 00:00:00 2001 From: Alex Patterson Date: Thu, 19 Oct 2023 20:14:46 -0400 Subject: [PATCH 01/19] bookmarks --- .../src/routes/(content-single)/course/BookMark.svelte | 6 ++++++ .../(content-single)/course/CompletionMark.svelte | 6 ++++++ .../routes/(content-single)/course/LessonList.svelte | 10 ++++++++-- 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 apps/codingcatdev/src/routes/(content-single)/course/BookMark.svelte create mode 100644 apps/codingcatdev/src/routes/(content-single)/course/CompletionMark.svelte diff --git a/apps/codingcatdev/src/routes/(content-single)/course/BookMark.svelte b/apps/codingcatdev/src/routes/(content-single)/course/BookMark.svelte new file mode 100644 index 000000000..82414fb59 --- /dev/null +++ b/apps/codingcatdev/src/routes/(content-single)/course/BookMark.svelte @@ -0,0 +1,6 @@ + + + diff --git a/apps/codingcatdev/src/routes/(content-single)/course/CompletionMark.svelte b/apps/codingcatdev/src/routes/(content-single)/course/CompletionMark.svelte new file mode 100644 index 000000000..eac078c5a --- /dev/null +++ b/apps/codingcatdev/src/routes/(content-single)/course/CompletionMark.svelte @@ -0,0 +1,6 @@ + + + diff --git a/apps/codingcatdev/src/routes/(content-single)/course/LessonList.svelte b/apps/codingcatdev/src/routes/(content-single)/course/LessonList.svelte index 15b3894ed..eba5ec7ea 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/LessonList.svelte +++ b/apps/codingcatdev/src/routes/(content-single)/course/LessonList.svelte @@ -1,10 +1,12 @@ + + +{#if $user?.uid} + {#await $user?.getIdTokenResult()} + + {:then user} + {#if user?.claims?.stripeRole} + + {:else} + + {/if} + {/await} +{:else} + +{/if} diff --git a/apps/codingcatdev/src/routes/(content-single)/course/CompletionMark.svelte b/apps/codingcatdev/src/routes/(content-single)/course/CompletionMark.svelte deleted file mode 100644 index eac078c5a..000000000 --- a/apps/codingcatdev/src/routes/(content-single)/course/CompletionMark.svelte +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/apps/codingcatdev/src/routes/(content-single)/course/Course.svelte b/apps/codingcatdev/src/routes/(content-single)/course/Course.svelte index 99148eee8..01c207b00 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/Course.svelte +++ b/apps/codingcatdev/src/routes/(content-single)/course/Course.svelte @@ -1,14 +1,11 @@ {#if data?.course} @@ -90,12 +87,7 @@ - {#if data?.course?.lesson} -
-

Lessons

- -
- {/if} + {:else} diff --git a/apps/codingcatdev/src/routes/(content-single)/course/LessonCards.svelte b/apps/codingcatdev/src/routes/(content-single)/course/LessonCards.svelte index f2458ec86..2c0b86d62 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/LessonCards.svelte +++ b/apps/codingcatdev/src/routes/(content-single)/course/LessonCards.svelte @@ -1,59 +1,58 @@ -
- {#each lesson as l} - {#if l?.section} -
- - {l.section} - -
-
- {/if} - -
+ + + {/each} + + +{/if} diff --git a/apps/codingcatdev/src/routes/(content-single)/course/LessonList.svelte b/apps/codingcatdev/src/routes/(content-single)/course/LessonList.svelte index eba5ec7ea..65da586b2 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/LessonList.svelte +++ b/apps/codingcatdev/src/routes/(content-single)/course/LessonList.svelte @@ -1,58 +1,43 @@ - +{/if} diff --git a/apps/codingcatdev/src/routes/(content-single)/course/Locked.svelte b/apps/codingcatdev/src/routes/(content-single)/course/Locked.svelte new file mode 100644 index 000000000..503113bb6 --- /dev/null +++ b/apps/codingcatdev/src/routes/(content-single)/course/Locked.svelte @@ -0,0 +1,13 @@ + + +{#if locked} + +{:else} + +{/if} diff --git a/apps/codingcatdev/src/routes/(content-single)/course/ProComplete.svelte b/apps/codingcatdev/src/routes/(content-single)/course/ProComplete.svelte new file mode 100644 index 000000000..5bb9d3360 --- /dev/null +++ b/apps/codingcatdev/src/routes/(content-single)/course/ProComplete.svelte @@ -0,0 +1,35 @@ + + +{#if $userDoc?.completed?.includes(lessonRef)} + +{:else} + +{/if} diff --git a/apps/codingcatdev/src/routes/(protected)/account/+page.server.ts b/apps/codingcatdev/src/routes/(protected)/account/+page.server.ts index e0bb4a6b5..70313b193 100644 --- a/apps/codingcatdev/src/routes/(protected)/account/+page.server.ts +++ b/apps/codingcatdev/src/routes/(protected)/account/+page.server.ts @@ -1,9 +1,5 @@ -import { - ccdValidateSessionCookie, - getUser, - updateUser, - type UserSettings -} from '$lib/server/firebase'; +import { ccdValidateSessionCookie, getUser, updateUser } from '$lib/server/firebase'; +import type { UserDoc } from '$lib/types/index.js'; import { fail } from '@sveltejs/kit'; export const prerender = false; @@ -23,8 +19,8 @@ export const actions = { return fail(401, { user: 'missing' }); } const user = await ccdValidateSessionCookie(ccdsession); - const settings = Object.fromEntries(data.entries()); + const settings: UserDoc['settings'] = { ...Object.fromEntries(data.entries()) }; - await updateUser(user?.uid, { settings }); + await updateUser(user?.uid, settings); } }; diff --git a/apps/codingcatdev/src/styles/markdown.css b/apps/codingcatdev/src/styles/markdown.css index 23e1f2d0a..af63f5368 100644 --- a/apps/codingcatdev/src/styles/markdown.css +++ b/apps/codingcatdev/src/styles/markdown.css @@ -22,4 +22,10 @@ code:is(:not(pre *)) { @apply !text-lg md:!text-2xl; } + .markdown + a:not(.unstyled):not(.permalink):is(:not(.prose *)):not(.btn):not(.btn-icon):not( + .app-bar a + ):not(.logo-item):not(a.card) { + @apply hover:brightness-110 underline; + } } diff --git a/apps/codingcatdev/src/styles/nav-list.css b/apps/codingcatdev/src/styles/nav-list.css index 5f1f8c8f3..bcad4975a 100644 --- a/apps/codingcatdev/src/styles/nav-list.css +++ b/apps/codingcatdev/src/styles/nav-list.css @@ -43,6 +43,6 @@ /* Theme: Rounded */ @apply rounded-token; /* Override typograpy */ - @apply !no-underline !text-base-token dark:!text-dark-token; + @apply !no-underline; } } diff --git a/apps/codingcatdev/src/styles/typography.css b/apps/codingcatdev/src/styles/typography.css index 57713ea9a..3416a9477 100644 --- a/apps/codingcatdev/src/styles/typography.css +++ b/apps/codingcatdev/src/styles/typography.css @@ -33,12 +33,6 @@ @apply text-base; } - a:not(.unstyled):not(.permalink):is(:not(.prose *)):not(.btn):not(.btn-icon):not(.app-bar a):not( - .logo-item - ):not(a.card) { - @apply text-primary-700 dark:text-primary-500 hover:brightness-110 underline; - } - blockquote:not(.unstyled):is(:not(.prose *)) { @apply text-token text-base italic border-l-8 border-l-secondary-500 px-4 pl-4; } diff --git a/apps/firebase/firestore.rules b/apps/firebase/firestore.rules index fca2d5616..0ce12eb3a 100644 --- a/apps/firebase/firestore.rules +++ b/apps/firebase/firestore.rules @@ -1,6 +1,23 @@ rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { + match /users/{userId} { + allow read, write: if belongsTo(userId); + + match /courses/{courseId} { + allow read, write: if belongsTo(userId); + + match /sections/{sectionId} { + allow read, write: if belongsTo(userId); + + match /lessons/{lessonId} { + allow read, write: if belongsTo(userId); + } + } + } + } + + //Stripe match /stripe-customers/{uid} { allow read: if request.auth.uid == uid; @@ -26,5 +43,9 @@ service cloud.firestore { allow read: if true; } } + + function belongsTo(userId) { + return request.auth.uid == userId; + } } } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2c94e1663..2f6ff2ee4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -41,6 +41,9 @@ importers: prism-themes: specifier: ^1.9.0 version: 1.9.0 + sveltefire: + specifier: ^0.4.2 + version: 0.4.2(firebase@10.4.0)(svelte@4.2.1) devDependencies: '@firebase/app-types': specifier: ~0.9.0 @@ -466,7 +469,6 @@ packages: dependencies: '@jridgewell/gen-mapping': 0.3.3 '@jridgewell/trace-mapping': 0.3.19 - dev: true /@apollo/client@3.7.7(graphql@16.6.0): resolution: {integrity: sha512-Rp/pCWuJSjLN7Xl5Qi2NoeURmZYEU/TIUz0n/LOwEo1tGdU2W7/fGVZ8+5um58JeVYq4UoTGBKFxSVeG4s411A==} @@ -2001,7 +2003,7 @@ packages: engines: {node: '>= 10.14.2'} dependencies: '@jest/types': 26.6.2 - '@types/node': 14.18.63 + '@types/node': 20.8.6 chalk: 4.1.2 jest-message-util: 26.6.2 jest-util: 26.6.2 @@ -2017,7 +2019,7 @@ packages: '@jest/test-result': 26.6.2 '@jest/transform': 26.6.2 '@jest/types': 26.6.2 - '@types/node': 14.18.63 + '@types/node': 20.8.6 ansi-escapes: 4.3.2 chalk: 4.1.2 exit: 0.1.2 @@ -2054,7 +2056,7 @@ packages: dependencies: '@jest/fake-timers': 26.6.2 '@jest/types': 26.6.2 - '@types/node': 14.18.63 + '@types/node': 20.8.6 jest-mock: 26.6.2 dev: true @@ -2064,7 +2066,7 @@ packages: dependencies: '@jest/types': 26.6.2 '@sinonjs/fake-timers': 6.0.1 - '@types/node': 14.18.63 + '@types/node': 20.8.6 jest-message-util: 26.6.2 jest-mock: 26.6.2 jest-util: 26.6.2 @@ -2197,28 +2199,23 @@ packages: '@jridgewell/set-array': 1.1.2 '@jridgewell/sourcemap-codec': 1.4.15 '@jridgewell/trace-mapping': 0.3.19 - dev: true /@jridgewell/resolve-uri@3.1.1: resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} engines: {node: '>=6.0.0'} - dev: true /@jridgewell/set-array@1.1.2: resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} engines: {node: '>=6.0.0'} - dev: true /@jridgewell/sourcemap-codec@1.4.15: resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - dev: true /@jridgewell/trace-mapping@0.3.19: resolution: {integrity: sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==} dependencies: '@jridgewell/resolve-uri': 3.1.1 '@jridgewell/sourcemap-codec': 1.4.15 - dev: true /@jsdoc/salty@0.2.5: resolution: {integrity: sha512-TfRP53RqunNe2HBobVBJ0VLhK1HbfvBYeTC1ahnN64PWvyYyGebmMiPkuwvD9fpw2ZbkoPb8Q7mwy0aR8Z9rvw==} @@ -2884,7 +2881,6 @@ packages: /@types/estree@1.0.2: resolution: {integrity: sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==} - dev: true /@types/express-serve-static-core@4.17.33: resolution: {integrity: sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==} @@ -2938,7 +2934,7 @@ packages: /@types/graceful-fs@4.1.7: resolution: {integrity: sha512-MhzcwU8aUygZroVwL2jeYk6JisJrPl/oov/gsgGCue9mkgl9wjGbzReYQClxiUgFDnib9FuHqTndccKeZKxTRw==} dependencies: - '@types/node': 14.18.63 + '@types/node': 20.8.6 dev: true /@types/http-errors@2.0.2: @@ -3767,7 +3763,6 @@ packages: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} dependencies: dequal: 2.0.3 - dev: true /arr-diff@4.0.0: resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==} @@ -3905,7 +3900,6 @@ packages: resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} dependencies: dequal: 2.0.3 - dev: true /babel-jest@26.6.3(@babel/core@7.23.0): resolution: {integrity: sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA==} @@ -4344,7 +4338,6 @@ packages: acorn: 8.10.0 estree-walker: 3.0.3 periscopic: 3.1.0 - dev: true /collect-v8-coverage@1.0.2: resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} @@ -4523,7 +4516,6 @@ packages: dependencies: mdn-data: 2.0.30 source-map-js: 1.0.2 - dev: true /cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} @@ -4684,7 +4676,6 @@ packages: /dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} - dev: true /destroy@1.2.0: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} @@ -5316,7 +5307,6 @@ packages: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} dependencies: '@types/estree': 1.0.2 - dev: true /esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} @@ -6795,7 +6785,6 @@ packages: resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==} dependencies: '@types/estree': 1.0.2 - dev: true /is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} @@ -7066,7 +7055,7 @@ packages: '@jest/environment': 26.6.2 '@jest/fake-timers': 26.6.2 '@jest/types': 26.6.2 - '@types/node': 14.18.63 + '@types/node': 20.8.6 jest-mock: 26.6.2 jest-util: 26.6.2 jsdom: 16.7.0 @@ -7084,7 +7073,7 @@ packages: '@jest/environment': 26.6.2 '@jest/fake-timers': 26.6.2 '@jest/types': 26.6.2 - '@types/node': 14.18.63 + '@types/node': 20.8.6 jest-mock: 26.6.2 jest-util: 26.6.2 dev: true @@ -7100,7 +7089,7 @@ packages: dependencies: '@jest/types': 26.6.2 '@types/graceful-fs': 4.1.7 - '@types/node': 14.18.63 + '@types/node': 20.8.6 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -7126,7 +7115,7 @@ packages: '@jest/source-map': 26.6.2 '@jest/test-result': 26.6.2 '@jest/types': 26.6.2 - '@types/node': 14.18.63 + '@types/node': 20.8.6 chalk: 4.1.2 co: 4.6.0 expect: 26.6.2 @@ -7185,7 +7174,7 @@ packages: engines: {node: '>= 10.14.2'} dependencies: '@jest/types': 26.6.2 - '@types/node': 14.18.63 + '@types/node': 20.8.6 dev: true /jest-pnp-resolver@1.2.3(jest-resolve@26.6.2): @@ -7238,7 +7227,7 @@ packages: '@jest/environment': 26.6.2 '@jest/test-result': 26.6.2 '@jest/types': 26.6.2 - '@types/node': 14.18.63 + '@types/node': 20.8.6 chalk: 4.1.2 emittery: 0.7.2 exit: 0.1.2 @@ -7306,7 +7295,7 @@ packages: resolution: {integrity: sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==} engines: {node: '>= 10.14.2'} dependencies: - '@types/node': 14.18.63 + '@types/node': 20.8.6 graceful-fs: 4.2.11 dev: true @@ -7364,7 +7353,7 @@ packages: dependencies: '@jest/test-result': 26.6.2 '@jest/types': 26.6.2 - '@types/node': 14.18.63 + '@types/node': 20.8.6 ansi-escapes: 4.3.2 chalk: 4.1.2 jest-util: 26.6.2 @@ -7375,7 +7364,7 @@ packages: resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 14.18.63 + '@types/node': 20.8.6 merge-stream: 2.0.0 supports-color: 7.2.0 dev: true @@ -7745,7 +7734,6 @@ packages: /locate-character@3.0.0: resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} - dev: true /locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} @@ -7863,7 +7851,6 @@ packages: engines: {node: '>=12'} dependencies: '@jridgewell/sourcemap-codec': 1.4.15 - dev: true /make-dir@3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} @@ -7947,7 +7934,6 @@ packages: /mdn-data@2.0.30: resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} - dev: true /mdsvex@0.11.0(svelte@4.2.1): resolution: {integrity: sha512-gJF1s0N2nCmdxcKn8HDn0LKrN8poStqAicp6bBcsKFd/zkUBGLP5e7vnxu+g0pjBbDFOscUyI1mtHz+YK2TCDw==} @@ -8629,7 +8615,6 @@ packages: '@types/estree': 1.0.2 estree-walker: 3.0.3 is-reference: 3.0.2 - dev: true /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} @@ -9677,7 +9662,6 @@ packages: /source-map-js@1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} - dev: true /source-map-resolve@0.5.3: resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} @@ -10054,7 +10038,16 @@ packages: locate-character: 3.0.0 magic-string: 0.30.4 periscopic: 3.1.0 - dev: true + + /sveltefire@0.4.2(firebase@10.4.0)(svelte@4.2.1): + resolution: {integrity: sha512-3kt+C8/s+DGCDoyL4nDjvxY7Pq9VEhLbmbuVVzlUW4SpAYqhfutZhitKytnJdT6AwmsahV6x6iGyX0Mwg3sZgw==} + peerDependencies: + firebase: ^9.0.0 + svelte: ^4.0.0 + dependencies: + firebase: 10.4.0 + svelte: 4.2.1 + dev: false /symbol-observable@4.0.0: resolution: {integrity: sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==} From fe68473d217d1f6e01a12d6a53d0a353497edcaf Mon Sep 17 00:00:00 2001 From: Alex Patterson Date: Wed, 25 Oct 2023 15:50:31 -0400 Subject: [PATCH 04/19] removed prerender --- .../(content-single)/course/+layout.server.ts | 2 +- .../src/routes/(protected)/+layout.server.ts | 2 +- .../(protected)/account/+page.server.ts | 2 +- .../codingcatdev/src/routes/+layout.server.ts | 2 +- .../src/routes/login/+page.server.ts | 2 +- .../src/routes/search/+page.server.ts | 2 +- .../src/routes/signup/+page.server.ts | 50 +++++++++---------- 7 files changed, 31 insertions(+), 31 deletions(-) diff --git a/apps/codingcatdev/src/routes/(content-single)/course/+layout.server.ts b/apps/codingcatdev/src/routes/(content-single)/course/+layout.server.ts index f174c1f5f..f814bde5d 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/+layout.server.ts +++ b/apps/codingcatdev/src/routes/(content-single)/course/+layout.server.ts @@ -3,7 +3,7 @@ import { allowLocal, filterContent, getContentTypePath } from '$lib/server/conte import { ContentType, type Course, type Author, type Sponsor } from '$lib/types'; import { getShowDrafts } from '$lib/server/firebase'; -export const prerender = false; +//export const prerender = false; export const load = async ({ url, parent }) => { const data = await parent(); diff --git a/apps/codingcatdev/src/routes/(protected)/+layout.server.ts b/apps/codingcatdev/src/routes/(protected)/+layout.server.ts index f02cd3957..72f5548d6 100644 --- a/apps/codingcatdev/src/routes/(protected)/+layout.server.ts +++ b/apps/codingcatdev/src/routes/(protected)/+layout.server.ts @@ -2,7 +2,7 @@ import { allowLocal } from '$lib/server/content'; import { getStripeProducts } from '$lib/server/firebase'; import { redirect } from '@sveltejs/kit'; -export const prerender = false; +//export const prerender = false; export const load = async ({ url, parent }) => { const data = await parent(); diff --git a/apps/codingcatdev/src/routes/(protected)/account/+page.server.ts b/apps/codingcatdev/src/routes/(protected)/account/+page.server.ts index 70313b193..c91c76cde 100644 --- a/apps/codingcatdev/src/routes/(protected)/account/+page.server.ts +++ b/apps/codingcatdev/src/routes/(protected)/account/+page.server.ts @@ -2,7 +2,7 @@ import { ccdValidateSessionCookie, getUser, updateUser } from '$lib/server/fireb import type { UserDoc } from '$lib/types/index.js'; import { fail } from '@sveltejs/kit'; -export const prerender = false; +//export const prerender = false; export const load = async ({ url, parent }) => { const data = await parent(); diff --git a/apps/codingcatdev/src/routes/+layout.server.ts b/apps/codingcatdev/src/routes/+layout.server.ts index 43d9106f5..179b8c447 100644 --- a/apps/codingcatdev/src/routes/+layout.server.ts +++ b/apps/codingcatdev/src/routes/+layout.server.ts @@ -2,7 +2,7 @@ import { listContent, getContentTypeDirectory } from '$lib/server/content'; import { ccdValidateSessionCookie, validateStripeRole } from '$lib/server/firebase'; import { type Content, ContentType } from '$lib/types'; import type { Cookies } from '@sveltejs/kit'; -export const prerender = false; +//export const prerender = false; export const load = async ({ cookies }: { cookies: Cookies }) => { try { // Get latest podcast diff --git a/apps/codingcatdev/src/routes/login/+page.server.ts b/apps/codingcatdev/src/routes/login/+page.server.ts index 825e37cf2..1a8a82f81 100644 --- a/apps/codingcatdev/src/routes/login/+page.server.ts +++ b/apps/codingcatdev/src/routes/login/+page.server.ts @@ -2,7 +2,7 @@ import { ccdCreateSessionCookie } from '$lib/server/firebase'; import type { Actions, PageServerLoad } from './$types'; import { fail, redirect } from '@sveltejs/kit'; -export const prerender = false; +//export const prerender = false; export const actions = { login: async ({ cookies, url }) => { diff --git a/apps/codingcatdev/src/routes/search/+page.server.ts b/apps/codingcatdev/src/routes/search/+page.server.ts index 9065c5736..efa0598f5 100644 --- a/apps/codingcatdev/src/routes/search/+page.server.ts +++ b/apps/codingcatdev/src/routes/search/+page.server.ts @@ -1,6 +1,6 @@ import { init, inited, search } from '$lib/search'; -export const prerender = false; +//export const prerender = false; export async function load({ url, fetch }) { if (!inited) { diff --git a/apps/codingcatdev/src/routes/signup/+page.server.ts b/apps/codingcatdev/src/routes/signup/+page.server.ts index 0e60f3266..f043d84af 100644 --- a/apps/codingcatdev/src/routes/signup/+page.server.ts +++ b/apps/codingcatdev/src/routes/signup/+page.server.ts @@ -1,36 +1,36 @@ import { ccdCreateSessionCookie } from '$lib/server/firebase'; import type { Actions } from './$types'; -import { fail, redirect } from '@sveltejs/kit' +import { fail, redirect } from '@sveltejs/kit'; -export const prerender = false; +//export const prerender = false; export const actions = { - signup: async ({ cookies, url }) => { - const ccdLoginIdToken = cookies.get('__ccdlogin'); + signup: async ({ cookies, url }) => { + const ccdLoginIdToken = cookies.get('__ccdlogin'); - if (!ccdLoginIdToken) { - return fail(400, { missing: true }); - } + if (!ccdLoginIdToken) { + return fail(400, { missing: true }); + } - const sessionCookie = await ccdCreateSessionCookie(ccdLoginIdToken); - if (!sessionCookie) { - return fail(400, { incorrect: true }); - } - cookies.set(sessionCookie.name, sessionCookie.sessionCookie, sessionCookie.options); - cookies.set('__ccdlogin', '', { expires: new Date(Date.now() - 3600) }); + const sessionCookie = await ccdCreateSessionCookie(ccdLoginIdToken); + if (!sessionCookie) { + return fail(400, { incorrect: true }); + } + cookies.set(sessionCookie.name, sessionCookie.sessionCookie, sessionCookie.options); + cookies.set('__ccdlogin', '', { expires: new Date(Date.now() - 3600) }); - if (url.searchParams.has('redirectTo')) { - throw redirect(303, url.searchParams.get('redirectTo') || '/'); - } - throw redirect(303, '/'); - }, + if (url.searchParams.has('redirectTo')) { + throw redirect(303, url.searchParams.get('redirectTo') || '/'); + } + throw redirect(303, '/'); + } } satisfies Actions; -export const load = (async ({ parent, url }) => { - const { user } = await parent(); - if (user) throw redirect(303, '/account'); +export const load = async ({ parent, url }) => { + const { user } = await parent(); + if (user) throw redirect(303, '/account'); - return { - redirectTo: url.searchParams.get('redirectTo') || '' - } -}); \ No newline at end of file + return { + redirectTo: url.searchParams.get('redirectTo') || '' + }; +}; From 7155d9f926daceb934323bb486f4815e8140546a Mon Sep 17 00:00:00 2001 From: Alex Patterson Date: Wed, 25 Oct 2023 19:01:41 -0400 Subject: [PATCH 05/19] add settings and bookmarks clientside --- apps/codingcatdev/src/lib/server/firebase.ts | 27 ----------- apps/codingcatdev/src/lib/types/index.ts | 14 ++++-- .../course/LessonCards.svelte | 7 ++- .../(content-single)/course/LessonList.svelte | 7 +-- .../course/ProBookmark.svelte | 46 +++++++++++++++++++ .../course/ProComplete.svelte | 21 +++++++-- ...mpletionLockMark.svelte => ProMark.svelte} | 28 ++++++----- .../(protected)/account/+page.server.ts | 22 +-------- .../routes/(protected)/account/+page.svelte | 8 +++- .../(protected)/account/UserSettings.svelte | 35 +++++++++++--- apps/firebase/firestore.rules | 12 ----- 11 files changed, 129 insertions(+), 98 deletions(-) create mode 100644 apps/codingcatdev/src/routes/(content-single)/course/ProBookmark.svelte rename apps/codingcatdev/src/routes/(content-single)/course/{CompletionLockMark.svelte => ProMark.svelte} (62%) diff --git a/apps/codingcatdev/src/lib/server/firebase.ts b/apps/codingcatdev/src/lib/server/firebase.ts index 5b176d747..4a7e807ed 100644 --- a/apps/codingcatdev/src/lib/server/firebase.ts +++ b/apps/codingcatdev/src/lib/server/firebase.ts @@ -102,30 +102,3 @@ export const getStripeProducts = async () => { } return products; }; - -export const getUser = async (uid?: string) => { - if (!uid) return undefined; - - // Check if user is Pro and wants drafts - const auth = getAuth(app); - const user = await auth.getUser(uid); - - const db = getFirestore(); - const doc = await db.collection('users').doc(user.uid).get(); - return doc.data() as UserDoc; -}; - -export const updateUser = async (uid?: string, userSettings?: UserDoc['settings']) => { - if (!uid) return undefined; - if (!userSettings) return; - - // Check if user is Pro and wants drafts - const auth = getAuth(app); - const user = await auth.getUser(uid); - - const db = getFirestore(); - await db - .collection('users') - .doc(user.uid) - .set({ ...(userSettings || null) }, { merge: true }); -}; diff --git a/apps/codingcatdev/src/lib/types/index.ts b/apps/codingcatdev/src/lib/types/index.ts index b26a97713..44eaad093 100644 --- a/apps/codingcatdev/src/lib/types/index.ts +++ b/apps/codingcatdev/src/lib/types/index.ts @@ -151,10 +151,18 @@ export interface DirectoryStub { } export type Stub = FileStub | DirectoryStub; - -export interface UserDoc extends Content { - completed?: string[]; +export interface UserDoc { + pro?: Pro; +} +export interface Pro { settings?: { showDrafts?: boolean; }; + completed?: PathDate[]; + bookmarked?: PathDate[]; +} + +export interface PathDate { + path: string; + date: number; } diff --git a/apps/codingcatdev/src/routes/(content-single)/course/LessonCards.svelte b/apps/codingcatdev/src/routes/(content-single)/course/LessonCards.svelte index 2c0b86d62..71e5129ed 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/LessonCards.svelte +++ b/apps/codingcatdev/src/routes/(content-single)/course/LessonCards.svelte @@ -1,9 +1,8 @@ @@ -39,8 +38,8 @@ {/if}
-
- +
+
{l.title} diff --git a/apps/codingcatdev/src/routes/(content-single)/course/LessonList.svelte b/apps/codingcatdev/src/routes/(content-single)/course/LessonList.svelte index 65da586b2..12f5d91a7 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/LessonList.svelte +++ b/apps/codingcatdev/src/routes/(content-single)/course/LessonList.svelte @@ -1,10 +1,8 @@ + +{#if $userDoc?.pro?.bookmarked?.filter((c) => c.path === lessonRef)?.length} + +{:else} + +{/if} diff --git a/apps/codingcatdev/src/routes/(content-single)/course/ProComplete.svelte b/apps/codingcatdev/src/routes/(content-single)/course/ProComplete.svelte index 5bb9d3360..d1fe06c96 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/ProComplete.svelte +++ b/apps/codingcatdev/src/routes/(content-single)/course/ProComplete.svelte @@ -4,7 +4,7 @@ import { CheckCircle } from '@steeze-ui/heroicons'; import { Icon } from '@steeze-ui/svelte-icon'; import type { LayoutData } from './$types'; - import type { Lesson } from '$lib/types'; + import type { Lesson, UserDoc } from '$lib/types'; /* DATA */ export let data: LayoutData; @@ -12,14 +12,18 @@ const user = userStore(auth); const docRef = 'users/' + $user?.uid; - const userDoc = docStore(firestore, docRef); + const userDoc = docStore(firestore, docRef); const lessonRef = `/course/${data.course.slug}/lesson/${lesson.slug}`; -{#if $userDoc?.completed?.includes(lessonRef)} +{#if $userDoc?.pro?.completed?.filter((c) => c.path === lessonRef)?.length}
diff --git a/apps/codingcatdev/src/routes/(protected)/account/UserSettings.svelte b/apps/codingcatdev/src/routes/(protected)/account/UserSettings.svelte index ccd14230e..4c246e767 100644 --- a/apps/codingcatdev/src/routes/(protected)/account/UserSettings.svelte +++ b/apps/codingcatdev/src/routes/(protected)/account/UserSettings.svelte @@ -1,7 +1,32 @@
@@ -12,21 +37,19 @@
-
+
updateShowDrafts(e)} >
Show Drafts
Pro Feature
-
- -
- +
diff --git a/apps/firebase/firestore.rules b/apps/firebase/firestore.rules index 0ce12eb3a..20c6b0e96 100644 --- a/apps/firebase/firestore.rules +++ b/apps/firebase/firestore.rules @@ -3,18 +3,6 @@ service cloud.firestore { match /databases/{database}/documents { match /users/{userId} { allow read, write: if belongsTo(userId); - - match /courses/{courseId} { - allow read, write: if belongsTo(userId); - - match /sections/{sectionId} { - allow read, write: if belongsTo(userId); - - match /lessons/{lessonId} { - allow read, write: if belongsTo(userId); - } - } - } } //Stripe From 0fda86d565bf7d53ba4279f62797dbea62003de2 Mon Sep 17 00:00:00 2001 From: Alex Patterson Date: Thu, 26 Oct 2023 10:59:35 -0400 Subject: [PATCH 06/19] change bookmarks and complete to sub collection --- apps/codingcatdev/src/lib/client/firebase.ts | 5 ++- .../(content-single)/course/LessonList.svelte | 4 +- .../course/ProBookmark.svelte | 45 ++++++++++--------- .../course/ProComplete.svelte | 45 ++++++++++--------- .../(content-single)/course/ProMark.svelte | 4 +- apps/firebase/firestore.rules | 8 ++++ 6 files changed, 61 insertions(+), 50 deletions(-) diff --git a/apps/codingcatdev/src/lib/client/firebase.ts b/apps/codingcatdev/src/lib/client/firebase.ts index 8aeae38df..6a143137d 100644 --- a/apps/codingcatdev/src/lib/client/firebase.ts +++ b/apps/codingcatdev/src/lib/client/firebase.ts @@ -17,7 +17,8 @@ import { onSnapshot, Firestore, setDoc, - type DocumentData + type DocumentData, + initializeFirestore } from 'firebase/firestore'; import { httpsCallable, getFunctions, type Functions } from 'firebase/functions'; import { @@ -61,7 +62,7 @@ if ( // As httpOnly cookies are to be used, do not persist any state client side. // setPersistence(auth, browserSessionPersistence); - firestore = getFirestore(app); + firestore = initializeFirestore(app, { ignoreUndefinedProperties: true }); functions = getFunctions(app); analytics = getAnalytics(app); } else { diff --git a/apps/codingcatdev/src/routes/(content-single)/course/LessonList.svelte b/apps/codingcatdev/src/routes/(content-single)/course/LessonList.svelte index 12f5d91a7..7b168d083 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/LessonList.svelte +++ b/apps/codingcatdev/src/routes/(content-single)/course/LessonList.svelte @@ -10,7 +10,7 @@ {#if data?.course?.lesson} -
+
{/if} - - diff --git a/apps/codingcatdev/src/routes/(content-list)/guests/GuestCards.svelte b/apps/codingcatdev/src/routes/(content-list)/guests/GuestCards.svelte index 37b78bb6e..f02ad54c9 100644 --- a/apps/codingcatdev/src/routes/(content-list)/guests/GuestCards.svelte +++ b/apps/codingcatdev/src/routes/(content-list)/guests/GuestCards.svelte @@ -71,9 +71,3 @@ {/if} - - diff --git a/apps/codingcatdev/src/routes/(content-list)/sponsors/SponsorCards.svelte b/apps/codingcatdev/src/routes/(content-list)/sponsors/SponsorCards.svelte index f0bde5c75..4e32da3cd 100644 --- a/apps/codingcatdev/src/routes/(content-list)/sponsors/SponsorCards.svelte +++ b/apps/codingcatdev/src/routes/(content-list)/sponsors/SponsorCards.svelte @@ -63,9 +63,3 @@ {/if} - - diff --git a/apps/codingcatdev/src/routes/(content-single)/course/ProCourseBookmarked.svelte b/apps/codingcatdev/src/routes/(content-single)/course/ProCourseBookmarked.svelte index 34f00a5d8..f56dd06f9 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/ProCourseBookmarked.svelte +++ b/apps/codingcatdev/src/routes/(content-single)/course/ProCourseBookmarked.svelte @@ -1,12 +1,13 @@ diff --git a/apps/codingcatdev/src/routes/(content-single)/course/ProCourseCompleted.svelte b/apps/codingcatdev/src/routes/(content-single)/course/ProCourseCompleted.svelte index fc4345eea..cdf0e7965 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/ProCourseCompleted.svelte +++ b/apps/codingcatdev/src/routes/(content-single)/course/ProCourseCompleted.svelte @@ -1,12 +1,13 @@ diff --git a/apps/codingcatdev/src/routes/(content-single)/course/ProCourseMark.svelte b/apps/codingcatdev/src/routes/(content-single)/course/ProCourseMark.svelte index e2412ab5d..38bbf05e3 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/ProCourseMark.svelte +++ b/apps/codingcatdev/src/routes/(content-single)/course/ProCourseMark.svelte @@ -1,14 +1,19 @@ @@ -30,6 +31,7 @@ {:else} Free {/if} + {#if data?.authors}
diff --git a/apps/codingcatdev/src/routes/(content-single)/course/ProCourseCompleted.svelte b/apps/codingcatdev/src/routes/(content-single)/course/ProCourseCompleted.svelte index cdf0e7965..22829e762 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/ProCourseCompleted.svelte +++ b/apps/codingcatdev/src/routes/(content-single)/course/ProCourseCompleted.svelte @@ -1,12 +1,12 @@ diff --git a/apps/codingcatdev/src/routes/(content-single)/course/ProCourseMark.svelte b/apps/codingcatdev/src/routes/(content-single)/course/ProCourseMark.svelte index 38bbf05e3..8a28f27be 100644 --- a/apps/codingcatdev/src/routes/(content-single)/course/ProCourseMark.svelte +++ b/apps/codingcatdev/src/routes/(content-single)/course/ProCourseMark.svelte @@ -5,13 +5,15 @@ import { ContentType } from '$lib/types'; import ProCourseCompleted from './ProCourseCompleted.svelte'; import ProCourseBookmarked from './ProCourseBookmarked.svelte'; + import ProSaved from './ProSaved.svelte'; import { auth } from '$lib/client/firebase'; import { userStore } from 'sveltefire'; + import { Bookmark } from '@steeze-ui/heroicons'; /* DATA */ export let data: { content?: Content; - course: Course | Saved; + course?: Course | Saved; user?: LayoutData['user']; }; export let lesson: Lesson | undefined = undefined; @@ -21,10 +23,31 @@ {#if data?.user?.stripeRole && $user?.uid} -
- - -
+ {#if data?.course !== undefined} +
+ + +
+ {:else if data?.content} +
+ +
{/if} {:else if data.content?.type === ContentType.lesson}
diff --git a/apps/codingcatdev/src/routes/(content-single)/course/ProSaved.svelte b/apps/codingcatdev/src/routes/(content-single)/course/ProSaved.svelte new file mode 100644 index 000000000..f412ceafd --- /dev/null +++ b/apps/codingcatdev/src/routes/(content-single)/course/ProSaved.svelte @@ -0,0 +1,52 @@ + + + +{#if $saved?.savedComplete} + +{:else} + +{/if} diff --git a/apps/codingcatdev/src/routes/(protected)/dashboard/+page.svelte b/apps/codingcatdev/src/routes/(protected)/dashboard/+page.svelte index 960b1ba89..34b1526c1 100644 --- a/apps/codingcatdev/src/routes/(protected)/dashboard/+page.svelte +++ b/apps/codingcatdev/src/routes/(protected)/dashboard/+page.svelte @@ -9,6 +9,7 @@ import DashboardBookmarks from './DashboardBookmarks.svelte'; import { auth } from '$lib/client/firebase'; import { userStore } from 'sveltefire'; + import DashboardCompleted from './DashboardCompleted.svelte'; export let data: PageData; @@ -32,6 +33,7 @@ {#if $user?.uid} + {/if}
diff --git a/apps/codingcatdev/src/routes/(protected)/dashboard/DashboardBookmarks.svelte b/apps/codingcatdev/src/routes/(protected)/dashboard/DashboardBookmarks.svelte index 075126d60..c6119df48 100644 --- a/apps/codingcatdev/src/routes/(protected)/dashboard/DashboardBookmarks.svelte +++ b/apps/codingcatdev/src/routes/(protected)/dashboard/DashboardBookmarks.svelte @@ -7,12 +7,13 @@ import { collectionStore, userStore } from 'sveltefire'; import { auth, firestore } from '$lib/client/firebase'; import type { Saved } from '$lib/types'; - import ProCourseMark from '../../(content-single)/course/ProCourseMark.svelte'; + import { collection, orderBy, query } from 'firebase/firestore'; const user = userStore(auth); export let data: PageData; const bookmarkedRef = 'users/' + $user?.uid + `/bookmarked`; - const bookmarked = collectionStore(firestore, bookmarkedRef); + const q: any = query(collection(firestore, bookmarkedRef), orderBy('savedUpdated', 'desc')); + const bookmarked = collectionStore(firestore, q);
@@ -30,7 +31,7 @@
{#each $bookmarked as bookmark (bookmark)} -
+
{#if bookmark?.cover} {/if}
-
+

{bookmark.title}

+ {#if bookmark?.lesson}