Browse Source

axios test (#705)

* add version controller

* use axios to get version

* allow typescript

* use version api service
pull/707/head
Jason Dove 4 years ago committed by GitHub
parent
commit
d88c179b63
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 20
      ErsatzTV/Controllers/Api/VersionController.cs
  2. 13
      ErsatzTV/Startup.cs
  3. 1244
      ErsatzTV/client-app/package-lock.json
  4. 14
      ErsatzTV/client-app/package.json
  5. 3
      ErsatzTV/client-app/src/components/Navigation/SideBarVersion.vue
  6. 0
      ErsatzTV/client-app/src/main.ts
  7. 2
      ErsatzTV/client-app/src/plugins/vuetify.ts
  8. 71
      ErsatzTV/client-app/src/services/AbstractApiService.ts
  9. 16
      ErsatzTV/client-app/src/services/VersionService.ts
  10. 11
      ErsatzTV/client-app/src/shims-tsx.d.ts
  11. 4
      ErsatzTV/client-app/src/shims-vue.d.ts
  12. 6
      ErsatzTV/client-app/src/stores/applicationState.js
  13. 42
      ErsatzTV/client-app/tsconfig.json

20
ErsatzTV/Controllers/Api/VersionController.cs

@ -0,0 +1,20 @@
using System.Reflection;
using Microsoft.AspNetCore.Mvc;
namespace ErsatzTV.Controllers.Api;
[ApiController]
public class VersionController
{
private static readonly string Version;
static VersionController()
{
Version = Assembly.GetEntryAssembly()?
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?
.InformationalVersion ?? "unknown";
}
[HttpGet("/api/version")]
public string GetVersion() => Version;
}

13
ErsatzTV/Startup.cs

@ -68,10 +68,16 @@ namespace ErsatzTV;
public class Startup public class Startup
{ {
public Startup(IConfiguration configuration) => Configuration = configuration; public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
Configuration = configuration;
CurrentEnvironment = env;
}
public IConfiguration Configuration { get; } public IConfiguration Configuration { get; }
private IWebHostEnvironment CurrentEnvironment { get; }
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
BugsnagConfiguration bugsnagConfig = Configuration.GetSection("Bugsnag").Get<BugsnagConfiguration>(); BugsnagConfiguration bugsnagConfig = Configuration.GetSection("Bugsnag").Get<BugsnagConfiguration>();
@ -131,7 +137,10 @@ public class Startup
options.ImplicitlyValidateChildProperties = true; options.ImplicitlyValidateChildProperties = true;
}); });
services.AddSpaStaticFiles(options => options.RootPath = "wwwroot/v2"); if (!CurrentEnvironment.IsDevelopment())
{
services.AddSpaStaticFiles(options => options.RootPath = "wwwroot/v2");
}
services.AddMemoryCache(); services.AddMemoryCache();

1244
ErsatzTV/client-app/package-lock.json generated

File diff suppressed because it is too large Load Diff

14
ErsatzTV/client-app/package.json

