Resolved all ts lint errors on build

This commit is contained in:
2022-08-11 18:37:33 +02:00
parent f7fe582200
commit 41067aae84
19 changed files with 130 additions and 66 deletions

View File

@@ -13,10 +13,16 @@
<script setup lang="ts"> <script setup lang="ts">
import { defineProps } from "vue"; import { defineProps } from "vue";
import CastListItem from "src/components/CastListItem.vue"; import CastListItem from "src/components/CastListItem.vue";
import type { MediaTypes, CreditTypes } from "../interfaces/IList"; import type {
IMovie,
IShow,
IPerson,
ICast,
ICrew
} from "../interfaces/IList";
interface Props { interface Props {
cast: Array<MediaTypes | CreditTypes>; cast: Array<IMovie | IShow | IPerson | ICast | ICrew>;
} }
defineProps<Props>(); defineProps<Props>();

View File

@@ -11,10 +11,10 @@
<script setup lang="ts"> <script setup lang="ts">
import { defineProps, computed } from "vue"; import { defineProps, computed } from "vue";
import { useStore } from "vuex"; import { useStore } from "vuex";
import type { MediaTypes, CreditTypes } from "../interfaces/IList"; import type { ICast, ICrew, IMovie, IShow } from "../interfaces/IList";
interface Props { interface Props {
creditItem: MediaTypes | CreditTypes; creditItem: ICast | ICrew | IMovie | IShow;
} }
const props = defineProps<Props>(); const props = defineProps<Props>();

View File

