mirror of
https://github.com/sasjs/server.git
synced 2025-12-11 03:34:35 +00:00
fix(appstream): app logo + improvements
This commit is contained in:
@@ -88,5 +88,10 @@
|
|||||||
},
|
},
|
||||||
"configuration": {
|
"configuration": {
|
||||||
"sasPath": "/opt/sas/sas9/SASHome/SASFoundation/9.4/sas"
|
"sasPath": "/opt/sas/sas9/SASHome/SASFoundation/9.4/sas"
|
||||||
|
},
|
||||||
|
"nodemonConfig": {
|
||||||
|
"ignore": [
|
||||||
|
"tmp/appStreamConfig.json"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -214,6 +214,8 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
message:
|
message:
|
||||||
type: string
|
type: string
|
||||||
|
streamServiceName:
|
||||||
|
type: string
|
||||||
example:
|
example:
|
||||||
$ref: '#/components/schemas/FileTree'
|
$ref: '#/components/schemas/FileTree'
|
||||||
required:
|
required:
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ interface DeployPayload {
|
|||||||
interface DeployResponse {
|
interface DeployResponse {
|
||||||
status: string
|
status: string
|
||||||
message: string
|
message: string
|
||||||
|
streamServiceName?: string
|
||||||
example?: FileTree
|
example?: FileTree
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,12 +22,15 @@ driveRouter.post('/deploy', async (req, res) => {
|
|||||||
try {
|
try {
|
||||||
const response = await controller.deploy(body)
|
const response = await controller.deploy(body)
|
||||||
|
|
||||||
if (body.streamWebFolder)
|
if (body.streamWebFolder) {
|
||||||
publishAppStream(
|
const { streamServiceName } = await publishAppStream(
|
||||||
body.appLoc,
|
body.appLoc,
|
||||||
body.streamWebFolder,
|
body.streamWebFolder,
|
||||||
body.streamServiceName
|
body.streamServiceName,
|
||||||
|
body.streamLogo
|
||||||
)
|
)
|
||||||
|
response.streamServiceName = streamServiceName
|
||||||
|
}
|
||||||
|
|
||||||
res.send(response)
|
res.send(response)
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
|
|||||||
@@ -17,13 +17,20 @@ const style = `<style>
|
|||||||
border-radius: 10px 10px 0 0;
|
border-radius: 10px 10px 0 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
.app-container .app img{
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
</style>`
|
</style>`
|
||||||
|
|
||||||
const defaultAppLogo = '/sasjs-logo.svg'
|
const defaultAppLogo = '/sasjs-logo.svg'
|
||||||
|
|
||||||
const singleAppStreamHtml = (streamServiceName: string, logo?: string) =>
|
const singleAppStreamHtml = (
|
||||||
` <a class="app" href="${streamServiceName}">
|
streamServiceName: string,
|
||||||
<img src="${logo ?? defaultAppLogo}" />
|
appLoc: string,
|
||||||
|
logo?: string
|
||||||
|
) =>
|
||||||
|
` <a class="app" href="${streamServiceName}" title="${appLoc}">
|
||||||
|
<img src="${logo ? streamServiceName + '/' + logo : defaultAppLogo}" />
|
||||||
${streamServiceName}
|
${streamServiceName}
|
||||||
</a>`
|
</a>`
|
||||||
|
|
||||||
@@ -36,12 +43,11 @@ export const appStreamHtml = (appStreamConfig: AppStreamConfig) => `
|
|||||||
<body>
|
<body>
|
||||||
<h1>App Stream</h1>
|
<h1>App Stream</h1>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
${Object.entries(appStreamConfig).map(([streamServiceName, entry]) =>
|
${Object.entries(appStreamConfig)
|
||||||
singleAppStreamHtml(streamServiceName, entry.logo)
|
.map(([streamServiceName, entry]) =>
|
||||||
)}
|
singleAppStreamHtml(streamServiceName, entry.appLoc, entry.streamLogo)
|
||||||
<a class="app" href="#"><img src="/sasjs-logo.svg" />App Name here</a>
|
)
|
||||||
<a class="app" href="#"><img src="/sasjs-logo.svg" />App Name here</a>
|
.join('')}
|
||||||
<a class="app" href="#"><img src="/sasjs-logo.svg" />App Name here</a>
|
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>`
|
</html>`
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export const publishAppStream = async (
|
|||||||
appLoc: string,
|
appLoc: string,
|
||||||
streamWebFolder: string,
|
streamWebFolder: string,
|
||||||
streamServiceName?: string,
|
streamServiceName?: string,
|
||||||
|
streamLogo?: string,
|
||||||
addEntryToFile: boolean = true
|
addEntryToFile: boolean = true
|
||||||
) => {
|
) => {
|
||||||
const driveFilesPath = getTmpFilesFolderPath()
|
const driveFilesPath = getTmpFilesFolderPath()
|
||||||
@@ -37,8 +38,19 @@ export const publishAppStream = async (
|
|||||||
? Object.keys(process.appStreamConfig).length
|
? Object.keys(process.appStreamConfig).length
|
||||||
: 0
|
: 0
|
||||||
|
|
||||||
if (!streamServiceName || process.appStreamConfig[streamServiceName]) {
|
if (!streamServiceName) {
|
||||||
streamServiceName = `AppStreamName${appCount + 1}`
|
streamServiceName = `AppStreamName${appCount + 1}`
|
||||||
|
} else {
|
||||||
|
const alreadyDeployed = process.appStreamConfig[streamServiceName]
|
||||||
|
if (alreadyDeployed) {
|
||||||
|
if (alreadyDeployed.appLoc === appLoc) {
|
||||||
|
// redeploying to same streamServiceName
|
||||||
|
} else {
|
||||||
|
// trying to deploy to another existing streamServiceName
|
||||||
|
// assign new streamServiceName
|
||||||
|
streamServiceName = `${streamServiceName}-${appCount + 1}`
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
router.use(`/${streamServiceName}`, express.static(pathToDeployment))
|
router.use(`/${streamServiceName}`, express.static(pathToDeployment))
|
||||||
@@ -47,7 +59,7 @@ export const publishAppStream = async (
|
|||||||
streamServiceName,
|
streamServiceName,
|
||||||
appLoc,
|
appLoc,
|
||||||
streamWebFolder,
|
streamWebFolder,
|
||||||
undefined,
|
streamLogo,
|
||||||
addEntryToFile
|
addEntryToFile
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -56,7 +68,9 @@ export const publishAppStream = async (
|
|||||||
'Serving Stream App: ',
|
'Serving Stream App: ',
|
||||||
`http://localhost:${sasJsPort}/AppStream/${streamServiceName}`
|
`http://localhost:${sasJsPort}/AppStream/${streamServiceName}`
|
||||||
)
|
)
|
||||||
|
return { streamServiceName }
|
||||||
}
|
}
|
||||||
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default router
|
export default router
|
||||||
|
|||||||
@@ -2,6 +2,6 @@ export interface AppStreamConfig {
|
|||||||
[key: string]: {
|
[key: string]: {
|
||||||
appLoc: string
|
appLoc: string
|
||||||
streamWebFolder: string
|
streamWebFolder: string
|
||||||
logo?: string
|
streamLogo?: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,9 +22,15 @@ export const loadAppStreamConfig = async () => {
|
|||||||
process.appStreamConfig = {}
|
process.appStreamConfig = {}
|
||||||
|
|
||||||
for (const [streamServiceName, entry] of Object.entries(appStreamConfig)) {
|
for (const [streamServiceName, entry] of Object.entries(appStreamConfig)) {
|
||||||
const { appLoc, streamWebFolder } = entry
|
const { appLoc, streamWebFolder, streamLogo } = entry
|
||||||
|
|
||||||
publishAppStream(appLoc, streamWebFolder, streamServiceName, false)
|
publishAppStream(
|
||||||
|
appLoc,
|
||||||
|
streamWebFolder,
|
||||||
|
streamServiceName,
|
||||||
|
streamLogo,
|
||||||
|
false
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('App Stream Config loaded!')
|
console.log('App Stream Config loaded!')
|
||||||
@@ -34,14 +40,14 @@ export const addEntryToAppStreamConfig = (
|
|||||||
streamServiceName: string,
|
streamServiceName: string,
|
||||||
appLoc: string,
|
appLoc: string,
|
||||||
streamWebFolder: string,
|
streamWebFolder: string,
|
||||||
logo?: string,
|
streamLogo?: string,
|
||||||
addEntryToFile: boolean = true
|
addEntryToFile: boolean = true
|
||||||
) => {
|
) => {
|
||||||
if (streamServiceName && appLoc && streamWebFolder) {
|
if (streamServiceName && appLoc && streamWebFolder) {
|
||||||
process.appStreamConfig[streamServiceName] = {
|
process.appStreamConfig[streamServiceName] = {
|
||||||
appLoc,
|
appLoc,
|
||||||
streamWebFolder,
|
streamWebFolder,
|
||||||
logo
|
streamLogo
|
||||||
}
|
}
|
||||||
if (addEntryToFile) saveAppStreamConfig()
|
if (addEntryToFile) saveAppStreamConfig()
|
||||||
}
|
}
|
||||||
@@ -68,7 +74,7 @@ const saveAppStreamConfig = async () => {
|
|||||||
const isValidAppStreamConfig = (config: any) => {
|
const isValidAppStreamConfig = (config: any) => {
|
||||||
if (config) {
|
if (config) {
|
||||||
return !Object.entries(config).some(([streamServiceName, entry]) => {
|
return !Object.entries(config).some(([streamServiceName, entry]) => {
|
||||||
const { appLoc, streamWebFolder, logo } = entry as any
|
const { appLoc, streamWebFolder, streamLogo } = entry as any
|
||||||
|
|
||||||
return (
|
return (
|
||||||
typeof streamServiceName !== 'string' ||
|
typeof streamServiceName !== 'string' ||
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ export const deployValidation = (data: any): Joi.ValidationResult =>
|
|||||||
appLoc: Joi.string().pattern(/^\//).required().min(2),
|
appLoc: Joi.string().pattern(/^\//).required().min(2),
|
||||||
streamServiceName: Joi.string(),
|
streamServiceName: Joi.string(),
|
||||||
streamWebFolder: Joi.string(),
|
streamWebFolder: Joi.string(),
|
||||||
|
streamLogo: Joi.string(),
|
||||||
fileTree: Joi.any().required()
|
fileTree: Joi.any().required()
|
||||||
}).validate(data)
|
}).validate(data)
|
||||||
|
|
||||||
|
|||||||
@@ -66,11 +66,21 @@ const Header = (props: any) => {
|
|||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
size="large"
|
size="large"
|
||||||
startIcon={<OpenInNewIcon />}
|
endIcon={<OpenInNewIcon />}
|
||||||
style={{ marginLeft: '50px' }}
|
|
||||||
>
|
>
|
||||||
API Docs
|
API Docs
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
href={`${baseUrl}/AppStream`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
size="large"
|
||||||
|
endIcon={<OpenInNewIcon />}
|
||||||
|
>
|
||||||
|
App Stream
|
||||||
|
</Button>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
</AppBar>
|
</AppBar>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user