init: Initial Commit

This commit is contained in:
2024-01-15 20:47:37 -05:00
commit 5a2fd27aa3
28 changed files with 3416 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
FROM node:lts-alpine as develop-stage
WORKDIR /app
COPY package*.json ./
RUN yarn install
COPY . .
FROM develop-stage as build-stage
RUN yarn build
FROM nginx:stable-alpine as production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

View File

@@ -0,0 +1,12 @@
const exampleFilenames = [
'Solyaris.1972.1080p.BluRay.FLAC2.0.x264-SbR.mkv',
'Dekalog.E01.REPACK.1989.720p.BluRay.AAC.1.0.x264-ZQ.mkv',
'The.Mandalorian.S02E01.Chapter.9.The.Marshal.1080p.DSNP.WEB-DL.DDP5.1.Atmos.H.264-LAZY.mkv',
'Planet.Earth.SE.E01.From.Pole.To.Pole.2006.1080i.BluRay.Remux.VC-1.DTS-HD.5.1-DA4LiFE.mkv',
'Ugetsu monogatari 1953 720p BluRay AAC2.0 x264-npuer.mkv',
'Tetsuwan Atom (1959) [TSHS] episode 01 [66C473BB].mp4',
'The.Star.Wars.Holiday.Special.1978.EditDroid.Edition.DVDRip.x264.mkv',
'Hitchcock.Presents.S01E01.1955.Revenge.DVDRip.DD2.x264-HANDJOB.mkv'
]
export default exampleFilenames

View File

@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>guessit</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

2654
services/frontend/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
{
"name": "guessit",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"@highlightjs/vue-plugin": "github:highlightjs/vue-plugin",
"axios": "^1.6.5",
"highlight.js": "^11.9.0",
"vue": "^3.3.11",
"vue3-simple-icons": "^11.0.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.5.2",
"autoprefixer": "^10.4.16",
"postcss": "^8.4.33",
"tailwindcss": "^3.4.1",
"typescript": "^5.2.2",
"vite": "^5.0.8",
"vue-tsc": "^1.8.25"
}
}

View File

@@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,22 @@
<script setup lang="ts">
import { ref } from 'vue'
import Header from './components/Header.vue'
import Home from './components/Home.vue'
import About from './components/About.vue'
import Footer from './components/Footer.vue'
const isHome = ref(true)
const setHome = (value: boolean) => {
isHome.value = value
}
</script>
<template>
<div class="min-h-screen w-full bg-slate-100 flex flex-col justify-between items-center p-16 gap-5 text-neutral-700">
<Header @setHome="setHome" />
<Home v-if="isHome" />
<About v-else />
<Footer />
</div>
</template>

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>

After

Width:  |  Height:  |  Size: 496 B

View File

@@ -0,0 +1,43 @@
<script setup lang="ts">
import { VueDotjsIcon, TailwindCssIcon, FlaskIcon, DockerIcon, VercelIcon, GoogleCloudIcon } from 'vue3-simple-icons'
</script>
<template>
<div class="flex flex-col gap-2 flew-grow text-center md:w-[750px]">
<div class="flex flex-col items-center justify-center bg-[#2e3440] rounded-lg shadow-lg text-white p-8 space-y-5">
<h2 class="text-4xl font-semibold">
About
</h2>
<p>
A web app that guesses info about a video file based on its filename, this app was made with Vue 3 and Tailwind CSS, the backend its powered by Flask and the python library guessit, it was deployed with Vercel and GCP.
</p>
</div>
<div class="flex items-center gap-2 text-sm flex-wrap justify-center">
<div class="bg-[#2e3440] rounded shadow-lg text-white px-3 py-2 flex gap-2 items-center">
<FlaskIcon class="w-4 h-4 fill-slate-50" />
<p>Flask</p>
</div>
<div class="bg-[#2e3440] rounded shadow-lg text-white px-3 py-2 flex gap-2 items-center">
<VueDotjsIcon class="w-4 h-4 fill-slate-50" />
<p>VueJS</p>
</div>
<div class="bg-[#2e3440] rounded shadow-lg text-white px-3 py-2 flex gap-2 items-center">
<TailwindCssIcon class="w-4 h-4 fill-slate-50" />
<p>TailwindCSS</p>
</div>
<div class="bg-[#2e3440] rounded shadow-lg text-white px-3 py-2 flex gap-2 items-center">
<DockerIcon class="w-4 h-4 fill-slate-50" />
<p>Docker</p>
</div>
<div class="bg-[#2e3440] rounded shadow-lg text-white px-3 py-2 flex gap-2 items-center">
<VercelIcon class="w-4 h-4 fill-slate-50" />
<p>Vercel</p>
</div>
<div class="bg-[#2e3440] rounded shadow-lg text-white px-3 py-2 flex gap-2 items-center">
<GoogleCloudIcon class="w-4 h-4 fill-slate-50" />
<p>Google Cloud Platform</p>
</div>
</div>
</div>
</template>