@@ -14,13 +14,12 @@
import { useStore } from "vuex"; import { useStore } from "vuex";
import Movie from "@/components/popup/Movie.vue"; import Movie from "@/components/popup/Movie.vue";
import Person from "@/components/popup/Person.vue"; import Person from "@/components/popup/Person.vue";
import { ListTypes } from "../interfaces/IList"; import { MediaTypes } from "../interfaces/IList";
import type { MediaTypes } from "../interfaces/IList";
import type { Ref } from "vue"; import type { Ref } from "vue";
interface URLQueryParameters { interface URLQueryParameters {
id: number; id: number;
type: ListTypes; type: MediaTypes;
} }
const store = useStore(); const store = useStore();
@@ -41,14 +40,23 @@
}); });
function getFromURLQuery(): URLQueryParameters { function getFromURLQuery(): URLQueryParameters {
let id, type; let id: number;
let type: MediaTypes;
const params = new URLSearchParams(window.location.search); const params = new URLSearchParams(window.location.search);
params.forEach((value, key) => { params.forEach((value, key) => {
if (!(key in ListTypes)) return; if (
!(
key === MediaTypes.Movie ||
key === MediaTypes.Show ||
key === MediaTypes.Person
)
) {
return;
}
id = Number(params.get(key)); id = Number(params.get(key));
type = key; type = MediaTypes[key];
}); });
return { id, type }; return { id, type };

View File

@@ -7,7 +7,7 @@
> >
<results-list-item <results-list-item
v-for="(result, index) in results" v-for="(result, index) in results"
:key="`${result.type}-${result.id}-${index}`" :key="generateResultKey(index, `${result.type}-${result.id}`)"
:listItem="result" :listItem="result"
/> />
</ul> </ul>
@@ -28,6 +28,10 @@
} }
const props = defineProps<Props>(); const props = defineProps<Props>();
function generateResultKey(index: string | number | symbol, value: string) {
return `${String(index)}-${value}`;
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -38,10 +38,10 @@
import { useStore } from "vuex"; import { useStore } from "vuex";
import { buildImageProxyUrl } from "../utils"; import { buildImageProxyUrl } from "../utils";
import type { Ref } from "vue"; import type { Ref } from "vue";
import type { MediaTypes } from "../interfaces/IList"; import type { IMovie, IShow, IPerson, IRequest } from "../interfaces/IList";
interface Props { interface Props {
listItem: MediaTypes; listItem: IMovie | IShow | IPerson;
} }
const props = defineProps<Props>(); const props = defineProps<Props>();

View File

@@ -52,13 +52,13 @@
import IconClose from "@/icons/IconClose.vue"; import IconClose from "@/icons/IconClose.vue";
import config from "../../config"; import config from "../../config";
import type { Ref } from "vue"; import type { Ref } from "vue";
import type { ListTypes } from "../../interfaces/IList"; import type { MediaTypes } from "../../interfaces/IList";
interface ISearchResult { interface ISearchResult {
title: string; title: string;
id: number; id: number;
adult: boolean; adult: boolean;
type: ListTypes; type: MediaTypes;
} }
const store = useStore(); const store = useStore();

View File

@@ -15,7 +15,7 @@
</figure> </figure>
<div v-if="media" class="movie__title"> <div v-if="media" class="movie__title">
<h1>{{ media.title || media.name }}</h1> <h1>{{ media.title }}</h1>
<i>{{ media.tagline }}</i> <i>{{ media.tagline }}</i>
</div> </div>
<loading-placeholder v-else :count="2" /> <loading-placeholder v-else :count="2" />
@@ -111,9 +111,13 @@
title="Release date" title="Release date"
:detail="media.year" :detail="media.year"
/> />
<Detail v-if="media.rating" title="Rating" :detail="media.rating" />
<Detail <Detail
v-if="media.type == ListTypes.Show" v-if="media.type === MediaTypes.Movie && media.rating"
title="Rating"
:detail="media.rating"
/>
<Detail
v-if="media.type == MediaTypes.Show"
title="Seasons" title="Seasons"
:detail="media.seasons" :detail="media.seasons"
/> />
@@ -184,7 +188,7 @@
IMediaCredits, IMediaCredits,
ICast ICast
} from "../../interfaces/IList"; } from "../../interfaces/IList";
import { ListTypes } from "../../interfaces/IList"; import { MediaTypes } from "../../interfaces/IList";
import { humanMinutes } from "../../utils"; import { humanMinutes } from "../../utils";
import { import {
@@ -200,7 +204,7 @@
interface Props { interface Props {
id: number; id: number;
type: ListTypes.Movie | ListTypes.Show; type: MediaTypes.Movie | MediaTypes.Show;
} }
const props = defineProps<Props>(); const props = defineProps<Props>();
@@ -243,10 +247,10 @@
let apiFunction: Function; let apiFunction: Function;
let parameters: object; let parameters: object;
if (props.type === ListTypes.Movie) { if (props.type === MediaTypes.Movie) {
apiFunction = getMovie; apiFunction = getMovie;
parameters = { checkExistance: true, credits: false }; parameters = { checkExistance: true, credits: false };
} else if (props.type === ListTypes.Show) { } else if (props.type === MediaTypes.Show) {
apiFunction = getShow; apiFunction = getShow;
parameters = { checkExistance: true, credits: false }; parameters = { checkExistance: true, credits: false };
} }
@@ -260,11 +264,11 @@
} }
function getCredits( function getCredits(
type: ListTypes.Movie | ListTypes.Show type: MediaTypes.Movie | MediaTypes.Show
): Promise<IMediaCredits> { ): Promise<IMediaCredits> {
if (type === ListTypes.Movie) { if (type === MediaTypes.Movie) {
return getMovieCredits(props.id); return getMovieCredits(props.id);
} else if (type === ListTypes.Show) { } else if (type === MediaTypes.Show) {
return getShowCredits(props.id); return getShowCredits(props.id);
} }
@@ -301,7 +305,7 @@
} }
function openTmdb() { function openTmdb() {
const tmdbType = props.type === ListTypes.Show ? "tv" : props.type; const tmdbType = props.type === MediaTypes.Show ? "tv" : props.type;
const tmdbURL = "https://www.themoviedb.org/" + tmdbType + "/" + props.id; const tmdbURL = "https://www.themoviedb.org/" + tmdbType + "/" + props.id;
window.location.href = tmdbURL; window.location.href = tmdbURL;
} }

View File

