From 69b232e1811e73e185947d31a178b6d3362add2b Mon Sep 17 00:00:00 2001
From: esikkala <esko.ikkala@aalto.fi>
Date: Tue, 7 Dec 2021 11:28:02 +0200
Subject: [PATCH] Convert client side configs to JSON

---
 .../perspectives/sampo/InstanceHomePage.js    |  11 +-
 .../sampo/InstanceHomePage.stories.js         |   2 +-
 .../perspectives/sampo/Main.stories.js        |   2 +-
 .../perspectives/sampo/MainCard.stories.js    |   2 +-
 .../perspectives/sampo/TopBar.stories.js      |   2 +-
 src/client/configs/PortalConfig.js            |  15 --
 src/client/configs/PortalConfig.json          |  15 ++
 .../configs/sampo/InstanceHomePageConfig.js   |  49 ----
 src/client/configs/sampo/PerspectiveConfig.js | 218 -----------------
 .../configs/sampo/PerspectiveConfig.json      | 226 ++++++++++++++++++
 .../sampo/PerspectiveConfigOnlyInfoPages.js   | 125 ----------
 .../sampo/PerspectiveConfigOnlyInfoPages.json | 128 ++++++++++
 src/client/containers/SemanticPortal.js       |  27 ++-
 src/client/epics/index.js                     |   2 +-
 src/client/helpers/helpers.js                 |  18 ++
 src/client/index.js                           |   2 +-
 src/client/reducers/index.js                  |   6 +-
 17 files changed, 422 insertions(+), 428 deletions(-)
 delete mode 100644 src/client/configs/PortalConfig.js
 create mode 100644 src/client/configs/PortalConfig.json
 delete mode 100644 src/client/configs/sampo/InstanceHomePageConfig.js
 delete mode 100644 src/client/configs/sampo/PerspectiveConfig.js
 create mode 100644 src/client/configs/sampo/PerspectiveConfig.json
 delete mode 100644 src/client/configs/sampo/PerspectiveConfigOnlyInfoPages.js
 create mode 100644 src/client/configs/sampo/PerspectiveConfigOnlyInfoPages.json

diff --git a/src/client/components/perspectives/sampo/InstanceHomePage.js b/src/client/components/perspectives/sampo/InstanceHomePage.js
index ba153d8c..99288ab9 100644
--- a/src/client/components/perspectives/sampo/InstanceHomePage.js
+++ b/src/client/components/perspectives/sampo/InstanceHomePage.js
@@ -7,6 +7,7 @@ import CircularProgress from '@material-ui/core/CircularProgress'
 import purple from '@material-ui/core/colors/purple'
 import PerspectiveTabs from '../../main_layout/PerspectiveTabs'
 import InstanceHomePageTable from '../../main_layout/InstanceHomePageTable'
+import { getLocalIDFromAppLocation, createURIfromLocalID } from '../../../helpers/helpers'
 import { Route, Redirect } from 'react-router-dom'
 import { has } from 'lodash'
 // const ApexChart = lazy(() => import('../../facet_results/ApexChart'))
