This is the codeAbility Sharing Platform! Learn more about the
codeAbility Sharing Platform
.
Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
development
sharing
sharing plugin Demo
Commits
4c4b0dbe
Commit
4c4b0dbe
authored
Mar 20, 2021
by
Michael Breu
💬
Browse files
Intermediate commit (first complete version)
parent
3c84784b
Changes
15
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
441 additions
and
28700 deletions
+441
-28700
package-lock.json
package-lock.json
+71
-28685
pom.xml
pom.xml
+24
-1
proxy.conf.json
proxy.conf.json
+1
-1
src/main/java/org/codeability/sharing/demo/config/SecurityConfiguration.java
...odeability/sharing/demo/config/SecurityConfiguration.java
+5
-0
src/main/java/org/codeability/sharing/demo/service/SharingDemoService.java
.../codeability/sharing/demo/service/SharingDemoService.java
+114
-0
src/main/java/org/codeability/sharing/demo/service/SharingPluginService.java
...odeability/sharing/demo/service/SharingPluginService.java
+3
-3
src/main/java/org/codeability/sharing/demo/web/rest/SharingDemoResource.java
...odeability/sharing/demo/web/rest/SharingDemoResource.java
+122
-0
src/main/java/org/codeability/sharing/demo/web/rest/dto/SharingInfoDTO.java
...codeability/sharing/demo/web/rest/dto/SharingInfoDTO.java
+32
-0
src/main/resources/config/application-dev.yml
src/main/resources/config/application-dev.yml
+2
-2
src/main/resources/config/application.yml
src/main/resources/config/application.yml
+1
-1
src/main/webapp/app/sharing/service/sharing-demo.service.ts
src/main/webapp/app/sharing/service/sharing-demo.service.ts
+31
-0
src/main/webapp/app/sharing/sharing.component.html
src/main/webapp/app/sharing/sharing.component.html
+14
-2
src/main/webapp/app/sharing/sharing.component.ts
src/main/webapp/app/sharing/sharing.component.ts
+16
-3
src/main/webapp/app/sharing/sharing.module.ts
src/main/webapp/app/sharing/sharing.module.ts
+4
-1
src/test/resources/config/application.yml
src/test/resources/config/application.yml
+1
-1
No files found.
package-lock.json
View file @
4c4b0dbe
This diff is collapsed.
Click to expand it.
pom.xml
View file @
4c4b0dbe
...
...
@@ -113,7 +113,30 @@
<artifactId>
SharingPluginPlatformAPI
</artifactId>
<version>
0.0.1
</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.core/jersey-client -->
<dependency>
<groupId>
org.glassfish.jersey.core
</groupId>
<artifactId>
jersey-client
</artifactId>
<version>
2.29.1
</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>
commons-io
</groupId>
<artifactId>
commons-io
</artifactId>
<version>
2.6
</version>
</dependency>
<dependency>
<groupId>
org.glassfish.jersey.inject
</groupId>
<artifactId>
jersey-hk2
</artifactId>
<version>
2.33
</version>
</dependency>
<dependency>
<groupId>
org.glassfish.jersey.media
</groupId>
<artifactId>
jersey-media-json-jackson
</artifactId>
<version>
2.29.1
</version>
</dependency>
<dependency>
<groupId>
io.github.jhipster
</groupId>
<artifactId>
jhipster-framework
</artifactId>
...
...
proxy.conf.json
View file @
4c4b0dbe
{
"*"
:
{
"target"
:
"http://localhost:808
0
"
,
"target"
:
"http://localhost:808
2
"
,
"secure"
:
false
,
"loglevel"
:
"debug"
}
...
...
src/main/java/org/codeability/sharing/demo/config/SecurityConfiguration.java
View file @
4c4b0dbe
...
...
@@ -46,6 +46,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
public
SecurityConfiguration
(
CorsFilter
corsFilter
,
JHipsterProperties
jHipsterProperties
,
SecurityProblemSupport
problemSupport
)
{
this
.
corsFilter
=
corsFilter
;
this
.
problemSupport
=
problemSupport
;
this
.
jHipsterProperties
=
jHipsterProperties
;
}
...
...
@@ -67,6 +68,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
// @formatter:off
http
.
csrf
()
.
ignoringAntMatchers
(
"/api/sharingImport/**"
)
.
csrfTokenRepository
(
CookieCsrfTokenRepository
.
withHttpOnlyFalse
())
.
and
()
.
addFilterBefore
(
corsFilter
,
CsrfFilter
.
class
)
...
...
@@ -87,6 +89,9 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
.
authorizeRequests
()
.
antMatchers
(
"/api/auth-info"
).
permitAll
()
.
antMatchers
(
"/api/sharingPluginConfig"
).
permitAll
()
.
antMatchers
(
"/api/sharingImport/**"
).
permitAll
()
.
antMatchers
(
"/api/sharingImport/basket"
).
permitAll
()
.
antMatchers
(
"/api/**"
).
authenticated
()
.
antMatchers
(
"/management/health"
).
permitAll
()
.
antMatchers
(
"/management/info"
).
permitAll
()
...
...
src/main/java/org/codeability/sharing/demo/service/SharingDemoService.java
0 → 100644
View file @
4c4b0dbe
package
org.codeability.sharing.demo.service
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.FileNotFoundException
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.util.Optional
;
import
java.util.concurrent.TimeUnit
;
import
javax.ws.rs.client.Client
;
import
javax.ws.rs.client.ClientBuilder
;
import
javax.ws.rs.client.WebTarget
;
import
javax.ws.rs.core.MediaType
;
import
org.apache.commons.io.FileUtils
;
import
org.codeability.sharing.demo.web.rest.dto.SharingInfoDTO
;
import
org.codeability.sharing.plugins.api.ShoppingBasket
;
import
org.glassfish.jersey.client.ClientConfig
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.data.util.Pair
;
import
org.springframework.stereotype.Service
;
import
com.google.common.cache.CacheBuilder
;
import
com.google.common.cache.CacheLoader
;
import
com.google.common.cache.LoadingCache
;
@Service
public
class
SharingDemoService
{
public
SharingDemoService
()
{
}
private
final
Logger
log
=
LoggerFactory
.
getLogger
(
SharingDemoService
.
class
);
public
Optional
<
ShoppingBasket
>
getBasketInfo
(
SharingInfoDTO
sharingInfo
)
{
ClientConfig
restClientConfig
=
new
ClientConfig
();
restClientConfig
.
register
(
ShoppingBasket
.
class
);
Client
client
=
ClientBuilder
.
newClient
(
restClientConfig
);
WebTarget
target
=
client
.
target
(
sharingInfo
.
getApiBaseURL
()+
"/basket/"
+
sharingInfo
.
getBasketToken
());
// TODO make error proof
ShoppingBasket
shoppingBasket
=
target
.
request
().
accept
(
MediaType
.
APPLICATION_JSON
).
get
(
ShoppingBasket
.
class
);
if
(
shoppingBasket
!=
null
)
{
for
(
ShoppingBasket
.
ExerciseInfo
ex:
shoppingBasket
.
exerciseInfo
)
{
convertKeyWordsToArtemisJSON
(
ex
);
}
}
return
Optional
.
of
(
shoppingBasket
);
}
// TODO this is the wrong place, should be done in GUI.
private
void
convertKeyWordsToArtemisJSON
(
ShoppingBasket
.
ExerciseInfo
ex
)
{
// TODO escape keyword for JSON
for
(
int
i
=
0
;
i
<
ex
.
keywords
.
size
();
i
++)
{
ex
.
keywords
.
set
(
i
,
"{ \"category\": \""
+
ex
.
keywords
.
get
(
i
)
+
"\", \"color\":\"#691b0b\"}"
);
}
}
LoadingCache
<
Pair
<
String
,
Integer
>,
File
>
repositoryCache
=
CacheBuilder
.
newBuilder
()
.
maximumSize
(
10000
)
.
expireAfterWrite
(
4
,
TimeUnit
.
HOURS
)
.
build
(
new
CacheLoader
<
Pair
<
String
,
Integer
>,
File
>()
{
public
File
load
(
Pair
<
String
,
Integer
>
key
)
{
return
null
;
}
});
public
Optional
<
InputStream
>
getBasketItemStream
(
SharingInfoDTO
sharingInfo
,
int
itemPosition
)
{
ClientConfig
restClientConfig
=
new
ClientConfig
();
restClientConfig
.
register
(
ShoppingBasket
.
class
);
Client
client
=
ClientBuilder
.
newClient
(
restClientConfig
);
WebTarget
target
=
client
.
target
(
sharingInfo
.
getApiBaseURL
()+
"/basket/"
+
sharingInfo
.
getBasketToken
()
+
"/repository/"
+
itemPosition
);
// TODO make error proof
InputStream
zipInput
=
target
.
request
().
accept
(
MediaType
.
APPLICATION_OCTET_STREAM
).
get
(
InputStream
.
class
);
return
Optional
.
of
(
zipInput
);
}
public
InputStream
getCachedBasketItemStream
(
SharingInfoDTO
sharingInfo
,
int
itemPosition
)
throws
IOException
{
File
f
=
null
;
f
=
repositoryCache
.
getIfPresent
(
Pair
.
of
(
sharingInfo
.
getBasketToken
(),
itemPosition
));
if
(
f
!=
null
)
{
try
{
return
new
FileInputStream
(
f
);
}
catch
(
FileNotFoundException
e
)
{
log
.
warn
(
"Cannot find cached file for {}:{} at {}"
,
sharingInfo
.
getBasketToken
(),
itemPosition
,
f
.
getAbsoluteFile
(),
e
);
}
}
f
=
File
.
createTempFile
(
"baskedCache"
+
sharingInfo
.
getBasketToken
()
+
"-"
+
itemPosition
,
"zip"
);
Optional
<
InputStream
>
isO
=
getBasketItemStream
(
sharingInfo
,
itemPosition
);
if
(
isO
.
isEmpty
())
{
return
null
;
}
FileUtils
.
copyInputStreamToFile
(
isO
.
get
(),
f
);
return
new
FileInputStream
(
f
);
}
}
src/main/java/org/codeability/sharing/demo/service/SharingPluginService.java
View file @
4c4b0dbe
...
...
@@ -20,11 +20,11 @@ public class SharingPluginService {
public
SharingPluginConfig
getPluginConfig
(
String
baseAPIURI
)
{
SharingPluginConfig
.
Action
actionCollection
=
new
SharingPluginConfig
.
Action
(
"DemoAction"
,
"/sharingPluginLandingPage"
,
"DemoAction
1
"
,
"/sharingPluginLandingPage"
,
"Transfer Collection to Demo Plugin"
,
"metadata.type.externalName=='collection
s
'"
);
// select for collections
"metadata.type.externalName=='collection'"
);
// select for collections
SharingPluginConfig
.
Action
actionProgExercise
=
new
SharingPluginConfig
.
Action
(
"DemoAction"
,
"/sharingPluginLandingPage"
,
"DemoAction
2
"
,
"/sharingPluginLandingPage"
,
"Transfer Programming Exercise to Demo Plugin"
,
"metadata.type.externalName=='programming exercise'"
);
// select for programming exercise
// "Import to Artemis", "metadata.type.externalName=='programming exercise' || metadata.type.externalName=='collection'");
...
...
src/main/java/org/codeability/sharing/demo/web/rest/SharingDemoResource.java
0 → 100644
View file @
4c4b0dbe
package
org.codeability.sharing.demo.web.rest
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.nio.charset.StandardCharsets
;
import
java.util.Optional
;
import
java.util.zip.ZipEntry
;
import
java.util.zip.ZipInputStream
;
import
org.codeability.sharing.demo.service.SharingDemoService
;
import
org.codeability.sharing.demo.web.rest.dto.SharingInfoDTO
;
import
org.codeability.sharing.plugins.api.ShoppingBasket
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.util.StreamUtils
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
io.github.jhipster.web.util.ResponseUtil
;
/**
* REST controller for managing Exercise.
*/
@RestController
@RequestMapping
(
"/api"
)
public
class
SharingDemoResource
{
private
final
Logger
log
=
LoggerFactory
.
getLogger
(
SharingDemoResource
.
class
);
private
final
SharingDemoService
exerciseSharingService
;
public
SharingDemoResource
(
SharingDemoService
exerciseSharingService
)
{
this
.
exerciseSharingService
=
exerciseSharingService
;
}
/**
* GET /sharingImport/
*
* @param sharingInfo information about sharing input
* @return the ResponseEntity with status 200 (OK) and with body the exercise, or with status 404 (Not Found)
*/
@PostMapping
(
"/sharingImport/basket"
)
public
ResponseEntity
<
ShoppingBasket
>
loadShoppingBasket
(
@RequestBody
SharingInfoDTO
sharingInfo
)
{
Optional
<
ShoppingBasket
>
sharingInfoDTO
=
exerciseSharingService
.
getBasketInfo
(
sharingInfo
);
return
ResponseUtil
.
wrapOrNotFound
(
sharingInfoDTO
);
}
public
static
class
SharingSetupInfo
{
SharingInfoDTO
sharingInfo
;
int
exercisePosition
;
public
SharingInfoDTO
getSharingInfo
()
{
return
sharingInfo
;
}
public
void
setSharingInfo
(
SharingInfoDTO
sharingInfo
)
{
this
.
sharingInfo
=
sharingInfo
;
}
public
int
getExercisePosition
()
{
return
exercisePosition
;
}
public
void
setExercisePosition
(
int
exercisePosition
)
{
this
.
exercisePosition
=
exercisePosition
;
}
}
/**
* GET /sharingImport/basket/exercise/{exercisePosition}/readMe : get problem statement.
*
* @param basketToken the basket
* @return the ResponseEntity with status 200 (OK) and with body the exercise, or with status 404 (Not Found)
*/
@PostMapping
(
"/sharingImport/basket/exercise/{exercisePosition}/readMe.md"
)
// @PreAuthorize("hasAnyRole('INSTRUCTOR', 'ADMIN')")
public
ResponseEntity
<
String
>
getProblemStatement
(
@PathVariable
(
"exercisePosition"
)
int
exercisePosition
,
@RequestBody
SharingInfoDTO
basketToken
)
throws
IOException
{
InputStream
repositoryStream
=
null
;
try
{
repositoryStream
=
exerciseSharingService
.
getCachedBasketItemStream
(
basketToken
,
exercisePosition
);
}
catch
(
IOException
e
)
{
log
.
error
(
"Cannot read input Template for "
+
basketToken
.
getBasketToken
());
}
ZipInputStream
zippedRepositoryStream
=
new
ZipInputStream
(
repositoryStream
);
ZipEntry
statement
=
getEntry
(
"exercise.md"
,
zippedRepositoryStream
);
if
(
statement
==
null
)
{
return
ResponseEntity
.
ok
().
body
(
"Statement not found!"
)
;
}
ByteArrayOutputStream
baos
=
new
ByteArrayOutputStream
();
StreamUtils
.
copy
(
zippedRepositoryStream
,
baos
);
String
statementString
=
baos
.
toString
(
StandardCharsets
.
UTF_8
);
return
ResponseEntity
.
ok
().
body
(
statementString
);
}
public
ZipEntry
getEntry
(
String
path
,
ZipInputStream
zippedRepositoryStream
)
throws
IOException
{
ZipEntry
currentEntry
=
zippedRepositoryStream
.
getNextEntry
();
String
prefix
=
""
;
if
(
currentEntry
.
isDirectory
())
{
// main directory is prefix to all entries
prefix
=
currentEntry
.
getName
();
}
while
(
currentEntry
!=
null
)
{
if
(!
currentEntry
.
isDirectory
()
&&
currentEntry
.
getName
().
equals
(
prefix
+
path
))
return
currentEntry
;
currentEntry
=
zippedRepositoryStream
.
getNextEntry
();
}
return
null
;
}
}
src/main/java/org/codeability/sharing/demo/web/rest/dto/SharingInfoDTO.java
0 → 100644
View file @
4c4b0dbe
package
org.codeability.sharing.demo.web.rest.dto
;
public
class
SharingInfoDTO
{
private
String
basketToken
;
private
String
returnURL
;
private
String
apiBaseURL
;
public
String
getReturnURL
()
{
return
returnURL
;
}
public
void
setReturnURL
(
String
returnURL
)
{
this
.
returnURL
=
returnURL
;
}
public
String
getApiBaseURL
()
{
return
apiBaseURL
;
}
public
void
setApiBaseURL
(
String
apiBaseURL
)
{
this
.
apiBaseURL
=
apiBaseURL
;
}
public
String
getBasketToken
()
{
return
basketToken
;
}
public
void
setBasketToken
(
String
basketToken
)
{
this
.
basketToken
=
basketToken
;
}
}
src/main/resources/config/application-dev.yml
View file @
4c4b0dbe
...
...
@@ -63,7 +63,7 @@ spring:
cache
:
false
server
:
port
:
808
0
port
:
808
2
# ===================================================================
# JHipster specific properties
...
...
@@ -85,7 +85,7 @@ jhipster:
allow-credentials
:
true
max-age
:
1800
mail
:
# specific JHipster mail property, for standard properties see MailProperties
base-url
:
http://127.0.0.1:808
0
base-url
:
http://127.0.0.1:808
2
metrics
:
logs
:
# Reports metrics in the logs
enabled
:
false
...
...
src/main/resources/config/application.yml
View file @
4c4b0dbe
...
...
@@ -22,7 +22,7 @@ management:
include
:
[
'
configprops'
,
'
env'
,
'
health'
,
'
info'
,
'
jhimetrics'
,
'
logfile'
,
'
loggers'
,
'
prometheus'
,
'
threaddump'
]
endpoint
:
health
:
show-details
:
when_authorized
show-details
:
WHEN_AUTHORIZED
roles
:
'
ROLE_ADMIN'
jhimetrics
:
enabled
:
true
...
...
src/main/webapp/app/sharing/service/sharing-demo.service.ts
0 → 100644
View file @
4c4b0dbe
import
{
Injectable
}
from
'
@angular/core
'
;
import
{
HttpClient
}
from
'
@angular/common/http
'
;
import
{
Observable
}
from
'
rxjs
'
;
import
{
SharingInfo
}
from
'
app/sharing/sharing.model
'
;
export
type
ExerciseInfo
=
{
title
:
string
;
gitLabProjectId
:
string
;
gitLabURI
:
string
;
keywords
:
string
[];
};
export
type
ShoppingBasket
=
{
exerciseInfo
:
Array
<
ExerciseInfo
>
;
};
const
SERVER_API_URL
=
'
http://localhost:8082/
'
@
Injectable
({
providedIn
:
'
root
'
})
export
class
SharingDemoService
{
public
resourceUrl
=
SERVER_API_URL
+
'
api/sharingImport
'
;
public
resourceUrlPS
=
SERVER_API_URL
+
'
api/sharingImport/basket/exercise/
'
;
constructor
(
private
http
:
HttpClient
,
private
sharingInfo
:
SharingInfo
)
{}
loadShoppingBasket
():
Observable
<
ShoppingBasket
>
{
return
this
.
http
.
post
<
ShoppingBasket
>
(
this
.
resourceUrl
+
'
/basket
'
,
this
.
sharingInfo
);
}
}
src/main/webapp/app/sharing/sharing.component.html
View file @
4c4b0dbe
...
...
@@ -4,11 +4,23 @@
<h1>
Happy Sharing
</h1>
</div>
<div
class=
"content"
>
<div><b>
This page is intentionally ugly :-)
</b></div
>
<h1>
Data from URL
</h1
>
<div>
basketToken: {{this.sharingInfo.basketToken}}
</div>
<div>
returnURL: {{this.sharingInfo.returnURL}}
</div>
<div>
apiBaseURL: {{this.sharingInfo.apiBaseURL}}
</div>
<div
*ngIf=
"!isInstuctor()"
>
Please ensure to log in as instructor!
</div>
</div>
<h1>
Shopping Basket Data from SharingPlattform (loaded via plugin backend)
</h1>
<div><span
*ngIf=
"!shoppingBasket"
>
No Shopping Basket loaded
</span></div>
<div
*ngIf=
"shoppingBasket"
>
<div
>
The Shopping Basket contains {{shoppingBasket.exerciseInfo.length}} element(s):
</div>
<div
*ngFor=
"let execInfo of shoppingBasket.exerciseInfo"
>
<div>
title: {{execInfo.title}}
</div>
<div>
gitLabURI: {{execInfo.gitLabURI}}
</div>
<div>
gitLabProjectId: {{execInfo.gitLabProjectId}}
</div>
<div>
keywords:
<span
*ngFor=
"let kw of execInfo.keywords"
></span>
"{{kw}}"
</div>
</div>
</div>
</div>
</body>
src/main/webapp/app/sharing/sharing.component.ts
View file @
4c4b0dbe
import
{
Component
,
OnInit
}
from
'
@angular/core
'
;
import
{
ActivatedRoute
,
Router
}
from
'
@angular/router
'
;
import
{
ActivatedRoute
}
from
'
@angular/router
'
;
import
{
SharingInfo
}
from
'
./sharing.model
'
;
import
{
SharingDemoService
,
ShoppingBasket
}
from
'
./service/sharing-demo.service
'
;
@
Component
({
selector
:
'
jhi-sharing
'
,
...
...
@@ -9,10 +10,13 @@ import { SharingInfo } from './sharing.model';
})
export
class
SharingComponent
implements
OnInit
{
public
shoppingBasket
:
ShoppingBasket
;
constructor
(
private
route
:
ActivatedRoute
,
private
router
:
Router
,
public
sharingInfo
:
SharingInfo
,
private
sharingDemoService
:
SharingDemoService
,
)
{
this
.
route
.
params
.
subscribe
((
params
)
=>
{
...
...
@@ -21,10 +25,19 @@ export class SharingComponent implements OnInit {
this
.
route
.
queryParams
.
subscribe
((
qparam
)
=>
{
sharingInfo
.
returnURL
=
qparam
[
'
returnURL
'
];
sharingInfo
.
apiBaseURL
=
qparam
[
'
apiBaseURL
'
];
// }
this
.
loadShoppingBasket
();
});
this
.
shoppingBasket
=
{}
as
ShoppingBasket
;
}
loadShoppingBasket
():
void
{
this
.
sharingDemoService
.
loadShoppingBasket
().
subscribe
((
res
:
ShoppingBasket
)
=>
{
this
.
shoppingBasket
=
res
;
});
}
/**
* Initialises the sharing page for import
*/
...
...
src/main/webapp/app/sharing/sharing.module.ts
View file @
4c4b0dbe
import
{
NgModule
}
from
'
@angular/core
'
;
import
{
RouterModule
}
from
'
@angular/router
'
;
import
{
CommonModule
}
from
'
@angular/common
'
;
import
{
SharingComponent
}
from
'
app/sharing/sharing.component
'
;
import
{
featureOverviewState
}
from
'
app/sharing/sharing.route
'
;
const
SHARING_ROUTES
=
[...
featureOverviewState
];
@
NgModule
({
imports
:
[
RouterModule
.
forChild
(
SHARING_ROUTES
)],
imports
:
[
CommonModule
,
RouterModule
.
forChild
(
SHARING_ROUTES
)],
declarations
:
[
SharingComponent
],
})
export
class
SharingModule
{}
src/test/resources/config/application.yml
View file @
4c4b0dbe
...
...
@@ -99,7 +99,7 @@ jhipster:
queue-size
:
512
mail
:
from
:
test@localhost
base-url
:
http://127.0.0.1:808
0
base-url
:
http://127.0.0.1:808
2
metrics
:
logs
:
# Reports metrics in the logs
enabled
:
true
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment