mirror of
https://github.com/Arcadia-Solutions/arcadia.git
synced 2026-01-06 09:39:38 -06:00
Merge pull request #52 from bees/front-ci-basic
Add CI checks for the frontend for linting and formatting
This commit is contained in:
20
.github/workflows/ci.yml
vendored
20
.github/workflows/ci.yml
vendored
@@ -48,3 +48,23 @@ jobs:
|
||||
|
||||
- name: Ensure schema and query metadata are in sync
|
||||
run: cargo sqlx prepare --check
|
||||
|
||||
lint-format-frontend:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./frontend
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: 'npm'
|
||||
cache-dependency-path: frontend/package-lock.json
|
||||
|
||||
- run: npm ci
|
||||
- run: npm run lint
|
||||
- run: npm run check-format
|
||||
|
||||
|
||||
1
frontend/.gitignore
vendored
1
frontend/.gitignore
vendored
@@ -8,7 +8,6 @@ pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
package-lock.json
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
|
||||
7627
frontend/package-lock.json
generated
Normal file
7627
frontend/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -14,7 +14,8 @@
|
||||
"lint:oxlint": "oxlint . --fix -D correctness --ignore-path .gitignore",
|
||||
"lint:eslint": "eslint . --fix",
|
||||
"lint": "run-s lint:*",
|
||||
"format": "prettier --write src/"
|
||||
"format": "prettier --write src/",
|
||||
"check-format": "prettier --check src"
|
||||
},
|
||||
"dependencies": {
|
||||
"@primeuix/themes": "^1.0.0",
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
|
||||
/* semantic color variables for this project */
|
||||
:root {
|
||||
|
||||
--color-primary: #5fe1ab;
|
||||
--color-secondary: rgb(135, 110, 208);
|
||||
--color-background-primary: #2f2f2f;
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
@import './base.css';
|
||||
|
||||
body{
|
||||
body {
|
||||
margin: 0;
|
||||
background-color: var(--color-background-primary); /* Dark theme */
|
||||
}
|
||||
|
||||
#app{
|
||||
#app {
|
||||
max-width: 2100px;
|
||||
margin: 0 auto;
|
||||
font-weight: normal;
|
||||
|
||||
}
|
||||
|
||||
#app-container {
|
||||
@@ -20,21 +19,21 @@ body{
|
||||
color: white;
|
||||
}
|
||||
|
||||
#view-container{
|
||||
#view-container {
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
a:hover{
|
||||
a:hover {
|
||||
background-color: transparent !important;
|
||||
/* color: var(--color-primary); */
|
||||
}
|
||||
a{
|
||||
a {
|
||||
color: var(--color-secondary);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.p-datatable-table,
|
||||
.p-accordionpanel{
|
||||
.p-accordionpanel {
|
||||
border-radius: 7px;
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -42,10 +41,10 @@ a{
|
||||
width: 100% !important;
|
||||
} */
|
||||
|
||||
.dense-accordion .p-accordionheader{
|
||||
.dense-accordion .p-accordionheader {
|
||||
padding: 0.5em;
|
||||
}
|
||||
.dense-accordion .p-accordioncontent-content{
|
||||
.dense-accordion .p-accordioncontent-content {
|
||||
padding-top: 1em;
|
||||
}
|
||||
|
||||
@@ -59,14 +58,14 @@ a{
|
||||
overflow-wrap: break-word !important;
|
||||
}
|
||||
|
||||
.bold{
|
||||
.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
.warning{
|
||||
.warning {
|
||||
color: rgb(213, 128, 31);
|
||||
}
|
||||
.danger{
|
||||
color:rgb(214, 52, 52);
|
||||
.danger {
|
||||
color: rgb(214, 52, 52);
|
||||
}
|
||||
|
||||
.line {
|
||||
|
||||
@@ -80,7 +80,7 @@ export default {
|
||||
this.new_comment.answers_to_comment_id = null
|
||||
data.created_by = {}
|
||||
data.created_by = useUserStore()
|
||||
// TODO: don't mutate the prop
|
||||
// eslint-disable-next-line vue/no-mutating-props -- TODO: don't mutate the prop
|
||||
this.comments.push(data)
|
||||
this.sending_comment = false
|
||||
})
|
||||
|
||||
@@ -235,13 +235,13 @@ export default {
|
||||
addCover() {
|
||||
this.editionGroupForm.covers.push('')
|
||||
},
|
||||
removeCover(index: Number) {
|
||||
removeCover(index: number) {
|
||||
this.editionGroupForm.covers.splice(index, 1)
|
||||
},
|
||||
addLink() {
|
||||
this.editionGroupForm.external_links.push('')
|
||||
},
|
||||
removeLink(index: Number) {
|
||||
removeLink(index: number) {
|
||||
this.editionGroupForm.external_links.splice(index, 1)
|
||||
},
|
||||
},
|
||||
|
||||
@@ -28,7 +28,7 @@ export default {
|
||||
torrent_requests: {},
|
||||
},
|
||||
methods: {
|
||||
bytesToReadable(bytes: Number) {
|
||||
bytesToReadable(bytes: number) {
|
||||
return bytesToReadable(bytes)
|
||||
},
|
||||
},
|
||||
|
||||
@@ -286,13 +286,13 @@ export default {
|
||||
addLink() {
|
||||
this.titleGroupForm.external_links.push('')
|
||||
},
|
||||
removeLink(index: Number) {
|
||||
removeLink(index: number) {
|
||||
this.titleGroupForm.external_links.splice(index, 1)
|
||||
},
|
||||
addCover() {
|
||||
this.titleGroupForm.covers.push('')
|
||||
},
|
||||
removeCover(index: Number) {
|
||||
removeCover(index: number) {
|
||||
this.titleGroupForm.covers.splice(index, 1)
|
||||
},
|
||||
},
|
||||
|
||||
@@ -191,7 +191,7 @@ export default {
|
||||
return { titleGroupStore }
|
||||
},
|
||||
methods: {
|
||||
getExternalDatabaseData(item_id: string | Number, database: string) {
|
||||
getExternalDatabaseData(item_id: string | number, database: string) {
|
||||
this.gettingExternalDatabaseData = true
|
||||
getExternalDatabaseData(item_id, database).then((data) => {
|
||||
data.title_group.original_release_date = new Date(data.title_group.original_release_date)
|
||||
@@ -204,7 +204,7 @@ export default {
|
||||
this.gettingExternalDatabaseData = false
|
||||
})
|
||||
},
|
||||
async sendTitleGroup(titleGroupForm: Object) {
|
||||
async sendTitleGroup(titleGroupForm: object) {
|
||||
if (this.action == 'select') {
|
||||
this.gettingTitleGroupInfo = true
|
||||
if (!this.titleGroupStore.id) {
|
||||
|
||||
@@ -11,9 +11,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Image } from 'primevue'
|
||||
export default {
|
||||
components: { Image },
|
||||
props: {
|
||||
title_group: {},
|
||||
},
|
||||
|
||||
@@ -179,9 +179,11 @@ export default {
|
||||
const reportedTorrent = this.title_group.edition_groups
|
||||
.flatMap((edition_group) => edition_group.torrents)
|
||||
.find((torrent) => torrent.id == torrentReport.reported_torrent_id)
|
||||
reportedTorrent.reports
|
||||
? reportedTorrent.reports.push(torrentReport)
|
||||
: (reportedTorrent.reports = [torrentReport])
|
||||
if (reportedTorrent.reports) {
|
||||
reportedTorrent.reports.push(torrentReport)
|
||||
} else {
|
||||
reportedTorrent.reports = [torrentReport]
|
||||
}
|
||||
},
|
||||
reportTorrent(id: number) {
|
||||
this.reportingTorrentId = id
|
||||
@@ -197,13 +199,13 @@ export default {
|
||||
timeAgo(date: string) {
|
||||
return timeAgo(date)
|
||||
},
|
||||
bytesToReadable(bytes: Number) {
|
||||
bytesToReadable(bytes: number) {
|
||||
return bytesToReadable(bytes)
|
||||
},
|
||||
purifyHtml(html: string) {
|
||||
return DOMPurify.sanitize(html)
|
||||
},
|
||||
downloadTorrent(torrentId: Number) {
|
||||
downloadTorrent(torrentId: number) {
|
||||
downloadTorrent(torrentId)
|
||||
},
|
||||
},
|
||||
@@ -218,9 +220,9 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
getEditionGroupSlug() {
|
||||
return (id: Number) => {
|
||||
return (id: number) => {
|
||||
return getEditionGroupSlug(
|
||||
this.title_group.edition_groups.find((group: Object) => group.id === id),
|
||||
this.title_group.edition_groups.find((group: object) => group.id === id),
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import axios from 'axios';
|
||||
import axios from 'axios'
|
||||
|
||||
const api = axios.create({
|
||||
baseURL: 'http://localhost:8080/api',
|
||||
@@ -6,16 +6,19 @@ const api = axios.create({
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
api.interceptors.request.use((config) => {
|
||||
const token = localStorage.getItem('token');
|
||||
if (token && !config.url?.includes('/login') && !config.url?.includes('/register')) {
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
return config;
|
||||
}, (error) => {
|
||||
return Promise.reject(error);
|
||||
});
|
||||
api.interceptors.request.use(
|
||||
(config) => {
|
||||
const token = localStorage.getItem('token')
|
||||
if (token && !config.url?.includes('/login') && !config.url?.includes('/register')) {
|
||||
config.headers.Authorization = `Bearer ${token}`
|
||||
}
|
||||
return config
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error)
|
||||
},
|
||||
)
|
||||
|
||||
export default api;
|
||||
export default api
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import api from './api.ts'
|
||||
|
||||
export const getArtist = async (id: string | Number) => {
|
||||
export const getArtist = async (id: string | number) => {
|
||||
try {
|
||||
return (await api.get('/artist?id=' + id)).data
|
||||
} catch (error) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import api from './api.ts'
|
||||
|
||||
export const login = async (form: Object) => {
|
||||
export const login = async (form: object) => {
|
||||
try {
|
||||
return (await api.post('/login', form)).data
|
||||
} catch (error) {
|
||||
@@ -9,7 +9,7 @@ export const login = async (form: Object) => {
|
||||
}
|
||||
}
|
||||
|
||||
export const register = async (form: Object) => {
|
||||
export const register = async (form: object) => {
|
||||
try {
|
||||
return (await api.post('/register', form)).data
|
||||
} catch (error) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import api from './api.ts'
|
||||
|
||||
export const getExternalDatabaseData = async (item_id: string | Number, database: string) => {
|
||||
export const getExternalDatabaseData = async (item_id: string | number, database: string) => {
|
||||
try {
|
||||
switch (database) {
|
||||
case 'openlibrary': {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import api from './api.ts'
|
||||
|
||||
export const subscribeToItem = async (item_id: string | Number, item: string) => {
|
||||
export const subscribeToItem = async (item_id: string | number, item: string) => {
|
||||
try {
|
||||
return (await api.post('/subscription?item=' + item + '&item_id=' + item_id)).data
|
||||
} catch (error) {
|
||||
@@ -8,7 +8,7 @@ export const subscribeToItem = async (item_id: string | Number, item: string) =>
|
||||
throw error
|
||||
}
|
||||
}
|
||||
export const unsubscribeToItem = async (item_id: string | Number, item: string) => {
|
||||
export const unsubscribeToItem = async (item_id: string | number, item: string) => {
|
||||
try {
|
||||
return (await api.delete('/subscription?item=' + item + '&item_id=' + item_id)).data
|
||||
} catch (error) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import api from './api.ts'
|
||||
|
||||
export const getSeries = async (id: string | Number) => {
|
||||
export const getSeries = async (id: string | number) => {
|
||||
try {
|
||||
return (await api.get('/series?id=' + id)).data
|
||||
} catch (error) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import api from './api.ts'
|
||||
|
||||
export const getTitleGroup = async (id: string | Number) => {
|
||||
export const getTitleGroup = async (id: string | number) => {
|
||||
try {
|
||||
return (await api.get('/title-group?id=' + id)).data
|
||||
} catch (error) {
|
||||
@@ -8,7 +8,7 @@ export const getTitleGroup = async (id: string | Number) => {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
export const getTitleGroupLite = async (id: string | Number) => {
|
||||
export const getTitleGroupLite = async (id: string | number) => {
|
||||
try {
|
||||
return (await api.get('/title-group/lite?id=' + id)).data
|
||||
} catch (error) {
|
||||
@@ -52,7 +52,7 @@ export const uploadTorrent = async (torrentForm: object) => {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
export const downloadTorrent = async (torrentId: Number | string) => {
|
||||
export const downloadTorrent = async (torrentId: number | string) => {
|
||||
try {
|
||||
const response = await api.get('/torrent?id=' + torrentId, {
|
||||
responseType: 'blob',
|
||||
|
||||
@@ -15,7 +15,11 @@ function preProcess(text) {
|
||||
|
||||
function getType(text) {
|
||||
text = preProcess(text)
|
||||
return text.match(/Disc (Title|Label)\s*:/i) ? 'bdinfo' : text.match(/Complete name\s*:/i) ? 'mediainfo' : null
|
||||
return text.match(/Disc (Title|Label)\s*:/i)
|
||||
? 'bdinfo'
|
||||
: text.match(/Complete name\s*:/i)
|
||||
? 'mediainfo'
|
||||
: null
|
||||
}
|
||||
|
||||
export const getFileInfo = (text) => {
|
||||
@@ -43,4 +47,3 @@ export const getFileInfo = (text) => {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -160,8 +160,8 @@ export default class MediainfoConverter {
|
||||
/2160p/i.test(completeName) || width === '3840'
|
||||
? '2160p'
|
||||
: /1080i/i.test(completeName) ||
|
||||
((width === '1920' || (width < 1920 && height === '1080')) &&
|
||||
(scanType === 'Interlaced' || scanType === 'MBAFF'))
|
||||
((width === '1920' || (width < 1920 && height === '1080')) &&
|
||||
(scanType === 'Interlaced' || scanType === 'MBAFF'))
|
||||
? '1080i'
|
||||
: /1080p/i.test(completeName) || width === '1920' || (width < 1920 && height === '1080')
|
||||
? '1080p'
|
||||
|
||||
@@ -35,7 +35,7 @@ export default class MediainfoParser {
|
||||
return result
|
||||
}
|
||||
|
||||
extractFields({ sectionName, sectionBody }) {
|
||||
extractFields({ sectionName: _sectionName, sectionBody }) {
|
||||
const result = {}
|
||||
const lines = splitIntoLines(sectionBody)
|
||||
for (const line of lines) {
|
||||
@@ -47,4 +47,4 @@ export default class MediainfoParser {
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ export function splitIntoBDInfoSections(text) {
|
||||
.trim()
|
||||
.replace(/\n\r/, '\n')
|
||||
.split(/([a-zA-Z ]*:\n)/)
|
||||
.map((v) => v.trim())
|
||||
.map((v) => v.trim()),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ export function splitIntoSections(text) {
|
||||
.trim()
|
||||
.replace(/\n\r/, '\n')
|
||||
.split(/\n\s*\n/)
|
||||
.map((v) => v.trim())
|
||||
.map((v) => v.trim()),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ export function splitIntoLines(text) {
|
||||
.trim()
|
||||
.replace(/\n\r/, '\n')
|
||||
.split(/\n/)
|
||||
.map((v) => v.trim())
|
||||
.map((v) => v.trim()),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -78,4 +78,4 @@ export function calcDiskType(size) {
|
||||
} else if (size <= DISK_SIZE.BD100) {
|
||||
return 'BD100'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ export const timeAgo = (date: string) => {
|
||||
? `${Math.floor(diff / 3600)}h ago`
|
||||
: `${Math.floor(diff / 86400)}d ago`
|
||||
}
|
||||
export const bytesToReadable = (bytes: Number) => {
|
||||
export const bytesToReadable = (bytes: number) => {
|
||||
const units = ['B', 'KiB', 'MiB', 'GiB', 'TiB']
|
||||
let size = bytes
|
||||
let unitIndex = 0
|
||||
@@ -69,7 +69,7 @@ export const isValidUrl = (url: string) => {
|
||||
try {
|
||||
new URL(url)
|
||||
return true
|
||||
} catch (_) {
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,13 +22,14 @@
|
||||
/>
|
||||
</div>
|
||||
</ContentContainer>
|
||||
<TitleGroupPreviewTable
|
||||
v-for="title_group in title_groups"
|
||||
:key="title_group.id"
|
||||
:title_group="title_group"
|
||||
v-if="title_group_preview_mode == 'table'"
|
||||
class="preview-table"
|
||||
/>
|
||||
<div v-if="title_group_preview_mode == 'table'">
|
||||
<TitleGroupPreviewTable
|
||||
v-for="title_group in title_groups"
|
||||
:key="title_group.id"
|
||||
:title_group="title_group"
|
||||
class="preview-table"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<ArtistSidebar :artist />
|
||||
</div>
|
||||
|
||||
@@ -22,13 +22,14 @@
|
||||
/>
|
||||
</div>
|
||||
</ContentContainer>
|
||||
<TitleGroupPreviewTable
|
||||
v-for="title_group in title_groups"
|
||||
:key="title_group.id"
|
||||
:title_group="title_group"
|
||||
v-if="title_group_preview_mode == 'table'"
|
||||
class="preview-table"
|
||||
/>
|
||||
<div v-if="title_group_preview_mode == 'table'">
|
||||
<TitleGroupPreviewTable
|
||||
v-for="title_group in title_groups"
|
||||
:key="title_group.id"
|
||||
:title_group="title_group"
|
||||
class="preview-table"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<SeriesSidebar :series />
|
||||
</div>
|
||||
|
||||
@@ -15,13 +15,14 @@
|
||||
/>
|
||||
</div>
|
||||
</ContentContainer>
|
||||
<TitleGroupPreviewTable
|
||||
v-for="title_group in search_results.title_groups"
|
||||
:key="title_group.id"
|
||||
:title_group="title_group"
|
||||
v-if="title_group_preview_mode == 'table'"
|
||||
class="preview-table"
|
||||
/>
|
||||
<div v-if="title_group_preview_mode == 'table'">
|
||||
<TitleGroupPreviewTable
|
||||
v-for="title_group in search_results.title_groups"
|
||||
:key="title_group.id"
|
||||
:title_group="title_group"
|
||||
class="preview-table"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user