diff --git a/api/src/main/kotlin/edu/wgu/osmt/api/model/ApiKeyword.kt b/api/src/main/kotlin/edu/wgu/osmt/api/model/ApiKeyword.kt index 1c3e285db..c9d25c1fc 100644 --- a/api/src/main/kotlin/edu/wgu/osmt/api/model/ApiKeyword.kt +++ b/api/src/main/kotlin/edu/wgu/osmt/api/model/ApiKeyword.kt @@ -2,14 +2,17 @@ package edu.wgu.osmt.api.model import com.fasterxml.jackson.annotation.JsonInclude import com.fasterxml.jackson.annotation.JsonProperty +import edu.wgu.osmt.config.AppConfig import edu.wgu.osmt.keyword.Keyword import edu.wgu.osmt.keyword.KeywordDao import edu.wgu.osmt.keyword.KeywordTypeEnum +import org.springframework.beans.factory.annotation.Autowired @JsonInclude(JsonInclude.Include.ALWAYS) class ApiKeyword( private val keyword: Keyword, - private val totalSkills: Long? + private val totalSkills: Long?, + private val appConfig: AppConfig ) { @get:JsonProperty val id: Long? @@ -35,22 +38,30 @@ class ApiKeyword( val skillCount: Long? get() = totalSkills + @get:JsonProperty + val publicUrl: String + get() = "${appConfig.baseUrl}/api/metadata/keywords/${id}" + companion object { fun fromDao( keywordDao: KeywordDao, + appConfig: AppConfig ): ApiKeyword { return ApiKeyword( keyword = keywordDao.toModel(), - totalSkills = keywordDao.skills.count() + totalSkills = keywordDao.skills.count(), + appConfig = appConfig ) } fun fromModel( - keyword: Keyword + keyword: Keyword, + appConfig: AppConfig ): ApiKeyword { return ApiKeyword( totalSkills = keyword.id?.let { KeywordDao.findById(it)?.skills?.count() ?: 0 }, - keyword = keyword + keyword = keyword, + appConfig = appConfig ) } } diff --git a/api/src/main/kotlin/edu/wgu/osmt/keyword/KeywordController.kt b/api/src/main/kotlin/edu/wgu/osmt/keyword/KeywordController.kt index 80d3463f0..f611750ee 100644 --- a/api/src/main/kotlin/edu/wgu/osmt/keyword/KeywordController.kt +++ b/api/src/main/kotlin/edu/wgu/osmt/keyword/KeywordController.kt @@ -36,6 +36,7 @@ import org.springframework.web.bind.annotation.GetMapping 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.RequestParam import org.springframework.web.bind.annotation.ResponseBody import org.springframework.web.server.ResponseStatusException @@ -74,7 +75,16 @@ class KeywordController @Autowired constructor( return ResponseEntity.status(200) .headers(responseHeaders) - .body(searchResults.map { ApiKeyword.fromModel(it.content) }.toList()) + .body(searchResults.map { ApiKeyword.fromModel(it.content, appConfig) }.toList()) + } + + @RequestMapping(path = [ + "${RoutePaths.API}${RoutePaths.UNVERSIONED}${RoutePaths.KEYWORD_DETAIL}" + ], + produces = [MediaType.TEXT_HTML_VALUE]) + fun byUUIDHtmlView(@PathVariable id: String): String { + System.out.println("here by uuid html view keyword") + return "forward:${RoutePaths.UNVERSIONED}/metadata/keywords/$id" } @GetMapping( @@ -104,7 +114,7 @@ class KeywordController @Autowired constructor( return ResponseEntity .status(HttpStatus.OK) - .body(keywordRepository.createFromApi(apiKeywordUpdate)?.let { ApiKeyword(it.toModel(), it.skills.count()) }) + .body(keywordRepository.createFromApi(apiKeywordUpdate)?.let { ApiKeyword(it.toModel(), it.skills.count(), appConfig) }) } @PostMapping( @@ -126,7 +136,7 @@ class KeywordController @Autowired constructor( oAuthHelper.readableUserName(user) ) ?.let { - ApiKeyword(it.toModel(), it.skills.count()) + ApiKeyword(it.toModel(), it.skills.count(), appConfig) } ) } @@ -149,7 +159,7 @@ class KeywordController @Autowired constructor( private fun byId( id: Long, ): ApiKeyword? { - val found = keywordRepository.findById(id)?.let { ApiKeyword(it.toModel(), it.skills.count()) } + val found = keywordRepository.findById(id)?.let { ApiKeyword(it.toModel(), it.skills.count(), appConfig) } return found } diff --git a/api/src/main/kotlin/edu/wgu/osmt/security/SecurityConfig.kt b/api/src/main/kotlin/edu/wgu/osmt/security/SecurityConfig.kt index 8f65d2471..e47974934 100644 --- a/api/src/main/kotlin/edu/wgu/osmt/security/SecurityConfig.kt +++ b/api/src/main/kotlin/edu/wgu/osmt/security/SecurityConfig.kt @@ -85,6 +85,7 @@ class SecurityConfig : WebSecurityConfigurerAdapter() { .mvcMatchers(GET, "${RoutePaths.API}${RoutePaths.API_V3}${RoutePaths.SKILL_DETAIL}", "${RoutePaths.API}${RoutePaths.API_V2}${RoutePaths.SKILL_DETAIL}", "${RoutePaths.API}${RoutePaths.UNVERSIONED}${RoutePaths.SKILL_DETAIL}").permitAll() + .mvcMatchers(GET,"${RoutePaths.API}${RoutePaths.UNVERSIONED}${RoutePaths.KEYWORD_DETAIL}").permitAll() .mvcMatchers(GET, "${RoutePaths.API}${RoutePaths.API_V3}${RoutePaths.COLLECTION_DETAIL}", "${RoutePaths.API}${RoutePaths.API_V2}${RoutePaths.COLLECTION_DETAIL}", "${RoutePaths.API}${RoutePaths.UNVERSIONED}${RoutePaths.COLLECTION_DETAIL}").permitAll() diff --git a/api/src/test/kotlin/edu/wgu/osmt/api/model/ApiKeywordTest.kt b/api/src/test/kotlin/edu/wgu/osmt/api/model/ApiKeywordTest.kt index ff53d3c45..2fa9045d4 100644 --- a/api/src/test/kotlin/edu/wgu/osmt/api/model/ApiKeywordTest.kt +++ b/api/src/test/kotlin/edu/wgu/osmt/api/model/ApiKeywordTest.kt @@ -1,11 +1,13 @@ package edu.wgu.osmt.api.model +import edu.wgu.osmt.config.AppConfig import edu.wgu.osmt.keyword.Keyword import edu.wgu.osmt.mockdata.MockData import org.assertj.core.api.Assertions import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestInstance +import org.springframework.beans.factory.annotation.Autowired @TestInstance(TestInstance.Lifecycle.PER_CLASS) internal class ApiKeywordTest { @@ -23,11 +25,11 @@ internal class ApiKeywordTest { val kw: Keyword = mockData.getKeywords().first() // Act - val api: ApiKeyword = ApiKeyword(kw, 7) + val api: ApiKeyword = ApiKeyword(kw, 7, mockData.appConfig) // Assert Assertions.assertThat(api.id).isEqualTo(kw.id) Assertions.assertThat(api.type).isEqualTo(kw.type) Assertions.assertThat(api.name).isEqualTo(kw.value) } -} \ No newline at end of file +} diff --git a/ui/src/app/app-routing.module.ts b/ui/src/app/app-routing.module.ts index c04db4ebb..0d3267f80 100644 --- a/ui/src/app/app-routing.module.ts +++ b/ui/src/app/app-routing.module.ts @@ -89,12 +89,14 @@ const routes: Routes = [ /* KEYWORDS */ - {path: "metadata", + { + path: "metadata", component: MetadataListComponent, canActivate: [AuthGuard], }, // create metadata - {path: "named-references/create", + { + path: "named-references/create", component: NamedReferenceFormComponent, canActivate: [AuthGuard], data: { @@ -109,7 +111,8 @@ const routes: Routes = [ }, },*/ // edit metadata - {path: "named-references/:id/edit", + { + path: "named-references/:id/edit", component: NamedReferenceFormComponent, canActivate: [AuthGuard], data: { @@ -124,20 +127,19 @@ const routes: Routes = [ }, },*/ // public metadata detail - {path: "named-references/:id", - component: MetadataPublicComponent, - canActivate: [AuthGuard] - }, - {path: "job-codes/:id", + { + path: "job-codes/:id", component: MetadataPublicComponent, canActivate: [AuthGuard] }, // admin metadata detail - {path: "named-references/:id/manage", + { + path: "named-references/:id/manage", component: MetadataManageComponent, canActivate: [AuthGuard] }, - {path: "job-codes/:id/manage", + { + path: "job-codes/:id/manage", component: MetadataManageComponent, canActivate: [AuthGuard] }, @@ -246,6 +248,10 @@ const routes: Routes = [ {path: "collections/:uuid", component: CollectionPublicComponent}, {path: "api/skills/:uuid", component: RichSkillPublicComponent}, {path: "api/collections/:uuid", component: CollectionPublicComponent}, + { + path: "api/metadata/keywords/:id", + component: MetadataPublicComponent + }, /* AUTHENTICATION REDIRECTS */ {path: "login", component: LoginComponent}, // redirect to oauth login diff --git a/ui/src/app/metadata/detail/abstract-metadata-detail.component.ts b/ui/src/app/metadata/detail/abstract-metadata-detail.component.ts index 93c83ce11..94fec549c 100644 --- a/ui/src/app/metadata/detail/abstract-metadata-detail.component.ts +++ b/ui/src/app/metadata/detail/abstract-metadata-detail.component.ts @@ -125,6 +125,7 @@ export abstract class AbstractMetadataDetailComponent extends QuickLinksHelper i protected setMetadata(metadata: ApiNamedReference | ApiJobCode) { this.metadata = metadata; + console.log(this.metadata) // this.titleService.setTitle(`${category.name} | Category | ${this.whitelabel.toolName}`) this.loadSkills(); @@ -132,7 +133,7 @@ export abstract class AbstractMetadataDetailComponent extends QuickLinksHelper i protected loadSkills(): void { if (this.metadata) { - this.skillTableControl.loadSkills(this.getId()) + this.skillTableControl.loadSkills(this.idParam ?? -1) } else { this.clearSkills(); } @@ -153,6 +154,10 @@ export abstract class AbstractMetadataDetailComponent extends QuickLinksHelper i return this.metadata?.id ?? -1; } + getPublicUrl(): string { + return (this.metadata as any)?.publicUrl ?? ""; + } + getCardFormat(): IDetailCardSectionData[] { return []; } diff --git a/ui/src/app/metadata/detail/metadata-list/metadata-list.component.html b/ui/src/app/metadata/detail/metadata-list/metadata-list.component.html index 7e75fb1d5..903abc8f7 100644 --- a/ui/src/app/metadata/detail/metadata-list/metadata-list.component.html +++ b/ui/src/app/metadata/detail/metadata-list/metadata-list.component.html @@ -5,7 +5,7 @@

{{title}}

- {{metadataCountLabel}} + {{metadataCountLabel}}. found based on diff --git a/ui/src/app/metadata/detail/metadata-list/metadata-list.component.ts b/ui/src/app/metadata/detail/metadata-list/metadata-list.component.ts index 47c22c6c2..453b412bd 100644 --- a/ui/src/app/metadata/detail/metadata-list/metadata-list.component.ts +++ b/ui/src/app/metadata/detail/metadata-list/metadata-list.component.ts @@ -19,7 +19,7 @@ import { NamedReferenceService } from "../../named-reference/service/named-refer }) export class MetadataListComponent extends AbstractListComponent implements OnInit { - selectedMetadataType = MetadataType.Category + selectedMetadataType = Object.values(MetadataType)[0]; typeControl: FormControl = new FormControl(this.selectedMetadataType) diff --git a/ui/src/app/metadata/detail/metadata-manage/metadata-manage.component.html b/ui/src/app/metadata/detail/metadata-manage/metadata-manage.component.html index d77f0020f..c2f4a8ed5 100644 --- a/ui/src/app/metadata/detail/metadata-manage/metadata-manage.component.html +++ b/ui/src/app/metadata/detail/metadata-manage/metadata-manage.component.html @@ -14,7 +14,7 @@ diff --git a/ui/src/app/metadata/detail/metadata-public/metadata-public.component.html b/ui/src/app/metadata/detail/metadata-public/metadata-public.component.html index 893ea2af9..62bcdb136 100644 --- a/ui/src/app/metadata/detail/metadata-public/metadata-public.component.html +++ b/ui/src/app/metadata/detail/metadata-public/metadata-public.component.html @@ -14,7 +14,7 @@ @@ -60,7 +60,7 @@

diff --git a/ui/src/app/metadata/detail/metadata-selector/metadata-selector.component.ts b/ui/src/app/metadata/detail/metadata-selector/metadata-selector.component.ts index d8c4a605e..4dfd46ec6 100644 --- a/ui/src/app/metadata/detail/metadata-selector/metadata-selector.component.ts +++ b/ui/src/app/metadata/detail/metadata-selector/metadata-selector.component.ts @@ -14,10 +14,18 @@ export class MetadataSelectorComponent { @Input() currentSelection?: string - protected readonly MetadataType = MetadataType + types: string[] = [] @Input() isVisible: () => boolean = () => false + constructor() { + this.types = Object.values(MetadataType).sort((a, b) => { + if(a < b) { return -1; } + if(a > b) { return 1; } + return 0; + }) + } + onValueChange(value: string): void { this.control?.patchValue(value) this.currentSelection = value diff --git a/ui/src/app/metadata/named-reference/NamedReference.ts b/ui/src/app/metadata/named-reference/NamedReference.ts index eb5d2d50d..5caee08f8 100644 --- a/ui/src/app/metadata/named-reference/NamedReference.ts +++ b/ui/src/app/metadata/named-reference/NamedReference.ts @@ -7,6 +7,7 @@ export interface NamedReferenceInterface { url: string framework: string skillCount: number + publicUrl: string } export class ApiNamedReference implements NamedReferenceInterface { @@ -16,6 +17,7 @@ export class ApiNamedReference implements NamedReferenceInterface { type?: MetadataType = MetadataType.Category url = "" skillCount: number = 0 + publicUrl = "" constructor(o?: NamedReferenceInterface) { if (o !== undefined) { diff --git a/ui/src/app/metadata/named-reference/named-reference-form/named-reference-form.component.html b/ui/src/app/metadata/named-reference/named-reference-form/named-reference-form.component.html index 24ccac77a..f76e315ee 100644 --- a/ui/src/app/metadata/named-reference/named-reference-form/named-reference-form.component.html +++ b/ui/src/app/metadata/named-reference/named-reference-form/named-reference-form.component.html @@ -33,7 +33,7 @@

-
+
>
-
+
- Copy URLdd + Copy URL diff --git a/ui/test/resource/mock-data.ts b/ui/test/resource/mock-data.ts index 6943612f9..6fc6eb284 100644 --- a/ui/test/resource/mock-data.ts +++ b/ui/test/resource/mock-data.ts @@ -62,7 +62,7 @@ export function createMockNamedReference2( url = "http://url123", framework = "Framework" ): NamedReferenceInterface { - return {id,name,type,url,framework, skillCount: 0 + return {id,name,type,url,framework, skillCount: 0, publicUrl: url } }