@ -9,6 +9,7 @@
}, },
"dependencies": { "dependencies": {
"@mdi/font": "5.9.55", "@mdi/font": "5.9.55",
"axios": "^0.26.1",
"core-js": "^3.8.3", "core-js": "^3.8.3",
"pinia": "^2.0.11", "pinia": "^2.0.11",
"roboto-fontface": "*", "roboto-fontface": "*",
@ -19,16 +20,21 @@
"devDependencies": { "devDependencies": {
"@babel/core": "^7.12.16", "@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16", "@babel/eslint-parser": "^7.12.16",
"@typescript-eslint/eslint-plugin": "^5.4.0",
"@typescript-eslint/parser": "^5.4.0",
"@vue/cli-plugin-babel": "~5.0.0", "@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0", "@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-plugin-typescript": "~5.0.0",
"@vue/cli-service": "~5.0.0", "@vue/cli-service": "~5.0.0",
"@vue/composition-api": "^1.4.9", "@vue/composition-api": "^1.4.9",
"@vue/eslint-config-typescript": "^9.1.0",
"eslint": "^7.32.0", "eslint": "^7.32.0",
"eslint-config-prettier": "^8.5.0", "eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^8.0.3", "eslint-plugin-vue": "^8.0.3",
"sass": "~1.32.0", "sass": "~1.32.0",
"sass-loader": "^10.0.0", "sass-loader": "^10.0.0",
"typescript": "~4.5.5",
"vue-cli-plugin-vuetify": "~2.4.7", "vue-cli-plugin-vuetify": "~2.4.7",
"vue-template-compiler": "^2.6.14", "vue-template-compiler": "^2.6.14",
"vuetify-loader": "^1.7.0" "vuetify-loader": "^1.7.0"
@ -41,14 +47,16 @@
"extends": [ "extends": [
"plugin:vue/essential", "plugin:vue/essential",
"plugin:prettier/recommended", "plugin:prettier/recommended",
"eslint:recommended" "eslint:recommended",
"@vue/typescript"
], ],
"parserOptions": { "parserOptions": {
"parser": "@babel/eslint-parser" "parser": "@typescript-eslint/parser"
}, },
"rules": { "rules": {
"prettier/prettier": [ "prettier/prettier": [
"error", { "error",
{
"endOfLine": "auto", "endOfLine": "auto",
"tabWidth": 4 "tabWidth": 4
} }

3
ErsatzTV/client-app/src/components/Navigation/SideBarVersion.vue

@ -13,6 +13,9 @@ import { applicationState } from '@/stores/applicationState';
export default { export default {
name: 'SideBarVersion', name: 'SideBarVersion',
setup() {
applicationState().getVersion();
},
computed: { computed: {
...mapState(applicationState, [ ...mapState(applicationState, [
'currentServerVersion', 'currentServerVersion',

0
ErsatzTV/client-app/src/main.js → ErsatzTV/client-app/src/main.ts

2
ErsatzTV/client-app/src/plugins/vuetify.js → ErsatzTV/client-app/src/plugins/vuetify.ts

@ -1,5 +1,5 @@
import Vue from 'vue'; import Vue from 'vue';
import Vuetify from 'vuetify/lib/framework'; import Vuetify from 'vuetify';
import colors from 'vuetify/lib/util/colors'; import colors from 'vuetify/lib/util/colors';
Vue.use(Vuetify); Vue.use(Vuetify);

71
ErsatzTV/client-app/src/services/AbstractApiService.ts

@ -0,0 +1,71 @@
import type { AxiosError, AxiosInstance, AxiosResponse } from 'axios';
import axios from 'axios';
export function isAxiosError(value: any): value is AxiosError {
return typeof value?.response === 'object';
}
export abstract class AbstractApiService {
protected readonly http: AxiosInstance;
protected constructor(
protected readonly path?: string,
protected readonly baseURL: string = '/'
) {
if (path) {
this.baseURL += path;
}
this.http = axios.create({
baseURL
// ... further stuff, e.g. `withCredentials: true`
});
this.http.defaults.headers.common['Accept'] =
'application/json;charset=UTF-8';
this.http.defaults.headers.common['Content-Type'] =
'application/json;charset=UTF-8';
}
protected createParams(record: Record<string, any>): URLSearchParams {
const params: URLSearchParams = new URLSearchParams();
for (const key in record) {
if (Object.prototype.hasOwnProperty.call(record, key)) {
const value: any = record[key];
if (value !== null && value !== undefined) {
params.append(key, value);
} else {
console.debug(
`Param key '${key}' was null or undefined and will be ignored`
);
}
}
}
return params;
}
protected handleResponse<T>(response: AxiosResponse<T>): T {
return response.data;
}
protected handleError(error: unknown): never {
if (error instanceof Error) {
if (isAxiosError(error)) {
if (error.response) {
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
throw error;
} else if (error.request) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser
console.log(error.request);
throw new Error(error as any);
}
} else {
// Something happened in setting up the request that triggered an Error
console.log('Error', error.message);
throw new Error(error.message);
}
}
throw new Error(error as any);
}
}

16
ErsatzTV/client-app/src/services/VersionService.ts

@ -0,0 +1,16 @@
import { AbstractApiService } from './AbstractApiService';
class VersionApiService extends AbstractApiService {
public constructor() {
super('/api/version');
}
public version(): Promise<string> {
return this.http
.get('')
.then(this.handleResponse)
.catch(this.handleError.bind(this));
}
}
export const versionApiService: VersionApiService = new VersionApiService();

11
ErsatzTV/client-app/src/shims-tsx.d.ts vendored

@ -0,0 +1,11 @@
import Vue, { VNode } from 'vue';
declare global {
namespace JSX {
interface Element extends VNode {}
interface ElementClass extends Vue {}
interface IntrinsicElements {
[elem: string]: any;
}
}
}

4
ErsatzTV/client-app/src/shims-vue.d.ts vendored

@ -0,0 +1,4 @@
declare module '*.vue' {
import Vue from 'vue';
export default Vue;
}

6
ErsatzTV/client-app/src/stores/applicationState.js

@ -1,4 +1,5 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { versionApiService } from '@/services/VersionService';
const originURL = `${window.location.origin}`; const originURL = `${window.location.origin}`;
@ -6,7 +7,7 @@ export const applicationState = defineStore('appState', {
state: () => { state: () => {
return { return {
miniMenu: false, miniMenu: false,
currentVersion: '0.4.3-7cd2f9a-docker-nvidia', // Needs to be pulled from API with an action when ready currentVersion: 'unknown',
m3uURL: originURL + '/iptv/channels.m3u', // this will need to be fixed for reverse proxies m3uURL: originURL + '/iptv/channels.m3u', // this will need to be fixed for reverse proxies
xmlURL: originURL + '/iptv/xmltv.xml', // this will need to be fixed for reverse proxies xmlURL: originURL + '/iptv/xmltv.xml', // this will need to be fixed for reverse proxies
documentationURL: 'https://ersatztv.org/', documentationURL: 'https://ersatztv.org/',
@ -37,6 +38,9 @@ export const applicationState = defineStore('appState', {
}, },
disableMiniNavigation() { disableMiniNavigation() {
this.miniMenu = false; this.miniMenu = false;
},
async getVersion() {
this.currentVersion = await versionApiService.version();
} }
} }
}); });

42
ErsatzTV/client-app/tsconfig.json

@ -0,0 +1,42 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"allowJs": true,
"jsx": "preserve",
"moduleResolution": "node",
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"useDefineForClassFields": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env",
"vuetify"
],
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
}
Loading…
Cancel
Save