split frontend routing config from backend config.

Added method to use embedded frontend routing.
rename desktop config to desktop_sandbox config.

adding desktop_mode (used for Wails Desktop app + hash based routing)
make sure all `window.location` parsing works correctly with desktop_mode
This commit is contained in:
Jason Kulatunga 2023-08-28 16:23:29 -07:00
parent 0984f9edde
commit a9cb793c8a
11 changed files with 64 additions and 20 deletions

View File

@ -63,7 +63,7 @@ build-frontend-prod: dep-frontend
.PHONY: build-frontend-desktop
build-frontend-desktop: dep-frontend
cd frontend && yarn build -- -c desktop
cd frontend && yarn build -- -c desktop_sandbox
.PHONY: test-frontend

View File

@ -1,6 +1,7 @@
package web
import (
"embed"
"fmt"
"github.com/fastenhealth/fasten-onprem/backend/pkg/config"
"github.com/fastenhealth/fasten-onprem/backend/pkg/web/handler"
@ -16,16 +17,16 @@ type AppEngine struct {
Logger *logrus.Entry
}
func (ae *AppEngine) Setup(logger *logrus.Entry) *gin.Engine {
func (ae *AppEngine) Setup() (*gin.RouterGroup, *gin.Engine) {
r := gin.New()
r.Use(middleware.LoggerMiddleware(logger))
r.Use(middleware.RepositoryMiddleware(ae.Config, logger))
r.Use(middleware.LoggerMiddleware(ae.Logger))
r.Use(middleware.RepositoryMiddleware(ae.Config, ae.Logger))
r.Use(middleware.ConfigMiddleware(ae.Config))
r.Use(gin.Recovery())
basePath := ae.Config.GetString("web.listen.basepath")
logger.Debugf("basepath: %s", basePath)
ae.Logger.Debugf("basepath: %s", basePath)
base := r.Group(basePath)
{
@ -95,24 +96,50 @@ func (ae *AppEngine) Setup(logger *logrus.Entry) *gin.Engine {
}
}
return base, r
}
func (ae *AppEngine) SetupFrontendRouting(base *gin.RouterGroup, router *gin.Engine) *gin.Engine {
//Static request routing
base.StaticFS("/web", http.Dir(ae.Config.GetString("web.src.frontend.path")))
//redirect base url to /web
base.GET("/", func(c *gin.Context) {
c.Redirect(http.StatusFound, basePath+"/web")
c.Redirect(http.StatusFound, ae.Config.GetString("web.listen.basepath")+"/web")
})
//catch-all, serve index page.
r.NoRoute(func(c *gin.Context) {
router.NoRoute(func(c *gin.Context) {
path := c.Request.URL.Path
if strings.HasPrefix(path, "/api") || strings.HasPrefix(path, "/api") {
if strings.HasPrefix(path, "/api") {
c.JSON(http.StatusNotFound, gin.H{"success": false, "error": "404 endpoint not found"})
} else {
c.File(fmt.Sprintf("%s/index.html", ae.Config.GetString("web.src.frontend.path")))
}
})
return r
return router
}
func (ae *AppEngine) SetupEmbeddedFrontendRouting(embeddedAssetsFS embed.FS, base *gin.RouterGroup, router *gin.Engine) *gin.Engine {
//Static request routing
base.StaticFS("/web", http.FS(embeddedAssetsFS))
//redirect base url to /web
base.GET("/", func(c *gin.Context) {
c.Redirect(http.StatusFound, ae.Config.GetString("web.listen.basepath")+"/web")
})
//catch-all, serve index page.
router.NoRoute(func(c *gin.Context) {
path := c.Request.URL.Path
if strings.HasPrefix(path, "/api") {
c.JSON(http.StatusNotFound, gin.H{"success": false, "error": "404 endpoint not found"})
} else {
ae.Logger.Infof("could not find %s, fallback to index.html", path)
c.FileFromFS("index.html", http.FS(embeddedAssetsFS))
}
})
return router
}
func (ae *AppEngine) Start() error {
@ -122,7 +149,8 @@ func (ae *AppEngine) Start() error {
gin.SetMode(gin.DebugMode)
}
r := ae.Setup(ae.Logger)
baseRouterGroup, ginRouter := ae.Setup()
r := ae.SetupFrontendRouting(baseRouterGroup, ginRouter)
return r.Run(fmt.Sprintf("%s:%s", ae.Config.GetString("web.listen.host"), ae.Config.GetString("web.listen.port")))
}

View File

@ -127,11 +127,11 @@
}
]
},
"desktop": {
"desktop_sandbox": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.desktop.ts"
"with": "src/environments/environment.desktop_sandbox.ts"
}
],
"optimization": true,
@ -171,8 +171,8 @@
"cloud_sandbox": {
"browserTarget": "fastenhealth:build:cloud_sandbox"
},
"desktop": {
"browserTarget": "fastenhealth:build:desktop"
"desktop_sandbox": {
"browserTarget": "fastenhealth:build:desktop_sandbox"
}
}
},