@@ -61,7 +62,7 @@ class InstanceHomePage extends React.Component {
   }
 
   getLocalID = () => {
-    return this.props.instanceHomePageConfig.getLocalIDFromAppLocation({
+    return getLocalIDFromAppLocation({
       location: this.props.routeProps.location,
       perspectiveConfig: this.props.perspectiveConfig
     })
@@ -73,13 +74,13 @@ class InstanceHomePage extends React.Component {
   }
 
   fetchTableData = () => {
-    const { perspectiveConfig, instanceHomePageConfig } = this.props
-    const resultClass = perspectiveConfig.id
+    const { perspectiveConfig } = this.props
+    const { baseURI, URITemplate, id } = perspectiveConfig
     const localID = this.getLocalID()
     this.setState({ localID })
-    const uri = instanceHomePageConfig.createURIfromLocalID({ localID, perspectiveConfig })
+    const uri = createURIfromLocalID({ localID, baseURI, URITemplate })
     this.props.fetchByURI({
-      resultClass,
+      resultClass: id,
       facetClass: null,
       variant: null,
       uri
diff --git a/src/client/components/perspectives/sampo/InstanceHomePage.stories.js b/src/client/components/perspectives/sampo/InstanceHomePage.stories.js
index 6f4b1a21..55e4aad9 100644
--- a/src/client/components/perspectives/sampo/InstanceHomePage.stories.js
+++ b/src/client/components/perspectives/sampo/InstanceHomePage.stories.js
@@ -2,8 +2,8 @@ import React from 'react'
 import { useSelector } from 'react-redux'
 import { useLocation } from 'react-router-dom'
 import InstanceHomePage, { InstanceHomePageComponent } from './InstanceHomePage'
-import { perspectiveConfig } from '../../../configs/sampo/PerspectiveConfig'
 import { data, sparqlQuery } from './InstanceHomePage.testData.js'
+const { default: perspectiveConfig } = await import('../../../configs/sampo/PerspectiveConfig.json')
 
 export default {
   component: InstanceHomePageComponent,
diff --git a/src/client/components/perspectives/sampo/Main.stories.js b/src/client/components/perspectives/sampo/Main.stories.js
index 47e90298..00a49b28 100644
--- a/src/client/components/perspectives/sampo/Main.stories.js
+++ b/src/client/components/perspectives/sampo/Main.stories.js
@@ -1,6 +1,6 @@
 import React from 'react'
 import Main from './Main'
-import { perspectiveConfig } from '../../../configs/sampo/PerspectiveConfig'
+const { default: perspectiveConfig } = await import('../../../configs/sampo/PerspectiveConfig.json')
 
 export default {
   component: Main,
diff --git a/src/client/components/perspectives/sampo/MainCard.stories.js b/src/client/components/perspectives/sampo/MainCard.stories.js
index 06efb262..69ae562a 100644
--- a/src/client/components/perspectives/sampo/MainCard.stories.js
+++ b/src/client/components/perspectives/sampo/MainCard.stories.js
@@ -1,7 +1,7 @@
 import React from 'react'
 import MainCard from './MainCard'
-import { perspectiveConfig } from '../../../configs/sampo/PerspectiveConfig'
 import Center from '../../../../../.storybook/Center'
+const { default: perspectiveConfig } = await import('../../../configs/sampo/PerspectiveConfig.json')
 
 export default {
   component: MainCard,
diff --git a/src/client/components/perspectives/sampo/TopBar.stories.js b/src/client/components/perspectives/sampo/TopBar.stories.js
index 63ab31d4..ffb5fb56 100644
--- a/src/client/components/perspectives/sampo/TopBar.stories.js
+++ b/src/client/components/perspectives/sampo/TopBar.stories.js
@@ -2,7 +2,7 @@ import React from 'react'
 import TopBar from './TopBar'
 import { useSelector } from 'react-redux'
 import { useLocation } from 'react-router-dom'
-import { perspectiveConfig } from '../../../configs/sampo/PerspectiveConfig'
+const { default: perspectiveConfig } = await import('../../../configs/sampo/PerspectiveConfig.json')
 
 export default {
   component: TopBar,
diff --git a/src/client/configs/PortalConfig.js b/src/client/configs/PortalConfig.js
deleted file mode 100644
index ea2ebf2c..00000000
--- a/src/client/configs/PortalConfig.js
+++ /dev/null
@@ -1,15 +0,0 @@
-export default {
-  portalID: 'sampo',
-  localeConfig: [
-    {
-      id: 'en',
-      label: 'English',
-      filename: 'localeEN.json'
-    },
-    {
-      id: 'fi',
-      label: 'English',
-      filename: 'localeFI.json'
-    }
-  ]
-}
diff --git a/src/client/configs/PortalConfig.json b/src/client/configs/PortalConfig.json
new file mode 100644
index 00000000..f9636ecc
--- /dev/null
+++ b/src/client/configs/PortalConfig.json
@@ -0,0 +1,15 @@
+{
+    "portalID": "sampo",
+    "localeConfig": [
+        {
+            "id": "en",
+            "label": "English",
+            "filename": "localeEN.json"
+        },
+        {
+            "id": "fi",
+            "label": "English",
+            "filename": "localeFI.json"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/client/configs/sampo/InstanceHomePageConfig.js b/src/client/configs/sampo/InstanceHomePageConfig.js
deleted file mode 100644
index 0e544590..00000000
--- a/src/client/configs/sampo/InstanceHomePageConfig.js
+++ /dev/null
@@ -1,49 +0,0 @@
-export const getLocalIDFromAppLocation = ({ location, perspectiveConfig }) => {
-  const locationArr = location.pathname.split('/')
-  let localID = locationArr.pop()
-  perspectiveConfig.instancePageTabs.forEach(tab => {
-    if (localID === tab.id) {
-      localID = locationArr.pop() // pop again if tab id
-    }
-  })
-  return localID
-}
-
-export const createURIfromLocalID = ({ localID, perspectiveConfig }) => {
-  let uri = ''
-  const base = 'http://ldf.fi/mmm'
-  const resultClass = perspectiveConfig.id
-  switch (resultClass) {
-    case 'perspective1':
-      uri = `${base}/manifestation_singleton/${localID}`
-      break
-    case 'perspective2':
-      uri = `${base}/work/${localID}`
-      break
-    case 'perspective3':
-      uri = `${base}/event/${localID}`
-      break
-    case 'manuscripts':
-      uri = `${base}/manifestation_singleton/${localID}`
-      break
-    case 'expressions':
-      uri = `${base}/expression/${localID}`
-      break
-    case 'collections':
-      uri = `${base}/collection/${localID}`
-      break
-    case 'works':
-      uri = `${base}/work/${localID}`
-      break
-    case 'events':
-      uri = `${base}/event/${localID}`
-      break
-    case 'actors':
-      uri = `${base}/actor/${localID}`
-      break
-    case 'places':
-      uri = `${base}/place/${localID}`
-      break
-  }
-  return uri
-}
diff --git a/src/client/configs/sampo/PerspectiveConfig.js b/src/client/configs/sampo/PerspectiveConfig.js
deleted file mode 100644
index fd3f2ac1..00000000
--- a/src/client/configs/sampo/PerspectiveConfig.js
+++ /dev/null
@@ -1,218 +0,0 @@
-export const perspectiveConfig = [
-  {
-    id: 'perspective1',
-    frontPageImage: 'main_page/manuscripts-452x262.jpg',
-    defaultActiveFacets: [],
-    defaultTab: 'table',
-    defaultInstancePageTab: 'table',
-    tabs: [
-      {
-        id: 'table',
-        value: 0,
-        icon: 'CalendarViewDay'
-      },
-      {
-        id: 'production_places',
-        value: 1,
-        icon: 'AddLocation'
-      },
-      {
-        id: 'production_places_heatmap',
-        value: 2,
-        icon: 'AddLocation'
-      },
-      {
-        id: 'production_dates',
-        value: 3,
-        icon: 'ShowChart'
-      },
-      {
-        id: 'event_dates',
-        value: 4,
-        icon: 'ShowChart'
-      },
-      {
-        id: 'last_known_locations',
-        value: 5,
-        icon: 'LocationOn'
-      },
-      {
-        id: 'migrations',
-        value: 6,
-        icon: 'Redo'
-      },
-      {
-        id: 'network',
-        value: 7,
-        icon: 'BubbleChart'
-      },
-      {
-        id: 'export',
-        value: 8,
-        icon: 'CloudDownload'
-      }
-    ],
-    instancePageTabs: [
-      {
-        id: 'table',
-        value: 0,
-        icon: 'CalendarViewDay'
-      },
-      {
-        id: 'network',
-        value: 1,
-        icon: 'BubbleChart'
-      },
-      {
-        id: 'export',
-        value: 2,
-        icon: 'CloudDownload'
-      }
-    ]
-  },
-  {
-    id: 'perspective2',
-    frontPageImage: 'main_page/works-452x262.jpg',
-    defaultActiveFacets: ['prefLabel'],
-    tabs: [
-      {
-        id: 'table',
-        value: 0,
-        icon: 'CalendarViewDay'
-      },
-      {
-        id: 'export',
-        value: 1,
-        icon: 'CloudDownload'
-      }
-    ],
-    instancePageTabs: [
-      {
-        id: 'table',
-        value: 0,
-        icon: 'CalendarViewDay'
-      },
-      {
-        id: 'export',
-        value: 1,
-        icon: 'CloudDownload'
-      }
-    ]
-  },
-  {
-    id: 'perspective3',
-    frontPageImage: 'main_page/events-452x262.jpg',
-    defaultActiveFacets: new Set(['prefLabel']),
-    tabs: [
-      {
-        id: 'table',
-        value: 0,
-        icon: 'CalendarViewDay'
-      },
-      {
-        id: 'map',
-        value: 1,
-        icon: 'AddLocation'
-      },
-
-      {
-        id: 'export',
-        value: 2,
-        icon: 'CloudDownload'
-      }
-    ],
-    instancePageTabs: [
-      {
-        id: 'table',
-        value: 0,
-        icon: 'CalendarViewDay'
-      },
-
-      {
-        id: 'export',
-        value: 1,
-        icon: 'CloudDownload'
-      }
-    ]
-  },
-  {
-    id: 'finds',
-    isHidden: true,
-    frontPageImage: null,
-    defaultActiveFacets: new Set(['prefLabel']),
-    tabs: [
-      {
-        id: 'table',
-        value: 0,
-        icon: 'CalendarViewDay'
-      },
-      {
-        id: 'map',
-        value: 1,
-        icon: 'AddLocation'
-      },
-      {
-        id: 'export',
-        value: 2,
-        icon: 'CloudDownload'
-      }
-    ],
-    instancePageTabs: [
-      {
-        id: 'table',
-        value: 0,
-        icon: 'CalendarViewDay'
-      },
-      {
-        id: 'recommendations',
-        value: 1,
-        icon: 'Star'
-      },
-      {
-        id: 'export',
-        value: 2,
-        icon: 'CloudDownload'
-      }
-    ]
-  },
-  {
-    id: 'fullTextSearch',
-    isHidden: true,
-    searchMode: 'full-text-search'
-  },
-  {
-    id: 'clientFSPlaces',
-    frontPageImage: 'main_page/places-452x262.jpg',
-    defaultActiveFacets: ['datasetSelector'],
-    searchMode: 'federated-search',
-    tabs: [
-      {
-        id: 'table',
-        value: 0,
-        icon: 'CalendarViewDay'
-      },
-      {
-        id: 'map_clusters',
-        value: 1,
-        icon: 'TripOrigin'
-      },
-      {
-        id: 'map_markers',
-        value: 2,
-        icon: 'LocationOn'
-      },
-      {
-        id: 'statistics',
-        value: 3,
-        icon: 'PieChart'
-      },
-      {
-        id: 'download',
-        value: 4,
-        icon: 'CloudDownload'
-      }
-    ]
-  }
-]
-
-// console.log(JSON.stringify(perspectiveConfig))
diff --git a/src/client/configs/sampo/PerspectiveConfig.json b/src/client/configs/sampo/PerspectiveConfig.json
new file mode 100644
index 00000000..b4d25578
--- /dev/null
+++ b/src/client/configs/sampo/PerspectiveConfig.json
@@ -0,0 +1,226 @@
+[
+    {
+        "id": "perspective1",
+        "baseURI": "http://ldf.fi/mmm",
+        "URITemplate": "<BASE_URI>/manifestation_singleton/<LOCAL_ID>",
+        "frontPageImage": "main_page/manuscripts-452x262.jpg",
+        "defaultActiveFacets": [],
+        "defaultTab": "table",
+        "defaultInstancePageTab": "table",
+        "tabs": [
+            {
+                "id": "table",
+                "value": 0,
+                "icon": "CalendarViewDay"
+            },
+            {
+                "id": "production_places",
+                "value": 1,
+                "icon": "AddLocation"
+            },
+            {
+                "id": "production_places_heatmap",
+                "value": 2,
+                "icon": "AddLocation"
+            },
+            {
+                "id": "production_dates",
+                "value": 3,
+                "icon": "ShowChart"
+            },
+            {
+                "id": "event_dates",
+                "value": 4,
+                "icon": "ShowChart"
+            },
+            {
+                "id": "last_known_locations",
+                "value": 5,
+                "icon": "LocationOn"
+            },
+            {
+                "id": "migrations",
+                "value": 6,
+                "icon": "Redo"
+            },
+            {
+                "id": "network",
+                "value": 7,
+                "icon": "BubbleChart"
+            },
+            {
+                "id": "export",
+                "value": 8,
+                "icon": "CloudDownload"
+            }
+        ],
+        "instancePageTabs": [
+            {
+                "id": "table",
+                "value": 0,
+                "icon": "CalendarViewDay"
+            },
+            {
+                "id": "network",
+                "value": 1,
+                "icon": "BubbleChart"
+            },
+            {
+                "id": "export",
+                "value": 2,
+                "icon": "CloudDownload"
+            }
+        ]
+    },
+    {
+        "id": "perspective2",
+        "baseURI": "http://ldf.fi/mmm",
+        "URITemplate": "<BASE_URI>/work/<LOCAL_ID>",
+        "frontPageImage": "main_page/works-452x262.jpg",
+        "defaultActiveFacets": [
+            "prefLabel"
+        ],
+        "tabs": [
+            {
+                "id": "table",
+                "value": 0,
+                "icon": "CalendarViewDay"
+            },
+            {
+                "id": "export",
+                "value": 1,
+                "icon": "CloudDownload"
+            }
+        ],
+        "instancePageTabs": [
+            {
+                "id": "table",
+                "value": 0,
+                "icon": "CalendarViewDay"
+            },
+            {
+                "id": "export",
+                "value": 1,
+                "icon": "CloudDownload"
+            }
+        ]
+    },
+    {
+        "id": "perspective3",
+        "baseURI": "http://ldf.fi/mmm",
+        "URITemplate": "<BASE_URI>/event/<LOCAL_ID>",
+        "frontPageImage": "main_page/events-452x262.jpg",
+        "defaultActiveFacets": [],
+        "tabs": [
+            {
+                "id": "table",
+                "value": 0,
+                "icon": "CalendarViewDay"
+            },
+            {
+                "id": "map",
+                "value": 1,
+                "icon": "AddLocation"
+            },
+            {
+                "id": "export",
+                "value": 2,
+                "icon": "CloudDownload"
+            }
+        ],
+        "instancePageTabs": [
+            {
+                "id": "table",
+                "value": 0,
+                "icon": "CalendarViewDay"
+            },
+            {
+                "id": "export",
+                "value": 1,
+                "icon": "CloudDownload"
+            }
+        ]
+    },
+    {
+        "id": "finds",
+        "baseURI": "http://ldf.fi/findsampo",
+        "URITemplate": "<BASE_URI>/find/<LOCAL_ID>",
+        "isHidden": true,
+        "frontPageImage": null,
+        "defaultActiveFacets": [],
+        "tabs": [
+            {
+                "id": "table",
+                "value": 0,
+                "icon": "CalendarViewDay"
+            },
+            {
+                "id": "map",
+                "value": 1,
+                "icon": "AddLocation"
+            },
+            {
+                "id": "export",
+                "value": 2,
+                "icon": "CloudDownload"
+            }
+        ],
+        "instancePageTabs": [
+            {
+                "id": "table",
+                "value": 0,
+                "icon": "CalendarViewDay"
+            },
+            {
+                "id": "recommendations",
+                "value": 1,
+                "icon": "Star"
+            },
+            {
+                "id": "export",
+                "value": 2,
+                "icon": "CloudDownload"
+            }
+        ]
+    },
+    {
+        "id": "fullTextSearch",
+        "isHidden": true,
+        "searchMode": "full-text-search"
+    },
+    {
+        "id": "clientFSPlaces",
+        "frontPageImage": "main_page/places-452x262.jpg",
+        "defaultActiveFacets": [
+            "datasetSelector"
+        ],
+        "searchMode": "federated-search",
+        "tabs": [
+            {
+                "id": "table",
+                "value": 0,
+                "icon": "CalendarViewDay"
+            },
+            {
+                "id": "map_clusters",
+                "value": 1,
+                "icon": "TripOrigin"
+            },
+            {
+                "id": "map_markers",
+                "value": 2,
+                "icon": "LocationOn"
+            },
+            {
+                "id": "statistics",
+                "value": 3,
+                "icon": "PieChart"
+            },
+            {
+                "id": "download",
+                "value": 4,
+                "icon": "CloudDownload"
+            }
+        ]
+    }
+]
\ No newline at end of file
diff --git a/src/client/configs/sampo/PerspectiveConfigOnlyInfoPages.js b/src/client/configs/sampo/PerspectiveConfigOnlyInfoPages.js
deleted file mode 100644
index 64b039a1..00000000
--- a/src/client/configs/sampo/PerspectiveConfigOnlyInfoPages.js
+++ /dev/null
@@ -1,125 +0,0 @@
-import React from 'react'
-import CalendarViewDayIcon from '@material-ui/icons/CalendarViewDay'
-import CloudDownloadIcon from '@material-ui/icons/CloudDownload'
-
-export const perspectiveConfigOnlyInfoPages = [
-  {
-    id: 'manuscripts',
-    perspectiveDescHeight: 160,
-    instancePageTabs: [
-      {
-        id: 'table',
-        value: 0,
-        icon: <CalendarViewDayIcon />
-      },
-
-      {
-        id: 'export',
-        value: 1,
-        icon: <CloudDownloadIcon />
-      }
-    ]
-  },
-  {
-    id: 'works',
-    perspectiveDescHeight: 160,
-    instancePageTabs: [
-      {
-        id: 'table',
-        value: 0,
-        icon: <CalendarViewDayIcon />
-      },
-
-      {
-        id: 'export',
-        value: 1,
-        icon: <CloudDownloadIcon />
-      }
-    ]
-  },
-  {
-    id: 'events',
-    perspectiveDescHeight: 160,
-    instancePageTabs: [
-      {
-        id: 'table',
-        value: 0,
-        icon: <CalendarViewDayIcon />
-      },
-
-      {
-        id: 'export',
-        value: 1,
-        icon: <CloudDownloadIcon />
-      }
-    ]
-  },
-  {
-    id: 'actors',
-    perspectiveDescHeight: 160,
-    instancePageTabs: [
-      {
-        id: 'table',
-        value: 0,
-        icon: <CalendarViewDayIcon />
-      },
-
-      {
-        id: 'export',
-        value: 1,
-        icon: <CloudDownloadIcon />
-      }
-    ]
-  },
-  {
-    id: 'places',
-    perspectiveDescHeight: 160,
-    instancePageTabs: [
-      {
-        id: 'table',
-        value: 0,
-        icon: <CalendarViewDayIcon />
-      },
-
-      {
-        id: 'export',
-        value: 1,
-        icon: <CloudDownloadIcon />
-      }
-    ]
-  },
-  {
-    id: 'expressions',
-    perspectiveDescHeight: 160,
-    instancePageTabs: [
-      {
-        id: 'table',
-        value: 0,
-        icon: <CalendarViewDayIcon />
-      },
-
-      {
-        id: 'export',
-        value: 1,
-        icon: <CloudDownloadIcon />
-      }
-    ]
-  },
-  {
-    id: 'collections',
-    perspectiveDescHeight: 160,
-    instancePageTabs: [
-      {
-        id: 'table',
-        value: 0,
-        icon: <CalendarViewDayIcon />
-      },
-
-      {
-        id: 'export',
-        value: 1,
-        icon: <CloudDownloadIcon />
-      }
-    ]
-  }
-]
diff --git a/src/client/configs/sampo/PerspectiveConfigOnlyInfoPages.json b/src/client/configs/sampo/PerspectiveConfigOnlyInfoPages.json
new file mode 100644
index 00000000..cfe1c0e4
--- /dev/null
+++ b/src/client/configs/sampo/PerspectiveConfigOnlyInfoPages.json
@@ -0,0 +1,128 @@
+[
+  {
+    "id": "manuscripts",
+    "baseURI": "http://ldf.fi/mmm",
+    "URITemplate": "<BASE_URI>/manifestation_singleton/<LOCAL_ID>",
+    "perspectiveDescHeight": 160,
+    "instancePageTabs": [
+      {
+        "id": "table",
+        "value": 0,
+        "icon": "CalendarViewDay"
+      },
+      {
+        "id": "export",
+        "value": 1,
+        "icon": "CloudDownload"
+      }
+    ]
+  },
+  {
+    "id": "works",
+    "baseURI": "http://ldf.fi/mmm",
+    "URITemplate": "<BASE_URI>/work/<LOCAL_ID>",
+    "perspectiveDescHeight": 160,
+    "instancePageTabs": [
+      {
+        "id": "table",
+        "value": 0,
+        "icon": "CalendarViewDay"
+      },
+      {
+        "id": "export",
+        "value": 1,
+        "icon": "CloudDownload"
+      }
+    ]
+  },
+  {
+    "id": "events",
+    "baseURI": "http://ldf.fi/mmm",
+    "URITemplate": "<BASE_URI>/event/<LOCAL_ID>",
+    "perspectiveDescHeight": 160,
+    "instancePageTabs": [
+      {
+        "id": "table",
+        "value": 0,
+        "icon": "CalendarViewDay"
+      },
+      {
+        "id": "export",
+        "value": 1,
+        "icon": "CloudDownload"
+      }
+    ]
+  },
+  {
+    "id": "actors",
+    "baseURI": "http://ldf.fi/mmm",
+    "URITemplate": "<BASE_URI>/actor/<LOCAL_ID>",
+    "perspectiveDescHeight": 160,
+    "instancePageTabs": [
+      {
+        "id": "table",
+        "value": 0,
+        "icon": "CalendarViewDay"
+      },
+      {
+        "id": "export",
+        "value": 1,
+        "icon": "CloudDownload"
+      }
+    ]
+  },
+  {
+    "id": "places",
+    "baseURI": "http://ldf.fi/mmm",
+    "URITemplate": "<BASE_URI>/place/<LOCAL_ID>",
+    "perspectiveDescHeight": 160,
+    "instancePageTabs": [
+      {
+        "id": "table",
+        "value": 0,
+        "icon": "CalendarViewDay"
+      },
+      {
+        "id": "export",
+        "value": 1,
+        "icon": "CloudDownload"
+      }
+    ]
+  },
+  {
+    "id": "expressions",
+    "baseURI": "http://ldf.fi/mmm",
+    "URITemplate": "<BASE_URI>/expression/<LOCAL_ID>",
+    "perspectiveDescHeight": 160,
+    "instancePageTabs": [
+      {
+        "id": "table",
+        "value": 0,
+        "icon": "CalendarViewDay"
+      },
+      {
+        "id": "export",
+        "value": 1,
+        "icon": "CloudDownload"
+      }
+    ]
+  },
+  {
+    "id": "collections",
+    "baseURI": "http://ldf.fi/mmm",
+    "URITemplate": "<BASE_URI>/collection/<LOCAL_ID>",
+    "perspectiveDescHeight": 160,
+    "instancePageTabs": [
+      {
+        "id": "table",
+        "value": 0,
+        "icon": "CalendarViewDay"
+      },
+      {
+        "id": "export",
+        "value": 1,
+        "icon": "CloudDownload"
+      }
+    ]
+  }
+]
\ No newline at end of file
diff --git a/src/client/containers/SemanticPortal.js b/src/client/containers/SemanticPortal.js
index 90280e6d..7ff8fbb2 100644
--- a/src/client/containers/SemanticPortal.js
+++ b/src/client/containers/SemanticPortal.js
@@ -50,11 +50,10 @@ import {
 import { filterResults } from '../selectors'
 
 // ** Portal configuration **
-import portalConfig from '../configs/PortalConfig'
+import portalConfig from '../configs/PortalConfig.json'
 const { portalID } = portalConfig
-const { perspectiveConfig } = await import(`../configs/${portalID}/PerspectiveConfig`)
-const { perspectiveConfigOnlyInfoPages } = await import(`../configs/${portalID}/PerspectiveConfigOnlyInfoPages`)
-const instanceHomePageConfig = await import(`../configs/${portalID}/InstanceHomePageConfig`)
+const { default: perspectiveConfig } = await import(`../configs/${portalID}/PerspectiveConfig.json`)
+const { default: perspectiveConfigOnlyInfoPages } = await import(`../configs/${portalID}/PerspectiveConfigOnlyInfoPages.json`)
 const {
   rootUrl,
   layoutConfig,
@@ -88,7 +87,21 @@ for (const perspective of perspectiveConfig) {
       tab.icon = <MuiIcon iconName={tab.icon} />
     }
   }
-  perspective.defaultActiveFacets = new Set(perspective.defaultActiveFacets)
+  if (has(perspective, 'instancePageTabs')) {
+    for (const tab of perspective.instancePageTabs) {
+      tab.icon = <MuiIcon iconName={tab.icon} />
+    }
+  }
+  if (has(perspective, 'defaultActiveFacets')) {
+    perspective.defaultActiveFacets = new Set(perspective.defaultActiveFacets)
+  }
+}
+for (const perspective of perspectiveConfigOnlyInfoPages) {
+  if (has(perspective, 'instancePageTabs')) {
+    for (const tab of perspective.instancePageTabs) {
+      tab.icon = <MuiIcon iconName={tab.icon} />
+    }
+  }
 }
 const barChartConfig = await import(`../configs/${portalID}/ApexCharts/BarChartConfig`)
 const lineChartConfig = await import(`../configs/${portalID}/ApexCharts/LineChartConfig`)
@@ -500,7 +513,7 @@ const SemanticPortal = props => {
                                   pieChartConfig={pieChartConfig}
                                   leafletConfig={leafletConfig}
                                   networkConfig={networkConfig}
-                                  instanceHomePageConfig={instanceHomePageConfig}
+                                  portalConfig={portalConfig}
                                 />
                               </Grid>
                             </Grid>
@@ -573,7 +586,7 @@ const SemanticPortal = props => {
                             pieChartConfig={pieChartConfig}
                             leafletConfig={leafletConfig}
                             networkConfig={networkConfig}
-                            instanceHomePageConfig={instanceHomePageConfig}
+                            portalConfig={portalConfig}
                           />
                         </Grid>
                       </Grid>
diff --git a/src/client/epics/index.js b/src/client/epics/index.js
index 2f185b19..f789c202 100644
--- a/src/client/epics/index.js
+++ b/src/client/epics/index.js
@@ -51,7 +51,7 @@ import {
   updateKnowledgeGraphMetadata,
   fetchGeoJSONLayersFailed
 } from '../actions'
-import portalConfig from '../configs/PortalConfig'
+import portalConfig from '../configs/PortalConfig.json'
 const { portalID, localeConfig } = portalConfig
 const { documentFinderAPIUrl } = await import(`../configs/${portalID}/GeneralConfig`)
 export const availableLocales = {}
diff --git a/src/client/helpers/helpers.js b/src/client/helpers/helpers.js
index 8865d9a4..35e6591b 100644
--- a/src/client/helpers/helpers.js
+++ b/src/client/helpers/helpers.js
@@ -158,3 +158,21 @@ export const generateLabelForMissingValue = ({ facetClass, facetID }) => {
   return intl.get(`perspectives.${facetClass}.properties.${facetID}.missingValueLabel`) ||
    intl.get('facetBar.defaultMissingValueLabel') || 'Unknown'
 }
+
+export const getLocalIDFromAppLocation = ({ location, perspectiveConfig }) => {
+  const locationArr = location.pathname.split('/')
+  let localID = locationArr.pop()
+  perspectiveConfig.instancePageTabs.forEach(tab => {
+    if (localID === tab.id) {
+      localID = locationArr.pop() // pop again if tab id
+    }
+  })
+  return localID
+}
+
+export const createURIfromLocalID = ({ localID, baseURI, URITemplate }) => {
+  let uri = URITemplate
+  uri = uri.replaceAll('<BASE_URI>', baseURI)
+  uri = uri.replaceAll('<LOCAL_ID>', localID)
+  return uri
+}
diff --git a/src/client/index.js b/src/client/index.js
index eb77904b..660e39aa 100644
--- a/src/client/index.js
+++ b/src/client/index.js
@@ -18,7 +18,7 @@ import '@nosferatu500/react-sortable-tree/style.css'
 import 'react-redux-toastr/lib/css/react-redux-toastr.min.css'
 import 'mapbox-gl/dist/mapbox-gl.css'
 
-import portalConfig from './configs/PortalConfig'
+import portalConfig from './configs/PortalConfig.json'
 const { portalID } = portalConfig
 const { defaultLocale } = await import(`./configs/${portalID}/GeneralConfig`)
 
diff --git a/src/client/reducers/index.js b/src/client/reducers/index.js
index 08913d92..515069db 100644
--- a/src/client/reducers/index.js
+++ b/src/client/reducers/index.js
@@ -1,4 +1,4 @@
-import portalConfig from '../configs/PortalConfig'
+import portalConfig from '../configs/PortalConfig.json'
 import { combineReducers } from 'redux'
 import { reducer as toastrReducer } from 'react-redux-toastr'
 
@@ -17,8 +17,8 @@ const reducers = {
 
 // Import and add portal spefic reducers:
 const { portalID } = portalConfig
-const { perspectiveConfig } = await import(`../configs/${portalID}/PerspectiveConfig`)
-const { perspectiveConfigOnlyInfoPages } = await import(`../configs/${portalID}/PerspectiveConfigOnlyInfoPages`)
+const { default: perspectiveConfig } = await import(`../configs/${portalID}/PerspectiveConfig.json`)
+const { default: perspectiveConfigOnlyInfoPages } = await import(`../configs/${portalID}/PerspectiveConfigOnlyInfoPages.json`)
 for (const perspective of perspectiveConfig) {
   if (perspective.searchMode && perspective.searchMode === 'federated-search') {
     const { default: reducer } = await import(`./${portalID}/clientSideFacetedSearch`)
-- 
GitLab