@@ -3,7 +3,7 @@
<header ref="header"> <header ref="header">
<div class="info"> <div class="info">
<h1 v-if="person"> <h1 v-if="person">
{{ person.title || person.name }} {{ person.name }}
</h1> </h1>
<div v-else> <div v-else>
<loading-placeholder :count="1" /> <loading-placeholder :count="1" />
@@ -84,7 +84,7 @@
IMovie, IMovie,
IShow IShow
} from "../../interfaces/IList"; } from "../../interfaces/IList";
import { ListTypes } from "../../interfaces/IList"; import { MediaTypes } from "../../interfaces/IList";
interface Props { interface Props {
id: number; id: number;
@@ -137,12 +137,12 @@
function personCreditedFrom(cast: Array<IMovie | IShow>): void { function personCreditedFrom(cast: Array<IMovie | IShow>): void {
creditedMovies.value = cast creditedMovies.value = cast
.filter(credit => credit.type === ListTypes.Movie) .filter(credit => credit.type === MediaTypes.Movie)
.filter(alreadyExists) .filter(alreadyExists)
.sort(sortPopularity); .sort(sortPopularity);
creditedShows.value = cast creditedShows.value = cast
.filter(credit => credit.type === ListTypes.Show) .filter(credit => credit.type === MediaTypes.Show)
.filter(alreadyExists) .filter(alreadyExists)
.sort(sortPopularity); .sort(sortPopularity);
} }

View File

@@ -34,8 +34,9 @@
import SeasonedInput from "@/components/ui/SeasonedInput.vue"; import SeasonedInput from "@/components/ui/SeasonedInput.vue";
import SeasonedButton from "@/components/ui/SeasonedButton.vue"; import SeasonedButton from "@/components/ui/SeasonedButton.vue";
import SeasonedMessages from "@/components/ui/SeasonedMessages.vue"; import SeasonedMessages from "@/components/ui/SeasonedMessages.vue";
import { ErrorMessageTypes } from "../../interfaces/IErrorMessage";
import type { Ref } from "vue"; import type { Ref } from "vue";
import type IErrorMessage from "../../interfaces/IErrorMessage"; import type { IErrorMessage } from "../../interfaces/IErrorMessage";
interface ResetPasswordPayload { interface ResetPasswordPayload {
old_password: string; old_password: string;
@@ -52,7 +53,11 @@
} }
function addWarningMessage(message: string, title?: string) { function addWarningMessage(message: string, title?: string) {
messages.value.push({ message, title, type: "warning" }); messages.value.push({
message,
title,
type: ErrorMessageTypes.Warning
} as IErrorMessage);
} }
function validate() { function validate() {

View File

@@ -49,8 +49,9 @@
import SeasonedButton from "@/components/ui/SeasonedButton.vue"; import SeasonedButton from "@/components/ui/SeasonedButton.vue";
import SeasonedMessages from "@/components/ui/SeasonedMessages.vue"; import SeasonedMessages from "@/components/ui/SeasonedMessages.vue";
import { linkPlexAccount, unlinkPlexAccount } from "../../api"; import { linkPlexAccount, unlinkPlexAccount } from "../../api";
import { ErrorMessageTypes } from "../../interfaces/IErrorMessage";
import type { Ref, ComputedRef } from "vue"; import type { Ref, ComputedRef } from "vue";
import type IErrorMessage from "../../interfaces/IErrorMessage"; import type { IErrorMessage } from "../../interfaces/IErrorMessage";
interface Emit { interface Emit {
(e: "reload"); (e: "reload");
@@ -89,10 +90,10 @@
} }
messages.value.push({ messages.value.push({
type: success ? "success" : "error", type: success ? ErrorMessageTypes.Success : ErrorMessageTypes.Error,
title: success ? "Authenticated with plex" : "Something went wrong", title: success ? "Authenticated with plex" : "Something went wrong",
message: message message: message
}); } as IErrorMessage);
} }
async function unauthenticatePlex() { async function unauthenticatePlex() {
@@ -103,12 +104,14 @@
} }
messages.value.push({ messages.value.push({
type: response.success ? "success" : "error", type: response.success
? ErrorMessageTypes.Success
: ErrorMessageTypes.Error,
title: response.success title: response.success
? "Unlinked plex account " ? "Unlinked plex account "
: "Something went wrong", : "Something went wrong",
message: response.message message: response.message
}); } as IErrorMessage);
} }
</script> </script>

View File

@@ -39,7 +39,7 @@
interface Emit { interface Emit {
(e: "change"); (e: "change");
(e: "enter"); (e: "enter", event?: KeyboardEvent);
(e: "update:modelValue", value: string); (e: "update:modelValue", value: string);
} }

View File

