mirror of
https://github.com/PeWu/topola-viewer.git
synced 2026-07-17 17:21:48 +00:00
refactor: restrict WikiTree integration to the apps.wikitree.com domain and add helper utilities
This commit is contained in:
@@ -38,7 +38,7 @@ Here is an example from the Web:
|
|||||||
|
|
||||||
* [J. F. Kennedy](https://pewu.github.io/topola-viewer/#/view?url=https%3A%2F%2Fchronoplexsoftware.com%2Fmyfamilytree%2Fsamples%2FThe%2520Kennedy%2520Family.gdz) (from [chronoplexsoftware.com](https://chronoplexsoftware.com/myfamilytree/samples/))
|
* [J. F. Kennedy](https://pewu.github.io/topola-viewer/#/view?url=https%3A%2F%2Fchronoplexsoftware.com%2Fmyfamilytree%2Fsamples%2FThe%2520Kennedy%2520Family.gdz) (from [chronoplexsoftware.com](https://chronoplexsoftware.com/myfamilytree/samples/))
|
||||||
* [Shakespeare](https://pewu.github.io/topola-viewer/#/view?url=https%3A%2F%2Fwebtreeprint.com%2Ftp_downloader.php%3Fpath%3Dfamous_gedcoms%2Fshakespeare.ged%26file%3Dshakespeare.ged) (from [webtreeprint.com](https://webtreeprint.com/tp_famous_gedcoms.php))
|
* [Shakespeare](https://pewu.github.io/topola-viewer/#/view?url=https%3A%2F%2Fwebtreeprint.com%2Ftp_downloader.php%3Fpath%3Dfamous_gedcoms%2Fshakespeare.ged%26file%3Dshakespeare.ged) (from [webtreeprint.com](https://webtreeprint.com/tp_famous_gedcoms.php))
|
||||||
* [Maria Skłodowska-Curie](https://pewu.github.io/topola-viewer/#/view?indi=Sk%C5%82odowska-2&source=wikitree) (from [WikiTree](https://www.wikitree.com/wiki/Sk%C5%82odowska-2))
|
* [Maria Skłodowska-Curie](https://apps.wikitree.com/apps/wiech13/topola-viewer/#/view?indi=Sk%C5%82odowska-2&source=wikitree) (from [WikiTree](https://www.wikitree.com/wiki/Sk%C5%82odowska-2))
|
||||||
|
|
||||||
If you have data in a genealogy database, you can export your data in GEDCOM format and load it using the "Load from file" menu.
|
If you have data in a genealogy database, you can export your data in GEDCOM format and load it using the "Load from file" menu.
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
Person,
|
Person,
|
||||||
} from 'wikitree-js';
|
} from 'wikitree-js';
|
||||||
import {TopolaError} from '../util/error';
|
import {TopolaError} from '../util/error';
|
||||||
|
import {isOnWikitreeDomain} from '../util/wikitree_util';
|
||||||
|
|
||||||
const WIKITREE_APP_ID = 'topola-viewer';
|
const WIKITREE_APP_ID = 'topola-viewer';
|
||||||
/** Prefix for IDs of private individuals. */
|
/** Prefix for IDs of private individuals. */
|
||||||
@@ -270,7 +271,7 @@ export async function loadData(
|
|||||||
authcode?: string,
|
authcode?: string,
|
||||||
): Promise<Person[]> {
|
): Promise<Person[]> {
|
||||||
// Work around CORS if not in apps.wikitree.com domain.
|
// Work around CORS if not in apps.wikitree.com domain.
|
||||||
const handleCors = window.location.hostname !== 'apps.wikitree.com';
|
const handleCors = !isOnWikitreeDomain();
|
||||||
|
|
||||||
await logInIfNeeded(authcode, handleCors);
|
await logInIfNeeded(authcode, handleCors);
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {Card, Grid, Image} from 'semantic-ui-react';
|
|||||||
import {getChangelog, updateSeenVersion} from './changelog';
|
import {getChangelog, updateSeenVersion} from './changelog';
|
||||||
import logo from './topola.jpg';
|
import logo from './topola.jpg';
|
||||||
import {Media} from './util/media';
|
import {Media} from './util/media';
|
||||||
|
import {isOnWikitreeDomain, WIKITREE_TOPOLA_URL} from './util/wikitree_util';
|
||||||
|
|
||||||
/** Link that loads a view. */
|
/** Link that loads a view. */
|
||||||
function ViewLink(props: {params: {[key: string]: string}; text: string}) {
|
function ViewLink(props: {params: {[key: string]: string}; text: string}) {
|
||||||
@@ -82,13 +83,23 @@ function Contents() {
|
|||||||
)
|
)
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<ViewLink
|
{isOnWikitreeDomain() ? (
|
||||||
params={{
|
<ViewLink
|
||||||
indi: 'Skłodowska-2',
|
params={{
|
||||||
source: 'wikitree',
|
indi: 'Skłodowska-2',
|
||||||
}}
|
source: 'wikitree',
|
||||||
text="Maria Skłodowska-Curie"
|
}}
|
||||||
/>{' '}
|
text="Maria Skłodowska-Curie"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<a
|
||||||
|
href={`${WIKITREE_TOPOLA_URL}/#/view?source=wikitree&indi=Sk%C5%82odowska-2`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
Maria Skłodowska-Curie ↗
|
||||||
|
</a>
|
||||||
|
)}{' '}
|
||||||
(<FormattedMessage id="intro.from" defaultMessage="from" />{' '}
|
(<FormattedMessage id="intro.from" defaultMessage="from" />{' '}
|
||||||
<a href="https://www.wikitree.com/wiki/Sk%C5%82odowska-2">
|
<a href="https://www.wikitree.com/wiki/Sk%C5%82odowska-2">
|
||||||
wikitree.com
|
wikitree.com
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {Dropdown, Icon, Menu} from 'semantic-ui-react';
|
|||||||
import {IndiInfo, JsonGedcomData} from 'topola';
|
import {IndiInfo, JsonGedcomData} from 'topola';
|
||||||
import {isGoogleDriveConfigured} from '../datasource/google_drive_service';
|
import {isGoogleDriveConfigured} from '../datasource/google_drive_service';
|
||||||
import {Media} from '../util/media';
|
import {Media} from '../util/media';
|
||||||
|
import {isOnWikitreeDomain} from '../util/wikitree_util';
|
||||||
import {GoogleDriveMenu} from './google_drive_menu';
|
import {GoogleDriveMenu} from './google_drive_menu';
|
||||||
import {MenuItem, MenuType} from './menu_item';
|
import {MenuItem, MenuType} from './menu_item';
|
||||||
import {SearchBar} from './search';
|
import {SearchBar} from './search';
|
||||||
@@ -50,6 +51,11 @@ export function TopBar(props: Props) {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
|
// WikiTree menus only work when hosted on apps.wikitree.com because
|
||||||
|
// WikiTree's API requires same-origin access. The CORS proxy workaround is
|
||||||
|
// no longer functional.
|
||||||
|
const showWikiTree = props.showWikiTreeMenus && isOnWikitreeDomain();
|
||||||
|
|
||||||
const {searchResults, searchString, setSearchString, handleResultSelect} =
|
const {searchResults, searchString, setSearchString, handleResultSelect} =
|
||||||
useSearch({
|
useSearch({
|
||||||
data: props.data,
|
data: props.data,
|
||||||
@@ -246,7 +252,7 @@ export function TopBar(props: Props) {
|
|||||||
<>
|
<>
|
||||||
<UploadMenu menuType={menuType} {...props} />
|
<UploadMenu menuType={menuType} {...props} />
|
||||||
<UrlMenu menuType={menuType} {...props} />
|
<UrlMenu menuType={menuType} {...props} />
|
||||||
<WikiTreeMenu menuType={menuType} {...props} />
|
{showWikiTree && <WikiTreeMenu menuType={menuType} {...props} />}
|
||||||
<GoogleDriveMenu
|
<GoogleDriveMenu
|
||||||
menuType={menuType}
|
menuType={menuType}
|
||||||
onTokenAcquired={props.onGoogleTokenAcquired}
|
onTokenAcquired={props.onGoogleTokenAcquired}
|
||||||
@@ -257,7 +263,7 @@ export function TopBar(props: Props) {
|
|||||||
|
|
||||||
function fileMenus(screenSize: ScreenSize) {
|
function fileMenus(screenSize: ScreenSize) {
|
||||||
// In standalone WikiTree mode, show only the "Select WikiTree ID" menu.
|
// In standalone WikiTree mode, show only the "Select WikiTree ID" menu.
|
||||||
if (!props.standalone && props.showWikiTreeMenus) {
|
if (!props.standalone && showWikiTree) {
|
||||||
switch (screenSize) {
|
switch (screenSize) {
|
||||||
case ScreenSize.LARGE:
|
case ScreenSize.LARGE:
|
||||||
return <WikiTreeMenu menuType={MenuType.Menu} {...props} />;
|
return <WikiTreeMenu menuType={MenuType.Menu} {...props} />;
|
||||||
@@ -307,7 +313,7 @@ export function TopBar(props: Props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function wikiTreeLoginMenu(screenSize: ScreenSize) {
|
function wikiTreeLoginMenu(screenSize: ScreenSize) {
|
||||||
if (!props.showWikiTreeMenus) {
|
if (!showWikiTree) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {useLocation, useNavigate} from 'react-router';
|
|||||||
import {Button, Form, Header, Input, Modal} from 'semantic-ui-react';
|
import {Button, Form, Header, Input, Modal} from 'semantic-ui-react';
|
||||||
import {getLoggedInUserName, navigateToLoginPage} from 'wikitree-js';
|
import {getLoggedInUserName, navigateToLoginPage} from 'wikitree-js';
|
||||||
import {analyticsEvent} from '../util/analytics';
|
import {analyticsEvent} from '../util/analytics';
|
||||||
|
import {WIKITREE_TOPOLA_URL} from '../util/wikitree_util';
|
||||||
import {MenuItem, MenuType} from './menu_item';
|
import {MenuItem, MenuType} from './menu_item';
|
||||||
import wikitreeLogo from './wikitree.png';
|
import wikitreeLogo from './wikitree.png';
|
||||||
|
|
||||||
@@ -157,10 +158,8 @@ export function WikiTreeLoginMenu(props: Props) {
|
|||||||
* Topola Viewer hosted on apps.wikitree.com.
|
* Topola Viewer hosted on apps.wikitree.com.
|
||||||
*/
|
*/
|
||||||
function login() {
|
function login() {
|
||||||
const wikiTreeTopolaUrl =
|
|
||||||
'https://apps.wikitree.com/apps/wiech13/topola-viewer';
|
|
||||||
// TODO: remove authcode if it is in the current URL.
|
// TODO: remove authcode if it is in the current URL.
|
||||||
const returnUrl = `${wikiTreeTopolaUrl}${window.location.hash}`;
|
const returnUrl = `${WIKITREE_TOPOLA_URL}${window.location.hash}`;
|
||||||
navigateToLoginPage(returnUrl);
|
navigateToLoginPage(returnUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
17
src/util/wikitree_util.ts
Normal file
17
src/util/wikitree_util.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* Base URL for Topola Viewer hosted on apps.wikitree.com.
|
||||||
|
* WikiTree API calls only work when the app is served from this domain.
|
||||||
|
*/
|
||||||
|
export const WIKITREE_TOPOLA_URL =
|
||||||
|
'https://apps.wikitree.com/apps/wiech13/topola-viewer';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the app is currently hosted on the apps.wikitree.com domain.
|
||||||
|
*
|
||||||
|
* WikiTree's API requires being served from this domain due to authentication
|
||||||
|
* and CORS restrictions. When not on this domain, WikiTree data loading does
|
||||||
|
* not work.
|
||||||
|
*/
|
||||||
|
export function isOnWikitreeDomain(): boolean {
|
||||||
|
return window.location.hostname === 'apps.wikitree.com';
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user