-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
etl pipeline to postgres with prisma to frontend
- Loading branch information
1 parent
fc7e929
commit b31ca14
Showing
33 changed files
with
2,167 additions
and
336 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Dockerfile | ||
FROM node:19-alpine | ||
WORKDIR /app | ||
RUN apk add --update --no-cache libc6-compat | ||
COPY package*.json ./ | ||
RUN npm install | ||
EXPOSE 3000 | ||
|
||
CMD ["npm", "run", "dev", "--"] |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
<template> | ||
<div> | ||
<v-footer :elevation="0" class="mt-16"> | ||
<v-container class="py-16"> | ||
|
||
<div class="d-flex"> | ||
<div style="width:150px"> | ||
<nuxt-link to="https://github.com/2x-ai"><img src="/assets/2x_logo_white.svg" alt="2xAI logo" | ||
height="48" /></nuxt-link> | ||
</div> | ||
<div class="me-auto pl-4"> | ||
<nuxt-link to="https://twitter.com/marcusklarqvist"><v-icon>mdi-twitter</v-icon></nuxt-link> | ||
<nuxt-link to="https://twitter.com/twoxAI"><v-icon>mdi-twitter</v-icon></nuxt-link> | ||
<nuxt-link to="https://github.com/2x-ai"><v-icon>mdi-github</v-icon></nuxt-link> | ||
<nuxt-link to="https://github.com/mklarqvist"><v-icon>mdi-github</v-icon></nuxt-link> | ||
</div> | ||
</div> | ||
Data sources are: <nuxt-link to="https://www.themoviedb.org/">TMDb</nuxt-link>, <nuxt-link | ||
to="https://www.imdb.com/">IMDb</nuxt-link>, <nuxt-link to="https://www.wikipedia.org/">Wikipedia</nuxt-link>, | ||
<nuxt-link to="https://themoviespoiler.com/">The Movie Spoiler</nuxt-link>. Copyrights and all other rights belong | ||
to their respective owner. | ||
</v-container> | ||
</v-footer> | ||
</div> | ||
</template> | ||
|
||
<script setup> | ||
</script> | ||
|
||
<style> | ||
.v-footer { | ||
color: rgba(255, 255, 255, 0.7); | ||
background-color: black; | ||
} | ||
.v-footer a { | ||
text-decoration: underline; | ||
color: rgba(255, 255, 255, 0.7); | ||
} | ||
.v-footer a:hover { | ||
opacity: 1; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
<template> | ||
<div> | ||
<v-app-bar style="color:white;" | ||
:style="props.color ? `background-color: rgba(${props.color.DarkVibrant.rgb[0]},${props.color.DarkVibrant.rgb[1]},${props.color.DarkVibrant.rgb[2]}, 1)` : 'inherit'"> | ||
<v-app-bar-nav-icon> | ||
<img src="/assets/movie_2x_logo.svg" height="36" /> | ||
</v-app-bar-nav-icon> | ||
<v-app-bar-title style="flex: inherit;margin-inline-start:8px;-webkit-margin-start: 8px;" class="mr-4"> | ||
<nuxt-link to="/">FlickFinder</nuxt-link> | ||
</v-app-bar-title> | ||
|
||
<!-- Search bar --> | ||
<v-text-field v-model="search" hide-details prepend-inner-icon="mdi-magnify" single-line placeholder="Search" | ||
@keyup.enter="searchMovie(search)"></v-text-field> | ||
|
||
|
||
<v-spacer></v-spacer> | ||
|
||
<!-- Links --> | ||
<nuxt-link to="https://www.github.com/mklarqvist"> | ||
<v-btn icon> | ||
<v-icon>mdi-github</v-icon> | ||
</v-btn> | ||
</nuxt-link> | ||
|
||
<nuxt-link to="https://www.twitter.com/marcusklarqvist"> | ||
<v-btn icon> | ||
<v-icon>mdi-twitter</v-icon> | ||
</v-btn> | ||
</nuxt-link> | ||
|
||
</v-app-bar> | ||
</div> | ||
</template> | ||
|
||
<script setup> | ||
const props = defineProps({ | ||
color: { | ||
type: Object, // A colorPalette | ||
required: false | ||
}, | ||
}); | ||
const search = ref(''); | ||
const searchMovie = (query) => { | ||
if (query) { | ||
navigateTo(`/search/${query}`) | ||
} | ||
} | ||
</script> | ||
|
||
<style scoped> | ||
.v-toolbar { | ||
background-color: black; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
<template> | ||
<!-- dialog text similarity --> | ||
<div class="text-center"> | ||
<v-dialog v-model="props.dialogSynopsis" width="auto" @keydown.esc="togglePanel()"> | ||
<v-card> | ||
<div style="position: relative;"> | ||
<v-row style="border: 1px solid rgba(0,0,0,0.2);margin: 20px 0;"> | ||
<v-col md="2" cols="3" style="border-right: 1px solid rgba(0,0,0,0.2);padding: 0;"> | ||
<v-img class="poster lazyload lazyloaded" | ||
:src="`https://www.themoviedb.org/t/p/w300_and_h450_bestv2/${props.referencePosterPath}`" | ||
:data-src="`https://www.themoviedb.org/t/p/w300_and_h450_bestv2/${props.referencePosterPath}`" | ||
:data-srcset="`https://www.themoviedb.org/t/p/w300_and_h450_bestv2/${props.referencePosterPath} 1x, https://www.themoviedb.org/t/p/w600_and_h900_bestv2/${props.referencePosterPath} 2x`" | ||
:srcset="`https://www.themoviedb.org/t/p/w300_and_h450_bestv2/${props.referencePosterPath} 1x, https://www.themoviedb.org/t/p/w600_and_h900_bestv2/${props.referencePosterPath} 2x`" | ||
:alt="title" width="100%"> | ||
<template v-slot:placeholder> | ||
<div class="d-flex align-center justify-center fill-height"> | ||
<v-progress-circular color="grey-lighten-4" indeterminate></v-progress-circular> | ||
</div> | ||
</template> | ||
</v-img> | ||
</v-col> | ||
<v-col md="4" cols="3" style="border-right: 1px solid rgba(0,0,0,0.2);" class="pa-4"> | ||
<h3>{{ props.title }}</h3> | ||
<div class="mb-2">Matching synopsis section (could be truncated):</div> | ||
<word-animator :inputText="props.referenceText"></word-animator> | ||
<div class="mt-2"> | ||
Source: <img src="/assets/imdb_logo.png" alt="IMDb logo" height="15"> | ||
</div> | ||
</v-col> | ||
<v-col md="4" cols="3" style="border-right: 1px solid rgba(0,0,0,0.2);" class="pa-4"> | ||
<h3>{{ props.queryTitle }}</h3> | ||
<div class="mb-2">Matching synopsis section (could be truncated):</div> | ||
<word-animator :inputText="props.queryText"></word-animator> | ||
<div class="mt-2"> | ||
Source: <img src="/assets/imdb_logo.png" alt="IMDb logo" height="15"> | ||
</div> | ||
|
||
</v-col> | ||
<v-col md="2" cols="3" style="padding: 0;"> | ||
<nuxt-link :to="`/movie/${queryMovieId}`"> | ||
<v-img class="poster lazyload lazyloaded" | ||
:src="`https://www.themoviedb.org/t/p/w300_and_h450_bestv2/${props.queryPosterPath}`" | ||
:data-src="`https://www.themoviedb.org/t/p/w300_and_h450_bestv2/${props.queryPosterPath}`" | ||
:data-srcset="`https://www.themoviedb.org/t/p/w300_and_h450_bestv2/${props.queryPosterPath} 1x, https://www.themoviedb.org/t/p/w600_and_h900_bestv2/${props.queryPosterPath} 2x`" | ||
:srcset="`https://www.themoviedb.org/t/p/w300_and_h450_bestv2/${props.queryPosterPath} 1x, https://www.themoviedb.org/t/p/w600_and_h900_bestv2/${props.queryPosterPath} 2x`" | ||
:alt="title" width="100%"> | ||
<template v-slot:placeholder> | ||
<div class="d-flex align-center justify-center fill-height"> | ||
<v-progress-circular color="grey-lighten-4" indeterminate></v-progress-circular> | ||
</div> | ||
</template> | ||
</v-img> | ||
<v-btn style=" | ||
-webkit-transition: background 100ms,opacity 100ms; | ||
transition: background 100ms,opacity 100ms; | ||
border: none; | ||
outline: none; | ||
cursor: pointer; | ||
line-height: 1; | ||
color: #fff; | ||
background: linear-gradient(145deg,#000,#333); | ||
border-radius: 24px; | ||
-webkit-letter-spacing: 1px; | ||
-moz-letter-spacing: 1px; | ||
-ms-letter-spacing: 1px; | ||
letter-spacing: 1px; | ||
font-size: 14px; | ||
padding: 16px 20px; | ||
height: 48px; | ||
width: 100%; | ||
border-radius: 0; | ||
border-bottom-left-radius: 24px; | ||
border-bottom-right-radius: 24px; | ||
"> | ||
<v-icon class="mr-2">mdi-movie-filter-outline</v-icon>Visit</v-btn> | ||
</nuxt-link> | ||
</v-col> | ||
</v-row> | ||
|
||
<v-btn color="black" variant="text" @click="togglePanel()" | ||
style="position: absolute;top:5px;right:5px;background-color: rgba(0,0,0,0.25)"><v-icon>mdi-close</v-icon></v-btn> | ||
|
||
</div> | ||
</v-card> | ||
</v-dialog> | ||
</div> | ||
</template> | ||
|
||
<script setup> | ||
const props = defineProps({ | ||
title: { | ||
type: String, | ||
required: true | ||
}, | ||
queryTitle: { | ||
type: String, | ||
required: true | ||
}, | ||
queryPosterPath: { | ||
type: String, | ||
required: true | ||
}, | ||
referencePosterPath: { | ||
type: String, | ||
required: true | ||
}, | ||
dialogSynopsis: Boolean, | ||
queryText: { | ||
type: String, | ||
required: true | ||
}, | ||
referenceText: { | ||
type: String, | ||
required: true | ||
}, | ||
referenceMovieId: { | ||
type: Number, | ||
required: true | ||
}, | ||
queryMovieId: { | ||
type: Number, | ||
required: true | ||
}, | ||
}) | ||
const emit = defineEmits(['closePanel']) | ||
function togglePanel() { | ||
console.log('clicked close panel') | ||
emit('closePanel') | ||
} | ||
</script> | ||
|
||
<style scoped> | ||
.v-responsive__sizer { | ||
padding-bottom: 100%; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
<template> | ||
<div class="word-animator"> | ||
<span class="text-progress" :class="{'animate-[cursorBlink_600ms_ease-in-out_infinite_alternate]': isRunning, 'text-finished': isFinished}">{{ animatedWord }}</span> | ||
</div> | ||
</template> | ||
|
||
<script setup> | ||
import { watchEffect } from "vue"; | ||
const props = defineProps({ | ||
inputText: String, | ||
}); | ||
const animatedWord = ref(""); | ||
const isRunning = ref(false) | ||
const isFinished = ref(false) | ||
const animateText = (text) => { | ||
isRunning.value = true | ||
isFinished.value = false | ||
animatedWord.value = ""; | ||
const animationSpeed = 2; // 2 milliseconds per character | ||
let charIndex = 0; | ||
const intervalId = setInterval(() => { | ||
animatedWord.value += text[charIndex]; | ||
charIndex++; | ||
if (charIndex >= text.length) { | ||
clearInterval(intervalId); | ||
isRunning.value = false | ||
isFinished.value = true | ||
} | ||
}, animationSpeed); | ||
}; | ||
watchEffect(() => { | ||
if (props.inputText) { | ||
animateText(props.inputText); | ||
} | ||
}); | ||
</script> | ||
|
||
<style lang="scss" scoped> | ||
.text-progress { | ||
white-space: pre-wrap; | ||
font-size: 1rem; | ||
line-height: 130%; | ||
letter-spacing: 0; | ||
-moz-osx-font-smoothing: grayscale; | ||
-webkit-font-smoothing: antialiased; | ||
border-right: 12px solid #000; | ||
background-color: rgba(0, 0, 0, 0.2); | ||
transition: background-color .2s ease-in-out; | ||
} | ||
.animate-\[cursorBlink_600ms_ease-in-out_infinite_alternate\] { | ||
-webkit-animation: cursorBlink .6s ease-in-out infinite alternate; | ||
animation: cursorBlink .6s ease-in-out infinite alternate; | ||
} | ||
.text-finished { | ||
border: none; | ||
background-color: transparent; | ||
} | ||
@-webkit-keyframes cursorBlink { | ||
0% { | ||
border-right-color:initial | ||
} | ||
to { | ||
border-right-color:transparent | ||
} | ||
} | ||
@keyframes cursorBlink { | ||
0% { | ||
border-right-color:initial | ||
} | ||
to { | ||
border-right-color:transparent | ||
} | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# docker-compose.yml | ||
version: '3.9' | ||
|
||
services: | ||
nuxt: | ||
build: . | ||
container_name: nuxt-app | ||
ports: | ||
- '3000:3000' | ||
depends_on: | ||
- db | ||
environment: | ||
DATABASE_URL: postgresql://user:password@db:5432/dbname | ||
volumes: | ||
- .:/app | ||
- /app/node_modules | ||
db: | ||
image: postgres:15.2-alpine | ||
container_name: postgres-db | ||
environment: | ||
POSTGRES_USER: user | ||
POSTGRES_PASSWORD: password | ||
POSTGRES_DB: dbname | ||
volumes: | ||
- db-data:/var/lib/postgresql/data | ||
|
||
volumes: | ||
db-data: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.