@@ -3,34 +3,32 @@
<div <div
class="card" class="card"
v-for="(message, index) in messages" v-for="(message, index) in messages"
:key="`${index}-${message.title}-${message.type}}`" :key="generateMessageKey(index, message)"
:class="message.type || 'warning'" :class="message.type || 'warning'"
> >
<span class="pinstripe"></span> <span class="pinstripe"></span>
<div class="content"> <div class="content">
<h2 class="title"> <h2 class="title">
{{ message.title || defaultTitles[message.type] }} {{ message.title }}
</h2> </h2>
<span v-if="message.message" class="message">{{ <span v-if="message.message" class="message">{{
message.message message.message
}}</span> }}</span>
</div> </div>
<button class="dismiss" @click="dismiss(index)">X</button> <button class="dismiss" @click="dismiss(Number(index))">X</button>
</div> </div>
</transition-group> </transition-group>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { defineProps, defineEmits } from "vue"; import { defineProps, defineEmits } from "vue";
import type {
ErrorMessageTypes,
IErrorMessage
} from "../../interfaces/IErrorMessage";
import type { Ref } from "vue"; import type { Ref } from "vue";
interface IErrorMessage {
title: string;
message: string;
type: "error" | "success" | "warning";
}
interface Props { interface Props {
messages: IErrorMessage[]; messages: IErrorMessage[];
} }
@@ -45,14 +43,25 @@
const defaultTitles = { const defaultTitles = {
error: "Unexpected error", error: "Unexpected error",
warning: "Something went wrong", warning: "Something went wrong",
success: "", success: "Success!",
undefined: "Something went wrong" undefined: "Something went wrong"
}; };
function titleFromType(type: ErrorMessageTypes) {
return defaultTitles[type];
}
function dismiss(index: number) { function dismiss(index: number) {
props.messages.splice(index, 1); props.messages.splice(index, 1);
emit("update:messages", [...props.messages]); emit("update:messages", [...props.messages]);
} }
function generateMessageKey(
index: string | number | symbol,
errorMessage: IErrorMessage
) {
return `${String(index)}-${errorMessage.title}-${errorMessage.type}`;
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -1,5 +1,12 @@
export default interface IErrorMessage { export enum ErrorMessageTypes {
Error = "error",
Success = "success",
Warning = "warning"
}
export interface IErrorMessage {
id: string;
title: string; title: string;
message: string; message: string;
type: "error" | "success" | "warning"; type: ErrorMessageTypes;
} }

View File

@@ -11,7 +11,7 @@ import type { MediaTypes } from "./IList";
// } // }
export interface IStatePopup { export interface IStatePopup {
id: number | null; id: number;
type: MediaTypes | null; type: MediaTypes;
open: boolean; open: boolean;
} }

View File

@@ -1,5 +1,5 @@
import router from "../routes"; import router from "../routes";
import { ListTypes } from "../interfaces/IList"; import { MediaTypes } from "../interfaces/IList";
import type { IStatePopup } from "../interfaces/IStatePopup"; import type { IStatePopup } from "../interfaces/IStatePopup";
const removeIncludedQueryParams = (params, key) => { const removeIncludedQueryParams = (params, key) => {
@@ -16,7 +16,7 @@ function paramsToObject(entries) {
return result; return result;
} }
const updateQueryParams = (id: number | null = null, type: string = "") => { const updateQueryParams = (id: number = null, type: MediaTypes = null) => {
let params = new URLSearchParams(window.location.search); let params = new URLSearchParams(window.location.search);
params = removeIncludedQueryParams(params, "movie"); params = removeIncludedQueryParams(params, "movie");
params = removeIncludedQueryParams(params, "show"); params = removeIncludedQueryParams(params, "show");
@@ -59,7 +59,7 @@ export default {
} }
}, },
actions: { actions: {
open: ({ commit }, { id, type = "movie" }) => { open: ({ commit }, { id, type }: { id: number; type: MediaTypes }) => {
if (!isNaN(id)) id = Number(id); if (!isNaN(id)) id = Number(id);
commit("SET_OPEN", { id, type }); commit("SET_OPEN", { id, type });
updateQueryParams(id, type); updateQueryParams(id, type);

View File

@@ -2,7 +2,7 @@
<section> <section>
<LandingBanner /> <LandingBanner />
<div v-for="list in lists" :key="list.name"> <div v-for="list in lists" :key="list.title">
<ResultsSection <ResultsSection
:apiFunction="list.apiFunction" :apiFunction="list.apiFunction"
:title="list.title" :title="list.title"

View File

@@ -46,8 +46,9 @@
import SeasonedMessages from "@/components/ui/SeasonedMessages.vue"; import SeasonedMessages from "@/components/ui/SeasonedMessages.vue";
import { register } from "../api"; import { register } from "../api";
import { focusFirstFormInput, focusOnNextElement } from "../utils"; import { focusFirstFormInput, focusOnNextElement } from "../utils";
import { ErrorMessageTypes } from "../interfaces/IErrorMessage";
import type { Ref } from "vue"; import type { Ref } from "vue";
import type IErrorMessage from "../interfaces/IErrorMessage"; import type { IErrorMessage } from "../interfaces/IErrorMessage";
const username: Ref<string> = ref(""); const username: Ref<string> = ref("");
const password: Ref<string> = ref(""); const password: Ref<string> = ref("");
@@ -65,11 +66,19 @@
} }
function addErrorMessage(message: string, title?: string) { function addErrorMessage(message: string, title?: string) {
messages.value.push({ message, title, type: "error" }); messages.value.push({
message,
title,
type: ErrorMessageTypes.Error
} as IErrorMessage);
} }
function addWarningMessage(message: string, title?: string) { function addWarningMessage(message: string, title?: string) {
messages.value.push({ message, title, type: "warning" }); messages.value.push({
message,
title,
type: ErrorMessageTypes.Warning
} as IErrorMessage);
} }
function validate(): Promise<boolean> { function validate(): Promise<boolean> {

View File

@@ -26,7 +26,7 @@
import PageHeader from "@/components/PageHeader.vue"; import PageHeader from "@/components/PageHeader.vue";
import ToggleButton from "@/components/ui/ToggleButton.vue"; import ToggleButton from "@/components/ui/ToggleButton.vue";
import type { Ref } from "vue"; import type { Ref } from "vue";
import { ListTypes } from "../interfaces/IList"; import { MediaTypes } from "../interfaces/IList";
// interface ISearchParams { // interface ISearchParams {
// query: string; // query: string;
@@ -38,11 +38,11 @@
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const toggleOptions = ["all", ...Object.values(ListTypes)]; const toggleOptions = ["all", ...Object.values(MediaTypes)];
const query: Ref<string> = ref(null); const query: Ref<string> = ref(null);
const page: Ref<number> = ref(1); const page: Ref<number> = ref(1);
const adult: Ref<boolean> = ref(false); const adult: Ref<boolean> = ref(false);
const mediaType: Ref<ListTypes> = ref(null); const mediaType: Ref<MediaTypes> = ref(null);
const title = computed(() => `Search results: ${query.value}`); const title = computed(() => `Search results: ${query.value}`);
@@ -51,7 +51,7 @@
query.value = decodeURIComponent(urlQuery?.query?.toString()); query.value = decodeURIComponent(urlQuery?.query?.toString());
page.value = Number(urlQuery?.page) || 1; page.value = Number(urlQuery?.page) || 1;
adult.value = Boolean(urlQuery?.adult) || adult.value; adult.value = Boolean(urlQuery?.adult) || adult.value;
mediaType.value = (urlQuery?.media_type as ListTypes) || mediaType.value; mediaType.value = (urlQuery?.media_type as MediaTypes) || mediaType.value;
} }
let search = ( let search = (

View File

@@ -37,8 +37,9 @@
import SeasonedMessages from "@/components/ui/SeasonedMessages.vue"; import SeasonedMessages from "@/components/ui/SeasonedMessages.vue";
import { login } from "../api"; import { login } from "../api";
import { focusFirstFormInput, focusOnNextElement } from "../utils"; import { focusFirstFormInput, focusOnNextElement } from "../utils";
import { ErrorMessageTypes } from "../interfaces/IErrorMessage";
import type { Ref } from "vue"; import type { Ref } from "vue";
import type IErrorMessage from "../interfaces/IErrorMessage"; import type { IErrorMessage } from "../interfaces/IErrorMessage";
const username: Ref<string> = ref(""); const username: Ref<string> = ref("");
const password: Ref<string> = ref(""); const password: Ref<string> = ref("");
@@ -55,11 +56,19 @@
} }
function addErrorMessage(message: string, title?: string) { function addErrorMessage(message: string, title?: string) {
messages.value.push({ message, title, type: "error" }); messages.value.push({
message,
title,
type: ErrorMessageTypes.Error
} as IErrorMessage);
} }
function addWarningMessage(message: string, title?: string) { function addWarningMessage(message: string, title?: string) {
messages.value.push({ message, title, type: "warning" }); messages.value.push({
message,
title,
type: ErrorMessageTypes.Warning
} as IErrorMessage);
} }
function validate(): Promise<boolean> { function validate(): Promise<boolean> {