feat(preferences): error reporting segment (#652)
* feat(preferences): error reporting segment * feat(preferences): move error reporting to general pane
This commit is contained in:
@@ -1,14 +1,14 @@
|
|||||||
import { RoundIconButton } from '@/components/RoundIconButton';
|
import { RoundIconButton } from '@/components/RoundIconButton';
|
||||||
import { TitleBar, Title } from '@/components/TitleBar';
|
import { TitleBar, Title } from '@/components/TitleBar';
|
||||||
import { FunctionComponent } from 'preact';
|
import { FunctionComponent } from 'preact';
|
||||||
import { AccountPreferences, HelpAndFeedback, Security } from './panes';
|
import { AccountPreferences, General, HelpAndFeedback, Security } from './panes';
|
||||||
import { observer } from 'mobx-react-lite';
|
import { observer } from 'mobx-react-lite';
|
||||||
import { PreferencesMenu } from './PreferencesMenu';
|
import { PreferencesMenu } from './PreferencesMenu';
|
||||||
import { PreferencesMenuView } from './PreferencesMenuView';
|
import { PreferencesMenuView } from './PreferencesMenuView';
|
||||||
import { WebApplication } from '@/ui_models/application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import { MfaProps } from './panes/two-factor-auth/MfaProps';
|
import { MfaProps } from './panes/two-factor-auth/MfaProps';
|
||||||
import { AppState } from '@/ui_models/app_state';
|
import { AppState } from '@/ui_models/app_state';
|
||||||
import { useCallback, useEffect } from 'preact/hooks';
|
import { useEffect } from 'preact/hooks';
|
||||||
|
|
||||||
interface PreferencesProps extends MfaProps {
|
interface PreferencesProps extends MfaProps {
|
||||||
application: WebApplication;
|
application: WebApplication;
|
||||||
@@ -21,7 +21,7 @@ const PaneSelector: FunctionComponent<
|
|||||||
> = observer((props) => {
|
> = observer((props) => {
|
||||||
switch (props.menu.selectedPaneId) {
|
switch (props.menu.selectedPaneId) {
|
||||||
case 'general':
|
case 'general':
|
||||||
return null;
|
return <General appState={props.appState} application={props.application} />
|
||||||
case 'account':
|
case 'account':
|
||||||
return (
|
return (
|
||||||
<AccountPreferences
|
<AccountPreferences
|
||||||
|
|||||||
@@ -7,18 +7,18 @@ const HorizontalLine: FunctionComponent<{ index: number; length: number }> = ({
|
|||||||
}) => (index < length - 1 ? <HorizontalSeparator classes="my-4" /> : null);
|
}) => (index < length - 1 ? <HorizontalSeparator classes="my-4" /> : null);
|
||||||
|
|
||||||
export const PreferencesGroup: FunctionComponent = ({ children }) => (
|
export const PreferencesGroup: FunctionComponent = ({ children }) => (
|
||||||
<div className="bg-default border-1 border-solid rounded border-gray-300 px-6 py-6 flex flex-col">
|
<div className="bg-default border-1 border-solid rounded border-gray-300 px-6 py-6 flex flex-col mb-3">
|
||||||
{Array.isArray(children)
|
{Array.isArray(children)
|
||||||
? children
|
? children
|
||||||
.filter(
|
.filter(
|
||||||
(child) => child != undefined && child !== '' && child !== false
|
(child) => child != undefined && child !== '' && child !== false
|
||||||
)
|
)
|
||||||
.map((child, i, arr) => (
|
.map((child, i, arr) => (
|
||||||
<>
|
<>
|
||||||
{child}
|
{child}
|
||||||
<HorizontalLine index={i} length={arr.length} />
|
<HorizontalLine index={i} length={arr.length} />
|
||||||
</>
|
</>
|
||||||
))
|
))
|
||||||
: children}
|
: children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,12 +7,6 @@ export const PreferencesPane: FunctionComponent = ({ children }) => (
|
|||||||
{children != undefined && Array.isArray(children)
|
{children != undefined && Array.isArray(children)
|
||||||
? children
|
? children
|
||||||
.filter((child) => child != undefined)
|
.filter((child) => child != undefined)
|
||||||
.map((child) => (
|
|
||||||
<>
|
|
||||||
{child}
|
|
||||||
<div className="min-h-3" />
|
|
||||||
</>
|
|
||||||
))
|
|
||||||
: children}
|
: children}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
16
app/assets/javascripts/preferences/panes/General.tsx
Normal file
16
app/assets/javascripts/preferences/panes/General.tsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { WebApplication } from '@/ui_models/application';
|
||||||
|
import { AppState } from '@/ui_models/app_state';
|
||||||
|
import { FunctionComponent } from 'preact';
|
||||||
|
import { PreferencesPane } from '../components';
|
||||||
|
import { ErrorReporting } from './general-segments';
|
||||||
|
|
||||||
|
interface GeneralProps {
|
||||||
|
appState: AppState;
|
||||||
|
application: WebApplication;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const General: FunctionComponent<GeneralProps> = (props) => (
|
||||||
|
<PreferencesPane>
|
||||||
|
<ErrorReporting appState={props.appState} />
|
||||||
|
</PreferencesPane>
|
||||||
|
);
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
import { useState } from 'preact/hooks';
|
||||||
|
import { storage, StorageKey } from '@Services/localStorage';
|
||||||
|
import { disableErrorReporting, enableErrorReporting, errorReportingId } from '@Services/errorReporting';
|
||||||
|
import { alertDialog } from '@Services/alertService';
|
||||||
|
import { observer } from 'mobx-react-lite';
|
||||||
|
import { AppState } from '@/ui_models/app_state';
|
||||||
|
import { FunctionComponent } from 'preact';
|
||||||
|
import { PreferencesGroup, PreferencesSegment, Title, Text } from '@/preferences/components';
|
||||||
|
import { Switch } from '@/components/Switch';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
appState: AppState;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ErrorReporting: FunctionComponent<Props> = observer(({ appState }: Props) => {
|
||||||
|
const [isErrorReportingEnabled] = useState(() => storage.get(StorageKey.DisableErrorReporting) === false);
|
||||||
|
const [errorReportingIdValue] = useState(() => errorReportingId());
|
||||||
|
|
||||||
|
const toggleErrorReportingEnabled = () => {
|
||||||
|
if (isErrorReportingEnabled) {
|
||||||
|
disableErrorReporting();
|
||||||
|
} else {
|
||||||
|
enableErrorReporting();
|
||||||
|
}
|
||||||
|
if (!appState.sync.inProgress) {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const openErrorReportingDialog = () => {
|
||||||
|
alertDialog({
|
||||||
|
title: 'Data sent during automatic error reporting',
|
||||||
|
text: `
|
||||||
|
We use <a target="_blank" rel="noreferrer" href="https://www.bugsnag.com/">Bugsnag</a>
|
||||||
|
to automatically report errors that occur while the app is running. See
|
||||||
|
<a target="_blank" rel="noreferrer" href="https://docs.bugsnag.com/platforms/javascript/#sending-diagnostic-data">
|
||||||
|
this article, paragraph 'Browser' under 'Sending diagnostic data',
|
||||||
|
</a>
|
||||||
|
to see what data is included in error reports.
|
||||||
|
<br><br>
|
||||||
|
Error reports never include IP addresses and are fully
|
||||||
|
anonymized. We use error reports to be alerted when something in our
|
||||||
|
code is causing unexpected errors and crashes in your application
|
||||||
|
experience.
|
||||||
|
`
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PreferencesGroup>
|
||||||
|
<PreferencesSegment>
|
||||||
|
|
||||||
|
<div className="flex flex-row items-center">
|
||||||
|
<div className="flex-grow flex flex-col">
|
||||||
|
<Title>Error Reporting</Title>
|
||||||
|
<Text>
|
||||||
|
Help us improve Standard Notes by automatically submitting
|
||||||
|
anonymized error reports.
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col justify-center items-center min-w-15">
|
||||||
|
<Switch onChange={toggleErrorReportingEnabled} checked={isErrorReportingEnabled} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="min-h-2" />
|
||||||
|
|
||||||
|
{errorReportingIdValue && (
|
||||||
|
<>
|
||||||
|
<Text>
|
||||||
|
Your random identifier is <span className="font-bold">{errorReportingIdValue}</span>
|
||||||
|
</Text>
|
||||||
|
<Text>
|
||||||
|
Disabling error reporting will remove that identifier from your
|
||||||
|
local storage, and a new identifier will be created should you
|
||||||
|
decide to enable error reporting again in the future.
|
||||||
|
</Text>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Text>
|
||||||
|
<a className="cursor-pointer" onClick={openErrorReportingDialog}>What data is being sent?</a>
|
||||||
|
</Text>
|
||||||
|
</PreferencesSegment>
|
||||||
|
</PreferencesGroup>
|
||||||
|
);
|
||||||
|
});
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './ErrorReporting';
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
export * from './HelpFeedback';
|
export * from './HelpFeedback';
|
||||||
export * from './Security';
|
export * from './Security';
|
||||||
export * from './AccountPreferences';
|
export * from './AccountPreferences';
|
||||||
|
export * from './General';
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { ApplicationEvent } from '@standardnotes/snjs';
|
|||||||
import { isSameDay } from '@/utils';
|
import { isSameDay } from '@/utils';
|
||||||
import { PreferencesGroup, PreferencesSegment, Title, Text } from '@/preferences/components';
|
import { PreferencesGroup, PreferencesSegment, Title, Text } from '@/preferences/components';
|
||||||
import { Button } from '@/components/Button';
|
import { Button } from '@/components/Button';
|
||||||
import { Switch } from '@/components/Switch';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
application: WebApplication;
|
application: WebApplication;
|
||||||
|
|||||||
Reference in New Issue
Block a user