diff --git a/docker/Dockerfile b/docker/Dockerfile index 5409a22..a4b1981 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -22,7 +22,7 @@ COPY webapp/frontend /scrutiny/src RUN npm install -g @angular/cli@9.1.4 && \ mkdir -p /scrutiny/dist && \ npm install && \ - ng build --output-path=/scrutiny/dist --deploy-url="/web/" --base-href="/web/" --prod + ng build --output-path=/scrutiny/dist --prod ######## diff --git a/webapp/backend/pkg/web/server.go b/webapp/backend/pkg/web/server.go index 76f8fb9..6bfd99a 100644 --- a/webapp/backend/pkg/web/server.go +++ b/webapp/backend/pkg/web/server.go @@ -13,7 +13,6 @@ import ( "net/http" "os" "path/filepath" - "strings" ) type AppEngine struct { @@ -29,37 +28,31 @@ func (ae *AppEngine) Setup(logger logrus.FieldLogger) *gin.Engine { r.Use(gin.Recovery()) basePath := ae.Config.GetString("web.src.backend.basepath") - if len(basePath) > 0 { - r.Group(basePath, func(c *gin.Context) { - c.Request.URL.Path = strings.TrimPrefix(c.Request.URL.Path, basePath) - r.HandleContext(c) - }) - } else { - basePath = "/" - } - - - api := r.Group("/api") + logger.Debugf("basepath: %s", basePath) + base := r.Group(basePath) { - api.GET("/health", func(c *gin.Context) { - c.JSON(http.StatusOK, gin.H{ - "success": true, + api := base.Group("/api") + { + api.GET("/health", func(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{ + "success": true, + }) }) - }) - api.POST("/health/notify", handler.SendTestNotification) //check if notifications are configured correctly + api.POST("/health/notify", handler.SendTestNotification) //check if notifications are configured correctly - api.POST("/devices/register", handler.RegisterDevices) //used by Collector to register new devices and retrieve filtered list - api.GET("/summary", handler.GetDevicesSummary) //used by Dashboard - api.POST("/device/:wwn/smart", handler.UploadDeviceMetrics) //used by Collector to upload data - api.POST("/device/:wwn/selftest", handler.UploadDeviceSelfTests) - api.GET("/device/:wwn/details", handler.GetDeviceDetails) //used by Details + api.POST("/devices/register", handler.RegisterDevices) //used by Collector to register new devices and retrieve filtered list + api.GET("/summary", handler.GetDevicesSummary) //used by Dashboard + api.POST("/device/:wwn/smart", handler.UploadDeviceMetrics) //used by Collector to upload data + api.POST("/device/:wwn/selftest", handler.UploadDeviceSelfTests) + api.GET("/device/:wwn/details", handler.GetDeviceDetails) //used by Details + } } //Static request routing - r.StaticFS("/web", http.Dir(ae.Config.GetString("web.src.frontend.path"))) + base.StaticFS("/web", http.Dir(ae.Config.GetString("web.src.frontend.path"))) //redirect base url to /web - r.GET("/", func(c *gin.Context) { + base.GET("/", func(c *gin.Context) { c.Redirect(http.StatusFound, basePath + "/web") }) diff --git a/webapp/frontend/src/app/app.module.ts b/webapp/frontend/src/app/app.module.ts index 9b5ee3a..904ee15 100644 --- a/webapp/frontend/src/app/app.module.ts +++ b/webapp/frontend/src/app/app.module.ts @@ -2,6 +2,7 @@ import { NgModule, enableProdMode } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { ExtraOptions, PreloadAllModules, RouterModule } from '@angular/router'; +import { APP_BASE_HREF } from '@angular/common'; import { MarkdownModule } from 'ngx-markdown'; import { TreoModule } from '@treo'; import { TreoConfigModule } from '@treo/services/config'; @@ -11,7 +12,7 @@ import { appConfig } from 'app/core/config/app.config'; import { mockDataServices } from 'app/data/mock'; import { LayoutModule } from 'app/layout/layout.module'; import { AppComponent } from 'app/app.component'; -import { appRoutes } from 'app/app.routing'; +import { appRoutes, getAppBaseHref } from 'app/app.routing'; const routerConfig: ExtraOptions = { scrollPositionRestoration: 'enabled', @@ -54,7 +55,13 @@ if (process.env.NODE_ENV === 'production') { ], bootstrap : [ AppComponent - ] + ], + providers: [ + { + provide: APP_BASE_HREF, + useValue: getAppBaseHref() + } + ], }) export class AppModule { diff --git a/webapp/frontend/src/app/app.routing.ts b/webapp/frontend/src/app/app.routing.ts index f7ad8bc..2be8dd2 100644 --- a/webapp/frontend/src/app/app.routing.ts +++ b/webapp/frontend/src/app/app.routing.ts @@ -2,6 +2,17 @@ import { Route } from '@angular/router'; import { LayoutComponent } from 'app/layout/layout.component'; import { EmptyLayoutComponent } from 'app/layout/layouts/empty/empty.component'; +// @formatter:off +export function getAppBaseHref(): string { + return getBasePath() + '/web'; +} + +// @formatter:off +// tslint:disable:max-line-length +export function getBasePath(): string { + return window.location.pathname.split('/web').slice(0, 1)[0]; +} + // @formatter:off // tslint:disable:max-line-length export const appRoutes: Route[] = [ diff --git a/webapp/frontend/src/app/layout/common/search/search.component.ts b/webapp/frontend/src/app/layout/common/search/search.component.ts index 56a824f..3c48651 100644 --- a/webapp/frontend/src/app/layout/common/search/search.component.ts +++ b/webapp/frontend/src/app/layout/common/search/search.component.ts @@ -5,6 +5,7 @@ import { MatFormField } from '@angular/material/form-field'; import { Subject } from 'rxjs'; import { debounceTime, filter, map, takeUntil } from 'rxjs/operators'; import { TreoAnimations } from '@treo/animations/public-api'; +import { getBasePath } from 'app/app.routing'; @Component({ selector : 'search', @@ -199,7 +200,7 @@ export class SearchComponent implements OnInit, OnDestroy }) ) .subscribe((value) => { - this._httpClient.post('api/common/search', {query: value}) + this._httpClient.post(getBasePath() + '/api/common/search', {query: value}) .subscribe((response: any) => { this.results = response.results; }); diff --git a/webapp/frontend/src/app/modules/dashboard/dashboard.service.ts b/webapp/frontend/src/app/modules/dashboard/dashboard.service.ts index bd81204..f73704c 100644 --- a/webapp/frontend/src/app/modules/dashboard/dashboard.service.ts +++ b/webapp/frontend/src/app/modules/dashboard/dashboard.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { BehaviorSubject, Observable } from 'rxjs'; import { tap } from 'rxjs/operators'; +import { getBasePath } from 'app/app.routing'; @Injectable({ providedIn: 'root' @@ -45,7 +46,7 @@ export class DashboardService */ getData(): Observable { - return this._httpClient.get('/api/summary').pipe( + return this._httpClient.get(getBasePath() + '/api/summary').pipe( tap((response: any) => { this._data.next(response); }) diff --git a/webapp/frontend/src/app/modules/detail/detail.service.ts b/webapp/frontend/src/app/modules/detail/detail.service.ts index 12e0a59..5747571 100644 --- a/webapp/frontend/src/app/modules/detail/detail.service.ts +++ b/webapp/frontend/src/app/modules/detail/detail.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { BehaviorSubject, Observable } from 'rxjs'; import { tap } from 'rxjs/operators'; +import { getBasePath } from 'app/app.routing'; @Injectable({ providedIn: 'root' @@ -45,7 +46,7 @@ export class DetailService */ getData(wwn): Observable { - return this._httpClient.get(`/api/device/${wwn}/details`).pipe( + return this._httpClient.get(getBasePath() + `/api/device/${wwn}/details`).pipe( tap((response: any) => { this._data.next(response); }) diff --git a/webapp/frontend/src/browserconfig.xml b/webapp/frontend/src/browserconfig.xml index c554148..ddcadc8 100644 --- a/webapp/frontend/src/browserconfig.xml +++ b/webapp/frontend/src/browserconfig.xml @@ -1,2 +1,2 @@ -#ffffff \ No newline at end of file +#ffffff diff --git a/webapp/frontend/src/index.html b/webapp/frontend/src/index.html index 1578a30..56dca49 100644 --- a/webapp/frontend/src/index.html +++ b/webapp/frontend/src/index.html @@ -3,7 +3,6 @@ scrutiny - @@ -22,7 +21,7 @@ - + diff --git a/webapp/frontend/src/manifest.json b/webapp/frontend/src/manifest.json index 013d4a6..a6ee00c 100644 --- a/webapp/frontend/src/manifest.json +++ b/webapp/frontend/src/manifest.json @@ -2,40 +2,40 @@ "name": "App", "icons": [ { - "src": "\/android-icon-36x36.png", + "src": ".\/android-icon-36x36.png", "sizes": "36x36", "type": "image\/png", "density": "0.75" }, { - "src": "\/android-icon-48x48.png", + "src": ".\/android-icon-48x48.png", "sizes": "48x48", "type": "image\/png", "density": "1.0" }, { - "src": "\/android-icon-72x72.png", + "src": ".\/android-icon-72x72.png", "sizes": "72x72", "type": "image\/png", "density": "1.5" }, { - "src": "\/android-icon-96x96.png", + "src": ".\/android-icon-96x96.png", "sizes": "96x96", "type": "image\/png", "density": "2.0" }, { - "src": "\/android-icon-144x144.png", + "src": ".\/android-icon-144x144.png", "sizes": "144x144", "type": "image\/png", "density": "3.0" }, { - "src": "\/android-icon-192x192.png", + "src": ".\/android-icon-192x192.png", "sizes": "192x192", "type": "image\/png", "density": "4.0" } ] -} \ No newline at end of file +}