View File

@ -14,6 +14,7 @@ import {MedicalHistoryComponent} from './pages/medical-history/medical-history.c
import {ReportLabsComponent} from './pages/report-labs/report-labs.component';
import {ResourceCreatorComponent} from './pages/resource-creator/resource-creator.component';
import {ExploreComponent} from './pages/explore/explore.component';
import {environment} from '../environments/environment';
const routes: Routes = [
@ -50,7 +51,7 @@ const routes: Routes = [
@NgModule({
imports: [
RouterModule.forRoot(routes),
RouterModule.forRoot(routes, {useHash: environment.environment_desktop}),
CommonModule,
BrowserModule,
],

View File

@ -79,7 +79,8 @@ export class MedicalSourcesConnectedComponent implements OnInit {
//get required parameters from the URI and local storage
const callbackUrlParts = new URL(window.location.href)
const fragmentParams = new URLSearchParams(callbackUrlParts.hash.substring(1))
//in desktop mode, we're using fragment routing, and the callback params are in the fragment.
const fragmentParams = new URLSearchParams(callbackUrlParts.hash.split('?')?.[1] || '')
const callbackCode = callbackUrlParts.searchParams.get("code") || fragmentParams.get("code")
const callbackState = callbackUrlParts.searchParams.get("state") || fragmentParams.get("state")
const callbackError = callbackUrlParts.searchParams.get("error") || fragmentParams.get("error")

View File

@ -145,14 +145,21 @@ export class LighthouseService {
*/
redirectWithOriginAndDestination(destUrl: string, sourceType: string, callbackUri: string): void {
const originUrlParts = new URL(window.location.href)
originUrlParts.hash = "" //reset hash in-case its present.
originUrlParts.pathname = this.pathJoin([originUrlParts.pathname, `callback/${sourceType}`])
if(environment.environment_desktop){
//hash based routing
originUrlParts.hash = this.pathJoin([originUrlParts.hash, `callback/${sourceType}`])
} else {
//path based routing
originUrlParts.hash = "" //reset hash in-case its present.
originUrlParts.pathname = this.pathJoin([originUrlParts.pathname, `callback/${sourceType}`])
}
const redirectUrlParts = new URL(callbackUri.replace("/callback/", "/redirect/"));
const redirectParams = new URLSearchParams()
redirectParams.set("origin_url", originUrlParts.toString())
redirectParams.set("dest_url", destUrl)
redirectParams.set("desktop_mode", environment.environment_desktop ? "true" : "false")
redirectUrlParts.search = redirectParams.toString()
console.log(redirectUrlParts.toString());

View File

@ -1,6 +1,7 @@
export const environment = {
production: true,
environment_cloud: true,
environment_desktop: false,
environment_name: "sandbox",
lighthouse_api_endpoint_base: 'https://lighthouse.fastenhealth.com/sandbox',

View File

@ -1,9 +1,10 @@
export const environment = {
production: true,
environment_cloud: false,
environment_name: "desktop",
environment_desktop: true,
environment_name: "desktop_sandbox",
lighthouse_api_endpoint_base: 'https://lighthouse.fastenhealth.com/v1',
lighthouse_api_endpoint_base: 'https://lighthouse.fastenhealth.com/sandbox',
//used to specify the api server that we're going to use (can be relative or absolute). Must not have trailing slash

View File

@ -1,6 +1,7 @@
export const environment = {
production: true,
environment_cloud: false,
environment_desktop: false,
environment_name: "prod",
lighthouse_api_endpoint_base: 'https://lighthouse.fastenhealth.com/v1',

View File

@ -5,6 +5,7 @@
export const environment = {
production: true,
environment_cloud: false,
environment_desktop: false,
environment_name: "sandbox",
lighthouse_api_endpoint_base: 'https://lighthouse.fastenhealth.com/sandbox',

View File

@ -9,6 +9,9 @@ export const environment = {
// is the application running in the cloud? (enables 3rd party IdP's and token based couchdb authentication)
environment_cloud: false,
// is the application running in a desktop environment (Wails). If so we will use hash based routing
environment_desktop: false,
// the environment name, `sandbox`, `prod`, `beta`
environment_name: "sandbox",