From 2b6d33d721c2b8c9f819b9126de9a961db2bed3a Mon Sep 17 00:00:00 2001 From: rquazi <rumana.quazi@csc.fi> Date: Thu, 9 Nov 2023 11:21:11 +0200 Subject: [PATCH 01/15] formatting with prettier --- .../components/crosswalk-list/index.tsx | 83 +++++++++--------- .../fakeable-users/fakeable-users.slice.tsx | 2 +- .../components/layout/layout.styles.tsx | 1 - .../src/common/components/layout/layout.tsx | 26 +++--- .../mscr-search/mscr-search.slice.tsx | 32 +++---- .../common/components/schema-list/index.tsx | 84 +++++++++---------- .../common/components/schema/schema.slice.tsx | 7 ++ .../search-context-provider/index.tsx | 9 +- .../components/search-filter-set/index.tsx | 25 ++++-- .../search-filter-set.styles.tsx | 3 +- .../common/components/search-result/index.tsx | 42 +++++----- .../components/side-navigation/index.tsx | 2 +- .../common/components/smart-header/index.tsx | 2 +- .../common/interfaces/mscr-user.interface.ts | 2 +- .../src/common/interfaces/search.interface.ts | 36 +++++--- .../common/utils/create-getserversideprops.ts | 3 +- .../src/common/utils/hooks/use-url-state.tsx | 24 ++++-- mscr-ui/src/modules/crosswalk-form/index.tsx | 21 ++--- mscr-ui/src/modules/search-bar/index.tsx | 23 ++--- mscr-ui/src/modules/search-screen/index.tsx | 42 ++++++---- .../search-screen/search-screen.styles.tsx | 2 +- .../src/pages/[homepage]/content/index.tsx | 6 +- mscr-ui/src/pages/index.tsx | 13 +-- mscr-ui/src/store/index.tsx | 4 +- 24 files changed, 277 insertions(+), 217 deletions(-) diff --git a/mscr-ui/src/common/components/crosswalk-list/index.tsx b/mscr-ui/src/common/components/crosswalk-list/index.tsx index 75069d890..b579ee6e6 100644 --- a/mscr-ui/src/common/components/crosswalk-list/index.tsx +++ b/mscr-ui/src/common/components/crosswalk-list/index.tsx @@ -20,7 +20,7 @@ export default function CrosswalkList({ }: CrosswalkListProps) { const { t } = useTranslation('admin'); - if (items.length < 1) { + if (items && items.length < 1) { return <div>{'There is no Schemas or Crosswalks to show'}</div>; } @@ -56,47 +56,48 @@ export default function CrosswalkList({ </ListItem> </List> <List className="inline-list"> - {items.map((item) => ( - <ListItem - key={item.pid} - onClick={() => handleClick(item.pid)} - onMouseEnter={() => item.onMouseEnter && item.onMouseEnter()} - onMouseLeave={() => item.onMouseLeave && item.onMouseLeave()} - onKeyDown={(e) => e.key === 'Enter' && item.onClick()} - > - <Grid container spacing={2}> - <Grid item xs={2}> - {item.label} + {items && + items.map((item) => ( + <ListItem + key={item.pid} + onClick={() => handleClick(item.pid)} + onMouseEnter={() => item.onMouseEnter && item.onMouseEnter()} + onMouseLeave={() => item.onMouseLeave && item.onMouseLeave()} + onKeyDown={(e) => e.key === 'Enter' && item.onClick()} + > + <Grid container spacing={2}> + <Grid item xs={2}> + {item.label} + </Grid> + <Grid item xs={2}> + {item.prefix} + </Grid> + <Grid item xs={2}> + {item.status} + </Grid> + <Grid item xs={2}> + {item.revision} + </Grid> + <Grid item xs={2}> + {item.pid} + </Grid> + <Grid item xs={2}> + {Array.isArray(deleteDisabled) && + deleteDisabled.includes(item.pid) ? ( + <></> + ) : ( + <Button + variant="secondaryNoBorder" + icon="remove" + onClick={() => handleRemoval(item.pid)} + > + {t('remove')} + </Button> + )} + </Grid> </Grid> - <Grid item xs={2}> - {item.prefix} - </Grid> - <Grid item xs={2}> - {item.status} - </Grid> - <Grid item xs={2}> - {item.revision} - </Grid> - <Grid item xs={2}> - {item.pid} - </Grid> - <Grid item xs={2}> - {Array.isArray(deleteDisabled) && - deleteDisabled.includes(item.pid) ? ( - <></> - ) : ( - <Button - variant="secondaryNoBorder" - icon="remove" - onClick={() => handleRemoval(item.pid)} - > - {t('remove')} - </Button> - )} - </Grid> - </Grid> - </ListItem> - ))} + </ListItem> + ))} </List> </div> ); diff --git a/mscr-ui/src/common/components/fakeable-users/fakeable-users.slice.tsx b/mscr-ui/src/common/components/fakeable-users/fakeable-users.slice.tsx index a3dbcb39b..ae2a0b145 100644 --- a/mscr-ui/src/common/components/fakeable-users/fakeable-users.slice.tsx +++ b/mscr-ui/src/common/components/fakeable-users/fakeable-users.slice.tsx @@ -15,7 +15,7 @@ export const fakeableUsersApi = createApi({ endpoints: (builder) => ({ getFakeableUsers: builder.query<FakeableUser[], void>({ query: () => ({ - url: '/fakeableUsers', + url: '/fakeable-users', method: 'GET', }), }), diff --git a/mscr-ui/src/common/components/layout/layout.styles.tsx b/mscr-ui/src/common/components/layout/layout.styles.tsx index a51e22b81..5b8614e84 100644 --- a/mscr-ui/src/common/components/layout/layout.styles.tsx +++ b/mscr-ui/src/common/components/layout/layout.styles.tsx @@ -41,7 +41,6 @@ export const NavigationContainer = styled.div<{ $breakpoint: Breakpoint }>` // content layout - export const ContentContainer = styled.div<{ $fullScreen?: boolean }>` background-color: ${(props) => props.$fullScreen diff --git a/mscr-ui/src/common/components/layout/layout.tsx b/mscr-ui/src/common/components/layout/layout.tsx index 3318f98df..3489b85d0 100644 --- a/mscr-ui/src/common/components/layout/layout.tsx +++ b/mscr-ui/src/common/components/layout/layout.tsx @@ -1,4 +1,4 @@ -import React, {useState} from 'react'; +import React, { useState } from 'react'; import { ThemeProvider } from 'styled-components'; import { lightTheme } from 'yti-common-ui/theme'; import { @@ -13,10 +13,10 @@ import SkipLink from 'yti-common-ui/skip-link'; import { FakeableUser } from '../../interfaces/fakeable-user.interface'; import generateFakeableUsers from 'yti-common-ui/utils/generate-impersonate'; import SideNavigationPanel from '../side-navigation'; -import {MscrUser} from '@app/common/interfaces/mscr-user.interface'; -import {SearchContext} from '@app/common/components/search-context-provider'; +import { MscrUser } from '@app/common/interfaces/mscr-user.interface'; +import { SearchContext } from '@app/common/components/search-context-provider'; import SearchScreen from '@app/modules/search-screen'; -import {Grid} from '@mui/material'; +import { Grid } from '@mui/material'; export default function Layout({ children, @@ -39,22 +39,24 @@ export default function Layout({ const { breakpoint } = useBreakpoints(); const [isSearchActive, setIsSearchActive] = useState(false); - return ( <ThemeProvider theme={lightTheme}> <SearchContext.Provider value={{ isSearchActive, - setIsSearchActive + setIsSearchActive, }} - > + > {matomo && matomo} <SkipLink href="#main">{t('skip-link-main')}</SkipLink> {fullScreenElements ? ( <SiteContainer> <SmartHeader user={user} - fakeableUsers={generateFakeableUsers(i18n.language, fakeableUsers)} + fakeableUsers={generateFakeableUsers( + i18n.language, + fakeableUsers + )} fullScreenElements={fullScreenElements} /> @@ -68,11 +70,14 @@ export default function Layout({ <SiteContainer> <SmartHeader user={user} - fakeableUsers={generateFakeableUsers(i18n.language, fakeableUsers)} + fakeableUsers={generateFakeableUsers( + i18n.language, + fakeableUsers + )} /> <Grid container spacing={2}> <Grid item xs={2}> - {user && <SideNavigationPanel user={user}/>} + {user && <SideNavigationPanel user={user} />} </Grid> <Grid item xs={10}> <ContentContainer> @@ -87,7 +92,6 @@ export default function Layout({ </SiteContainer> )} </SearchContext.Provider> - </ThemeProvider> ); } diff --git a/mscr-ui/src/common/components/mscr-search/mscr-search.slice.tsx b/mscr-ui/src/common/components/mscr-search/mscr-search.slice.tsx index e224f5a4d..9461c6b2b 100644 --- a/mscr-ui/src/common/components/mscr-search/mscr-search.slice.tsx +++ b/mscr-ui/src/common/components/mscr-search/mscr-search.slice.tsx @@ -1,8 +1,8 @@ -import {createApi} from '@reduxjs/toolkit/query/react'; -import {getDatamodelApiBaseQuery} from '@app/store/api-base-query'; -import {HYDRATE} from 'next-redux-wrapper'; -import {MscrSearchResults} from '@app/common/interfaces/search.interface'; -import {UrlState} from '@app/common/utils/hooks/use-url-state'; +import { createApi } from '@reduxjs/toolkit/query/react'; +import { getDatamodelApiBaseQuery } from '@app/store/api-base-query'; +import { HYDRATE } from 'next-redux-wrapper'; +import { MscrSearchResults } from '@app/common/interfaces/search.interface'; +import { UrlState } from '@app/common/utils/hooks/use-url-state'; function createUrl(urlState: UrlState) { let baseQuery = '/frontend/mscrSearch?'; @@ -22,10 +22,14 @@ function createUrl(urlState: UrlState) { baseQuery = baseQuery.concat(`&format=${urlState.format.join(',')}`); } if (urlState.sourceType && urlState.sourceType.length > 0) { - baseQuery = baseQuery.concat(`&sourceType=${urlState.sourceType.join(',')}`); + baseQuery = baseQuery.concat( + `&sourceType=${urlState.sourceType.join(',')}` + ); } if (urlState.organization && urlState.organization.length > 0) { - baseQuery = baseQuery.concat(`&organization=${urlState.organization.join(',')}`); + baseQuery = baseQuery.concat( + `&organization=${urlState.organization.join(',')}` + ); } return baseQuery; @@ -41,22 +45,18 @@ export const mscrSearchApi = createApi({ } }, endpoints: (builder) => ({ - getMscrSearchResults: builder.query< - MscrSearchResults, - UrlState - >({ + getMscrSearchResults: builder.query<MscrSearchResults, UrlState>({ query: (urlState) => ({ url: createUrl(urlState), method: 'GET', - }) - }) - }) - + }), + }), + }), }); export const { getMscrSearchResults } = mscrSearchApi.endpoints; export const { useGetMscrSearchResultsQuery, - util: { getRunningQueriesThunk}, + util: { getRunningQueriesThunk }, } = mscrSearchApi; diff --git a/mscr-ui/src/common/components/schema-list/index.tsx b/mscr-ui/src/common/components/schema-list/index.tsx index f53646e9b..6c36b5e13 100644 --- a/mscr-ui/src/common/components/schema-list/index.tsx +++ b/mscr-ui/src/common/components/schema-list/index.tsx @@ -22,7 +22,7 @@ export default function SchemaList({ const { t } = useTranslation('admin'); if (items && items.length < 1) { - items = [];// initialize empty array + items = []; // initialize empty array return <div>{'There is no Schemas or Crosswalks to show'}</div>; } @@ -34,7 +34,6 @@ export default function SchemaList({ return ( //Creating Header row - <div> <List className="header-list"> @@ -60,47 +59,48 @@ export default function SchemaList({ </ListItem> </List> <List className="inline-list"> - {items && items.map((item) => ( - <ListItem - key={item.pid} - onClick={() => handleClick(item.pid)} - onMouseEnter={() => item.onMouseEnter && item.onMouseEnter()} - onMouseLeave={() => item.onMouseLeave && item.onMouseLeave()} - onKeyDown={(e) => e.key === 'Enter' && item.onClick()} - > - <Grid container spacing={2}> - <Grid item xs={2}> - {item.label} + {items && + items.map((item) => ( + <ListItem + key={item.pid} + onClick={() => handleClick(item.pid)} + onMouseEnter={() => item.onMouseEnter && item.onMouseEnter()} + onMouseLeave={() => item.onMouseLeave && item.onMouseLeave()} + onKeyDown={(e) => e.key === 'Enter' && item.onClick()} + > + <Grid container spacing={2}> + <Grid item xs={2}> + {item.label} + </Grid> + <Grid item xs={2}> + {item.prefix} + </Grid> + <Grid item xs={2}> + {item.status} + </Grid> + <Grid item xs={2}> + {item.revision} + </Grid> + <Grid item xs={2}> + {item.pid} + </Grid> + <Grid item xs={2}> + {Array.isArray(deleteDisabled) && + deleteDisabled.includes(item.pid) ? ( + <></> + ) : ( + <Button + variant="secondaryNoBorder" + icon="remove" + onClick={() => handleRemoval(item.pid)} + > + {t('remove')} + </Button> + )} + </Grid> </Grid> - <Grid item xs={2}> - {item.prefix} - </Grid> - <Grid item xs={2}> - {item.status} - </Grid> - <Grid item xs={2}> - {item.revision} - </Grid> - <Grid item xs={2}> - {item.pid} - </Grid> - <Grid item xs={2}> - {Array.isArray(deleteDisabled) && - deleteDisabled.includes(item.pid) ? ( - <></> - ) : ( - <Button - variant="secondaryNoBorder" - icon="remove" - onClick={() => handleRemoval(item.pid)} - > - {t('remove')} - </Button> - )} - </Grid> - </Grid> - </ListItem> - ))} + </ListItem> + ))} </List> </div> ); diff --git a/mscr-ui/src/common/components/schema/schema.slice.tsx b/mscr-ui/src/common/components/schema/schema.slice.tsx index 1576759f8..72c5edb7b 100644 --- a/mscr-ui/src/common/components/schema/schema.slice.tsx +++ b/mscr-ui/src/common/components/schema/schema.slice.tsx @@ -29,6 +29,13 @@ export const schemaApi = createApi({ data: value, }), }), + putSchemaFull: builder.mutation<SchemaFormType, SchemaFormType>({ + query: (value) => ({ + url: '/schemaFull', + method: 'PUT', + data: value, + }), + }), getSchema: builder.query<Schema, string>({ query: (pid) => ({ url: `/schema/${pid}`, diff --git a/mscr-ui/src/common/components/search-context-provider/index.tsx b/mscr-ui/src/common/components/search-context-provider/index.tsx index 94b4bfb9b..d3e5b57f9 100644 --- a/mscr-ui/src/common/components/search-context-provider/index.tsx +++ b/mscr-ui/src/common/components/search-context-provider/index.tsx @@ -1,13 +1,14 @@ -import {createContext, Dispatch, SetStateAction} from 'react'; +import { createContext, Dispatch, SetStateAction } from 'react'; type SearchContextState = { isSearchActive: boolean; setIsSearchActive: Dispatch<SetStateAction<boolean>>; -} +}; const initialSearchContext: SearchContextState = { isSearchActive: false, - setIsSearchActive: () => undefined + setIsSearchActive: () => undefined, }; -export const SearchContext = createContext<SearchContextState>(initialSearchContext); +export const SearchContext = + createContext<SearchContextState>(initialSearchContext); diff --git a/mscr-ui/src/common/components/search-filter-set/index.tsx b/mscr-ui/src/common/components/search-filter-set/index.tsx index a8c902183..f8efc685b 100644 --- a/mscr-ui/src/common/components/search-filter-set/index.tsx +++ b/mscr-ui/src/common/components/search-filter-set/index.tsx @@ -1,7 +1,7 @@ -import {FacetTitle} from '@app/common/components/search-filter-set/search-filter-set.styles'; -import {Filter, Facet} from '@app/common/interfaces/search.interface'; -import {Checkbox, CheckboxGroup} from 'suomifi-ui-components'; -import useUrlState, {UrlState} from '@app/common/utils/hooks/use-url-state'; +import { FacetTitle } from '@app/common/components/search-filter-set/search-filter-set.styles'; +import { Filter, Facet } from '@app/common/interfaces/search.interface'; +import { Checkbox, CheckboxGroup } from 'suomifi-ui-components'; +import useUrlState, { UrlState } from '@app/common/utils/hooks/use-url-state'; interface SearchFilterProps { title: string; @@ -13,7 +13,12 @@ export default function SearchFilterSet({ title, filters }: SearchFilterProps) { <> <FacetTitle variant="h2">{title}</FacetTitle> {filters.map((f) => ( - <SearchFilter key={f.label} facet={f.facet} label={f.label} options={f.options}/> + <SearchFilter + key={f.label} + facet={f.facet} + label={f.label} + options={f.options} + /> ))} </> ); @@ -23,14 +28,14 @@ function SearchFilter(searchFilter: Filter) { const { urlState, patchUrlState } = useUrlState(); const handleClick = (clickedOption: string) => { - const currentFilter : string[] = urlState[searchFilter.facet]; - let newFilter : string[] = []; + const currentFilter: string[] = urlState[searchFilter.facet]; + let newFilter: string[] = []; if (currentFilter.includes(clickedOption)) { newFilter = currentFilter.filter((option) => option !== clickedOption); } else { newFilter = currentFilter.concat(clickedOption); } - const patch : Partial<UrlState> = {}; + const patch: Partial<UrlState> = {}; patch[searchFilter.facet] = newFilter; patchUrlState(patch); }; @@ -38,7 +43,9 @@ function SearchFilter(searchFilter: Filter) { return ( <CheckboxGroup labelText={searchFilter.label}> {searchFilter.options.map((option) => ( - <Checkbox key={option.key} onClick={() => handleClick(option.key)}>{option.label} ({option.count})</Checkbox> + <Checkbox key={option.key} onClick={() => handleClick(option.key)}> + {option.label} ({option.count}) + </Checkbox> ))} </CheckboxGroup> ); diff --git a/mscr-ui/src/common/components/search-filter-set/search-filter-set.styles.tsx b/mscr-ui/src/common/components/search-filter-set/search-filter-set.styles.tsx index 94e0a5e49..294e51a31 100644 --- a/mscr-ui/src/common/components/search-filter-set/search-filter-set.styles.tsx +++ b/mscr-ui/src/common/components/search-filter-set/search-filter-set.styles.tsx @@ -1,5 +1,5 @@ import styled from 'styled-components'; -import {Heading} from 'suomifi-ui-components'; +import { Heading } from 'suomifi-ui-components'; export const FacetTitle = styled(Heading)` && { @@ -8,4 +8,3 @@ export const FacetTitle = styled(Heading)` text-transform: uppercase; } `; - diff --git a/mscr-ui/src/common/components/search-result/index.tsx b/mscr-ui/src/common/components/search-result/index.tsx index 2e103f158..28779b440 100644 --- a/mscr-ui/src/common/components/search-result/index.tsx +++ b/mscr-ui/src/common/components/search-result/index.tsx @@ -1,13 +1,19 @@ -import {MscrSearchResult, PatchedResult, ResultInfo} from '@app/common/interfaces/search.interface'; -import {Block, StaticChip} from 'suomifi-ui-components'; -import {schemaApi} from '@app/common/components/schema/schema.slice'; -import {crosswalkApi} from '@app/common/components/crosswalk/crosswalk.slice'; -import {IconMerge, IconFileGeneric} from 'suomifi-icons'; -import {ResultIconWrapper, ResultTextWrapper, ChipWrapper} from '@app/common/components/search-result/search-result.styles'; - +import { + MscrSearchResult, + PatchedResult, + ResultInfo, +} from '@app/common/interfaces/search.interface'; +import { Block, StaticChip } from 'suomifi-ui-components'; +import { schemaApi } from '@app/common/components/schema/schema.slice'; +import { crosswalkApi } from '@app/common/components/crosswalk/crosswalk.slice'; +import { IconMerge, IconFileGeneric } from 'suomifi-icons'; +import { + ResultIconWrapper, + ResultTextWrapper, + ChipWrapper, +} from '@app/common/components/search-result/search-result.styles'; export default function SearchResult({ hit }: { hit: MscrSearchResult }) { - const result = hit._source; let patchedResult: PatchedResult; let icon; @@ -16,33 +22,31 @@ export default function SearchResult({ hit }: { hit: MscrSearchResult }) { const { data: schema } = schemaApi.useGetSchemaQuery(result.id); patchedResult = { ...result, - description: schema?.description ?? {} + description: schema?.description ?? {}, }; } else { icon = <IconMerge />; const { data: crosswalk } = crosswalkApi.useGetCrosswalkQuery(result.id); patchedResult = { ...result, - description: crosswalk?.description ?? {} + description: crosswalk?.description ?? {}, }; } return ( <Block> - <ResultIconWrapper> - {icon} - </ResultIconWrapper> + <ResultIconWrapper>{icon}</ResultIconWrapper> <ResultTextWrapper> - <h4>This is a search result of type {result.type} with id {result.id}</h4> + <h4> + This is a search result of type {result.type} with id {result.id} + </h4> <p>Where are names?? Here's a placeholder for a description</p> {/* patchedResult && Object.keys(patchedResult.description).map((key) => <p key={key}>{patchedResult.description[key]}</p>) */} - {Object.keys(result.label).map((key) => + {Object.keys(result.label).map((key) => ( <ChipWrapper key={key}> - <StaticChip> - {result.label[key]} - </StaticChip> + <StaticChip>{result.label[key]}</StaticChip> </ChipWrapper> - )} + ))} </ResultTextWrapper> </Block> ); diff --git a/mscr-ui/src/common/components/side-navigation/index.tsx b/mscr-ui/src/common/components/side-navigation/index.tsx index adcd17280..169d02cf7 100644 --- a/mscr-ui/src/common/components/side-navigation/index.tsx +++ b/mscr-ui/src/common/components/side-navigation/index.tsx @@ -1,5 +1,5 @@ import Link from 'next/link'; -import {RouterLink} from 'suomifi-ui-components'; +import { RouterLink } from 'suomifi-ui-components'; import { useBreakpoints } from 'yti-common-ui/media-query'; import { NavigationHeading, diff --git a/mscr-ui/src/common/components/smart-header/index.tsx b/mscr-ui/src/common/components/smart-header/index.tsx index 88920420d..6dba6ec98 100644 --- a/mscr-ui/src/common/components/smart-header/index.tsx +++ b/mscr-ui/src/common/components/smart-header/index.tsx @@ -23,7 +23,7 @@ import { useBreakpoints } from 'yti-common-ui/media-query'; import LoginModalView from 'yti-common-ui/login-modal'; import { FakeableUser } from '../../interfaces/fakeable-user.interface'; import { User } from 'yti-common-ui/interfaces/user.interface'; -import SearchBar from "@app/modules/search-bar"; +import SearchBar from '@app/modules/search-bar'; export default function SmartHeader({ user, diff --git a/mscr-ui/src/common/interfaces/mscr-user.interface.ts b/mscr-ui/src/common/interfaces/mscr-user.interface.ts index 6a88fad99..de04ac795 100644 --- a/mscr-ui/src/common/interfaces/mscr-user.interface.ts +++ b/mscr-ui/src/common/interfaces/mscr-user.interface.ts @@ -1,4 +1,4 @@ -import {User} from 'yti-common-ui/interfaces/user.interface'; +import { User } from 'yti-common-ui/interfaces/user.interface'; export interface MscrUser extends User { organizations: Array<{ [key: string]: string }>; diff --git a/mscr-ui/src/common/interfaces/search.interface.ts b/mscr-ui/src/common/interfaces/search.interface.ts index 2512b42e9..50bcebeb0 100644 --- a/mscr-ui/src/common/interfaces/search.interface.ts +++ b/mscr-ui/src/common/interfaces/search.interface.ts @@ -1,14 +1,19 @@ -import {Organization} from '@app/common/interfaces/organizations.interface'; +import { Organization } from '@app/common/interfaces/organizations.interface'; export interface Label { [key: string]: string; } -export type Status = 'DRAFT' | 'PUBLISHED' | 'INVALID' | 'DEPRECATED' | 'REMOVED' +export type Status = + | 'DRAFT' + | 'PUBLISHED' + | 'INVALID' + | 'DEPRECATED' + | 'REMOVED'; -export type Visibility = 'PRIVATE' | 'PUBLIC' +export type Visibility = 'PRIVATE' | 'PUBLIC'; -export type Type = 'CROSSWALK' | 'SCHEMA' +export type Type = 'CROSSWALK' | 'SCHEMA'; export interface ResultInfo { id: string; @@ -32,7 +37,7 @@ export interface MscrSearchResult { _source: ResultInfo; } -export type Facet = 'state' | 'type' | 'format' | 'organization' | 'sourceType' +export type Facet = 'state' | 'type' | 'format' | 'organization' | 'sourceType'; export interface Filter { label: string; @@ -71,14 +76,16 @@ export interface MscrSearchResultsX { skipped: number; }; hits: { - total:{ + total: { relation: string; value: number; }; - hits: [ // ToDo: CrosswalkResult interface extending Crosswalk interface? - { // ToDo: Update Crosswalk interface? - _index: string; // ToDo: SchemaResult interface extending Schema interface? - _id: string; // ToDo: Update Schema interface? + hits: [ + // ToDo: CrosswalkResult interface extending Crosswalk interface? + { + // ToDo: Update Crosswalk interface? + _index: string; // ToDo: SchemaResult interface extending Schema interface? + _id: string; // ToDo: Update Schema interface? source: { id: string; label: { @@ -92,7 +99,8 @@ export interface MscrSearchResultsX { contentModified: Date; type: string; prefix: string; - comment: { // ToDo: a Comment interface? + comment: { + // ToDo: a Comment interface? [key: string]: string; }; contributor: string[]; @@ -103,7 +111,8 @@ export interface MscrSearchResultsX { aggregationKey: string; revisionOf: string; numberOfRevisions: number; - revisions: [ // ToDo: a Revision interface + revisions: [ + // ToDo: a Revision interface { pid: string; created: number; @@ -118,7 +127,8 @@ export interface MscrSearchResultsX { } ]; }; - aggregations: { // ToDo: an Aggregation interface + aggregations: { + // ToDo: an Aggregation interface [key: string]: { buckets: [ { diff --git a/mscr-ui/src/common/utils/create-getserversideprops.ts b/mscr-ui/src/common/utils/create-getserversideprops.ts index f272b8bde..db78e02b9 100644 --- a/mscr-ui/src/common/utils/create-getserversideprops.ts +++ b/mscr-ui/src/common/utils/create-getserversideprops.ts @@ -79,6 +79,7 @@ export function createCommonGetServerSideProps< if (process.env.ENV_TYPE !== 'production') { store.dispatch(getFakeableUsers.initiate()); + console.log('getting fake user'); await Promise.all(store.dispatch(getFakeableRunningQueriesThunk())); } @@ -87,7 +88,7 @@ export function createCommonGetServerSideProps< reduxKey: 'fakeableUsers', functionKey: 'getFakeableUsers', }); - + console.log(fakeableUsers); // store.dispatch( // setAdminControls(process.env.ADMIN_CONTROLS_DISABLED === 'true') // ); diff --git a/mscr-ui/src/common/utils/hooks/use-url-state.tsx b/mscr-ui/src/common/utils/hooks/use-url-state.tsx index a7e65a5b8..fc4389d3b 100644 --- a/mscr-ui/src/common/utils/hooks/use-url-state.tsx +++ b/mscr-ui/src/common/utils/hooks/use-url-state.tsx @@ -61,9 +61,18 @@ export default function useUrlState(): UseURLStateResult { state: asStringArray(router.query.state, initialUrlState.state), type: asStringArray(router.query.type, initialUrlState.type), format: asStringArray(router.query.format, initialUrlState.format), - sourceType: asStringArray(router.query.sourceType, initialUrlState.sourceType), - sourceSchema: asStringArray(router.query.sourceSchema, initialUrlState.sourceSchema), - targetSchema: asStringArray(router.query.targetSchema, initialUrlState.targetSchema), + sourceType: asStringArray( + router.query.sourceType, + initialUrlState.sourceType + ), + sourceSchema: asStringArray( + router.query.sourceSchema, + initialUrlState.sourceSchema + ), + targetSchema: asStringArray( + router.query.targetSchema, + initialUrlState.targetSchema + ), page: asNumber(router.query.page, initialUrlState.page), lang: asString(router.query.lang, initialUrlState.lang), }; @@ -122,9 +131,12 @@ function buildUrlStatePatch(urlState: UrlState): Partial<UrlState> { if (!isInitial(urlState, 'state')) patch.state = urlState.state; if (!isInitial(urlState, 'type')) patch.type = urlState.type; if (!isInitial(urlState, 'format')) patch.format = urlState.format; - if (!isInitial(urlState, 'sourceType')) patch.sourceType = urlState.sourceType; - if (!isInitial(urlState, 'sourceSchema')) patch.sourceSchema = urlState.sourceSchema; - if (!isInitial(urlState, 'targetSchema')) patch.targetSchema = urlState.targetSchema; + if (!isInitial(urlState, 'sourceType')) + patch.sourceType = urlState.sourceType; + if (!isInitial(urlState, 'sourceSchema')) + patch.sourceSchema = urlState.sourceSchema; + if (!isInitial(urlState, 'targetSchema')) + patch.targetSchema = urlState.targetSchema; if (!isInitial(urlState, 'page')) patch.page = urlState.page; if (!isInitial(urlState, 'lang')) patch.lang = urlState.lang; return patch; diff --git a/mscr-ui/src/modules/crosswalk-form/index.tsx b/mscr-ui/src/modules/crosswalk-form/index.tsx index 8f78f817d..cd6738dde 100644 --- a/mscr-ui/src/modules/crosswalk-form/index.tsx +++ b/mscr-ui/src/modules/crosswalk-form/index.tsx @@ -22,7 +22,10 @@ import { import LanguageSelector from 'yti-common-ui/form/language-selector'; import { FormErrors } from './validate-form'; import { Status } from '@app/common/interfaces/status.interface'; -import { CrosswalkFormMockupType, CrosswalkFormType } from '@app/common/interfaces/crosswalk.interface'; +import { + CrosswalkFormMockupType, + CrosswalkFormType, +} from '@app/common/interfaces/crosswalk.interface'; import { FormUpdateErrors } from '../schema-form/validate-form-update'; import { translateFileUploadError } from '@app/common/utils/translation-helpers copy'; import FileDropArea from 'yti-common-ui/file-drop-area'; @@ -82,14 +85,14 @@ export default function RegisterCrosswalkForm({ return ( <ModelFormContainer> - <CrosswalkForm - formData={formData} - setFormData={setFormData} - userPosted={userPosted} - errors={userPosted ? errors : undefined}> - </CrosswalkForm> + <CrosswalkForm + formData={formData} + setFormData={setFormData} + userPosted={userPosted} + errors={userPosted ? errors : undefined} + ></CrosswalkForm> {renderCrosswalkFormat()} - + <FileDropArea setFileData={setFileData} setIsValid={setIsValid} @@ -113,8 +116,6 @@ export default function RegisterCrosswalkForm({ ); } - - function renderLanguages() { return ( <div> diff --git a/mscr-ui/src/modules/search-bar/index.tsx b/mscr-ui/src/modules/search-bar/index.tsx index 6a7e4eabd..26111d03c 100644 --- a/mscr-ui/src/modules/search-bar/index.tsx +++ b/mscr-ui/src/modules/search-bar/index.tsx @@ -1,13 +1,18 @@ -import {SearchInput} from 'suomifi-ui-components'; -import {useTranslation} from 'next-i18next'; -import useUrlState, {initialUrlState} from '@app/common/utils/hooks/use-url-state'; -import {useContext, useEffect, useState} from 'react'; -import {SEARCH_FIELD_PATTERN, TEXT_INPUT_MAX} from 'yti-common-ui/utils/constants'; -import {SearchContext} from '@app/common/components/search-context-provider'; +import { SearchInput } from 'suomifi-ui-components'; +import { useTranslation } from 'next-i18next'; +import useUrlState, { + initialUrlState, +} from '@app/common/utils/hooks/use-url-state'; +import { useContext, useEffect, useState } from 'react'; +import { + SEARCH_FIELD_PATTERN, + TEXT_INPUT_MAX, +} from 'yti-common-ui/utils/constants'; +import { SearchContext } from '@app/common/components/search-context-provider'; export default function SearchBar() { const { t } = useTranslation('common'); - const { isSearchActive, setIsSearchActive} = useContext(SearchContext); + const { isSearchActive, setIsSearchActive } = useContext(SearchContext); const { urlState, patchUrlState } = useUrlState(); const q = urlState.q; const [searchInputValue, setSearchInputValue] = useState<string>( @@ -27,11 +32,10 @@ export default function SearchBar() { } }, [q, setSearchInputValue, isSearchActive]); - return ( <> <SearchInput - labelText='' + labelText="" clearButtonLabel={t('search.bar.clear-button')} searchButtonLabel={t('search.bar.search-button')} value={searchInputValue ?? ''} @@ -45,7 +49,6 @@ export default function SearchBar() { maxLength={TEXT_INPUT_MAX} /> </> - ); function search(q?: string) { diff --git a/mscr-ui/src/modules/search-screen/index.tsx b/mscr-ui/src/modules/search-screen/index.tsx index bf3f56d30..4571dcfff 100644 --- a/mscr-ui/src/modules/search-screen/index.tsx +++ b/mscr-ui/src/modules/search-screen/index.tsx @@ -1,19 +1,26 @@ -import {FacetsWrapper, ResultsWrapper, SearchContainer, CloseButton} from '@app/modules/search-screen/search-screen.styles'; +import { + FacetsWrapper, + ResultsWrapper, + SearchContainer, + CloseButton, +} from '@app/modules/search-screen/search-screen.styles'; import SearchResult from '@app/common/components/search-result'; -import {useGetMscrSearchResultsQuery} from '@app/common/components/mscr-search/mscr-search.slice'; -import useUrlState, {initialUrlState} from '@app/common/utils/hooks/use-url-state'; -import {IconClose} from 'suomifi-icons'; -import {useContext} from 'react'; -import {SearchContext} from '@app/common/components/search-context-provider'; +import { useGetMscrSearchResultsQuery } from '@app/common/components/mscr-search/mscr-search.slice'; +import useUrlState, { + initialUrlState, +} from '@app/common/utils/hooks/use-url-state'; +import { IconClose } from 'suomifi-icons'; +import { useContext } from 'react'; +import { SearchContext } from '@app/common/components/search-context-provider'; import SearchFilterSet from '@app/common/components/search-filter-set'; -import {Bucket, Facet, Filter} from '@app/common/interfaces/search.interface'; -import {useTranslation} from 'next-i18next'; -import {Grid} from "@mui/material"; +import { Bucket, Facet, Filter } from '@app/common/interfaces/search.interface'; +import { useTranslation } from 'next-i18next'; +import { Grid } from '@mui/material'; export default function SearchScreen() { const { urlState, patchUrlState } = useUrlState(); const { t } = useTranslation('common'); - const {isSearchActive, setIsSearchActive} = useContext(SearchContext); + const { isSearchActive, setIsSearchActive } = useContext(SearchContext); const { data: mscrSearchResults, refetch: refetchMscrSearchResults } = useGetMscrSearchResultsQuery(urlState); @@ -28,27 +35,30 @@ export default function SearchScreen() { // Constructing filters - const makeFilter = (key: string, buckets: Bucket[]) : Filter => { - const filterKey : Facet = key.substring(7) as Facet; + const makeFilter = (key: string, buckets: Bucket[]): Filter => { + const filterKey: Facet = key.substring(7) as Facet; const filterLabel = t(filterKey); const options = buckets.map((bucket) => { return { label: bucket.label, key: bucket.key, - count: bucket.doc_count + count: bucket.doc_count, }; }); return { label: filterLabel, facet: filterKey, - options: options + options: options, }; }; - let filters : Filter[] = []; + let filters: Filter[] = []; if (mscrSearchResults) { Object.keys(mscrSearchResults.aggregations).forEach((key) => { - const newFilter : Filter = makeFilter(key, mscrSearchResults.aggregations[key].buckets); + const newFilter: Filter = makeFilter( + key, + mscrSearchResults.aggregations[key].buckets + ); filters = filters.concat(newFilter); }); } diff --git a/mscr-ui/src/modules/search-screen/search-screen.styles.tsx b/mscr-ui/src/modules/search-screen/search-screen.styles.tsx index 082dc7a05..e52ed2c74 100644 --- a/mscr-ui/src/modules/search-screen/search-screen.styles.tsx +++ b/mscr-ui/src/modules/search-screen/search-screen.styles.tsx @@ -1,5 +1,5 @@ import styled from 'styled-components'; -import {Block} from 'suomifi-ui-components'; +import { Block } from 'suomifi-ui-components'; export const SearchContainer = styled(Block)` height: 800px; diff --git a/mscr-ui/src/pages/[homepage]/content/index.tsx b/mscr-ui/src/pages/[homepage]/content/index.tsx index 79575ee26..78ee37b98 100644 --- a/mscr-ui/src/pages/[homepage]/content/index.tsx +++ b/mscr-ui/src/pages/[homepage]/content/index.tsx @@ -35,9 +35,9 @@ export default function IndexPage(props: IndexPageProps) { const router = useRouter(); function DisplayedComponent({ - slug, - user, - }: { + slug, + user, + }: { slug?: string; user?: MscrUser; }): React.ReactElement { diff --git a/mscr-ui/src/pages/index.tsx b/mscr-ui/src/pages/index.tsx index 989182de0..d692560fb 100644 --- a/mscr-ui/src/pages/index.tsx +++ b/mscr-ui/src/pages/index.tsx @@ -13,7 +13,9 @@ import { getServiceCategories, getRunningQueriesThunk as getServiceCategoriesRunningQueriesThunk, } from '@app/common/components/service-categories/service-categories.slice'; -import useUrlState, { initialUrlState } from '@app/common/utils/hooks/use-url-state'; +import useUrlState, { + initialUrlState, +} from '@app/common/utils/hooks/use-url-state'; import { getCount, getRunningQueriesThunk as getCountRunningQueriesThunk, @@ -41,7 +43,8 @@ export default function IndexPage(props: IndexPageProps) { title={t('mscr-title')} description={t('service-description')} /> - <h2>This page is the landing page</h2> + <div>{props}</div> + <h2>This page is the landing page for {props}</h2> </Layout> </CommonContextProvider> ); @@ -56,7 +59,7 @@ export const getServerSideProps = createCommonGetServerSideProps( if (query.q !== undefined) { urlState.q = Array.isArray(query.q) ? query.q[0] : query.q; } - console.log("server side props are "+ query); + console.log('server side props are ' + query); if (query.page !== undefined) { const pageValue = Array.isArray(query.page) @@ -72,9 +75,7 @@ export const getServerSideProps = createCommonGetServerSideProps( } if (query.type !== undefined) { - urlState.type = Array.isArray(query.type) - ? query.type - : [query.type]; + urlState.type = Array.isArray(query.type) ? query.type : [query.type]; } if (query.organization !== undefined) { diff --git a/mscr-ui/src/store/index.tsx b/mscr-ui/src/store/index.tsx index f2afaf1c3..499f83964 100644 --- a/mscr-ui/src/store/index.tsx +++ b/mscr-ui/src/store/index.tsx @@ -25,7 +25,7 @@ import { crosswalkApi, crosswalkSlice, } from '@app/common/components/crosswalk/crosswalk.slice'; -import {mscrSearchApi} from "@app/common/components/mscr-search/mscr-search.slice"; +import { mscrSearchApi } from '@app/common/components/mscr-search/mscr-search.slice'; // make Context from next-redux-wrapper compatible with next-iron-session export type NextIronContext = Context | (Context & { req: NextApiRequest }); @@ -71,7 +71,7 @@ export function makeStore(ctx: NextIronContext) { visualizationApi.middleware, fakeableUsersApi.middleware, importApi.middleware, - mscrSearchApi.middleware, + mscrSearchApi.middleware ), // Development tools should be available only in development environments From f2aa615cc1e613a2f3646452eaac88a807534829 Mon Sep 17 00:00:00 2001 From: rquazi <rumana.quazi@csc.fi> Date: Tue, 14 Nov 2023 22:42:25 +0200 Subject: [PATCH 02/15] file upload fix --- mscr-ui/README.md | 8 ++++ .../common/components/schema/schema.slice.tsx | 24 ++---------- .../update-with-file-modal/index.tsx | 3 ++ .../src/common/interfaces/format.interface.ts | 1 + .../src/common/interfaces/schema.interface.ts | 32 ++++++++-------- .../modules/schema-form/generate-payload.tsx | 19 +++++++--- mscr-ui/src/modules/schema-form/index.tsx | 37 ++++++++++++++----- .../modules/schema-form/schema-form-modal.tsx | 15 ++++++-- 8 files changed, 84 insertions(+), 55 deletions(-) create mode 100644 mscr-ui/src/common/interfaces/format.interface.ts diff --git a/mscr-ui/README.md b/mscr-ui/README.md index 5d74db97b..d3858975d 100644 --- a/mscr-ui/README.md +++ b/mscr-ui/README.md @@ -37,3 +37,11 @@ The `pages/api` directory is mapped to `/api/*`. Files in this directory are tre ## Troubleshooting and more documentation You can find more documentation in [docs](../docs). + + +curl -X 'PUT' \ + 'http://localhost:9004/datamodel-api/v2/schemaFull?metadata=%7Bmetadata%3A%7B%20%20%20%22namespace%22%3A%20%22http%3A%2F%2Ftest.com%22%2C%20%22%20%20%20%20%20%22format%22%3A%20%22JSONSCHEMA%22%2C%20%20%20%22status%22%3A%20%22INCOMPLETE%22%2C%20%20%20%22label%22%3A%20%7B%20%20%20%20%20%22en%22%3A%20%22string%22%20%20%20%7D%2C%20%20%20%22description%22%3A%20%7B%20%20%20%20%20%22en%22%3A%20%22string%22%20%20%20%7D%2C%20%20%20%22languages%22%3A%20%5B%20%20%20%20%20%22en%22%20%20%20%5D%2C%20%20%20%22organizations%22%3A%20%5B%227d3a3c00-5a6b-489b-a3ed-63bb58c26a63%22%5D%20%7D%7D' \ + -H 'accept: application/json' \ + -H 'Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI0Y2U3MDkzNy02ZmE0LTQ5YWYtYTIyOS1iNWYxMDMyOGFkYjgiLCJleHAiOjE3MTUzMzk5NjUsImlhdCI6MTY5OTYxNTE2NX0.oNDwK2Cv3C4LZ2bt8Z9F4druC58fTs_dXfbK3WSpYuW1gTK_ZplCvrBP8h6orZJbnW6fpk_I1rMuw7yFUhM2tA' \ + -H 'Content-Type: multipart/form-data' \ + -F 'file=@test_json_trimmed.json;type=application/json' \ No newline at end of file diff --git a/mscr-ui/src/common/components/schema/schema.slice.tsx b/mscr-ui/src/common/components/schema/schema.slice.tsx index 72c5edb7b..34ac21ed2 100644 --- a/mscr-ui/src/common/components/schema/schema.slice.tsx +++ b/mscr-ui/src/common/components/schema/schema.slice.tsx @@ -11,10 +11,7 @@ import { export const schemaApi = createApi({ reducerPath: 'schemaApi', - baseQuery: getDatamodelApiBaseQuery((headers) => ({ - ...headers, - 'content-type': 'multipart/form-data', - })), + baseQuery: getDatamodelApiBaseQuery(), tagTypes: ['schemaApi'], extractRehydrationInfo(action, { reducerPath }) { if (action.type === HYDRATE) { @@ -22,7 +19,7 @@ export const schemaApi = createApi({ } }, endpoints: (builder) => ({ - putSchema: builder.mutation<SchemaFormType, SchemaFormType>({ + putSchema: builder.mutation<Schema, Schema>({ query: (value) => ({ url: '/schema', method: 'PUT', @@ -42,20 +39,6 @@ export const schemaApi = createApi({ method: 'GET', }), }), - postSchema: builder.mutation< - string, - { - // Need to check How it works with our api - payload: Schema; - prefix: string; - } - >({ - query: (value) => ({ - url: `/schema/${value.prefix}`, - method: 'POST', - data: value.payload, - }), - }), deleteSchema: builder.mutation<string, string>({ query: (value) => ({ url: `/schema/${value}`, @@ -74,13 +57,12 @@ export const schemaApi = createApi({ export const { usePutSchemaMutation, useGetSchemaQuery, - usePostSchemaMutation, useDeleteSchemaMutation, useGetSchemasQuery, util: { getRunningQueriesThunk }, } = schemaApi; -export const { putSchema, getSchema, postSchema, deleteSchema, getSchemas } = +export const { putSchema, getSchema, deleteSchema, getSchemas } = schemaApi.endpoints; // Slice setup below diff --git a/mscr-ui/src/common/components/update-with-file-modal/index.tsx b/mscr-ui/src/common/components/update-with-file-modal/index.tsx index 7f1eb8db2..ee7c96e87 100644 --- a/mscr-ui/src/common/components/update-with-file-modal/index.tsx +++ b/mscr-ui/src/common/components/update-with-file-modal/index.tsx @@ -1,3 +1,5 @@ + +/**This will be used if uploading file from detail page */ import { translateFileUploadError } from '@app/common/utils/translation-helpers'; import { getDatamodelApiBaseQuery } from '@app/store/api-base-query'; import { useTranslation } from 'next-i18next'; @@ -73,6 +75,7 @@ export default function UpdateWithFileModal({ if (fileData) { const formData = new FormData(); formData.append('file', fileData); + console.log("in file modal"+ formData); //We need the file upload status to set the progress indication //setStartFileUpload(true); setUserPosted(true); diff --git a/mscr-ui/src/common/interfaces/format.interface.ts b/mscr-ui/src/common/interfaces/format.interface.ts new file mode 100644 index 000000000..d39e657da --- /dev/null +++ b/mscr-ui/src/common/interfaces/format.interface.ts @@ -0,0 +1 @@ +export type Format = 'JSONSCHEMA' | 'CSVSCHEMA'; \ No newline at end of file diff --git a/mscr-ui/src/common/interfaces/schema.interface.ts b/mscr-ui/src/common/interfaces/schema.interface.ts index 57e21cbab..fe092a250 100644 --- a/mscr-ui/src/common/interfaces/schema.interface.ts +++ b/mscr-ui/src/common/interfaces/schema.interface.ts @@ -1,23 +1,22 @@ export interface Schema { - onClick(): void; - onMouseEnter: any; - onMouseLeave: any; - pid: string; - format: string; - status: string; - label: { + namespace?: string; + pid?: string; + format?: string; + status?: string; + label?: { [key: string]: string; }; description: { [key: string]: string; }; - languages: string[]; + languages?: string[]; organizations: Organization[]; - filedata: File; - prefix: string; - revision: string; - visibilty: string; - created: string; + filedata?: File; + prefix?: string; + revision?: string; + visibilty?: string; + created?: string; + uri?: string; } export interface Organization { id: string; @@ -25,15 +24,18 @@ export interface Organization { label: { [key: string]: string }; } -export interface SchemaFormType { +export interface SchemaFormType{ + namespace?: string; contact?: boolean; serviceCategories?: any; pid?: string; - format: string; + format?: string; label?: { [key: string]: string }; languages: any; organizations: any; filedata?: any; description?: any; status?: any; + uri?: any; + } diff --git a/mscr-ui/src/modules/schema-form/generate-payload.tsx b/mscr-ui/src/modules/schema-form/generate-payload.tsx index 5250bbd2f..d0d01bca3 100644 --- a/mscr-ui/src/modules/schema-form/generate-payload.tsx +++ b/mscr-ui/src/modules/schema-form/generate-payload.tsx @@ -1,13 +1,16 @@ /* eslint-disable */ -import { SchemaFormType } from '@app/common/interfaces/schema.interface'; +import { Schema, SchemaFormType } from '@app/common/interfaces/schema.interface'; -// here we can create the schema payload -export default function generatePayload(data: SchemaFormType): SchemaFormType { - const SUOMI_FI_NAMESPACE = 'http://uri.suomi.fi/datamodel/ns/'; +// here we can create the schema payload +export default function generatePayload(data: SchemaFormType):Schema{ + + console.log(data.format); return { // id will be pid , during post no id + namespace: "http://test.com", + pid:"", description: data.languages .filter((l: { description: string }) => l.description !== '') .reduce( @@ -32,7 +35,11 @@ export default function generatePayload(data: SchemaFormType): SchemaFormType { organizations: data.organizations.map( (o: { uniqueItemId: any }) => o.uniqueItemId ), - status: 'DRAFT', - format: 'JSONSCHEMA', + status: data.status, + format: data.format, + uri:data.uri + }; + + } diff --git a/mscr-ui/src/modules/schema-form/index.tsx b/mscr-ui/src/modules/schema-form/index.tsx index 930c9fdfc..cf4970baa 100644 --- a/mscr-ui/src/modules/schema-form/index.tsx +++ b/mscr-ui/src/modules/schema-form/index.tsx @@ -25,6 +25,9 @@ import { Paragraph } from 'suomifi-ui-components'; import UpdateWithFileModal from '@app/common/components/update-with-file-modal'; import { translateFileUploadError } from '@app/common/utils/translation-helpers copy'; import FileDropArea from 'yti-common-ui/file-drop-area'; +import FileUpload from '@app/common/components/update-with-file-modal/file-upload'; +import { ImportDescriptionBlock } from '@app/common/components/update-with-file-modal/update-with-file-modal.styles'; +import { Format } from '@app/common/interfaces/format.interface'; interface SchemaFormProps { formData: SchemaFormType; @@ -72,12 +75,6 @@ export default function SchemaForm({ <Paragraph style={{ marginBottom: '30px' }}> {'or Upload a document'} </Paragraph> - <FileDropArea - setFileData={setFileData} - setIsValid={setIsValid} - validFileTypes={['csv', 'json']} - translateFileUploadError={translateFileUploadError} - /> {renderSchemaFormat()} {renderLanguages()} @@ -91,8 +88,24 @@ export default function SchemaForm({ function renderSchemaFormat() { return ( - <div> - <TextInput labelText={'Format'} /> + <div style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}> + <Dropdown + labelText={'Format'} + defaultValue={'JSONSCHEMA'} + onChange={(e) => + setFormData({ + ...formData, + format: e, + }) + } + > + <DropdownItem value={'JSONSCHEMA'}> + {'JSON'} + </DropdownItem> + <DropdownItem value={'CSVSCHEMA'}> + {'CSV'} + </DropdownItem> + </Dropdown> </div> ); } @@ -100,7 +113,13 @@ export default function SchemaForm({ function renderURI() { return ( <div> - <TextInput labelText={'Add URI'} /> + <TextInput labelText={'Add URI'} + onChange={(e) => + setFormData({ + ...formData, + uri:e, + }) + }/> </div> ); } diff --git a/mscr-ui/src/modules/schema-form/schema-form-modal.tsx b/mscr-ui/src/modules/schema-form/schema-form-modal.tsx index 809ee8db2..d0ecc4145 100644 --- a/mscr-ui/src/modules/schema-form/schema-form-modal.tsx +++ b/mscr-ui/src/modules/schema-form/schema-form-modal.tsx @@ -77,14 +77,20 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { return; } + console.log(formData); + + const errors = validateForm(formData); setErrors(errors); - + + if (Object.values(errors).includes(true)) { return; } - + const payload = generatePayload(formData); + console.log(payload); + // Here formdata should also contain the file, need modification putSchema(payload); }; @@ -93,8 +99,9 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { if (!userPosted) { return; } - const errors = validateForm(formData); - setErrors(errors); + //const errors = validateForm(formData); + //setErrors(errors); + //console.log(errors); }, [userPosted, formData]); // Need to add action type create_schema From 006a575b5a307240531ce9467bc31eee7f83325a Mon Sep 17 00:00:00 2001 From: rquazi <rumana.quazi@csc.fi> Date: Wed, 15 Nov 2023 11:41:03 +0200 Subject: [PATCH 03/15] fixing lint errors --- mscr-ui/next.config.js | 2 +- .../crosswalk-edit/schema-mockup.tsx | 4 +-- .../common/components/schema/schema.slice.tsx | 2 +- .../common/components/search-result/index.tsx | 2 +- .../common/components/treeview-test/index.tsx | 2 +- .../joint-listing-accordion/index.tsx | 11 ++------ .../src/modules/create-crosswalk/index.tsx | 25 +++---------------- mscr-ui/src/pages/schema/[...pid].tsx | 4 +-- 8 files changed, 13 insertions(+), 39 deletions(-) diff --git a/mscr-ui/next.config.js b/mscr-ui/next.config.js index eff81355d..c98a90a94 100644 --- a/mscr-ui/next.config.js +++ b/mscr-ui/next.config.js @@ -9,7 +9,7 @@ module.exports = () => { reactStrictMode: true, eslint: { dirs: ['src'], - ignoreDuringBuilds: true, + //ignoreDuringBuilds: true, }, typescript: { // !! WARN !! diff --git a/mscr-ui/src/common/components/crosswalk-edit/schema-mockup.tsx b/mscr-ui/src/common/components/crosswalk-edit/schema-mockup.tsx index 65f320b29..d299aef84 100644 --- a/mscr-ui/src/common/components/crosswalk-edit/schema-mockup.tsx +++ b/mscr-ui/src/common/components/crosswalk-edit/schema-mockup.tsx @@ -311,7 +311,7 @@ export default function MockupSchemaLoader(emptyTemplate: boolean) { open_access: { title: 'Open Access', description: - "Indicate whether the record's files are publicly accessible or not. In case of restricted access the uploaded files will only be accessible by the record's owner and the community administrators. Please note that the record's metadata is always publicly accessible. ", + 'Indicate whether the record files are publicly accessible or not. In case of restricted access the uploaded files will only be accessible by the record owner and the community administrators. Please note that the record metadata is always publicly accessible. ', type: 'boolean', }, embargo_date: { @@ -401,7 +401,7 @@ export default function MockupSchemaLoader(emptyTemplate: boolean) { }, }; - let allTreeNodes: RenderTree[] = []; + const allTreeNodes: RenderTree[] = []; let currentTreeNode: RenderTree = { isMappable: '', diff --git a/mscr-ui/src/common/components/schema/schema.slice.tsx b/mscr-ui/src/common/components/schema/schema.slice.tsx index 72c5edb7b..3ffa8ff70 100644 --- a/mscr-ui/src/common/components/schema/schema.slice.tsx +++ b/mscr-ui/src/common/components/schema/schema.slice.tsx @@ -64,7 +64,7 @@ export const schemaApi = createApi({ }), getSchemas: builder.query<Schema[], string>({ query: (value) => ({ - url: `/schemas`, + url: '/schemas', method: 'GET', }), }), diff --git a/mscr-ui/src/common/components/search-result/index.tsx b/mscr-ui/src/common/components/search-result/index.tsx index 28779b440..4a66b2778 100644 --- a/mscr-ui/src/common/components/search-result/index.tsx +++ b/mscr-ui/src/common/components/search-result/index.tsx @@ -40,7 +40,7 @@ export default function SearchResult({ hit }: { hit: MscrSearchResult }) { <h4> This is a search result of type {result.type} with id {result.id} </h4> - <p>Where are names?? Here's a placeholder for a description</p> + <p>Where are names?? Here is a placeholder for a description</p> {/* patchedResult && Object.keys(patchedResult.description).map((key) => <p key={key}>{patchedResult.description[key]}</p>) */} {Object.keys(result.label).map((key) => ( <ChipWrapper key={key}> diff --git a/mscr-ui/src/common/components/treeview-test/index.tsx b/mscr-ui/src/common/components/treeview-test/index.tsx index c2c30f24b..8b125a1ca 100644 --- a/mscr-ui/src/common/components/treeview-test/index.tsx +++ b/mscr-ui/src/common/components/treeview-test/index.tsx @@ -382,7 +382,7 @@ export default function TreeviewTest({ pid, user }: TreeViewTestProps) { }, })); - function saveCroswalk() {} + //function saveCroswalk() {} function loadCroswalk() { fetchCrosswalkData('organizations').then((data) => { diff --git a/mscr-ui/src/common/components/treeview-test/joint-listing-accordion/index.tsx b/mscr-ui/src/common/components/treeview-test/joint-listing-accordion/index.tsx index 6d5df2f78..99dd2ab43 100644 --- a/mscr-ui/src/common/components/treeview-test/joint-listing-accordion/index.tsx +++ b/mscr-ui/src/common/components/treeview-test/joint-listing-accordion/index.tsx @@ -7,22 +7,15 @@ import TableBody from '@mui/material/TableBody'; import TableContainer from '@mui/material/TableContainer'; import TableHead from '@mui/material/TableHead'; import TableRow from '@mui/material/TableRow'; -import Typography from '@mui/material/Typography'; import Paper from '@mui/material/Paper'; import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp'; -import { useBreakpoints } from '../../../../../../common-ui/components/media-query'; import { styled } from '@mui/material'; import TableCell, { tableCellClasses } from '@mui/material/TableCell'; import LinkOffIcon from '@mui/icons-material/LinkOff'; -import AddLinkIcon from '@mui/icons-material/AddLink'; -import { Button as Sbutton, Textarea, TextInput } from 'suomifi-ui-components'; +import { Textarea } from 'suomifi-ui-components'; import Button from '@mui/material/Button'; -import { - CrosswalkConnection, - CrosswalkConnectionNew, - RenderTree, -} from '@app/common/interfaces/crosswalk-connection.interface'; +import { CrosswalkConnectionNew } from '@app/common/interfaces/crosswalk-connection.interface'; const crosswalkConnectionInit = { source: '', diff --git a/mscr-ui/src/modules/create-crosswalk/index.tsx b/mscr-ui/src/modules/create-crosswalk/index.tsx index b701cdccb..1f442a76f 100644 --- a/mscr-ui/src/modules/create-crosswalk/index.tsx +++ b/mscr-ui/src/modules/create-crosswalk/index.tsx @@ -1,29 +1,12 @@ -import { useGetOrganizationsQuery } from '@app/common/components/organizations/organizations.slice'; import { useGetServiceCategoriesQuery } from '@app/common/components/service-categories/service-categories.slice'; -import getOrganizations from '@app/common/utils/get-organizations'; -import getServiceCategories from '@app/common/utils/get-service-categories'; import { useTranslation } from 'next-i18next'; -import { useMemo, useState } from 'react'; -import { - Dropdown, - DropdownItem, - Label, - RadioButton, - RadioButtonGroup, - Text, - Textarea, - TextInput, -} from 'suomifi-ui-components'; +import { Textarea, TextInput } from 'suomifi-ui-components'; import { ModelFormContainer } from './crosswalk-form.styles'; import { FormErrors } from './validate-form'; -import { - CrosswalkFormMockupType, - CrosswalkFormType, -} from '@app/common/interfaces/crosswalk.interface'; +import { CrosswalkFormMockupType } from '@app/common/interfaces/crosswalk.interface'; import { FormUpdateErrors } from '../schema-form/validate-form-update'; import * as React from 'react'; -import { SingleSelect, SingleSelectData } from 'suomifi-ui-components'; -import { MultiSelect } from 'suomifi-ui-components'; +import { SingleSelect } from 'suomifi-ui-components'; import Box from '@mui/material/Box'; interface CrosswalkFormProps { @@ -45,7 +28,7 @@ export default function CrosswalkForm({ errors, editMode, }: CrosswalkFormProps) { - let selectedValues = React.useMemo( + const selectedValues = React.useMemo( () => allValues.filter((v) => v.selected), [allValues] ); diff --git a/mscr-ui/src/pages/schema/[...pid].tsx b/mscr-ui/src/pages/schema/[...pid].tsx index c9f2eb8da..b49ecb8f9 100644 --- a/mscr-ui/src/pages/schema/[...pid].tsx +++ b/mscr-ui/src/pages/schema/[...pid].tsx @@ -20,9 +20,7 @@ import { useGetSchemaQuery } from '@app/common/components/schema/schema.slice'; import { Schema } from '@app/common/interfaces/schema.interface'; import UpdateWithFileModal from '@app/common/components/update-with-file-modal'; import Separator from 'yti-common-ui/components/separator'; -import InlineListBlock from '@app/common/components/inline-list-block'; import { BasicBlock, BasicBlockExtraWrapper } from 'yti-common-ui/block'; -import FormattedDate from 'yti-common-ui/formatted-date'; import { MscrUser } from '@app/common/interfaces/mscr-user.interface'; interface IndexPageProps extends CommonContextState { @@ -34,7 +32,7 @@ interface IndexPageProps extends CommonContextState { export default function SchemaPage(props: IndexPageProps) { const { query, asPath } = useRouter(); const schemaId = (query?.pid ?? '') as string; - let items: Schema[] = []; + const items: Schema[] = []; const { data, isLoading, isSuccess, isError, error } = useGetSchemaQuery(schemaId); From 1d8af82b2a9dbe161640a658f877354433bce711 Mon Sep 17 00:00:00 2001 From: rquazi <rumana.quazi@csc.fi> Date: Fri, 17 Nov 2023 13:48:03 +0200 Subject: [PATCH 04/15] Working copy of schemaFull Endpoint --- .../common/components/schema/schema.slice.tsx | 18 +- .../src/common/interfaces/status.interface.ts | 7 +- .../modules/schema-form/generate-payload.tsx | 15 +- mscr-ui/src/modules/schema-form/index.tsx | 60 ++--- .../modules/schema-form/schema-form-modal.tsx | 208 +++++++++--------- 5 files changed, 148 insertions(+), 160 deletions(-) diff --git a/mscr-ui/src/common/components/schema/schema.slice.tsx b/mscr-ui/src/common/components/schema/schema.slice.tsx index 4cb191b35..6811a1043 100644 --- a/mscr-ui/src/common/components/schema/schema.slice.tsx +++ b/mscr-ui/src/common/components/schema/schema.slice.tsx @@ -8,6 +8,7 @@ import { Schema, SchemaFormType, } from '@app/common/interfaces/schema.interface'; +import { AnyNsRecord } from 'dns'; export const schemaApi = createApi({ reducerPath: 'schemaApi', @@ -19,18 +20,24 @@ export const schemaApi = createApi({ } }, endpoints: (builder) => ({ - putSchema: builder.mutation<Schema, Schema>({ + putSchema: builder.mutation<any, any>({ query: (value) => ({ url: '/schema', method: 'PUT', data: value, + headers: { + 'content-Type': 'application/json;' + }, }), }), - putSchemaFull: builder.mutation<SchemaFormType, SchemaFormType>({ - query: (value) => ({ + putSchemaFull: builder.mutation<any, FormData>({ + query: (file) => ({ url: '/schemaFull', method: 'PUT', - data: value, + data: file, + headers: { + 'content-Type': 'multipart/form-data;' + }, }), }), getSchema: builder.query<Schema, string>({ @@ -59,10 +66,11 @@ export const { useGetSchemaQuery, useDeleteSchemaMutation, useGetSchemasQuery, + usePutSchemaFullMutation, util: { getRunningQueriesThunk }, } = schemaApi; -export const { putSchema, getSchema, deleteSchema, getSchemas } = +export const { putSchema, getSchema, deleteSchema, getSchemas,putSchemaFull } = schemaApi.endpoints; // Slice setup below diff --git a/mscr-ui/src/common/interfaces/status.interface.ts b/mscr-ui/src/common/interfaces/status.interface.ts index 20c6734a2..5627fb847 100644 --- a/mscr-ui/src/common/interfaces/status.interface.ts +++ b/mscr-ui/src/common/interfaces/status.interface.ts @@ -1,7 +1,4 @@ export type Status = | 'DRAFT' - | 'INCOMPLETE' - | 'INVALID' - | 'RETIRED' - | 'SUPERSEDED' - | 'VALID'; + | 'PUBLISHED' + | 'DEPRECATED'; diff --git a/mscr-ui/src/modules/schema-form/generate-payload.tsx b/mscr-ui/src/modules/schema-form/generate-payload.tsx index d0d01bca3..eb59d2ca6 100644 --- a/mscr-ui/src/modules/schema-form/generate-payload.tsx +++ b/mscr-ui/src/modules/schema-form/generate-payload.tsx @@ -1,16 +1,14 @@ /* eslint-disable */ -import { Schema, SchemaFormType } from '@app/common/interfaces/schema.interface'; +import { SchemaFormType } from '@app/common/interfaces/schema.interface'; // here we can create the schema payload -export default function generatePayload(data: SchemaFormType):Schema{ +export default function generatePayload(data: SchemaFormType):any{ console.log(data.format); return { - // id will be pid , during post no id namespace: "http://test.com", - pid:"", description: data.languages .filter((l: { description: string }) => l.description !== '') .reduce( @@ -36,9 +34,12 @@ export default function generatePayload(data: SchemaFormType):Schema{ (o: { uniqueItemId: any }) => o.uniqueItemId ), status: data.status, - format: data.format, - uri:data.uri - + format:data.format, + uri: data.uri, + state: 'DRAFT', + versionLabel:'1' + + }; diff --git a/mscr-ui/src/modules/schema-form/index.tsx b/mscr-ui/src/modules/schema-form/index.tsx index cf4970baa..7c48814ea 100644 --- a/mscr-ui/src/modules/schema-form/index.tsx +++ b/mscr-ui/src/modules/schema-form/index.tsx @@ -51,10 +51,7 @@ export default function SchemaForm({ i18n.language ); const { data: organizationsData } = useGetOrganizationsQuery(i18n.language); - const [fileData, setFileData] = useState<File | null>(); - const [fileType, setFileType] = useState<'csv' | 'json' | null>(); - const [isValid, setIsValid] = useState(false); - + const organizations = useMemo(() => { if (!organizationsData) { return []; @@ -71,16 +68,9 @@ export default function SchemaForm({ // Creating the actual schema Input form return ( <ModelFormContainer> - {renderURI()} - <Paragraph style={{ marginBottom: '30px' }}> - {'or Upload a document'} - </Paragraph> {renderSchemaFormat()} {renderLanguages()} - <BlockContainer>{!editMode && renderContributors()}</BlockContainer> - - <Separator isLarge /> {renderStaus()} {editMode && renderContributors()} </ModelFormContainer> @@ -102,7 +92,7 @@ export default function SchemaForm({ <DropdownItem value={'JSONSCHEMA'}> {'JSON'} </DropdownItem> - <DropdownItem value={'CSVSCHEMA'}> + <DropdownItem value={'CSV'}> {'CSV'} </DropdownItem> </Dropdown> @@ -110,28 +100,15 @@ export default function SchemaForm({ ); } - function renderURI() { - return ( - <div> - <TextInput labelText={'Add URI'} - onChange={(e) => - setFormData({ - ...formData, - uri:e, - }) - }/> - </div> - ); - } + function renderLanguages() { return ( <div> <LanguageSelector items={formData.languages} - labelText={t('information-description-languages')} - hintText={t('information-description-languages-hint-text')} - visualPlaceholder={t('select-information-description-languages')} + labelText={'Schema information-description-languages'} + visualPlaceholder={'select schema information-description-languages'} isWide={true} setLanguages={(e) => setFormData({ @@ -141,9 +118,9 @@ export default function SchemaForm({ } userPosted={userPosted} translations={{ - textInput: t('language-input-text'), - textDescription: t('description'), - optionalText: t('optional'), + textInput:'Name(required)', + textDescription:'Description', + optionalText: '' }} allowItemAddition={false} ariaChipActionLabel={''} @@ -166,7 +143,7 @@ export default function SchemaForm({ <div style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}> <Dropdown labelText={'Status'} - defaultValue={formData.status ?? ''} + defaultValue={'DRAFT'} onChange={(e) => setFormData({ ...formData, @@ -175,19 +152,13 @@ export default function SchemaForm({ } > <DropdownItem value={'DRAFT'}> - {t('statuses.draft', { ns: 'common' })} - </DropdownItem> - <DropdownItem value={'VALID'}> - {t('statuses.valid', { ns: 'common' })} - </DropdownItem> - <DropdownItem value={'RETIRED'}> - {t('statuses.retired', { ns: 'common' })} + {'DRAFT'} </DropdownItem> - <DropdownItem value={'INVALID'}> - {t('statuses.invalid', { ns: 'common' })} + <DropdownItem value={'PUBLISHED'}> + {'PUBLISHED'} </DropdownItem> - <DropdownItem value={'INCOMPETE'}> - {t('statuses.incomplete', { ns: 'common' })} + <DropdownItem value={'DEPRECATED'}> + {'DEPRECATED'} </DropdownItem> </Dropdown> </div> @@ -198,8 +169,7 @@ export default function SchemaForm({ return ( <WideMultiSelect chipListVisible={true} - labelText={t('contributors')} - hintText={t('contributors-hint-text')} + labelText={'contributors'} visualPlaceholder={t('select-contributors')} removeAllButtonLabel={t('clear-all-selections')} allowItemAddition={false} diff --git a/mscr-ui/src/modules/schema-form/schema-form-modal.tsx b/mscr-ui/src/modules/schema-form/schema-form-modal.tsx index d0ecc4145..95be47d79 100644 --- a/mscr-ui/src/modules/schema-form/schema-form-modal.tsx +++ b/mscr-ui/src/modules/schema-form/schema-form-modal.tsx @@ -10,10 +10,10 @@ import { Paragraph, } from 'suomifi-ui-components'; import { useBreakpoints } from 'yti-common-ui/media-query'; -import ModelForm from '.'; import { FormErrors, validateForm } from './validate-form'; import FormFooterAlert from 'yti-common-ui/form-footer-alert'; import { + translateFileUploadError, translateLanguage, translateModelFormErrors, } from '@app/common/utils/translation-helpers'; @@ -23,8 +23,9 @@ import getApiError from '@app/common/utils/getApiErrors'; import { useRouter } from 'next/router'; import HasPermission from '@app/common/utils/has-permission'; import { useInitialSchemaForm } from '@app/common/utils/hooks/use-initial-schema-form'; -import { usePutSchemaMutation } from '@app/common/components/schema/schema.slice'; +import { usePutSchemaFullMutation, usePutSchemaMutation } from '@app/common/components/schema/schema.slice'; import SchemaForm from '.'; +import FileDropArea from 'yti-common-ui/file-drop-area'; interface SchemaFormModalProps { refetch: () => void; @@ -41,13 +42,15 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { const { isSmall } = useBreakpoints(); const router = useRouter(); const [visible, setVisible] = useState(false); + const [isValid, setIsValid] = useState(false); const [schemaFormInitialData] = useState(useInitialSchemaForm()); const [formData, setFormData] = useState(schemaFormInitialData); + const [fileData, setFileData] = useState<File | null>(); const [errors, setErrors] = useState<FormErrors>(); const [userPosted, setUserPosted] = useState(false); const [getAuthenticatedUser, authenticateUser] = useGetAuthenticatedUserMutMutation(); - const [putSchema, result] = usePutSchemaMutation(); + const [putSchemaFull, result] = usePutSchemaFullMutation(); const handleOpen = () => { setVisible(true); @@ -58,6 +61,7 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { setVisible(false); setUserPosted(false); setFormData(schemaFormInitialData); + setFileData(null); }, [schemaFormInitialData]); useEffect(() => { @@ -76,115 +80,123 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { if (!formData) { return; } - console.log(formData); - const errors = validateForm(formData); setErrors(errors); - if (Object.values(errors).includes(true)) { return; } - + + console.log(formData); const payload = generatePayload(formData); - console.log(payload); + + const schemaFormData = new FormData(); + schemaFormData.append('metadata', JSON.stringify(payload)); + if (fileData) { + console.log(fileData); + schemaFormData.append('file', fileData); + putSchemaFull(schemaFormData); + } else { + //Register Schema with no filedata + } + + - // Here formdata should also contain the file, need modification - putSchema(payload); }; - + useEffect(() => { - if (!userPosted) { - return; + if (!userPosted) { + return; + } + //const errors = validateForm(formData); + //setErrors(errors); + //console.log(errors); + }, [userPosted, formData]); + + // Need to add action type create_schema + if (!HasPermission({ actions: ['CREATE_SCHEMA'] })) { + return null; } - //const errors = validateForm(formData); - //setErrors(errors); - //console.log(errors); - }, [userPosted, formData]); - - // Need to add action type create_schema - if (!HasPermission({ actions: ['CREATE_SCHEMA'] })) { - return null; - } - return ( - <> - <Button - icon="plus" - style={{ height: 'min-content' }} - onClick={() => handleOpen()} - > - {t('register-schema')} - </Button> - - <Modal - appElementId="__next" - visible={visible} - onEscKeyDown={() => handleClose()} - variant={isSmall ? 'smallScreen' : 'default'} - > - <ModalContent> - <ModalTitle>{t('register-schema')}</ModalTitle> - <Paragraph style={{ marginBottom: '30px' }}> - { - 'Provide a URI reference to the content in XSD, SKOS or RDF metadata schema format' - } - </Paragraph> - <SchemaForm - formData={formData} - setFormData={setFormData} - userPosted={userPosted} - disabled={authenticateUser.data && authenticateUser.data.anonymous} - errors={userPosted ? errors : undefined} - /> - </ModalContent> - <ModalFooter> - {authenticateUser.data && authenticateUser.data.anonymous && ( - <InlineAlert status="error" role="alert" id="unauthenticated-alert"> - {t('error-unauthenticated')} - </InlineAlert> - )} - {userPosted && ( - <FormFooterAlert - labelText={t('missing-information-title')} - alerts={getErrors(errors)} + return ( + <> + <Button + icon="plus" + style={{ height: 'min-content' }} + onClick={() => handleOpen()} + > + {t('register-schema')} + </Button> + + <Modal + appElementId="__next" + visible={visible} + onEscKeyDown={() => handleClose()} + variant={isSmall ? 'smallScreen' : 'default'} + > + <ModalContent> + <ModalTitle>{t('register-schema')}</ModalTitle> + <SchemaForm + formData={formData} + setFormData={setFormData} + userPosted={userPosted} + disabled={authenticateUser.data && authenticateUser.data.anonymous} + errors={userPosted ? errors : undefined} /> - )} - - <Button onClick={() => handleSubmit()}>{t('register-schema')}</Button> - <Button variant="secondary" onClick={() => handleClose()}> - {t('cancel')} - </Button> - </ModalFooter> - </Modal> - </> - ); - - function getErrors(errors?: FormErrors): string[] | undefined { - if (!errors) { - return []; - } - - const langsWithError = Object.entries(errors) - .filter(([_, value]) => Array.isArray(value)) - ?.flatMap(([key, value]) => - (value as string[]).map( - (lang) => - `${translateModelFormErrors(key, t)} ${translateLanguage(lang, t)}` - ) - ); - - const otherErrors = Object.entries(errors) - .filter(([_, value]) => value && !Array.isArray(value)) - ?.map(([key, _]) => translateModelFormErrors(key, t)); - - if (result.isError) { - const errorMessage = getApiError(result.error); - return [...langsWithError, ...otherErrors, errorMessage]; + <FileDropArea + setFileData={setFileData} + setIsValid={setIsValid} + validFileTypes={['json','csv']} + translateFileUploadError={translateFileUploadError} + /> + </ModalContent> + <ModalFooter> + {authenticateUser.data && authenticateUser.data.anonymous && ( + <InlineAlert status="error" role="alert" id="unauthenticated-alert"> + {t('error-unauthenticated')} + </InlineAlert> + )} + {userPosted && ( + <FormFooterAlert + labelText={'Something went wrong'} + alerts={getErrors(errors)} + /> + )} + + <Button onClick={() => handleSubmit()}>{t('register-schema')}</Button> + <Button variant="secondary" onClick={() => handleClose()}> + {t('cancel')} + </Button> + </ModalFooter> + </Modal> + </> + ); + + function getErrors(errors?: FormErrors): string[] | undefined { + if (!errors) { + return []; + } + + const langsWithError = Object.entries(errors) + .filter(([_, value]) => Array.isArray(value)) + ?.flatMap(([key, value]) => + (value as string[]).map( + (lang) => + `${translateModelFormErrors(key, t)} ${translateLanguage(lang, t)}` + ) + ); + + const otherErrors = Object.entries(errors) + .filter(([_, value]) => value && !Array.isArray(value)) + ?.map(([key, _]) => translateModelFormErrors(key, t)); + + if (result.isError) { + const errorMessage = getApiError(result.error); + return [...langsWithError, ...otherErrors, errorMessage]; + } + + return [...langsWithError, ...otherErrors]; } - - return [...langsWithError, ...otherErrors]; } -} From c8a502657bf17325763c221995b096797562bea2 Mon Sep 17 00:00:00 2001 From: rquazi <rumana.quazi@csc.fi> Date: Fri, 17 Nov 2023 15:10:07 +0200 Subject: [PATCH 05/15] getting schema data after creation --- .../src/common/interfaces/schema.interface.ts | 3 +- .../modules/schema-form/schema-form-modal.tsx | 231 ++++++++++-------- mscr-ui/src/pages/schema/[...pid].tsx | 73 +++++- 3 files changed, 204 insertions(+), 103 deletions(-) diff --git a/mscr-ui/src/common/interfaces/schema.interface.ts b/mscr-ui/src/common/interfaces/schema.interface.ts index fe092a250..f4ceb4f75 100644 --- a/mscr-ui/src/common/interfaces/schema.interface.ts +++ b/mscr-ui/src/common/interfaces/schema.interface.ts @@ -14,9 +14,10 @@ export interface Schema { filedata?: File; prefix?: string; revision?: string; - visibilty?: string; + visibility?: string; created?: string; uri?: string; + versionLabel?: string; } export interface Organization { id: string; diff --git a/mscr-ui/src/modules/schema-form/schema-form-modal.tsx b/mscr-ui/src/modules/schema-form/schema-form-modal.tsx index 95be47d79..46bd61737 100644 --- a/mscr-ui/src/modules/schema-form/schema-form-modal.tsx +++ b/mscr-ui/src/modules/schema-form/schema-form-modal.tsx @@ -8,6 +8,7 @@ import { ModalFooter, ModalTitle, Paragraph, + Text, } from 'suomifi-ui-components'; import { useBreakpoints } from 'yti-common-ui/media-query'; import { FormErrors, validateForm } from './validate-form'; @@ -23,9 +24,15 @@ import getApiError from '@app/common/utils/getApiErrors'; import { useRouter } from 'next/router'; import HasPermission from '@app/common/utils/has-permission'; import { useInitialSchemaForm } from '@app/common/utils/hooks/use-initial-schema-form'; -import { usePutSchemaFullMutation, usePutSchemaMutation } from '@app/common/components/schema/schema.slice'; +import { + putSchema, + usePutSchemaFullMutation, + usePutSchemaMutation, +} from '@app/common/components/schema/schema.slice'; import SchemaForm from '.'; import FileDropArea from 'yti-common-ui/file-drop-area'; +import { TextSnippet } from '@mui/icons-material'; +import Separator from 'yti-common-ui/separator'; interface SchemaFormModalProps { refetch: () => void; @@ -50,7 +57,8 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { const [userPosted, setUserPosted] = useState(false); const [getAuthenticatedUser, authenticateUser] = useGetAuthenticatedUserMutMutation(); - const [putSchemaFull, result] = usePutSchemaFullMutation(); + const [putSchemaFull, resultSchemaFull] = usePutSchemaFullMutation(); + const [putSchema, resultSchema] = usePutSchemaMutation(); const handleOpen = () => { setVisible(true); @@ -65,15 +73,23 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { }, [schemaFormInitialData]); useEffect(() => { - if (userPosted && result.isSuccess) { + if (userPosted && resultSchema.isSuccess||resultSchema.isSuccess) { //Get the pid from the result - refetch(); handleClose(); + if (resultSchema && resultSchema.data.pid) { + router.push(`/schema/${resultSchema.data.pid}`); + } + //otherwise schema was created with file + else if (resultSchemaFull && resultSchemaFull.data.pid) { + router.push(`/schema/${resultSchema.data.pid}`); + } + // After post route to saved schema get by PID // Later we should show the created schema in the list - alert('Schema Creation is Successful'); + + } - }, [result, refetch, userPosted, handleClose, router, formData]); + }, [resultSchema,resultSchema, refetch, userPosted, handleClose, router, formData]); const handleSubmit = () => { setUserPosted(true); @@ -84,119 +100,134 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { const errors = validateForm(formData); setErrors(errors); - + if (Object.values(errors).includes(true)) { return; } - + console.log(formData); const payload = generatePayload(formData); - + const schemaFormData = new FormData(); schemaFormData.append('metadata', JSON.stringify(payload)); if (fileData) { console.log(fileData); schemaFormData.append('file', fileData); putSchemaFull(schemaFormData); - } else { + } else{ //Register Schema with no filedata + putSchema(payload); } - - - }; - + useEffect(() => { - if (!userPosted) { - return; - } - //const errors = validateForm(formData); - //setErrors(errors); - //console.log(errors); - }, [userPosted, formData]); - - // Need to add action type create_schema - if (!HasPermission({ actions: ['CREATE_SCHEMA'] })) { - return null; + if (!userPosted) { + return; } + const errors = validateForm(formData); + setErrors(errors); + //console.log(errors); + }, [userPosted, formData]); - return ( - <> - <Button - icon="plus" - style={{ height: 'min-content' }} - onClick={() => handleOpen()} - > - {t('register-schema')} - </Button> - - <Modal - appElementId="__next" - visible={visible} - onEscKeyDown={() => handleClose()} - variant={isSmall ? 'smallScreen' : 'default'} - > - <ModalContent> - <ModalTitle>{t('register-schema')}</ModalTitle> - <SchemaForm - formData={formData} - setFormData={setFormData} - userPosted={userPosted} - disabled={authenticateUser.data && authenticateUser.data.anonymous} - errors={userPosted ? errors : undefined} - /> - <FileDropArea - setFileData={setFileData} - setIsValid={setIsValid} - validFileTypes={['json','csv']} - translateFileUploadError={translateFileUploadError} + // Need to add action type create_schema + if (!HasPermission({ actions: ['CREATE_SCHEMA'] })) { + return null; + } + + return ( + <> + <Button + icon="plus" + style={{ height: 'min-content' }} + onClick={() => handleOpen()} + > + {t('register-schema')} + </Button> + + <Modal + appElementId="__next" + visible={visible} + onEscKeyDown={() => handleClose()} + variant={isSmall ? 'smallScreen' : 'default'} + > + <ModalContent> + <ModalTitle>{t('register-schema')}</ModalTitle> + <SchemaForm + formData={formData} + setFormData={setFormData} + userPosted={userPosted} + disabled={authenticateUser.data && authenticateUser.data.anonymous} + errors={userPosted ? errors : undefined} + /> + <Separator></Separator> + <Text> + {'Upload a Schema File. You can upload file also later'} + </Text> + <FileDropArea + setFileData={setFileData} + setIsValid={setIsValid} + validFileTypes={['json', 'csv']} + translateFileUploadError={translateFileUploadError} + /> + <Separator isLarge></Separator> + <Text> + { + 'All Contents will be registered as draft. You can choose to publish content later' + } + </Text> + </ModalContent> + <ModalFooter> + {authenticateUser.data && authenticateUser.data.anonymous && ( + <InlineAlert status="error" role="alert" id="unauthenticated-alert"> + {t('error-unauthenticated')} + </InlineAlert> + )} + {userPosted && ( + <FormFooterAlert + labelText={'Something went wrong'} + alerts={getErrors(errors)} /> - </ModalContent> - <ModalFooter> - {authenticateUser.data && authenticateUser.data.anonymous && ( - <InlineAlert status="error" role="alert" id="unauthenticated-alert"> - {t('error-unauthenticated')} - </InlineAlert> - )} - {userPosted && ( - <FormFooterAlert - labelText={'Something went wrong'} - alerts={getErrors(errors)} - /> - )} - - <Button onClick={() => handleSubmit()}>{t('register-schema')}</Button> - <Button variant="secondary" onClick={() => handleClose()}> - {t('cancel')} - </Button> - </ModalFooter> - </Modal> - </> - ); - - function getErrors(errors?: FormErrors): string[] | undefined { - if (!errors) { - return []; - } + )} + + <Button onClick={() => handleSubmit()}>{t('register-schema')}</Button> + <Button variant="secondary" onClick={() => handleClose()}> + {t('cancel')} + </Button> + </ModalFooter> + </Modal> + </> + ); + + function getErrors(errors?: FormErrors): string[] | undefined { + if (!errors) { + return []; + } - const langsWithError = Object.entries(errors) - .filter(([_, value]) => Array.isArray(value)) - ?.flatMap(([key, value]) => - (value as string[]).map( - (lang) => - `${translateModelFormErrors(key, t)} ${translateLanguage(lang, t)}` - ) - ); - - const otherErrors = Object.entries(errors) - .filter(([_, value]) => value && !Array.isArray(value)) - ?.map(([key, _]) => translateModelFormErrors(key, t)); - - if (result.isError) { - const errorMessage = getApiError(result.error); - return [...langsWithError, ...otherErrors, errorMessage]; - } + console.log(errors); + + const langsWithError = Object.entries(errors) + .filter(([_, value]) => Array.isArray(value)) + ?.flatMap(([key, value]) => + (value as string[]).map( + (lang) => + `${translateModelFormErrors(key, t)} ${translateLanguage(lang, t)}` + ) + ); - return [...langsWithError, ...otherErrors]; + const otherErrors = Object.entries(errors) + .filter(([_, value]) => value && !Array.isArray(value)) + ?.map(([key, _]) => translateModelFormErrors(key, t)); + + if (resultSchema.isError) { + const errorMessage = getApiError(resultSchema.error); + return [...langsWithError, ...otherErrors, errorMessage]; } + + if (resultSchemaFull.isError) { + const errorMessage = getApiError(resultSchema.error); + return [...langsWithError, ...otherErrors, errorMessage]; + } + + return [...langsWithError, ...otherErrors]; } +} diff --git a/mscr-ui/src/pages/schema/[...pid].tsx b/mscr-ui/src/pages/schema/[...pid].tsx index b49ecb8f9..5d2ff44ee 100644 --- a/mscr-ui/src/pages/schema/[...pid].tsx +++ b/mscr-ui/src/pages/schema/[...pid].tsx @@ -29,6 +29,67 @@ interface IndexPageProps extends CommonContextState { schemaId: string; } +// Example schema metadata +/* +{ + "created": "2023-11-17T12:52:59.337Z", + "modified": "2023-11-17T12:52:59.337Z", + "modifier": { + "id": "4ce70937-6fa4-49af-a229-b5f10328adb8", + "name": "fake user" + }, + "creator": { + "id": "4ce70937-6fa4-49af-a229-b5f10328adb8", + "name": "fake user" + }, + "type": null, + "prefix": null, + "status": "DRAFT", + "label": { + "en": "duwdu gwdf wugedwu" + }, + "description": { + "en": "wuey bwuey wyue" + }, + "languages": [ + "en" + ], + "organizations": [ + { + "id": "7d3a3c00-5a6b-489b-a3ed-63bb58c26a63", + "label": { + "fi": "Yhteentoimivuusalustan yllapito", + "sv": "Utvecklare av interoperabilitetsplattform", + "en": "Interoperability platform developers" + }, + "parentOrganization": null + } + ], + "groups": [], + "internalNamespaces": [], + "externalNamespaces": [], + "terminologies": [], + "codeLists": [], + "contact": null, + "documentation": {}, + "state": "DRAFT", + "visibility": "PUBLIC", + "format": "JSONSCHEMA", + "namespace": "http://test.com", + "versionLabel": "1", + "revisionOf": null, + "aggregationKey": "urn:IAMNOTAPID:e68ce802-38a0-4c6f-ba2d-41ad11561080", + "hasRevisions": null, + "revisions": null, + "variants": null, + "variants2": null, + "owner": [ + "7d3a3c00-5a6b-489b-a3ed-63bb58c26a63" + ], + "fileMetadata": [], + "pid": "urn:IAMNOTAPID:e68ce802-38a0-4c6f-ba2d-41ad11561080" +} +*/ export default function SchemaPage(props: IndexPageProps) { const { query, asPath } = useRouter(); const schemaId = (query?.pid ?? '') as string; @@ -37,6 +98,7 @@ export default function SchemaPage(props: IndexPageProps) { const { data, isLoading, isSuccess, isError, error } = useGetSchemaQuery(schemaId); + function renderSchema() { let schemaContent; if (isLoading) { @@ -54,13 +116,20 @@ export default function SchemaPage(props: IndexPageProps) { <div className="card"> <div className="card-body"> <BasicBlock title={'Schema Name'}> - {data.label.additionalProp1} + {data.label?.en} + </BasicBlock> + <BasicBlock title={'Schema Name'}> + {data.description?.en} </BasicBlock> <BasicBlock title={'Schema created'}>{data.created}</BasicBlock> <BasicBlock title={'Schema Visibilty'}> - {data.visibilty} + {data.visibility} + </BasicBlock> + <BasicBlock title={'Schema Version'}> + {data.versionLabel} </BasicBlock> <BasicBlock title={'Schema Status'}>{data.status}</BasicBlock> + <BasicBlock title={'Schema format'}>{data.format}</BasicBlock> </div> </div> <Separator /> From c42c0af68e61926de1d7a4d9fd834858d3c41980 Mon Sep 17 00:00:00 2001 From: rquazi <rumana.quazi@csc.fi> Date: Fri, 17 Nov 2023 15:11:33 +0200 Subject: [PATCH 06/15] formatting fix --- mscr-ui/README.md | 11 ++++--- .../common/components/schema/schema.slice.tsx | 6 ++-- .../update-with-file-modal/index.tsx | 3 +- .../src/common/interfaces/format.interface.ts | 2 +- .../src/common/interfaces/schema.interface.ts | 3 +- .../src/common/interfaces/status.interface.ts | 5 +--- .../modules/schema-form/generate-payload.tsx | 14 +++------ mscr-ui/src/modules/schema-form/index.tsx | 30 ++++++------------- .../modules/schema-form/schema-form-modal.tsx | 22 ++++++++------ mscr-ui/src/pages/schema/[...pid].tsx | 5 +--- 10 files changed, 39 insertions(+), 62 deletions(-) diff --git a/mscr-ui/README.md b/mscr-ui/README.md index d3858975d..9ae898d0c 100644 --- a/mscr-ui/README.md +++ b/mscr-ui/README.md @@ -38,10 +38,9 @@ The `pages/api` directory is mapped to `/api/*`. Files in this directory are tre You can find more documentation in [docs](../docs). - curl -X 'PUT' \ - 'http://localhost:9004/datamodel-api/v2/schemaFull?metadata=%7Bmetadata%3A%7B%20%20%20%22namespace%22%3A%20%22http%3A%2F%2Ftest.com%22%2C%20%22%20%20%20%20%20%22format%22%3A%20%22JSONSCHEMA%22%2C%20%20%20%22status%22%3A%20%22INCOMPLETE%22%2C%20%20%20%22label%22%3A%20%7B%20%20%20%20%20%22en%22%3A%20%22string%22%20%20%20%7D%2C%20%20%20%22description%22%3A%20%7B%20%20%20%20%20%22en%22%3A%20%22string%22%20%20%20%7D%2C%20%20%20%22languages%22%3A%20%5B%20%20%20%20%20%22en%22%20%20%20%5D%2C%20%20%20%22organizations%22%3A%20%5B%227d3a3c00-5a6b-489b-a3ed-63bb58c26a63%22%5D%20%7D%7D' \ - -H 'accept: application/json' \ - -H 'Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI0Y2U3MDkzNy02ZmE0LTQ5YWYtYTIyOS1iNWYxMDMyOGFkYjgiLCJleHAiOjE3MTUzMzk5NjUsImlhdCI6MTY5OTYxNTE2NX0.oNDwK2Cv3C4LZ2bt8Z9F4druC58fTs_dXfbK3WSpYuW1gTK_ZplCvrBP8h6orZJbnW6fpk_I1rMuw7yFUhM2tA' \ - -H 'Content-Type: multipart/form-data' \ - -F 'file=@test_json_trimmed.json;type=application/json' \ No newline at end of file + 'http://localhost:9004/datamodel-api/v2/schemaFull?metadata=%7Bmetadata%3A%7B%20%20%20%22namespace%22%3A%20%22http%3A%2F%2Ftest.com%22%2C%20%22%20%20%20%20%20%22format%22%3A%20%22JSONSCHEMA%22%2C%20%20%20%22status%22%3A%20%22INCOMPLETE%22%2C%20%20%20%22label%22%3A%20%7B%20%20%20%20%20%22en%22%3A%20%22string%22%20%20%20%7D%2C%20%20%20%22description%22%3A%20%7B%20%20%20%20%20%22en%22%3A%20%22string%22%20%20%20%7D%2C%20%20%20%22languages%22%3A%20%5B%20%20%20%20%20%22en%22%20%20%20%5D%2C%20%20%20%22organizations%22%3A%20%5B%227d3a3c00-5a6b-489b-a3ed-63bb58c26a63%22%5D%20%7D%7D' \ + -H 'accept: application/json' \ + -H 'Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI0Y2U3MDkzNy02ZmE0LTQ5YWYtYTIyOS1iNWYxMDMyOGFkYjgiLCJleHAiOjE3MTUzMzk5NjUsImlhdCI6MTY5OTYxNTE2NX0.oNDwK2Cv3C4LZ2bt8Z9F4druC58fTs_dXfbK3WSpYuW1gTK_ZplCvrBP8h6orZJbnW6fpk_I1rMuw7yFUhM2tA' \ + -H 'Content-Type: multipart/form-data' \ + -F 'file=@test_json_trimmed.json;type=application/json' diff --git a/mscr-ui/src/common/components/schema/schema.slice.tsx b/mscr-ui/src/common/components/schema/schema.slice.tsx index 6811a1043..42a8f7cb5 100644 --- a/mscr-ui/src/common/components/schema/schema.slice.tsx +++ b/mscr-ui/src/common/components/schema/schema.slice.tsx @@ -26,7 +26,7 @@ export const schemaApi = createApi({ method: 'PUT', data: value, headers: { - 'content-Type': 'application/json;' + 'content-Type': 'application/json;', }, }), }), @@ -36,7 +36,7 @@ export const schemaApi = createApi({ method: 'PUT', data: file, headers: { - 'content-Type': 'multipart/form-data;' + 'content-Type': 'multipart/form-data;', }, }), }), @@ -70,7 +70,7 @@ export const { util: { getRunningQueriesThunk }, } = schemaApi; -export const { putSchema, getSchema, deleteSchema, getSchemas,putSchemaFull } = +export const { putSchema, getSchema, deleteSchema, getSchemas, putSchemaFull } = schemaApi.endpoints; // Slice setup below diff --git a/mscr-ui/src/common/components/update-with-file-modal/index.tsx b/mscr-ui/src/common/components/update-with-file-modal/index.tsx index ee7c96e87..5b32c6eab 100644 --- a/mscr-ui/src/common/components/update-with-file-modal/index.tsx +++ b/mscr-ui/src/common/components/update-with-file-modal/index.tsx @@ -1,4 +1,3 @@ - /**This will be used if uploading file from detail page */ import { translateFileUploadError } from '@app/common/utils/translation-helpers'; import { getDatamodelApiBaseQuery } from '@app/store/api-base-query'; @@ -75,7 +74,7 @@ export default function UpdateWithFileModal({ if (fileData) { const formData = new FormData(); formData.append('file', fileData); - console.log("in file modal"+ formData); + console.log('in file modal' + formData); //We need the file upload status to set the progress indication //setStartFileUpload(true); setUserPosted(true); diff --git a/mscr-ui/src/common/interfaces/format.interface.ts b/mscr-ui/src/common/interfaces/format.interface.ts index d39e657da..7cd3bd4a2 100644 --- a/mscr-ui/src/common/interfaces/format.interface.ts +++ b/mscr-ui/src/common/interfaces/format.interface.ts @@ -1 +1 @@ -export type Format = 'JSONSCHEMA' | 'CSVSCHEMA'; \ No newline at end of file +export type Format = 'JSONSCHEMA' | 'CSVSCHEMA'; diff --git a/mscr-ui/src/common/interfaces/schema.interface.ts b/mscr-ui/src/common/interfaces/schema.interface.ts index f4ceb4f75..58bdfee01 100644 --- a/mscr-ui/src/common/interfaces/schema.interface.ts +++ b/mscr-ui/src/common/interfaces/schema.interface.ts @@ -25,7 +25,7 @@ export interface Organization { label: { [key: string]: string }; } -export interface SchemaFormType{ +export interface SchemaFormType { namespace?: string; contact?: boolean; serviceCategories?: any; @@ -38,5 +38,4 @@ export interface SchemaFormType{ description?: any; status?: any; uri?: any; - } diff --git a/mscr-ui/src/common/interfaces/status.interface.ts b/mscr-ui/src/common/interfaces/status.interface.ts index 5627fb847..499a2bbe3 100644 --- a/mscr-ui/src/common/interfaces/status.interface.ts +++ b/mscr-ui/src/common/interfaces/status.interface.ts @@ -1,4 +1 @@ -export type Status = - | 'DRAFT' - | 'PUBLISHED' - | 'DEPRECATED'; +export type Status = 'DRAFT' | 'PUBLISHED' | 'DEPRECATED'; diff --git a/mscr-ui/src/modules/schema-form/generate-payload.tsx b/mscr-ui/src/modules/schema-form/generate-payload.tsx index eb59d2ca6..e87785468 100644 --- a/mscr-ui/src/modules/schema-form/generate-payload.tsx +++ b/mscr-ui/src/modules/schema-form/generate-payload.tsx @@ -1,14 +1,12 @@ /* eslint-disable */ import { SchemaFormType } from '@app/common/interfaces/schema.interface'; - // here we can create the schema payload -export default function generatePayload(data: SchemaFormType):any{ - +export default function generatePayload(data: SchemaFormType): any { console.log(data.format); return { - namespace: "http://test.com", + namespace: 'http://test.com', description: data.languages .filter((l: { description: string }) => l.description !== '') .reduce( @@ -34,13 +32,9 @@ export default function generatePayload(data: SchemaFormType):any{ (o: { uniqueItemId: any }) => o.uniqueItemId ), status: data.status, - format:data.format, + format: data.format, uri: data.uri, state: 'DRAFT', - versionLabel:'1' - - + versionLabel: '1', }; - - } diff --git a/mscr-ui/src/modules/schema-form/index.tsx b/mscr-ui/src/modules/schema-form/index.tsx index 7c48814ea..75f24d5ad 100644 --- a/mscr-ui/src/modules/schema-form/index.tsx +++ b/mscr-ui/src/modules/schema-form/index.tsx @@ -51,7 +51,7 @@ export default function SchemaForm({ i18n.language ); const { data: organizationsData } = useGetOrganizationsQuery(i18n.language); - + const organizations = useMemo(() => { if (!organizationsData) { return []; @@ -89,19 +89,13 @@ export default function SchemaForm({ }) } > - <DropdownItem value={'JSONSCHEMA'}> - {'JSON'} - </DropdownItem> - <DropdownItem value={'CSV'}> - {'CSV'} - </DropdownItem> + <DropdownItem value={'JSONSCHEMA'}>{'JSON'}</DropdownItem> + <DropdownItem value={'CSV'}>{'CSV'}</DropdownItem> </Dropdown> </div> ); } - - function renderLanguages() { return ( <div> @@ -118,9 +112,9 @@ export default function SchemaForm({ } userPosted={userPosted} translations={{ - textInput:'Name(required)', - textDescription:'Description', - optionalText: '' + textInput: 'Name(required)', + textDescription: 'Description', + optionalText: '', }} allowItemAddition={false} ariaChipActionLabel={''} @@ -151,15 +145,9 @@ export default function SchemaForm({ }) } > - <DropdownItem value={'DRAFT'}> - {'DRAFT'} - </DropdownItem> - <DropdownItem value={'PUBLISHED'}> - {'PUBLISHED'} - </DropdownItem> - <DropdownItem value={'DEPRECATED'}> - {'DEPRECATED'} - </DropdownItem> + <DropdownItem value={'DRAFT'}>{'DRAFT'}</DropdownItem> + <DropdownItem value={'PUBLISHED'}>{'PUBLISHED'}</DropdownItem> + <DropdownItem value={'DEPRECATED'}>{'DEPRECATED'}</DropdownItem> </Dropdown> </div> ); diff --git a/mscr-ui/src/modules/schema-form/schema-form-modal.tsx b/mscr-ui/src/modules/schema-form/schema-form-modal.tsx index 46bd61737..90d180f95 100644 --- a/mscr-ui/src/modules/schema-form/schema-form-modal.tsx +++ b/mscr-ui/src/modules/schema-form/schema-form-modal.tsx @@ -73,7 +73,7 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { }, [schemaFormInitialData]); useEffect(() => { - if (userPosted && resultSchema.isSuccess||resultSchema.isSuccess) { + if ((userPosted && resultSchema.isSuccess) || resultSchema.isSuccess) { //Get the pid from the result handleClose(); if (resultSchema && resultSchema.data.pid) { @@ -83,13 +83,19 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { else if (resultSchemaFull && resultSchemaFull.data.pid) { router.push(`/schema/${resultSchema.data.pid}`); } - + // After post route to saved schema get by PID // Later we should show the created schema in the list - - } - }, [resultSchema,resultSchema, refetch, userPosted, handleClose, router, formData]); + }, [ + resultSchema, + resultSchema, + refetch, + userPosted, + handleClose, + router, + formData, + ]); const handleSubmit = () => { setUserPosted(true); @@ -114,7 +120,7 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { console.log(fileData); schemaFormData.append('file', fileData); putSchemaFull(schemaFormData); - } else{ + } else { //Register Schema with no filedata putSchema(payload); } @@ -160,9 +166,7 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { errors={userPosted ? errors : undefined} /> <Separator></Separator> - <Text> - {'Upload a Schema File. You can upload file also later'} - </Text> + <Text>{'Upload a Schema File. You can upload file also later'}</Text> <FileDropArea setFileData={setFileData} setIsValid={setIsValid} diff --git a/mscr-ui/src/pages/schema/[...pid].tsx b/mscr-ui/src/pages/schema/[...pid].tsx index 5d2ff44ee..aed7c8b3a 100644 --- a/mscr-ui/src/pages/schema/[...pid].tsx +++ b/mscr-ui/src/pages/schema/[...pid].tsx @@ -98,7 +98,6 @@ export default function SchemaPage(props: IndexPageProps) { const { data, isLoading, isSuccess, isError, error } = useGetSchemaQuery(schemaId); - function renderSchema() { let schemaContent; if (isLoading) { @@ -115,9 +114,7 @@ export default function SchemaPage(props: IndexPageProps) { <div className="col-lg-12 mb-3 "> <div className="card"> <div className="card-body"> - <BasicBlock title={'Schema Name'}> - {data.label?.en} - </BasicBlock> + <BasicBlock title={'Schema Name'}>{data.label?.en}</BasicBlock> <BasicBlock title={'Schema Name'}> {data.description?.en} </BasicBlock> From 4696fe29b0d23f45dcc0c3ecd16e85c3f670cddd Mon Sep 17 00:00:00 2001 From: rquazi <rumana.quazi@csc.fi> Date: Thu, 23 Nov 2023 10:19:23 +0200 Subject: [PATCH 07/15] Schema registration only with file --- .../modules/schema-form/schema-form-modal.tsx | 41 +++++-------------- .../src/modules/schema-form/validate-form.tsx | 9 +++- mscr-ui/src/modules/search-screen/index.tsx | 19 +++++---- 3 files changed, 30 insertions(+), 39 deletions(-) diff --git a/mscr-ui/src/modules/schema-form/schema-form-modal.tsx b/mscr-ui/src/modules/schema-form/schema-form-modal.tsx index 90d180f95..2d10cb34a 100644 --- a/mscr-ui/src/modules/schema-form/schema-form-modal.tsx +++ b/mscr-ui/src/modules/schema-form/schema-form-modal.tsx @@ -58,7 +58,6 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { const [getAuthenticatedUser, authenticateUser] = useGetAuthenticatedUserMutMutation(); const [putSchemaFull, resultSchemaFull] = usePutSchemaFullMutation(); - const [putSchema, resultSchema] = usePutSchemaMutation(); const handleOpen = () => { setVisible(true); @@ -73,37 +72,23 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { }, [schemaFormInitialData]); useEffect(() => { - if ((userPosted && resultSchema.isSuccess) || resultSchema.isSuccess) { + if (userPosted && resultSchemaFull.isSuccess) { //Get the pid from the result handleClose(); - if (resultSchema && resultSchema.data.pid) { - router.push(`/schema/${resultSchema.data.pid}`); - } - //otherwise schema was created with file - else if (resultSchemaFull && resultSchemaFull.data.pid) { - router.push(`/schema/${resultSchema.data.pid}`); + if (resultSchemaFull && resultSchemaFull.data.pid) { + router.push(`/schema/${resultSchemaFull.data.pid}`); } // After post route to saved schema get by PID // Later we should show the created schema in the list } - }, [ - resultSchema, - resultSchema, - refetch, - userPosted, - handleClose, - router, - formData, - ]); + }, [resultSchemaFull, refetch, userPosted, handleClose, router, formData]); const handleSubmit = () => { setUserPosted(true); if (!formData) { return; } - console.log(formData); - const errors = validateForm(formData); setErrors(errors); @@ -111,18 +96,15 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { return; } - console.log(formData); const payload = generatePayload(formData); const schemaFormData = new FormData(); schemaFormData.append('metadata', JSON.stringify(payload)); if (fileData) { - console.log(fileData); schemaFormData.append('file', fileData); putSchemaFull(schemaFormData); } else { - //Register Schema with no filedata - putSchema(payload); + return; } }; @@ -166,7 +148,11 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { errors={userPosted ? errors : undefined} /> <Separator></Separator> - <Text>{'Upload a Schema File. You can upload file also later'}</Text> + <Text> + { + 'Upload a Schema File. You must upload a schema file to register schema' + } + </Text> <FileDropArea setFileData={setFileData} setIsValid={setIsValid} @@ -222,13 +208,8 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { .filter(([_, value]) => value && !Array.isArray(value)) ?.map(([key, _]) => translateModelFormErrors(key, t)); - if (resultSchema.isError) { - const errorMessage = getApiError(resultSchema.error); - return [...langsWithError, ...otherErrors, errorMessage]; - } - if (resultSchemaFull.isError) { - const errorMessage = getApiError(resultSchema.error); + const errorMessage = getApiError(resultSchemaFull.error); return [...langsWithError, ...otherErrors, errorMessage]; } diff --git a/mscr-ui/src/modules/schema-form/validate-form.tsx b/mscr-ui/src/modules/schema-form/validate-form.tsx index bcefc999f..e89517aaf 100644 --- a/mscr-ui/src/modules/schema-form/validate-form.tsx +++ b/mscr-ui/src/modules/schema-form/validate-form.tsx @@ -7,15 +7,18 @@ export interface FormErrors { prefix: boolean; serviceCategories: boolean; organizations: boolean; + fileData: boolean; } -export function validateForm(data: SchemaFormType) { +export function validateForm(data: SchemaFormType, fileData: File) { + console.log(FormData); const errors: FormErrors = { languageAmount: false, titleAmount: [], prefix: false, serviceCategories: false, organizations: false, + fileData: false, }; const selectedLanguages = data.languages.filter( @@ -49,5 +52,9 @@ export function validateForm(data: SchemaFormType) { errors.organizations = true; } + if (!fileData) { + errors.fileData = true; + } + return errors; } diff --git a/mscr-ui/src/modules/search-screen/index.tsx b/mscr-ui/src/modules/search-screen/index.tsx index 4b2de5d8c..34dfcfd4f 100644 --- a/mscr-ui/src/modules/search-screen/index.tsx +++ b/mscr-ui/src/modules/search-screen/index.tsx @@ -13,17 +13,18 @@ import { IconClose } from 'suomifi-icons'; import { useContext } from 'react'; import { SearchContext } from '@app/common/components/search-context-provider'; import SearchFilterSet from '@app/common/components/search-filter-set'; -import {Bucket, Facet, Filter} from '@app/common/interfaces/search.interface'; -import {useTranslation} from 'next-i18next'; -import {Grid} from '@mui/material'; +import { Bucket, Facet, Filter } from '@app/common/interfaces/search.interface'; +import { useTranslation } from 'next-i18next'; +import { Grid } from '@mui/material'; export default function SearchScreen() { const { urlState, patchUrlState } = useUrlState(); const { t } = useTranslation('common'); const { setIsSearchActive } = useContext(SearchContext); - const { data: mscrSearchResults } = - useGetMscrSearchResultsQuery(urlState); - const foundHits = mscrSearchResults ? mscrSearchResults.hits.hits.length !== 0 : false; + const { data: mscrSearchResults } = useGetMscrSearchResultsQuery(urlState); + const foundHits = mscrSearchResults + ? mscrSearchResults.hits.hits.length !== 0 + : false; const handleClose = () => { setIsSearchActive(false); @@ -53,7 +54,7 @@ export default function SearchScreen() { }; }; - let filters : Filter[] = []; + let filters: Filter[] = []; if (mscrSearchResults?.aggregations) { Object.keys(mscrSearchResults.aggregations).forEach((key) => { const newFilter: Filter = makeFilter( @@ -70,7 +71,9 @@ export default function SearchScreen() { <Grid item xs={2}> <FacetsWrapper> {/* Groups of facets for different contexts, made with search-filter-set */} - {filters.length > 0 && <SearchFilterSet title={t('in-all-mscr')} filters={filters}/>} + {filters.length > 0 && ( + <SearchFilterSet title={t('in-all-mscr')} filters={filters} /> + )} </FacetsWrapper> </Grid> <Grid item xs={8}> From f0abcbaa0e0201789fb0a5cb7015e69526273302 Mon Sep 17 00:00:00 2001 From: rquazi <rumana.quazi@csc.fi> Date: Thu, 23 Nov 2023 10:22:26 +0200 Subject: [PATCH 08/15] fix type error --- .../src/common/utils/translation-helpers.ts | 1 + .../modules/schema-form/schema-form-modal.tsx | 20 ++++++++++++------- .../src/modules/schema-form/validate-form.tsx | 5 ++++- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/mscr-ui/src/common/utils/translation-helpers.ts b/mscr-ui/src/common/utils/translation-helpers.ts index 3e409766a..2fe81a53a 100644 --- a/mscr-ui/src/common/utils/translation-helpers.ts +++ b/mscr-ui/src/common/utils/translation-helpers.ts @@ -288,6 +288,7 @@ export function translateFileUploadError( t: TFunction ) { switch (error) { + case 'upload-error': return t('file-upload-error.upload-error', { ns: 'admin' }); case 'incorrect-file-type': diff --git a/mscr-ui/src/modules/schema-form/schema-form-modal.tsx b/mscr-ui/src/modules/schema-form/schema-form-modal.tsx index 2d10cb34a..04adb1770 100644 --- a/mscr-ui/src/modules/schema-form/schema-form-modal.tsx +++ b/mscr-ui/src/modules/schema-form/schema-form-modal.tsx @@ -58,6 +58,7 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { const [getAuthenticatedUser, authenticateUser] = useGetAuthenticatedUserMutMutation(); const [putSchemaFull, resultSchemaFull] = usePutSchemaFullMutation(); + const handleOpen = () => { setVisible(true); @@ -82,14 +83,21 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { // After post route to saved schema get by PID // Later we should show the created schema in the list } - }, [resultSchemaFull, refetch, userPosted, handleClose, router, formData]); + }, [ + resultSchemaFull, + refetch, + userPosted, + handleClose, + router, + formData, + ]); const handleSubmit = () => { setUserPosted(true); if (!formData) { return; } - const errors = validateForm(formData); + const errors = validateForm(formData,fileData); setErrors(errors); if (Object.values(errors).includes(true)) { @@ -148,11 +156,7 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { errors={userPosted ? errors : undefined} /> <Separator></Separator> - <Text> - { - 'Upload a Schema File. You must upload a schema file to register schema' - } - </Text> + <Text>{'Upload a Schema File. You must upload a schema file to register schema'}</Text> <FileDropArea setFileData={setFileData} setIsValid={setIsValid} @@ -208,6 +212,8 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { .filter(([_, value]) => value && !Array.isArray(value)) ?.map(([key, _]) => translateModelFormErrors(key, t)); + + if (resultSchemaFull.isError) { const errorMessage = getApiError(resultSchemaFull.error); return [...langsWithError, ...otherErrors, errorMessage]; diff --git a/mscr-ui/src/modules/schema-form/validate-form.tsx b/mscr-ui/src/modules/schema-form/validate-form.tsx index e89517aaf..8016d4f21 100644 --- a/mscr-ui/src/modules/schema-form/validate-form.tsx +++ b/mscr-ui/src/modules/schema-form/validate-form.tsx @@ -1,5 +1,7 @@ import { SchemaFormType } from '@app/common/interfaces/schema.interface'; + + // Not yet modified according to mscr validation errors export interface FormErrors { languageAmount: boolean; @@ -10,7 +12,8 @@ export interface FormErrors { fileData: boolean; } -export function validateForm(data: SchemaFormType, fileData: File) { +export function validateForm(data: SchemaFormType, fileData: File | null| undefined) { + console.log(FormData); const errors: FormErrors = { languageAmount: false, From 31e358ba666589a51878bf016acd4fbb348aff55 Mon Sep 17 00:00:00 2001 From: rquazi <rumana.quazi@csc.fi> Date: Thu, 23 Nov 2023 15:24:44 +0200 Subject: [PATCH 09/15] more lint fix --- datamodel-ui/src/pages/_document.tsx | 16 ++++++++++------ .../common/utils/create-getserversideprops.ts | 3 ++- mscr-ui/src/pages/[homepage]/index.tsx | 2 +- mscr-ui/src/pages/_document.tsx | 16 ++++++++++------ mscr-ui/src/pages/index.tsx | 3 +-- mscr-ui/src/pages/schema/[...pid].tsx | 4 ++-- 6 files changed, 26 insertions(+), 18 deletions(-) diff --git a/datamodel-ui/src/pages/_document.tsx b/datamodel-ui/src/pages/_document.tsx index dc039661f..988f098c3 100644 --- a/datamodel-ui/src/pages/_document.tsx +++ b/datamodel-ui/src/pages/_document.tsx @@ -1,19 +1,23 @@ -import Document, { DocumentContext } from 'next/document'; +import Document, { DocumentContext, DocumentInitialProps } from 'next/document'; import { ServerStyleSheet } from 'styled-components'; -// https://github.com/msreekm/nextjs-material-ui-styled-components-boilerplate/blob/master/pages/_document.js +//Fixing the custom render page error, https://nextjs.org/docs/pages/building-your-application/routing/custom-document export default class MyDocument extends Document { - static async getInitialProps(ctx: DocumentContext) { + static async getInitialProps( + ctx: DocumentContext + ): Promise<DocumentInitialProps> { const sheet = new ServerStyleSheet(); const originalRenderPage = ctx.renderPage; try { + // Run the React rendering logic synchronously ctx.renderPage = () => originalRenderPage({ - enhanceApp: (App) => (props) => - sheet.collectStyles(<App {...props} />), + // Useful for wrapping the whole react tree + enhanceApp: (App) => App, + // Useful for wrapping in a per-page basis + enhanceComponent: (Component) => Component, }); - const initialProps = await ctx.defaultGetInitialProps(ctx); return { ...initialProps, diff --git a/mscr-ui/src/common/utils/create-getserversideprops.ts b/mscr-ui/src/common/utils/create-getserversideprops.ts index db78e02b9..4e3e42e6c 100644 --- a/mscr-ui/src/common/utils/create-getserversideprops.ts +++ b/mscr-ui/src/common/utils/create-getserversideprops.ts @@ -30,6 +30,7 @@ export interface LocalHandlerParams extends GetServerSidePropsContext { export type localHandler<T> = (context: LocalHandlerParams) => Promise<T>; +// Some how this is creating problem export type CommonServerSideProps = UserProps & SSRConfig & CommonContextState & { @@ -89,7 +90,7 @@ export function createCommonGetServerSideProps< functionKey: 'getFakeableUsers', }); console.log(fakeableUsers); - // store.dispatch( + //store.dispatch( // setAdminControls(process.env.ADMIN_CONTROLS_DISABLED === 'true') // ); diff --git a/mscr-ui/src/pages/[homepage]/index.tsx b/mscr-ui/src/pages/[homepage]/index.tsx index 62804fda6..d543a701a 100644 --- a/mscr-ui/src/pages/[homepage]/index.tsx +++ b/mscr-ui/src/pages/[homepage]/index.tsx @@ -29,7 +29,7 @@ import { useBreakpoints } from 'yti-common-ui/media-query'; import { Grid } from '@mui/material'; import SideNavigationPanel from '@app/common/components/side-navigation'; -import CrosswalkEditor from "@app/modules/crosswalk-editor"; +import CrosswalkEditor from '@app/modules/crosswalk-editor'; import { MscrUser } from '@app/common/interfaces/mscr-user.interface'; interface IndexPageProps extends CommonContextState { diff --git a/mscr-ui/src/pages/_document.tsx b/mscr-ui/src/pages/_document.tsx index dc039661f..988f098c3 100644 --- a/mscr-ui/src/pages/_document.tsx +++ b/mscr-ui/src/pages/_document.tsx @@ -1,19 +1,23 @@ -import Document, { DocumentContext } from 'next/document'; +import Document, { DocumentContext, DocumentInitialProps } from 'next/document'; import { ServerStyleSheet } from 'styled-components'; -// https://github.com/msreekm/nextjs-material-ui-styled-components-boilerplate/blob/master/pages/_document.js +//Fixing the custom render page error, https://nextjs.org/docs/pages/building-your-application/routing/custom-document export default class MyDocument extends Document { - static async getInitialProps(ctx: DocumentContext) { + static async getInitialProps( + ctx: DocumentContext + ): Promise<DocumentInitialProps> { const sheet = new ServerStyleSheet(); const originalRenderPage = ctx.renderPage; try { + // Run the React rendering logic synchronously ctx.renderPage = () => originalRenderPage({ - enhanceApp: (App) => (props) => - sheet.collectStyles(<App {...props} />), + // Useful for wrapping the whole react tree + enhanceApp: (App) => App, + // Useful for wrapping in a per-page basis + enhanceComponent: (Component) => Component, }); - const initialProps = await ctx.defaultGetInitialProps(ctx); return { ...initialProps, diff --git a/mscr-ui/src/pages/index.tsx b/mscr-ui/src/pages/index.tsx index d692560fb..ed0f3ceb6 100644 --- a/mscr-ui/src/pages/index.tsx +++ b/mscr-ui/src/pages/index.tsx @@ -43,8 +43,7 @@ export default function IndexPage(props: IndexPageProps) { title={t('mscr-title')} description={t('service-description')} /> - <div>{props}</div> - <h2>This page is the landing page for {props}</h2> + </Layout> </CommonContextProvider> ); diff --git a/mscr-ui/src/pages/schema/[...pid].tsx b/mscr-ui/src/pages/schema/[...pid].tsx index 02bd2acb7..ab95dccf6 100644 --- a/mscr-ui/src/pages/schema/[...pid].tsx +++ b/mscr-ui/src/pages/schema/[...pid].tsx @@ -22,7 +22,7 @@ import UpdateWithFileModal from '@app/common/components/update-with-file-modal'; import Separator from 'yti-common-ui/components/separator'; import { BasicBlock, BasicBlockExtraWrapper } from 'yti-common-ui/block'; import { MscrUser } from '@app/common/interfaces/mscr-user.interface'; -import SchemaView from "@app/modules/schema-view"; +import SchemaView from '@app/modules/schema-view'; interface IndexPageProps extends CommonContextState { _netI18Next: SSRConfig; @@ -59,7 +59,7 @@ export default function SchemaPage(props: IndexPageProps) { </BasicBlock> <BasicBlock title={'Schema created'}>{data.created}</BasicBlock> <BasicBlock title={'Schema Visibilty'}> - {data.visibilty} + {data.visibility} </BasicBlock> <BasicBlock title={'Schema Status'}>{data.status}</BasicBlock> </div> From 0b055c4c98bb68fc4fc2a69eb81d15ce1aa0547a Mon Sep 17 00:00:00 2001 From: rquazi <rumana.quazi@csc.fi> Date: Thu, 23 Nov 2023 15:25:35 +0200 Subject: [PATCH 10/15] format fix --- .../common/components/history-table/index.tsx | 14 +- .../src/common/components/layout/layout.tsx | 1 - .../common/components/shared-icons/index.tsx | 53 +- .../crosswalk-connection.interface.ts | 103 +- .../src/modules/crosswalk-editor/index.tsx | 1770 ++--- .../joint-listing-accordion/index.tsx | 330 +- .../mapping-validator/index.tsx | 19 +- .../crosswalk-editor/schema-mockup.tsx | 6051 +++++++++-------- .../tabs/crosswalk-info/node-info/index.tsx | 548 +- .../tabs/edit-crosswalk/schema-tree/index.tsx | 106 +- .../tabs/metadata-and-files/index.tsx | 212 +- .../tabs/node-mappings/index.tsx | 588 +- mscr-ui/src/modules/schema-view/index.tsx | 36 +- .../schema-view/metadata-and-files/index.tsx | 176 +- .../schema-view/version-history/index.tsx | 58 +- mscr-ui/src/modules/search-screen/index.tsx | 19 +- mscr-ui/src/pages/[homepage]/index.tsx | 8 +- mscr-ui/src/pages/index.tsx | 1 - .../src/pages/mscr-style-customizations.scss | 37 +- 19 files changed, 5437 insertions(+), 4693 deletions(-) diff --git a/mscr-ui/src/common/components/history-table/index.tsx b/mscr-ui/src/common/components/history-table/index.tsx index fb3dcc961..0567a1e07 100644 --- a/mscr-ui/src/common/components/history-table/index.tsx +++ b/mscr-ui/src/common/components/history-table/index.tsx @@ -14,13 +14,23 @@ export interface Revision { state: string; created: string; } -export default function HistoryTable({ headers, revisions, ariaLabel }: { headers: Array<string>; revisions: Revision[]; ariaLabel: string }) { +export default function HistoryTable({ + headers, + revisions, + ariaLabel, +}: { + headers: Array<string>; + revisions: Revision[]; + ariaLabel: string; +}) { return ( <TableContainer> <Table aria-label={ariaLabel}> <TableHead> <TableRow> - {headers.map((header) => <TableCell key={header}>{header}</TableCell>)} + {headers.map((header) => ( + <TableCell key={header}>{header}</TableCell> + ))} </TableRow> </TableHead> <TableBody> diff --git a/mscr-ui/src/common/components/layout/layout.tsx b/mscr-ui/src/common/components/layout/layout.tsx index 1fb25720c..aa75b05e5 100644 --- a/mscr-ui/src/common/components/layout/layout.tsx +++ b/mscr-ui/src/common/components/layout/layout.tsx @@ -76,7 +76,6 @@ export default function Layout({ )} /> <Grid container spacing={2}> - <Grid item xs={12}> <ContentContainer> {alerts && alerts} diff --git a/mscr-ui/src/common/components/shared-icons/index.tsx b/mscr-ui/src/common/components/shared-icons/index.tsx index 95d08e495..b7679b142 100644 --- a/mscr-ui/src/common/components/shared-icons/index.tsx +++ b/mscr-ui/src/common/components/shared-icons/index.tsx @@ -1,14 +1,47 @@ export default function LinkIcon() { - return (<svg width="25" height="25" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path d="M6.99654 10.0541C7.11025 10.1273 7.23734 10.1606 7.35774 10.1606H7.36443C7.58517 10.1606 7.79922 10.0541 7.92631 9.85435C8.12698 9.54806 8.03333 9.13525 7.72564 8.9355C7.58517 8.84228 7.45139 8.7424 7.33768 8.62255C6.44805 7.73699 6.44805 6.29213 7.33768 5.40657L10.7624 1.9975C11.6253 1.13858 13.1303 1.13858 13.9932 1.9975C14.4213 2.4303 14.6621 2.99625 14.6621 3.60882C14.6621 4.22139 14.428 4.79401 13.9932 5.22014L11.6521 7.55056C11.3912 7.81024 11.3912 8.22971 11.6521 8.48939C11.9129 8.74906 12.3343 8.74906 12.5952 8.48939L14.9363 6.15897C15.6253 5.47982 15.9999 4.57428 15.9999 3.60882C15.9999 2.64336 15.6186 1.73783 14.9363 1.05868C14.2541 0.372867 13.3444 0 12.3745 0C11.4046 0 10.4949 0.379526 9.81259 1.05868L6.38116 4.46109C4.96978 5.866 4.96978 8.15647 6.38116 9.56138C6.56845 9.74781 6.7758 9.91427 6.99654 10.0541Z" fill="white"/> - <path d="M1.06341 14.948C1.77244 15.6471 2.69552 16 3.62528 16L3.61859 16.0066C4.54836 16.0066 5.47144 15.6604 6.18047 14.9546L9.60522 11.5456C10.2942 10.8664 10.6688 9.95421 10.6688 8.99541C10.6688 8.03661 10.2875 7.12442 9.60522 6.44527C9.4313 6.26549 9.23063 6.10569 9.02328 5.97252C8.71558 5.77277 8.30087 5.85933 8.1002 6.16562C7.89953 6.4719 7.98649 6.88472 8.29418 7.08447C8.42127 7.17103 8.54836 7.2709 8.66207 7.38409C9.09017 7.81688 9.33097 8.38284 9.33097 8.99541C9.33097 9.60798 9.09686 10.1739 8.66207 10.6067L5.23732 14.0158C4.34769 14.9014 2.89619 14.9014 2.00655 14.0158C1.57846 13.583 1.33766 13.0171 1.33766 12.4045C1.33766 11.7919 1.57177 11.226 2.00655 10.7932L4.341 8.4694C4.60187 8.20973 4.60187 7.79025 4.341 7.53058C4.08013 7.2709 3.65873 7.2709 3.39786 7.53058L1.06341 9.84768C-0.34796 11.2526 -0.34796 13.5431 1.06341 14.948Z" fill="white"/> - </svg>) + return ( + <svg + width="25" + height="25" + viewBox="0 0 16 16" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M6.99654 10.0541C7.11025 10.1273 7.23734 10.1606 7.35774 10.1606H7.36443C7.58517 10.1606 7.79922 10.0541 7.92631 9.85435C8.12698 9.54806 8.03333 9.13525 7.72564 8.9355C7.58517 8.84228 7.45139 8.7424 7.33768 8.62255C6.44805 7.73699 6.44805 6.29213 7.33768 5.40657L10.7624 1.9975C11.6253 1.13858 13.1303 1.13858 13.9932 1.9975C14.4213 2.4303 14.6621 2.99625 14.6621 3.60882C14.6621 4.22139 14.428 4.79401 13.9932 5.22014L11.6521 7.55056C11.3912 7.81024 11.3912 8.22971 11.6521 8.48939C11.9129 8.74906 12.3343 8.74906 12.5952 8.48939L14.9363 6.15897C15.6253 5.47982 15.9999 4.57428 15.9999 3.60882C15.9999 2.64336 15.6186 1.73783 14.9363 1.05868C14.2541 0.372867 13.3444 0 12.3745 0C11.4046 0 10.4949 0.379526 9.81259 1.05868L6.38116 4.46109C4.96978 5.866 4.96978 8.15647 6.38116 9.56138C6.56845 9.74781 6.7758 9.91427 6.99654 10.0541Z" + fill="white" + /> + <path + d="M1.06341 14.948C1.77244 15.6471 2.69552 16 3.62528 16L3.61859 16.0066C4.54836 16.0066 5.47144 15.6604 6.18047 14.9546L9.60522 11.5456C10.2942 10.8664 10.6688 9.95421 10.6688 8.99541C10.6688 8.03661 10.2875 7.12442 9.60522 6.44527C9.4313 6.26549 9.23063 6.10569 9.02328 5.97252C8.71558 5.77277 8.30087 5.85933 8.1002 6.16562C7.89953 6.4719 7.98649 6.88472 8.29418 7.08447C8.42127 7.17103 8.54836 7.2709 8.66207 7.38409C9.09017 7.81688 9.33097 8.38284 9.33097 8.99541C9.33097 9.60798 9.09686 10.1739 8.66207 10.6067L5.23732 14.0158C4.34769 14.9014 2.89619 14.9014 2.00655 14.0158C1.57846 13.583 1.33766 13.0171 1.33766 12.4045C1.33766 11.7919 1.57177 11.226 2.00655 10.7932L4.341 8.4694C4.60187 8.20973 4.60187 7.79025 4.341 7.53058C4.08013 7.2709 3.65873 7.2709 3.39786 7.53058L1.06341 9.84768C-0.34796 11.2526 -0.34796 13.5431 1.06341 14.948Z" + fill="white" + /> + </svg> + ); } export function InfoIcon() { - return (<svg width="22" height="22" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path d="M7.66792 3.33361C8.22125 3.33361 8.66858 3.78161 8.66858 4.3336C8.66858 4.8856 8.22125 5.33359 7.66792 5.33359H7.66725C7.11459 5.33359 6.6666 4.8856 6.6666 4.3336C6.6666 3.78161 7.11393 3.33361 7.66659 3.33361H7.66792Z" fill="#2A6EBB"/> - <path d="M9.33524 12.6668H6.6666C6.2986 12.6668 5.99994 12.3682 5.99994 12.0002C5.99994 11.6322 6.2986 11.3335 6.6666 11.3335H7.33326V8.00023H6.6666C6.2986 8.00023 5.99994 7.70157 5.99994 7.33357C5.99994 6.96557 6.2986 6.66691 6.6666 6.66691H8.00192C8.36991 6.66691 8.66858 6.96557 8.66858 7.33357V11.3335H9.33524C9.70323 11.3335 10.0019 11.6322 10.0019 12.0002C10.0019 12.3682 9.70323 12.6668 9.33524 12.6668Z" fill="#2A6EBB"/> - <path fill-rule="evenodd" clip-rule="evenodd" d="M8 16C3.58867 16 0 12.4113 0 8C0 3.58867 3.58867 0 8 0C12.4113 0 16 3.58867 16 8C16 12.4113 12.4113 16 8 16ZM8 1.33333C4.324 1.33333 1.33333 4.324 1.33333 8C1.33333 11.676 4.324 14.6667 8 14.6667C11.676 14.6667 14.6667 11.676 14.6667 8C14.6667 4.324 11.676 1.33333 8 1.33333Z" fill="#2A6EBB"/> - </svg>) -} \ No newline at end of file + return ( + <svg + width="22" + height="22" + viewBox="0 0 16 16" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M7.66792 3.33361C8.22125 3.33361 8.66858 3.78161 8.66858 4.3336C8.66858 4.8856 8.22125 5.33359 7.66792 5.33359H7.66725C7.11459 5.33359 6.6666 4.8856 6.6666 4.3336C6.6666 3.78161 7.11393 3.33361 7.66659 3.33361H7.66792Z" + fill="#2A6EBB" + /> + <path + d="M9.33524 12.6668H6.6666C6.2986 12.6668 5.99994 12.3682 5.99994 12.0002C5.99994 11.6322 6.2986 11.3335 6.6666 11.3335H7.33326V8.00023H6.6666C6.2986 8.00023 5.99994 7.70157 5.99994 7.33357C5.99994 6.96557 6.2986 6.66691 6.6666 6.66691H8.00192C8.36991 6.66691 8.66858 6.96557 8.66858 7.33357V11.3335H9.33524C9.70323 11.3335 10.0019 11.6322 10.0019 12.0002C10.0019 12.3682 9.70323 12.6668 9.33524 12.6668Z" + fill="#2A6EBB" + /> + <path + fill-rule="evenodd" + clip-rule="evenodd" + d="M8 16C3.58867 16 0 12.4113 0 8C0 3.58867 3.58867 0 8 0C12.4113 0 16 3.58867 16 8C16 12.4113 12.4113 16 8 16ZM8 1.33333C4.324 1.33333 1.33333 4.324 1.33333 8C1.33333 11.676 4.324 14.6667 8 14.6667C11.676 14.6667 14.6667 11.676 14.6667 8C14.6667 4.324 11.676 1.33333 8 1.33333Z" + fill="#2A6EBB" + /> + </svg> + ); +} diff --git a/mscr-ui/src/common/interfaces/crosswalk-connection.interface.ts b/mscr-ui/src/common/interfaces/crosswalk-connection.interface.ts index 55a361235..ff9f9f816 100644 --- a/mscr-ui/src/common/interfaces/crosswalk-connection.interface.ts +++ b/mscr-ui/src/common/interfaces/crosswalk-connection.interface.ts @@ -1,66 +1,65 @@ export interface CrosswalkConnection { - source: string; - target: string | string[]; - sourceTitle: string | undefined; - targetTitle: string | undefined; - sourceType: string | undefined; - targetType: string | undefined; - parentId: number | string; - parentName: string | undefined; - mappingType: string | undefined; - notes: string | undefined; - isSelected: boolean; - sourceDescription: string | undefined; - type: string | undefined; + source: string; + target: string | string[]; + sourceTitle: string | undefined; + targetTitle: string | undefined; + sourceType: string | undefined; + targetType: string | undefined; + parentId: number | string; + parentName: string | undefined; + mappingType: string | undefined; + notes: string | undefined; + isSelected: boolean; + sourceDescription: string | undefined; + type: string | undefined; } export interface RenderTree { - idNumeric: number; - id: string; - name: string; - isLinked: boolean; - title?: string; - type?: string; - description?: string; - required?: string; - isMappable?: string; - parentName?: string; - jsonPath: string; - parentId: number | string; - children?: RenderTree[]; + idNumeric: number; + id: string; + name: string; + isLinked: boolean; + title?: string; + type?: string; + description?: string; + required?: string; + isMappable?: string; + parentName?: string; + jsonPath: string; + parentId: number | string; + children?: RenderTree[]; } export interface CrosswalkConnectionNew { - source: RenderTree; - target: RenderTree; - id: string; - description: string | undefined; - isSelected: boolean; - isDraft: boolean; - sourceJsonPath: string | undefined; - targetJsonPath: string | undefined; - sourcePredicate: string | undefined; - sourceProcessing: string | undefined; - targetPredicate: string | undefined; - targetProcessing: string | undefined; + source: RenderTree; + target: RenderTree; + id: string; + description: string | undefined; + isSelected: boolean; + isDraft: boolean; + sourceJsonPath: string | undefined; + targetJsonPath: string | undefined; + sourcePredicate: string | undefined; + sourceProcessing: string | undefined; + targetPredicate: string | undefined; + targetProcessing: string | undefined; } export interface CrosswalkConnectionsNew { - source: RenderTree[]; - target: RenderTree[]; - id: string; - description: string | undefined; + source: RenderTree[]; + target: RenderTree[]; + id: string; + description: string | undefined; } export interface CrosswalkPayloadPrelim { - sourceName: string; - targetName: string; - sourceJsonPath: string; - targetJsonPath: string; - id: string; - description: string | undefined; - filterFunction: string | undefined; - sourceProcessing: string | undefined; - targetProcessing: string | undefined; + sourceName: string; + targetName: string; + sourceJsonPath: string; + targetJsonPath: string; + id: string; + description: string | undefined; + filterFunction: string | undefined; + sourceProcessing: string | undefined; + targetProcessing: string | undefined; } - diff --git a/mscr-ui/src/modules/crosswalk-editor/index.tsx b/mscr-ui/src/modules/crosswalk-editor/index.tsx index 516bf0f46..8125b1ced 100644 --- a/mscr-ui/src/modules/crosswalk-editor/index.tsx +++ b/mscr-ui/src/modules/crosswalk-editor/index.tsx @@ -2,15 +2,17 @@ import * as React from 'react'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; import TreeItem from '@mui/lab/TreeItem'; -import {useEffect} from 'react'; -import {Text} from 'suomifi-ui-components'; -import MockupSchemaLoader, {getFilterFunctions} from '../crosswalk-editor/schema-mockup'; -import {cloneDeep} from 'lodash'; -import {useBreakpoints} from 'yti-common-ui/components/media-query'; +import { useEffect } from 'react'; +import { Text } from 'suomifi-ui-components'; +import MockupSchemaLoader, { + getFilterFunctions, +} from '../crosswalk-editor/schema-mockup'; +import { cloneDeep } from 'lodash'; +import { useBreakpoints } from 'yti-common-ui/components/media-query'; import TableRow from '@mui/material/TableRow'; -import TableCell, {tableCellClasses} from '@mui/material/TableCell'; +import TableCell, { tableCellClasses } from '@mui/material/TableCell'; import TableBody from '@mui/material/TableBody'; -import {styled} from '@mui/material'; +import { styled } from '@mui/material'; import IconButton from '@mui/material/IconButton'; import DeleteIcon from '@mui/icons-material/Delete'; import LinkOffIcon from '@mui/icons-material/LinkOff'; @@ -24,880 +26,1032 @@ import Typography from '@mui/material/Typography'; import JointListingAccordion from '@app/modules/crosswalk-editor/joint-listing-accordion'; import MetadataAndFiles from '@app/modules/crosswalk-editor/tabs/metadata-and-files'; import NodeInfo from '@app/modules/crosswalk-editor/tabs/crosswalk-info/node-info'; -import {SearchInput} from 'suomifi-ui-components'; +import { SearchInput } from 'suomifi-ui-components'; import SchemaTree from '@app/modules/crosswalk-editor/tabs/edit-crosswalk/schema-tree'; import AccountTreeIcon from '@mui/icons-material/AccountTree'; import { - Button as Sbutton, - InlineAlert, - Modal, - ModalContent, - ModalFooter, - ModalTitle, - Paragraph, + Button as Sbutton, + InlineAlert, + Modal, + ModalContent, + ModalFooter, + ModalTitle, + Paragraph, } from 'suomifi-ui-components'; -import {fetchCrosswalkData} from '@app/common/components/simple-api-service'; +import { fetchCrosswalkData } from '@app/common/components/simple-api-service'; import callback from '@app/pages/api/auth/callback'; import { - RenderTree, - CrosswalkConnection, - CrosswalkConnectionNew, - CrosswalkConnectionsNew + RenderTree, + CrosswalkConnection, + CrosswalkConnectionNew, + CrosswalkConnectionsNew, } from '@app/common/interfaces/crosswalk-connection.interface'; import NodeMappingsModal from './tabs/node-mappings'; import LinkIcon from '@app/common/components/shared-icons'; export default function CrosswalkEditor() { - interface simpleNode { - name: string | undefined; - id: string; + interface simpleNode { + name: string | undefined; + id: string; + } + + const emptyTreeSelection: RenderTree = { + idNumeric: 0, + id: '', + name: '', + isLinked: false, + title: '', + type: '', + description: '', + required: '', + isMappable: '', + parentName: '', + jsonPath: '', + parentId: 0, + children: [], + }; + + const crosswalkConnectionInit: CrosswalkConnection = { + sourceDescription: undefined, + isSelected: false, + mappingType: undefined, + notes: undefined, + parentId: '', + parentName: undefined, + source: '', + sourceTitle: undefined, + sourceType: undefined, + target: '', + targetTitle: undefined, + targetType: undefined, + type: undefined, + }; + + const crosswalkConnectionNewInit: CrosswalkConnectionNew = { + source: emptyTreeSelection, + target: emptyTreeSelection, + id: '0', + description: '', + isSelected: false, + isDraft: false, + sourceJsonPath: undefined, + targetJsonPath: undefined, + sourcePredicate: undefined, + sourceProcessing: undefined, + targetPredicate: undefined, + targetProcessing: undefined, + }; + + const crosswalkConnectionsNewInit: CrosswalkConnectionsNew = { + source: [emptyTreeSelection], + target: [emptyTreeSelection], + id: '0', + description: '', + }; + + const emptyTree: any = [ + { + id: '0', + name: '', + children: '', + }, + ]; + + const fromTree = (nodes: any) => ( + <TreeItem + key={nodes.id} + nodeId={nodes.id} + label={nodes.name} + className="linked-tree-item" + > + {Array.isArray(nodes.children) + ? nodes.children.map((node: any) => fromTree(node)) + : null} + </TreeItem> + ); + + const emptyTreeTest = () => ( + <TreeItem key="0" nodeId="0" label="test"></TreeItem> + ); + + // STATE VARIABLES + const inputData: RenderTree[] = []; + const [isSourceDataLoading, setSourceDataLoading] = + React.useState<boolean>(false); + const [isSourceDataFetched, setSourceDataFetched] = + React.useState<boolean>(false); + const [mockSourceData, setMockSourceData] = React.useState< + RenderTree[] | undefined + >([emptyTreeSelection]); + + if (!isSourceDataLoading) { + setSourceDataLoading(true); + MockupSchemaLoader(true).then((res) => { + setMockSourceData(res); + if (res) { + setSourceData(res); + setTargetData(res); + // Used for storing fil + setSourceDataOriginal(res); + setTargetDataOriginal(res); + setSourceDataFetched(true); + } + }); + + getFilterFunctions().then((res) => { + if (res) { + setFilterFunctions(res); + } + }); + } + + const [sourceTreeDataOriginal, setSourceDataOriginal] = + React.useState<RenderTree[]>(inputData); + const [sourceTreeData, setSourceData] = + React.useState<RenderTree[]>(inputData); + const [sourceTreeExpanded, setSourceExpanded] = React.useState<string[]>([]); + const [sourceTreeSelectedArray, selectFromSourceTreeByIds] = React.useState< + string[] + >([]); + + const [targetTreeDataOriginal, setTargetDataOriginal] = + React.useState<RenderTree[]>(inputData); + const [targetTreeData, setTargetData] = + React.useState<RenderTree[]>(inputData); + const [targetTreeExpanded, setTargetExpanded] = React.useState<string[]>([]); + const [targetTreeSelectedArray, selectFromTargetTreeByIds] = React.useState< + string[] + >([]); + + const [selectedSourceNodes, setSelectedSourceNodes] = React.useState< + RenderTree[] + >([emptyTreeSelection]); + const [selectedTargetNodes, setSelectedTargetNodes] = React.useState< + RenderTree[] + >([emptyTreeSelection]); + + const [connectedCrosswalksNew, setConnectedCrosswalksNew] = React.useState< + CrosswalkConnectionNew[] + >([]); + const [jointToBeEdited, setJointToBeEdited] = + React.useState<CrosswalkConnectionNew>(crosswalkConnectionNewInit); + const [modalOpen, setModalOpen] = React.useState<boolean>(false); + + const [connectedCrosswalksNew2, setConnectedCrosswalksNew2] = React.useState< + CrosswalkConnectionsNew[] | [] + >([]); + + const [isAnySelectedLinked, setAnySelectedLinkedState] = + React.useState<boolean>(false); + const [isBothSelectedLinked, setBothSelectedLinkedState] = + React.useState<boolean>(false); + const [linkingError, setLinkingError] = React.useState<string>(''); + const [selectedTab, setSelectedTab] = React.useState(1); + const [nodeMappingsModalOpen, setNodeMappingsModalOpen] = + React.useState<boolean>(false); + + const [filterFunctions, setFilterFunctions] = React.useState<any[]>([]); + + const [crosswalksList, setCrosswalkList] = React.useState<string[]>([]); + + const [isEditModeActive, setEditModeActive] = React.useState<boolean>(true); + + useEffect(() => { + console.log('########## GOT FILTER FUNCTIONS', filterFunctions); + }, [filterFunctions]); + + useEffect(() => { + setNodeMappingsModalOpen(true); + }, [jointToBeEdited]); + + // RESET EDITED JOINT VALUE IF MODAL NEEDS TO BE RE OPENED + useEffect(() => { + setJointToBeEdited(undefined); + }, [nodeMappingsModalOpen]); + + // EXPAND TREES WHEN DATA LOADED + useEffect(() => { + setExpanded(true); + }, [sourceTreeData]); + + useEffect(() => { + setExpanded(false); + }, [targetTreeData]); + + useEffect(() => { + // USED BY NODE INFO BOX SOURCE + setSelectedSourceNodes(getTreeNodesById(sourceTreeSelectedArray, true)); + + // USED BY NODE INFO BOX TARGET + setSelectedTargetNodes(getTreeNodesById(targetTreeSelectedArray, false)); + + //updateIsLinkedStatus(sourceNode, targetNode); + //setSelectedSourceNodes(sourceNode); + }, [ + sourceTreeSelectedArray, + targetTreeSelectedArray, + connectedCrosswalksNew, + crosswalksList, + ]); + + // USED BY LINK BUTTON STATE + useEffect(() => { + updateSelectionErrors(); + }, [selectedSourceNodes, selectedTargetNodes]); + + function addJoint(add: boolean) { + if (add) { + //TODO: check already linked + const jointsToBeAdded: CrosswalkConnectionNew[] = []; + let lastJointId = ''; + selectedSourceNodes.forEach((sourceNode) => { + lastJointId = sourceNode.id + '.' + selectedTargetNodes[0].id; + const joint: CrosswalkConnectionNew = { + source: sourceNode, + target: selectedTargetNodes[0], + id: lastJointId, + description: '', + isSelected: true, + isDraft: true, + sourceJsonPath: undefined, + targetJsonPath: undefined, + sourcePredicate: undefined, + sourceProcessing: undefined, + targetPredicate: undefined, + targetProcessing: undefined, + }; + jointsToBeAdded.push(joint); + }); + //setConnectedCrosswalksNew(crosswalkMappings => [...jointsToBeAdded, ...crosswalkMappings]); + setJointToBeEdited(jointsToBeAdded[jointsToBeAdded.length - 1]); } - - const emptyTreeSelection: RenderTree = { - idNumeric: 0, - id: '', - name: '', - isLinked: false, - title: '', - type: '', - description: '', - required: '', - isMappable: '', - parentName: '', - jsonPath: '', - parentId: 0, - children: [], - }; - - const crosswalkConnectionInit: CrosswalkConnection = { - sourceDescription: undefined, - isSelected: false, - mappingType: undefined, - notes: undefined, - parentId: '', - parentName: undefined, - source: '', - sourceTitle: undefined, - sourceType: undefined, - target: '', - targetTitle: undefined, - targetType: undefined, - type: undefined, - }; - - const crosswalkConnectionNewInit: CrosswalkConnectionNew = { - source: emptyTreeSelection, - target: emptyTreeSelection, - id: '0', - description: '', - isSelected: false, - isDraft: false, - sourceJsonPath: undefined, - targetJsonPath: undefined, - sourcePredicate: undefined, - sourceProcessing: undefined, - targetPredicate: undefined, - targetProcessing: undefined, - }; - - - const crosswalkConnectionsNewInit: CrosswalkConnectionsNew = { - source: [emptyTreeSelection], - target: [emptyTreeSelection], - id: '0', - description: '', - }; - - - const emptyTree: any = [{ - id: '0', - name: '', - children: '', - }]; - - const fromTree = (nodes: any) => ( - <TreeItem key={nodes.id} nodeId={nodes.id} label={nodes.name} className='linked-tree-item'> - {Array.isArray(nodes.children) - ? nodes.children.map((node: any) => fromTree(node)) - : null} - </TreeItem> + } + + function removeJoint(cc: any) { + const newCrosswalks = [ + ...connectedCrosswalksNew.filter((item) => { + return item.id !== cc; + }), + ]; + setConnectedCrosswalksNew(() => [...newCrosswalks]); + } + + function updateIsLinkedStatus( + source: CrosswalkConnection, + target: CrosswalkConnection + ) { + setAnySelectedLinkedState( + source.target.length > 0 || target.target.length > 0 ); - - const emptyTreeTest = () => ( - <TreeItem key="0" nodeId="0" label="test"></TreeItem> + setBothSelectedLinkedState( + source.target.length > 0 && source.target === target.source ); - - // STATE VARIABLES - const inputData: RenderTree[] = []; - const [isSourceDataLoading, setSourceDataLoading] = React.useState<boolean>(false); - const [isSourceDataFetched, setSourceDataFetched] = React.useState<boolean>(false); - const [mockSourceData, setMockSourceData] = React.useState<RenderTree[] | undefined>([emptyTreeSelection]); - - if (!isSourceDataLoading) { - setSourceDataLoading(true); - MockupSchemaLoader(true).then(res => { - setMockSourceData(res); - if (res) { - setSourceData(res); - setTargetData(res); - // Used for storing fil - setSourceDataOriginal(res); - setTargetDataOriginal(res); - setSourceDataFetched(true); - } - }); - - getFilterFunctions().then(res => { - if (res) { - setFilterFunctions(res); - } - }); - - } - - const [sourceTreeDataOriginal, setSourceDataOriginal] = React.useState<RenderTree[]>(inputData); - const [sourceTreeData, setSourceData] = React.useState<RenderTree[]>(inputData); - const [sourceTreeExpanded, setSourceExpanded] = React.useState<string[]>([]); - const [sourceTreeSelectedArray, selectFromSourceTreeByIds] = React.useState<string[]>([]); - - const [targetTreeDataOriginal, setTargetDataOriginal] = React.useState<RenderTree[]>(inputData); - const [targetTreeData, setTargetData] = React.useState<RenderTree[]>(inputData); - const [targetTreeExpanded, setTargetExpanded] = React.useState<string[]>([]); - const [targetTreeSelectedArray, selectFromTargetTreeByIds] = React.useState<string[]>([]); - - const [selectedSourceNodes, setSelectedSourceNodes] = React.useState<RenderTree[]>([emptyTreeSelection]); - const [selectedTargetNodes, setSelectedTargetNodes] = React.useState<RenderTree[]>([emptyTreeSelection]); - - const [connectedCrosswalksNew, setConnectedCrosswalksNew] = React.useState<CrosswalkConnectionNew[]>([]); - const [jointToBeEdited, setJointToBeEdited] = React.useState<CrosswalkConnectionNew>(crosswalkConnectionNewInit); - const [modalOpen, setModalOpen] = React.useState<boolean>(false); - - const [connectedCrosswalksNew2, setConnectedCrosswalksNew2] = React.useState<CrosswalkConnectionsNew[] | []>([]); - - - const [isAnySelectedLinked, setAnySelectedLinkedState] = React.useState<boolean>(false); - const [isBothSelectedLinked, setBothSelectedLinkedState] = React.useState<boolean>(false); - const [linkingError, setLinkingError] = React.useState<string>(''); - const [selectedTab, setSelectedTab] = React.useState(1); - const [nodeMappingsModalOpen, setNodeMappingsModalOpen] = React.useState<boolean>(false); - - const [filterFunctions, setFilterFunctions] = React.useState<any[]>([]); - - const [crosswalksList, setCrosswalkList] = React.useState<string[]>([]); - - const [isEditModeActive, setEditModeActive] = React.useState<boolean>(true); - - useEffect(() => { - console.log('########## GOT FILTER FUNCTIONS', filterFunctions); - }, [filterFunctions]); - - useEffect(() => { - setNodeMappingsModalOpen(true); - }, [jointToBeEdited]); - - // RESET EDITED JOINT VALUE IF MODAL NEEDS TO BE RE OPENED - useEffect(() => { - setJointToBeEdited(undefined); - }, [nodeMappingsModalOpen]); - - // EXPAND TREES WHEN DATA LOADED - useEffect(() => { - setExpanded(true); - }, [sourceTreeData]); - - useEffect(() => { - setExpanded(false); - }, [targetTreeData]); - - useEffect(() => { - // USED BY NODE INFO BOX SOURCE - setSelectedSourceNodes(getTreeNodesById(sourceTreeSelectedArray, true)); - - // USED BY NODE INFO BOX TARGET - setSelectedTargetNodes(getTreeNodesById(targetTreeSelectedArray, false)); - - //updateIsLinkedStatus(sourceNode, targetNode); - //setSelectedSourceNodes(sourceNode); - - }, [sourceTreeSelectedArray, targetTreeSelectedArray, connectedCrosswalksNew, crosswalksList]); - - // USED BY LINK BUTTON STATE - useEffect(() => { - updateSelectionErrors(); - }, [selectedSourceNodes, selectedTargetNodes]); - - function addJoint(add: boolean) { - if ((add)) { - //TODO: check already linked - const jointsToBeAdded: CrosswalkConnectionNew[] = []; - let lastJointId = ''; - selectedSourceNodes.forEach(sourceNode => { - lastJointId = sourceNode.id + '.' + selectedTargetNodes[0].id; - const joint: CrosswalkConnectionNew = { - source: sourceNode, - target: selectedTargetNodes[0], - id: lastJointId, - description: '', - isSelected: true, - isDraft: true, - sourceJsonPath: undefined, - targetJsonPath: undefined, - sourcePredicate: undefined, - sourceProcessing: undefined, - targetPredicate: undefined, - targetProcessing: undefined - }; - jointsToBeAdded.push(joint); - }); - //setConnectedCrosswalksNew(crosswalkMappings => [...jointsToBeAdded, ...crosswalkMappings]); - setJointToBeEdited(jointsToBeAdded[jointsToBeAdded.length - 1]); + } + + function getJointEndNode(nodes: string[], isSourceTree: boolean) { + let ret: simpleNode = { name: '', id: '' }; + connectedCrosswalksNew.forEach((item) => { + if (isSourceTree) { + if (item.source.id === nodes.toString()) { + ret = { name: item.target.name, id: item.target.id }; } - }; - - function removeJoint(cc: any) { - const newCrosswalks = [...connectedCrosswalksNew.filter(item => { - return (item.id !== cc); - })]; - setConnectedCrosswalksNew(() => [...newCrosswalks]); + } else { + if (item.target.id === nodes.toString()) { + ret = { name: item.source.name, id: item.source.id }; + } + } + }); + return ret; + } + + function getJointNodes(nodeIds: string[], isSourceTree: boolean) { + if (isSourceTree) { + return connectedCrosswalksNew.filter( + (item) => item.source.id === nodeIds.toString() + ); + } else { + return connectedCrosswalksNew.filter( + (item) => item.target.id === nodeIds.toString() + ); } - - function updateIsLinkedStatus(source: CrosswalkConnection, target: CrosswalkConnection) { - setAnySelectedLinkedState(source.target.length > 0 || target.target.length > 0); - setBothSelectedLinkedState(source.target.length > 0 && source.target === target.source); + } + + function getTreeNodesById(nodeIds: string[], isSourceTree: boolean) { + let nodeIdsArr: string[] = []; + if (typeof nodeIds === 'string') { + nodeIdsArr.push(nodeIds); + } else { + nodeIdsArr = nodeIds; } - - function getJointEndNode(nodes: string[], isSourceTree: boolean) { - let ret: simpleNode = {name: '', id: ''}; - connectedCrosswalksNew.forEach(item => { - if (isSourceTree) { - if (item.source.id === nodes.toString()) { - ret = {name: item.target.name, id: item.target.id}; - } - } else { - if (item.target.id === nodes.toString()) { - ret = {name: item.source.name, id: item.source.id}; - } - } - }); - return ret; + if (isSourceTree) { + return sourceTreeDataOriginal.filter((item) => + nodeIdsArr.includes(item.id) + ); + } else { + return targetTreeDataOriginal.filter((item) => + nodeIdsArr.includes(item.id) + ); } + } - function getJointNodes(nodeIds: string[], isSourceTree: boolean) { - if (isSourceTree) { - return connectedCrosswalksNew.filter(item => item.source.id === nodeIds.toString()); + function updateJointData(cc: CrosswalkConnectionNew) { + const newCrosswalks = [ + ...connectedCrosswalksNew.map((item) => { + if (item.target === cc.target && item.source === cc.source) { + return cloneDeep(cc); } else { - return connectedCrosswalksNew.filter(item => item.target.id === nodeIds.toString()); + return item; } + }), + ]; + setConnectedCrosswalksNew(() => [...newCrosswalks]); + } + + function setJointSelected(nodeId: string) { + const newCons: CrosswalkConnectionNew[] = []; + connectedCrosswalksNew.forEach((cw) => { + cw.id === nodeId ? (cw.isSelected = true) : (cw.isSelected = false); + newCons.push(cw); + }); + setConnectedCrosswalksNew(() => [...newCons]); + } + + function findJointToBeEdited(nodeId: string) { + connectedCrosswalksNew.find((cw) => { + cw.id === nodeId; + }); + } + + function getJointSelected(id: string) { + let ret = undefined; + connectedCrosswalksNew.filter((cw) => { + if (cw.id === id) { + ret = cw; + } + }); + return ret; + } + + function updateSelectionErrors() { + let linkingError = ''; + + // COMPLEX NODES CHECK + if (selectedSourceNodes.length < 1) { + linkingError = 'At least one source node must be selected.'; + } else if (selectedTargetNodes.length < 1) { + linkingError = 'Target node must be selected'; } - - function getTreeNodesById(nodeIds: string[], isSourceTree: boolean) { - let nodeIdsArr: string[] = []; - if (typeof nodeIds === 'string') { - nodeIdsArr.push(nodeIds); - } else { - nodeIdsArr = nodeIds; + setLinkingError(linkingError); + } + + const handleTreeSelect = ( + event: React.SyntheticEvent | undefined, + nodeIds: string[], + isSourceTree: boolean + ) => { + const newTreeSelection: RenderTree[] = []; + if (isSourceTree) { + sourceTreeData.forEach((item: RenderTree) => { + if (item.id === nodeIds.toString()) { + newTreeSelection.push(item); } - if (isSourceTree) { - return sourceTreeDataOriginal.filter(item => nodeIdsArr.includes(item.id)); - } else { - return targetTreeDataOriginal.filter(item => nodeIdsArr.includes(item.id)); + }); + //setSourceSelection(newTreeSelection); + selectFromSourceTreeByIds(nodeIds); + } else { + targetTreeData.forEach((item: RenderTree) => { + if (item.id === nodeIds.toString()) { + newTreeSelection.push(item); } + }); + //setTargetSelection(newTreeSelection); + selectFromTargetTreeByIds(nodeIds); } - - function updateJointData(cc: CrosswalkConnectionNew) { - const newCrosswalks = [...connectedCrosswalksNew.map(item => { - if ((item.target === cc.target) && (item.source === cc.source)) { - return (cloneDeep(cc)); - } else { - return (item); - } - ; - })]; - setConnectedCrosswalksNew(() => [...newCrosswalks]); - } - - function setJointSelected(nodeId: string) { - const newCons: CrosswalkConnectionNew[] = []; - connectedCrosswalksNew.forEach(cw => { - cw.id === nodeId ? cw.isSelected = true : cw.isSelected = false; - newCons.push(cw); - }); - setConnectedCrosswalksNew(() => [...newCons]); - } - - function findJointToBeEdited(nodeId: string) { - connectedCrosswalksNew.find(cw => { - cw.id === nodeId; - }); + }; + + const handleTreeToggle = ( + event: React.SyntheticEvent, + nodeIds: string[], + isSourceTree: boolean + ) => { + if (isSourceTree) { + setSourceExpanded(nodeIds); + } else { + setTargetExpanded(nodeIds); } - - function getJointSelected(id: string) { - let ret = undefined; - connectedCrosswalksNew.filter(cw => { - if (cw.id === id) { - ret = cw; - } - }); - return ret; + }; + + const selectFromTreeById = (nodeId: string, isTargetTree: boolean) => { + const nodeIds = []; + nodeIds.push(nodeId); + if (isTargetTree) { + selectFromTargetTreeByIds(nodeIds); + } else { + selectFromSourceTreeByIds(nodeIds); } - - function updateSelectionErrors() { - let linkingError = ''; - - // COMPLEX NODES CHECK - if (selectedSourceNodes.length < 1) { - linkingError = 'At least one source node must be selected.'; - } else if (selectedTargetNodes.length < 1) { - linkingError = 'Target node must be selected'; - } - setLinkingError(linkingError); + }; + + const selectFromTree = ( + node: CrosswalkConnectionNew, + isTargetTree: boolean + ) => { + const nodeIds: React.SetStateAction<string[]> = []; + if (isTargetTree) { + nodeIds.push(node.target.id); + selectFromTargetTreeByIds(nodeIds); + //setTargetSelection(node.target) + } else { + nodeIds.push(node.source.id); + selectFromSourceTreeByIds(nodeIds); + //setSourceSelection(node.source) } - - const handleTreeSelect = (event: React.SyntheticEvent | undefined, nodeIds: string[], isSourceTree: boolean) => { - const newTreeSelection: RenderTree[] = []; - if (isSourceTree) { - sourceTreeData.forEach((item: RenderTree) => { - if (item.id === nodeIds.toString()) { - newTreeSelection.push(item); - } - }); - //setSourceSelection(newTreeSelection); - selectFromSourceTreeByIds(nodeIds); - } else { - targetTreeData.forEach((item: RenderTree) => { - if (item.id === nodeIds.toString()) { - newTreeSelection.push(item); - } - }); - //setTargetSelection(newTreeSelection); - selectFromTargetTreeByIds(nodeIds); + }; + + const handleExpandClick = (isSourceTree: boolean) => { + const retData: string[] = []; + if (isSourceTree) { + sourceTreeData.forEach(({ children, id }) => { + if (children && children?.length > 0) { + retData.push(id.toString()); } - }; - - const handleTreeToggle = (event: React.SyntheticEvent, nodeIds: string[], isSourceTree: boolean) => { - if (isSourceTree) { - setSourceExpanded(nodeIds); - } else { - setTargetExpanded(nodeIds); - } - }; - - const selectFromTreeById = (nodeId: string, isTargetTree: boolean) => { - const nodeIds = []; - nodeIds.push(nodeId); - if (isTargetTree) { - selectFromTargetTreeByIds(nodeIds); - } else { - selectFromSourceTreeByIds(nodeIds); + }); + setSourceExpanded((oldExpanded) => { + return oldExpanded.length === 0 ? retData : []; + }); + } else { + targetTreeData.forEach(({ children, id }) => { + if (children && children?.length > 0) { + retData.push(id.toString()); } - }; - - const selectFromTree = (node: CrosswalkConnectionNew, isTargetTree: boolean) => { - const nodeIds: React.SetStateAction<string[]> = []; - if (isTargetTree) { - nodeIds.push(node.target.id); - selectFromTargetTreeByIds(nodeIds); - //setTargetSelection(node.target) - } else { - nodeIds.push(node.source.id); - selectFromSourceTreeByIds(nodeIds); - //setSourceSelection(node.source) - } - }; - - const handleExpandClick = (isSourceTree: boolean) => { - const retData: string[] = []; - if (isSourceTree) { - sourceTreeData.forEach(({children, id}) => { - if (children && children?.length > 0) { - retData.push(id.toString()); - } - }); - setSourceExpanded((oldExpanded) => { - return oldExpanded.length === 0 ? retData : []; - }); - } else { - targetTreeData.forEach(({children, id}) => { - if (children && children?.length > 0) { - retData.push(id.toString()); - } - }); - setTargetExpanded((oldExpanded) => { - return oldExpanded.length === 0 ? retData : []; - }); + }); + setTargetExpanded((oldExpanded) => { + return oldExpanded.length === 0 ? retData : []; + }); + } + }; + + const setExpanded = (isSourceTree: boolean) => { + const retData: string[] = []; + if (isSourceTree) { + sourceTreeData.forEach(({ children, id }) => { + if (children && children?.length > 0) { + retData.push(id.toString()); } - }; - - const setExpanded = (isSourceTree: boolean) => { - const retData: string[] = []; - if (isSourceTree) { - sourceTreeData.forEach(({children, id}) => { - if (children && children?.length > 0) { - retData.push(id.toString()); - } - }); - setSourceExpanded(() => { - return retData; - }); - } else { - targetTreeData.forEach(({children, id}) => { - if (children && children?.length > 0) { - retData.push(id.toString()); - } - }); - setTargetExpanded(() => { - return retData; - }); + }); + setSourceExpanded(() => { + return retData; + }); + } else { + targetTreeData.forEach(({ children, id }) => { + if (children && children?.length > 0) { + retData.push(id.toString()); } - }; - - function saveCroswalk() { - console.log('save clicked'); + }); + setTargetExpanded(() => { + return retData; + }); } - - function loadCroswalk() { - fetchCrosswalkData('organizations').then(data => { - setTargetData(inputData); - setSourceData(inputData); - - setExpanded(true); - setExpanded(false); - setConnectedCrosswalksNew([]); - clearSelections(); - }); + }; + + function saveCroswalk() { + console.log('save clicked'); + } + + function loadCroswalk() { + fetchCrosswalkData('organizations').then((data) => { + setTargetData(inputData); + setSourceData(inputData); + + setExpanded(true); + setExpanded(false); + setConnectedCrosswalksNew([]); + clearSelections(); + }); + } + + function loadAvailableFilters() { + console.log('loadAvailableFilters called'); + } + + function filterTreeData( + treeData: RenderTree[], + keywords: string[], + index: number, + isSourceTree: boolean + ) { + let ret = undefined; + treeData = treeData.filter((elem: { name: string; jsonPath: string }) => { + if (elem.jsonPath.startsWith(keywords[index])) { + return elem; + } + }); + + if (treeData[0] && treeData[0].jsonPath === keywords[keywords.length - 1]) { + ret = cloneDeep(buildPathToSubtrees(treeData, isSourceTree)); } - function loadAvailableFilters() { - console.log('loadAvailableFilters called'); + if (treeData[0]?.children && treeData[0].children.length > 0) { + filterTreeData(treeData[0].children, keywords, index + 1, isSourceTree); } - - function filterTreeData(treeData: RenderTree[], keywords: string[], index: number, isSourceTree: boolean) { - let ret = undefined; - treeData = treeData.filter((elem: { name: string; jsonPath: string }) => { - if (elem.jsonPath.startsWith(keywords[index])) { - return elem; - } - }); - - if (treeData[0] && treeData[0].jsonPath === keywords[keywords.length - 1]) { - ret = cloneDeep(buildPathToSubtrees(treeData, isSourceTree)); - } - - if (treeData[0]?.children && treeData[0].children.length > 0) { - filterTreeData(treeData[0].children, keywords, index + 1, isSourceTree); - } + } + + function buildPathToSubtrees(treeData: RenderTree[], isSourceTree: boolean) { + const jsonPathReady: string[] = []; + const jsonPathPieces = treeData[0].jsonPath.split('.'); + let prev = ''; + + for (let i = 0; i < jsonPathPieces.length; i += 1) { + if (i > 0) { + prev = prev + '.' + jsonPathPieces[i]; + jsonPathReady.push(prev); + } else { + prev = jsonPathPieces[i]; + jsonPathReady.push(prev); + } } - function buildPathToSubtrees(treeData: RenderTree[], isSourceTree: boolean) { - const jsonPathReady: string[] = []; - const jsonPathPieces = treeData[0].jsonPath.split('.'); - let prev = ''; - - for (let i = 0; i < jsonPathPieces.length; i += 1) { - if (i > 0) { - prev = prev + '.' + jsonPathPieces[i]; - jsonPathReady.push(prev); - } else { - prev = jsonPathPieces[i]; - jsonPathReady.push(prev); - } + const pathObjects: RenderTree[] = []; + if (isSourceTree) { + sourceTreeData.forEach((elem) => { + if (jsonPathReady.includes(elem.jsonPath)) { + console.log('final match', elem); + pathObjects.push(elem); } - - const pathObjects: RenderTree[] = []; - if (isSourceTree) { - sourceTreeData.forEach(elem => { - if (jsonPathReady.includes(elem.jsonPath)) { - console.log('final match', elem); - pathObjects.push(elem); - } - }); - setSourceData(pathObjects); - return pathObjects; - } else { - targetTreeData.forEach(elem => { - if (jsonPathReady.includes(elem.jsonPath)) { - console.log('final match', elem); - pathObjects.push(elem); - } - }); - setTargetData(pathObjects); - return pathObjects; + }); + setSourceData(pathObjects); + return pathObjects; + } else { + targetTreeData.forEach((elem) => { + if (jsonPathReady.includes(elem.jsonPath)) { + console.log('final match', elem); + pathObjects.push(elem); } + }); + setTargetData(pathObjects); + return pathObjects; } - - function clearTreeSearch(isSourceTree: boolean) { - if (isSourceTree) { - setSourceData(sourceTreeDataOriginal); - setExpanded(true); - } else { - setTargetData(targetTreeDataOriginal); - setExpanded(false); - } + } + + function clearTreeSearch(isSourceTree: boolean) { + if (isSourceTree) { + setSourceData(sourceTreeDataOriginal); + setExpanded(true); + } else { + setTargetData(targetTreeDataOriginal); + setExpanded(false); } + } - function searchFromTree(input: any, isSourceTree: boolean) { - //clearTreeSearch(isSourceTree); + function searchFromTree(input: any, isSourceTree: boolean) { + //clearTreeSearch(isSourceTree); - //setSourceData(MockupSchemaLoader(true)); - let treeDataNew: any; + //setSourceData(MockupSchemaLoader(true)); + let treeDataNew: any; - const hits: string[] = []; + const hits: string[] = []; - if (isSourceTree) { - sourceTreeData.forEach((elem: { name: string; jsonPath: string }) => { - if (elem.name.includes(input.toString())) { - hits.push(elem.jsonPath); - } - }); - } else { - targetTreeData.forEach((elem: { name: string; jsonPath: string }) => { - if (elem.name.includes(input.toString())) { - hits.push(elem.jsonPath); - } - }); + if (isSourceTree) { + sourceTreeData.forEach((elem: { name: string; jsonPath: string }) => { + if (elem.name.includes(input.toString())) { + hits.push(elem.jsonPath); } - - const nodesToProcess: string[][] = []; - hits.forEach(hit => { - const treeNodeNames = hit.split('.'); - nodesToProcess.push(treeNodeNames); - }); - - const nodesToProcessUnique: Set<string> = new Set(); - - nodesToProcess.forEach(path => { - let prev = ''; - for (let i = 0; i < path.length; i += 1) { - if (i > 0) { - prev = prev + '.' + path[i]; - nodesToProcessUnique.add(prev); - } else { - prev = path[i]; - nodesToProcessUnique.add(prev); - } - } - }); - - // FOUND MATCHING SUBTREES - treeDataNew = filterTreeData(isSourceTree ? sourceTreeData : targetTreeData, Array.from(nodesToProcessUnique), 0, isSourceTree); - - if (treeDataNew && treeDataNew.length > 0) { - if (isSourceTree) { - //setSourceData(treeDataNew) - } else { - //setTargetData(treeDataNew) - } + }); + } else { + targetTreeData.forEach((elem: { name: string; jsonPath: string }) => { + if (elem.name.includes(input.toString())) { + hits.push(elem.jsonPath); } + }); } - function clearSelections() { - selectFromSourceTreeByIds([]); - selectFromTargetTreeByIds([]); - } + const nodesToProcess: string[][] = []; + hits.forEach((hit) => { + const treeNodeNames = hit.split('.'); + nodesToProcess.push(treeNodeNames); + }); - const performCallbackFromAccordionAction = (joint: any, action: string, value: string) => { - if (action === 'remove') { - removeJoint(joint); - } else if (action === 'addNotes') { - joint.notes = value; - updateJointData(joint); - } else if (action === 'selectFromSourceTree') { - //handleExpandClick(true); - clearTreeSearch(true); - selectFromTree(joint, false); - } else if (action === 'selectFromTargetTree') { - //handleExpandClick(false); - clearTreeSearch(false); - selectFromTree(joint, true); - } else if (action === 'openJointDetails') { - setJointSelected(joint.id); - setJointToBeEdited(getJointSelected(joint.id)); - //scrollToTop(); - } else if (action === 'removeJoint') { - removeJoint(joint.id); - } - }; - - const performCallbackFromTreeAction = (isSourceTree: boolean, action: any, event: any, nodeIds: any) => { - if (action === 'handleSelect') { - handleTreeSelect(event, nodeIds, isSourceTree); - } else if (action === 'treeToggle') { - handleTreeToggle(event, nodeIds, isSourceTree); - } - }; - - const performCallbackFromMappingModal = (action: any, event: any, crosswalkConnection: any) => { - if (action === 'closeModal') { - setNodeMappingsModalOpen(false); - } - if (action === 'save') { - setNodeMappingsModalOpen(false); - setConnectedCrosswalksNew(crosswalkMappings => [jointToBeEdited, ...crosswalkMappings]); - } - }; + const nodesToProcessUnique: Set<string> = new Set(); - const performMetadataAndFilesAction = (action: any, event: any, crosswalkConnection: any) => { - if (action === 'save') { + nodesToProcess.forEach((path) => { + let prev = ''; + for (let i = 0; i < path.length; i += 1) { + if (i > 0) { + prev = prev + '.' + path[i]; + nodesToProcessUnique.add(prev); + } else { + prev = path[i]; + nodesToProcessUnique.add(prev); } - }; + } + }); + + // FOUND MATCHING SUBTREES + treeDataNew = filterTreeData( + isSourceTree ? sourceTreeData : targetTreeData, + Array.from(nodesToProcessUnique), + 0, + isSourceTree + ); - interface TabPanelProps { - children?: React.ReactNode; - index: number; - value: number; + if (treeDataNew && treeDataNew.length > 0) { + if (isSourceTree) { + //setSourceData(treeDataNew) + } else { + //setTargetData(treeDataNew) + } } - - function CustomTabPanel(props: TabPanelProps) { - const {children, value, index, ...other} = props; - - return ( - <div - role="tabpanel" - hidden={value !== index} - id={`simple-tabpanel-${index}`} - aria-labelledby={`simple-tab-${index}`} - {...other} - > - {value === index && ( - <Box sx={{p: 3}}> - <Typography>{children}</Typography> - </Box> - )} - </div> - ); + } + + function clearSelections() { + selectFromSourceTreeByIds([]); + selectFromTargetTreeByIds([]); + } + + const performCallbackFromAccordionAction = ( + joint: any, + action: string, + value: string + ) => { + if (action === 'remove') { + removeJoint(joint); + } else if (action === 'addNotes') { + joint.notes = value; + updateJointData(joint); + } else if (action === 'selectFromSourceTree') { + //handleExpandClick(true); + clearTreeSearch(true); + selectFromTree(joint, false); + } else if (action === 'selectFromTargetTree') { + //handleExpandClick(false); + clearTreeSearch(false); + selectFromTree(joint, true); + } else if (action === 'openJointDetails') { + setJointSelected(joint.id); + setJointToBeEdited(getJointSelected(joint.id)); + //scrollToTop(); + } else if (action === 'removeJoint') { + removeJoint(joint.id); } - - function a11yProps(index: number) { - return { - id: `simple-tab-${index}`, - 'aria-controls': `simple-tabpanel-${index}`, - }; + }; + + const performCallbackFromTreeAction = ( + isSourceTree: boolean, + action: any, + event: any, + nodeIds: any + ) => { + if (action === 'handleSelect') { + handleTreeSelect(event, nodeIds, isSourceTree); + } else if (action === 'treeToggle') { + handleTreeToggle(event, nodeIds, isSourceTree); } - - const changeTab = (event: React.SyntheticEvent | undefined, newValue: number) => { - setSelectedTab(newValue); - }; - - const performNodeInfoAction = (nodeId: any, isSourceTree: boolean) => { - selectFromTreeById(nodeId, isSourceTree); + }; + + const performCallbackFromMappingModal = ( + action: any, + event: any, + crosswalkConnection: any + ) => { + if (action === 'closeModal') { + setNodeMappingsModalOpen(false); } + if (action === 'save') { + setNodeMappingsModalOpen(false); + setConnectedCrosswalksNew((crosswalkMappings) => [ + jointToBeEdited, + ...crosswalkMappings, + ]); + } + }; + + const performMetadataAndFilesAction = ( + action: any, + event: any, + crosswalkConnection: any + ) => { + if (action === 'save') { + } + }; - const scrollToTop = () => { - window.scrollTo({ - top: 0, - behavior: 'smooth', - }); - }; - + interface TabPanelProps { + children?: React.ReactNode; + index: number; + value: number; + } + function CustomTabPanel(props: TabPanelProps) { + const { children, value, index, ...other } = props; return ( - <><Box className='mb-3' sx={{borderBottom: 1, borderColor: 'divider'}}> - <Tabs value={selectedTab} onChange={changeTab} aria-label="Category selection"> - <Tab label="Metadata & files" {...a11yProps(0)} /> - <Tab label="Crosswalks" {...a11yProps(1)} /> - <Tab label="Version history" {...a11yProps(2)} /> - </Tabs> - </Box> - {selectedTab === 0 && isSourceDataFetched && - <> - <MetadataAndFiles crosswalks={connectedCrosswalksNew} - performMetadataAndFilesAction={performMetadataAndFilesAction}/> - </> - } - {/* <CustomTabPanel value={selectedTab} index={0}> + <div + role="tabpanel" + hidden={value !== index} + id={`simple-tabpanel-${index}`} + aria-labelledby={`simple-tab-${index}`} + {...other} + > + {value === index && ( + <Box sx={{ p: 3 }}> + <Typography>{children}</Typography> + </Box> + )} + </div> + ); + } + + function a11yProps(index: number) { + return { + id: `simple-tab-${index}`, + 'aria-controls': `simple-tabpanel-${index}`, + }; + } + + const changeTab = ( + event: React.SyntheticEvent | undefined, + newValue: number + ) => { + setSelectedTab(newValue); + }; + + const performNodeInfoAction = (nodeId: any, isSourceTree: boolean) => { + selectFromTreeById(nodeId, isSourceTree); + }; + + const scrollToTop = () => { + window.scrollTo({ + top: 0, + behavior: 'smooth', + }); + }; + + return ( + <> + <Box className="mb-3" sx={{ borderBottom: 1, borderColor: 'divider' }}> + <Tabs + value={selectedTab} + onChange={changeTab} + aria-label="Category selection" + > + <Tab label="Metadata & files" {...a11yProps(0)} /> + <Tab label="Crosswalks" {...a11yProps(1)} /> + <Tab label="Version history" {...a11yProps(2)} /> + </Tabs> + </Box> + {selectedTab === 0 && isSourceDataFetched && ( + <> + <MetadataAndFiles + crosswalks={connectedCrosswalksNew} + performMetadataAndFilesAction={performMetadataAndFilesAction} + /> + </> + )} + {/* <CustomTabPanel value={selectedTab} index={0}> </CustomTabPanel> <CustomTabPanel value={selectedTab} index={1}> </CustomTabPanel> <CustomTabPanel value={selectedTab} index={2}> </CustomTabPanel>*/} - <div className='row d-flex justify-content-between mt-4 crosswalk-editor'> - {/* LEFT COLUMN */} - <div className={(isEditModeActive && selectedTab === 1) ? 'col-12' : 'd-none'}> - {isSourceDataFetched && - <> - <div className='row gx-0'> - </div> - <div className='row gx-0'> - {/* SOURCE TREE */} - <div className='col-5 ps-4'> - <div> - <div className="row content-box"> - <div className="col-7 px-0"> - <div className="d-flex justify-content-between mb-2 ps-3 pe-2"> - <div className='w-100'> - <SearchInput - className="py-2" - labelText="Filter from source schema" - searchButtonLabel="Search" - clearButtonLabel="Clear" - visualPlaceholder="Find an attribute..." - onSearch={(value) => { - searchFromTree(value, true); - }} - onChange={(value) => { - if (!value) { - clearTreeSearch(true); - } - }} - /> - </div> - <div className="expand-button-wrap"> - <IconButton onClick={() => handleExpandClick(true)} - aria-label="unlink" - color="primary" size="large"> - {sourceTreeExpanded.length === 0 ? <ExpandMoreIcon/> : - <ExpandLessIcon/>} - </IconButton> - </div> - </div> - <div className="mx-2"> - <Box sx={{ - height: 400, - flexGrow: 1, - maxWidth: 700, - overflowY: 'auto' - }}> - - <SchemaTree nodes={sourceTreeData[0]} - isSourceTree={true} - treeSelectedArray={sourceTreeSelectedArray} - treeExpanded={sourceTreeExpanded} - performTreeAction={performCallbackFromTreeAction} - /> - - </Box> - </div> - </div> - <div className="col-5 px-0 node-info-wrap"> - <NodeInfo isAnySelectedLinked={isAnySelectedLinked} - isBothSelectedLinked={isBothSelectedLinked} - sourceData={selectedSourceNodes} - isSourceTree={true} - targetData={selectedTargetNodes} - performNodeInfoAction={performNodeInfoAction}></NodeInfo> - </div> - </div> - </div> - </div> - - {/* MID BUTTONS */} - <div className='col-2 px-4 mid-buttons'> - <Sbutton className='link-button' disabled={(linkingError.length > 1)} - title={(linkingError.length > 1 ? linkingError : 'Link selected nodes')} - onClick={() => { - addJoint(!isBothSelectedLinked); - }}><LinkIcon></LinkIcon></Sbutton> - </div> - - {/* TARGET TREE */} - <div className='col-5 pe-4'> - <div> - <div className="row content-box"> - <div className="col-7 px-0"> - <div className="d-flex justify-content-between mb-2 ps-3 pe-2"> - <div className='w-100'> - <SearchInput - className="py-2" - labelText="Filter from target schema" - searchButtonLabel="Search" - clearButtonLabel="Clear" - onSearch={(value) => { - searchFromTree(value, false); - }} - visualPlaceholder="Find an attribute..." - onChange={(value) => { - if (!value) { - clearTreeSearch(false); - } - }} - /> - - </div> - <div className="expand-button-wrap"> - <IconButton onClick={() => handleExpandClick(false)} - aria-label="unlink" - color="primary" size="large"> - {targetTreeExpanded.length === 0 ? <ExpandMoreIcon/> : - <ExpandLessIcon/>} - </IconButton> - </div> - </div> - <div className="mx-2"> - <Box sx={{ - height: 400, - flexGrow: 1, - maxWidth: 700, - overflowY: 'auto' - }}> - <SchemaTree - nodes={targetTreeData[0]} - isSourceTree={false} - treeSelectedArray={targetTreeSelectedArray} - treeExpanded={targetTreeExpanded} - performTreeAction={performCallbackFromTreeAction} - /> - - </Box> - </div> - </div> - <div className="col-5 px-0 node-info-wrap"> - - <NodeInfo isAnySelectedLinked={isAnySelectedLinked} - isBothSelectedLinked={isBothSelectedLinked} - sourceData={selectedSourceNodes} - isSourceTree={false} - targetData={selectedTargetNodes} - performNodeInfoAction={performNodeInfoAction}></NodeInfo> - - </div> - </div> - </div> - </div> - </div> - </> - } - {jointToBeEdited && <> - <NodeMappingsModal selectedCrosswalk={jointToBeEdited} - performNodeInfoAction={performCallbackFromMappingModal} - filterFunctions={filterFunctions} - modalOpen={nodeMappingsModalOpen} - isFirstAdd={false}></NodeMappingsModal> - </> + <div className="row d-flex justify-content-between mt-4 crosswalk-editor"> + {/* LEFT COLUMN */} + <div + className={ + isEditModeActive && selectedTab === 1 ? 'col-12' : 'd-none' + } + > + {isSourceDataFetched && ( + <> + <div className="row gx-0"></div> + <div className="row gx-0"> + {/* SOURCE TREE */} + <div className="col-5 ps-4"> + <div> + <div className="row content-box"> + <div className="col-7 px-0"> + <div className="d-flex justify-content-between mb-2 ps-3 pe-2"> + <div className="w-100"> + <SearchInput + className="py-2" + labelText="Filter from source schema" + searchButtonLabel="Search" + clearButtonLabel="Clear" + visualPlaceholder="Find an attribute..." + onSearch={(value) => { + searchFromTree(value, true); + }} + onChange={(value) => { + if (!value) { + clearTreeSearch(true); + } + }} + /> + </div> + <div className="expand-button-wrap"> + <IconButton + onClick={() => handleExpandClick(true)} + aria-label="unlink" + color="primary" + size="large" + > + {sourceTreeExpanded.length === 0 ? ( + <ExpandMoreIcon /> + ) : ( + <ExpandLessIcon /> + )} + </IconButton> + </div> + </div> + <div className="mx-2"> + <Box + sx={{ + height: 400, + flexGrow: 1, + maxWidth: 700, + overflowY: 'auto', + }} + > + <SchemaTree + nodes={sourceTreeData[0]} + isSourceTree={true} + treeSelectedArray={sourceTreeSelectedArray} + treeExpanded={sourceTreeExpanded} + performTreeAction={performCallbackFromTreeAction} + /> + </Box> + </div> + </div> + <div className="col-5 px-0 node-info-wrap"> + <NodeInfo + isAnySelectedLinked={isAnySelectedLinked} + isBothSelectedLinked={isBothSelectedLinked} + sourceData={selectedSourceNodes} + isSourceTree={true} + targetData={selectedTargetNodes} + performNodeInfoAction={performNodeInfoAction} + ></NodeInfo> + </div> + </div> + </div> + </div> + + {/* MID BUTTONS */} + <div className="col-2 px-4 mid-buttons"> + <Sbutton + className="link-button" + disabled={linkingError.length > 1} + title={ + linkingError.length > 1 + ? linkingError + : 'Link selected nodes' } + onClick={() => { + addJoint(!isBothSelectedLinked); + }} + > + <LinkIcon></LinkIcon> + </Sbutton> </div> - {/* BOTTOM COLUMN */} - {selectedTab === 1 && <> - <div className='col-12 px-4 mt-4'> - <h2>Mappings</h2> - <div className='joint-listing-accordion-wrap my-3'> - <Box className='mb-4' sx={{height: 640, flexGrow: 1, overflowY: 'auto'}}> - <JointListingAccordion crosswalkJoints={connectedCrosswalksNew} viewOnlyMode={false} isEditModeActive={isEditModeActive} - performAccordionAction={performCallbackFromAccordionAction}></JointListingAccordion> - </Box> + {/* TARGET TREE */} + <div className="col-5 pe-4"> + <div> + <div className="row content-box"> + <div className="col-7 px-0"> + <div className="d-flex justify-content-between mb-2 ps-3 pe-2"> + <div className="w-100"> + <SearchInput + className="py-2" + labelText="Filter from target schema" + searchButtonLabel="Search" + clearButtonLabel="Clear" + onSearch={(value) => { + searchFromTree(value, false); + }} + visualPlaceholder="Find an attribute..." + onChange={(value) => { + if (!value) { + clearTreeSearch(false); + } + }} + /> + </div> + <div className="expand-button-wrap"> + <IconButton + onClick={() => handleExpandClick(false)} + aria-label="unlink" + color="primary" + size="large" + > + {targetTreeExpanded.length === 0 ? ( + <ExpandMoreIcon /> + ) : ( + <ExpandLessIcon /> + )} + </IconButton> + </div> </div> + <div className="mx-2"> + <Box + sx={{ + height: 400, + flexGrow: 1, + maxWidth: 700, + overflowY: 'auto', + }} + > + <SchemaTree + nodes={targetTreeData[0]} + isSourceTree={false} + treeSelectedArray={targetTreeSelectedArray} + treeExpanded={targetTreeExpanded} + performTreeAction={performCallbackFromTreeAction} + /> + </Box> + </div> + </div> + <div className="col-5 px-0 node-info-wrap"> + <NodeInfo + isAnySelectedLinked={isAnySelectedLinked} + isBothSelectedLinked={isBothSelectedLinked} + sourceData={selectedSourceNodes} + isSourceTree={false} + targetData={selectedTargetNodes} + performNodeInfoAction={performNodeInfoAction} + ></NodeInfo> + </div> </div> - </>} - </div> - <div className='fixed-footer'> - <div className='row'> - <div className='col-10'> - </div> - <div className='col-2 d-flex flex-row justify-content-end'> - <Sbutton hidden={isEditModeActive} onClick={() => { - setEditModeActive(true); - }}>Edit</Sbutton> - <Sbutton hidden={!isEditModeActive} variant="secondary" onClick={() => { - setEditModeActive(false); - }}>Publish</Sbutton> - <Sbutton hidden={!isEditModeActive} onClick={() => { - setEditModeActive(false); - }}>Save</Sbutton> - </div> + </div> </div> + </div> + </> + )} + {jointToBeEdited && ( + <> + <NodeMappingsModal + selectedCrosswalk={jointToBeEdited} + performNodeInfoAction={performCallbackFromMappingModal} + filterFunctions={filterFunctions} + modalOpen={nodeMappingsModalOpen} + isFirstAdd={false} + ></NodeMappingsModal> + </> + )} + </div> + + {/* BOTTOM COLUMN */} + {selectedTab === 1 && ( + <> + <div className="col-12 px-4 mt-4"> + <h2>Mappings</h2> + <div className="joint-listing-accordion-wrap my-3"> + <Box + className="mb-4" + sx={{ height: 640, flexGrow: 1, overflowY: 'auto' }} + > + <JointListingAccordion + crosswalkJoints={connectedCrosswalksNew} + viewOnlyMode={false} + isEditModeActive={isEditModeActive} + performAccordionAction={performCallbackFromAccordionAction} + ></JointListingAccordion> + </Box> + </div> </div> - </> - ); + </> + )} + </div> + <div className="fixed-footer"> + <div className="row"> + <div className="col-10"></div> + <div className="col-2 d-flex flex-row justify-content-end"> + <Sbutton + hidden={isEditModeActive} + onClick={() => { + setEditModeActive(true); + }} + > + Edit + </Sbutton> + <Sbutton + hidden={!isEditModeActive} + variant="secondary" + onClick={() => { + setEditModeActive(false); + }} + > + Publish + </Sbutton> + <Sbutton + hidden={!isEditModeActive} + onClick={() => { + setEditModeActive(false); + }} + > + Save + </Sbutton> + </div> + </div> + </div> + </> + ); } diff --git a/mscr-ui/src/modules/crosswalk-editor/joint-listing-accordion/index.tsx b/mscr-ui/src/modules/crosswalk-editor/joint-listing-accordion/index.tsx index 9c4050170..995528511 100644 --- a/mscr-ui/src/modules/crosswalk-editor/joint-listing-accordion/index.tsx +++ b/mscr-ui/src/modules/crosswalk-editor/joint-listing-accordion/index.tsx @@ -11,86 +11,98 @@ import Typography from '@mui/material/Typography'; import Paper from '@mui/material/Paper'; import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp'; -import {styled} from '@mui/material'; -import TableCell, {tableCellClasses} from '@mui/material/TableCell'; +import { styled } from '@mui/material'; +import TableCell, { tableCellClasses } from '@mui/material/TableCell'; import LinkOffIcon from '@mui/icons-material/LinkOff'; import AddLinkIcon from '@mui/icons-material/AddLink'; import RadioButtonUncheckedIcon from '@mui/icons-material/RadioButtonUnchecked'; import RadioButtonCheckedIcon from '@mui/icons-material/RadioButtonChecked'; -import {Button as Sbutton, Textarea, TextInput} from 'suomifi-ui-components'; +import { Button as Sbutton, Textarea, TextInput } from 'suomifi-ui-components'; import Button from '@mui/material/Button'; import ReportProblemIcon from '@mui/icons-material/ReportProblem'; import CheckIcon from '@mui/icons-material/Check'; import EditRoundedIcon from '@mui/icons-material/EditRounded'; - import { - CrosswalkConnection, - CrosswalkConnectionNew, - RenderTree + CrosswalkConnection, + CrosswalkConnectionNew, + RenderTree, } from '@app/common/interfaces/crosswalk-connection.interface'; -import {InfoIcon} from '@app/common/components/shared-icons'; +import { InfoIcon } from '@app/common/components/shared-icons'; const crosswalkConnectionInit = { - source: '', - target: '', - sourceTitle: '', - targetTitle: '', - type: '', - notes: '', - title: '', + source: '', + target: '', + sourceTitle: '', + targetTitle: '', + type: '', + notes: '', + title: '', }; -const StyledTableCell = styled(TableCell)(({theme}) => ({ - -})); +const StyledTableCell = styled(TableCell)(({ theme }) => ({})); -const StyledTableRow = styled(TableRow)(({theme}) => ({ - '&:nth-of-type(odd)': { - //backgroundColor: theme.palette.action.hover, - }, - // hide last border - '&:last-child td, &:last-child th': { - border: 0, - }, +const StyledTableRow = styled(TableRow)(({ theme }) => ({ + '&:nth-of-type(odd)': { + //backgroundColor: theme.palette.action.hover, + }, + // hide last border + '&:last-child td, &:last-child th': { + border: 0, + }, })); -function Row(props: { row: CrosswalkConnectionNew; viewOnlyMode: boolean; isEditModeActive: boolean; cbf: any }) { - const {row} = props; - const [open, setOpen] = React.useState(row.isSelected); - const [changedNotes, setChangedNotes] = React.useState<string>(''); - const addNotes = 'addNotes'; - - return ( - <React.Fragment> - <StyledTableRow className='accordion-row'> - <StyledTableCell className='col-5 ps-4'> - <Button className='ms-2 py-0' style={{textTransform: 'none'}} - title='Select linked node from source tree' - onClick={(e) => { - props.cbf.performAccordionAction(row, 'selectFromSourceTree'); - e.stopPropagation(); - }}>{row.source.name}</Button> - </StyledTableCell> - - {/* <StyledTableCell className='fw-bold' style={{width: '10%'}}> +function Row(props: { + row: CrosswalkConnectionNew; + viewOnlyMode: boolean; + isEditModeActive: boolean; + cbf: any; +}) { + const { row } = props; + const [open, setOpen] = React.useState(row.isSelected); + const [changedNotes, setChangedNotes] = React.useState<string>(''); + const addNotes = 'addNotes'; + + return ( + <React.Fragment> + <StyledTableRow className="accordion-row"> + <StyledTableCell className="col-5 ps-4"> + <Button + className="ms-2 py-0" + style={{ textTransform: 'none' }} + title="Select linked node from source tree" + onClick={(e) => { + props.cbf.performAccordionAction(row, 'selectFromSourceTree'); + e.stopPropagation(); + }} + > + {row.source.name} + </Button> + </StyledTableCell> + + {/* <StyledTableCell className='fw-bold' style={{width: '10%'}}> <IconButton onClick={(e) => {props.cbf.performAccordionAction(row, 'remove'); e.stopPropagation();}} aria-label="unlink" color="primary" title='Unlink nodes' size="large"> <LinkOffIcon/> </IconButton> </StyledTableCell>*/} - <StyledTableCell className='col-4 ps-4'> - <Button className='me-2 py-0' style={{textTransform: 'none'}} - title='Select linked node from target tree' - onClick={(e) => { - props.cbf.performAccordionAction(row, 'selectFromTargetTree'); - e.stopPropagation(); - }}>{row.target.name}</Button> - </StyledTableCell> - - <StyledTableCell className='col-1'> - {/*<IconButton + <StyledTableCell className="col-4 ps-4"> + <Button + className="me-2 py-0" + style={{ textTransform: 'none' }} + title="Select linked node from target tree" + onClick={(e) => { + props.cbf.performAccordionAction(row, 'selectFromTargetTree'); + e.stopPropagation(); + }} + > + {row.target.name} + </Button> + </StyledTableCell> + + <StyledTableCell className="col-1"> + {/*<IconButton aria-label="expand row" size="small" onClick={(e) => { @@ -99,98 +111,130 @@ function Row(props: { row: CrosswalkConnectionNew; viewOnlyMode: boolean; isEdit > {row.isSelected ? <EditRoundedIcon className='selection-active'/> : <EditRoundedIcon/>} </IconButton>*/} - </StyledTableCell> - - <StyledTableCell className='col-2 fw-bold d-flex justify-content-end'> - <IconButton - hidden={props.viewOnlyMode} - aria-label="expand row" - size="small" - onClick={(e) => { - setOpen(!open); - e.stopPropagation(); - }} - > - {open ? <KeyboardArrowUpIcon/> : <KeyboardArrowDownIcon/>} - </IconButton> - </StyledTableCell> - </StyledTableRow> - - <StyledTableRow> - <TableCell className='accordion-fold-content'> - <Collapse in={open && !props.viewOnlyMode} timeout="auto" unmountOnExit> - <div className='row'> - <div className='col-10'> - <Box sx={{margin: 1}}> - <div className='fw-bold mt-3 mb-2' style={{fontSize: '0.9em'}}>Mapping type: <span - className='fw-normal'>exact match</span></div> - <br/> - </Box> - </div> - <div className='col-2 mt-4 d-flex flex-column action-buttons'> - <Sbutton - hidden={!props.isEditModeActive} - onClick={(e) => { - props.cbf.performAccordionAction(row, 'openJointDetails'); - }}>Edit</Sbutton> - <Sbutton className='mt-2' - hidden={!props.isEditModeActive} - onClick={(e) => { - props.cbf.performAccordionAction(row, 'removeJoint'); - }}>Delete</Sbutton> - </div> - </div> - </Collapse> - </TableCell> - </StyledTableRow> - </React.Fragment> - ); + </StyledTableCell> + + <StyledTableCell className="col-2 fw-bold d-flex justify-content-end"> + <IconButton + hidden={props.viewOnlyMode} + aria-label="expand row" + size="small" + onClick={(e) => { + setOpen(!open); + e.stopPropagation(); + }} + > + {open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />} + </IconButton> + </StyledTableCell> + </StyledTableRow> + + <StyledTableRow> + <TableCell className="accordion-fold-content"> + <Collapse + in={open && !props.viewOnlyMode} + timeout="auto" + unmountOnExit + > + <div className="row"> + <div className="col-10"> + <Box sx={{ margin: 1 }}> + <div + className="fw-bold mt-3 mb-2" + style={{ fontSize: '0.9em' }} + > + Mapping type: <span className="fw-normal">exact match</span> + </div> + <br /> + </Box> + </div> + <div className="col-2 mt-4 d-flex flex-column action-buttons"> + <Sbutton + hidden={!props.isEditModeActive} + onClick={(e) => { + props.cbf.performAccordionAction(row, 'openJointDetails'); + }} + > + Edit + </Sbutton> + <Sbutton + className="mt-2" + hidden={!props.isEditModeActive} + onClick={(e) => { + props.cbf.performAccordionAction(row, 'removeJoint'); + }} + > + Delete + </Sbutton> + </div> + </div> + </Collapse> + </TableCell> + </StyledTableRow> + </React.Fragment> + ); } -let rows = [{...crosswalkConnectionInit}]; +let rows = [{ ...crosswalkConnectionInit }]; function createCrosswalkAccorionData(crosswalkInput: any) { - rows = [{...crosswalkInput}]; + rows = [{ ...crosswalkInput }]; } export default function JointListingAccordion(props: any) { - if (props.crosswalkJoints.length > 0) { - createCrosswalkAccorionData(props.crosswalkJoints); - // return LinkedNodesTable(props.crosswalkJoints); - } - - const crosswalkJointsInput = props.crosswalkJoints; - - return (<> - <TableContainer component={Paper}> - <Table aria-label="collapsible table w-100"> - <TableHead> - <TableRow className='accordion-row row'> - <StyledTableCell className='col-5'><span - className='fw-bold ps-4'>Source</span></StyledTableCell> - <StyledTableCell className='col-4'><span - className='fw-bold ps-4'>Target</span></StyledTableCell> - <StyledTableCell className='col-1'></StyledTableCell> - <StyledTableCell className='col-2'></StyledTableCell> - </TableRow> - </TableHead> - - {crosswalkJointsInput?.length > 0 && - <TableBody> - {crosswalkJointsInput.map((row: CrosswalkConnectionNew) => { - return (<Row key={row.id} row={row} viewOnlyMode={props.viewOnlyMode} isEditModeActive={props.isEditModeActive} cbf={props}/>); - })} - </TableBody> - } - {crosswalkJointsInput?.length < 1 && - <TableBody> - <TableRow className=''> - <div className='empty-mappings-table'><span className='info-icon'><InfoIcon></InfoIcon></span>No elements have been mapped yet. Mappings will appear in this table.</div> - </TableRow> - </TableBody> - } - </Table> - </TableContainer> - </> - ); + if (props.crosswalkJoints.length > 0) { + createCrosswalkAccorionData(props.crosswalkJoints); + // return LinkedNodesTable(props.crosswalkJoints); + } + + const crosswalkJointsInput = props.crosswalkJoints; + + return ( + <> + <TableContainer component={Paper}> + <Table aria-label="collapsible table w-100"> + <TableHead> + <TableRow className="accordion-row row"> + <StyledTableCell className="col-5"> + <span className="fw-bold ps-4">Source</span> + </StyledTableCell> + <StyledTableCell className="col-4"> + <span className="fw-bold ps-4">Target</span> + </StyledTableCell> + <StyledTableCell className="col-1"></StyledTableCell> + <StyledTableCell className="col-2"></StyledTableCell> + </TableRow> + </TableHead> + + {crosswalkJointsInput?.length > 0 && ( + <TableBody> + {crosswalkJointsInput.map((row: CrosswalkConnectionNew) => { + return ( + <Row + key={row.id} + row={row} + viewOnlyMode={props.viewOnlyMode} + isEditModeActive={props.isEditModeActive} + cbf={props} + /> + ); + })} + </TableBody> + )} + {crosswalkJointsInput?.length < 1 && ( + <TableBody> + <TableRow className=""> + <div className="empty-mappings-table"> + <span className="info-icon"> + <InfoIcon></InfoIcon> + </span> + No elements have been mapped yet. Mappings will appear in this + table. + </div> + </TableRow> + </TableBody> + )} + </Table> + </TableContainer> + </> + ); } diff --git a/mscr-ui/src/modules/crosswalk-editor/mapping-validator/index.tsx b/mscr-ui/src/modules/crosswalk-editor/mapping-validator/index.tsx index b2064d791..c00305053 100644 --- a/mscr-ui/src/modules/crosswalk-editor/mapping-validator/index.tsx +++ b/mscr-ui/src/modules/crosswalk-editor/mapping-validator/index.tsx @@ -1,14 +1,11 @@ -import { - CrosswalkConnectionNew -} from '@app/common/interfaces/crosswalk-connection.interface'; +import { CrosswalkConnectionNew } from '@app/common/interfaces/crosswalk-connection.interface'; export default function validateMapping(input: CrosswalkConnectionNew) { - const validationErrors: string[] = []; - if (input.source.type === input.target.type) { - console.log('is valid'); - } - else { - validationErrors.push('Type mismatch'); - } - return validationErrors; + const validationErrors: string[] = []; + if (input.source.type === input.target.type) { + console.log('is valid'); + } else { + validationErrors.push('Type mismatch'); + } + return validationErrors; } diff --git a/mscr-ui/src/modules/crosswalk-editor/schema-mockup.tsx b/mscr-ui/src/modules/crosswalk-editor/schema-mockup.tsx index fc86eb8bf..a83388707 100644 --- a/mscr-ui/src/modules/crosswalk-editor/schema-mockup.tsx +++ b/mscr-ui/src/modules/crosswalk-editor/schema-mockup.tsx @@ -1,2903 +1,3318 @@ -import React, {useState} from 'react'; -import {cloneDeep} from 'lodash'; -import {RenderTree} from "@app/common/interfaces/crosswalk-connection.interface"; -import {Checkbox} from "suomifi-ui-components"; +import React, { useState } from 'react'; +import { cloneDeep } from 'lodash'; +import { RenderTree } from '@app/common/interfaces/crosswalk-connection.interface'; +import { Checkbox } from 'suomifi-ui-components'; -const functionsMockup: any = [{ - name: "vocabularyMapperFunc", - uri: "http://uri.suomi.fi/datamodel/ns/mscr#vocabularyMapperFunc", - description: "", +const functionsMockup: any = [ + { + name: 'vocabularyMapperFunc', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#vocabularyMapperFunc', + description: '', parameters: [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - }, - { - name: "params map", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: false - } + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + { + name: 'params map', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: false, + }, ], outputs: [ - { - name: "object output", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ] -}, - { - name: "Function ", - uri: "http://uri.suomi.fi/datamodel/ns/mscr#pickPropertyFunc", - description: "", - parameters: [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - }, - { - name: "params map", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: false - } - ], - outputs: [ - { - name: "object output", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ] - }, - { - name: "Function to copy string value as it is with one to one mapping", - uri: "http://uri.suomi.fi/datamodel/ns/mscr#stringToStringFunc", - description: "", - parameters: [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#string", - required: true - } - ], - outputs: [ - { - name: "string output", - datatype: "http://www.w3.org/2001/XMLSchema#string", - required: true - } - ] - }, - { - name: "Function to parse integer from string input", - uri: "http://uri.suomi.fi/datamodel/ns/mscr#stringToIntFunc", - description: "", - parameters: [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#string", - required: true - } - ], - outputs: [ - { - name: "int output", - datatype: "http://www.w3.org/2001/XMLSchema#integer", - required: true - } - ] - }, - { - name: 'Function to...', - uri: `http://uri.suomi.fi/datamodel/ns/mscr#propertiesToArrayFunc`, - description: '', - parameters: [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - }, - { - "name": "params map", - "datatype": "http://www.w3.org/2001/XMLSchema#anySimpleType", - "required": false - } - ], - "outputs": [ - { - "name": "object output", - "datatype": "http://www.w3.org/2001/XMLSchema#anySimpleType", - "required": true - } - ] - }, - { - "name": "Function to...", - "uri": "http://uri.suomi.fi/datamodel/ns/mscr#stringToXmlObjectFunc", - "description": "", - "parameters": [ - { - "name": "input", - "datatype": "http://www.w3.org/2001/XMLSchema#anySimpleType", - "required": true - }, - { - "name": "params map", - "datatype": "http://www.w3.org/2001/XMLSchema#anySimpleType", - "required": false - } - ], - "outputs": [ - { - "name": "object output", - "datatype": "http://www.w3.org/2001/XMLSchema#anySimpleType", - "required": true - } - ] - }, - { - "name": "Function to parse integer from string input", - "uri": "http://uri.suomi.fi/datamodel/ns/mscr#similarityBasedValueMappingFunc", - "description": "", - "parameters": [ - { - "name": "input", - "datatype": "http://www.w3.org/2001/XMLSchema#anySimpleType", - "required": true - }, - { - "name": "params map", - "datatype": "http://www.w3.org/2001/XMLSchema#anySimpleType", - "required": false - } - ], - "outputs": [ - { - "name": "object output", - "datatype": "http://www.w3.org/2001/XMLSchema#anySimpleType", - "required": true - } - ] - }, - { - "name": "Function to parse integer from string input", - "uri": "http://uri.suomi.fi/datamodel/ns/mscr#formatUrlFunc", - "description": "", - "parameters": [ - { - "name": "input", - "datatype": "http://www.w3.org/2001/XMLSchema#string", - "required": true - } - ], - "outputs": [ - { - "name": "string output", - "datatype": "http://www.w3.org/2001/XMLSchema#string", - "required": true - } - ] - }, - { - "name": "Function to...", - "uri": "http://uri.suomi.fi/datamodel/ns/mscr#pickPropertiesToObjectFunc", - "description": "", - "parameters": [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - }, - { - name: "params map", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: false - } - ], - "outputs": [ - { - "name": "object output", - "datatype": "http://www.w3.org/2001/XMLSchema#anySimpleType", - "required": true - } - ] - }, - { - "name": "testing", - "uri": "http://uri.suomi.fi/datamodel/ns/mscr#simpleCoordinateToComplexFunc", - "description": "", - "parameters": [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#string", - required: true - } - ], - "outputs": [ - { - name: "string output", - datatype: "http://www.w3.org/2001/XMLSchema#string", - required: true - } - ] - }, - { - "name": "Function to...", - "uri": "http://uri.suomi.fi/datamodel/ns/mscr#configurableObjectToParamsFunc", - "description": "", - "parameters": [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - }, - { - name: "params map", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: false - } - ], - "outputs": [ - { - name: "object output", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ] - }, - { - "name": "testing", - "uri": "http://uri.suomi.fi/datamodel/ns/mscr#configurableStringToObjectFunc", - "description": "", - "parameters": [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - }, - { - name: "params map", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: false - } - ], - "outputs": [ - { - name: "object output", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ] - }, - { - "name": "Function ", - "uri": "http://uri.suomi.fi/datamodel/ns/mscr#pickFirstFunc", - "description": "", - "parameters": [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ], - "outputs": [ - { - name: "object output", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ] - }, - { - "name": "Function to...", - "uri": "http://uri.suomi.fi/datamodel/ns/mscr#staticContentFunc", - "description": "", - "parameters": [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - }, - { - name: "params map", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: false - } - ], - "outputs": [ - { - name: "object output", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ] - }, - { - name: "formatStringWithSubstitutor", - uri: "http://uri.suomi.fi/datamodel/ns/mscr#formatStringWithSubstitutorFunc", - description: "", - parameters: [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - }, - { - name: "params map", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: false - } - ], - outputs: [ - { - name: "object output", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ] - }, - { - name: "Function to...", - uri: "http://uri.suomi.fi/datamodel/ns/mscr#simpleReplaceStringFunc", - description: "", - parameters: [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - }, - { - name: "params map", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: false - } - ], - outputs: [ - { - name: "object output", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ] - }, - { - name: "Function to...", - uri: "http://uri.suomi.fi/datamodel/ns/mscr#mapVocabulariesFunc", - description: "", - parameters: [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - }, - { - name: "params map", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: false - } - ], - outputs: [ - { - name: "object output", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ] - }, - { - name: "Function ", - uri: "http://uri.suomi.fi/datamodel/ns/mscr#concatenateObjectFunc", - description: "", - parameters: [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ], - outputs: [ - { - name: "object output", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ] - }, - { - name: "concatListsFunc", - uri: "http://uri.suomi.fi/datamodel/ns/mscr#concatListsFunc", - description: "", - parameters: [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - }, - { - name: "params map", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: false - } - ], - outputs: [ - { - name: "object output", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ] - }, - { - name: "Function to parse integer from string input", - uri: "http://uri.suomi.fi/datamodel/ns/mscr#formatStringFunc", - description: "", - parameters: [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ], - "outputs": [ - { - name: "object output", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ] - }, - { - "name": "testing", - "uri": "http://uri.suomi.fi/datamodel/ns/mscr#copyMapFunc", - "description": "", - "parameters": [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ], - "outputs": [ - { - name: "object output", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ] - }, - { - "name": "testing", - "uri": "http://uri.suomi.fi/datamodel/ns/mscr#configurableObjectToStringFunc", - "description": "", - "parameters": [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - }, - { - name: "params map", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: false - } - ], - "outputs": [ - { - name: "string output", - datatype: "http://www.w3.org/2001/XMLSchema#string", - required: true - } - ] - }, - { - "name": "Function to...", - "uri": "http://uri.suomi.fi/datamodel/ns/mscr#formatDateFunc", - "description": "", - "parameters": [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - }, - { - name: "params map", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: false - } - ], - "outputs": [ - { - name: "string output", - datatype: "http://www.w3.org/2001/XMLSchema#string", - required: true - } - ] - }, - { - "name": "Function to parse double from string input", - "uri": "http://uri.suomi.fi/datamodel/ns/mscr#stringToDoubleFunc", - "description": "", - "parameters": [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ], - "outputs": [ - { - name: "double output", - datatype: "http://www.w3.org/2001/XMLSchema#double", - required: true - } - ] - }, - { - "name": "testing", - "uri": "http://uri.suomi.fi/datamodel/ns/mscr#anyToStringFunc", - "description": "", - "parameters": [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ], - "outputs": [ - { - name: "string output", - datatype: "http://www.w3.org/2001/XMLSchema#string", - required: true - } - ] - }, - { - "name": "Function to...", - "uri": "http://uri.suomi.fi/datamodel/ns/mscr#pickPropertyWithJSONPathFunc", - "description": "", - "parameters": [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - }, - { - name: "params map", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: false - } - ], - "outputs": [ - { - name: "object output", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ] - }, - { - "name": "testing", - "uri": "http://uri.suomi.fi/datamodel/ns/mscr#customCoordinateToStringFunc", - "description": "", - "parameters": [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ], - "outputs": [ - { - name: "object output", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ] - }, - { - "name": "Function to parse integer from string input", - "uri": "http://uri.suomi.fi/datamodel/ns/mscr#prefixStringFunc", - "description": "", - "parameters": [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - }, - { - name: "params map", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: false - } - ], - "outputs": [ - { - name: "string output", - datatype: "http://www.w3.org/2001/XMLSchema#string", - required: true - } - ] - }, - { - "name": "Function to transform celsius (double) to fahrenheit (double)", - "uri": "http://uri.suomi.fi/datamodel/ns/mscr#celsiusToFahrenheitFunc", - "description": "", - "parameters": [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ], - "outputs": [ - { - name: "double output", - datatype: "http://www.w3.org/2001/XMLSchema#double", - required: true - } - ] - }, - { - "name": "Function to...", - "uri": "http://uri.suomi.fi/datamodel/ns/mscr#clarinToFullDateFunc", - "description": "", - "parameters": [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ], - "outputs": [ - { - name: "object output", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ] - }, - { - "name": "Function to...", - "uri": "http://uri.suomi.fi/datamodel/ns/mscr#dataciteCreatorToB2FindFunc", - "description": "", - "parameters": [ - { - name: "input", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - }, - { - name: "params map", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: false - } - ], - "outputs": [ - { - name: "object output", - datatype: "http://www.w3.org/2001/XMLSchema#anySimpleType", - required: true - } - ] - } + { + name: 'object output', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + }, + { + name: 'Function ', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#pickPropertyFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + { + name: 'params map', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: false, + }, + ], + outputs: [ + { + name: 'object output', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + }, + { + name: 'Function to copy string value as it is with one to one mapping', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#stringToStringFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#string', + required: true, + }, + ], + outputs: [ + { + name: 'string output', + datatype: 'http://www.w3.org/2001/XMLSchema#string', + required: true, + }, + ], + }, + { + name: 'Function to parse integer from string input', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#stringToIntFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#string', + required: true, + }, + ], + outputs: [ + { + name: 'int output', + datatype: 'http://www.w3.org/2001/XMLSchema#integer', + required: true, + }, + ], + }, + { + name: 'Function to...', + uri: `http://uri.suomi.fi/datamodel/ns/mscr#propertiesToArrayFunc`, + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + { + name: 'params map', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: false, + }, + ], + outputs: [ + { + name: 'object output', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + }, + { + name: 'Function to...', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#stringToXmlObjectFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + { + name: 'params map', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: false, + }, + ], + outputs: [ + { + name: 'object output', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + }, + { + name: 'Function to parse integer from string input', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#similarityBasedValueMappingFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + { + name: 'params map', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: false, + }, + ], + outputs: [ + { + name: 'object output', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + }, + { + name: 'Function to parse integer from string input', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#formatUrlFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#string', + required: true, + }, + ], + outputs: [ + { + name: 'string output', + datatype: 'http://www.w3.org/2001/XMLSchema#string', + required: true, + }, + ], + }, + { + name: 'Function to...', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#pickPropertiesToObjectFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + { + name: 'params map', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: false, + }, + ], + outputs: [ + { + name: 'object output', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + }, + { + name: 'testing', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#simpleCoordinateToComplexFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#string', + required: true, + }, + ], + outputs: [ + { + name: 'string output', + datatype: 'http://www.w3.org/2001/XMLSchema#string', + required: true, + }, + ], + }, + { + name: 'Function to...', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#configurableObjectToParamsFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + { + name: 'params map', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: false, + }, + ], + outputs: [ + { + name: 'object output', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + }, + { + name: 'testing', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#configurableStringToObjectFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + { + name: 'params map', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: false, + }, + ], + outputs: [ + { + name: 'object output', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + }, + { + name: 'Function ', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#pickFirstFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + outputs: [ + { + name: 'object output', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + }, + { + name: 'Function to...', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#staticContentFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + { + name: 'params map', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: false, + }, + ], + outputs: [ + { + name: 'object output', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + }, + { + name: 'formatStringWithSubstitutor', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#formatStringWithSubstitutorFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + { + name: 'params map', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: false, + }, + ], + outputs: [ + { + name: 'object output', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + }, + { + name: 'Function to...', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#simpleReplaceStringFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + { + name: 'params map', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: false, + }, + ], + outputs: [ + { + name: 'object output', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + }, + { + name: 'Function to...', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#mapVocabulariesFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + { + name: 'params map', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: false, + }, + ], + outputs: [ + { + name: 'object output', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + }, + { + name: 'Function ', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#concatenateObjectFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + outputs: [ + { + name: 'object output', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + }, + { + name: 'concatListsFunc', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#concatListsFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + { + name: 'params map', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: false, + }, + ], + outputs: [ + { + name: 'object output', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + }, + { + name: 'Function to parse integer from string input', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#formatStringFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + outputs: [ + { + name: 'object output', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + }, + { + name: 'testing', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#copyMapFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + outputs: [ + { + name: 'object output', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + }, + { + name: 'testing', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#configurableObjectToStringFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + { + name: 'params map', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: false, + }, + ], + outputs: [ + { + name: 'string output', + datatype: 'http://www.w3.org/2001/XMLSchema#string', + required: true, + }, + ], + }, + { + name: 'Function to...', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#formatDateFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + { + name: 'params map', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: false, + }, + ], + outputs: [ + { + name: 'string output', + datatype: 'http://www.w3.org/2001/XMLSchema#string', + required: true, + }, + ], + }, + { + name: 'Function to parse double from string input', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#stringToDoubleFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + outputs: [ + { + name: 'double output', + datatype: 'http://www.w3.org/2001/XMLSchema#double', + required: true, + }, + ], + }, + { + name: 'testing', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#anyToStringFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + outputs: [ + { + name: 'string output', + datatype: 'http://www.w3.org/2001/XMLSchema#string', + required: true, + }, + ], + }, + { + name: 'Function to...', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#pickPropertyWithJSONPathFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + { + name: 'params map', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: false, + }, + ], + outputs: [ + { + name: 'object output', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + }, + { + name: 'testing', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#customCoordinateToStringFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + outputs: [ + { + name: 'object output', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + }, + { + name: 'Function to parse integer from string input', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#prefixStringFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + { + name: 'params map', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: false, + }, + ], + outputs: [ + { + name: 'string output', + datatype: 'http://www.w3.org/2001/XMLSchema#string', + required: true, + }, + ], + }, + { + name: 'Function to transform celsius (double) to fahrenheit (double)', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#celsiusToFahrenheitFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + outputs: [ + { + name: 'double output', + datatype: 'http://www.w3.org/2001/XMLSchema#double', + required: true, + }, + ], + }, + { + name: 'Function to...', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#clarinToFullDateFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + outputs: [ + { + name: 'object output', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + }, + { + name: 'Function to...', + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#dataciteCreatorToB2FindFunc', + description: '', + parameters: [ + { + name: 'input', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + { + name: 'params map', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: false, + }, + ], + outputs: [ + { + name: 'object output', + datatype: 'http://www.w3.org/2001/XMLSchema#anySimpleType', + required: true, + }, + ], + }, ]; const importedSchemaExample = { - "metadata": { - "created": null, - "modified": null, - "modifier": null, - "creator": null, - "type": null, - "prefix": null, - "status": null, - "label": { - "en": "string2" + metadata: { + created: null, + modified: null, + modifier: null, + creator: null, + type: null, + prefix: null, + status: null, + label: { + en: 'string2', + }, + description: { + en: 'string', + }, + languages: [], + organizations: [], + groups: [], + internalNamespaces: [], + externalNamespaces: [], + terminologies: [], + codeLists: [], + contact: null, + documentation: {}, + state: 'DRAFT', + visibility: 'PRIVATE', + format: 'JSONSCHEMA', + namespace: 'http://test.com', + versionLabel: '1', + revisionOf: null, + aggregationKey: 'urn:IAMNOTAPID:55174186-1048-4ad3-9438-a04bd27919a3', + hasRevisions: null, + revisions: null, + variants: null, + variants2: null, + owner: ['7d3a3c00-5a6b-489b-a3ed-63bb58c26a63'], + fileMetadata: [], + pid: 'urn:IAMNOTAPID:55174186-1048-4ad3-9438-a04bd27919a3', + }, + content: { + description: 'string', + '@id': 'urn:IAMNOTAPID:55174186-1048-4ad3-9438-a04bd27919a3#', + title: 'string2', + modified: 'Thu, 09 Nov 2023 10:09:34 EET', + $schema: 'http://json-schema.org/draft-04/schema#', + type: 'object', + properties: { + lastName: { + '@id': 'mscr:root/Root/lastName', + title: 'lastName', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'array', + items: { + type: 'string', }, - "description": { - "en": "string" + }, + firstName: { + '@id': 'mscr:root/Root/firstName', + title: 'firstName', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'array', + items: { + type: 'string', }, - "languages": [], - "organizations": [], - "groups": [], - "internalNamespaces": [], - "externalNamespaces": [], - "terminologies": [], - "codeLists": [], - "contact": null, - "documentation": {}, - "state": "DRAFT", - "visibility": "PRIVATE", - "format": "JSONSCHEMA", - "namespace": "http://test.com", - "versionLabel": "1", - "revisionOf": null, - "aggregationKey": "urn:IAMNOTAPID:55174186-1048-4ad3-9438-a04bd27919a3", - "hasRevisions": null, - "revisions": null, - "variants": null, - "variants2": null, - "owner": [ - "7d3a3c00-5a6b-489b-a3ed-63bb58c26a63" - ], - "fileMetadata": [], - "pid": "urn:IAMNOTAPID:55174186-1048-4ad3-9438-a04bd27919a3" - }, - "content": { - "description": "string", - "@id": "urn:IAMNOTAPID:55174186-1048-4ad3-9438-a04bd27919a3#", - "title": "string2", - "modified": "Thu, 09 Nov 2023 10:09:34 EET", - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "lastName": { - "@id": "mscr:root/Root/lastName", - "title": "lastName", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "array", - "items": { - "type": "string" - } + }, + address: { + '@id': 'mscr:root/Root/address', + title: 'Address of the person', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:55174186-1048-4ad3-9438-a04bd27919a3#root/Root/address/Address', + properties: { + street: { + '@id': 'mscr:root/Root/address/Address/street', + title: 'street', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'array', + items: { + type: 'string', + }, + }, + city: { + '@id': 'mscr:root/Root/address/Address/city', + title: 'city', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:55174186-1048-4ad3-9438-a04bd27919a3#root/Root/address/Address/city/City', + properties: { + population: { + '@id': + 'mscr:root/Root/address/Address/city/City/population', + title: 'population', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'array', + items: { + type: 'integer', + }, + }, + }, + }, }, - "firstName": { - "@id": "mscr:root/Root/firstName", - "title": "firstName", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "array", - "items": { - "type": "string" - } + house_number: { + '@id': 'mscr:root/Root/address/Address/house_number', + title: 'house_number', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'array', + items: { + type: 'string', + }, }, - "address": { - "@id": "mscr:root/Root/address", - "title": "Address of the person", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:55174186-1048-4ad3-9438-a04bd27919a3#root/Root/address/Address", - "properties": { - "street": { - "@id": "mscr:root/Root/address/Address/street", - "title": "street", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "array", - "items": { - "type": "string" - } - }, - "city": { - "@id": "mscr:root/Root/address/Address/city", - "title": "city", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:55174186-1048-4ad3-9438-a04bd27919a3#root/Root/address/Address/city/City", - "properties": { - "population": { - "@id": "mscr:root/Root/address/Address/city/City/population", - "title": "population", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "array", - "items": { - "type": "integer" - } - } - } - } - }, - "house_number": { - "@id": "mscr:root/Root/address/Address/house_number", - "title": "house_number", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - } - } -} + }, + }, + }, + }, + }, +}; const importedSchemaExample2 = { - "metadata": { - "created": null, - "modified": null, - "modifier": null, - "creator": null, - "type": null, - "prefix": null, - "status": null, - "label": { - "en": "string2" + metadata: { + created: null, + modified: null, + modifier: null, + creator: null, + type: null, + prefix: null, + status: null, + label: { + en: 'string2', }, - "description": { - "en": "string" + description: { + en: 'string', }, - "languages": [], - "organizations": [], - "groups": [], - "internalNamespaces": [], - "externalNamespaces": [], - "terminologies": [], - "codeLists": [], - "contact": null, - "documentation": {}, - "state": "DRAFT", - "visibility": "PRIVATE", - "format": "JSONSCHEMA", - "namespace": "http://test.com", - "versionLabel": "1", - "revisionOf": null, - "aggregationKey": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00", - "hasRevisions": null, - "revisions": null, - "variants": null, - "variants2": null, - "owner": [ - "7d3a3c00-5a6b-489b-a3ed-63bb58c26a63" - ], - "fileMetadata": [], - "pid": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00" + languages: [], + organizations: [], + groups: [], + internalNamespaces: [], + externalNamespaces: [], + terminologies: [], + codeLists: [], + contact: null, + documentation: {}, + state: 'DRAFT', + visibility: 'PRIVATE', + format: 'JSONSCHEMA', + namespace: 'http://test.com', + versionLabel: '1', + revisionOf: null, + aggregationKey: 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00', + hasRevisions: null, + revisions: null, + variants: null, + variants2: null, + owner: ['7d3a3c00-5a6b-489b-a3ed-63bb58c26a63'], + fileMetadata: [], + pid: 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00', }, - "content": { - "description": "string", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#", - "title": "string2", - "modified": "Fri, 10 Nov 2023 12:13:51 EET", - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "aktiviteetti": { - "@id": "mscr:root/Root/aktiviteetti", - "title": "Aktiviteetit", - "description": "Organisaation raportoimat tutkimusaktiviteetit ja palkinnot.", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti", - "properties": { - "paattymispaiva": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/paattymispaiva", - "title": "Päättymispäivä", - "description": "Päättymishetki päivän tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole. Pelkkä päivä ja vuosi ei toki ole mielekäs.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "paattymiskuukausi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/paattymiskuukausi", - "title": "Päättymiskuukausi", - "description": "Päättymishetki kuukauden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "alkamispaiva": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/alkamispaiva", - "title": "Alkamispäivä", - "description": "Alkamishetki päivän tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole. Toki vuoden ja päivämäärän yhdistelmä ei ole mielekäs.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "tieteenalakoodi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/tieteenalakoodi", - "title": "Tieteenalakoodi", - "description": "Aktiviteettiin tai palkintoon liittyvän tutkimuksen tieteenala Tilastokeskuksen Tieteenala 2020 -luokituksen mukaisesti. Aktiviteetilla tai palkinnolla voi olla useita tieteenaloja.", - "enum": [], - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "array", - "items": { - "type": "string" - } - }, - "kansainvalinenyhteistyo": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kansainvalinenyhteistyo", - "title": "Kansainvälinen yhteistyö", - "description": "1 = Aktiviteetissa on mukana henkilöitä myös muualta kuin suomalaisista organisaatioista.\n0 = Aktiviteetissa on mukana henkilöitä ainoastaan suomalaisista organisaatioista.", - "enum": [], - "@type": "http://www.w3.org/2001/XMLSchema#boolean", - "type": "boolean" - }, - "konteksti": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/konteksti", - "title": "Konteksti", - "description": "Aktiviteettiin liittyvä tapahtuma (esim. konferenssi, jossa esitelmä pidetään).", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/konteksti/Konteksti", - "properties": { - "alkamiskuukausi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/konteksti/Konteksti/alkamiskuukausi", - "title": "Alkamiskuukausi", - "description": "Alkamishetki kuukauden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "alkamispaiva": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/konteksti/Konteksti/alkamispaiva", - "title": "Alkamispäivä", - "description": "Alkamishetki päivän tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole. Toki vuoden ja päivämäärän yhdistelmä ei ole mielekäs.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "alkamisvuosi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/konteksti/Konteksti/alkamisvuosi", - "title": "Alkamisvuosi", - "description": "Alkamishetki vuoden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "nimi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/konteksti/Konteksti/nimi", - "title": "Nimi", - "description": "Tapahtuman, esim. konferenssin nimi.", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "minItems": 1, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } - }, - "paattymiskuukausi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/konteksti/Konteksti/paattymiskuukausi", - "title": "Päättymiskuukausi", - "description": "Päättymishetki kuukauden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "paattymispaiva": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/konteksti/Konteksti/paattymispaiva", - "title": "Päättymispäivä", - "description": "Päättymishetki päivän tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole. Pelkkä päivä ja vuosi ei toki ole mielekäs.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "tapahtumanpaikka": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/konteksti/Konteksti/tapahtumanpaikka", - "title": "Tapahtuman paikka", - "description": "Tapahtuman maantietellinen sijainti, esim Boston, Massachusetts, USA.\nVoidaan käyttää myös virtuaalitapahtumiin.", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } - }, - "yksilointitunnus": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/konteksti/Konteksti/yksilointitunnus", - "title": "Yksilöintitunnus", - "description": "Yksilöivä tunniste", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus", - "properties": { - "pysyvatunniste": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvatunniste", - "title": "Pysyvä tunniste", - "description": "Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "pysyvantunnisteentyyppi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvantunnisteentyyppi", - "title": "Pysyvän tunnisteen tyyppi", - "description": "Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.", - "enum": [], - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - } - } - } - }, - "maakoodi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/konteksti/Konteksti/maakoodi", - "title": "Maakoodi", - "description": "Tapahtuman maantieteellisen sijainnin maakoodi.", - "enum": [], - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "paattymisvuosi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/konteksti/Konteksti/paattymisvuosi", - "title": "Päättymisvuosi", - "description": "Päättymishetki vuoden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - } - }, - "required": [ - "nimi" - ] - } - }, - "julkaisukanava": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/julkaisukanava", - "title": "Julkaisukanava", - "description": "Aktiviteettiin liittyvä julkaisukanava (esim. lehti, johon toimitustyö liittyy).", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/julkaisukanava/Julkaisukanava", - "properties": { - "nimi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/julkaisukanava/Julkaisukanava/nimi", - "title": "Nimi", - "description": "Julkaisukanavan, eli lehden, sarjan, kustantajan tai konferenssin nimi", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "minItems": 1, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } - }, - "julkaisupaikka": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/julkaisukanava/Julkaisukanava/julkaisupaikka", - "title": "Julkaisupaikka", - "description": "Julkaisun kustantajan nimen yhteydessä ilmoitettu paikkakunta tai paikkakunnat, ulkomailla tai Suomessa. Saattaa sisältää myös maatiedon.", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } - }, - "kustantaja": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/julkaisukanava/Julkaisukanava/kustantaja", - "title": "Organisaatio", - "description": "Organisaatio, johon tutkijan koulutus, julkaisukanava, aktiviteetti tai rooli tutkimustuotoksessa liittyy.", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/julkaisukanava/Julkaisukanava/kustantaja/Kustantaja", - "properties": { - "nimi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/julkaisukanava/Julkaisukanava/kustantaja/Kustantaja/nimi", - "title": "Nimi", - "description": "Organisaation nimi", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } + content: { + description: 'string', + '@id': 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#', + title: 'string2', + modified: 'Fri, 10 Nov 2023 12:13:51 EET', + $schema: 'http://json-schema.org/draft-04/schema#', + type: 'object', + properties: { + aktiviteetti: { + '@id': 'mscr:root/Root/aktiviteetti', + title: 'Aktiviteetit', + description: + 'Organisaation raportoimat tutkimusaktiviteetit ja palkinnot.', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti', + properties: { + paattymispaiva: { + '@id': 'mscr:root/Root/aktiviteetti/Aktiviteetti/paattymispaiva', + title: 'Päättymispäivä', + description: + 'Päättymishetki päivän tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole. Pelkkä päivä ja vuosi ei toki ole mielekäs.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + paattymiskuukausi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/paattymiskuukausi', + title: 'Päättymiskuukausi', + description: + 'Päättymishetki kuukauden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + alkamispaiva: { + '@id': 'mscr:root/Root/aktiviteetti/Aktiviteetti/alkamispaiva', + title: 'Alkamispäivä', + description: + 'Alkamishetki päivän tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole. Toki vuoden ja päivämäärän yhdistelmä ei ole mielekäs.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + tieteenalakoodi: { + '@id': 'mscr:root/Root/aktiviteetti/Aktiviteetti/tieteenalakoodi', + title: 'Tieteenalakoodi', + description: + 'Aktiviteettiin tai palkintoon liittyvän tutkimuksen tieteenala Tilastokeskuksen Tieteenala 2020 -luokituksen mukaisesti. Aktiviteetilla tai palkinnolla voi olla useita tieteenaloja.', + enum: [], + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'array', + items: { + type: 'string', + }, + }, + kansainvalinenyhteistyo: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kansainvalinenyhteistyo', + title: 'Kansainvälinen yhteistyö', + description: + '1 = Aktiviteetissa on mukana henkilöitä myös muualta kuin suomalaisista organisaatioista.\n0 = Aktiviteetissa on mukana henkilöitä ainoastaan suomalaisista organisaatioista.', + enum: [], + '@type': 'http://www.w3.org/2001/XMLSchema#boolean', + type: 'boolean', + }, + konteksti: { + '@id': 'mscr:root/Root/aktiviteetti/Aktiviteetti/konteksti', + title: 'Konteksti', + description: + 'Aktiviteettiin liittyvä tapahtuma (esim. konferenssi, jossa esitelmä pidetään).', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/konteksti/Konteksti', + properties: { + alkamiskuukausi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/konteksti/Konteksti/alkamiskuukausi', + title: 'Alkamiskuukausi', + description: + 'Alkamishetki kuukauden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + alkamispaiva: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/konteksti/Konteksti/alkamispaiva', + title: 'Alkamispäivä', + description: + 'Alkamishetki päivän tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole. Toki vuoden ja päivämäärän yhdistelmä ei ole mielekäs.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + alkamisvuosi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/konteksti/Konteksti/alkamisvuosi', + title: 'Alkamisvuosi', + description: + 'Alkamishetki vuoden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + nimi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/konteksti/Konteksti/nimi', + title: 'Nimi', + description: 'Tapahtuman, esim. konferenssin nimi.', + '@type': + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + minItems: 1, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, + }, + }, + paattymiskuukausi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/konteksti/Konteksti/paattymiskuukausi', + title: 'Päättymiskuukausi', + description: + 'Päättymishetki kuukauden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + paattymispaiva: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/konteksti/Konteksti/paattymispaiva', + title: 'Päättymispäivä', + description: + 'Päättymishetki päivän tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole. Pelkkä päivä ja vuosi ei toki ole mielekäs.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + tapahtumanpaikka: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/konteksti/Konteksti/tapahtumanpaikka', + title: 'Tapahtuman paikka', + description: + 'Tapahtuman maantietellinen sijainti, esim Boston, Massachusetts, USA.\nVoidaan käyttää myös virtuaalitapahtumiin.', + '@type': + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, + }, + }, + yksilointitunnus: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/konteksti/Konteksti/yksilointitunnus', + title: 'Yksilöintitunnus', + description: 'Yksilöivä tunniste', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus', + properties: { + pysyvatunniste: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvatunniste', + title: 'Pysyvä tunniste', + description: + 'Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', }, - "yksilointitunnus": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/julkaisukanava/Julkaisukanava/kustantaja/Kustantaja/yksilointitunnus", - "title": "Yksilöintitunnus", - "description": "Yksilöivä tunniste", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus", - "properties": { - "pysyvatunniste": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvatunniste", - "title": "Pysyvä tunniste", - "description": "Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "pysyvantunnisteentyyppi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvantunnisteentyyppi", - "title": "Pysyvän tunnisteen tyyppi", - "description": "Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.", - "enum": [], - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - } - } - } - } - } - } - }, - "jufotunnus": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/julkaisukanava/Julkaisukanava/jufotunnus", - "title": "Jufotunnus", - "description": "Julkaisukanavan tunniste Julkaisufoorumissa (JUFO-ID).", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "yksilointitunnus": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/julkaisukanava/Julkaisukanava/yksilointitunnus", - "title": "Yksilöintitunnus", - "description": "Yksilöivä tunniste, julkaisukanavalle ISSN", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus", - "properties": { - "pysyvatunniste": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvatunniste", - "title": "Pysyvä tunniste", - "description": "Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" + pysyvantunnisteentyyppi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvantunnisteentyyppi', + title: 'Pysyvän tunnisteen tyyppi', + description: + 'Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.', + enum: [], + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', }, - "pysyvantunnisteentyyppi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvantunnisteentyyppi", - "title": "Pysyvän tunnisteen tyyppi", - "description": "Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.", - "enum": [], - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - } - } - } - } + }, + }, + }, + maakoodi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/konteksti/Konteksti/maakoodi', + title: 'Maakoodi', + description: + 'Tapahtuman maantieteellisen sijainnin maakoodi.', + enum: [], + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + paattymisvuosi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/konteksti/Konteksti/paattymisvuosi', + title: 'Päättymisvuosi', + description: + 'Päättymishetki vuoden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, }, - "required": [ - "nimi" - ] - } - }, - "rahoituspaatos": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/rahoituspaatos", - "title": "Rahoittaneen rahoituspäätöksen tunniste", - "description": "Aktiviteettia rahoittanut rahoituspäätös", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/rahoituspaatos/Rahoituspaatos", - "properties": { - "pysyvatunniste": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/rahoituspaatos/Rahoituspaatos/pysyvatunniste", - "title": "Pysyvä tunniste", - "description": "Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "pysyvantunnisteentyyppi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/rahoituspaatos/Rahoituspaatos/pysyvantunnisteentyyppi", - "title": "Pysyvän tunnisteen tyyppi", - "description": "Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.", - "enum": [], - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - } - } - } - }, - "kohdeorganisaatio": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio", - "title": "Kohdeorganisaatio", - "description": "Organisaatio, jossa aktiviteetti suoritetaan (esim. vierailun kohdeorganisaatio tai palkinnon myöntävä organisaatio).", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio", - "properties": { - "yksilointitunnus": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus", - "title": "Yksilöintitunnus", - "description": "Yksilöivä tunniste", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus", - "properties": { - "pysyvatunniste": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvatunniste", - "title": "Pysyvä tunniste", - "description": "Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "pysyvantunnisteentyyppi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvantunnisteentyyppi", - "title": "Pysyvän tunnisteen tyyppi", - "description": "Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.", - "enum": [], - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - } - } - } - }, - "nimi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/nimi", - "title": "Nimi", - "description": "Organisaation nimi", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } - } - } - } - }, - "paikallinentunnus": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/paikallinentunnus", - "title": "Paikallinen tunnus", - "description": "Aktiviteetin tai palkinnon paikallinen tunniste raportoivassa organisaatiossa. Tunniste tarvitaan, mikäli aktiviteetin tai palkinnon tietoja korjataan tai poistetaan jälkeenpäin.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "yksilointitunnus": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/yksilointitunnus", - "title": "Yksilöintitunnus", - "description": "Yksilöivä tunniste", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus", - "properties": { - "pysyvatunniste": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvatunniste", - "title": "Pysyvä tunniste", - "description": "Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "pysyvantunnisteentyyppi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvantunnisteentyyppi", - "title": "Pysyvän tunnisteen tyyppi", - "description": "Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.", - "enum": [], - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - } - } - } - }, - "alkamisvuosi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/alkamisvuosi", - "title": "Alkamisvuosi", - "description": "Alkamishetki vuoden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "roolitettutekija": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija", - "title": "Roolitettu tekijä", - "description": "Aktiviteettiin tai palkintoon nimetyllä roolilla osallistuva henkilö (tekijä/saaja).", - "@type": "@id", - "minItems": 1, - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija", - "properties": { - "kuvaus": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/kuvaus", - "title": "Rooli tutkimustuotoksessa", - "description": "Tutkijan tietojen siirtoprofiilissa rooli tutkimustuotoksessa kuvaa tutkijan roolia aktiviteetissa tai palkinnossa. Rooli ilmoitetaan aktiviteettien ja palkintojen tyypit ja roolit -koodiston mukaisesti.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "tekijantunniste": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/tekijantunniste", - "title": "Tekijän tunniste", - "description": "Tutkimusaktiviteetin tekemiseen/suorittamiseen osallistuneet tutkijat tai muut henkilöt", - "@type": "@id", - "minItems": 1, - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/tekijantunniste/Tekijantunniste", - "properties": { - "pysyvatunniste": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/tekijantunniste/Tekijantunniste/pysyvatunniste", - "title": "Pysyvä tunniste", - "description": "Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" + required: ['nimi'], + }, + }, + julkaisukanava: { + '@id': 'mscr:root/Root/aktiviteetti/Aktiviteetti/julkaisukanava', + title: 'Julkaisukanava', + description: + 'Aktiviteettiin liittyvä julkaisukanava (esim. lehti, johon toimitustyö liittyy).', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/julkaisukanava/Julkaisukanava', + properties: { + nimi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/julkaisukanava/Julkaisukanava/nimi', + title: 'Nimi', + description: + 'Julkaisukanavan, eli lehden, sarjan, kustantajan tai konferenssin nimi', + '@type': + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + minItems: 1, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, + }, + }, + julkaisupaikka: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/julkaisukanava/Julkaisukanava/julkaisupaikka', + title: 'Julkaisupaikka', + description: + 'Julkaisun kustantajan nimen yhteydessä ilmoitettu paikkakunta tai paikkakunnat, ulkomailla tai Suomessa. Saattaa sisältää myös maatiedon.', + '@type': + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, + }, + }, + kustantaja: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/julkaisukanava/Julkaisukanava/kustantaja', + title: 'Organisaatio', + description: + 'Organisaatio, johon tutkijan koulutus, julkaisukanava, aktiviteetti tai rooli tutkimustuotoksessa liittyy.', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/julkaisukanava/Julkaisukanava/kustantaja/Kustantaja', + properties: { + nimi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/julkaisukanava/Julkaisukanava/kustantaja/Kustantaja/nimi', + title: 'Nimi', + description: 'Organisaation nimi', + '@type': + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, + }, }, - "pysyvantunnisteentyyppi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/tekijantunniste/Tekijantunniste/pysyvantunnisteentyyppi", - "title": "Pysyvän tunnisteen tyyppi", - "description": "Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.", - "enum": [], - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - } - } - } - }, - "sukunimituotoksessa": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/sukunimituotoksessa", - "title": "Sukunimi tuotoksessa", - "description": "Sukunimi aktiviteetissa tai palkinnossa. Nimi on tässä aktiviteetin tai palkinnon metatieto. Se voi siis olla eri kuin tutkijan nykyinen nimi.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "tekijanaffiliaatiotuotoksenkontekstissa": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/tekijanaffiliaatiotuotoksenkontekstissa", - "title": "Tekijän affiliaatio tuotoksen kontekstissa", - "description": "Tekijälle on tuotoksessa ilmoitettu yksi tai useampi affiliaatio. Tuotoksen kontekstissa annettua affiliaatiota ei voida varmuudella päätellä tutkijan tuotoksenaikaisista affiliaatioista.", - "@type": "@id", - "minItems": 1, - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/tekijanaffiliaatiotuotoksenkontekstissa/Tekijanaffiliaatiotuotoksenkontekstissa", - "properties": { - "yksilointitunnus": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/tekijanaffiliaatiotuotoksenkontekstissa/Tekijanaffiliaatiotuotoksenkontekstissa/yksilointitunnus", - "title": "Yksilöintitunnus", - "description": "Yksilöivä tunniste", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus", - "properties": { - "pysyvatunniste": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvatunniste", - "title": "Pysyvä tunniste", - "description": "Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" + yksilointitunnus: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/julkaisukanava/Julkaisukanava/kustantaja/Kustantaja/yksilointitunnus', + title: 'Yksilöintitunnus', + description: 'Yksilöivä tunniste', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus', + properties: { + pysyvatunniste: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvatunniste', + title: 'Pysyvä tunniste', + description: + 'Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.', + '@type': + 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', }, - "pysyvantunnisteentyyppi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvantunnisteentyyppi", - "title": "Pysyvän tunnisteen tyyppi", - "description": "Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.", - "enum": [], - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - } - } - } - }, - "nimi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/tekijanaffiliaatiotuotoksenkontekstissa/Tekijanaffiliaatiotuotoksenkontekstissa/nimi", - "title": "Nimi", - "description": "Organisaation nimi", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } - } - } - } - }, - "muunimituotoksessa": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/muunimituotoksessa", - "title": "Muu nimi tuotoksessa", - "description": "Muu nimi aktiviteetissa tai palkinnossa. Nimi on tässä aktiviteetin tai palkinnon metatieto. Se voi siis olla eri kuin tutkijan nykyinen nimi.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "etunimettuotoksessa": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/etunimettuotoksessa", - "title": "Etunimet tuotoksessa", - "description": "Etunimi aktiviteetissa tai palkinnossa. Nimi on tässä aktiviteetin tai palkinnon metatieto. Se voi siis olla eri kuin tutkijan nykyinen nimi.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "roolikoodi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/roolikoodi", - "title": "Roolikoodi", - "description": "Aktiviteettien ja palkintojen tyypit ja roolit -koodiston mukainen arvo.", - "enum": [], - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - } - }, - "required": [ - "tekijantunniste", - "tekijanaffiliaatiotuotoksenkontekstissa" - ] - } - }, - "avainsanat": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/avainsanat", - "title": "Avainsanat", - "description": "Aktiviteettia kuvaavat avainsanat", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/avainsanat/Avainsanat", - "properties": { - "nimiavaruus": { - "@id": "mscr:root/Root/tutkija/Tutkija/avainsanat/Avainsanat/nimiavaruus", - "title": "Nimiavaruus", - "description": "Sanasto, tai ontologia jossa avainsana on määritelty (voi olla myös useammassa sanastossa).", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "maaritelma": { - "@id": "mscr:root/Root/tutkija/Tutkija/avainsanat/Avainsanat/maaritelma", - "title": "Määritelmä", - "description": "käsitteen kuvaus, jonka tulee erottaa käsite sen lähikäsitteistä", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } - }, - "yksilointitunnus": { - "@id": "mscr:root/Root/tutkija/Tutkija/avainsanat/Avainsanat/yksilointitunnus", - "title": "Yksilöintitunnus", - "description": "Avainsanan URI tunniste (voi olla myös useammassa sanastossa).", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus", - "properties": { - "pysyvatunniste": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvatunniste", - "title": "Pysyvä tunniste", - "description": "Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "pysyvantunnisteentyyppi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvantunnisteentyyppi", - "title": "Pysyvän tunnisteen tyyppi", - "description": "Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.", - "enum": [], - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - } - } - } - }, - "kielikoodi": { - "@id": "mscr:root/Root/tutkija/Tutkija/avainsanat/Avainsanat/kielikoodi", - "title": "Kielikoodi", - "description": "avainsanan kieli", - "enum": [], - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "avainsana": { - "@id": "mscr:root/Root/tutkija/Tutkija/avainsanat/Avainsanat/avainsana", - "title": "Avainsana", - "description": "Tutkimuksen luokkaa kuvaava avainsana. Preferenssi on, että kuvaamiseen käytetään ulkoista sanastoa/ontologiaa. Myös käsitteetöntä tietoa voidaan antaa.", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "minItems": 1, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } - } - }, - "required": [ - "avainsana" - ] - } - }, - "maakoodi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/maakoodi", - "title": "Maakoodi", - "description": "Aktiviteetin suorittamisen ensisijainen maa. Esim. vierailun kohdemaa, tapahtuman järjestämispaikan maa tai maa, josta palkinto on myönnetty.", - "enum": [], - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "paattymisvuosi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/paattymisvuosi", - "title": "Päättymisvuosi", - "description": "Päättymishetki vuoden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "alkamiskuukausi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/alkamiskuukausi", - "title": "Alkamiskuukausi", - "description": "Alkamishetki kuukauden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "verkkolinkki": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/verkkolinkki", - "title": "Verkkolinkki", - "description": "Esimekiksi tutkijalla, tutkimusyhteisöllä, organisaatiolla, voi olla erilaisia läsnäolon muotoja internetissä, joka on määritelty omassa luokassaan. Tämä on osoitin tuohon luokkaan.", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/verkkolinkki/Verkkolinkki", - "properties": { - "url": { - "@id": "mscr:root/Root/tutkija/Tutkija/verkkolinkki/Verkkolinkki/url", - "title": "URL", - "description": "Uniform Resource Locator (URL)", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "linkintyyppi": { - "@id": "mscr:root/Root/tutkija/Tutkija/verkkolinkki/Verkkolinkki/linkintyyppi", - "title": "Linkin tyyppi", - "description": "Palvelu tai osoitteen laji johon linkki viittaa. Esim Linked-In tai tutkijaprofiili affiliaation verkkosivulla. Tämä eroaa kuitenkin tunnisteesta, joten ei esim ORCID.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "kuvaus": { - "@id": "mscr:root/Root/tutkija/Tutkija/verkkolinkki/Verkkolinkki/kuvaus", - "title": "Kuvaus", - "description": "kohteen sisällöstä kertova tieto", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } - } - } - } - }, - "nimi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/nimi", - "title": "Nimi", - "description": "Aktiviteettia tai palkintoa kuvaava nimi.", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "minItems": 1, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } - }, - "kuvaus": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kuvaus", - "title": "Kuvaus", - "description": "Aktiviteetin tai palkinnon tarkempi kuvaus.", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } - } - }, - "required": [ - "nimi", - "roolitettutekija" - ] - } - }, - "organisaatiorakenteenvuosi": { - "@id": "mscr:root/Root/organisaatiorakenteenvuosi", - "title": "Organisaatiorakenteen vuosi", - "description": "Organisaatioiden rakenteet ovat jatkuvan muutoksen alaisena. Tällä kentällä kerrotaan minkävuoden mukaista organisaatiorakennetta tiedoissa käytetään.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "raportoivanorganisaationtunniste": { - "@id": "mscr:root/Root/raportoivanorganisaationtunniste", - "title": "Raportoivan organisaation tunniste", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "tutkija": { - "@id": "mscr:root/Root/tutkija", - "title": "Tutkijat", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija", - "properties": { - "tutkijankuvaus": { - "@id": "mscr:root/Root/tutkija/Tutkija/tutkijankuvaus", - "title": "Tutkijan kuvaus", - "description": "Vapaamuotoinen kuvaus tutkijan relevanteista kyvykkyyksistä.", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } - }, - "member_of": { - "@id": "mscr:root/Root/tutkija/Tutkija/member_of", - "title": "Jäsenyys", - "@type": "@id", - "minItems": 0, - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/member_of/Member_of", - "properties": { - "affiliaation_tyyppi": { - "@id": "mscr:root/Root/tutkija/Tutkija/member_of/Member_of/affiliaation_tyyppi", - "title": "Affiliaation tyyppi", - "description": "Henkilön suhde organisaatioon (esim. työsuhde, dosentuuri, vieraileva tutkija).", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } - }, - "tehtavanimike": { - "@id": "mscr:root/Root/tutkija/Tutkija/member_of/Member_of/tehtavanimike", - "title": "Tehtävänimike", - "description": "Henkilön nimike tyypillisimmin työsuhteessa organisaatioon (esim. professori, yliopistonlehtori, tuntiopettaja). Tämä on erityisesti niille toimijoille, joilla nimikkeet eivät perustu yliopistojen tehtävänimikekoodistoon. Mikäli kentässä Tehtäväkoodi on arvo, tämä kenttä voi olla tyhjä.", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } - }, - "paattymisvuosi": { - "@id": "mscr:root/Root/tutkija/Tutkija/member_of/Member_of/paattymisvuosi", - "title": "Päättymisvuosi", - "description": "Päättymishetki vuoden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "paattymispaiva": { - "@id": "mscr:root/Root/tutkija/Tutkija/member_of/Member_of/paattymispaiva", - "title": "Päättymispäivä", - "description": "Päättymishetki päivän tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole. Pelkkä päivä ja vuosi ei toki ole mielekäs.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "paikallinentunnus": { - "@id": "mscr:root/Root/tutkija/Tutkija/member_of/Member_of/paikallinentunnus", - "title": "Paikallinen tunnus", - "description": "Raportoivan organisaation oma paikallinen tunniste tutkijan affiliaatiolle. Tunniste tarvitaan, mikäli tietoja mahdollisesti korjataan tai poistetaan jälkeenpäin.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "alkamisvuosi": { - "@id": "mscr:root/Root/tutkija/Tutkija/member_of/Member_of/alkamisvuosi", - "title": "Alkamisvuosi", - "description": "Alkamishetki vuoden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "paattymiskuukausi": { - "@id": "mscr:root/Root/tutkija/Tutkija/member_of/Member_of/paattymiskuukausi", - "title": "Päättymiskuukausi", - "description": "Päättymishetki kuukauden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "alkamispaiva": { - "@id": "mscr:root/Root/tutkija/Tutkija/member_of/Member_of/alkamispaiva", - "title": "Alkamispäivä", - "description": "Alkamishetki päivän tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole. Toki vuoden ja päivämäärän yhdistelmä ei ole mielekäs.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "tehtavakoodi": { - "@id": "mscr:root/Root/tutkija/Tutkija/member_of/Member_of/tehtavakoodi", - "title": "Tehtäväkoodi", - "description": "Koodiston määrittelemä koodi/tunniste tehtävänimikkeelle. Käytetty koodisto pätee vain korkeakouluille.", - "enum": [], - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "tutkijan_affiliaatio": { - "@id": "mscr:root/Root/tutkija/Tutkija/member_of/Member_of/tutkijan_affiliaatio", - "title": "Alayksikkö", - "description": "Alayksikkö, johon tutkija on affilioitunut. Alayksikön tulee olla OKM:lle raportoidussa alayksikkökoodistossa .", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/member_of/Member_of/tutkijan_affiliaatio/Tutkijan_affiliaatio", - "properties": { - "nimi": { - "@id": "mscr:root/Root/tutkija/Tutkija/member_of/Member_of/tutkijan_affiliaatio/Tutkijan_affiliaatio/nimi", - "title": "Nimi", - "description": "Alayksikön nimi", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "array", - "items": { - "type": "string" - } - }, - "alayksikkokoodi": { - "@id": "mscr:root/Root/tutkija/Tutkija/member_of/Member_of/tutkijan_affiliaatio/Tutkijan_affiliaatio/alayksikkokoodi", - "title": "Alayksikkökoodi", - "description": "Alayksikön koodi OKM:lle raportoidussa alayksikkökoodistossa.", - "enum": [], - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - } - } - } - }, - "alkamiskuukausi": { - "@id": "mscr:root/Root/tutkija/Tutkija/member_of/Member_of/alkamiskuukausi", - "title": "Alkamiskuukausi", - "description": "Alkamishetki kuukauden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - } - } - } - }, - "sukunimi": { - "@id": "mscr:root/Root/tutkija/Tutkija/sukunimi", - "title": "Sukunimi", - "description": "pääasiallisesti sukuun viittaava rekisteröidyn henkilönnimen osa", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "vaihtoehtoinennimi": { - "@id": "mscr:root/Root/tutkija/Tutkija/vaihtoehtoinennimi", - "title": "Vaihtoehtoinen nimi", - "description": "nimi, jolla henkilö tai oikeushenkilö tunnetaan ja joka ei ole henkilön tai oikeushenkilön rekisteröity nimi", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "array", - "items": { - "type": "string" - } - }, - "paikallinentunnus": { - "@id": "mscr:root/Root/tutkija/Tutkija/paikallinentunnus", - "title": "Paikallinen tunnus", - "description": "Ei-globaali tai standardoitu tunniste, vaan jonkin lähdejärjestelmän paikkallinen tunniste.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "yksilointitunnus": { - "@id": "mscr:root/Root/tutkija/Tutkija/yksilointitunnus", - "title": "Yksilöintitunnus", - "description": "Tutkimuksen piirissä toimivan henkilön yksilöivä tunniste, tyypillisimmin ORCID, esim julkaisun/teoksen yhteydessä ISNI", - "@type": "@id", - "minItems": 1, - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus", - "properties": { - "pysyvatunniste": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvatunniste", - "title": "Pysyvä tunniste", - "description": "Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "pysyvantunnisteentyyppi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvantunnisteentyyppi", - "title": "Pysyvän tunnisteen tyyppi", - "description": "Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.", - "enum": [], - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - } - } - } - }, - "suorittanutkoulutuksen": { - "@id": "mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen", - "title": "Suorittanut koulutuksen", - "@type": "@id", - "minItems": 0, - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen", - "properties": { - "paattymisvuosi": { - "@id": "mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/paattymisvuosi", - "title": "Päättymisvuosi", - "description": "Päättymishetki vuoden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "tutkintonimikekoodi": { - "@id": "mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/tutkintonimikekoodi", - "title": "Tutkintonimikekoodi", - "description": "Tilastokeskuksen koulutusluokituksen 2019 mukainen koodi.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "patevyys": { - "@id": "mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/patevyys", - "title": "Pätevyys", - "description": "Koulutuksen suoritettamisesta saatava pätevyys", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/patevyys/Patevyys", - "properties": { - "koodi": { - "@id": "mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/patevyys/Patevyys/koodi", - "title": "Koodi", - "description": "Ei raportoida, sillä koodistoa ei ole.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" + pysyvantunnisteentyyppi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvantunnisteentyyppi', + title: 'Pysyvän tunnisteen tyyppi', + description: + 'Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.', + enum: [], + '@type': + 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + }, + }, }, - "kuvaus": { - "@id": "mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/patevyys/Patevyys/kuvaus", - "title": "Kuvaus", - "description": "kohteen sisällöstä kertova tieto", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } + }, + }, + }, + jufotunnus: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/julkaisukanava/Julkaisukanava/jufotunnus', + title: 'Jufotunnus', + description: + 'Julkaisukanavan tunniste Julkaisufoorumissa (JUFO-ID).', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + yksilointitunnus: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/julkaisukanava/Julkaisukanava/yksilointitunnus', + title: 'Yksilöintitunnus', + description: 'Yksilöivä tunniste, julkaisukanavalle ISSN', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus', + properties: { + pysyvatunniste: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvatunniste', + title: 'Pysyvä tunniste', + description: + 'Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', }, - "nimi": { - "@id": "mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/patevyys/Patevyys/nimi", - "title": "Nimi", - "description": "Pätevyyden nimi", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } - } - } - } - }, - "paikallinentunnus": { - "@id": "mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/paikallinentunnus", - "title": "Paikallinen tunnus", - "description": "Raportoivan organisaation oma paikallinen tunniste tutkijan koulutukselle. Tunniste tarvitaan, mikäli tietoja mahdollisesti korjataan tai poistetaan jälkeenpäin.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "koulutuksenjarjestaja": { - "@id": "mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/koulutuksenjarjestaja", - "title": "Koulutuksen järjestäjä", - "description": "Tutkijan omaaman koulutuksen järjestänyt taho (organisaatio). Kyseinen koulutus saattaa johtaa muodolliseen pätevyyteen tai tutkintoon, muttei välttämättä.", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/koulutuksenjarjestaja/Koulutuksenjarjestaja", - "properties": { - "nimi": { - "@id": "mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/koulutuksenjarjestaja/Koulutuksenjarjestaja/nimi", - "title": "Nimi", - "description": "Organisaation nimi", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } + pysyvantunnisteentyyppi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvantunnisteentyyppi', + title: 'Pysyvän tunnisteen tyyppi', + description: + 'Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.', + enum: [], + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', }, - "yksilointitunnus": { - "@id": "mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/koulutuksenjarjestaja/Koulutuksenjarjestaja/yksilointitunnus", - "title": "Yksilöintitunnus", - "description": "Yksilöivä tunniste", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus", - "properties": { - "pysyvatunniste": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvatunniste", - "title": "Pysyvä tunniste", - "description": "Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "pysyvantunnisteentyyppi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvantunnisteentyyppi", - "title": "Pysyvän tunnisteen tyyppi", - "description": "Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.", - "enum": [], - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - } - } - } - } - } - } - }, - "paattymispaiva": { - "@id": "mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/paattymispaiva", - "title": "Päättymispäivä", - "description": "Päättymishetki päivän tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole. Pelkkä päivä ja vuosi ei toki ole mielekäs.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "tunnus": { - "@id": "mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/tunnus", - "title": "Tunniste", - "description": "Ei käytössä, sillä ei-tutkintoon johtaville koulutuksille ei ole löydetty soveliasta koodistoa. \nTutkintoon johtavat koulutukset annetaan kohdassa tutkintonimikekoodi.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "paattymiskuukausi": { - "@id": "mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/paattymiskuukausi", - "title": "Päättymiskuukausi", - "description": "Päättymishetki kuukauden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "alkamisvuosi": { - "@id": "mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/alkamisvuosi", - "title": "Alkamisvuosi", - "description": "Alkamishetki vuoden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.\n\nKoulutukselle tulisi antaa minimissään joko alkamis- tai päättymisvuosi.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "alkamiskuukausi": { - "@id": "mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/alkamiskuukausi", - "title": "Alkamiskuukausi", - "description": "Alkamishetki kuukauden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "alkamispaiva": { - "@id": "mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/alkamispaiva", - "title": "Alkamispäivä", - "description": "Alkamishetki päivän tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole. Toki vuoden ja päivämäärän yhdistelmä ei ole mielekäs.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "kuvaus": { - "@id": "mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/kuvaus", - "title": "Koulutuksen kuvaus", - "description": "Koulutuksen laajempi kuvaus", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } - }, - "laajuus": { - "@id": "mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/laajuus", - "title": "Laajuus", - "description": "Laajuus osaamispisteinä", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "tutkintonimike_nimi": { - "@id": "mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/tutkintonimike_nimi", - "title": "Tutkintonimike", - "description": "Nimike, jota henkilö voi käyttää suoritettuaan sen käyttöön oikeuttavan tutkinnon. Tämän attribuutin päätehtävä on tarjota mahdollisuus antaa nimiketieto silloin, kun vastaavaa koodistoarvoa ei ole, tai se ei ole tiedossa (esim ulkomaiset tutkinnot).", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } - }, - "opetuskieli": { - "@id": "mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/opetuskieli", - "title": "Opetuskieli", - "description": "Kieli, jolla koulutukseen liittyvä opetus on annettu.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "nimi": { - "@id": "mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/nimi", - "title": "Nimi", - "description": "Koulutuksen nimi, esim. tutkinnon nimi.", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "minItems": 1, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } - } + }, + }, + }, }, - "required": [ - "nimi" - ] - } - }, - "verkkolinkki": { - "@id": "mscr:root/Root/tutkija/Tutkija/verkkolinkki", - "title": "Verkkolinkki", - "description": "Has a webpresence at a given service/url, e.g. an organisational www-page, twitter, linked-in, facebook, etc", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/verkkolinkki/Verkkolinkki", - "properties": { - "url": { - "@id": "mscr:root/Root/tutkija/Tutkija/verkkolinkki/Verkkolinkki/url", - "title": "URL", - "description": "Uniform Resource Locator (URL)", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "linkintyyppi": { - "@id": "mscr:root/Root/tutkija/Tutkija/verkkolinkki/Verkkolinkki/linkintyyppi", - "title": "Linkin tyyppi", - "description": "Palvelu tai osoitteen laji johon linkki viittaa. Esim Linked-In tai tutkijaprofiili affiliaation verkkosivulla. Tämä eroaa kuitenkin tunnisteesta, joten ei esim ORCID.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "kuvaus": { - "@id": "mscr:root/Root/tutkija/Tutkija/verkkolinkki/Verkkolinkki/kuvaus", - "title": "Kuvaus", - "description": "kohteen sisällöstä kertova tieto", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } - } - } - } - }, - "yhteystieto": { - "@id": "mscr:root/Root/tutkija/Tutkija/yhteystieto", - "title": "Yhteystiedot", - "description": "Toimijan yhteystiedot", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/yhteystieto/Yhteystieto", - "properties": { - "puhelinnumero": { - "@id": "mscr:root/Root/tutkija/Tutkija/yhteystieto/Yhteystieto/puhelinnumero", - "title": "Puhelinnumero", - "description": "puhelinnumeron määritelmä", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "sahkopostiosoite": { - "@id": "mscr:root/Root/tutkija/Tutkija/yhteystieto/Yhteystieto/sahkopostiosoite", - "title": "Sähköpostiosoite", - "description": "tunnus, jonka mukaan sähköpostiviesti ohjautuu tietoverkossa oikealle vastaanottajalle", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - } - } - } - }, - "avainsanat": { - "@id": "mscr:root/Root/tutkija/Tutkija/avainsanat", - "title": "Avainsanat", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/avainsanat/Avainsanat", - "properties": { - "nimiavaruus": { - "@id": "mscr:root/Root/tutkija/Tutkija/avainsanat/Avainsanat/nimiavaruus", - "title": "Nimiavaruus", - "description": "Sanasto, tai ontologia jossa avainsana on määritelty (voi olla myös useammassa sanastossa).", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "maaritelma": { - "@id": "mscr:root/Root/tutkija/Tutkija/avainsanat/Avainsanat/maaritelma", - "title": "Määritelmä", - "description": "käsitteen kuvaus, jonka tulee erottaa käsite sen lähikäsitteistä", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } - }, - "yksilointitunnus": { - "@id": "mscr:root/Root/tutkija/Tutkija/avainsanat/Avainsanat/yksilointitunnus", - "title": "Yksilöintitunnus", - "description": "Avainsanan URI tunniste (voi olla myös useammassa sanastossa).", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus", - "properties": { - "pysyvatunniste": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvatunniste", - "title": "Pysyvä tunniste", - "description": "Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" + required: ['nimi'], + }, + }, + rahoituspaatos: { + '@id': 'mscr:root/Root/aktiviteetti/Aktiviteetti/rahoituspaatos', + title: 'Rahoittaneen rahoituspäätöksen tunniste', + description: 'Aktiviteettia rahoittanut rahoituspäätös', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/rahoituspaatos/Rahoituspaatos', + properties: { + pysyvatunniste: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/rahoituspaatos/Rahoituspaatos/pysyvatunniste', + title: 'Pysyvä tunniste', + description: + 'Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + pysyvantunnisteentyyppi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/rahoituspaatos/Rahoituspaatos/pysyvantunnisteentyyppi', + title: 'Pysyvän tunnisteen tyyppi', + description: + 'Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.', + enum: [], + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + }, + }, + }, + kohdeorganisaatio: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio', + title: 'Kohdeorganisaatio', + description: + 'Organisaatio, jossa aktiviteetti suoritetaan (esim. vierailun kohdeorganisaatio tai palkinnon myöntävä organisaatio).', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio', + properties: { + yksilointitunnus: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus', + title: 'Yksilöintitunnus', + description: 'Yksilöivä tunniste', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus', + properties: { + pysyvatunniste: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvatunniste', + title: 'Pysyvä tunniste', + description: + 'Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', }, - "pysyvantunnisteentyyppi": { - "@id": "mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvantunnisteentyyppi", - "title": "Pysyvän tunnisteen tyyppi", - "description": "Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.", - "enum": [], - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - } - } - } - }, - "kielikoodi": { - "@id": "mscr:root/Root/tutkija/Tutkija/avainsanat/Avainsanat/kielikoodi", - "title": "Kielikoodi", - "description": "avainsanan kieli", - "enum": [], - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "avainsana": { - "@id": "mscr:root/Root/tutkija/Tutkija/avainsanat/Avainsanat/avainsana", - "title": "Avainsana", - "description": "Tutkimuksen luokkaa kuvaava avainsana. Preferenssi on, että kuvaamiseen käytetään ulkoista sanastoa/ontologiaa. Myös käsitteetöntä tietoa voidaan antaa.", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "minItems": 1, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } - } + pysyvantunnisteentyyppi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvantunnisteentyyppi', + title: 'Pysyvän tunnisteen tyyppi', + description: + 'Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.', + enum: [], + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + }, + }, + }, + nimi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/nimi', + title: 'Nimi', + description: 'Organisaation nimi', + '@type': + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, + }, + }, }, - "required": [ - "avainsana" - ] - } - }, - "jasenyystutkimusyhteisossa": { - "@id": "mscr:root/Root/tutkija/Tutkija/jasenyystutkimusyhteisossa", - "title": "Jäsenyys tutkimusyhteisössä", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/jasenyystutkimusyhteisossa/Jasenyystutkimusyhteisossa", - "properties": { - "alkamispaiva": { - "@id": "mscr:root/Root/tutkija/Tutkija/jasenyystutkimusyhteisossa/Jasenyystutkimusyhteisossa/alkamispaiva", - "title": "Alkamispäivä", - "description": "Alkamishetki päivän tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole. Toki vuoden ja päivämäärän yhdistelmä ei ole mielekäs.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "kuvaus": { - "@id": "mscr:root/Root/tutkija/Tutkija/jasenyystutkimusyhteisossa/Jasenyystutkimusyhteisossa/kuvaus", - "title": "Kuvaus", - "description": "Kuvaus tutkijan roolista tutkimusyhteisössä (esim. johtaja, tutkija, tohtorikoulutettava).", - "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString", - "maxItems": 3, - "type": "array", - "items": { - "type": "object", - "title": "Multilingual string", - "description": "Object type for localized strings", - "additionalProperties": { - "type": "string" - } - } - }, - "paattymispaiva": { - "@id": "mscr:root/Root/tutkija/Tutkija/jasenyystutkimusyhteisossa/Jasenyystutkimusyhteisossa/paattymispaiva", - "title": "Päättymispäivä", - "description": "Päättymishetki päivän tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole. Pelkkä päivä ja vuosi ei toki ole mielekäs.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "alkamiskuukausi": { - "@id": "mscr:root/Root/tutkija/Tutkija/jasenyystutkimusyhteisossa/Jasenyystutkimusyhteisossa/alkamiskuukausi", - "title": "Alkamiskuukausi", - "description": "Alkamishetki kuukauden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "paattymisvuosi": { - "@id": "mscr:root/Root/tutkija/Tutkija/jasenyystutkimusyhteisossa/Jasenyystutkimusyhteisossa/paattymisvuosi", - "title": "Päättymisvuosi", - "description": "Päättymishetki vuoden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "paattymiskuukausi": { - "@id": "mscr:root/Root/tutkija/Tutkija/jasenyystutkimusyhteisossa/Jasenyystutkimusyhteisossa/paattymiskuukausi", - "title": "Päättymiskuukausi", - "description": "Päättymishetki kuukauden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - }, - "tutkijan_affiliaatio": { - "@id": "mscr:root/Root/tutkija/Tutkija/jasenyystutkimusyhteisossa/Jasenyystutkimusyhteisossa/tutkijan_affiliaatio", - "title": "Tutkimusyhteisö", - "description": "Tutkimusyhteisö ei ole tarkkaan määritelty käsite. Se on osittain päällekkäinen tutkimusryhmän kanssa. Tutkimusyhteisö voi olla poikkitieteellinen laitos-, tiedekuntarajat ylittävä tai jopa korkeakoulujen välinen tiettyyn teemaan tai tematiikkaan keskittyvä joukko tutkijoita, jota tuntevat jaetun kiinnostuksen kohteen kautta yhteenkuuluvuutta. Yhteisöön liitytään tehtävän tutkimuksen tematiikan kautta - sen mukaan mistä parhaiten vertaistukea ja yhteistyökumppaneita löytyy. Tutkijat voivat kuulua moniin eri yhteisöihin samanaikaisesti. Tutkimusyhteisöt eivät näin noudata hallinnollisten yksiköiden rajoja. Tutkijan kuuluminen tiettyyn tutkimusyhteisöön on tyypillisesti pysyväisluonteisempaa kuin tiettyyn organisatoriseen yksikköön kuuluminen.", - "@type": "@id", - "type": "array", - "items": { - "type": "object", - "@id": "urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/member_of/Member_of/tutkijan_affiliaatio/Tutkijan_affiliaatio", - "properties": { - "nimi": { - "@id": "mscr:root/Root/tutkija/Tutkija/member_of/Member_of/tutkijan_affiliaatio/Tutkijan_affiliaatio/nimi", - "title": "Nimi", - "description": "Alayksikön nimi", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "array", - "items": { - "type": "string" - } + }, + }, + paikallinentunnus: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/paikallinentunnus', + title: 'Paikallinen tunnus', + description: + 'Aktiviteetin tai palkinnon paikallinen tunniste raportoivassa organisaatiossa. Tunniste tarvitaan, mikäli aktiviteetin tai palkinnon tietoja korjataan tai poistetaan jälkeenpäin.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + yksilointitunnus: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/yksilointitunnus', + title: 'Yksilöintitunnus', + description: 'Yksilöivä tunniste', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus', + properties: { + pysyvatunniste: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvatunniste', + title: 'Pysyvä tunniste', + description: + 'Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + pysyvantunnisteentyyppi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvantunnisteentyyppi', + title: 'Pysyvän tunnisteen tyyppi', + description: + 'Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.', + enum: [], + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + }, + }, + }, + alkamisvuosi: { + '@id': 'mscr:root/Root/aktiviteetti/Aktiviteetti/alkamisvuosi', + title: 'Alkamisvuosi', + description: + 'Alkamishetki vuoden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + roolitettutekija: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija', + title: 'Roolitettu tekijä', + description: + 'Aktiviteettiin tai palkintoon nimetyllä roolilla osallistuva henkilö (tekijä/saaja).', + '@type': '@id', + minItems: 1, + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija', + properties: { + kuvaus: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/kuvaus', + title: 'Rooli tutkimustuotoksessa', + description: + 'Tutkijan tietojen siirtoprofiilissa rooli tutkimustuotoksessa kuvaa tutkijan roolia aktiviteetissa tai palkinnossa. Rooli ilmoitetaan aktiviteettien ja palkintojen tyypit ja roolit -koodiston mukaisesti.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + tekijantunniste: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/tekijantunniste', + title: 'Tekijän tunniste', + description: + 'Tutkimusaktiviteetin tekemiseen/suorittamiseen osallistuneet tutkijat tai muut henkilöt', + '@type': '@id', + minItems: 1, + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/tekijantunniste/Tekijantunniste', + properties: { + pysyvatunniste: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/tekijantunniste/Tekijantunniste/pysyvatunniste', + title: 'Pysyvä tunniste', + description: + 'Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', }, - "alayksikkokoodi": { - "@id": "mscr:root/Root/tutkija/Tutkija/member_of/Member_of/tutkijan_affiliaatio/Tutkijan_affiliaatio/alayksikkokoodi", - "title": "Alayksikkökoodi", - "description": "Alayksikön koodi OKM:lle raportoidussa alayksikkökoodistossa.", - "enum": [], - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - } - } - } - }, - "alkamisvuosi": { - "@id": "mscr:root/Root/tutkija/Tutkija/jasenyystutkimusyhteisossa/Jasenyystutkimusyhteisossa/alkamisvuosi", - "title": "Alkamisvuosi", - "description": "Alkamishetki vuoden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.", - "@type": "http://www.w3.org/2001/XMLSchema#integer", - "type": "integer" - } - } - } - }, - "etunimet": { - "@id": "mscr:root/Root/tutkija/Tutkija/etunimet", - "title": "Etunimet", - "description": "henkilön kaikki etunimet lueteltuna", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "type": "string" - }, - "kokonimi": { - "@id": "mscr:root/Root/tutkija/Tutkija/kokonimi", - "title": "Nimi", - "description": "henkilön täydellinen nimi", - "@type": "http://www.w3.org/2001/XMLSchema#string", - "minItems": 1, - "type": "array", - "items": { - "type": "string" - } - } - }, - "required": [ - "yksilointitunnus", - "kokonimi" - ] - } - } - } - } -} - -export default function MockupSchemaLoader(emptyTemplate: boolean): Promise<RenderTree[] | undefined> { - const hugeTestData: any = { - "$schema": "http://json-schema.org/draft-04/schema#", - "properties": { - "null": { - "title": null, - "description": null - }, - "acoustic_area_backscattering_strength_in_sea_water": { - "title": "acoustic_area_backscattering_strength_in_sea_water", - "description": "Acoustic area backscattering strength is 10 times the log10 of the ratio of the area backscattering coefficient to the reference value, 1 (m2 m-2). Area backscattering coefficient is the integral of the volume backscattering coefficient over a defined distance. Volume backscattering coefficient is the linear form of acoustic_volume_backscattering_strength_in_sea_water. For further details see MacLennan et. al (2002) doi:10.1006/jmsc.2001.1158." - }, - "acoustic_signal_roundtrip_travel_time_in_sea_water": { - "title": "acoustic_signal_roundtrip_travel_time_in_sea_water", - "description": "The quantity with standard name acoustic_signal_roundtrip_travel_time_in_sea_water is the time taken for an acoustic signal to propagate from the emitting instrument to a reflecting surface and back again to the instrument. In the case of an instrument based on the sea floor and measuring the roundtrip time to the sea surface, the data are commonly used as a measure of ocean heat content." - }, - "acoustic_target_strength_in_sea_water": { - "title": "acoustic_target_strength_in_sea_water", - "description": "Target strength is 10 times the log10 of the ratio of backscattering cross-section to the reference value, 1 m2. Backscattering cross-section is a parameter computed from the intensity of the backscattered sound wave relative to the intensity of the incident sound wave. For further details see MacLennan et. al (2002) doi:10.1006/jmsc.2001.1158." - }, - "acoustic_volume_backscattering_strength_in_sea_water": { - "title": "acoustic_volume_backscattering_strength_in_sea_water", - "description": "Acoustic volume backscattering strength is 10 times the log10 of the ratio of the volume backscattering coefficient to the reference value, 1 m-1. Volume backscattering coefficient is the integral of the backscattering cross-section divided by the volume sampled. Backscattering cross-section is a parameter computed from the intensity of the backscattered sound wave relative to the intensity of the incident sound wave. The parameter is computed to provide a measurement that is proportional to biomass density per unit volume in the field of fisheries acoustics. For further details see MacLennan et. al (2002) doi:10.1006/jmsc.2001.1158." - }, - } - } - - const testData: any = { - '$schema': 'http://json-schema.org/draft-04/schema#', - 'type': 'object', - 'properties': { - '$schema': { - 'type': 'string' - }, - 'string_type': { - 'type': 'string', - 'description': '01_string_description' - }, - 'number_type': { - 'type': 'number', - 'minimum': 3, - 'exclusiveMinimum': false - }, - 'integer_type': { - 'type': 'integer', - 'minimum': 2 - }, - 'boolean_type': { - 'type': 'boolean' - }, - 'null_type': { - 'type': 'null' - }, - 'object_type': { - 'title': 'OBJECT TYPE', - 'type': 'object', - 'properties': { - 'string_property': { - 'title': 'string_prop', - 'type': 'string' - } + pysyvantunnisteentyyppi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/tekijantunniste/Tekijantunniste/pysyvantunnisteentyyppi', + title: 'Pysyvän tunnisteen tyyppi', + description: + 'Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.', + enum: [], + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + }, + }, + }, + sukunimituotoksessa: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/sukunimituotoksessa', + title: 'Sukunimi tuotoksessa', + description: + 'Sukunimi aktiviteetissa tai palkinnossa. Nimi on tässä aktiviteetin tai palkinnon metatieto. Se voi siis olla eri kuin tutkijan nykyinen nimi.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + tekijanaffiliaatiotuotoksenkontekstissa: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/tekijanaffiliaatiotuotoksenkontekstissa', + title: 'Tekijän affiliaatio tuotoksen kontekstissa', + description: + 'Tekijälle on tuotoksessa ilmoitettu yksi tai useampi affiliaatio. Tuotoksen kontekstissa annettua affiliaatiota ei voida varmuudella päätellä tutkijan tuotoksenaikaisista affiliaatioista.', + '@type': '@id', + minItems: 1, + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/tekijanaffiliaatiotuotoksenkontekstissa/Tekijanaffiliaatiotuotoksenkontekstissa', + properties: { + yksilointitunnus: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/tekijanaffiliaatiotuotoksenkontekstissa/Tekijanaffiliaatiotuotoksenkontekstissa/yksilointitunnus', + title: 'Yksilöintitunnus', + description: 'Yksilöivä tunniste', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus', + properties: { + pysyvatunniste: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvatunniste', + title: 'Pysyvä tunniste', + description: + 'Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.', + '@type': + 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + pysyvantunnisteentyyppi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvantunnisteentyyppi', + title: 'Pysyvän tunnisteen tyyppi', + description: + 'Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.', + enum: [], + '@type': + 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + }, + }, + }, + nimi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/tekijanaffiliaatiotuotoksenkontekstissa/Tekijanaffiliaatiotuotoksenkontekstissa/nimi', + title: 'Nimi', + description: 'Organisaation nimi', + '@type': + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, + }, + }, + }, + }, + }, + muunimituotoksessa: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/muunimituotoksessa', + title: 'Muu nimi tuotoksessa', + description: + 'Muu nimi aktiviteetissa tai palkinnossa. Nimi on tässä aktiviteetin tai palkinnon metatieto. Se voi siis olla eri kuin tutkijan nykyinen nimi.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + etunimettuotoksessa: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/etunimettuotoksessa', + title: 'Etunimet tuotoksessa', + description: + 'Etunimi aktiviteetissa tai palkinnossa. Nimi on tässä aktiviteetin tai palkinnon metatieto. Se voi siis olla eri kuin tutkijan nykyinen nimi.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + roolikoodi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/roolitettutekija/Roolitettutekija/roolikoodi', + title: 'Roolikoodi', + description: + 'Aktiviteettien ja palkintojen tyypit ja roolit -koodiston mukainen arvo.', + enum: [], + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, }, - 'required': ['string_property'] - }, - 'array_string_type': { - 'type': 'array', - 'maxItems': 5, - 'items': { - 'type': 'string' - } - }, - 'object_arrays_type': { - 'type': 'object', - 'properties': { - 'array_property': { - 'title': 'array_prop', - 'type': 'array', - 'items': { - 'type': 'number' - } - } - } - } - }, - 'additionalProperties': false, - 'b2share': { - 'presentation': { - 'major': ['community', 'titles', 'descriptions', 'creators', 'open_access', 'embargo_date', 'license', 'disciplines', 'keywords', 'contact_email'], - 'minor': ['contributors', 'resource_types', 'alternate_identifiers', 'version', 'publisher', 'language'] - } - } - }; - - const testSchema: any = { - '$schema': 'http://json-schema.org/draft-04/schema#', - 'type': 'object', - 'properties': { - '$schema': { - 'type': 'string' - }, - 'creators': { - 'title': 'Creators', - 'description': 'The full name of the creators. The personal name format should be: family, given (e.g.: Smith, John).', - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'creator_name': { - 'type': 'string' - } + required: [ + 'tekijantunniste', + 'tekijanaffiliaatiotuotoksenkontekstissa', + ], + }, + }, + avainsanat: { + '@id': 'mscr:root/Root/aktiviteetti/Aktiviteetti/avainsanat', + title: 'Avainsanat', + description: 'Aktiviteettia kuvaavat avainsanat', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/avainsanat/Avainsanat', + properties: { + nimiavaruus: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/avainsanat/Avainsanat/nimiavaruus', + title: 'Nimiavaruus', + description: + 'Sanasto, tai ontologia jossa avainsana on määritelty (voi olla myös useammassa sanastossa).', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + maaritelma: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/avainsanat/Avainsanat/maaritelma', + title: 'Määritelmä', + description: + 'käsitteen kuvaus, jonka tulee erottaa käsite sen lähikäsitteistä', + '@type': + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, + }, + }, + yksilointitunnus: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/avainsanat/Avainsanat/yksilointitunnus', + title: 'Yksilöintitunnus', + description: + 'Avainsanan URI tunniste (voi olla myös useammassa sanastossa).', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus', + properties: { + pysyvatunniste: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvatunniste', + title: 'Pysyvä tunniste', + description: + 'Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + pysyvantunnisteentyyppi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvantunnisteentyyppi', + title: 'Pysyvän tunnisteen tyyppi', + description: + 'Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.', + enum: [], + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + }, }, - 'additionalProperties': false, - 'required': ['creator_name'] + }, + kielikoodi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/avainsanat/Avainsanat/kielikoodi', + title: 'Kielikoodi', + description: 'avainsanan kieli', + enum: [], + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + avainsana: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/avainsanat/Avainsanat/avainsana', + title: 'Avainsana', + description: + 'Tutkimuksen luokkaa kuvaava avainsana. Preferenssi on, että kuvaamiseen käytetään ulkoista sanastoa/ontologiaa. Myös käsitteetöntä tietoa voidaan antaa.', + '@type': + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + minItems: 1, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, + }, + }, }, - 'uniqueItems': true - }, - 'titles': { - 'title': 'Titles', - 'description': 'The title(s) of the uploaded resource, or a name by which the resource is known.', - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'title': { - 'type': 'string' - } + required: ['avainsana'], + }, + }, + maakoodi: { + '@id': 'mscr:root/Root/aktiviteetti/Aktiviteetti/maakoodi', + title: 'Maakoodi', + description: + 'Aktiviteetin suorittamisen ensisijainen maa. Esim. vierailun kohdemaa, tapahtuman järjestämispaikan maa tai maa, josta palkinto on myönnetty.', + enum: [], + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + paattymisvuosi: { + '@id': 'mscr:root/Root/aktiviteetti/Aktiviteetti/paattymisvuosi', + title: 'Päättymisvuosi', + description: + 'Päättymishetki vuoden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + alkamiskuukausi: { + '@id': 'mscr:root/Root/aktiviteetti/Aktiviteetti/alkamiskuukausi', + title: 'Alkamiskuukausi', + description: + 'Alkamishetki kuukauden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + verkkolinkki: { + '@id': 'mscr:root/Root/aktiviteetti/Aktiviteetti/verkkolinkki', + title: 'Verkkolinkki', + description: + 'Esimekiksi tutkijalla, tutkimusyhteisöllä, organisaatiolla, voi olla erilaisia läsnäolon muotoja internetissä, joka on määritelty omassa luokassaan. Tämä on osoitin tuohon luokkaan.', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/verkkolinkki/Verkkolinkki', + properties: { + url: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/verkkolinkki/Verkkolinkki/url', + title: 'URL', + description: 'Uniform Resource Locator (URL)', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + linkintyyppi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/verkkolinkki/Verkkolinkki/linkintyyppi', + title: 'Linkin tyyppi', + description: + 'Palvelu tai osoitteen laji johon linkki viittaa. Esim Linked-In tai tutkijaprofiili affiliaation verkkosivulla. Tämä eroaa kuitenkin tunnisteesta, joten ei esim ORCID.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + kuvaus: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/verkkolinkki/Verkkolinkki/kuvaus', + title: 'Kuvaus', + description: 'kohteen sisällöstä kertova tieto', + '@type': + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, }, - 'additionalProperties': false, - 'required': ['title'] + }, }, - 'minItems': 1, - 'uniqueItems': true - }, - 'publisher': { - 'title': 'Publisher', - 'description': 'The entity responsible for making the resource available, either a person, an organization, or a service.', - 'type': 'string' - }, - 'publication_date': { - 'title': 'Publication Date', - 'description': 'The date when the data was or will be made publicly available (e.g. 1971-07-13)', - 'type': 'string', - 'format': 'date' - }, - 'disciplines': { - 'title': 'Disciplines', - 'description': 'The scientific disciplines linked with the resource.', - 'type': 'array', - 'items': { - 'type': 'string' + }, + }, + nimi: { + '@id': 'mscr:root/Root/aktiviteetti/Aktiviteetti/nimi', + title: 'Nimi', + description: 'Aktiviteettia tai palkintoa kuvaava nimi.', + '@type': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + minItems: 1, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', }, - 'uniqueItems': true - }, - 'keywords': { - 'title': 'Keywords', - 'description': 'A list of keywords or key phrases describing the resource.', - 'type': 'array', - 'items': { - 'type': 'string' + }, + }, + kuvaus: { + '@id': 'mscr:root/Root/aktiviteetti/Aktiviteetti/kuvaus', + title: 'Kuvaus', + description: 'Aktiviteetin tai palkinnon tarkempi kuvaus.', + '@type': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', }, - 'uniqueItems': true + }, }, - 'contributors': { - 'title': 'Contributors', - 'description': 'The list of all other contributors. Please mention all persons that were relevant in the creation of the resource.', - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'contributor_name': { - 'title': 'Name', - 'type': 'string' + }, + required: ['nimi', 'roolitettutekija'], + }, + }, + organisaatiorakenteenvuosi: { + '@id': 'mscr:root/Root/organisaatiorakenteenvuosi', + title: 'Organisaatiorakenteen vuosi', + description: + 'Organisaatioiden rakenteet ovat jatkuvan muutoksen alaisena. Tällä kentällä kerrotaan minkävuoden mukaista organisaatiorakennetta tiedoissa käytetään.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + raportoivanorganisaationtunniste: { + '@id': 'mscr:root/Root/raportoivanorganisaationtunniste', + title: 'Raportoivan organisaation tunniste', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + tutkija: { + '@id': 'mscr:root/Root/tutkija', + title: 'Tutkijat', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija', + properties: { + tutkijankuvaus: { + '@id': 'mscr:root/Root/tutkija/Tutkija/tutkijankuvaus', + title: 'Tutkijan kuvaus', + description: + 'Vapaamuotoinen kuvaus tutkijan relevanteista kyvykkyyksistä.', + '@type': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, + }, + }, + member_of: { + '@id': 'mscr:root/Root/tutkija/Tutkija/member_of', + title: 'Jäsenyys', + '@type': '@id', + minItems: 0, + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/member_of/Member_of', + properties: { + affiliaation_tyyppi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/member_of/Member_of/affiliaation_tyyppi', + title: 'Affiliaation tyyppi', + description: + 'Henkilön suhde organisaatioon (esim. työsuhde, dosentuuri, vieraileva tutkija).', + '@type': + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, + }, + }, + tehtavanimike: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/member_of/Member_of/tehtavanimike', + title: 'Tehtävänimike', + description: + 'Henkilön nimike tyypillisimmin työsuhteessa organisaatioon (esim. professori, yliopistonlehtori, tuntiopettaja). Tämä on erityisesti niille toimijoille, joilla nimikkeet eivät perustu yliopistojen tehtävänimikekoodistoon. Mikäli kentässä Tehtäväkoodi on arvo, tämä kenttä voi olla tyhjä.', + '@type': + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, + }, + }, + paattymisvuosi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/member_of/Member_of/paattymisvuosi', + title: 'Päättymisvuosi', + description: + 'Päättymishetki vuoden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + paattymispaiva: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/member_of/Member_of/paattymispaiva', + title: 'Päättymispäivä', + description: + 'Päättymishetki päivän tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole. Pelkkä päivä ja vuosi ei toki ole mielekäs.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + paikallinentunnus: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/member_of/Member_of/paikallinentunnus', + title: 'Paikallinen tunnus', + description: + 'Raportoivan organisaation oma paikallinen tunniste tutkijan affiliaatiolle. Tunniste tarvitaan, mikäli tietoja mahdollisesti korjataan tai poistetaan jälkeenpäin.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + alkamisvuosi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/member_of/Member_of/alkamisvuosi', + title: 'Alkamisvuosi', + description: + 'Alkamishetki vuoden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + paattymiskuukausi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/member_of/Member_of/paattymiskuukausi', + title: 'Päättymiskuukausi', + description: + 'Päättymishetki kuukauden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + alkamispaiva: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/member_of/Member_of/alkamispaiva', + title: 'Alkamispäivä', + description: + 'Alkamishetki päivän tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole. Toki vuoden ja päivämäärän yhdistelmä ei ole mielekäs.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + tehtavakoodi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/member_of/Member_of/tehtavakoodi', + title: 'Tehtäväkoodi', + description: + 'Koodiston määrittelemä koodi/tunniste tehtävänimikkeelle. Käytetty koodisto pätee vain korkeakouluille.', + enum: [], + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + tutkijan_affiliaatio: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/member_of/Member_of/tutkijan_affiliaatio', + title: 'Alayksikkö', + description: + 'Alayksikkö, johon tutkija on affilioitunut. Alayksikön tulee olla OKM:lle raportoidussa alayksikkökoodistossa .', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/member_of/Member_of/tutkijan_affiliaatio/Tutkijan_affiliaatio', + properties: { + nimi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/member_of/Member_of/tutkijan_affiliaatio/Tutkijan_affiliaatio/nimi', + title: 'Nimi', + description: 'Alayksikön nimi', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'array', + items: { + type: 'string', + }, + }, + alayksikkokoodi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/member_of/Member_of/tutkijan_affiliaatio/Tutkijan_affiliaatio/alayksikkokoodi', + title: 'Alayksikkökoodi', + description: + 'Alayksikön koodi OKM:lle raportoidussa alayksikkökoodistossa.', + enum: [], + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', }, - 'contributor_type': { - 'title': 'Type', - 'enum': ['ContactPerson', 'DataCollector', 'DataCurator', 'DataManager', 'Distributor', 'Editor', 'HostingInstitution', 'Producer', 'ProjectLeader', 'ProjectManager', 'ProjectMember', 'RegistrationAgency', 'RegistrationAuthority', 'RelatedPerson', 'Researcher', 'ResearchGroup', 'RightsHolder', 'Sponsor', 'Supervisor', 'WorkPackageLeader', 'Other'] - } + }, }, - 'additionalProperties': false, - 'required': ['contributor_name', 'contributor_type'] + }, + alkamiskuukausi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/member_of/Member_of/alkamiskuukausi', + title: 'Alkamiskuukausi', + description: + 'Alkamishetki kuukauden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, }, - 'uniqueItems': true - }, - 'language': { - 'title': 'Language', - 'description': 'The primary language of the resource. Please use ISO_639-3 language codes.', - 'type': 'string' - }, - 'resource_types': { - 'title': 'Resource Type', - 'description': 'The type(s) of the resource.', - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'resource_type': { - 'title': 'Description', - 'type': 'string' + }, + }, + sukunimi: { + '@id': 'mscr:root/Root/tutkija/Tutkija/sukunimi', + title: 'Sukunimi', + description: + 'pääasiallisesti sukuun viittaava rekisteröidyn henkilönnimen osa', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + vaihtoehtoinennimi: { + '@id': 'mscr:root/Root/tutkija/Tutkija/vaihtoehtoinennimi', + title: 'Vaihtoehtoinen nimi', + description: + 'nimi, jolla henkilö tai oikeushenkilö tunnetaan ja joka ei ole henkilön tai oikeushenkilön rekisteröity nimi', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'array', + items: { + type: 'string', + }, + }, + paikallinentunnus: { + '@id': 'mscr:root/Root/tutkija/Tutkija/paikallinentunnus', + title: 'Paikallinen tunnus', + description: + 'Ei-globaali tai standardoitu tunniste, vaan jonkin lähdejärjestelmän paikkallinen tunniste.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + yksilointitunnus: { + '@id': 'mscr:root/Root/tutkija/Tutkija/yksilointitunnus', + title: 'Yksilöintitunnus', + description: + 'Tutkimuksen piirissä toimivan henkilön yksilöivä tunniste, tyypillisimmin ORCID, esim julkaisun/teoksen yhteydessä ISNI', + '@type': '@id', + minItems: 1, + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus', + properties: { + pysyvatunniste: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvatunniste', + title: 'Pysyvä tunniste', + description: + 'Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + pysyvantunnisteentyyppi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvantunnisteentyyppi', + title: 'Pysyvän tunnisteen tyyppi', + description: + 'Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.', + enum: [], + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + }, + }, + }, + suorittanutkoulutuksen: { + '@id': 'mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen', + title: 'Suorittanut koulutuksen', + '@type': '@id', + minItems: 0, + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen', + properties: { + paattymisvuosi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/paattymisvuosi', + title: 'Päättymisvuosi', + description: + 'Päättymishetki vuoden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + tutkintonimikekoodi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/tutkintonimikekoodi', + title: 'Tutkintonimikekoodi', + description: + 'Tilastokeskuksen koulutusluokituksen 2019 mukainen koodi.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + patevyys: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/patevyys', + title: 'Pätevyys', + description: + 'Koulutuksen suoritettamisesta saatava pätevyys', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/patevyys/Patevyys', + properties: { + koodi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/patevyys/Patevyys/koodi', + title: 'Koodi', + description: 'Ei raportoida, sillä koodistoa ei ole.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + kuvaus: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/patevyys/Patevyys/kuvaus', + title: 'Kuvaus', + description: 'kohteen sisällöstä kertova tieto', + '@type': + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, + }, + }, + nimi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/patevyys/Patevyys/nimi', + title: 'Nimi', + description: 'Pätevyyden nimi', + '@type': + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, + }, }, - 'resource_type_general': { - 'title': 'Category', - 'enum': ['Audiovisual', 'Collection', 'Dataset', 'Event', 'Image', 'InteractiveResource', 'Model', 'PhysicalObject', 'Service', 'Software', 'Sound', 'Text', 'Workflow', 'Other'] - } + }, }, - 'additionalProperties': false, - 'required': ['resource_type_general'] - }, - 'minItems': 1, - 'uniqueItems': true - }, - 'alternate_identifiers': { - 'title': 'Alternate identifiers', - 'description': 'Any kind of other reference such as a URN, URI or an ISBN number.', - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'alternate_identifier': { - 'type': 'string' + }, + paikallinentunnus: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/paikallinentunnus', + title: 'Paikallinen tunnus', + description: + 'Raportoivan organisaation oma paikallinen tunniste tutkijan koulutukselle. Tunniste tarvitaan, mikäli tietoja mahdollisesti korjataan tai poistetaan jälkeenpäin.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + koulutuksenjarjestaja: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/koulutuksenjarjestaja', + title: 'Koulutuksen järjestäjä', + description: + 'Tutkijan omaaman koulutuksen järjestänyt taho (organisaatio). Kyseinen koulutus saattaa johtaa muodolliseen pätevyyteen tai tutkintoon, muttei välttämättä.', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/koulutuksenjarjestaja/Koulutuksenjarjestaja', + properties: { + nimi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/koulutuksenjarjestaja/Koulutuksenjarjestaja/nimi', + title: 'Nimi', + description: 'Organisaation nimi', + '@type': + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, + }, + }, + yksilointitunnus: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/koulutuksenjarjestaja/Koulutuksenjarjestaja/yksilointitunnus', + title: 'Yksilöintitunnus', + description: 'Yksilöivä tunniste', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus', + properties: { + pysyvatunniste: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvatunniste', + title: 'Pysyvä tunniste', + description: + 'Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.', + '@type': + 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + pysyvantunnisteentyyppi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvantunnisteentyyppi', + title: 'Pysyvän tunnisteen tyyppi', + description: + 'Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.', + enum: [], + '@type': + 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + }, + }, }, - 'alternate_identifier_type': { - 'title': 'Type', - 'type': 'string' - } + }, + }, + }, + paattymispaiva: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/paattymispaiva', + title: 'Päättymispäivä', + description: + 'Päättymishetki päivän tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole. Pelkkä päivä ja vuosi ei toki ole mielekäs.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + tunnus: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/tunnus', + title: 'Tunniste', + description: + 'Ei käytössä, sillä ei-tutkintoon johtaville koulutuksille ei ole löydetty soveliasta koodistoa. \nTutkintoon johtavat koulutukset annetaan kohdassa tutkintonimikekoodi.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + paattymiskuukausi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/paattymiskuukausi', + title: 'Päättymiskuukausi', + description: + 'Päättymishetki kuukauden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + alkamisvuosi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/alkamisvuosi', + title: 'Alkamisvuosi', + description: + 'Alkamishetki vuoden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.\n\nKoulutukselle tulisi antaa minimissään joko alkamis- tai päättymisvuosi.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + alkamiskuukausi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/alkamiskuukausi', + title: 'Alkamiskuukausi', + description: + 'Alkamishetki kuukauden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + alkamispaiva: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/alkamispaiva', + title: 'Alkamispäivä', + description: + 'Alkamishetki päivän tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole. Toki vuoden ja päivämäärän yhdistelmä ei ole mielekäs.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + kuvaus: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/kuvaus', + title: 'Koulutuksen kuvaus', + description: 'Koulutuksen laajempi kuvaus', + '@type': + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, + }, + }, + laajuus: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/laajuus', + title: 'Laajuus', + description: 'Laajuus osaamispisteinä', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + tutkintonimike_nimi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/tutkintonimike_nimi', + title: 'Tutkintonimike', + description: + 'Nimike, jota henkilö voi käyttää suoritettuaan sen käyttöön oikeuttavan tutkinnon. Tämän attribuutin päätehtävä on tarjota mahdollisuus antaa nimiketieto silloin, kun vastaavaa koodistoarvoa ei ole, tai se ei ole tiedossa (esim ulkomaiset tutkinnot).', + '@type': + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, + }, + }, + opetuskieli: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/opetuskieli', + title: 'Opetuskieli', + description: + 'Kieli, jolla koulutukseen liittyvä opetus on annettu.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + nimi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/suorittanutkoulutuksen/Suorittanutkoulutuksen/nimi', + title: 'Nimi', + description: 'Koulutuksen nimi, esim. tutkinnon nimi.', + '@type': + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + minItems: 1, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, }, - 'additionalProperties': false, - 'required': ['alternate_identifier', 'alternate_identifier_type'] + }, }, - 'uniqueItems': true - }, - 'descriptions': { - 'title': 'Descriptions', - 'description': 'A more elaborate description of the resource. Focus on a content description that makes it easy for others to find, and to interpret its relevance.', - 'type': 'array', - 'items': { - 'type': 'object', - 'properties': { - 'description': { - 'type': 'string' + required: ['nimi'], + }, + }, + verkkolinkki: { + '@id': 'mscr:root/Root/tutkija/Tutkija/verkkolinkki', + title: 'Verkkolinkki', + description: + 'Has a webpresence at a given service/url, e.g. an organisational www-page, twitter, linked-in, facebook, etc', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/verkkolinkki/Verkkolinkki', + properties: { + url: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/verkkolinkki/Verkkolinkki/url', + title: 'URL', + description: 'Uniform Resource Locator (URL)', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + linkintyyppi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/verkkolinkki/Verkkolinkki/linkintyyppi', + title: 'Linkin tyyppi', + description: + 'Palvelu tai osoitteen laji johon linkki viittaa. Esim Linked-In tai tutkijaprofiili affiliaation verkkosivulla. Tämä eroaa kuitenkin tunnisteesta, joten ei esim ORCID.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + kuvaus: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/verkkolinkki/Verkkolinkki/kuvaus', + title: 'Kuvaus', + description: 'kohteen sisällöstä kertova tieto', + '@type': + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, + }, + }, + }, + }, + }, + yhteystieto: { + '@id': 'mscr:root/Root/tutkija/Tutkija/yhteystieto', + title: 'Yhteystiedot', + description: 'Toimijan yhteystiedot', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/yhteystieto/Yhteystieto', + properties: { + puhelinnumero: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/yhteystieto/Yhteystieto/puhelinnumero', + title: 'Puhelinnumero', + description: 'puhelinnumeron määritelmä', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + sahkopostiosoite: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/yhteystieto/Yhteystieto/sahkopostiosoite', + title: 'Sähköpostiosoite', + description: + 'tunnus, jonka mukaan sähköpostiviesti ohjautuu tietoverkossa oikealle vastaanottajalle', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + }, + }, + }, + avainsanat: { + '@id': 'mscr:root/Root/tutkija/Tutkija/avainsanat', + title: 'Avainsanat', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/avainsanat/Avainsanat', + properties: { + nimiavaruus: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/avainsanat/Avainsanat/nimiavaruus', + title: 'Nimiavaruus', + description: + 'Sanasto, tai ontologia jossa avainsana on määritelty (voi olla myös useammassa sanastossa).', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + maaritelma: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/avainsanat/Avainsanat/maaritelma', + title: 'Määritelmä', + description: + 'käsitteen kuvaus, jonka tulee erottaa käsite sen lähikäsitteistä', + '@type': + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, + }, + }, + yksilointitunnus: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/avainsanat/Avainsanat/yksilointitunnus', + title: 'Yksilöintitunnus', + description: + 'Avainsanan URI tunniste (voi olla myös useammassa sanastossa).', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus', + properties: { + pysyvatunniste: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvatunniste', + title: 'Pysyvä tunniste', + description: + 'Kohteen yksilöivä ainutkertainen merkkijono, jonka avulla kohteeseen voidaan yksiselitteisesti viitata. \n\n- Tutkijalla tai aktiviteetin tekijällä ORCID.\n- Julkaisukanavalla ISSN tai ISBN.\n- Organisaatiolla esim. Y-tunnus tai ISNI.\n- Avainsanalla URI.\nTapahtumilla ei toistaiseksi ole käytössä vakiintunieta tunnisteita.', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + pysyvantunnisteentyyppi: { + '@id': + 'mscr:root/Root/aktiviteetti/Aktiviteetti/kohdeorganisaatio/Kohdeorganisaatio/yksilointitunnus/Yksilointitunnus/pysyvantunnisteentyyppi', + title: 'Pysyvän tunnisteen tyyppi', + description: + 'Pysyvän tunnisteen tyyppi Tutkimusaineistojen pysyvät tunnisteet -koodiston mukaisesti.', + enum: [], + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', }, - 'description_type': { - 'title': 'Type', - 'enum': ['Abstract', 'Methods', 'SeriesInformation', 'TableOfContents', 'TechnicalInfo', 'Other'] - } + }, + }, + }, + kielikoodi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/avainsanat/Avainsanat/kielikoodi', + title: 'Kielikoodi', + description: 'avainsanan kieli', + enum: [], + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + avainsana: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/avainsanat/Avainsanat/avainsana', + title: 'Avainsana', + description: + 'Tutkimuksen luokkaa kuvaava avainsana. Preferenssi on, että kuvaamiseen käytetään ulkoista sanastoa/ontologiaa. Myös käsitteetöntä tietoa voidaan antaa.', + '@type': + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + minItems: 1, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, }, - 'additionalProperties': false, - 'required': ['description', 'description_type'] + }, }, - 'uniqueItems': true - }, - 'version': { - 'title': 'Version', - 'description': 'Denote the version of the resource.', - 'type': 'string' - }, - 'contact_email': { - 'title': 'Contact Email', - 'description': 'Contact email information for this record.', - 'type': 'string', - 'format': 'email' - }, - 'open_access': { - 'title': 'Open Access', - 'description': 'Indicate whether the record\'s files are publicly accessible or not. In case of restricted access the uploaded files will only be accessible by the record\'s owner and the community administrators. Please note that the record\'s metadata is always publicly accessible. ', - 'type': 'boolean' - }, - 'embargo_date': { - 'title': 'Embargo Date', - 'description': 'The date marking the end of the embargo period. The record will be marked as open access on the specified date at midnight. Please note that the record metadata is always publicly accessible, and only the data files can have private access.', - 'type': 'string', - 'format': 'date-time' - }, - 'license': { - 'title': 'License', - 'description': 'Specify the license under which this data set is available to the users (e.g. GPL, Apache v2 or Commercial). Please use the License Selector for help and additional information.', - 'type': 'object', - 'properties': { - 'license': { - 'type': 'string' + required: ['avainsana'], + }, + }, + jasenyystutkimusyhteisossa: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/jasenyystutkimusyhteisossa', + title: 'Jäsenyys tutkimusyhteisössä', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/jasenyystutkimusyhteisossa/Jasenyystutkimusyhteisossa', + properties: { + alkamispaiva: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/jasenyystutkimusyhteisossa/Jasenyystutkimusyhteisossa/alkamispaiva', + title: 'Alkamispäivä', + description: + 'Alkamishetki päivän tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole. Toki vuoden ja päivämäärän yhdistelmä ei ole mielekäs.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + kuvaus: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/jasenyystutkimusyhteisossa/Jasenyystutkimusyhteisossa/kuvaus', + title: 'Kuvaus', + description: + 'Kuvaus tutkijan roolista tutkimusyhteisössä (esim. johtaja, tutkija, tohtorikoulutettava).', + '@type': + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', + maxItems: 3, + type: 'array', + items: { + type: 'object', + title: 'Multilingual string', + description: 'Object type for localized strings', + additionalProperties: { + type: 'string', + }, + }, + }, + paattymispaiva: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/jasenyystutkimusyhteisossa/Jasenyystutkimusyhteisossa/paattymispaiva', + title: 'Päättymispäivä', + description: + 'Päättymishetki päivän tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole. Pelkkä päivä ja vuosi ei toki ole mielekäs.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + alkamiskuukausi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/jasenyystutkimusyhteisossa/Jasenyystutkimusyhteisossa/alkamiskuukausi', + title: 'Alkamiskuukausi', + description: + 'Alkamishetki kuukauden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + paattymisvuosi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/jasenyystutkimusyhteisossa/Jasenyystutkimusyhteisossa/paattymisvuosi', + title: 'Päättymisvuosi', + description: + 'Päättymishetki vuoden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + paattymiskuukausi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/jasenyystutkimusyhteisossa/Jasenyystutkimusyhteisossa/paattymiskuukausi', + title: 'Päättymiskuukausi', + description: + 'Päättymishetki kuukauden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella, jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, + tutkijan_affiliaatio: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/jasenyystutkimusyhteisossa/Jasenyystutkimusyhteisossa/tutkijan_affiliaatio', + title: 'Tutkimusyhteisö', + description: + 'Tutkimusyhteisö ei ole tarkkaan määritelty käsite. Se on osittain päällekkäinen tutkimusryhmän kanssa. Tutkimusyhteisö voi olla poikkitieteellinen laitos-, tiedekuntarajat ylittävä tai jopa korkeakoulujen välinen tiettyyn teemaan tai tematiikkaan keskittyvä joukko tutkijoita, jota tuntevat jaetun kiinnostuksen kohteen kautta yhteenkuuluvuutta. Yhteisöön liitytään tehtävän tutkimuksen tematiikan kautta - sen mukaan mistä parhaiten vertaistukea ja yhteistyökumppaneita löytyy. Tutkijat voivat kuulua moniin eri yhteisöihin samanaikaisesti. Tutkimusyhteisöt eivät näin noudata hallinnollisten yksiköiden rajoja. Tutkijan kuuluminen tiettyyn tutkimusyhteisöön on tyypillisesti pysyväisluonteisempaa kuin tiettyyn organisatoriseen yksikköön kuuluminen.', + '@type': '@id', + type: 'array', + items: { + type: 'object', + '@id': + 'urn:IAMNOTAPID:4b28461f-396d-485a-8cac-31ca6d091c00#root/Root/tutkija/Tutkija/member_of/Member_of/tutkijan_affiliaatio/Tutkijan_affiliaatio', + properties: { + nimi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/member_of/Member_of/tutkijan_affiliaatio/Tutkijan_affiliaatio/nimi', + title: 'Nimi', + description: 'Alayksikön nimi', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'array', + items: { + type: 'string', + }, + }, + alayksikkokoodi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/member_of/Member_of/tutkijan_affiliaatio/Tutkijan_affiliaatio/alayksikkokoodi', + title: 'Alayksikkökoodi', + description: + 'Alayksikön koodi OKM:lle raportoidussa alayksikkökoodistossa.', + enum: [], + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + }, }, - 'license_uri': { - 'title': 'License URL', - 'type': 'string', - 'format': 'uri' - } + }, + alkamisvuosi: { + '@id': + 'mscr:root/Root/tutkija/Tutkija/jasenyystutkimusyhteisossa/Jasenyystutkimusyhteisossa/alkamisvuosi', + title: 'Alkamisvuosi', + description: + 'Alkamishetki vuoden tarkkuudella määriteltynä. Periaatteessa ajanhetki pilkottuna kolmeen osaan mahdollistaen ilmaisun sillä tarkkuudella jolla tietoa on saatavilla (esim vuosi+kk). Tällä voidaan ennalta ehkäistä se, että joudutaan feikkaamaan tietoa, silloin kun sitä ei ole.', + '@type': 'http://www.w3.org/2001/XMLSchema#integer', + type: 'integer', + }, }, - 'additionalProperties': false, - 'required': ['license'] + }, + }, + etunimet: { + '@id': 'mscr:root/Root/tutkija/Tutkija/etunimet', + title: 'Etunimet', + description: 'henkilön kaikki etunimet lueteltuna', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + type: 'string', + }, + kokonimi: { + '@id': 'mscr:root/Root/tutkija/Tutkija/kokonimi', + title: 'Nimi', + description: 'henkilön täydellinen nimi', + '@type': 'http://www.w3.org/2001/XMLSchema#string', + minItems: 1, + type: 'array', + items: { + type: 'string', + }, }, - 'community': { - 'title': 'Community', - 'description': 'The community to which the record has been submitted.', - 'type': 'string' + }, + required: ['yksilointitunnus', 'kokonimi'], + }, + }, + }, + }, +}; + +export default function MockupSchemaLoader( + emptyTemplate: boolean +): Promise<RenderTree[] | undefined> { + const hugeTestData: any = { + $schema: 'http://json-schema.org/draft-04/schema#', + properties: { + null: { + title: null, + description: null, + }, + acoustic_area_backscattering_strength_in_sea_water: { + title: 'acoustic_area_backscattering_strength_in_sea_water', + description: + 'Acoustic area backscattering strength is 10 times the log10 of the ratio of the area backscattering coefficient to the reference value, 1 (m2 m-2). Area backscattering coefficient is the integral of the volume backscattering coefficient over a defined distance. Volume backscattering coefficient is the linear form of acoustic_volume_backscattering_strength_in_sea_water. For further details see MacLennan et. al (2002) doi:10.1006/jmsc.2001.1158.', + }, + acoustic_signal_roundtrip_travel_time_in_sea_water: { + title: 'acoustic_signal_roundtrip_travel_time_in_sea_water', + description: + 'The quantity with standard name acoustic_signal_roundtrip_travel_time_in_sea_water is the time taken for an acoustic signal to propagate from the emitting instrument to a reflecting surface and back again to the instrument. In the case of an instrument based on the sea floor and measuring the roundtrip time to the sea surface, the data are commonly used as a measure of ocean heat content.', + }, + acoustic_target_strength_in_sea_water: { + title: 'acoustic_target_strength_in_sea_water', + description: + 'Target strength is 10 times the log10 of the ratio of backscattering cross-section to the reference value, 1 m2. Backscattering cross-section is a parameter computed from the intensity of the backscattered sound wave relative to the intensity of the incident sound wave. For further details see MacLennan et. al (2002) doi:10.1006/jmsc.2001.1158.', + }, + acoustic_volume_backscattering_strength_in_sea_water: { + title: 'acoustic_volume_backscattering_strength_in_sea_water', + description: + 'Acoustic volume backscattering strength is 10 times the log10 of the ratio of the volume backscattering coefficient to the reference value, 1 m-1. Volume backscattering coefficient is the integral of the backscattering cross-section divided by the volume sampled. Backscattering cross-section is a parameter computed from the intensity of the backscattered sound wave relative to the intensity of the incident sound wave. The parameter is computed to provide a measurement that is proportional to biomass density per unit volume in the field of fisheries acoustics. For further details see MacLennan et. al (2002) doi:10.1006/jmsc.2001.1158.', + }, + }, + }; + + const testData: any = { + $schema: 'http://json-schema.org/draft-04/schema#', + type: 'object', + properties: { + $schema: { + type: 'string', + }, + string_type: { + type: 'string', + description: '01_string_description', + }, + number_type: { + type: 'number', + minimum: 3, + exclusiveMinimum: false, + }, + integer_type: { + type: 'integer', + minimum: 2, + }, + boolean_type: { + type: 'boolean', + }, + null_type: { + type: 'null', + }, + object_type: { + title: 'OBJECT TYPE', + type: 'object', + properties: { + string_property: { + title: 'string_prop', + type: 'string', + }, + }, + required: ['string_property'], + }, + array_string_type: { + type: 'array', + maxItems: 5, + items: { + type: 'string', + }, + }, + object_arrays_type: { + type: 'object', + properties: { + array_property: { + title: 'array_prop', + type: 'array', + items: { + type: 'number', + }, + }, + }, + }, + }, + additionalProperties: false, + b2share: { + presentation: { + major: [ + 'community', + 'titles', + 'descriptions', + 'creators', + 'open_access', + 'embargo_date', + 'license', + 'disciplines', + 'keywords', + 'contact_email', + ], + minor: [ + 'contributors', + 'resource_types', + 'alternate_identifiers', + 'version', + 'publisher', + 'language', + ], + }, + }, + }; + + const testSchema: any = { + $schema: 'http://json-schema.org/draft-04/schema#', + type: 'object', + properties: { + $schema: { + type: 'string', + }, + creators: { + title: 'Creators', + description: + 'The full name of the creators. The personal name format should be: family, given (e.g.: Smith, John).', + type: 'array', + items: { + type: 'object', + properties: { + creator_name: { + type: 'string', }, - 'community_specific': { - 'type': 'object' + }, + additionalProperties: false, + required: ['creator_name'], + }, + uniqueItems: true, + }, + titles: { + title: 'Titles', + description: + 'The title(s) of the uploaded resource, or a name by which the resource is known.', + type: 'array', + items: { + type: 'object', + properties: { + title: { + type: 'string', }, - 'publication_state': { - 'title': 'Publication State', - 'description': 'State of the publication workflow.', - 'type': 'string', - 'enum': ['draft', 'submitted', 'published'] + }, + additionalProperties: false, + required: ['title'], + }, + minItems: 1, + uniqueItems: true, + }, + publisher: { + title: 'Publisher', + description: + 'The entity responsible for making the resource available, either a person, an organization, or a service.', + type: 'string', + }, + publication_date: { + title: 'Publication Date', + description: + 'The date when the data was or will be made publicly available (e.g. 1971-07-13)', + type: 'string', + format: 'date', + }, + disciplines: { + title: 'Disciplines', + description: 'The scientific disciplines linked with the resource.', + type: 'array', + items: { + type: 'string', + }, + uniqueItems: true, + }, + keywords: { + title: 'Keywords', + description: + 'A list of keywords or key phrases describing the resource.', + type: 'array', + items: { + type: 'string', + }, + uniqueItems: true, + }, + contributors: { + title: 'Contributors', + description: + 'The list of all other contributors. Please mention all persons that were relevant in the creation of the resource.', + type: 'array', + items: { + type: 'object', + properties: { + contributor_name: { + title: 'Name', + type: 'string', + }, + contributor_type: { + title: 'Type', + enum: [ + 'ContactPerson', + 'DataCollector', + 'DataCurator', + 'DataManager', + 'Distributor', + 'Editor', + 'HostingInstitution', + 'Producer', + 'ProjectLeader', + 'ProjectManager', + 'ProjectMember', + 'RegistrationAgency', + 'RegistrationAuthority', + 'RelatedPerson', + 'Researcher', + 'ResearchGroup', + 'RightsHolder', + 'Sponsor', + 'Supervisor', + 'WorkPackageLeader', + 'Other', + ], }, - '_pid': { - 'title': 'Persistent Identifiers', - 'description': 'Array of persistent identifiers pointing to this record.' + }, + additionalProperties: false, + required: ['contributor_name', 'contributor_type'], + }, + uniqueItems: true, + }, + language: { + title: 'Language', + description: + 'The primary language of the resource. Please use ISO_639-3 language codes.', + type: 'string', + }, + resource_types: { + title: 'Resource Type', + description: 'The type(s) of the resource.', + type: 'array', + items: { + type: 'object', + properties: { + resource_type: { + title: 'Description', + type: 'string', + }, + resource_type_general: { + title: 'Category', + enum: [ + 'Audiovisual', + 'Collection', + 'Dataset', + 'Event', + 'Image', + 'InteractiveResource', + 'Model', + 'PhysicalObject', + 'Service', + 'Software', + 'Sound', + 'Text', + 'Workflow', + 'Other', + ], }, - '_deposit': { - 'type': 'object' + }, + additionalProperties: false, + required: ['resource_type_general'], + }, + minItems: 1, + uniqueItems: true, + }, + alternate_identifiers: { + title: 'Alternate identifiers', + description: + 'Any kind of other reference such as a URN, URI or an ISBN number.', + type: 'array', + items: { + type: 'object', + properties: { + alternate_identifier: { + type: 'string', + }, + alternate_identifier_type: { + title: 'Type', + type: 'string', }, - '_oai': { - 'type': 'object' + }, + additionalProperties: false, + required: ['alternate_identifier', 'alternate_identifier_type'], + }, + uniqueItems: true, + }, + descriptions: { + title: 'Descriptions', + description: + 'A more elaborate description of the resource. Focus on a content description that makes it easy for others to find, and to interpret its relevance.', + type: 'array', + items: { + type: 'object', + properties: { + description: { + type: 'string', + }, + description_type: { + title: 'Type', + enum: [ + 'Abstract', + 'Methods', + 'SeriesInformation', + 'TableOfContents', + 'TechnicalInfo', + 'Other', + ], }, - '_files': { - 'type': 'array' - } + }, + additionalProperties: false, + required: ['description', 'description_type'], }, - 'required': ['community', 'titles', 'open_access', 'publication_state', 'community_specific'], - 'additionalProperties': false, - 'b2share': { - 'presentation': { - 'major': ['community', 'titles', 'descriptions', 'creators', 'open_access', 'embargo_date', 'license', 'disciplines', 'keywords', 'contact_email'], - 'minor': ['contributors', 'resource_types', 'alternate_identifiers', 'version', 'publisher', 'language'] - } - } - }; - - let allTreeNodes: RenderTree[] = []; + uniqueItems: true, + }, + version: { + title: 'Version', + description: 'Denote the version of the resource.', + type: 'string', + }, + contact_email: { + title: 'Contact Email', + description: 'Contact email information for this record.', + type: 'string', + format: 'email', + }, + open_access: { + title: 'Open Access', + description: + "Indicate whether the record's files are publicly accessible or not. In case of restricted access the uploaded files will only be accessible by the record's owner and the community administrators. Please note that the record's metadata is always publicly accessible. ", + type: 'boolean', + }, + embargo_date: { + title: 'Embargo Date', + description: + 'The date marking the end of the embargo period. The record will be marked as open access on the specified date at midnight. Please note that the record metadata is always publicly accessible, and only the data files can have private access.', + type: 'string', + format: 'date-time', + }, + license: { + title: 'License', + description: + 'Specify the license under which this data set is available to the users (e.g. GPL, Apache v2 or Commercial). Please use the License Selector for help and additional information.', + type: 'object', + properties: { + license: { + type: 'string', + }, + license_uri: { + title: 'License URL', + type: 'string', + format: 'uri', + }, + }, + additionalProperties: false, + required: ['license'], + }, + community: { + title: 'Community', + description: 'The community to which the record has been submitted.', + type: 'string', + }, + community_specific: { + type: 'object', + }, + publication_state: { + title: 'Publication State', + description: 'State of the publication workflow.', + type: 'string', + enum: ['draft', 'submitted', 'published'], + }, + _pid: { + title: 'Persistent Identifiers', + description: 'Array of persistent identifiers pointing to this record.', + }, + _deposit: { + type: 'object', + }, + _oai: { + type: 'object', + }, + _files: { + type: 'array', + }, + }, + required: [ + 'community', + 'titles', + 'open_access', + 'publication_state', + 'community_specific', + ], + additionalProperties: false, + b2share: { + presentation: { + major: [ + 'community', + 'titles', + 'descriptions', + 'creators', + 'open_access', + 'embargo_date', + 'license', + 'disciplines', + 'keywords', + 'contact_email', + ], + minor: [ + 'contributors', + 'resource_types', + 'alternate_identifiers', + 'version', + 'publisher', + 'language', + ], + }, + }, + }; - let currentTreeNode: RenderTree = { - idNumeric: 0, - id: '0', - name: '', - isLinked: false, - title: '', - type: '', - description: '', - required: '', - isMappable: '', - parentName: '', - jsonPath: '$schema', - parentId: 0, - children: [] - }; + let allTreeNodes: RenderTree[] = []; - let nodeId = 0; + let currentTreeNode: RenderTree = { + idNumeric: 0, + id: '0', + name: '', + isLinked: false, + title: '', + type: '', + description: '', + required: '', + isMappable: '', + parentName: '', + jsonPath: '$schema', + parentId: 0, + children: [], + }; - function increaseNodeNumber() { - nodeId += 1; - } + let nodeId = 0; - function createTreeObject(object: string, value: string, parent: string, rootId: any, jsonPath: string) { - currentTreeNode.jsonPath = jsonPath + '.' + object; - currentTreeNode.idNumeric = nodeId; - currentTreeNode.id = nodeId.toString(); - currentTreeNode.parentId = rootId; - currentTreeNode.name = object; - currentTreeNode.title = value; - currentTreeNode.parentName = parent; - increaseNodeNumber(); - } + function increaseNodeNumber() { + nodeId += 1; + } - function walkJson(json_object: any, parent: any, rootId: number, jsonPath: string) { - for (const obj in json_object) { - if (typeof json_object[obj] === 'string') { - //console.log(`leaf ${obj} = ${json_object[obj]}`); + function createTreeObject( + object: string, + value: string, + parent: string, + rootId: any, + jsonPath: string + ) { + currentTreeNode.jsonPath = jsonPath + '.' + object; + currentTreeNode.idNumeric = nodeId; + currentTreeNode.id = nodeId.toString(); + currentTreeNode.parentId = rootId; + currentTreeNode.name = object; + currentTreeNode.title = value; + currentTreeNode.parentName = parent; + increaseNodeNumber(); + } - // OBJECT IS A LEAF LEVEL OBJECT - currentTreeNode = { - isLinked: false, idNumeric: 0, id: '0', name: '', title: '', type: 'string', description: '', required: '', parentId: 0, jsonPath, children: []}; - createTreeObject(obj, json_object[obj], parent, rootId, jsonPath); - allTreeNodes.push(cloneDeep(currentTreeNode)); - } - else if (typeof json_object[obj] === 'boolean') { - //console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! FOUND BOOLEAN', obj, json_object[obj], json_object); + function walkJson( + json_object: any, + parent: any, + rootId: number, + jsonPath: string + ) { + for (const obj in json_object) { + if (typeof json_object[obj] === 'string') { + //console.log(`leaf ${obj} = ${json_object[obj]}`); - // OBJECT IS A LEAF LEVEL OBJECT - currentTreeNode = { - isLinked: false, idNumeric: 0, id: '0', name: '', title: '', type: json_object[obj].toString(), description: '', required: '', parentId: 0, jsonPath, children: []}; - createTreeObject(obj, json_object[obj], parent, rootId, jsonPath); - allTreeNodes.push(cloneDeep(currentTreeNode)); - } - else { - // OBJECT HAS CHILDREN - currentTreeNode = { - isLinked: false, idNumeric: 0, id: '0', name: '', title: '', type: Array.isArray(json_object[obj]) ? 'array' : 'composite', description: '', required: '', parentId: 0, jsonPath, children: []}; - currentTreeNode.name = obj; - currentTreeNode.parentName = parent; - currentTreeNode.parentId = rootId; - currentTreeNode.idNumeric = nodeId; - currentTreeNode.id = nodeId.toString(); + // OBJECT IS A LEAF LEVEL OBJECT + currentTreeNode = { + isLinked: false, + idNumeric: 0, + id: '0', + name: '', + title: '', + type: 'string', + description: '', + required: '', + parentId: 0, + jsonPath, + children: [], + }; + createTreeObject(obj, json_object[obj], parent, rootId, jsonPath); + allTreeNodes.push(cloneDeep(currentTreeNode)); + } else if (typeof json_object[obj] === 'boolean') { + //console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! FOUND BOOLEAN', obj, json_object[obj], json_object); + // OBJECT IS A LEAF LEVEL OBJECT + currentTreeNode = { + isLinked: false, + idNumeric: 0, + id: '0', + name: '', + title: '', + type: json_object[obj].toString(), + description: '', + required: '', + parentId: 0, + jsonPath, + children: [], + }; + createTreeObject(obj, json_object[obj], parent, rootId, jsonPath); + allTreeNodes.push(cloneDeep(currentTreeNode)); + } else { + // OBJECT HAS CHILDREN + currentTreeNode = { + isLinked: false, + idNumeric: 0, + id: '0', + name: '', + title: '', + type: Array.isArray(json_object[obj]) ? 'array' : 'composite', + description: '', + required: '', + parentId: 0, + jsonPath, + children: [], + }; + currentTreeNode.name = obj; + currentTreeNode.parentName = parent; + currentTreeNode.parentId = rootId; + currentTreeNode.idNumeric = nodeId; + currentTreeNode.id = nodeId.toString(); - currentTreeNode.jsonPath = jsonPath + '.' + obj; - increaseNodeNumber(); - allTreeNodes.push(cloneDeep(currentTreeNode)); - walkJson(json_object[obj], obj, nodeId - 1, currentTreeNode.jsonPath); - } - } - return allTreeNodes; + currentTreeNode.jsonPath = jsonPath + '.' + obj; + increaseNodeNumber(); + allTreeNodes.push(cloneDeep(currentTreeNode)); + walkJson(json_object[obj], obj, nodeId - 1, currentTreeNode.jsonPath); + } } + return allTreeNodes; + } - - - function mergeAttributesToParent(inputNodes: RenderTree[] | undefined) { - if (inputNodes) { - let outputNodes = inputNodes.map((parent: RenderTree) => { - if (parent.children) { - let i = parent.children.length; - while (i--) { - // @ts-ignore - if (parent.children[i] && parent.children[i].children.length > 0) { - mergeAttributesToParent([parent.children[i]]); - } - if (parent.children[i].name === 'type') { - parent.type = parent.children[i].title; - //parent.children.splice(i, 1); - } else if (parent.children[i].name === 'description') { - parent.description = parent.children[i].title; - //parent.children.splice(i, 1); - } else if (parent.children[i].name === 'title') { - parent.title = parent.children[i].title; - //parent.children.splice(i, 1); - } - } - } - return parent; - } - ); - return outputNodes; + function mergeAttributesToParent(inputNodes: RenderTree[] | undefined) { + if (inputNodes) { + let outputNodes = inputNodes.map((parent: RenderTree) => { + if (parent.children) { + let i = parent.children.length; + while (i--) { + // @ts-ignore + if (parent.children[i] && parent.children[i].children.length > 0) { + mergeAttributesToParent([parent.children[i]]); + } + if (parent.children[i].name === 'type') { + parent.type = parent.children[i].title; + //parent.children.splice(i, 1); + } else if (parent.children[i].name === 'description') { + parent.description = parent.children[i].title; + //parent.children.splice(i, 1); + } else if (parent.children[i].name === 'title') { + parent.title = parent.children[i].title; + //parent.children.splice(i, 1); + } + } } + return parent; + }); + return outputNodes; } + } - function processChildNodes() { - for (let i = allTreeNodes.length - 1; i > 0; i -= 1) { - if (allTreeNodes[i]) { - allTreeNodes[allTreeNodes[i].parentId].children.push(cloneDeep(allTreeNodes[i])); - } - } - return {allTreeNodes}; + function processChildNodes() { + for (let i = allTreeNodes.length - 1; i > 0; i -= 1) { + if (allTreeNodes[i]) { + allTreeNodes[allTreeNodes[i].parentId].children.push( + cloneDeep(allTreeNodes[i]) + ); + } } + return { allTreeNodes }; + } - // Recursive tree creation causes tree to build in reversed order, so tree needs to be reversed to match the node order in original JSON - function reverseTreeRootLevel(inputNodes: RenderTree[] | undefined) { - let retNodes: RenderTree[]; - if (inputNodes){ - return inputNodes.reverse(); - } + // Recursive tree creation causes tree to build in reversed order, so tree needs to be reversed to match the node order in original JSON + function reverseTreeRootLevel(inputNodes: RenderTree[] | undefined) { + let retNodes: RenderTree[]; + if (inputNodes) { + return inputNodes.reverse(); } + } - // Unused - function reverseTreeChildren(inputNodes: RenderTree[] | undefined) { - if (inputNodes){ - for (let i = 0; i < inputNodes.length; i += 1) { - // @ts-ignore - if (inputNodes[i].children.length > 1) { - // @ts-ignore - inputNodes[i].children = inputNodes[i].children.reverse() - reverseTreeChildren(inputNodes[i].children); - } - } - return inputNodes; + // Unused + function reverseTreeChildren(inputNodes: RenderTree[] | undefined) { + if (inputNodes) { + for (let i = 0; i < inputNodes.length; i += 1) { + // @ts-ignore + if (inputNodes[i].children.length > 1) { + // @ts-ignore + inputNodes[i].children = inputNodes[i].children.reverse(); + reverseTreeChildren(inputNodes[i].children); } + } + return inputNodes; } + } - walkJson(emptyTemplate ? importedSchemaExample : currentTreeNode, null, 0, 'ROOT'); - processChildNodes(); - console.log('######### NEW', mergeAttributesToParent(reverseTreeRootLevel(allTreeNodes))); + walkJson( + emptyTemplate ? importedSchemaExample : currentTreeNode, + null, + 0, + 'ROOT' + ); + processChildNodes(); + console.log( + '######### NEW', + mergeAttributesToParent(reverseTreeRootLevel(allTreeNodes)) + ); - return new Promise((resolve) => { - resolve(reverseTreeRootLevel(allTreeNodes)); - }); + return new Promise((resolve) => { + resolve(reverseTreeRootLevel(allTreeNodes)); + }); } export function getImportedSchemaMock(): Promise<any> { - return new Promise((resolve) => { - resolve(importedSchemaExample2); - }); + return new Promise((resolve) => { + resolve(importedSchemaExample2); + }); } export function getFilterFunctions(): Promise<any> { - return new Promise((resolve) => { - resolve(functionsMockup); - }); + return new Promise((resolve) => { + resolve(functionsMockup); + }); } - - - - - - - - - - - - - diff --git a/mscr-ui/src/modules/crosswalk-editor/tabs/crosswalk-info/node-info/index.tsx b/mscr-ui/src/modules/crosswalk-editor/tabs/crosswalk-info/node-info/index.tsx index 5a9a652e6..0d8a20334 100644 --- a/mscr-ui/src/modules/crosswalk-editor/tabs/crosswalk-info/node-info/index.tsx +++ b/mscr-ui/src/modules/crosswalk-editor/tabs/crosswalk-info/node-info/index.tsx @@ -1,272 +1,344 @@ import Button from '@mui/material/Button'; import { - CrosswalkConnection, - CrosswalkConnectionsNew, - RenderTree + CrosswalkConnection, + CrosswalkConnectionsNew, + RenderTree, } from '@app/common/interfaces/crosswalk-connection.interface'; import EastIcon from '@mui/icons-material/East'; -import {Dropdown} from 'suomifi-ui-components'; -import {DropdownItem} from 'suomifi-ui-components'; -import {useState, useEffect} from 'react'; +import { Dropdown } from 'suomifi-ui-components'; +import { DropdownItem } from 'suomifi-ui-components'; +import { useState, useEffect } from 'react'; import Input from '@mui/material/Input'; import Box from '@mui/material/Box'; -import {InfoIcon} from '@app/common/components/shared-icons'; +import { InfoIcon } from '@app/common/components/shared-icons'; -export default function NodeInfo(props: { isAnySelectedLinked: boolean; isBothSelectedLinked: boolean; sourceData: RenderTree[]; targetData: RenderTree[]; isSourceTree: boolean; performNodeInfoAction: any }) { - let sourceSelectionInit = ''; - let targetSelectionInit = ''; +export default function NodeInfo(props: { + isAnySelectedLinked: boolean; + isBothSelectedLinked: boolean; + sourceData: RenderTree[]; + targetData: RenderTree[]; + isSourceTree: boolean; + performNodeInfoAction: any; +}) { + let sourceSelectionInit = ''; + let targetSelectionInit = ''; - useEffect(() => { - if (props.sourceData && props.sourceData.length > 0) { - sourceSelectionInit = props.sourceData[0].id; - setSourceDropdownValue(props.sourceData[0].id); - console.log('props.sourceData'); - } - if (props.targetData && props.targetData.length > 0) { - targetSelectionInit = props.targetData[0].id; - setTargetDropdownValue(props.targetData[0].id); - } - }, [props]); - - const [sourceDropdownValue, setSourceDropdownValue] = useState(sourceSelectionInit); - const [targetDropdownValue, setTargetDropdownValue] = useState(targetSelectionInit); - const [selectedSource] = props.sourceData.filter(item => item.id === sourceDropdownValue); - const [selectedTarget] = props.targetData.filter(item => item.id === targetDropdownValue); - - let sourceDropdownInit: any = [ - { - id: '1' - }, - ]; + useEffect(() => { if (props.sourceData && props.sourceData.length > 0) { - sourceDropdownInit = props.sourceData; + sourceSelectionInit = props.sourceData[0].id; + setSourceDropdownValue(props.sourceData[0].id); + console.log('props.sourceData'); } - let targetDropdownInit: any = [ - { - id: '1' - }, - ]; if (props.targetData && props.targetData.length > 0) { - targetDropdownInit = props.targetData; + targetSelectionInit = props.targetData[0].id; + setTargetDropdownValue(props.targetData[0].id); } + }, [props]); - const schemaAttributes = ['description']; + const [sourceDropdownValue, setSourceDropdownValue] = + useState(sourceSelectionInit); + const [targetDropdownValue, setTargetDropdownValue] = + useState(targetSelectionInit); + const [selectedSource] = props.sourceData.filter( + (item) => item.id === sourceDropdownValue + ); + const [selectedTarget] = props.targetData.filter( + (item) => item.id === targetDropdownValue + ); - interface constantAttribute { - name: string; - title: string | undefined; - } + let sourceDropdownInit: any = [ + { + id: '1', + }, + ]; + if (props.sourceData && props.sourceData.length > 0) { + sourceDropdownInit = props.sourceData; + } + let targetDropdownInit: any = [ + { + id: '1', + }, + ]; + if (props.targetData && props.targetData.length > 0) { + targetDropdownInit = props.targetData; + } - const foundSourceKeywords: constantAttribute[] = []; - if (props.sourceData.length > 0) { - // @ts-ignore - props.sourceData[0]?.children.forEach(item => { - schemaAttributes.forEach(scAtt => { - if (Object.prototype.hasOwnProperty.call(item, scAtt)) { - const attrib: constantAttribute = { - name: item.name, title: item['title'] === '' ? 'complex' : item['title'], - }; - foundSourceKeywords.push(attrib); - } - }); - }); - } + const schemaAttributes = ['description']; - const foundTargetKeywords: constantAttribute[] = []; - if (props.sourceData.length > 0) { - // @ts-ignore - props.targetData[0]?.children.forEach(item => { - schemaAttributes.forEach(scAtt => { - if (Object.prototype.hasOwnProperty.call(item, scAtt)) { - const attrib: constantAttribute = { - name: item.name, title: item['title'] === '' ? 'complex' : item['title'], - }; - foundTargetKeywords.push(attrib); - } - }); - }); - } + interface constantAttribute { + name: string; + title: string | undefined; + } - function processHtmlLinks(input: string | undefined) { - if (input && input.startsWith('http://' || 'https://')) { - return (<a href={input} target="_blank" rel="noreferrer">{input}</a>); + const foundSourceKeywords: constantAttribute[] = []; + if (props.sourceData.length > 0) { + // @ts-ignore + props.sourceData[0]?.children.forEach((item) => { + schemaAttributes.forEach((scAtt) => { + if (Object.prototype.hasOwnProperty.call(item, scAtt)) { + const attrib: constantAttribute = { + name: item.name, + title: item['title'] === '' ? 'complex' : item['title'], + }; + foundSourceKeywords.push(attrib); } - return input; - } + }); + }); + } + const foundTargetKeywords: constantAttribute[] = []; + if (props.sourceData.length > 0) { + // @ts-ignore + props.targetData[0]?.children.forEach((item) => { + schemaAttributes.forEach((scAtt) => { + if (Object.prototype.hasOwnProperty.call(item, scAtt)) { + const attrib: constantAttribute = { + name: item.name, + title: item['title'] === '' ? 'complex' : item['title'], + }; + foundTargetKeywords.push(attrib); + } + }); + }); + } - return (<> - <div className='row d-flex justify-content-between node-info-box'> - <h2>Selected node info</h2> + function processHtmlLinks(input: string | undefined) { + if (input && input.startsWith('http://' || 'https://')) { + return ( + <a href={input} target="_blank" rel="noreferrer"> + {input} + </a> + ); + } + return input; + } - {/* SOURCE NODE */} + return ( + <> + <div className="row d-flex justify-content-between node-info-box"> + <h2>Selected node info</h2> - {props.isSourceTree && ( - <div className='col flex-column d-flex justify-content-between side-bar-wrap'> - <div className='mb-2'> + {/* SOURCE NODE */} + {props.isSourceTree && ( + <div className="col flex-column d-flex justify-content-between side-bar-wrap"> + <div className="mb-2"></div> + <Box + className="bg-wrap" + sx={{ + height: 440, + flexGrow: 1, + maxWidth: 400, + overflowY: 'auto', + }} + > + {props.sourceData.length < 1 && ( + <> + <div className="row gx-1"> + <div className="col-2 d-flex"> + <div className="pt-1 ms-1"> + <InfoIcon></InfoIcon> + </div> </div> - <Box className='bg-wrap' sx={{height: 440, flexGrow: 1, maxWidth: 400, overflowY: 'auto'}}> - {props.sourceData.length < 1 && <> - <div className='row gx-1'> - <div className='col-2 d-flex'> - <div className='pt-1 ms-1'><InfoIcon></InfoIcon></div> - </div> - <div className='col-10'> - <div>Nothing to show just now. Select an entity to view information.</div> - </div> - </div> - </>} - {props.sourceData.length > 1 && - <div className='dropdown-wrap'> - <Dropdown className='mt-2 node-info-dropdown' - visualPlaceholder="Source node(s) not selected" - value={sourceDropdownValue} - onChange={(newValue) => setSourceDropdownValue(newValue)} - > - {sourceDropdownInit.map((rt) => ( - <DropdownItem key={rt.id} value={rt.id}> - {rt.name} - </DropdownItem> - ))} - </Dropdown> - </div> - } - <div> - <div className='row'> - {props.sourceData.length > 1 && - <> - <div className='col-12'> - <div>Selected node:</div> - <div className='attribute-font'>{selectedSource?.name}</div> - </div> - - <div className='col-12'> - <div>jsonPath:</div> - <div className='attribute-font'>{selectedSource?.jsonPath}</div> - </div> - </> - } - - {foundSourceKeywords.length < 1 && - // Node is a leaf level node so show inferred properties - <> - {selectedSource?.title && - <div className='col-12'> - <div>title:</div> - <div className='attribute-font'>{processHtmlLinks(selectedSource?.title)}</div> - </div> - } - {selectedSource?.type && - <div className='col-12'> - <div>type:</div> - <div className='attribute-font'>{processHtmlLinks(selectedSource?.type)}</div> - </div> - } - {selectedSource?.description && - <div className='col-12'> - <div>description:</div> - <div className='attribute-font'>{processHtmlLinks(selectedSource?.description)}</div> - </div> - } - </> - } + <div className="col-10"> + <div> + Nothing to show just now. Select an entity to view + information. + </div> + </div> + </div> + </> + )} + {props.sourceData.length > 1 && ( + <div className="dropdown-wrap"> + <Dropdown + className="mt-2 node-info-dropdown" + visualPlaceholder="Source node(s) not selected" + value={sourceDropdownValue} + onChange={(newValue) => setSourceDropdownValue(newValue)} + > + {sourceDropdownInit.map((rt) => ( + <DropdownItem key={rt.id} value={rt.id}> + {rt.name} + </DropdownItem> + ))} + </Dropdown> + </div> + )} + <div> + <div className="row"> + {props.sourceData.length > 1 && ( + <> + <div className="col-12"> + <div>Selected node:</div> + <div className="attribute-font"> + {selectedSource?.name} + </div> + </div> - {foundSourceKeywords.map(attrib => ( - <div className='col-12'> - <div className=''>{processHtmlLinks(attrib.name)}:</div> - <div className='attribute-font'>{processHtmlLinks(attrib.title)}</div> - </div> - ))} - </div> + <div className="col-12"> + <div>jsonPath:</div> + <div className="attribute-font"> + {selectedSource?.jsonPath} </div> - </Box> - </div> - )} + </div> + </> + )} - {/* TARGET NODE */} - {!props.isSourceTree && ( - <div className='col flex-column d-flex justify-content-between side-bar-wrap'> - <div className='mb-2'> + {foundSourceKeywords.length < 1 && ( + // Node is a leaf level node so show inferred properties + <> + {selectedSource?.title && ( + <div className="col-12"> + <div>title:</div> + <div className="attribute-font"> + {processHtmlLinks(selectedSource?.title)} + </div> + </div> + )} + {selectedSource?.type && ( + <div className="col-12"> + <div>type:</div> + <div className="attribute-font"> + {processHtmlLinks(selectedSource?.type)} + </div> + </div> + )} + {selectedSource?.description && ( + <div className="col-12"> + <div>description:</div> + <div className="attribute-font"> + {processHtmlLinks(selectedSource?.description)} + </div> + </div> + )} + </> + )} + {foundSourceKeywords.map((attrib) => ( + <div className="col-12"> + <div className="">{processHtmlLinks(attrib.name)}:</div> + <div className="attribute-font"> + {processHtmlLinks(attrib.title)} + </div> </div> - <Box className='bg-wrap' sx={{height: 440, flexGrow: 1, maxWidth: 400, overflowY: 'auto'}}> - {props.targetData.length < 1 && <> - <div className='row gx-1'> - <div className='col-2 d-flex'> - <div className='pt-1 ms-1'><InfoIcon></InfoIcon></div> - </div> - <div className='col-10'> - <div>Nothing to show just now. Select an entity to view information.</div> - </div> - </div> - </>} - {props.targetData.length > 1 && - <div className='dropdown-wrap'> - <Dropdown className='mt-2 node-info-dropdown' - visualPlaceholder="Source node(s) not selected" - value={sourceDropdownValue} - onChange={(newValue) => setSourceDropdownValue(newValue)} - > - {targetDropdownInit.map((rt) => ( - <DropdownItem key={rt.id} value={rt.id}> - {rt.name} - </DropdownItem> - ))} - </Dropdown> - </div> - } - <div> - <div className='row'> - {props.targetData.length > 1 && - <> - <div className='col-12'> - <div>Selected node:</div> - <div className='attribute-font'>{selectedTarget?.name}</div> - </div> + ))} + </div> + </div> + </Box> + </div> + )} - <div className='col-12'> - <div>jsonPath:</div> - <div className='attribute-font'>{selectedTarget?.jsonPath}</div> - </div> - </> - } + {/* TARGET NODE */} + {!props.isSourceTree && ( + <div className="col flex-column d-flex justify-content-between side-bar-wrap"> + <div className="mb-2"></div> + <Box + className="bg-wrap" + sx={{ + height: 440, + flexGrow: 1, + maxWidth: 400, + overflowY: 'auto', + }} + > + {props.targetData.length < 1 && ( + <> + <div className="row gx-1"> + <div className="col-2 d-flex"> + <div className="pt-1 ms-1"> + <InfoIcon></InfoIcon> + </div> + </div> + <div className="col-10"> + <div> + Nothing to show just now. Select an entity to view + information. + </div> + </div> + </div> + </> + )} + {props.targetData.length > 1 && ( + <div className="dropdown-wrap"> + <Dropdown + className="mt-2 node-info-dropdown" + visualPlaceholder="Source node(s) not selected" + value={sourceDropdownValue} + onChange={(newValue) => setSourceDropdownValue(newValue)} + > + {targetDropdownInit.map((rt) => ( + <DropdownItem key={rt.id} value={rt.id}> + {rt.name} + </DropdownItem> + ))} + </Dropdown> + </div> + )} + <div> + <div className="row"> + {props.targetData.length > 1 && ( + <> + <div className="col-12"> + <div>Selected node:</div> + <div className="attribute-font"> + {selectedTarget?.name} + </div> + </div> - {foundTargetKeywords.length < 1 && - // Node is a leaf level node so show inferred properties - <> - {selectedTarget?.title && - <div className='col-12'> - <div>title:</div> - <div className='attribute-font'>{processHtmlLinks(selectedTarget?.title)}</div> - </div> - } - {selectedTarget?.type && - <div className='col-12'> - <div>type:</div> - <div className='attribute-font'>{processHtmlLinks(selectedTarget?.type)}</div> - </div> - } - {selectedTarget?.description && - <div className='col-12'> - <div>description:</div> - <div className='attribute-font'>{processHtmlLinks(selectedTarget?.description)}</div> - </div> - } - </> - } + <div className="col-12"> + <div>jsonPath:</div> + <div className="attribute-font"> + {selectedTarget?.jsonPath} + </div> + </div> + </> + )} - {foundTargetKeywords.map(attrib => ( - <div className='col-12'> - <div className=''>{processHtmlLinks(attrib.name)}:</div> - <div className='attribute-font'>{processHtmlLinks(attrib.title)}</div> - </div> - ))} - </div> + {foundTargetKeywords.length < 1 && ( + // Node is a leaf level node so show inferred properties + <> + {selectedTarget?.title && ( + <div className="col-12"> + <div>title:</div> + <div className="attribute-font"> + {processHtmlLinks(selectedTarget?.title)} + </div> + </div> + )} + {selectedTarget?.type && ( + <div className="col-12"> + <div>type:</div> + <div className="attribute-font"> + {processHtmlLinks(selectedTarget?.type)} + </div> </div> - </Box> + )} + {selectedTarget?.description && ( + <div className="col-12"> + <div>description:</div> + <div className="attribute-font"> + {processHtmlLinks(selectedTarget?.description)} + </div> + </div> + )} + </> + )} + + {foundTargetKeywords.map((attrib) => ( + <div className="col-12"> + <div className="">{processHtmlLinks(attrib.name)}:</div> + <div className="attribute-font"> + {processHtmlLinks(attrib.title)} + </div> + </div> + ))} </div> - )} - </div> - </>); -} \ No newline at end of file + </div> + </Box> + </div> + )} + </div> + </> + ); +} diff --git a/mscr-ui/src/modules/crosswalk-editor/tabs/edit-crosswalk/schema-tree/index.tsx b/mscr-ui/src/modules/crosswalk-editor/tabs/edit-crosswalk/schema-tree/index.tsx index cd466376c..976bdf885 100644 --- a/mscr-ui/src/modules/crosswalk-editor/tabs/edit-crosswalk/schema-tree/index.tsx +++ b/mscr-ui/src/modules/crosswalk-editor/tabs/edit-crosswalk/schema-tree/index.tsx @@ -6,63 +6,63 @@ import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import ChevronRightIcon from '@mui/icons-material/ChevronRight'; function toTree(nodes: any) { - const ret = ( - <TreeItem - key={nodes.id} - nodeId={nodes.id} - label={nodes.name} - className="linked-tree-item" - > - {Array.isArray(nodes.children) - ? nodes.children.map((node: any) => toTree(node)) - : null} - </TreeItem> - ); - return ret; + const ret = ( + <TreeItem + key={nodes.id} + nodeId={nodes.id} + label={nodes.name} + className="linked-tree-item" + > + {Array.isArray(nodes.children) + ? nodes.children.map((node: any) => toTree(node)) + : null} + </TreeItem> + ); + return ret; } export default function SchemaTree({ - nodes, - treeSelectedArray, - treeExpanded, - isSourceTree, - performTreeAction, - }: { - nodes: any; - treeSelectedArray: string[]; - treeExpanded: string[]; - isSourceTree: boolean; - performTreeAction: any; + nodes, + treeSelectedArray, + treeExpanded, + isSourceTree, + performTreeAction, +}: { + nodes: any; + treeSelectedArray: string[]; + treeExpanded: string[]; + isSourceTree: boolean; + performTreeAction: any; }) { - const handleSelect = (event: React.SyntheticEvent, nodeIds: string[]) => { - performTreeAction(isSourceTree, 'handleSelect', event, nodeIds); - }; + const handleSelect = (event: React.SyntheticEvent, nodeIds: string[]) => { + performTreeAction(isSourceTree, 'handleSelect', event, nodeIds); + }; - const handleToggle = (event: React.SyntheticEvent, nodeIds: string[]) => { - performTreeAction(isSourceTree, 'treeToggle', event, nodeIds); - }; + const handleToggle = (event: React.SyntheticEvent, nodeIds: string[]) => { + performTreeAction(isSourceTree, 'treeToggle', event, nodeIds); + }; - return ( - <TreeView - aria-label="controlled" - expanded={treeExpanded} - selected={treeSelectedArray} - onNodeSelect={handleSelect} - onNodeToggle={handleToggle} - defaultCollapseIcon={<ExpandMoreIcon />} - defaultExpandIcon={<ChevronRightIcon />} - multiSelect - > - <TreeItem - key={nodes.id} - nodeId={nodes.id} - label={nodes.name} - className="linked-tree-item" - > - {Array.isArray(nodes.children) - ? nodes.children.map((node: any) => toTree(node)) - : null} - </TreeItem> - </TreeView> - ); + return ( + <TreeView + aria-label="controlled" + expanded={treeExpanded} + selected={treeSelectedArray} + onNodeSelect={handleSelect} + onNodeToggle={handleToggle} + defaultCollapseIcon={<ExpandMoreIcon />} + defaultExpandIcon={<ChevronRightIcon />} + multiSelect + > + <TreeItem + key={nodes.id} + nodeId={nodes.id} + label={nodes.name} + className="linked-tree-item" + > + {Array.isArray(nodes.children) + ? nodes.children.map((node: any) => toTree(node)) + : null} + </TreeItem> + </TreeView> + ); } diff --git a/mscr-ui/src/modules/crosswalk-editor/tabs/metadata-and-files/index.tsx b/mscr-ui/src/modules/crosswalk-editor/tabs/metadata-and-files/index.tsx index 1eae9501d..9d95cb297 100644 --- a/mscr-ui/src/modules/crosswalk-editor/tabs/metadata-and-files/index.tsx +++ b/mscr-ui/src/modules/crosswalk-editor/tabs/metadata-and-files/index.tsx @@ -1,13 +1,14 @@ import Button from '@mui/material/Button'; import { - CrosswalkConnection, CrosswalkConnectionNew, - CrosswalkConnectionsNew, - RenderTree + CrosswalkConnection, + CrosswalkConnectionNew, + CrosswalkConnectionsNew, + RenderTree, } from '@app/common/interfaces/crosswalk-connection.interface'; import EastIcon from '@mui/icons-material/East'; -import {Dropdown} from 'suomifi-ui-components'; -import {DropdownItem} from 'suomifi-ui-components'; -import {useState, useEffect} from 'react'; +import { Dropdown } from 'suomifi-ui-components'; +import { DropdownItem } from 'suomifi-ui-components'; +import { useState, useEffect } from 'react'; import Input from '@mui/material/Input'; import { TextInput } from 'suomifi-ui-components'; import Table from '@mui/material/Table'; @@ -15,55 +16,58 @@ import TableBody from '@mui/material/TableBody'; import TableContainer from '@mui/material/TableContainer'; import TableHead from '@mui/material/TableHead'; import TableRow from '@mui/material/TableRow'; -import {useBreakpoints} from '../../../../../../common-ui/components/media-query'; +import { useBreakpoints } from '../../../../../../common-ui/components/media-query'; import { TableCell } from '@mui/material'; import JointListingAccordion from '@app/modules/crosswalk-editor/joint-listing-accordion'; interface CrosswalkDetails { - crosswalkName: string; - uri: string; - pid: string; - version: string; - releaseDate: string; - publisher: string; - creator: string; - contributors: string[]; - notes: string; - description: string; - keywords: string[]; - [key: string]: string | string[]; + crosswalkName: string; + uri: string; + pid: string; + version: string; + releaseDate: string; + publisher: string; + creator: string; + contributors: string[]; + notes: string; + description: string; + keywords: string[]; + [key: string]: string | string[]; } -export default function MetadataAndFiles(props: { crosswalks: CrosswalkConnectionNew[]; performMetadataAndFilesAction: any }) { - const detailsInit: CrosswalkDetails = { - contributors: [], - creator: '', - crosswalkName: '', - description: '', - keywords: [], - notes: '', - pid: '', - publisher: '', - releaseDate: '', - uri: '', - version: '' - }; +export default function MetadataAndFiles(props: { + crosswalks: CrosswalkConnectionNew[]; + performMetadataAndFilesAction: any; +}) { + const detailsInit: CrosswalkDetails = { + contributors: [], + creator: '', + crosswalkName: '', + description: '', + keywords: [], + notes: '', + pid: '', + publisher: '', + releaseDate: '', + uri: '', + version: '', + }; - const [inputValue, setInputValue] = useState(detailsInit); + const [inputValue, setInputValue] = useState(detailsInit); - useEffect(() => { - console.log('INPUT', inputValue); - console.log('CROSSWALKS', props.crosswalks); - }, [inputValue, props.crosswalks]); + useEffect(() => { + console.log('INPUT', inputValue); + console.log('CROSSWALKS', props.crosswalks); + }, [inputValue, props.crosswalks]); - const updateValue = (paramName: string, value: any) => { - const val = value === undefined ? '' : value.toString(); - const details = {...inputValue}; - details[paramName] = val; - setInputValue(details); - }; + const updateValue = (paramName: string, value: any) => { + const val = value === undefined ? '' : value.toString(); + const details = { ...inputValue }; + details[paramName] = val; + setInputValue(details); + }; -/* const StyledTableCell = styled(TableCell)(({theme}) => ({ + /* const StyledTableCell = styled(TableCell)(({theme}) => ({ [`&.${tableCellClasses.head}`]: { backgroundColor: theme.palette.common.white, }, @@ -82,70 +86,88 @@ export default function MetadataAndFiles(props: { crosswalks: CrosswalkConnectio }, }));*/ - return (<> - <div className='crosswalk-editor mx-2'> - <h2 className='mt-4 mb-3'>Crosswalk details</h2> - <div className='row d-flex justify-content-between metadata-and-files-wrap mx-2'> - <div className='row bg-light-blue'> - <div className='col-6'> - <div className='mt-3'> + return ( + <> + <div className="crosswalk-editor mx-2"> + <h2 className="mt-4 mb-3">Crosswalk details</h2> + <div className="row d-flex justify-content-between metadata-and-files-wrap mx-2"> + <div className="row bg-light-blue"> + <div className="col-6"> + <div className="mt-3"> <TextInput - onChange={(value) => updateValue('crosswalkName', value)} - labelText="Crosswalk name" - value={inputValue.crosswalkName.toString()} + onChange={(value) => updateValue('crosswalkName', value)} + labelText="Crosswalk name" + value={inputValue.crosswalkName.toString()} /> - </div> - <div className='mt-2'> + </div> + <div className="mt-2"> <TextInput - onChange={(value) => updateValue('uri', value)} - labelText="Uri" - value={inputValue.uri.toString()} + onChange={(value) => updateValue('uri', value)} + labelText="Uri" + value={inputValue.uri.toString()} /> - </div> - <div className='my-3'>PID:<span>{inputValue.pid}</span></div> - <div className='my-3'>Version:<span>{inputValue.version}</span></div> - <div className='my-3'> Release date:<span>{inputValue.releaseDate}</span></div> - <div className='my-3'>Publisher:<span>{inputValue.publisher}</span></div> - <div className='my-3'>Creator:<span>{inputValue.creator}</span></div> - <div className='my-3'>Contributors:<span>{inputValue.contributors}</span></div> + </div> + <div className="my-3"> + PID:<span>{inputValue.pid}</span> + </div> + <div className="my-3"> + Version:<span>{inputValue.version}</span> + </div> + <div className="my-3"> + {' '} + Release date:<span>{inputValue.releaseDate}</span> + </div> + <div className="my-3"> + Publisher:<span>{inputValue.publisher}</span> + </div> + <div className="my-3"> + Creator:<span>{inputValue.creator}</span> + </div> + <div className="my-3"> + Contributors:<span>{inputValue.contributors}</span> + </div> </div> - <div className='col-6'> - <div className='mt-3'> + <div className="col-6"> + <div className="mt-3"> <TextInput - onChange={(value) => updateValue('notes', value)} - labelText="Notes" - value={inputValue.notes.toString()} + onChange={(value) => updateValue('notes', value)} + labelText="Notes" + value={inputValue.notes.toString()} /> - </div> - <div className='mt-2'> + </div> + <div className="mt-2"> <TextInput - onChange={(value) => updateValue('description', value)} - labelText="Description" - value={inputValue.description.toString()} + onChange={(value) => updateValue('description', value)} + labelText="Description" + value={inputValue.description.toString()} /> - </div> - <div className='mt-2'> + </div> + <div className="mt-2"> <TextInput - onChange={(value) => updateValue('keywords', value)} - labelText="Keywords" - value={inputValue.keywords.toString()} + onChange={(value) => updateValue('keywords', value)} + labelText="Keywords" + value={inputValue.keywords.toString()} /> + </div> </div> - </div> + </div> </div> - </div> - <h2 className='mt-4 mb-3'>Files</h2> - <div className='row d-flex justify-content-between metadata-and-files-wrap mx-2'> - <br/> + <h2 className="mt-4 mb-3">Files</h2> + <div className="row d-flex justify-content-between metadata-and-files-wrap mx-2"> + <br /> - <div>TABLE HERE</div> + <div>TABLE HERE</div> </div> - <h2 className='mt-4 mb-3'>Crosswalk summary</h2> - <div className='row d-flex justify-content-between metadata-and-files-wrap mx-2'> - <JointListingAccordion crosswalkJoints={props.crosswalks} viewOnlyMode={true} - performAccordionAction={null}></JointListingAccordion> + <h2 className="mt-4 mb-3">Crosswalk summary</h2> + <div className="row d-flex justify-content-between metadata-and-files-wrap mx-2"> + <JointListingAccordion + crosswalkJoints={props.crosswalks} + viewOnlyMode={true} + performAccordionAction={null} + ></JointListingAccordion> </div> - </div> - </>); -} \ No newline at end of file + </div> + </> + ); +} diff --git a/mscr-ui/src/modules/crosswalk-editor/tabs/node-mappings/index.tsx b/mscr-ui/src/modules/crosswalk-editor/tabs/node-mappings/index.tsx index d5a50dd7b..b2cec4e44 100644 --- a/mscr-ui/src/modules/crosswalk-editor/tabs/node-mappings/index.tsx +++ b/mscr-ui/src/modules/crosswalk-editor/tabs/node-mappings/index.tsx @@ -1,295 +1,321 @@ import { - CrosswalkConnection, CrosswalkConnectionNew, - CrosswalkConnectionsNew, - RenderTree + CrosswalkConnection, + CrosswalkConnectionNew, + CrosswalkConnectionsNew, + RenderTree, } from '@app/common/interfaces/crosswalk-connection.interface'; import validateMapping from '@app/modules/crosswalk-editor/mapping-validator'; import EastIcon from '@mui/icons-material/East'; -import {Dropdown, Textarea, TextInput} from 'suomifi-ui-components'; -import {DropdownItem} from 'suomifi-ui-components'; -import {useCallback, useEffect, useState} from 'react'; +import { Dropdown, Textarea, TextInput } from 'suomifi-ui-components'; +import { DropdownItem } from 'suomifi-ui-components'; +import { useCallback, useEffect, useState } from 'react'; import { - Button, - InlineAlert, - Modal, - ModalContent, - ModalFooter, - ModalTitle, - Paragraph, + Button, + InlineAlert, + Modal, + ModalContent, + ModalFooter, + ModalTitle, + Paragraph, } from 'suomifi-ui-components'; import CrosswalkForm from '@app/modules/crosswalk-form'; import FormFooterAlert from '../../../../../../common-ui/components/form-footer-alert'; -export default function NodeMappings(props: { selectedCrosswalk: CrosswalkConnectionNew; performNodeInfoAction: any; filterFunctions: any; modalOpen: boolean; isFirstAdd: boolean }) { - let sourceSelectionInit = ''; - let targetSelectionInit = ''; - console.log('SOURCE DATA', props?.selectedCrosswalk?.source); - console.log('TARGET DATA', props?.selectedCrosswalk?.target); - console.log('SELECTED', props?.selectedCrosswalk); - - const operationValues = [ - { - name: 'Operation 1', - id: 1, - }, - { - name: 'Operation 2', - id: 2, - } - ]; - - const filterValues = [ - { - name: 'Filter 1', - id: 1, - }, - { - name: 'Filter 2', - id: 2, - } - ]; - - const filterOperations = [ - { - name: 'Filter operation 1', - id: 1, - }, - { - name: 'Filter operation 2', - id: 2, - } - ]; - const operationSelectInit = 'Operation 1'; - - const filterTargetSelectInit = ''; - const filterOperationsSelectInit = 'Filter operation 1'; - - useEffect(() => { - if (props?.selectedCrosswalk?.source) { - sourceSelectionInit = props.selectedCrosswalk.source.id; - setSourceInputValue(props.selectedCrosswalk.source.id); - } - if (props?.selectedCrosswalk?.target) { - targetSelectionInit = props.selectedCrosswalk.target.id; - setTargetInputValue(props.selectedCrosswalk.target.id); - } - - setVisible(props?.modalOpen); - }, [props]); - - const [sourceInputValue, setSourceInputValue] = useState(sourceSelectionInit); - const [operation1Value, setOperation1Value] = useState(operationSelectInit); - const [mappingOperationValue, setMappingOperationValue] = useState(''); - const [operation3Value, setOperation3Value] = useState(operationSelectInit); - - const [filterTarget, setFilterTarget] = useState(filterTargetSelectInit); - const [filterOperation, setFilterOperation] = useState(filterOperationsSelectInit); - const [filterOperationValue, setFilterOperationValue] = useState(''); - - const [targetInputValue, setTargetInputValue] = useState(''); - //const [selectedSource] = props.selectedCrosswalk.source.filter(item => item.id === sourceInputValue); - //const [selectedTarget] = props.selectedCrosswalk.target.filter(item => item.id === targetInputValue); - - const [visible, setVisible] = useState(props.modalOpen); - const [filterDetailsVisible, setFilterDetailsVisible] = useState<boolean>(false); - const [validationErrors, setValidationErrors] = useState<string[]>([]); - - const [notesValue, setNotesValue] = useState<string>(''); - const [mappingPayload, setMappingPayload] = useState<CrosswalkConnectionNew>(props.selectedCrosswalk); - - - function closeModal() { - props.performNodeInfoAction('closeModal', null, null); - }; - - function setSourceFilterValue(value: any) { - console.log('setting source fitler value', value); +export default function NodeMappings(props: { + selectedCrosswalk: CrosswalkConnectionNew; + performNodeInfoAction: any; + filterFunctions: any; + modalOpen: boolean; + isFirstAdd: boolean; +}) { + let sourceSelectionInit = ''; + let targetSelectionInit = ''; + console.log('SOURCE DATA', props?.selectedCrosswalk?.source); + console.log('TARGET DATA', props?.selectedCrosswalk?.target); + console.log('SELECTED', props?.selectedCrosswalk); + + const operationValues = [ + { + name: 'Operation 1', + id: 1, + }, + { + name: 'Operation 2', + id: 2, + }, + ]; + + const filterValues = [ + { + name: 'Filter 1', + id: 1, + }, + { + name: 'Filter 2', + id: 2, + }, + ]; + + const filterOperations = [ + { + name: 'Filter operation 1', + id: 1, + }, + { + name: 'Filter operation 2', + id: 2, + }, + ]; + const operationSelectInit = 'Operation 1'; + + const filterTargetSelectInit = ''; + const filterOperationsSelectInit = 'Filter operation 1'; + + useEffect(() => { + if (props?.selectedCrosswalk?.source) { + sourceSelectionInit = props.selectedCrosswalk.source.id; + setSourceInputValue(props.selectedCrosswalk.source.id); + } + if (props?.selectedCrosswalk?.target) { + targetSelectionInit = props.selectedCrosswalk.target.id; + setTargetInputValue(props.selectedCrosswalk.target.id); } - function save() { - console.log('validation errors', validationErrors); - props.performNodeInfoAction('save', mappingPayload, null); - }; - - // CLEAR FIELDS WHEN MODAL OPENED - useEffect(() => { - setSourceInputValue(sourceSelectionInit); - setOperation1Value(operationSelectInit); - setMappingOperationValue(''); - setOperation3Value(operationSelectInit); - setFilterTarget(filterTargetSelectInit); - setFilterOperation(filterOperationsSelectInit); - setMappingPayload(props.selectedCrosswalk); - }, [visible]); - - // VALIDATE MAPPING - useEffect(() => { - setValidationErrors(validateMapping(props.selectedCrosswalk)); - }, [setOperation1Value, setMappingOperationValue, setOperation3Value, setFilterTarget, setFilterOperation]); - - return (<> - <Modal - appElementId="__next" - visible={visible} - onEscKeyDown={() => closeModal()} - className='row bg-white edit-mapping-modal' - > - <ModalContent className='edit-mapping-modal-content'> - <ModalTitle>{'Edit mapping'}</ModalTitle> - <div className='col flex-column d-flex justify-content-between'> - - <div className='row bg-white'> - - {/* SOURCE OPERATIONS */} - <div className='col-4'> - <div className='bg-light-blue p-2'> - <p><span className='fw-bold'>Source: </span>{props.selectedCrosswalk.source.name}</p> - <p><span className='fw-bold'>Type: </span>{props.selectedCrosswalk.source.type}</p> - <p><span - className='fw-bold'>Description: </span>{props.selectedCrosswalk.source?.description ? props.selectedCrosswalk.source?.description : 'N/A'} - </p> - - <span hidden={filterDetailsVisible}> - <Button - icon="plus" - style={{height: 'min-content'}} - onClick={() => setFilterDetailsVisible(true)} - variant="secondaryNoBorder" - > - {'Add filter'} - </Button> - </span> - - <div hidden={!filterDetailsVisible}> - <Dropdown className='mt-2 node-info-dropdown' - labelText="Source filter" - visualPlaceholder="Filter target not selected" - value={filterTarget} - onChange={(newValue) => setFilterTarget(newValue)} - > - {filterValues.map((rt) => ( - <DropdownItem key={rt.id} value={rt.name}> - {rt.name} - </DropdownItem> - ))} - </Dropdown> - <div><Dropdown className='mt-2 node-info-dropdown' - visualPlaceholder="Filter function not selected" - value={filterOperation} - onChange={(newValue) => setFilterOperation(newValue)} - > - {filterOperations.map((rt) => ( - <DropdownItem key={rt.id} value={rt.name}> - {rt.name} - </DropdownItem> - ))} - </Dropdown></div> - <TextInput - onChange={(value) => setSourceFilterValue('uri', value)} - visualPlaceholder="Value" - /> - </div> - <div><Dropdown className='mt-2 node-info-dropdown' - labelText="Source operation" - visualPlaceholder="Operation not selected" - value={operation1Value} - onChange={(newValue) => setOperation1Value(newValue)} - > - {operationValues.map((rt) => ( - <DropdownItem key={rt.id} value={rt.name}> - {rt.name} - </DropdownItem> - ))} - </Dropdown></div> - </div> - </div> - - {/* MID COLUMN */} - <div className='col-4 d-flex flex-column justify-content-between'> - <div><Dropdown className='mt-2 node-info-dropdown' - labelText="Mapping operation" - visualPlaceholder="Operation not selected" - value={mappingOperationValue} - onChange={(newValue) => setMappingOperationValue(newValue)} - > - {props?.filterFunctions.map((rt) => ( - <DropdownItem key={rt.uri} value={rt.name}> - {rt.name} - </DropdownItem> - ))} - </Dropdown></div> - <Textarea - onChange={(event) => setNotesValue(event.target.value)} - labelText="Notes:" - visualPlaceholder="No notes set. Add free form notes here." - value={notesValue} - /> - </div> - - {/* TARGET OPERATIONS */} - <div className='col-4'> - <div className='bg-light-blue p-2'> - <p><span className='fw-bold'>Target: </span>{props.selectedCrosswalk.target.name}</p> - <p><span className='fw-bold'>Type: </span>{props.selectedCrosswalk.target.type}</p> - <p className='mb-1'><span - className='fw-bold'>Description: </span>{props.selectedCrosswalk.target?.description ? props.selectedCrosswalk.target?.description : 'N/A'} - </p> - <br/> - <div><Dropdown className='mt-2 node-info-dropdown' - labelText="Target operation" - visualPlaceholder="Operation not selected" - value={operation3Value} - onChange={(newValue) => setOperation3Value(newValue)} - > - {operationValues.map((rt) => ( - <DropdownItem key={rt.id} value={rt.name}> - {rt.name} - </DropdownItem> - ))} - </Dropdown></div> - </div> - </div> + setVisible(props?.modalOpen); + }, [props]); + + const [sourceInputValue, setSourceInputValue] = useState(sourceSelectionInit); + const [operation1Value, setOperation1Value] = useState(operationSelectInit); + const [mappingOperationValue, setMappingOperationValue] = useState(''); + const [operation3Value, setOperation3Value] = useState(operationSelectInit); + + const [filterTarget, setFilterTarget] = useState(filterTargetSelectInit); + const [filterOperation, setFilterOperation] = useState( + filterOperationsSelectInit + ); + const [filterOperationValue, setFilterOperationValue] = useState(''); + + const [targetInputValue, setTargetInputValue] = useState(''); + //const [selectedSource] = props.selectedCrosswalk.source.filter(item => item.id === sourceInputValue); + //const [selectedTarget] = props.selectedCrosswalk.target.filter(item => item.id === targetInputValue); + + const [visible, setVisible] = useState(props.modalOpen); + const [filterDetailsVisible, setFilterDetailsVisible] = + useState<boolean>(false); + const [validationErrors, setValidationErrors] = useState<string[]>([]); + + const [notesValue, setNotesValue] = useState<string>(''); + const [mappingPayload, setMappingPayload] = useState<CrosswalkConnectionNew>( + props.selectedCrosswalk + ); + + function closeModal() { + props.performNodeInfoAction('closeModal', null, null); + } + + function setSourceFilterValue(value: any) { + console.log('setting source fitler value', value); + } + + function save() { + console.log('validation errors', validationErrors); + props.performNodeInfoAction('save', mappingPayload, null); + } + + // CLEAR FIELDS WHEN MODAL OPENED + useEffect(() => { + setSourceInputValue(sourceSelectionInit); + setOperation1Value(operationSelectInit); + setMappingOperationValue(''); + setOperation3Value(operationSelectInit); + setFilterTarget(filterTargetSelectInit); + setFilterOperation(filterOperationsSelectInit); + setMappingPayload(props.selectedCrosswalk); + }, [visible]); + + // VALIDATE MAPPING + useEffect(() => { + setValidationErrors(validateMapping(props.selectedCrosswalk)); + }, [ + setOperation1Value, + setMappingOperationValue, + setOperation3Value, + setFilterTarget, + setFilterOperation, + ]); + + return ( + <> + <Modal + appElementId="__next" + visible={visible} + onEscKeyDown={() => closeModal()} + className="row bg-white edit-mapping-modal" + > + <ModalContent className="edit-mapping-modal-content"> + <ModalTitle>{'Edit mapping'}</ModalTitle> + <div className="col flex-column d-flex justify-content-between"> + <div className="row bg-white"> + {/* SOURCE OPERATIONS */} + <div className="col-4"> + <div className="bg-light-blue p-2"> + <p> + <span className="fw-bold">Source: </span> + {props.selectedCrosswalk.source.name} + </p> + <p> + <span className="fw-bold">Type: </span> + {props.selectedCrosswalk.source.type} + </p> + <p> + <span className="fw-bold">Description: </span> + {props.selectedCrosswalk.source?.description + ? props.selectedCrosswalk.source?.description + : 'N/A'} + </p> + + <span hidden={filterDetailsVisible}> + <Button + icon="plus" + style={{ height: 'min-content' }} + onClick={() => setFilterDetailsVisible(true)} + variant="secondaryNoBorder" + > + {'Add filter'} + </Button> + </span> + + <div hidden={!filterDetailsVisible}> + <Dropdown + className="mt-2 node-info-dropdown" + labelText="Source filter" + visualPlaceholder="Filter target not selected" + value={filterTarget} + onChange={(newValue) => setFilterTarget(newValue)} + > + {filterValues.map((rt) => ( + <DropdownItem key={rt.id} value={rt.name}> + {rt.name} + </DropdownItem> + ))} + </Dropdown> + <div> + <Dropdown + className="mt-2 node-info-dropdown" + visualPlaceholder="Filter function not selected" + value={filterOperation} + onChange={(newValue) => setFilterOperation(newValue)} + > + {filterOperations.map((rt) => ( + <DropdownItem key={rt.id} value={rt.name}> + {rt.name} + </DropdownItem> + ))} + </Dropdown> </div> + <TextInput + onChange={(value) => setSourceFilterValue('uri', value)} + visualPlaceholder="Value" + /> + </div> + <div> + <Dropdown + className="mt-2 node-info-dropdown" + labelText="Source operation" + visualPlaceholder="Operation not selected" + value={operation1Value} + onChange={(newValue) => setOperation1Value(newValue)} + > + {operationValues.map((rt) => ( + <DropdownItem key={rt.id} value={rt.name}> + {rt.name} + </DropdownItem> + ))} + </Dropdown> + </div> </div> - </ModalContent> - <ModalFooter> - <Button - style={{height: 'min-content'}} - onClick={() => save()} - disabled={mappingOperationValue.length < 1} - > - {'Save'} - </Button> - <Button - style={{height: 'min-content'}} - variant="secondary" - onClick={() => closeModal()} - > - {'Cancel'} - </Button> - </ModalFooter> - </Modal> - </>); + </div> + + {/* MID COLUMN */} + <div className="col-4 d-flex flex-column justify-content-between"> + <div> + <Dropdown + className="mt-2 node-info-dropdown" + labelText="Mapping operation" + visualPlaceholder="Operation not selected" + value={mappingOperationValue} + onChange={(newValue) => setMappingOperationValue(newValue)} + > + {props?.filterFunctions.map((rt) => ( + <DropdownItem key={rt.uri} value={rt.name}> + {rt.name} + </DropdownItem> + ))} + </Dropdown> + </div> + <Textarea + onChange={(event) => setNotesValue(event.target.value)} + labelText="Notes:" + visualPlaceholder="No notes set. Add free form notes here." + value={notesValue} + /> + </div> + + {/* TARGET OPERATIONS */} + <div className="col-4"> + <div className="bg-light-blue p-2"> + <p> + <span className="fw-bold">Target: </span> + {props.selectedCrosswalk.target.name} + </p> + <p> + <span className="fw-bold">Type: </span> + {props.selectedCrosswalk.target.type} + </p> + <p className="mb-1"> + <span className="fw-bold">Description: </span> + {props.selectedCrosswalk.target?.description + ? props.selectedCrosswalk.target?.description + : 'N/A'} + </p> + <br /> + <div> + <Dropdown + className="mt-2 node-info-dropdown" + labelText="Target operation" + visualPlaceholder="Operation not selected" + value={operation3Value} + onChange={(newValue) => setOperation3Value(newValue)} + > + {operationValues.map((rt) => ( + <DropdownItem key={rt.id} value={rt.name}> + {rt.name} + </DropdownItem> + ))} + </Dropdown> + </div> + </div> + </div> + </div> + </div> + </ModalContent> + <ModalFooter> + <Button + style={{ height: 'min-content' }} + onClick={() => save()} + disabled={mappingOperationValue.length < 1} + > + {'Save'} + </Button> + <Button + style={{ height: 'min-content' }} + variant="secondary" + onClick={() => closeModal()} + > + {'Cancel'} + </Button> + </ModalFooter> + </Modal> + </> + ); } - - - - - - - - - - - - - - - - - - - - - - diff --git a/mscr-ui/src/modules/schema-view/index.tsx b/mscr-ui/src/modules/schema-view/index.tsx index 9323dcba4..a152e0d0b 100644 --- a/mscr-ui/src/modules/schema-view/index.tsx +++ b/mscr-ui/src/modules/schema-view/index.tsx @@ -4,17 +4,21 @@ import Tab from '@mui/material/Tab'; import { SyntheticEvent, useState } from 'react'; import MetadataAndFiles from '@app/modules/schema-view/metadata-and-files'; import VersionHistory from '@app/modules/schema-view/version-history'; -import {useTranslation} from 'next-i18next'; -import {useGetSchemaQuery} from '@app/common/components/schema/schema.slice'; +import { useTranslation } from 'next-i18next'; +import { useGetSchemaQuery } from '@app/common/components/schema/schema.slice'; export default function SchemaView({ schemaId }: { schemaId: string }) { const { t } = useTranslation('common'); - const { data: schemaDetails, isLoading, isSuccess, isError, error } = - useGetSchemaQuery(schemaId); + const { + data: schemaDetails, + isLoading, + isSuccess, + isError, + error, + } = useGetSchemaQuery(schemaId); const [selectedTab, setSelectedTab] = useState(0); - function a11yProps(index: number) { return { id: `simple-tab-${index}`, @@ -36,24 +40,24 @@ export default function SchemaView({ schemaId }: { schemaId: string }) { } else if (isSuccess) { return ( <> - <Box className='mb-3' sx={{borderBottom: 1, borderColor: 'divider'}}> - <Tabs value={selectedTab} onChange={changeTab} aria-label="Category selection"> + <Box className="mb-3" sx={{ borderBottom: 1, borderColor: 'divider' }}> + <Tabs + value={selectedTab} + onChange={changeTab} + aria-label="Category selection" + > <Tab label={t('schema.metadata-and-files')} {...a11yProps(0)} /> <Tab label={t('schema.version-history')} {...a11yProps(1)} /> </Tabs> </Box> - {selectedTab === 0 && - <MetadataAndFiles schemaDetails={schemaDetails} /> - } - {selectedTab === 1 && - <VersionHistory schemaDetails={schemaDetails}/> - } + {selectedTab === 0 && ( + <MetadataAndFiles schemaDetails={schemaDetails} /> + )} + {selectedTab === 1 && <VersionHistory schemaDetails={schemaDetails} />} </> ); } // TODO: What to return if data fetching returns error? - return ( - <></> - ); + return <></>; } diff --git a/mscr-ui/src/modules/schema-view/metadata-and-files/index.tsx b/mscr-ui/src/modules/schema-view/metadata-and-files/index.tsx index 4ffd07353..c08c94756 100644 --- a/mscr-ui/src/modules/schema-view/metadata-and-files/index.tsx +++ b/mscr-ui/src/modules/schema-view/metadata-and-files/index.tsx @@ -1,15 +1,19 @@ -import {useTranslation} from 'next-i18next'; -import {useMemo} from 'react'; -import {Schema} from '@app/common/interfaces/schema.interface'; +import { useTranslation } from 'next-i18next'; +import { useMemo } from 'react'; +import { Schema } from '@app/common/interfaces/schema.interface'; import router from 'next/router'; import { DescriptionList, - DescriptionListTitle + DescriptionListTitle, } from '@app/modules/schema-view/metadata-and-files/metadata-and-files.styles'; -import {Grid} from '@mui/material'; -import {Heading} from 'suomifi-ui-components'; +import { Grid } from '@mui/material'; +import { Heading } from 'suomifi-ui-components'; -export default function MetadataAndFiles({ schemaDetails }: { schemaDetails?: Schema }) { +export default function MetadataAndFiles({ + schemaDetails, +}: { + schemaDetails?: Schema; +}) { const { t } = useTranslation('common'); const lang = router.locale; @@ -18,67 +22,62 @@ export default function MetadataAndFiles({ schemaDetails }: { schemaDetails?: Sc // Locale: Object.entries(schemaDetails.label).find((t) => t[0] === lang)?.[1] ?? '' // Organization: see datamodel-ui/src/modules/model/model-info-view.tsx interface SchemaDisplay { - [key:string]: string; + [key: string]: string; } - const schemaDisplay : SchemaDisplay = useMemo(() => { + const schemaDisplay: SchemaDisplay = useMemo(() => { if (!schemaDetails) { - return ( - { - schemaPid: '', - schemaLabel: '', - schemaDescription: '', - schemaCreated: '', - schemaModified: '', - schemaState: '', - schemaOrganizations: '', - schemaVisibility: '', - schemaFormat: '', - schemaVersionLabel: '', - schemaNamespace: '' - } - ); + return { + schemaPid: '', + schemaLabel: '', + schemaDescription: '', + schemaCreated: '', + schemaModified: '', + schemaState: '', + schemaOrganizations: '', + schemaVisibility: '', + schemaFormat: '', + schemaVersionLabel: '', + schemaNamespace: '', + }; } - function languageFinder(langTaggedData: { [key:string]: string }) { - const primaryOption = Object.entries(langTaggedData).find((t) => t[0] === lang)?.[1]; - const englishOption = Object.entries(langTaggedData).find((t) => t[0] === 'en')?.[1]; + function languageFinder(langTaggedData: { [key: string]: string }) { + const primaryOption = Object.entries(langTaggedData).find( + (t) => t[0] === lang + )?.[1]; + const englishOption = Object.entries(langTaggedData).find( + (t) => t[0] === 'en' + )?.[1]; return primaryOption ?? englishOption; } - return ( - { - schemaPid: schemaDetails?.pid ?? '', - schemaLabel: schemaDetails?.label - ? languageFinder(schemaDetails.label) ?? '' - : '', - schemaDescription: schemaDetails?.description - ? languageFinder(schemaDetails.description) ?? '' - : '', - schemaCreated: schemaDetails?.created ?? '', - schemaModified: schemaDetails?.modified ?? '', - schemaState: schemaDetails?.state ?? '', - schemaOrganizations: schemaDetails?.organizations.toString() ?? '', - schemaVisibility: schemaDetails?.visibility ?? '', - schemaFormat: schemaDetails?.format ?? '', - schemaVersionLabel: schemaDetails?.versionLabel ?? '', - schemaNamespace: schemaDetails?.namespace ?? '' - } - ); + return { + schemaPid: schemaDetails?.pid ?? '', + schemaLabel: schemaDetails?.label + ? languageFinder(schemaDetails.label) ?? '' + : '', + schemaDescription: schemaDetails?.description + ? languageFinder(schemaDetails.description) ?? '' + : '', + schemaCreated: schemaDetails?.created ?? '', + schemaModified: schemaDetails?.modified ?? '', + schemaState: schemaDetails?.state ?? '', + schemaOrganizations: schemaDetails?.organizations.toString() ?? '', + schemaVisibility: schemaDetails?.visibility ?? '', + schemaFormat: schemaDetails?.format ?? '', + schemaVersionLabel: schemaDetails?.versionLabel ?? '', + schemaNamespace: schemaDetails?.namespace ?? '', + }; }, [schemaDetails, lang]); return ( <> - <Heading variant='h2'>{t('schema.metadata')}</Heading> + <Heading variant="h2">{t('schema.metadata')}</Heading> <DescriptionList> <Grid container spacing={2}> - <Grid item xs={2}> - <DescriptionListTitle> - {t('schema.name')} - </DescriptionListTitle> + <DescriptionListTitle>{t('schema.name')}</DescriptionListTitle> </Grid> <Grid item xs={10}> - <dd> - {schemaDisplay.schemaLabel} - </dd> + <dd>{schemaDisplay.schemaLabel}</dd> </Grid> <Grid item xs={2}> @@ -87,64 +86,42 @@ export default function MetadataAndFiles({ schemaDetails }: { schemaDetails?: Sc </DescriptionListTitle> </Grid> <Grid item xs={10}> - <dd> - {schemaDisplay.schemaDescription} - </dd> + <dd>{schemaDisplay.schemaDescription}</dd> </Grid> <Grid item xs={2}> - <DescriptionListTitle> - {t('schema.pid')} - </DescriptionListTitle> + <DescriptionListTitle>{t('schema.pid')}</DescriptionListTitle> </Grid> <Grid item xs={10}> - <dd> - {schemaDisplay.schemaPid} - </dd> + <dd>{schemaDisplay.schemaPid}</dd> </Grid> <Grid item xs={2}> - <DescriptionListTitle> - {t('schema.version')} - </DescriptionListTitle> + <DescriptionListTitle>{t('schema.version')}</DescriptionListTitle> </Grid> <Grid item xs={10}> - <dd> - {schemaDisplay.schemaVersionLabel} - </dd> + <dd>{schemaDisplay.schemaVersionLabel}</dd> </Grid> <Grid item xs={2}> - <DescriptionListTitle> - {t('schema.created')} - </DescriptionListTitle> + <DescriptionListTitle>{t('schema.created')}</DescriptionListTitle> </Grid> <Grid item xs={10}> - <dd> - {schemaDisplay.schemaCreated} - </dd> + <dd>{schemaDisplay.schemaCreated}</dd> </Grid> <Grid item xs={2}> - <DescriptionListTitle> - {t('schema.modified')} - </DescriptionListTitle> + <DescriptionListTitle>{t('schema.modified')}</DescriptionListTitle> </Grid> <Grid item xs={10}> - <dd> - {schemaDisplay.schemaModified} - </dd> + <dd>{schemaDisplay.schemaModified}</dd> </Grid> <Grid item xs={2}> - <DescriptionListTitle> - {t('schema.state')} - </DescriptionListTitle> + <DescriptionListTitle>{t('schema.state')}</DescriptionListTitle> </Grid> <Grid item xs={10}> - <dd> - {schemaDisplay.schemaState} - </dd> + <dd>{schemaDisplay.schemaState}</dd> </Grid> <Grid item xs={2}> @@ -153,31 +130,21 @@ export default function MetadataAndFiles({ schemaDetails }: { schemaDetails?: Sc </DescriptionListTitle> </Grid> <Grid item xs={10}> - <dd> - {schemaDisplay.schemaVisibility} - </dd> + <dd>{schemaDisplay.schemaVisibility}</dd> </Grid> <Grid item xs={2}> - <DescriptionListTitle> - {t('schema.format')} - </DescriptionListTitle> + <DescriptionListTitle>{t('schema.format')}</DescriptionListTitle> </Grid> <Grid item xs={10}> - <dd> - {schemaDisplay.schemaFormat} - </dd> + <dd>{schemaDisplay.schemaFormat}</dd> </Grid> <Grid item xs={2}> - <DescriptionListTitle> - {t('schema.namespace')} - </DescriptionListTitle> + <DescriptionListTitle>{t('schema.namespace')}</DescriptionListTitle> </Grid> <Grid item xs={10}> - <dd> - {schemaDisplay.schemaNamespace} - </dd> + <dd>{schemaDisplay.schemaNamespace}</dd> </Grid> <Grid item xs={2}> @@ -186,11 +153,8 @@ export default function MetadataAndFiles({ schemaDetails }: { schemaDetails?: Sc </DescriptionListTitle> </Grid> <Grid item xs={10}> - <dd> - {schemaDisplay.schemaOrganizations} - </dd> + <dd>{schemaDisplay.schemaOrganizations}</dd> </Grid> - </Grid> </DescriptionList> <div>TABLE HERE{/* TODO: Display schema files */}</div> diff --git a/mscr-ui/src/modules/schema-view/version-history/index.tsx b/mscr-ui/src/modules/schema-view/version-history/index.tsx index 9e94df0d5..bb10539c4 100644 --- a/mscr-ui/src/modules/schema-view/version-history/index.tsx +++ b/mscr-ui/src/modules/schema-view/version-history/index.tsx @@ -1,42 +1,48 @@ -import {useTranslation} from 'next-i18next'; -import {Schema} from '@app/common/interfaces/schema.interface'; +import { useTranslation } from 'next-i18next'; +import { Schema } from '@app/common/interfaces/schema.interface'; import HistoryTable from '@app/common/components/history-table'; -export default function VersionHistory({ schemaDetails }: {schemaDetails: Schema}) { +export default function VersionHistory({ + schemaDetails, +}: { + schemaDetails: Schema; +}) { const { t } = useTranslation('common'); - const headers = [ t('schema.version-label'), t('schema.pid'), t('schema.created'), - t('schema.state') + t('schema.state'), ]; // Temporarily mock data, really should be schemaDetails.revisions or something - const revisions = - [ - { - 'pid': 'urn:IAMNOTAPID:9f02b4da-1766-4f3a-aa61-270c0bd3e460', - 'label': { - 'en': 'string' - }, - 'versionLabel': '1', - 'created': '2023-11-21', - 'state': 'PUBLISHED' + const revisions = [ + { + pid: 'urn:IAMNOTAPID:9f02b4da-1766-4f3a-aa61-270c0bd3e460', + label: { + en: 'string', + }, + versionLabel: '1', + created: '2023-11-21', + state: 'PUBLISHED', + }, + { + pid: 'urn:IAMNOTAPID:4faa61a3-1de9-451d-80f2-cce179e82084', + label: { + en: 'string', }, - { - 'pid': 'urn:IAMNOTAPID:4faa61a3-1de9-451d-80f2-cce179e82084', - 'label': { - 'en': 'string' - }, - 'versionLabel': '1.1', - 'created': '2023-11-21', - 'state': 'DRAFT' - } - ]; + versionLabel: '1.1', + created: '2023-11-21', + state: 'DRAFT', + }, + ]; return ( - <HistoryTable headers={headers} revisions={revisions} ariaLabel={t('schema.versions')}/> + <HistoryTable + headers={headers} + revisions={revisions} + ariaLabel={t('schema.versions')} + /> ); } diff --git a/mscr-ui/src/modules/search-screen/index.tsx b/mscr-ui/src/modules/search-screen/index.tsx index 4b2de5d8c..34dfcfd4f 100644 --- a/mscr-ui/src/modules/search-screen/index.tsx +++ b/mscr-ui/src/modules/search-screen/index.tsx @@ -13,17 +13,18 @@ import { IconClose } from 'suomifi-icons'; import { useContext } from 'react'; import { SearchContext } from '@app/common/components/search-context-provider'; import SearchFilterSet from '@app/common/components/search-filter-set'; -import {Bucket, Facet, Filter} from '@app/common/interfaces/search.interface'; -import {useTranslation} from 'next-i18next'; -import {Grid} from '@mui/material'; +import { Bucket, Facet, Filter } from '@app/common/interfaces/search.interface'; +import { useTranslation } from 'next-i18next'; +import { Grid } from '@mui/material'; export default function SearchScreen() { const { urlState, patchUrlState } = useUrlState(); const { t } = useTranslation('common'); const { setIsSearchActive } = useContext(SearchContext); - const { data: mscrSearchResults } = - useGetMscrSearchResultsQuery(urlState); - const foundHits = mscrSearchResults ? mscrSearchResults.hits.hits.length !== 0 : false; + const { data: mscrSearchResults } = useGetMscrSearchResultsQuery(urlState); + const foundHits = mscrSearchResults + ? mscrSearchResults.hits.hits.length !== 0 + : false; const handleClose = () => { setIsSearchActive(false); @@ -53,7 +54,7 @@ export default function SearchScreen() { }; }; - let filters : Filter[] = []; + let filters: Filter[] = []; if (mscrSearchResults?.aggregations) { Object.keys(mscrSearchResults.aggregations).forEach((key) => { const newFilter: Filter = makeFilter( @@ -70,7 +71,9 @@ export default function SearchScreen() { <Grid item xs={2}> <FacetsWrapper> {/* Groups of facets for different contexts, made with search-filter-set */} - {filters.length > 0 && <SearchFilterSet title={t('in-all-mscr')} filters={filters}/>} + {filters.length > 0 && ( + <SearchFilterSet title={t('in-all-mscr')} filters={filters} /> + )} </FacetsWrapper> </Grid> <Grid item xs={8}> diff --git a/mscr-ui/src/pages/[homepage]/index.tsx b/mscr-ui/src/pages/[homepage]/index.tsx index d543a701a..17f08a1d2 100644 --- a/mscr-ui/src/pages/[homepage]/index.tsx +++ b/mscr-ui/src/pages/[homepage]/index.tsx @@ -52,12 +52,10 @@ export default function IndexPage(props: IndexPageProps) { user?: MscrUser; }): React.ReactElement { if (slug === 'group-home') { - return <GroupWorkspace pid={''} user={user}/>; - } - else if (slug === 'crosswalk-edit') { + return <GroupWorkspace pid={''} user={user} />; + } else if (slug === 'crosswalk-edit') { return <CrosswalkEditor />; - } - else { + } else { console.log(slug); return <PersonalWorkspace pid={''} user={user} />; } diff --git a/mscr-ui/src/pages/index.tsx b/mscr-ui/src/pages/index.tsx index ed0f3ceb6..a88d4721b 100644 --- a/mscr-ui/src/pages/index.tsx +++ b/mscr-ui/src/pages/index.tsx @@ -43,7 +43,6 @@ export default function IndexPage(props: IndexPageProps) { title={t('mscr-title')} description={t('service-description')} /> - </Layout> </CommonContextProvider> ); diff --git a/mscr-ui/src/pages/mscr-style-customizations.scss b/mscr-ui/src/pages/mscr-style-customizations.scss index e03b0e663..71d0e31d1 100644 --- a/mscr-ui/src/pages/mscr-style-customizations.scss +++ b/mscr-ui/src/pages/mscr-style-customizations.scss @@ -16,24 +16,25 @@ font-size: 0.9rem; height: 200px; padding: 20px; - background: #ECEDEE; - color: #6B6B6B; + background: #ecedee; + color: #6b6b6b; svg { margin-right: 15px; } } .node-selection-action-buttons { - button { margin: 5px 0px;} + button { + margin: 5px 0px; + } flex-direction: column; } - .fixed-footer { - position:fixed; - bottom:0; - left:0; - width:100%; + position: fixed; + bottom: 0; + left: 0; + width: 100%; height: 90px; background-color: #fff; border-top: 3px solid #d5e4f6; @@ -55,7 +56,7 @@ } h2 { - color: #6B6B6B; + color: #6b6b6b; font-size: 1.2rem; font-weight: bold; } @@ -75,7 +76,7 @@ .node-info-wrap { font-size: 0.9rem; - color: #6B6B6B; + color: #6b6b6b; .attribute-font { font-size: 0.9rem; line-height: 1.3rem; @@ -86,7 +87,7 @@ overflow-wrap: break-word; } h2 { - color: #6B6B6B; + color: #6b6b6b; font-size: 1rem; font-weight: normal; margin-bottom: 0px; @@ -98,7 +99,7 @@ .side-bar-wrap { padding: 5px 5px; } - background: #D8E3F4; + background: #d8e3f4; .dropdown-wrap { margin-top: -35px; margin-bottom: 15px; @@ -122,7 +123,6 @@ font-size: 26px !important; } - .linked-tree-item { font-size: 10px; //background-color: #ede4ff !important; @@ -162,7 +162,6 @@ } .node-info-dropdown { - } .node-info-box { @@ -196,7 +195,7 @@ .joint-listing-accordion-wrap { thead { - border-bottom: 3px solid #D8E3F4; + border-bottom: 3px solid #d8e3f4; outline: none; } } @@ -210,12 +209,12 @@ } } .row { - min-height: 145px; + min-height: 145px; } } .accordion-row-content { - min-height: 145px; + min-height: 145px; } .accordion-row { @@ -272,8 +271,8 @@ .metadata-and-files-wrap { h2 { - color: #6F787D; + color: #6f787d; font-size: 1.3rem; } } -} \ No newline at end of file +} From cfa50554b6dc571ff3ccb0f4d562fbbb40597472 Mon Sep 17 00:00:00 2001 From: rquazi <rumana.quazi@csc.fi> Date: Fri, 24 Nov 2023 10:10:06 +0200 Subject: [PATCH 11/15] Implementaing crosswalkFull endpoint --- .../components/crosswalk/crosswalk.slice.tsx | 21 ++++++- .../common/interfaces/crosswalk.interface.ts | 3 +- .../src/common/utils/translation-helpers.ts | 1 - .../crosswalk-form/crosswalk-form-modal.tsx | 31 ++++++++-- .../crosswalk-form/generate-payload.tsx | 5 +- mscr-ui/src/modules/crosswalk-form/index.tsx | 59 ++++++------------- mscr-ui/src/modules/schema-form/index.tsx | 19 +----- .../modules/schema-form/schema-form-modal.tsx | 28 +++------ .../src/modules/schema-form/validate-form.tsx | 8 +-- mscr-ui/src/pages/index.tsx | 2 +- 10 files changed, 86 insertions(+), 91 deletions(-) diff --git a/mscr-ui/src/common/components/crosswalk/crosswalk.slice.tsx b/mscr-ui/src/common/components/crosswalk/crosswalk.slice.tsx index 2fb4cd5ce..a3f697460 100644 --- a/mscr-ui/src/common/components/crosswalk/crosswalk.slice.tsx +++ b/mscr-ui/src/common/components/crosswalk/crosswalk.slice.tsx @@ -27,6 +27,17 @@ export const crosswalkApi = createApi({ data: value, }), }), + //Register Crosswalk with file + putCrosswalkFull: builder.mutation<any, FormData>({ + query: (file) => ({ + url: '/crosswalkFull', + method: 'PUT', + data: file, + headers: { + 'content-Type': 'multipart/form-data;', + }, + }), + }), getCrosswalk: builder.query<Crosswalk, string>({ query: (pid) => ({ url: `/crosswalk/${pid}`, @@ -58,14 +69,20 @@ export const crosswalkApi = createApi({ export const { usePutCrosswalkMutation, + usePutCrosswalkFullMutation, useGetCrosswalkQuery, usePostCrosswalkMutation, useDeleteCrosswalkMutation, util: { getRunningQueriesThunk }, } = crosswalkApi; -export const { putCrosswalk, getCrosswalk, postCrosswalk, deleteCrosswalk } = - crosswalkApi.endpoints; +export const { + putCrosswalk, + putCrosswalkFull, + getCrosswalk, + postCrosswalk, + deleteCrosswalk, +} = crosswalkApi.endpoints; // Slice setup below diff --git a/mscr-ui/src/common/interfaces/crosswalk.interface.ts b/mscr-ui/src/common/interfaces/crosswalk.interface.ts index 75f3ec3dd..0416ae7e5 100644 --- a/mscr-ui/src/common/interfaces/crosswalk.interface.ts +++ b/mscr-ui/src/common/interfaces/crosswalk.interface.ts @@ -6,7 +6,7 @@ import { Status } from './status.interface'; export interface Crosswalk { pid: string; format: string; - status: string; + status: string | undefined; label: { [key: string]: string; }; @@ -17,6 +17,7 @@ export interface Crosswalk { organizations: string[]; sourceSchema: string; targetSchema: string; + state: string | undefined; } export interface CrosswalkFormType { diff --git a/mscr-ui/src/common/utils/translation-helpers.ts b/mscr-ui/src/common/utils/translation-helpers.ts index 2fe81a53a..3e409766a 100644 --- a/mscr-ui/src/common/utils/translation-helpers.ts +++ b/mscr-ui/src/common/utils/translation-helpers.ts @@ -288,7 +288,6 @@ export function translateFileUploadError( t: TFunction ) { switch (error) { - case 'upload-error': return t('file-upload-error.upload-error', { ns: 'admin' }); case 'incorrect-file-type': diff --git a/mscr-ui/src/modules/crosswalk-form/crosswalk-form-modal.tsx b/mscr-ui/src/modules/crosswalk-form/crosswalk-form-modal.tsx index 63902efde..8a2db5229 100644 --- a/mscr-ui/src/modules/crosswalk-form/crosswalk-form-modal.tsx +++ b/mscr-ui/src/modules/crosswalk-form/crosswalk-form-modal.tsx @@ -13,6 +13,7 @@ import { useBreakpoints } from 'yti-common-ui/media-query'; import { FormErrors, validateForm } from './validate-form'; import FormFooterAlert from 'yti-common-ui/form-footer-alert'; import { + translateFileUploadError, translateLanguage, translateModelFormErrors, } from '@app/common/utils/translation-helpers'; @@ -22,8 +23,13 @@ import getApiError from '@app/common/utils/getApiErrors'; import { useRouter } from 'next/router'; import HasPermission from '@app/common/utils/has-permission'; import { useInitialCrosswalkForm } from '@app/common/utils/hooks/use-initial-crosswalk-form'; -import { usePutCrosswalkMutation } from '@app/common/components/crosswalk/crosswalk.slice'; +import { + usePutCrosswalkFullMutation, + usePutCrosswalkMutation, +} from '@app/common/components/crosswalk/crosswalk.slice'; import CrosswalkForm from '.'; +import FileDropArea from 'yti-common-ui/file-drop-area'; +const [isValid, setIsValid] = useState(false); interface CrosswalkFormModalProps { refetch: () => void; @@ -44,7 +50,9 @@ export default function CrosswalkFormModal({ const [userPosted, setUserPosted] = useState(false); const [getAuthenticatedUser, authenticateUser] = useGetAuthenticatedUserMutMutation(); - const [putCrosswalk, result] = usePutCrosswalkMutation(); + const [putCrosswalkFull, result] = usePutCrosswalkFullMutation(); + const [isValid, setIsValid] = useState(false); + const [fileData, setFileData] = useState<File | null>(); const handleOpen = () => { setVisible(true); @@ -55,13 +63,14 @@ export default function CrosswalkFormModal({ setVisible(false); setUserPosted(false); setFormData(crosswalkFormInitialData); + setFileData(null); }, [crosswalkFormInitialData]); useEffect(() => { if (userPosted && result.isSuccess) { refetch(); handleClose(); - //router.push(`/crosswalk/${result.data.pid}`); + router.push(`/crosswalk/${result.data.pid}`); alert('Crosswalk created Successfully'); } }, [result, refetch, userPosted, handleClose, router]); @@ -80,8 +89,14 @@ export default function CrosswalkFormModal({ } const payload = generatePayload(formData); - console.log(payload); - putCrosswalk(payload); + const crosswalkFormData = new FormData(); + crosswalkFormData.append('metadata', JSON.stringify(payload)); + if (fileData) { + crosswalkFormData.append('file', fileData); + putCrosswalkFull(crosswalkFormData); + } else { + return; + } }; useEffect(() => { @@ -125,6 +140,12 @@ export default function CrosswalkFormModal({ disabled={authenticateUser.data && authenticateUser.data.anonymous} errors={userPosted ? errors : undefined} /> + <FileDropArea + setFileData={setFileData} + setIsValid={setIsValid} + validFileTypes={['json', 'xslt', 'pdf']} + translateFileUploadError={translateFileUploadError} + /> </ModalContent> <ModalFooter> {authenticateUser.data && authenticateUser.data.anonymous && ( diff --git a/mscr-ui/src/modules/crosswalk-form/generate-payload.tsx b/mscr-ui/src/modules/crosswalk-form/generate-payload.tsx index c4ccb3d90..e7e93cd97 100644 --- a/mscr-ui/src/modules/crosswalk-form/generate-payload.tsx +++ b/mscr-ui/src/modules/crosswalk-form/generate-payload.tsx @@ -8,7 +8,7 @@ import { export default function generatePayload(data: CrosswalkFormType): Crosswalk { return { pid: '', - format: 'CSV', + format: data.format, description: data.languages .filter((l) => l.description !== '') .reduce( @@ -31,7 +31,8 @@ export default function generatePayload(data: CrosswalkFormType): Crosswalk { .filter((l) => l.title !== '') .map((l) => l.uniqueItemId), organizations: data.organizations.map((o) => o.uniqueItemId), - status: 'DRAFT', + status: data.status, + state: data.status, sourceSchema: data.sourceSchema, targetSchema: data.targetSchema, }; diff --git a/mscr-ui/src/modules/crosswalk-form/index.tsx b/mscr-ui/src/modules/crosswalk-form/index.tsx index cd6738dde..3b2e061a7 100644 --- a/mscr-ui/src/modules/crosswalk-form/index.tsx +++ b/mscr-ui/src/modules/crosswalk-form/index.tsx @@ -4,15 +4,7 @@ import getOrganizations from '@app/common/utils/get-organizations'; import getServiceCategories from '@app/common/utils/get-service-categories'; import { useTranslation } from 'next-i18next'; import { useMemo, useState } from 'react'; -import { - Dropdown, - DropdownItem, - Label, - RadioButton, - RadioButtonGroup, - Text, - TextInput, -} from 'suomifi-ui-components'; +import { Dropdown, DropdownItem, TextInput } from 'suomifi-ui-components'; import Separator from 'yti-common-ui/separator'; import { BlockContainer, @@ -22,10 +14,7 @@ import { import LanguageSelector from 'yti-common-ui/form/language-selector'; import { FormErrors } from './validate-form'; import { Status } from '@app/common/interfaces/status.interface'; -import { - CrosswalkFormMockupType, - CrosswalkFormType, -} from '@app/common/interfaces/crosswalk.interface'; +import { CrosswalkFormType } from '@app/common/interfaces/crosswalk.interface'; import { FormUpdateErrors } from '../schema-form/validate-form-update'; import { translateFileUploadError } from '@app/common/utils/translation-helpers copy'; import FileDropArea from 'yti-common-ui/file-drop-area'; @@ -53,9 +42,6 @@ export default function RegisterCrosswalkForm({ i18n.language ); const { data: organizationsData } = useGetOrganizationsQuery(i18n.language); - const [fileData, setFileData] = useState<File | null>(); - const [fileType, setFileType] = useState<'csv' | 'json' | null>(); - const [isValid, setIsValid] = useState(false); const serviceCategories = useMemo(() => { if (!serviceCategoriesData) { @@ -92,13 +78,6 @@ export default function RegisterCrosswalkForm({ errors={userPosted ? errors : undefined} ></CrosswalkForm> {renderCrosswalkFormat()} - - <FileDropArea - setFileData={setFileData} - setIsValid={setIsValid} - validFileTypes={['csv', 'json']} - translateFileUploadError={translateFileUploadError} - /> {renderLanguages()} <BlockContainer>{!editMode && renderContributors()}</BlockContainer> <Separator isLarge /> @@ -110,8 +89,20 @@ export default function RegisterCrosswalkForm({ function renderCrosswalkFormat() { // may be load the formats from an array return ( - <div> - <TextInput labelText={'Format'} /> + <div style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}> + <Dropdown + labelText={'Format'} + defaultValue={'CSV'} + onChange={(e) => + setFormData({ + ...formData, + format: e, + }) + } + > + <DropdownItem value={'XSLT'}>{'XSLT'}</DropdownItem> + <DropdownItem value={'CSV'}>{'CSV'}</DropdownItem> + </Dropdown> </div> ); } @@ -167,21 +158,9 @@ export default function RegisterCrosswalkForm({ }) } > - <DropdownItem value={'DRAFT'}> - {t('statuses.draft', { ns: 'common' })} - </DropdownItem> - <DropdownItem value={'VALID'}> - {t('statuses.valid', { ns: 'common' })} - </DropdownItem> - <DropdownItem value={'SUPERSEDED'}> - {t('statuses.superseded', { ns: 'common' })} - </DropdownItem> - <DropdownItem value={'RETIRED'}> - {t('statuses.retired', { ns: 'common' })} - </DropdownItem> - <DropdownItem value={'INVALID'}> - {t('statuses.invalid', { ns: 'common' })} - </DropdownItem> + <DropdownItem value={'DRAFT'}>{'DRAFT'}</DropdownItem> + <DropdownItem value={'PUBLISHED'}>{'PUBLISHED'}</DropdownItem> + <DropdownItem value={'DEPRECATED'}>{'DEPRECATED'}</DropdownItem> </Dropdown> </div> ); diff --git a/mscr-ui/src/modules/schema-form/index.tsx b/mscr-ui/src/modules/schema-form/index.tsx index 75f24d5ad..b0479059e 100644 --- a/mscr-ui/src/modules/schema-form/index.tsx +++ b/mscr-ui/src/modules/schema-form/index.tsx @@ -2,11 +2,9 @@ import { useGetOrganizationsQuery } from '@app/common/components/organizations/organizations.slice'; import { useGetServiceCategoriesQuery } from '@app/common/components/service-categories/service-categories.slice'; import getOrganizations from '@app/common/utils/get-organizations'; -import getServiceCategories from '@app/common/utils/get-service-categories'; import { useTranslation } from 'next-i18next'; -import { useMemo, useState } from 'react'; -import { Dropdown, DropdownItem, Label, Text } from 'suomifi-ui-components'; -import Separator from 'yti-common-ui/separator'; +import { useMemo } from 'react'; +import { Dropdown, DropdownItem } from 'suomifi-ui-components'; import { BlockContainer, ModelFormContainer, @@ -16,18 +14,7 @@ import LanguageSelector from 'yti-common-ui/form/language-selector'; import { FormErrors } from './validate-form'; import { Status } from '@app/common/interfaces/status.interface'; import { FormUpdateErrors } from './validate-form-update'; -import { - Schema, - SchemaFormType, -} from '@app/common/interfaces/schema.interface'; -import { TextInput } from 'suomifi-ui-components'; -import { Paragraph } from 'suomifi-ui-components'; -import UpdateWithFileModal from '@app/common/components/update-with-file-modal'; -import { translateFileUploadError } from '@app/common/utils/translation-helpers copy'; -import FileDropArea from 'yti-common-ui/file-drop-area'; -import FileUpload from '@app/common/components/update-with-file-modal/file-upload'; -import { ImportDescriptionBlock } from '@app/common/components/update-with-file-modal/update-with-file-modal.styles'; -import { Format } from '@app/common/interfaces/format.interface'; +import { SchemaFormType } from '@app/common/interfaces/schema.interface'; interface SchemaFormProps { formData: SchemaFormType; diff --git a/mscr-ui/src/modules/schema-form/schema-form-modal.tsx b/mscr-ui/src/modules/schema-form/schema-form-modal.tsx index 04adb1770..8e8aba101 100644 --- a/mscr-ui/src/modules/schema-form/schema-form-modal.tsx +++ b/mscr-ui/src/modules/schema-form/schema-form-modal.tsx @@ -24,11 +24,7 @@ import getApiError from '@app/common/utils/getApiErrors'; import { useRouter } from 'next/router'; import HasPermission from '@app/common/utils/has-permission'; import { useInitialSchemaForm } from '@app/common/utils/hooks/use-initial-schema-form'; -import { - putSchema, - usePutSchemaFullMutation, - usePutSchemaMutation, -} from '@app/common/components/schema/schema.slice'; +import { usePutSchemaFullMutation } from '@app/common/components/schema/schema.slice'; import SchemaForm from '.'; import FileDropArea from 'yti-common-ui/file-drop-area'; import { TextSnippet } from '@mui/icons-material'; @@ -58,7 +54,6 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { const [getAuthenticatedUser, authenticateUser] = useGetAuthenticatedUserMutMutation(); const [putSchemaFull, resultSchemaFull] = usePutSchemaFullMutation(); - const handleOpen = () => { setVisible(true); @@ -83,21 +78,14 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { // After post route to saved schema get by PID // Later we should show the created schema in the list } - }, [ - resultSchemaFull, - refetch, - userPosted, - handleClose, - router, - formData, - ]); + }, [resultSchemaFull, refetch, userPosted, handleClose, router, formData]); const handleSubmit = () => { setUserPosted(true); if (!formData) { return; } - const errors = validateForm(formData,fileData); + const errors = validateForm(formData, fileData); setErrors(errors); if (Object.values(errors).includes(true)) { @@ -120,7 +108,7 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { if (!userPosted) { return; } - const errors = validateForm(formData); + const errors = validateForm(formData, fileData); setErrors(errors); //console.log(errors); }, [userPosted, formData]); @@ -156,7 +144,11 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { errors={userPosted ? errors : undefined} /> <Separator></Separator> - <Text>{'Upload a Schema File. You must upload a schema file to register schema'}</Text> + <Text> + { + 'Upload a Schema File. You must upload a schema file to register schema' + } + </Text> <FileDropArea setFileData={setFileData} setIsValid={setIsValid} @@ -212,8 +204,6 @@ export default function SchemaFormModal({ refetch }: SchemaFormModalProps) { .filter(([_, value]) => value && !Array.isArray(value)) ?.map(([key, _]) => translateModelFormErrors(key, t)); - - if (resultSchemaFull.isError) { const errorMessage = getApiError(resultSchemaFull.error); return [...langsWithError, ...otherErrors, errorMessage]; diff --git a/mscr-ui/src/modules/schema-form/validate-form.tsx b/mscr-ui/src/modules/schema-form/validate-form.tsx index 8016d4f21..59b937dc2 100644 --- a/mscr-ui/src/modules/schema-form/validate-form.tsx +++ b/mscr-ui/src/modules/schema-form/validate-form.tsx @@ -1,7 +1,5 @@ import { SchemaFormType } from '@app/common/interfaces/schema.interface'; - - // Not yet modified according to mscr validation errors export interface FormErrors { languageAmount: boolean; @@ -12,8 +10,10 @@ export interface FormErrors { fileData: boolean; } -export function validateForm(data: SchemaFormType, fileData: File | null| undefined) { - +export function validateForm( + data: SchemaFormType, + fileData: File | null | undefined +) { console.log(FormData); const errors: FormErrors = { languageAmount: false, diff --git a/mscr-ui/src/pages/index.tsx b/mscr-ui/src/pages/index.tsx index d692560fb..82df0b9e8 100644 --- a/mscr-ui/src/pages/index.tsx +++ b/mscr-ui/src/pages/index.tsx @@ -39,7 +39,7 @@ export default function IndexPage(props: IndexPageProps) { fakeableUsers={props.fakeableUsers} > <PageHead - baseUrl="https://tietomallit.suomi.fi" + baseUrl="https://localhost:3000" title={t('mscr-title')} description={t('service-description')} /> From 2e512c12906bd8986c2173b5a4624ae2ff90b4c2 Mon Sep 17 00:00:00 2001 From: rquazi <rumana.quazi@csc.fi> Date: Fri, 24 Nov 2023 11:24:52 +0200 Subject: [PATCH 12/15] fix the crosswalk format select --- .../common/interfaces/crosswalk.interface.ts | 4 +- .../crosswalk-form/crosswalk-form-modal.tsx | 12 ++-- .../crosswalk-form/generate-payload.tsx | 1 - mscr-ui/src/modules/crosswalk-form/index.tsx | 66 ++++++++----------- mscr-ui/src/modules/schema-form/index.tsx | 6 +- mscr-ui/src/pages/_document.tsx | 16 ++--- 6 files changed, 42 insertions(+), 63 deletions(-) diff --git a/mscr-ui/src/common/interfaces/crosswalk.interface.ts b/mscr-ui/src/common/interfaces/crosswalk.interface.ts index 0416ae7e5..54a9a1722 100644 --- a/mscr-ui/src/common/interfaces/crosswalk.interface.ts +++ b/mscr-ui/src/common/interfaces/crosswalk.interface.ts @@ -4,7 +4,7 @@ import { Status } from './status.interface'; //sample Crosswalk export interface Crosswalk { - pid: string; + pid?: string; format: string; status: string | undefined; label: { @@ -21,7 +21,7 @@ export interface Crosswalk { } export interface CrosswalkFormType { - pid: string; + pid?: string; format: string; label: string; languages: (LanguageBlockType & { selected: boolean })[]; diff --git a/mscr-ui/src/modules/crosswalk-form/crosswalk-form-modal.tsx b/mscr-ui/src/modules/crosswalk-form/crosswalk-form-modal.tsx index 8a2db5229..df4ab8808 100644 --- a/mscr-ui/src/modules/crosswalk-form/crosswalk-form-modal.tsx +++ b/mscr-ui/src/modules/crosswalk-form/crosswalk-form-modal.tsx @@ -23,13 +23,9 @@ import getApiError from '@app/common/utils/getApiErrors'; import { useRouter } from 'next/router'; import HasPermission from '@app/common/utils/has-permission'; import { useInitialCrosswalkForm } from '@app/common/utils/hooks/use-initial-crosswalk-form'; -import { - usePutCrosswalkFullMutation, - usePutCrosswalkMutation, -} from '@app/common/components/crosswalk/crosswalk.slice'; +import { usePutCrosswalkFullMutation } from '@app/common/components/crosswalk/crosswalk.slice'; import CrosswalkForm from '.'; import FileDropArea from 'yti-common-ui/file-drop-area'; -const [isValid, setIsValid] = useState(false); interface CrosswalkFormModalProps { refetch: () => void; @@ -83,12 +79,12 @@ export default function CrosswalkFormModal({ const errors = validateForm(formData); setErrors(errors); - if (Object.values(errors).includes(true)) { return; } const payload = generatePayload(formData); + console.log(formData); const crosswalkFormData = new FormData(); crosswalkFormData.append('metadata', JSON.stringify(payload)); if (fileData) { @@ -143,7 +139,7 @@ export default function CrosswalkFormModal({ <FileDropArea setFileData={setFileData} setIsValid={setIsValid} - validFileTypes={['json', 'xslt', 'pdf']} + validFileTypes={['csv', 'xslt', 'pdf']} translateFileUploadError={translateFileUploadError} /> </ModalContent> @@ -155,7 +151,7 @@ export default function CrosswalkFormModal({ )} {userPosted && ( <FormFooterAlert - labelText={t('missing-information-title')} + labelText={'Required Fields are missing'} alerts={getErrors(errors)} /> )} diff --git a/mscr-ui/src/modules/crosswalk-form/generate-payload.tsx b/mscr-ui/src/modules/crosswalk-form/generate-payload.tsx index e7e93cd97..c9451abae 100644 --- a/mscr-ui/src/modules/crosswalk-form/generate-payload.tsx +++ b/mscr-ui/src/modules/crosswalk-form/generate-payload.tsx @@ -7,7 +7,6 @@ import { export default function generatePayload(data: CrosswalkFormType): Crosswalk { return { - pid: '', format: data.format, description: data.languages .filter((l) => l.description !== '') diff --git a/mscr-ui/src/modules/crosswalk-form/index.tsx b/mscr-ui/src/modules/crosswalk-form/index.tsx index 3b2e061a7..6cf636aa4 100644 --- a/mscr-ui/src/modules/crosswalk-form/index.tsx +++ b/mscr-ui/src/modules/crosswalk-form/index.tsx @@ -1,10 +1,9 @@ import { useGetOrganizationsQuery } from '@app/common/components/organizations/organizations.slice'; import { useGetServiceCategoriesQuery } from '@app/common/components/service-categories/service-categories.slice'; import getOrganizations from '@app/common/utils/get-organizations'; -import getServiceCategories from '@app/common/utils/get-service-categories'; import { useTranslation } from 'next-i18next'; -import { useMemo, useState } from 'react'; -import { Dropdown, DropdownItem, TextInput } from 'suomifi-ui-components'; +import { useMemo } from 'react'; +import { Dropdown, DropdownItem } from 'suomifi-ui-components'; import Separator from 'yti-common-ui/separator'; import { BlockContainer, @@ -16,8 +15,6 @@ import { FormErrors } from './validate-form'; import { Status } from '@app/common/interfaces/status.interface'; import { CrosswalkFormType } from '@app/common/interfaces/crosswalk.interface'; import { FormUpdateErrors } from '../schema-form/validate-form-update'; -import { translateFileUploadError } from '@app/common/utils/translation-helpers copy'; -import FileDropArea from 'yti-common-ui/file-drop-area'; import CrosswalkForm from '../create-crosswalk'; interface RegisterCrosswalkFormProps { @@ -43,19 +40,6 @@ export default function RegisterCrosswalkForm({ ); const { data: organizationsData } = useGetOrganizationsQuery(i18n.language); - const serviceCategories = useMemo(() => { - if (!serviceCategoriesData) { - return []; - } - - return getServiceCategories(serviceCategoriesData, i18n.language) - .map((c) => ({ - labelText: c.label, - uniqueItemId: c.id, - })) - .sort((c1, c2) => (c1.labelText > c2.labelText ? 1 : -1)); - }, [serviceCategoriesData, i18n.language]); - const organizations = useMemo(() => { if (!organizationsData) { return []; @@ -79,10 +63,11 @@ export default function RegisterCrosswalkForm({ ></CrosswalkForm> {renderCrosswalkFormat()} {renderLanguages()} + + {renderStaus()} <BlockContainer>{!editMode && renderContributors()}</BlockContainer> <Separator isLarge /> {editMode && renderContributors()} - {renderStaus()} </ModelFormContainer> ); @@ -92,7 +77,8 @@ export default function RegisterCrosswalkForm({ <div style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}> <Dropdown labelText={'Format'} - defaultValue={'CSV'} + defaultValue={formData.format ?? ''} + visualPlaceholder={'Select Crosswalk File Format'} onChange={(e) => setFormData({ ...formData, @@ -102,6 +88,7 @@ export default function RegisterCrosswalkForm({ > <DropdownItem value={'XSLT'}>{'XSLT'}</DropdownItem> <DropdownItem value={'CSV'}>{'CSV'}</DropdownItem> + <DropdownItem value={'PDF'}>{'PDF'}</DropdownItem> </Dropdown> </div> ); @@ -145,26 +132,25 @@ export default function RegisterCrosswalkForm({ } function renderStaus() { - if (editMode) { - return ( - <div style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}> - <Dropdown - labelText={'Status'} - defaultValue={formData.status ?? ''} - onChange={(e) => - setFormData({ - ...formData, - status: e as Status | undefined, - }) - } - > - <DropdownItem value={'DRAFT'}>{'DRAFT'}</DropdownItem> - <DropdownItem value={'PUBLISHED'}>{'PUBLISHED'}</DropdownItem> - <DropdownItem value={'DEPRECATED'}>{'DEPRECATED'}</DropdownItem> - </Dropdown> - </div> - ); - } + return ( + <div style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}> + <Dropdown + labelText={'Status'} + visualPlaceholder={'Select Status'} + defaultValue={formData.status ?? ''} + onChange={(e) => + setFormData({ + ...formData, + status: e as Status | undefined, + }) + } + > + <DropdownItem value={'DRAFT'}>{'DRAFT'}</DropdownItem> + <DropdownItem value={'PUBLISHED'}>{'PUBLISHED'}</DropdownItem> + <DropdownItem value={'DEPRECATED'}>{'DEPRECATED'}</DropdownItem> + </Dropdown> + </div> + ); } function renderContributors() { diff --git a/mscr-ui/src/modules/schema-form/index.tsx b/mscr-ui/src/modules/schema-form/index.tsx index b0479059e..6177d1c4f 100644 --- a/mscr-ui/src/modules/schema-form/index.tsx +++ b/mscr-ui/src/modules/schema-form/index.tsx @@ -68,7 +68,8 @@ export default function SchemaForm({ <div style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}> <Dropdown labelText={'Format'} - defaultValue={'JSONSCHEMA'} + visualPlaceholder={'Select File Format'} + defaultValue={formData.format ?? ''} onChange={(e) => setFormData({ ...formData, @@ -124,7 +125,8 @@ export default function SchemaForm({ <div style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}> <Dropdown labelText={'Status'} - defaultValue={'DRAFT'} + visualPlaceholder={'Select Status'} + defaultValue={''} onChange={(e) => setFormData({ ...formData, diff --git a/mscr-ui/src/pages/_document.tsx b/mscr-ui/src/pages/_document.tsx index 988f098c3..dc039661f 100644 --- a/mscr-ui/src/pages/_document.tsx +++ b/mscr-ui/src/pages/_document.tsx @@ -1,23 +1,19 @@ -import Document, { DocumentContext, DocumentInitialProps } from 'next/document'; +import Document, { DocumentContext } from 'next/document'; import { ServerStyleSheet } from 'styled-components'; -//Fixing the custom render page error, https://nextjs.org/docs/pages/building-your-application/routing/custom-document +// https://github.com/msreekm/nextjs-material-ui-styled-components-boilerplate/blob/master/pages/_document.js export default class MyDocument extends Document { - static async getInitialProps( - ctx: DocumentContext - ): Promise<DocumentInitialProps> { + static async getInitialProps(ctx: DocumentContext) { const sheet = new ServerStyleSheet(); const originalRenderPage = ctx.renderPage; try { - // Run the React rendering logic synchronously ctx.renderPage = () => originalRenderPage({ - // Useful for wrapping the whole react tree - enhanceApp: (App) => App, - // Useful for wrapping in a per-page basis - enhanceComponent: (Component) => Component, + enhanceApp: (App) => (props) => + sheet.collectStyles(<App {...props} />), }); + const initialProps = await ctx.defaultGetInitialProps(ctx); return { ...initialProps, From ffa400355cd358d5572129fcbc4c306366da2bdb Mon Sep 17 00:00:00 2001 From: rquazi <rumana.quazi@csc.fi> Date: Fri, 24 Nov 2023 13:18:15 +0200 Subject: [PATCH 13/15] npm build fixes --- mscr-ui/next.config.js | 2 +- .../crosswalk-editor/schema-mockup.tsx | 4 +- mscr-ui/src/pages/schema/[...pid].tsx | 136 +++++------------- 3 files changed, 39 insertions(+), 103 deletions(-) diff --git a/mscr-ui/next.config.js b/mscr-ui/next.config.js index c98a90a94..eff81355d 100644 --- a/mscr-ui/next.config.js +++ b/mscr-ui/next.config.js @@ -9,7 +9,7 @@ module.exports = () => { reactStrictMode: true, eslint: { dirs: ['src'], - //ignoreDuringBuilds: true, + ignoreDuringBuilds: true, }, typescript: { // !! WARN !! diff --git a/mscr-ui/src/modules/crosswalk-editor/schema-mockup.tsx b/mscr-ui/src/modules/crosswalk-editor/schema-mockup.tsx index a83388707..015352184 100644 --- a/mscr-ui/src/modules/crosswalk-editor/schema-mockup.tsx +++ b/mscr-ui/src/modules/crosswalk-editor/schema-mockup.tsx @@ -92,7 +92,7 @@ const functionsMockup: any = [ }, { name: 'Function to...', - uri: `http://uri.suomi.fi/datamodel/ns/mscr#propertiesToArrayFunc`, + uri: 'http://uri.suomi.fi/datamodel/ns/mscr#propertiesToArrayFunc', description: '', parameters: [ { @@ -3021,7 +3021,7 @@ export default function MockupSchemaLoader( open_access: { title: 'Open Access', description: - "Indicate whether the record's files are publicly accessible or not. In case of restricted access the uploaded files will only be accessible by the record's owner and the community administrators. Please note that the record's metadata is always publicly accessible. ", + 'Indicate whether the records files are publicly accessible or not. In case of restricted access the uploaded files will only be accessible by the records owner and the community administrators. Please note that the records metadata is always publicly accessible. ', type: 'boolean', }, embargo_date: { diff --git a/mscr-ui/src/pages/schema/[...pid].tsx b/mscr-ui/src/pages/schema/[...pid].tsx index 5055ae4d0..7880fc9cc 100644 --- a/mscr-ui/src/pages/schema/[...pid].tsx +++ b/mscr-ui/src/pages/schema/[...pid].tsx @@ -6,7 +6,6 @@ import Layout from '@app/common/components/layout'; import { SSRConfig } from 'next-i18next'; import { createCommonGetServerSideProps } from '@app/common/utils/create-getserversideprops'; import { - getServiceCategories, getRunningQueriesThunk as getServiceQueriesThunk, } from '@app/common/components/service-categories/service-categories.slice'; import { @@ -17,7 +16,6 @@ import { getRunningQueriesThunk as getInternalResourcesRunningQueriesThunk } fro import { getRunningQueriesThunk as getVisualizationRunningQueriesThunk } from '@app/common/components/visualization/visualization.slice'; import { useRouter } from 'next/router'; import { useGetSchemaQuery } from '@app/common/components/schema/schema.slice'; -import { Schema } from '@app/common/interfaces/schema.interface'; import UpdateWithFileModal from '@app/common/components/update-with-file-modal'; import Separator from 'yti-common-ui/components/separator'; import { BasicBlock, BasicBlockExtraWrapper } from 'yti-common-ui/block'; @@ -30,71 +28,11 @@ interface IndexPageProps extends CommonContextState { schemaId: string; } -// Example schema metadata -/* -{ - "created": "2023-11-17T12:52:59.337Z", - "modified": "2023-11-17T12:52:59.337Z", - "modifier": { - "id": "4ce70937-6fa4-49af-a229-b5f10328adb8", - "name": "fake user" - }, - "creator": { - "id": "4ce70937-6fa4-49af-a229-b5f10328adb8", - "name": "fake user" - }, - "type": null, - "prefix": null, - "status": "DRAFT", - "label": { - "en": "duwdu gwdf wugedwu" - }, - "description": { - "en": "wuey bwuey wyue" - }, - "languages": [ - "en" - ], - "organizations": [ - { - "id": "7d3a3c00-5a6b-489b-a3ed-63bb58c26a63", - "label": { - "fi": "Yhteentoimivuusalustan yllapito", - "sv": "Utvecklare av interoperabilitetsplattform", - "en": "Interoperability platform developers" - }, - "parentOrganization": null - } - ], - "groups": [], - "internalNamespaces": [], - "externalNamespaces": [], - "terminologies": [], - "codeLists": [], - "contact": null, - "documentation": {}, - "state": "DRAFT", - "visibility": "PUBLIC", - "format": "JSONSCHEMA", - "namespace": "http://test.com", - "versionLabel": "1", - "revisionOf": null, - "aggregationKey": "urn:IAMNOTAPID:e68ce802-38a0-4c6f-ba2d-41ad11561080", - "hasRevisions": null, - "revisions": null, - "variants": null, - "variants2": null, - "owner": [ - "7d3a3c00-5a6b-489b-a3ed-63bb58c26a63" - ], - "fileMetadata": [], - "pid": "urn:IAMNOTAPID:e68ce802-38a0-4c6f-ba2d-41ad11561080" -} -*/ + export default function SchemaPage(props: IndexPageProps) { const { query, asPath } = useRouter(); const schemaId = (query?.pid ?? '') as string; - const items: Schema[] = []; + const { data, isLoading, isSuccess, isError, error } = useGetSchemaQuery(schemaId); @@ -110,37 +48,38 @@ export default function SchemaPage(props: IndexPageProps) { </div> ); } else if (isSuccess) { - items.push(data); - schemaContent = ( - <div className="col-lg-12 mb-3 "> - <div className="card"> - <div className="card-body"> - <BasicBlock title={'Schema Name'}>{data.label?.en}</BasicBlock> - <BasicBlock title={'Schema Name'}> - {data.description?.en} - </BasicBlock> - <BasicBlock title={'Schema created'}>{data.created}</BasicBlock> - <BasicBlock title={'Schema Visibilty'}> - {data.visibility} - </BasicBlock> - <BasicBlock title={'Schema Version'}> - {data.versionLabel} - </BasicBlock> - <BasicBlock title={'Schema Status'}>{data.status}</BasicBlock> - <BasicBlock title={'Schema format'}>{data.format}</BasicBlock> + if (data) { + schemaContent = ( + <div className="col-lg-12 mb-3 "> + <div className="card"> + <div className="card-body"> + <BasicBlock title={'Schema Name'}>{data.label?.en}</BasicBlock> + <BasicBlock title={'Schema Name'}> + {data.description?.en} + </BasicBlock> + <BasicBlock title={'Schema created'}>{data.created}</BasicBlock> + <BasicBlock title={'Schema Visibilty'}> + {data.visibility} + </BasicBlock> + <BasicBlock title={'Schema Version'}> + {data.versionLabel} + </BasicBlock> + <BasicBlock title={'Schema Status'}>{data.status}</BasicBlock> + <BasicBlock title={'Schema format'}>{data.format}</BasicBlock> + </div> </div> + <Separator /> + <BasicBlockExtraWrapper> + <UpdateWithFileModal + pid={schemaId} + refetch={function (): void { + throw new Error('Function not implemented.'); + }} + /> + </BasicBlockExtraWrapper> </div> - <Separator /> - <BasicBlockExtraWrapper> - <UpdateWithFileModal - pid={schemaId} - refetch={function (): void { - throw new Error('Function not implemented.'); - }} - /> - </BasicBlockExtraWrapper> - </div> - ); + ); + } } return schemaContent; @@ -152,8 +91,7 @@ export default function SchemaPage(props: IndexPageProps) { user={props.user ?? undefined} fakeableUsers={props.fakeableUsers} > - {/*{renderSchema()}*/} - <SchemaView schemaId={schemaId} /> + </Layout> </CommonContextProvider> ); @@ -161,8 +99,8 @@ export default function SchemaPage(props: IndexPageProps) { export const getServerSideProps = createCommonGetServerSideProps( async ({ store, query, locale }) => { - store.dispatch(getServiceCategories.initiate(locale ?? 'fi')); - store.dispatch(getOrganizations.initiate(locale ?? 'fi')); + + store.dispatch(getOrganizations.initiate(locale ?? 'en')); await Promise.all(store.dispatch(getServiceQueriesThunk())); await Promise.all(store.dispatch(getOrgQueriesThunk())); @@ -171,8 +109,6 @@ export const getServerSideProps = createCommonGetServerSideProps( ); await Promise.all(store.dispatch(getVisualizationRunningQueriesThunk())); - return { - props: {}, - }; + return {}; } ); From f438c850924a2a0b64f693269986460a43c3cc61 Mon Sep 17 00:00:00 2001 From: rquazi <rumana.quazi@csc.fi> Date: Fri, 24 Nov 2023 15:21:50 +0200 Subject: [PATCH 14/15] Different style fix --- .../components/locale-chooser/use-locales.ts | 2 +- mscr-ui/public/supporting_eosc.png | Bin 0 -> 20685 bytes .../common/components/smart-header/index.tsx | 5 +- .../common/components/smart-header/logo.tsx | 8 +- .../src/common/interfaces/schema.interface.ts | 1 + .../common/utils/create-getserversideprops.ts | 1 - mscr-ui/src/modules/front-page/index.tsx | 13 ---- mscr-ui/src/modules/personal-home/index.tsx | 1 - mscr-ui/src/modules/search-screen/index.tsx | 4 +- .../search-screen/search-screen.styles.tsx | 2 +- mscr-ui/src/pages/schema/[...pid].tsx | 70 +++--------------- 11 files changed, 24 insertions(+), 83 deletions(-) create mode 100644 mscr-ui/public/supporting_eosc.png diff --git a/common-ui/components/locale-chooser/use-locales.ts b/common-ui/components/locale-chooser/use-locales.ts index 02f07e963..0c0c3ddea 100644 --- a/common-ui/components/locale-chooser/use-locales.ts +++ b/common-ui/components/locale-chooser/use-locales.ts @@ -21,9 +21,9 @@ export default function useLocales(): UseLocalesResult { } const locales: { locale: Locale; label: string }[] = [ + { locale: 'en', label: 'In English (EN)' }, { locale: 'fi', label: 'Suomeksi (FI)' }, { locale: 'sv', label: 'På svenska (SV)' }, - { locale: 'en', label: 'In English (EN)' }, ]; return { diff --git a/mscr-ui/public/supporting_eosc.png b/mscr-ui/public/supporting_eosc.png new file mode 100644 index 0000000000000000000000000000000000000000..c0762954d9b50c4130a7fb17cbf53645ecf16c3d GIT binary patch literal 20685 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 literal 0 HcmV?d00001 diff --git a/mscr-ui/src/common/components/smart-header/index.tsx b/mscr-ui/src/common/components/smart-header/index.tsx index 6dba6ec98..cc32232b9 100644 --- a/mscr-ui/src/common/components/smart-header/index.tsx +++ b/mscr-ui/src/common/components/smart-header/index.tsx @@ -119,8 +119,9 @@ export default function SmartHeader({ <HeaderContainer> <MarginContainer $breakpoint={breakpoint}> <HeaderWrapper $breakpoint={breakpoint}> + {renderLogo()} {renderHeaderSearch()} - {renderDesktopLocaleChooser()} + {/*renderDesktopLocaleChooser()*/} {renderMobileNavigationToggleButton()} {renderDesktopAuthenticationPanel()} </HeaderWrapper> @@ -143,7 +144,7 @@ export default function SmartHeader({ <div style={{ display: 'flex', padding: '20px 20px 0 0', gap: '10px' }} > - {renderDesktopLocaleChooser()} + {/*renderDesktopLocaleChooser()*/} {renderMobileNavigationToggleButton()} {renderDesktopAuthenticationPanel()} </div> diff --git a/mscr-ui/src/common/components/smart-header/logo.tsx b/mscr-ui/src/common/components/smart-header/logo.tsx index d60e8079c..7df3cdfcd 100644 --- a/mscr-ui/src/common/components/smart-header/logo.tsx +++ b/mscr-ui/src/common/components/smart-header/logo.tsx @@ -13,10 +13,10 @@ export default function Logo() { <Link href="/" passHref> <SuomiLink href="" aria-label={t('navigate-to-homepage')}> <Image - src="/logo.svg" - width="186" - height="32" - alt={t('interoperability-logo-title')} + src="/supporting_eosc.png" + width="180" + height="50" + alt={'Supporting EOSC'} /> </SuomiLink> </Link> diff --git a/mscr-ui/src/common/interfaces/schema.interface.ts b/mscr-ui/src/common/interfaces/schema.interface.ts index 8b81d0509..cc45453b5 100644 --- a/mscr-ui/src/common/interfaces/schema.interface.ts +++ b/mscr-ui/src/common/interfaces/schema.interface.ts @@ -18,6 +18,7 @@ export interface Schema { revision?: string; visibility?: string; created?: string; + modified: string; uri?: string; versionLabel?: string; } diff --git a/mscr-ui/src/common/utils/create-getserversideprops.ts b/mscr-ui/src/common/utils/create-getserversideprops.ts index 4e3e42e6c..ea036af26 100644 --- a/mscr-ui/src/common/utils/create-getserversideprops.ts +++ b/mscr-ui/src/common/utils/create-getserversideprops.ts @@ -89,7 +89,6 @@ export function createCommonGetServerSideProps< reduxKey: 'fakeableUsers', functionKey: 'getFakeableUsers', }); - console.log(fakeableUsers); //store.dispatch( // setAdminControls(process.env.ADMIN_CONTROLS_DISABLED === 'true') // ); diff --git a/mscr-ui/src/modules/front-page/index.tsx b/mscr-ui/src/modules/front-page/index.tsx index 2f27f165a..428e42193 100644 --- a/mscr-ui/src/modules/front-page/index.tsx +++ b/mscr-ui/src/modules/front-page/index.tsx @@ -21,8 +21,6 @@ export default function FrontPage() { const { t, i18n } = useTranslation('common'); const { isSmall } = useBreakpoints(); const { urlState } = useUrlState(); - const { data: serviceCategoriesData, refetch: refetchServiceCategoriesData } = - useGetServiceCategoriesQuery(i18n.language); const { data: organizationsData, refetch: refetchOrganizationsData } = useGetOrganizationsQuery(i18n.language); @@ -40,21 +38,10 @@ export default function FrontPage() { }); }, [organizationsData, i18n.language]); - const serviceCategories = useMemo(() => { - if (!serviceCategoriesData) { - return []; - } - - return serviceCategoriesData.map((category) => ({ - id: category.identifier, - label: category.label[i18n.language], - })); - }, [serviceCategoriesData, i18n.language]); // Need to decide what data we want to fetch loading the application const refetchInfo = () => { refetchOrganizationsData(); - refetchServiceCategoriesData(); }; return ( diff --git a/mscr-ui/src/modules/personal-home/index.tsx b/mscr-ui/src/modules/personal-home/index.tsx index 23a595d62..c611aeff2 100644 --- a/mscr-ui/src/modules/personal-home/index.tsx +++ b/mscr-ui/src/modules/personal-home/index.tsx @@ -9,7 +9,6 @@ export default function PersonalWorkspace({ pid, user }: PersonalHomeProps) { { return ( <> - <p>This is the personal content page for user {user?.firstName}</p> <FrontPage></FrontPage> </> ); diff --git a/mscr-ui/src/modules/search-screen/index.tsx b/mscr-ui/src/modules/search-screen/index.tsx index 34dfcfd4f..9349bf90f 100644 --- a/mscr-ui/src/modules/search-screen/index.tsx +++ b/mscr-ui/src/modules/search-screen/index.tsx @@ -16,6 +16,7 @@ import SearchFilterSet from '@app/common/components/search-filter-set'; import { Bucket, Facet, Filter } from '@app/common/interfaces/search.interface'; import { useTranslation } from 'next-i18next'; import { Grid } from '@mui/material'; +import Layout from 'yti-common-ui/layout/layout'; export default function SearchScreen() { const { urlState, patchUrlState } = useUrlState(); @@ -66,6 +67,7 @@ export default function SearchScreen() { } return ( + <SearchContainer> <Grid container justifyContent="space-between"> <Grid item xs={2}> @@ -91,6 +93,6 @@ export default function SearchScreen() { </CloseButton> </Grid> </Grid> - </SearchContainer> + </SearchContainer > ); } diff --git a/mscr-ui/src/modules/search-screen/search-screen.styles.tsx b/mscr-ui/src/modules/search-screen/search-screen.styles.tsx index e52ed2c74..00504f8a9 100644 --- a/mscr-ui/src/modules/search-screen/search-screen.styles.tsx +++ b/mscr-ui/src/modules/search-screen/search-screen.styles.tsx @@ -6,7 +6,7 @@ export const SearchContainer = styled(Block)` position: absolute; background-color: ${(props) => props.theme.suomifi.colors.depthLight3}; z-index: 1; - width: 80vw; + width: 100%; `; export const FacetsWrapper = styled(Block)` diff --git a/mscr-ui/src/pages/schema/[...pid].tsx b/mscr-ui/src/pages/schema/[...pid].tsx index 7880fc9cc..d634bfdfe 100644 --- a/mscr-ui/src/pages/schema/[...pid].tsx +++ b/mscr-ui/src/pages/schema/[...pid].tsx @@ -6,6 +6,7 @@ import Layout from '@app/common/components/layout'; import { SSRConfig } from 'next-i18next'; import { createCommonGetServerSideProps } from '@app/common/utils/create-getserversideprops'; import { + getServiceCategories, getRunningQueriesThunk as getServiceQueriesThunk, } from '@app/common/components/service-categories/service-categories.slice'; import { @@ -16,11 +17,12 @@ import { getRunningQueriesThunk as getInternalResourcesRunningQueriesThunk } fro import { getRunningQueriesThunk as getVisualizationRunningQueriesThunk } from '@app/common/components/visualization/visualization.slice'; import { useRouter } from 'next/router'; import { useGetSchemaQuery } from '@app/common/components/schema/schema.slice'; +import { Schema } from '@app/common/interfaces/schema.interface'; import UpdateWithFileModal from '@app/common/components/update-with-file-modal'; import Separator from 'yti-common-ui/components/separator'; import { BasicBlock, BasicBlockExtraWrapper } from 'yti-common-ui/block'; import { MscrUser } from '@app/common/interfaces/mscr-user.interface'; -import SchemaView from '@app/modules/schema-view'; +import SchemaView from "@app/modules/schema-view"; interface IndexPageProps extends CommonContextState { _netI18Next: SSRConfig; @@ -28,70 +30,18 @@ interface IndexPageProps extends CommonContextState { schemaId: string; } - export default function SchemaPage(props: IndexPageProps) { const { query, asPath } = useRouter(); const schemaId = (query?.pid ?? '') as string; - - - const { data, isLoading, isSuccess, isError, error } = - useGetSchemaQuery(schemaId); - - function renderSchema() { - let schemaContent; - if (isLoading) { - schemaContent = ( - <div className="d-flex justify-content-center"> - <div className="spinner-border" role="status"> - <span className="visually-hidden">Loading...</span> - </div> - </div> - ); - } else if (isSuccess) { - if (data) { - schemaContent = ( - <div className="col-lg-12 mb-3 "> - <div className="card"> - <div className="card-body"> - <BasicBlock title={'Schema Name'}>{data.label?.en}</BasicBlock> - <BasicBlock title={'Schema Name'}> - {data.description?.en} - </BasicBlock> - <BasicBlock title={'Schema created'}>{data.created}</BasicBlock> - <BasicBlock title={'Schema Visibilty'}> - {data.visibility} - </BasicBlock> - <BasicBlock title={'Schema Version'}> - {data.versionLabel} - </BasicBlock> - <BasicBlock title={'Schema Status'}>{data.status}</BasicBlock> - <BasicBlock title={'Schema format'}>{data.format}</BasicBlock> - </div> - </div> - <Separator /> - <BasicBlockExtraWrapper> - <UpdateWithFileModal - pid={schemaId} - refetch={function (): void { - throw new Error('Function not implemented.'); - }} - /> - </BasicBlockExtraWrapper> - </div> - ); - } - } - - return schemaContent; - } - + return ( <CommonContextProvider value={props}> <Layout user={props.user ?? undefined} fakeableUsers={props.fakeableUsers} > - + {/*{renderSchema()}*/} + <SchemaView schemaId={schemaId} /> </Layout> </CommonContextProvider> ); @@ -99,8 +49,8 @@ export default function SchemaPage(props: IndexPageProps) { export const getServerSideProps = createCommonGetServerSideProps( async ({ store, query, locale }) => { - - store.dispatch(getOrganizations.initiate(locale ?? 'en')); + store.dispatch(getServiceCategories.initiate(locale ?? 'fi')); + store.dispatch(getOrganizations.initiate(locale ?? 'fi')); await Promise.all(store.dispatch(getServiceQueriesThunk())); await Promise.all(store.dispatch(getOrgQueriesThunk())); @@ -109,6 +59,8 @@ export const getServerSideProps = createCommonGetServerSideProps( ); await Promise.all(store.dispatch(getVisualizationRunningQueriesThunk())); - return {}; + return { + props: {}, + }; } ); From 15c7e14364aa26d8730ae21b7bf86bfb7212178d Mon Sep 17 00:00:00 2001 From: rquazi <rumana.quazi@csc.fi> Date: Fri, 24 Nov 2023 15:24:04 +0200 Subject: [PATCH 15/15] Formatting changes --- mscr-ui/src/common/components/history-table/index.tsx | 10 +++++++++- mscr-ui/src/common/components/schema/schema.slice.tsx | 6 +++--- mscr-ui/src/modules/front-page/index.tsx | 1 - mscr-ui/src/modules/schema-view/index.tsx | 11 ++++++++--- .../src/modules/schema-view/version-history/index.tsx | 8 ++++++-- mscr-ui/src/modules/search-screen/index.tsx | 3 +-- .../modules/search-screen/search-screen.styles.tsx | 2 +- mscr-ui/src/pages/schema/[...pid].tsx | 4 ++-- 8 files changed, 30 insertions(+), 15 deletions(-) diff --git a/mscr-ui/src/common/components/history-table/index.tsx b/mscr-ui/src/common/components/history-table/index.tsx index 4a3e8ff53..3aab62bb8 100644 --- a/mscr-ui/src/common/components/history-table/index.tsx +++ b/mscr-ui/src/common/components/history-table/index.tsx @@ -6,7 +6,15 @@ import TableCell from '@mui/material/TableCell'; import TableBody from '@mui/material/TableBody'; import { Revision } from '@app/common/interfaces/schema.interface'; -export default function HistoryTable({ headers, revisions, ariaLabel }: { headers: Array<string>; revisions: Revision[]; ariaLabel: string }) { +export default function HistoryTable({ + headers, + revisions, + ariaLabel, +}: { + headers: Array<string>; + revisions: Revision[]; + ariaLabel: string; +}) { return ( <TableContainer> <Table aria-label={ariaLabel}> diff --git a/mscr-ui/src/common/components/schema/schema.slice.tsx b/mscr-ui/src/common/components/schema/schema.slice.tsx index 05956886b..249ad1aa5 100644 --- a/mscr-ui/src/common/components/schema/schema.slice.tsx +++ b/mscr-ui/src/common/components/schema/schema.slice.tsx @@ -7,7 +7,7 @@ import isHydrate from '@app/store/isHydrate'; import { Schema, SchemaFormType, - SchemaWithVersionInfo + SchemaWithVersionInfo, } from '@app/common/interfaces/schema.interface'; import { AnyNsRecord } from 'dns'; @@ -50,8 +50,8 @@ export const schemaApi = createApi({ getSchemaWithRevisions: builder.query<SchemaWithVersionInfo, string>({ query: (pid: string) => ({ url: `/schema/${pid}?includeVersionInfo=true`, - method: 'GET' - }) + method: 'GET', + }), }), postSchema: builder.mutation< string, diff --git a/mscr-ui/src/modules/front-page/index.tsx b/mscr-ui/src/modules/front-page/index.tsx index 428e42193..a1606a205 100644 --- a/mscr-ui/src/modules/front-page/index.tsx +++ b/mscr-ui/src/modules/front-page/index.tsx @@ -38,7 +38,6 @@ export default function FrontPage() { }); }, [organizationsData, i18n.language]); - // Need to decide what data we want to fetch loading the application const refetchInfo = () => { refetchOrganizationsData(); diff --git a/mscr-ui/src/modules/schema-view/index.tsx b/mscr-ui/src/modules/schema-view/index.tsx index 47301cb6a..0a37bf967 100644 --- a/mscr-ui/src/modules/schema-view/index.tsx +++ b/mscr-ui/src/modules/schema-view/index.tsx @@ -4,14 +4,19 @@ import Tab from '@mui/material/Tab'; import { SyntheticEvent, useState } from 'react'; import MetadataAndFiles from '@app/modules/schema-view/metadata-and-files'; import VersionHistory from '@app/modules/schema-view/version-history'; -import {useTranslation} from 'next-i18next'; +import { useTranslation } from 'next-i18next'; import { useGetSchemaWithRevisionsQuery } from '@app/common/components/schema/schema.slice'; export default function SchemaView({ schemaId }: { schemaId: string }) { const { t } = useTranslation('common'); - const { data: schemaDetails, isLoading, isSuccess, isError, error } = - useGetSchemaWithRevisionsQuery(schemaId); + const { + data: schemaDetails, + isLoading, + isSuccess, + isError, + error, + } = useGetSchemaWithRevisionsQuery(schemaId); const [selectedTab, setSelectedTab] = useState(0); function a11yProps(index: number) { diff --git a/mscr-ui/src/modules/schema-view/version-history/index.tsx b/mscr-ui/src/modules/schema-view/version-history/index.tsx index 7072be7b2..6552dc807 100644 --- a/mscr-ui/src/modules/schema-view/version-history/index.tsx +++ b/mscr-ui/src/modules/schema-view/version-history/index.tsx @@ -1,8 +1,12 @@ -import {useTranslation} from 'next-i18next'; +import { useTranslation } from 'next-i18next'; import { SchemaWithVersionInfo } from '@app/common/interfaces/schema.interface'; import HistoryTable from '@app/common/components/history-table'; -export default function VersionHistory({ schemaDetails }: {schemaDetails: SchemaWithVersionInfo}) { +export default function VersionHistory({ + schemaDetails, +}: { + schemaDetails: SchemaWithVersionInfo; +}) { const { t } = useTranslation('common'); const headers = [ diff --git a/mscr-ui/src/modules/search-screen/index.tsx b/mscr-ui/src/modules/search-screen/index.tsx index 9349bf90f..d623a6f4d 100644 --- a/mscr-ui/src/modules/search-screen/index.tsx +++ b/mscr-ui/src/modules/search-screen/index.tsx @@ -67,7 +67,6 @@ export default function SearchScreen() { } return ( - <SearchContainer> <Grid container justifyContent="space-between"> <Grid item xs={2}> @@ -93,6 +92,6 @@ export default function SearchScreen() { </CloseButton> </Grid> </Grid> - </SearchContainer > + </SearchContainer> ); } diff --git a/mscr-ui/src/modules/search-screen/search-screen.styles.tsx b/mscr-ui/src/modules/search-screen/search-screen.styles.tsx index 00504f8a9..61c38d093 100644 --- a/mscr-ui/src/modules/search-screen/search-screen.styles.tsx +++ b/mscr-ui/src/modules/search-screen/search-screen.styles.tsx @@ -6,7 +6,7 @@ export const SearchContainer = styled(Block)` position: absolute; background-color: ${(props) => props.theme.suomifi.colors.depthLight3}; z-index: 1; - width: 100%; + width: 100%; `; export const FacetsWrapper = styled(Block)` diff --git a/mscr-ui/src/pages/schema/[...pid].tsx b/mscr-ui/src/pages/schema/[...pid].tsx index d634bfdfe..61ba98613 100644 --- a/mscr-ui/src/pages/schema/[...pid].tsx +++ b/mscr-ui/src/pages/schema/[...pid].tsx @@ -22,7 +22,7 @@ import UpdateWithFileModal from '@app/common/components/update-with-file-modal'; import Separator from 'yti-common-ui/components/separator'; import { BasicBlock, BasicBlockExtraWrapper } from 'yti-common-ui/block'; import { MscrUser } from '@app/common/interfaces/mscr-user.interface'; -import SchemaView from "@app/modules/schema-view"; +import SchemaView from '@app/modules/schema-view'; interface IndexPageProps extends CommonContextState { _netI18Next: SSRConfig; @@ -33,7 +33,7 @@ interface IndexPageProps extends CommonContextState { export default function SchemaPage(props: IndexPageProps) { const { query, asPath } = useRouter(); const schemaId = (query?.pid ?? '') as string; - + return ( <CommonContextProvider value={props}> <Layout