From a01e34d1175c259c2a31dfb23c2aeedb69abee84 Mon Sep 17 00:00:00 2001
From: Sunny Aggarwal
Date: Mon, 5 Oct 2026 20:25:16 +0530
Subject: [PATCH 1/2] OpenConceptLab/ocl_online#374 | using path routing in
place of hash routing
---
.eslintrc.json | 1 +
public/index.html | 37 ++++-----
src/common/history.js | 81 +++++++++++++++++++
src/common/utils.js | 36 ++++++---
src/components/app/App.jsx | 7 +-
src/components/app/HeaderControls.jsx | 2 +-
src/components/app/LeftMenu.jsx | 8 +-
src/components/common/About.jsx | 4 +-
src/components/common/BaseEntityChip.jsx | 2 +-
.../common/EntityAttributesDialog.jsx | 2 +-
src/components/common/Events.jsx | 2 +-
src/components/common/OCLLogo.jsx | 2 +-
src/components/common/OwnerButton.jsx | 2 +-
src/components/common/ResourceReferences.jsx | 2 +-
src/components/concepts/Associations.jsx | 3 +-
src/components/concepts/ConceptDetails.jsx | 2 +-
src/components/concepts/ConceptForm.jsx | 5 +-
src/components/concepts/ConceptHeader.jsx | 2 +-
src/components/concepts/History.jsx | 4 +-
src/components/dashboard/DashboardEvents.jsx | 2 +-
src/components/dashboard/UserDashboard.jsx | 2 +-
src/components/errors/Error403.jsx | 2 +-
src/components/errors/ErrorBoundary.jsx | 3 +-
.../mappings/AssociationRowOptions.jsx | 11 +--
src/components/mappings/MappingDetails.jsx | 2 +-
src/components/mappings/MappingForm.jsx | 5 +-
src/components/mappings/MappingHeader.jsx | 2 +-
.../mappings/SortableAssociationRow.jsx | 3 +-
src/components/orgs/MemberList.jsx | 2 +-
src/components/orgs/OrgHeader.jsx | 4 +-
src/components/orgs/OrgMembers.jsx | 2 +-
src/components/orgs/OrgStatistics.jsx | 2 +-
src/components/orgs/OrgSummary.jsx | 2 +-
.../references/ReferenceDetails.jsx | 2 +-
src/components/repos/CloneToSourcePreview.jsx | 2 +-
.../repos/ExpansionDetailsDialog.jsx | 2 +-
src/components/repos/ExpansionRowList.jsx | 8 +-
src/components/repos/RepoContentSummary.jsx | 2 +-
src/components/repos/RepoHome.jsx | 2 +-
src/components/repos/RepoManagementList.jsx | 2 +-
src/components/repos/RepoVersionButton.jsx | 2 +-
.../repos/VersionResourcesComparison.jsx | 4 +-
src/components/repos/utils.js | 2 +-
src/components/search/Search.jsx | 6 +-
.../url-registry/CanonicalResolveResult.jsx | 16 ++--
src/components/users/AddMenuList.jsx | 4 +-
src/components/users/Following.jsx | 2 +-
src/components/users/OIDLoginCallback.jsx | 9 ++-
src/components/users/UserForm.jsx | 2 +-
src/components/users/UserMenu.jsx | 4 +-
src/components/users/UserProfile.jsx | 2 +-
src/components/users/UserStatistics.jsx | 2 +-
src/components/users/UserSummary.jsx | 2 +-
src/index.jsx | 21 ++++-
src/services/GAService.js | 2 +-
webpack.config.js | 8 +-
56 files changed, 234 insertions(+), 122 deletions(-)
create mode 100644 src/common/history.js
diff --git a/.eslintrc.json b/.eslintrc.json
index 042555ce7..2e46d0d94 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -162,6 +162,7 @@
"url",
"urls",
"href",
+ "hashchange",
"xhr",
"kwargs",
"svg",
diff --git a/public/index.html b/public/index.html
index 1297aabd0..db490179c 100644
--- a/public/index.html
+++ b/public/index.html
@@ -8,7 +8,7 @@
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
-
+
-
+
-
+
diff --git a/src/common/history.js b/src/common/history.js
new file mode 100644
index 000000000..9f8dc50b0
--- /dev/null
+++ b/src/common/history.js
@@ -0,0 +1,81 @@
+let appHistory = null
+
+export const setAppHistory = history => {
+ appHistory = history
+}
+
+export const toRoutePath = path => {
+ const legacy = path?.match(/^\/?#(\/.*)$/)
+ return legacy ? legacy[1] : path
+}
+
+export const navigate = (path, replace=false) => {
+ if(!path)
+ return
+ const routePath = toRoutePath(path)
+ if(!appHistory) {
+ if(replace)
+ window.location.replace(routePath)
+ else
+ window.location.assign(routePath)
+ return
+ }
+ if(replace)
+ appHistory.replace(routePath)
+ else
+ appHistory.push(routePath)
+}
+
+export const legacyHashRoute = (location=window.location) => {
+ const { hash, search } = location
+ if(!hash.startsWith('#/') || /[?&]referrer=/.test(search))
+ return null
+ let route = hash.slice(1)
+ const outer = search.replace(/^\?/, '')
+ if(outer) {
+ const hashAt = route.indexOf('#')
+ const tail = hashAt > -1 ? route.slice(hashAt) : ''
+ const head = hashAt > -1 ? route.slice(0, hashAt) : route
+ route = head + (head.includes('?') ? '&' : '?') + outer + tail
+ }
+ return route
+}
+
+export const redirectLegacyHashRoute = () => {
+ const route = legacyHashRoute()
+ if(route)
+ navigate(route, true)
+}
+
+const currentRoute = () => window.location.pathname + window.location.search + window.location.hash
+
+const isPlainLeftClick = event => event.button === 0 && !event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey
+
+const appLinkRoute = event => {
+ const anchor = event.target?.closest?.('a[href]')
+ if(!anchor || (anchor.target && anchor.target !== '_self') || anchor.hasAttribute('download'))
+ return null
+ const href = anchor.getAttribute('href')
+ if(!href || (href.startsWith('#') && !href.startsWith('#/')) || /^(mailto|tel|javascript):/i.test(href))
+ return null
+ const url = new URL(anchor.href, window.location.href)
+ if(url.origin !== window.location.origin)
+ return null
+ return legacyHashRoute(url) || url.pathname + url.search + url.hash
+}
+
+export const keepLinkClickBubbling = event => {
+ if(isPlainLeftClick(event) && appLinkRoute(event))
+ event.stopPropagation = () => {}
+}
+
+export const handleLinkClick = event => {
+ if(event.defaultPrevented || !isPlainLeftClick(event))
+ return
+ const route = appLinkRoute(event)
+ if(!route)
+ return
+ event.preventDefault()
+ if(route !== currentRoute())
+ navigate(route)
+}
diff --git a/src/common/utils.js b/src/common/utils.js
index 3d971328a..9556446d5 100644
--- a/src/common/utils.js
+++ b/src/common/utils.js
@@ -16,12 +16,13 @@ import {
import APIService from '../services/APIService';
import GAService from '../services/GAService';
import { SERVER_CONFIGS } from './serverConfigs';
+import { legacyHashRoute } from './history';
-export const currentPath = () => window.location.hash.split('?')[0];
+export const currentPath = () => window.location.pathname;
-export const isAtGlobalSearch = () => window.location.hash.includes('#/search') || isAtRoot();
+export const isAtGlobalSearch = () => currentPath().startsWith('/search') || isAtRoot();
-export const isAtRoot = () => currentPath() === '#/';
+export const isAtRoot = () => currentPath() === '/';
export const formatDate = date => moment(date).format(DATE_FORMAT);
export const formatTime = date => moment(date).format(TIME_FORMAT);
@@ -246,7 +247,7 @@ export const arrayToObject = arr => {
}, {});
}
-export const currentUserHasAccess = () => hasAccessToURL(window.location.hash.replace('#/', ''))
+export const currentUserHasAccess = () => hasAccessToURL(window.location.pathname)
export const hasAccessToURL = url => {
if(!isLoggedIn())
@@ -673,12 +674,12 @@ export const logoutUser = (redirectToLogin, forced) => {
localStorage.removeItem('visits');
}
- const returnTo = window.location.origin + '/' + window.location.hash
+ const returnTo = window.location.origin + window.location.pathname + window.location.search
if(forced)
sessionStorage.setItem('session_expired', 'true')
const redirectURL = forced ?
- window.location.origin + '/#/signin?returnTo=' + encodeURIComponent(returnTo) :
+ window.location.origin + '/signin?returnTo=' + encodeURIComponent(returnTo) :
undefined
const logoutURL = getSSOLogoutURL(redirectURL)
@@ -687,10 +688,8 @@ export const logoutUser = (redirectToLogin, forced) => {
window.location = logoutURL
else if(redirectToLogin)
getLoginURL(forced ? returnTo : undefined).then(url => { window.location.href = url })
- else {
- window.location.hash = '#/';
- window.location.reload();
- }
+ else
+ window.location.assign('/');
}
@@ -905,9 +904,22 @@ const routePath = route => {
// Keycloak only redeems a code when the token request repeats the sign-in's redirect_uri exactly, and the
// callback can't rebuild a page's query string (e.g. ?referrer= on links from openconceptlab.org). So sign-in
-// always goes through LOGIN_REDIRECT_URL, and the page to come back to (its hash route) waits here, in this tab.
+// always goes through LOGIN_REDIRECT_URL, and the page to come back to (its route) waits here, in this tab.
+const returnToRoute = returnTo => {
+ if(!returnTo)
+ return null
+ try {
+ const url = new URL(returnTo, window.location.origin)
+ if(url.origin !== window.location.origin)
+ return null
+ return legacyHashRoute(url) || url.pathname + url.search + url.hash
+ } catch {
+ return null
+ }
+}
+
const prepareOAuthReturnTo = returnTo => {
- const route = returnTo?.includes('#') ? returnTo.slice(returnTo.indexOf('#') + 1) : null
+ const route = returnToRoute(returnTo)
const path = route && routePath(route)
// The router matches paths case-insensitively, so /SIGNUP would start a sign-up too.
if(path?.startsWith('/') && !/^\/(oidc\/login|signin|signup)(\/|$)/i.test(path))
diff --git a/src/components/app/App.jsx b/src/components/app/App.jsx
index 3d3d98159..3068642df 100644
--- a/src/components/app/App.jsx
+++ b/src/components/app/App.jsx
@@ -128,14 +128,13 @@ const App = props => {
const queryParams = new URLSearchParams(search)
const referrer = queryParams.get('referrer')
if(isLoggedIn()) {
- // OIDLoginCallback navigates away itself; resetting the hash here would undo that.
- if(!pathname.startsWith('/oidc/login'))
- window.location.hash = '#' + pathname + search
+ if(hash && !pathname.startsWith('/oidc/login'))
+ props.history.replace(pathname + search)
} else if(isOtherOCLClientURL(referrer) && !isLoggedIn()) {
const parts = hash ? hash.split('?') : referrer.split('?')
let params = new URLSearchParams(parts[1])
if(params.get('auth') === 'true') {
- getLoginURL(window.location.origin + '/#' + pathname).then(url => { window.location.href = url })
+ getLoginURL(window.location.origin + pathname).then(url => { window.location.href = url })
}
}
}
diff --git a/src/components/app/HeaderControls.jsx b/src/components/app/HeaderControls.jsx
index 4ae1ee574..14f1c8c46 100644
--- a/src/components/app/HeaderControls.jsx
+++ b/src/components/app/HeaderControls.jsx
@@ -31,7 +31,7 @@ const HeaderControls = () => {
{
authenticated &&
<>
-
+
diff --git a/src/components/app/LeftMenu.jsx b/src/components/app/LeftMenu.jsx
index 4f5af14a7..fe6c8e410 100644
--- a/src/components/app/LeftMenu.jsx
+++ b/src/components/app/LeftMenu.jsx
@@ -63,7 +63,7 @@ const LeftMenu = ({ isOpen, onClose }) => {
{
px: 2,
borderRadius: '100px'
}}
- href={`#${user?.url}repos`}
+ href={`${user?.url}repos`}
className='no-anchor-styles'
selected={location.pathname === (user?.url + 'repos')}
>
@@ -172,7 +172,7 @@ const LeftMenu = ({ isOpen, onClose }) => {
padding: '0px 16px',
borderRadius: '100px'
}}
- href={`#${org?.url}`}
+ href={org?.url}
className='no-anchor-styles'
selected={location.pathname === org?.url}
>
@@ -220,7 +220,7 @@ const LeftMenu = ({ isOpen, onClose }) => {
padding: '0px 16px',
borderRadius: '100px'
}}
- href={`#${followed.url}`}
+ href={followed.url}
className='no-anchor-styles'
selected={location.pathname === followed?.url}
>
diff --git a/src/components/common/About.jsx b/src/components/common/About.jsx
index 7307d86d8..33da4614e 100644
--- a/src/components/common/About.jsx
+++ b/src/components/common/About.jsx
@@ -32,9 +32,9 @@ const About = ({ title, text, style, expanded }) => {
{title}
}
-
+
-
+
{
showReadMoreButton &&
diff --git a/src/components/common/BaseEntityChip.jsx b/src/components/common/BaseEntityChip.jsx
index 45ed8dc01..fc372040f 100644
--- a/src/components/common/BaseEntityChip.jsx
+++ b/src/components/common/BaseEntityChip.jsx
@@ -178,7 +178,7 @@ const BaseEntityChip = ({ entity, icon, hideType, hideRepoVersion, primary, size
onClick={noLink ? undefined : event => {
event.stopPropagation()
}}
- href={noLink ? undefined : '#' + (entity?.version_url || entity?.url)}
+ href={noLink ? undefined : entity?.version_url || entity?.url}
component='a'
{...rest}
/>
diff --git a/src/components/common/EntityAttributesDialog.jsx b/src/components/common/EntityAttributesDialog.jsx
index 2ec45c887..85f233a91 100644
--- a/src/components/common/EntityAttributesDialog.jsx
+++ b/src/components/common/EntityAttributesDialog.jsx
@@ -29,7 +29,7 @@ const EntityAttributesDialog = ({ entity, fields, open, onClose }) => {
if(info.type === 'external_link')
return formatWebsiteLink(value)
if(info.type === 'user')
- return
+ return
if(info.type === 'json')
return {JSON.stringify(value, undefined, 2)}
if(info.type === 'locales-list') {
diff --git a/src/components/common/Events.jsx b/src/components/common/Events.jsx
index 547d3dc83..f557541f6 100644
--- a/src/components/common/Events.jsx
+++ b/src/components/common/Events.jsx
@@ -48,7 +48,7 @@ const EventDescription = ({ event, isFirst, isLast, isJoined }) => {
{eventDescription}
{
rel ?
- :
+ :
null
}
diff --git a/src/components/common/OCLLogo.jsx b/src/components/common/OCLLogo.jsx
index 807956f9f..37d4368c7 100644
--- a/src/components/common/OCLLogo.jsx
+++ b/src/components/common/OCLLogo.jsx
@@ -4,7 +4,7 @@ import { PRIMARY_COLORS } from '../../common/colors'
const OCLLogo = ({ color, width, height, }) => {
return (
-
+
diff --git a/src/components/errors/ErrorBoundary.jsx b/src/components/errors/ErrorBoundary.jsx
index c04225134..7fe337ece 100644
--- a/src/components/errors/ErrorBoundary.jsx
+++ b/src/components/errors/ErrorBoundary.jsx
@@ -59,8 +59,7 @@ class ErrorBoundary extends React.Component {
}
isDebugMode() {
- const debug = new URLSearchParams(window.location.search).get('debug') ||
- new URLSearchParams(window.location.hash.split('?')[1] || '').get('debug')
+ const debug = new URLSearchParams(window.location.search).get('debug')
return debug === 'true' || debug === '1'
}
diff --git a/src/components/mappings/AssociationRowOptions.jsx b/src/components/mappings/AssociationRowOptions.jsx
index f0e94fc1b..d94c3f7d7 100644
--- a/src/components/mappings/AssociationRowOptions.jsx
+++ b/src/components/mappings/AssociationRowOptions.jsx
@@ -16,6 +16,7 @@ import RetireIcon from '@mui/icons-material/Delete'
import compact from 'lodash/compact'
import isNumber from 'lodash/isNumber'
import { dropVersion } from '../../common/utils'
+import { navigate } from '../../common/history'
const AssociationRowOptions = ({ mapping, concept, isIndirect, canAct, canSort, disabled, onAddNewClick, onAssignSortWeight, onClearSortWeight, onRetireClick }) => {
const { t } = useTranslation()
@@ -26,13 +27,13 @@ const AssociationRowOptions = ({ mapping, concept, isIndirect, canAct, canSort,
const fromConceptURL = mapping.from_concept_url || (mapping.to_concept_url ? conceptURL : undefined)
const toConceptURL = mapping.to_concept_url || (mapping.from_concept_url ? conceptURL : undefined)
- const navigate = href => () => { window.location.hash = href }
+ const openURL = href => () => navigate(href)
const options = compact([
- {label: t('mapping.open_mapping_details'), icon: , onClick: navigate(dropVersion(mapping.url))},
- fromConceptURL && fromConceptURL !== conceptURL && {label: t('mapping.open_from_concept'), icon: , onClick: navigate(fromConceptURL)},
- toConceptURL && toConceptURL !== conceptURL && {label: t('mapping.open_to_concept'), icon: , onClick: navigate(toConceptURL)},
- fromConceptURL && toConceptURL && {label: t('mapping.compare_concepts'), icon: , divider: true, onClick: navigate(`/concepts/compare?lhs=${fromConceptURL}&rhs=${toConceptURL}`)},
+ {label: t('mapping.open_mapping_details'), icon: , onClick: openURL(dropVersion(mapping.url))},
+ fromConceptURL && fromConceptURL !== conceptURL && {label: t('mapping.open_from_concept'), icon: , onClick: openURL(fromConceptURL)},
+ toConceptURL && toConceptURL !== conceptURL && {label: t('mapping.open_to_concept'), icon: , onClick: openURL(toConceptURL)},
+ fromConceptURL && toConceptURL && {label: t('mapping.compare_concepts'), icon: , divider: true, onClick: openURL(`/concepts/compare?lhs=${fromConceptURL}&rhs=${toConceptURL}`)},
canAct && onAddNewClick && {label: t('mapping.add_new_map_type_mapping', {mapType: mapTypeLabel}), icon: , divider: true, onClick: () => onAddNewClick(mapping.map_type)},
canSort && (
isNumber(mapping.sort_weight) ?
diff --git a/src/components/mappings/MappingDetails.jsx b/src/components/mappings/MappingDetails.jsx
index 3f0b2959f..a80235fc6 100644
--- a/src/components/mappings/MappingDetails.jsx
+++ b/src/components/mappings/MappingDetails.jsx
@@ -40,7 +40,7 @@ const MappingDetails = ({ mapping }) => {
}
- {t('common.last_updated')} {formatDateTime(mapping.versioned_updated_on || mapping.updated_on)} {t('common.by')}
+ {t('common.last_updated')} {formatDateTime(mapping.versioned_updated_on || mapping.updated_on)} {t('common.by')}
{t('checksums.standard')} {mapping?.checksums?.standard}
diff --git a/src/components/mappings/MappingForm.jsx b/src/components/mappings/MappingForm.jsx
index fe349da10..a20530d31 100644
--- a/src/components/mappings/MappingForm.jsx
+++ b/src/components/mappings/MappingForm.jsx
@@ -10,6 +10,7 @@ import {
import APIService from '../../services/APIService';
import GAService from '../../services/GAService';
import { arrayToObject, toParentURI, URIToParentParams } from '../../common/utils';
+import { navigate } from '../../common/history';
import { fetchMapTypes } from './utils';
import { OperationsContext } from '../app/LayoutContext';
import FormComponent, { CardSection } from '../common/FormComponent'
@@ -278,7 +279,7 @@ class MappingForm extends FormComponent {
parentURL &&
Your new mapping will live at:
- { `${window.location.origin}/#${parentURL}mappings/` }
+ { `${window.location.origin}${parentURL}mappings/` }
{id}/
@@ -392,7 +393,7 @@ class MappingForm extends FormComponent {
if(response.status === 201 || response.status === 200) { // success
setAlert({duration: 2000, message: edit ? t('mapping.success_update') : t('mapping.success_create'), severity: 'success'})
onClose(response.data);
- window.location.hash = response.data.url
+ navigate(response.data.url)
} else if (response?.status === 208) {
let error = get(response?.data, '__all__.0') || t('common.already_exists')
setAlert({duration: 10000, message: `${response.status}: ${error}`, severity: 'error'})
diff --git a/src/components/mappings/MappingHeader.jsx b/src/components/mappings/MappingHeader.jsx
index 982523c38..88c8d03ff 100644
--- a/src/components/mappings/MappingHeader.jsx
+++ b/src/components/mappings/MappingHeader.jsx
@@ -72,7 +72,7 @@ const MappingHeader = ({mapping, onClose, repoURL, nested, onEdit, onRetire, onC
size='small'
color='primary'
disabled={!detailsLoaded}
- href={detailsLoaded ? `#${mappingSourceURL}` : undefined}
+ href={detailsLoaded ? mappingSourceURL : undefined}
target='_blank'
rel='noopener noreferrer'
onClick={event => {
diff --git a/src/components/mappings/SortableAssociationRow.jsx b/src/components/mappings/SortableAssociationRow.jsx
index 85601eba1..0b5ad3f9b 100644
--- a/src/components/mappings/SortableAssociationRow.jsx
+++ b/src/components/mappings/SortableAssociationRow.jsx
@@ -17,6 +17,7 @@ import WarningIcon from '@mui/icons-material/WarningAmber'
import { map, get, forEach, orderBy, filter, find, isNumber, has, some, maxBy } from 'lodash';
import { toParentURI, getSiblings } from '../../common/utils'
+import { navigate } from '../../common/history'
import AssociationMappingCells from './AssociationMappingCells'
import AssociationRowOptions from './AssociationRowOptions'
@@ -142,7 +143,7 @@ const SortableAssociationRow = ({ concept, mappings, mapType, isSelf, isIndirect
{ if(targetURL) window.location.hash = targetURL }}
+ onClick={() => { if(targetURL) navigate(targetURL) }}
>
{
diff --git a/src/components/orgs/MemberList.jsx b/src/components/orgs/MemberList.jsx
index f88e140d2..539d987b6 100644
--- a/src/components/orgs/MemberList.jsx
+++ b/src/components/orgs/MemberList.jsx
@@ -39,7 +39,7 @@ const MemberList = ({ members, open, onClose }) => {
{
map(members, (member, i) => (
-
+
diff --git a/src/components/orgs/OrgHeader.jsx b/src/components/orgs/OrgHeader.jsx
index 9acf36ea0..7bd23bd6a 100644
--- a/src/components/orgs/OrgHeader.jsx
+++ b/src/components/orgs/OrgHeader.jsx
@@ -107,7 +107,7 @@ const OrgHeader = ({ org, members, onDeleteClick, canDelete, fetchMembers }) =>
open={Boolean(anchorEl)}
onClose={handleManageClick}
>
-
-
+
diff --git a/src/components/orgs/OrgSummary.jsx b/src/components/orgs/OrgSummary.jsx
index b51e0ceb1..a02a23196 100644
--- a/src/components/orgs/OrgSummary.jsx
+++ b/src/components/orgs/OrgSummary.jsx
@@ -16,7 +16,7 @@ const OrgSummary = ({org, members }) => {
- } />
+ } />
>
)
diff --git a/src/components/references/ReferenceDetails.jsx b/src/components/references/ReferenceDetails.jsx
index 05d37fe4c..934bb36af 100644
--- a/src/components/references/ReferenceDetails.jsx
+++ b/src/components/references/ReferenceDetails.jsx
@@ -122,7 +122,7 @@ const ReferenceDetails = ({ reference, style }) => {
{t('common.created_on')} {
- <>{formatDateTime(reference.created_at)} {t('common.by')} >
+ <>{formatDateTime(reference.created_at)} {t('common.by')} >
}
diff --git a/src/components/repos/CloneToSourcePreview.jsx b/src/components/repos/CloneToSourcePreview.jsx
index b6aee1244..3da2026c1 100644
--- a/src/components/repos/CloneToSourcePreview.jsx
+++ b/src/components/repos/CloneToSourcePreview.jsx
@@ -18,7 +18,7 @@ const entityHref = entity => {
const url = isVersionType(entity?.type)
? entity?.version_url || entity?.url
: entity?.url || entity?.version_url
- return url ? `#${url}` : undefined
+ return url || undefined
}
const MappingRow = ({ mapping }) => {
diff --git a/src/components/repos/ExpansionDetailsDialog.jsx b/src/components/repos/ExpansionDetailsDialog.jsx
index e0fa6169d..d6308a25f 100644
--- a/src/components/repos/ExpansionDetailsDialog.jsx
+++ b/src/components/repos/ExpansionDetailsDialog.jsx
@@ -28,7 +28,7 @@ const RepoVersionList = ({ title, versions = [], emptyLabel }) => (
`${version.owner}-${version.short_code}-${version.version}`
}
>
-
+
{`${version.owner} / ${version.short_code}:${version.version}`}
diff --git a/src/components/repos/ExpansionRowList.jsx b/src/components/repos/ExpansionRowList.jsx
index 3aa5e8acd..c49960fdf 100644
--- a/src/components/repos/ExpansionRowList.jsx
+++ b/src/components/repos/ExpansionRowList.jsx
@@ -50,7 +50,7 @@ const RepoVersionList = ({ versions, emptyLabel }) => (
'& a:hover': { textDecoration: 'underline' }
}}
>
-
+
{renderRepoVersionLabel(version)}
@@ -192,7 +192,7 @@ const ExpansionRowList = ({
{Object.entries(repoUpdates).map(([oldUrl, newUrl]) => {
- const compareUrl = `#${dropVersion(newUrl)}compare-versions?version1=${newUrl}&version2=${oldUrl}`;
+ const compareUrl = `${dropVersion(newUrl)}compare-versions?version1=${newUrl}&version2=${oldUrl}`;
return (
- {labelFromVersionUrl(oldUrl)}
+ {labelFromVersionUrl(oldUrl)}
{' → '}
- {labelFromVersionUrl(newUrl)}
+ {labelFromVersionUrl(newUrl)}
({t('common.compare')} )
diff --git a/src/components/repos/RepoContentSummary.jsx b/src/components/repos/RepoContentSummary.jsx
index 604d10b43..a3dea2c28 100644
--- a/src/components/repos/RepoContentSummary.jsx
+++ b/src/components/repos/RepoContentSummary.jsx
@@ -103,7 +103,7 @@ const RepoContentSummary = ({ summary, stats, summaries, baseURL }) => {
{...(baseURL ? {
// the stat opens the tab it counts, without also firing the row's click
component: Link,
- href: `#${baseURL}${CONFIG[stat].tab}/`,
+ href: `${baseURL}${CONFIG[stat].tab}/`,
onClick: event => event.stopPropagation(),
underline: 'none',
color: 'inherit'
diff --git a/src/components/repos/RepoHome.jsx b/src/components/repos/RepoHome.jsx
index 6525665f2..5d38e825e 100644
--- a/src/components/repos/RepoHome.jsx
+++ b/src/components/repos/RepoHome.jsx
@@ -551,7 +551,7 @@ const RepoHome = () => {
isVersion={isVersion}
owner={owner}
repo={currentRepo}
- repoHref={'#' + buildRepoPath(route, {version: 'HEAD', expansion: '', tab: '', resource: ''})}
+ repoHref={buildRepoPath(route, {version: 'HEAD', expansion: '', tab: '', resource: ''})}
versions={versions}
versionsLoading={versionsLoading}
previewVersions={compact([headVersion, latestVersion])}
diff --git a/src/components/repos/RepoManagementList.jsx b/src/components/repos/RepoManagementList.jsx
index 53a5fa58e..3b5904c83 100644
--- a/src/components/repos/RepoManagementList.jsx
+++ b/src/components/repos/RepoManagementList.jsx
@@ -13,7 +13,7 @@ import GAService from '../../services/GAService';
const RepoManagementList = ({ anchorEl, open, onClose, onClick, repo, id, isVersion, hasAccess, createSimilarHref }) => {
const { t } = useTranslation()
const url = isVersion ? repo.version_url : repo.url
- let editParams = isVersion ? {onClick: () => onClick('editVersion')} : {href: `#${url}edit`}
+ let editParams = isVersion ? {onClick: () => onClick('editVersion')} : {href: `${url}edit`}
return (