Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: implement new ts components #155

Merged
merged 3 commits into from
Jan 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,491 changes: 1,117 additions & 1,374 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,18 +95,18 @@
"jsxhint": "^0.15.1",
"less": "^4.1.3",
"lint-staged": "^13.1.0",
"mocha": "^5.0.0",
"mocha-sinon": "^2.0.0",
"mocha": "^10.2.0",
"mocha-sinon": "^2.1.2",
"node-gyp": "^8.3.0",
"prettier": "^2.8.2",
"prettier-plugin-packagejson": "^2.3.0",
"prettier-plugin-sort-json": "1.0.0",
"remote-redux-devtools": "^0.5.16",
"rimraf": "^3.0.2",
"shelljs": "^0.8.5",
"sinon": "^4.2.2",
"sinon-chai": "^2.8.0",
"sinon-chrome": "^2.2.4",
"sinon": "^15.0.1",
"sinon-chai": "^3.7.0",
"sinon-chrome": "^3.0.1",
"ts-jest": "^29.0.3",
"ts-loader": "^9.4.2",
"ts-node": "^10.9.1",
Expand Down
7 changes: 2 additions & 5 deletions src/components/MainList.test.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,27 @@
import React from 'react';
import { render } from '@testing-library/react';
import { renderWithProviders } from '../utils/test-utils';
import MainList from './MainList';