View File

@@ -0,0 +1,14 @@
<script setup lang="ts">
</script>
<template>
<div>
<ul class="flex justify-center bg-white rounded-lg px-2 py-1 text-sm shadow">
<a href="https://www.xyvs.io/" target="_blank" >
<li class="font-semibold rounded-lg px-3 py-2 hover:bg-neutral-50">
Made by xyvs
</li>
</a>
</ul>
</div>
</template>

View File

@@ -0,0 +1,30 @@
<script setup lang="ts">
const emit = defineEmits(['setHome'])
const setHome = (value: boolean) => {
emit('setHome', value)
}
</script>
<template>
<div>
<ul class="flex justify-center bg-white rounded-lg px-2 py-1 text-sm shadow">
<a href="#/" @click="setHome(true)">
<li class="font-semibold rounded-lg px-3 py-2 hover:bg-neutral-50">
Home
</li>
</a>
<a href="#/" @click="setHome(false)">
<li class="font-semibold rounded-lg px-3 py-2 hover:bg-neutral-50">
About
</li>
</a>
<a href="https://github.com/xyvs/guessit_app" target="_blank">
<li class="font-semibold rounded-lg px-3 py-2 hover:bg-neutral-50">
Code
</li>
</a>
</ul>
</div>
</template>

View File

@@ -0,0 +1,68 @@
<script setup lang="ts">
import { ref } from 'vue'
import axios from 'axios'
import exampleFilenames from '../../constants/filenames.ts'
import formatDictionaryAsString from '../../utils/formatting.ts'
const filename = ref('')
const code = ref(`{
result: 'Fill the input with the filename and click Guess'
}`)
const url = `${import.meta.env.VITE_HOST_URL}`
const setRandomFilename = () => {
filename.value = exampleFilenames[Math.floor(Math.random() * exampleFilenames.length)];
getFilenameData()
}
const getFilenameData = () => {
const data = {
filename: filename.value
}
axios.get(url, { params: data })
.then(response => {
code.value = formatDictionaryAsString(response.data)
})
.catch((error) => {
console.log(error)
})
}
</script>
<template>
<div class="flex flex-col gap-12 flew-grow text-center md:w-[600px] bg-[#2e3440] rounded-lg text-neutral-100 shadow pt-12 pb-6">
<div class="space-y-12 px-12">
<div class="flex flex-col items-center justify-center gap-4">
<h2 class="text-4xl font-semibold">
guessit
</h2>
<p>
A web app that guesses info about a video file based on its filename.
</p>
</div>
<div class="space-y-4 text-neutral-700">
<div class="text-sm flex w-full">
<div class="flex-grow">
<input v-model="filename" type="text" class="bg-neutral-100 p-3 rounded-l appearance-none focus:outline-none w-full shadow" placeholder="Enter the filename">
</div>
<button class="bg-slate-200 px-4 py-3 rounded-r shadow font-semibold hover:bg-slate-300" @click="getFilenameData">
Guess
</button>
</div>
<div class="flex flex-wrap justify-center text-sm gap-4">
<a href="#/">
<div class="bg-slate-200 rounded shadow px-4 py-2 font-semibold hover:bg-slate-300" @click="setRandomFilename">
Try a random filename
</div>
</a>
</div>
</div>
</div>
<div class="text-left text-sm rounded px-4">
<highlightjs :code="code" ref="codeRef" />
</div>
</div>
</template>

View File

@@ -0,0 +1,13 @@
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import 'highlight.js/styles/nord.css'
import hljs from 'highlight.js/lib/core';
import javascript from 'highlight.js/lib/languages/javascript';
import hljsVuePlugin from "@highlightjs/vue-plugin";
hljs.registerLanguage('javascript', javascript);
const app = createApp(App)
app.use(hljsVuePlugin)
app.mount('#app')

View File

@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

1
services/frontend/src/vite-env.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
/// <reference types="vite/client" />

View File

@@ -0,0 +1,11 @@
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{vue,js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}

View File

@@ -0,0 +1,25 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }]
}

View File

@@ -0,0 +1,10 @@
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}

View File

@@ -0,0 +1,15 @@
const formatDictionaryAsString = (obj: Object, indentation = 2) => {
let result: string = "{\n";
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
let value = obj[key];
let line = ' '.repeat(indentation) + `${key}: '${value}',\n`;
result += line;
}
}
result = result.slice(0, -2);
result += `\n}`;
return result;
}
export default formatDictionaryAsString;

View File

@@ -0,0 +1,7 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
})