Use custom api url for external links

This commit is contained in:
Alan Hamlett
2024-12-05 11:56:18 +01:00
parent 2aa07804c8
commit 3d141cbcdd
6 changed files with 53 additions and 41 deletions

View File

@@ -6,6 +6,7 @@ import { userLogout } from '../reducers/currentUser';
import { ReduxSelector } from '../types/store'; import { ReduxSelector } from '../types/store';
import { User } from '../types/user'; import { User } from '../types/user';
import changeExtensionState from '../utils/changeExtensionStatus'; import changeExtensionState from '../utils/changeExtensionStatus';
import { getWebsiteUrl } from '../utils/settings';
export interface MainListProps { export interface MainListProps {
loggingEnabled: boolean; loggingEnabled: boolean;
@@ -15,10 +16,10 @@ const openOptionsPage = async (): Promise<void> => {
await browser.runtime.openOptionsPage(); await browser.runtime.openOptionsPage();
}; };
export default function MainList({ export default async function MainList({
loggingEnabled, loggingEnabled,
totalTimeLoggedToday, totalTimeLoggedToday,
}: MainListProps): JSX.Element { }: MainListProps): Promise<JSX.Element> {
const dispatch = useDispatch(); const dispatch = useDispatch();
const user: User | undefined = useSelector( const user: User | undefined = useSelector(
@@ -53,6 +54,8 @@ export default function MainList({
</div> </div>
) : null; ) : null;
const url = await getWebsiteUrl();
return ( return (
<div> <div>
{user ? ( {user ? (
@@ -119,7 +122,7 @@ export default function MainList({
<a <a
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
href="https://wakatime.com/login" href={`${url}/login`}
className="list-group-item text-body-secondary" className="list-group-item text-body-secondary"
> >
<i className="fa fa-fw fa-sign-in me-2" /> <i className="fa fa-fw fa-sign-in me-2" />

View File

@@ -2,8 +2,9 @@ import React from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { ReduxSelector } from '../types/store'; import { ReduxSelector } from '../types/store';
import { User } from '../types/user'; import { User } from '../types/user';
import { getWebsiteUrl } from '../utils/settings';
export default function NavBar(): JSX.Element { export default async function NavBar(): Promise<Promise<JSX.Element>> {
const user: User | undefined = useSelector( const user: User | undefined = useSelector(
(selector: ReduxSelector) => selector.currentUser.user, (selector: ReduxSelector) => selector.currentUser.user,
); );
@@ -20,13 +21,14 @@ export default function NavBar(): JSX.Element {
} }
}; };
const customRules = () => { const customRules = async () => {
if (user) { if (user) {
const url = await getWebsiteUrl();
return ( return (
<li className="mb-2"> <li className="mb-2">
<a <a
target="_blank" target="_blank"
href="https://wakatime.com/settings/rules" href={`${url}/settings/rules`}
rel="noreferrer" rel="noreferrer"
className="text-body-secondary link-underline link-underline-opacity-0 d-flex w-100 align-items-center" className="text-body-secondary link-underline link-underline-opacity-0 d-flex w-100 align-items-center"
> >
@@ -40,13 +42,14 @@ export default function NavBar(): JSX.Element {
} }
}; };
const dashboard = () => { const dashboard = async () => {
if (user) { if (user) {
const url = await getWebsiteUrl();
return ( return (
<li className="mb-2"> <li className="mb-2">
<a <a
target="_blank" target="_blank"
href="https://wakatime.com/dashboard" href={url}
rel="noreferrer" rel="noreferrer"
className="text-body-secondary link-underline link-underline-opacity-0 d-flex w-100 align-items-center" className="text-body-secondary link-underline link-underline-opacity-0 d-flex w-100 align-items-center"
> >
@@ -84,8 +87,8 @@ export default function NavBar(): JSX.Element {
<div className="collapse navbar-collapse mt-4" id="userInfoCollapse"> <div className="collapse navbar-collapse mt-4" id="userInfoCollapse">
{signedInAs()} {signedInAs()}
<ul className="nav navbar-nav border-bottom pb-2"> <ul className="nav navbar-nav border-bottom pb-2">
{customRules()} {await customRules()}
{dashboard()} {await dashboard()}
<li className="dropdown"> <li className="dropdown">
<a <a
href="#" href="#"

View File

@@ -1,18 +1,18 @@
import { openDB } from 'idb';
import browser, { Tabs } from 'webextension-polyfill'; import browser, { Tabs } from 'webextension-polyfill';
/* eslint-disable no-fallthrough */ import { openDB } from 'idb';
/* eslint-disable default-case */
import moment from 'moment'; import moment from 'moment';
import { v4 as uuid4 } from 'uuid'; import { v4 as uuid4 } from 'uuid';
import { OptionalHeartbeat } from '../types/sites';
import { changeExtensionStatus } from '../utils/changeExtensionStatus';
import getDomainFromUrl, { getDomain } from '../utils/getDomainFromUrl';
import { getOperatingSystem, IS_EDGE, IS_FIREFOX } from '../utils/operatingSystem';
import { getSettings, Settings } from '../utils/settings';
import { getApiUrl } from '../utils/user';
import config, { ExtensionStatus } from '../config/config'; import config, { ExtensionStatus } from '../config/config';
import { EntityType, Heartbeat, HeartbeatsBulkResponse } from '../types/heartbeats'; import { EntityType, Heartbeat, HeartbeatsBulkResponse } from '../types/heartbeats';
import getDomainFromUrl, { getDomain } from '../utils/getDomainFromUrl';
import { IS_EDGE, IS_FIREFOX, getOperatingSystem } from '../utils/operatingSystem';
import { Settings, getApiUrl, getSettings } from '../utils/settings';
import { OptionalHeartbeat } from '../types/sites';
import { changeExtensionStatus } from '../utils/changeExtensionStatus';
/* eslint-disable no-fallthrough */
/* eslint-disable default-case */
class WakaTimeCore { class WakaTimeCore {
tabsWithDevtoolsOpen: Tabs.Tab[]; tabsWithDevtoolsOpen: Tabs.Tab[];
@@ -185,7 +185,7 @@ class WakaTimeCore {
const request: RequestInit = { const request: RequestInit = {
body: JSON.stringify( body: JSON.stringify(
heartbeats.map((heartbeat) => { heartbeats.map((heartbeat) => {
return { ...heartbeat, userAgent }; return { ...heartbeat, plugin: userAgent };
}), }),
), ),
credentials: 'omit', credentials: 'omit',

View File

@@ -1,9 +1,10 @@
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'; import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import axios, { AxiosResponse } from 'axios'; import axios, { AxiosResponse } from 'axios';
import browser from 'webextension-polyfill'; import browser from 'webextension-polyfill';
import config from '../config/config';
import { CurrentUser, User, UserPayload } from '../types/user'; import { CurrentUser, User, UserPayload } from '../types/user';
import { getApiUrl } from '../utils/user';
import config from '../config/config';
import { getApiUrl } from '../utils/settings';
interface setUserAction { interface setUserAction {
payload: User | undefined; payload: User | undefined;

View File

@@ -83,3 +83,21 @@ export const getSettings = async (): Promise<Settings> => {
export const saveSettings = async (settings: Settings): Promise<void> => { export const saveSettings = async (settings: Settings): Promise<void> => {
return browser.storage.sync.set(settings); return browser.storage.sync.set(settings);
}; };
export const getApiUrl = async () => {
const settings = await browser.storage.sync.get({
apiUrl: config.apiUrl,
});
let apiUrl = (settings.apiUrl as string) || config.apiUrl;
const suffixes = ['/', '.bulk', '/users/current/heartbeats', '/heartbeats', '/heartbeat'];
for (const suffix of suffixes) {
if (apiUrl.endsWith(suffix)) {
apiUrl = apiUrl.slice(0, -suffix.length);
}
}
return apiUrl;
};
export const getWebsiteUrl = async () => {
return (await getApiUrl()).replace('/api/v1', '').replace('://api.', '://');
};

View File

@@ -1,28 +1,15 @@
import { AnyAction, Dispatch } from '@reduxjs/toolkit'; import { AnyAction, Dispatch } from '@reduxjs/toolkit';
import axios, { AxiosResponse } from 'axios'; import axios, { AxiosResponse } from 'axios';
import browser from 'webextension-polyfill';
import moment from 'moment'; import moment from 'moment';
import config from '../config/config'; import browser from 'webextension-polyfill';
import { setApiKey, setLoggingEnabled, setTotalTimeLoggedToday } from '../reducers/configReducer'; import { setApiKey, setLoggingEnabled, setTotalTimeLoggedToday } from '../reducers/configReducer';
import { setUser } from '../reducers/currentUser';
import { GrandTotal, Summaries } from '../types/summaries'; import { GrandTotal, Summaries } from '../types/summaries';
import { ApiKeyPayload, AxiosUserResponse, User } from '../types/user'; import { ApiKeyPayload, AxiosUserResponse, User } from '../types/user';
import changeExtensionState from './changeExtensionStatus';
export const getApiUrl = async () => { import config from '../config/config';
const settings = await browser.storage.sync.get({ import { setUser } from '../reducers/currentUser';
apiUrl: config.apiUrl, import changeExtensionState from './changeExtensionStatus';
}); import { getApiUrl } from './settings';
let apiUrl = (settings.apiUrl as string) || config.apiUrl;
const suffixes = ['/', '.bulk', '/users/current/heartbeats', '/heartbeats', '/heartbeat'];
for (const suffix of suffixes) {
if (apiUrl.endsWith(suffix)) {
apiUrl = apiUrl.slice(0, -suffix.length);
}
}
return apiUrl;
};
/** /**
* Checks if the user is logged in. * Checks if the user is logged in.