type onClick = (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => void;
describe('MainList', () => {
let disableLogging: onClick;
let enableLogging: onClick;
let loggedIn: boolean;
let loggingEnabled: boolean;
let logoutUser: onClick;
let totalTimeLoggedToday: string;
beforeEach(() => {
disableLogging = jest.fn();
enableLogging = jest.fn();
loggingEnabled = false;
loggedIn = false;
logoutUser = jest.fn();
totalTimeLoggedToday = '1/1/1999';
});
it('should render properly', () => {
const { container } = render(
const { container } = renderWithProviders(
<MainList
disableLogging={disableLogging}
enableLogging={enableLogging}
loggingEnabled={loggingEnabled}
loggedIn={loggedIn}
logoutUser={logoutUser}
totalTimeLoggedToday={totalTimeLoggedToday}
/>,
Expand Down
19 changes: 12 additions & 7 deletions src/components/MainList.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React from 'react';
import { useSelector } from 'react-redux';
import { ReduxSelector } from '../types/store';
import { User } from '../types/user';

export interface MainListProps {
disableLogging: (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => void;
enableLogging: (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => void;
loggedIn: boolean;
loggingEnabled: boolean;
logoutUser: (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => void;
totalTimeLoggedToday?: string;
Expand All @@ -15,14 +17,17 @@ const openOptionsPage = async (): Promise<void> => {
export default function MainList({
disableLogging,
enableLogging,
loggedIn,
loggingEnabled,
logoutUser,
totalTimeLoggedToday,
}: MainListProps): JSX.Element {
const user: User | undefined = useSelector(
(selector: ReduxSelector) => selector.currentUser.user,
);

return (
<div>
{loggedIn && (
{user && (
<div className="row">
<div className="col-xs-12">
<blockquote>
Expand All @@ -34,7 +39,7 @@ export default function MainList({
</div>
</div>
)}
{loggingEnabled && loggedIn && (
{loggingEnabled && user && (
<div className="row">
<div className="col-xs-12">
<p>
Expand All @@ -45,7 +50,7 @@ export default function MainList({
</div>
</div>
)}
{!loggingEnabled && loggedIn && (
{!loggingEnabled && user && (
<div className="row">
<div className="col-xs-12">
<p>
Expand All @@ -61,15 +66,15 @@ export default function MainList({
<i className="fa fa-fw fa-cogs"></i>
Options
</a>
{loggedIn && (
{user && (
<div>
<a href="#" className="list-group-item" onClick={logoutUser}>
<i className="fa fa-fw fa-sign-out"></i>
Logout
</a>
</div>
)}
{!loggedIn && (
{!user && (
<a
target="_blank"
rel="noreferrer"
Expand Down
180 changes: 180 additions & 0 deletions src/components/NavBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { configLogout, setApiKey } from '../reducers/configReducer';
import { userLogout } from '../reducers/currentUser';
import { ReduxSelector } from '../types/store';
import { User } from '../types/user';
import config from '../config/config';
import apiKeyInvalid from '../utils/apiKey';
import { fetchUserData } from '../utils/user';

export default function NavBar(): JSX.Element {
const [state, setState] = useState({
apiKey: '',
apiKeyError: '',
loading: false,
});
useEffect(() => {
const fetch = async () => {
const { apiKey } = await browser.storage.sync.get({ apiKey: config.apiKey });
setState({ ...state, apiKey });
};

fetch();
}, []);

const dispatch = useDispatch();
const user: User | undefined = useSelector(
(selector: ReduxSelector) => selector.currentUser.user,
);

const signedInAs = () => {
if (user) {
return (
<p className="navbar-text">
Signed in as <b>{user.full_name}</b>
</p>
);
} else {
return <div />;
}
};

const customRules = () => {
if (user) {
return (
<li>
<a target="_blank" href="https://wakatime.com/settings/rules" rel="noreferrer">
<i className="fa fa-fw fa-filter"></i>
Custom Rules
</a>
</li>
);
} else {
return <div />;
}
};

const dashboard = () => {
if (user) {
return (
<li>
<a target="_blank" href="https://wakatime.com/dashboard" rel="noreferrer">
<i className="fa fa-fw fa-tachometer"></i>
Dashboard
</a>
</li>
);
} else {
return <div />;
}
};

return (
<nav className="navbar navbar-default" role="navigation">
<div className="container-fluid">
<div className="navbar-header">
<button
type="button"
className="navbar-toggle collapsed"
data-toggle="collapse"
data-target="#bs-example-navbar-collapse-1"
>
<span className="sr-only">Toggle navigation</span>
<i className="fa fa-fw fa-cogs"></i>
</button>
<a target="_blank" className="navbar-brand" href="https://wakatime.com" rel="noreferrer">
WakaTime
<img src="graphics/wakatime-logo-48.png" />
</a>
</div>
<div className="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
{signedInAs()}
<ul className="nav navbar-nav">
{customRules()}
{dashboard()}
<li className="dropdown">
<a
href="#"
className="dropdown-toggle"
data-toggle="dropdown"
role="button"
aria-expanded="false"
>
<i className="fa fa-fw fa-info"></i>
About
<span className="caret"></span>
</a>
<ul className="dropdown-menu" role="menu">
<li>
<a
target="_blank"
href="https://github.com/wakatime/chrome-wakatime/issues"
rel="noreferrer"
>
<i className="fa fa-fw fa-bug"></i>
Report an Issue
</a>
</li>
<li>
<a
target="_blank"
href="https://github.com/wakatime/chrome-wakatime"
rel="noreferrer"
>
<i className="fa fa-fw fa-github"></i>
View on GitHub
</a>
</li>
</ul>
</li>
<li>
<div className="container-fluid">
{state.apiKeyError && (
<div className="alert alert-danger" role="alert">
{state.apiKeyError}
</div>
)}
<div className="input-group">
<input
type="text"
className="form-control"
placeholder="API key"
value={state.apiKey}
onChange={(e) => {
const key = e.target.value;
const isApiKeyInvalid = apiKeyInvalid(key);
setState({ ...state, apiKey: key, apiKeyError: isApiKeyInvalid });
}}
/>
<span className="input-group-btn">
<button
className={`btn btn-default ${state.loading ? 'disabled' : ''}`}
disabled={state.loading}
type="button"
data-loading-text="Loading..."
onClick={async () => {
if (state.apiKeyError === '' && state.apiKey !== '') {
setState({ ...state, loading: true });
await browser.storage.sync.set({ apiKey: state.apiKey });
dispatch(configLogout());
dispatch(userLogout());
dispatch(setApiKey(state.apiKey));

await fetchUserData(state.apiKey, dispatch);
setState({ ...state, loading: false });
}
}}
>
Save
</button>
</span>
</div>
</div>
</li>
</ul>
</div>
</div>
</nav>
);
}
80 changes: 80 additions & 0 deletions src/components/WakaTime.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import React, { useEffect, useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { ApiKeyReducer, ReduxSelector } from '../types/store';
import config from '../config/config';
import { fetchUserData } from '../utils/user';
import changeExtensionState from '../utils/changeExtensionState';
import NavBar from './NavBar';
import MainList from './MainList';

export default function WakaTime(): JSX.Element {
const dispatch = useDispatch();

const defaultState = {
loggingEnabled: config.loggingEnabled,
totalTimeLoggedToday: '0 minutes',
};
const [state, setState] = useState(defaultState);
const {
apiKey: apiKeyFromRedux,
loggingEnabled,
totalTimeLoggedToday,
}: ApiKeyReducer = useSelector((selector: ReduxSelector) => selector.config);

useEffect(() => {
fetchUserData(apiKeyFromRedux, dispatch);
}, []);

const disableLogging = async () => {
setState({
...state,
loggingEnabled: false,
});

await changeExtensionState('notLogging');

await browser.storage.sync.set({
loggingEnabled: false,
});
};

const enableLogging = async () => {
setState({
...state,
loggingEnabled: true,
});

await changeExtensionState('allGood');

await browser.storage.sync.set({
loggingEnabled: true,
});
};

const logoutUser = async () => {
await browser.storage.sync.set({ apiKey: '' });

setState(defaultState);

await changeExtensionState('notSignedIn');
};

return (
<div>
<NavBar />
<div className="container">
<div className="row">
<div className="col-md-12">
<MainList
disableLogging={disableLogging}
enableLogging={enableLogging}
loggingEnabled={loggingEnabled}
totalTimeLoggedToday={totalTimeLoggedToday}
logoutUser={logoutUser}
/>
</div>
</div>
</div>
</div>
);
}
1 change: 1 addition & 0 deletions src/config/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ describe('wakatime config', () => {
"type": "success",
},
},
"apiKey": "",
"colors": {
"allGood": "",
"lightTheme": "white",
Expand Down
Loading