mirror of
https://github.com/actualbudget/actual.git
synced 2026-04-28 10:33:02 -05:00
lint: patch some no-empty-function violations & delete unused code (#6642)
* lint: patch some no-empty-function violations * docs: update ESLint rules and remove unused loadOwner function in UserAccess component * refactor: remove getRemoteFile function and associated method from budget file handlers * chore: disable docstring checks in coderabbit configuration
This commit is contained in:
committed by
GitHub
parent
0c3a515e29
commit
b88feb9336
@@ -10,6 +10,7 @@ reviews:
|
||||
enabled: false
|
||||
pre_merge_checks:
|
||||
docstrings:
|
||||
mode: off
|
||||
enabled: false
|
||||
custom_checks:
|
||||
- mode: error
|
||||
|
||||
@@ -464,16 +464,9 @@
|
||||
// TODO: enable these
|
||||
{
|
||||
"files": [
|
||||
"packages/desktop-client/src/components/admin/UserAccess/UserAccess.tsx",
|
||||
"packages/desktop-client/src/components/admin/UserDirectory/UserDirectory.tsx",
|
||||
"packages/desktop-client/src/components/budget/BudgetCategories.tsx",
|
||||
"packages/desktop-client/src/components/budget/envelope/BalanceMovementMenu.tsx",
|
||||
"packages/desktop-client/src/components/ManageRules.tsx",
|
||||
"packages/desktop-client/src/components/mobile/budget/ExpenseGroupList.tsx",
|
||||
"packages/desktop-client/src/components/modals/EditFieldModal.tsx",
|
||||
"packages/desktop-client/src/components/reports/reports/Calendar.tsx",
|
||||
"packages/desktop-client/src/components/schedules/ScheduleLink.tsx",
|
||||
"packages/desktop-client/src/components/ServerContext.tsx",
|
||||
"packages/desktop-client/src/components/table.tsx"
|
||||
],
|
||||
"rules": {
|
||||
|
||||
@@ -169,7 +169,7 @@ Custom ESLint rules specific to Actual.
|
||||
|
||||
- `no-untranslated-strings`: Enforces i18n usage
|
||||
- `prefer-trans-over-t`: Prefers Trans component over t() function
|
||||
- `prefer-logger-over-console`: Enforces using logger instead of console
|
||||
- `prefer-logger-over-console`: Enforces using logger instead of console in `packages/loot-core/`
|
||||
- `typography`: Typography rules
|
||||
- `prefer-if-statement`: Prefers explicit if statements
|
||||
|
||||
@@ -328,7 +328,6 @@ Always maintain newlines between import groups.
|
||||
|
||||
**Never:**
|
||||
|
||||
- Use `console.*` (use logger instead - enforced by ESLint)
|
||||
- Import from `uuid` without destructuring: use `import { v4 as uuidv4 } from 'uuid'`
|
||||
- Import colors directly - use theme instead
|
||||
- Import `@actual-app/web/*` in `loot-core`
|
||||
@@ -541,7 +540,6 @@ Before committing changes, ensure:
|
||||
- [ ] `yarn typecheck` passes
|
||||
- [ ] `yarn lint:fix` has been run
|
||||
- [ ] Relevant tests pass
|
||||
- [ ] No new console.\* usage (use logger)
|
||||
- [ ] User-facing strings are translated
|
||||
- [ ] Prefer `type` over `interface`
|
||||
- [ ] Named exports used (not default exports)
|
||||
|
||||
@@ -43,8 +43,12 @@ const ServerContext = createContext<ServerContextValue>({
|
||||
setURL: () => Promise.reject(new Error('ServerContext not initialized')),
|
||||
refreshLoginMethods: () =>
|
||||
Promise.reject(new Error('ServerContext not initialized')),
|
||||
setMultiuserEnabled: () => {},
|
||||
setLoginMethods: () => {},
|
||||
setMultiuserEnabled: () => {
|
||||
throw new Error('ServerContext not initialized');
|
||||
},
|
||||
setLoginMethods: () => {
|
||||
throw new Error('ServerContext not initialized');
|
||||
},
|
||||
});
|
||||
|
||||
export const useServerURL = () => useContext(ServerContext).url;
|
||||
|
||||
@@ -4,8 +4,6 @@ import React, {
|
||||
useEffect,
|
||||
useCallback,
|
||||
useMemo,
|
||||
type SetStateAction,
|
||||
type Dispatch,
|
||||
type CSSProperties,
|
||||
} from 'react';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
@@ -38,13 +36,9 @@ import { useDispatch } from '@desktop-client/redux';
|
||||
|
||||
type ManageUserAccessContentProps = {
|
||||
isModal: boolean;
|
||||
setLoading?: Dispatch<SetStateAction<boolean>>;
|
||||
};
|
||||
|
||||
function UserAccessContent({
|
||||
isModal,
|
||||
setLoading,
|
||||
}: ManageUserAccessContentProps) {
|
||||
function UserAccessContent({ isModal }: ManageUserAccessContentProps) {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const [allAccess, setAllAccess] = useState([]);
|
||||
@@ -76,7 +70,6 @@ function UserAccessContent({
|
||||
);
|
||||
|
||||
const loadAccess = useCallback(async () => {
|
||||
setLoading(true);
|
||||
const data: Awaited<ReturnType<Handlers['access-get-available-users']>> =
|
||||
await send('access-get-available-users', cloudFileId as string);
|
||||
|
||||
@@ -111,20 +104,7 @@ function UserAccessContent({
|
||||
|
||||
setAllAccess(loadedAccess);
|
||||
return loadedAccess;
|
||||
}, [cloudFileId, dispatch, setLoading, t]);
|
||||
|
||||
const loadOwner = useCallback(async () => {
|
||||
const file = (await send('get-user-file-info', cloudFileId as string)) ?? {
|
||||
usersWithAccess: [],
|
||||
};
|
||||
const owner = file?.usersWithAccess.filter(user => user.owner);
|
||||
|
||||
if (owner.length > 0) {
|
||||
return owner[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}, [cloudFileId]);
|
||||
}, [cloudFileId, dispatch, t]);
|
||||
|
||||
useEffect(() => {
|
||||
async function loadData() {
|
||||
@@ -132,8 +112,6 @@ function UserAccessContent({
|
||||
await loadAccess();
|
||||
} catch (error) {
|
||||
console.error('Error loading user access data:', error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +120,7 @@ function UserAccessContent({
|
||||
return () => {
|
||||
undo.setUndoState('openModal', null);
|
||||
};
|
||||
}, [setLoading, loadAccess, loadOwner]);
|
||||
}, [loadAccess]);
|
||||
|
||||
function loadMore() {
|
||||
setPage(page => page + 1);
|
||||
@@ -213,7 +191,6 @@ function UserAccessContent({
|
||||
style={{ width: 16, height: 16 }}
|
||||
onToggleSave={async () => {
|
||||
await loadAccess();
|
||||
setLoading(false);
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
@@ -223,14 +200,10 @@ function UserAccessContent({
|
||||
|
||||
type ManageUsersProps = {
|
||||
isModal: boolean;
|
||||
setLoading?: Dispatch<SetStateAction<boolean>>;
|
||||
};
|
||||
|
||||
export function UserAccess({
|
||||
isModal,
|
||||
setLoading = () => {},
|
||||
}: ManageUsersProps) {
|
||||
return <UserAccessContent isModal={isModal} setLoading={setLoading} />;
|
||||
export function UserAccess({ isModal }: ManageUsersProps) {
|
||||
return <UserAccessContent isModal={isModal} />;
|
||||
}
|
||||
|
||||
type UsersAccessListProps = {
|
||||
|
||||
@@ -4,8 +4,6 @@ import {
|
||||
useEffect,
|
||||
useCallback,
|
||||
useMemo,
|
||||
type SetStateAction,
|
||||
type Dispatch,
|
||||
type CSSProperties,
|
||||
} from 'react';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
@@ -37,7 +35,6 @@ import { signOut } from '@desktop-client/users/usersSlice';
|
||||
|
||||
type ManageUserDirectoryContentProps = {
|
||||
isModal: boolean;
|
||||
setLoading?: Dispatch<SetStateAction<boolean>>;
|
||||
};
|
||||
|
||||
function useGetUserDirectoryErrors() {
|
||||
@@ -81,10 +78,7 @@ function useGetUserDirectoryErrors() {
|
||||
return { getUserDirectoryErrors };
|
||||
}
|
||||
|
||||
function UserDirectoryContent({
|
||||
isModal,
|
||||
setLoading,
|
||||
}: ManageUserDirectoryContentProps) {
|
||||
function UserDirectoryContent({ isModal }: ManageUserDirectoryContentProps) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [allUsers, setAllUsers] = useState([]);
|
||||
@@ -120,8 +114,6 @@ function UserDirectoryContent({
|
||||
);
|
||||
|
||||
const loadUsers = useCallback(async () => {
|
||||
setLoading(true);
|
||||
|
||||
const loadedUsers = (await send('users-get')) ?? [];
|
||||
if ('error' in loadedUsers) {
|
||||
dispatch(
|
||||
@@ -135,19 +127,16 @@ function UserDirectoryContent({
|
||||
},
|
||||
}),
|
||||
);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
setAllUsers(loadedUsers);
|
||||
setLoading(false);
|
||||
return loadedUsers;
|
||||
}, [dispatch, getUserDirectoryErrors, setLoading, t]);
|
||||
}, [dispatch, getUserDirectoryErrors, t]);
|
||||
|
||||
useEffect(() => {
|
||||
async function loadData() {
|
||||
await loadUsers();
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
loadData();
|
||||
@@ -155,14 +144,13 @@ function UserDirectoryContent({
|
||||
return () => {
|
||||
undo.setUndoState('openModal', null);
|
||||
};
|
||||
}, [setLoading, loadUsers]);
|
||||
}, [loadUsers]);
|
||||
|
||||
function loadMore() {
|
||||
setPage(page => page + 1);
|
||||
}
|
||||
|
||||
const onDeleteSelected = useCallback(async () => {
|
||||
setLoading(true);
|
||||
const res = await send('user-delete-all', [...selectedInst.items]);
|
||||
|
||||
const error = res['error'];
|
||||
@@ -202,15 +190,7 @@ function UserDirectoryContent({
|
||||
|
||||
await loadUsers();
|
||||
selectedInst.dispatch({ type: 'select-none' });
|
||||
setLoading(false);
|
||||
}, [
|
||||
setLoading,
|
||||
selectedInst,
|
||||
loadUsers,
|
||||
dispatch,
|
||||
t,
|
||||
getUserDirectoryErrors,
|
||||
]);
|
||||
}, [selectedInst, loadUsers, dispatch, t, getUserDirectoryErrors]);
|
||||
|
||||
const onEditUser = useCallback(
|
||||
user => {
|
||||
@@ -222,14 +202,13 @@ function UserDirectoryContent({
|
||||
user,
|
||||
onSave: async () => {
|
||||
await loadUsers();
|
||||
setLoading(false);
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
},
|
||||
[dispatch, loadUsers, setLoading],
|
||||
[dispatch, loadUsers],
|
||||
);
|
||||
|
||||
function onAddUser() {
|
||||
@@ -248,7 +227,6 @@ function UserDirectoryContent({
|
||||
user,
|
||||
onSave: async () => {
|
||||
await loadUsers();
|
||||
setLoading(false);
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -370,14 +348,10 @@ function EmptyMessage({ text, style }: EmptyMessageProps) {
|
||||
|
||||
type ManageUsersProps = {
|
||||
isModal: boolean;
|
||||
setLoading?: Dispatch<SetStateAction<boolean>>;
|
||||
};
|
||||
|
||||
export function UserDirectory({
|
||||
isModal,
|
||||
setLoading = () => {},
|
||||
}: ManageUsersProps) {
|
||||
return <UserDirectoryContent isModal={isModal} setLoading={setLoading} />;
|
||||
export function UserDirectory({ isModal }: ManageUsersProps) {
|
||||
return <UserDirectoryContent isModal={isModal} />;
|
||||
}
|
||||
|
||||
type UsersListProps = {
|
||||
|
||||
@@ -282,7 +282,6 @@ export const BudgetCategories = memo<BudgetCategoriesProps>(
|
||||
}}
|
||||
editing
|
||||
onSave={_onSaveCategory}
|
||||
onDelete={async () => {}}
|
||||
onHideNewCategory={onHideNewCategory}
|
||||
onEditName={onEditName!}
|
||||
/>
|
||||
|
||||
@@ -27,16 +27,23 @@ type SidebarCategoryProps = {
|
||||
categoryGroup?: CategoryGroupEntity;
|
||||
dragPreview?: boolean;
|
||||
dragging?: boolean;
|
||||
editing: boolean;
|
||||
goalsShown?: boolean;
|
||||
style?: CSSProperties;
|
||||
borderColor?: string;
|
||||
isLast?: boolean;
|
||||
onEditName: (id: CategoryEntity['id']) => void;
|
||||
onSave: (category: CategoryEntity) => void;
|
||||
onDelete: (id: CategoryEntity['id']) => void;
|
||||
onHideNewCategory?: () => void;
|
||||
};
|
||||
} & (
|
||||
| {
|
||||
editing: true;
|
||||
onDelete?: never;
|
||||
}
|
||||
| {
|
||||
editing: boolean;
|
||||
onDelete: (id: CategoryEntity['id']) => void;
|
||||
}
|
||||
);
|
||||
|
||||
export function SidebarCategory({
|
||||
innerRef,
|
||||
|
||||
@@ -12,14 +12,14 @@ type BalanceMovementMenuProps = {
|
||||
categoryId: string;
|
||||
month: string;
|
||||
onBudgetAction: (month: string, action: string, arg?: unknown) => void;
|
||||
onClose?: () => void;
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
export function BalanceMovementMenu({
|
||||
categoryId,
|
||||
month,
|
||||
onBudgetAction,
|
||||
onClose = () => {},
|
||||
onClose,
|
||||
}: BalanceMovementMenuProps) {
|
||||
const format = useFormat();
|
||||
|
||||
|
||||
@@ -109,7 +109,6 @@ export function EditFieldModal({
|
||||
value={formatDate(parseISO(today), dateFormat)}
|
||||
dateFormat={dateFormat}
|
||||
embedded
|
||||
onUpdate={() => {}}
|
||||
onSelect={date => {
|
||||
onSelect(dayFromDate(parseDate(date, 'yyyy-MM-dd', new Date())));
|
||||
close();
|
||||
|
||||
@@ -149,7 +149,6 @@ export function ScheduleLink({
|
||||
allowCompleted={false}
|
||||
filter={filter}
|
||||
minimal
|
||||
onAction={() => {}}
|
||||
onSelect={id => {
|
||||
onSelect(id);
|
||||
close();
|
||||
|
||||
@@ -45,11 +45,21 @@ type SchedulesTableProps = {
|
||||
filter: string;
|
||||
allowCompleted: boolean;
|
||||
onSelect: (id: ScheduleEntity['id']) => void;
|
||||
onAction: (actionName: ScheduleItemAction, id: ScheduleEntity['id']) => void;
|
||||
style: CSSProperties;
|
||||
minimal?: boolean;
|
||||
tableStyle?: CSSProperties;
|
||||
};
|
||||
} & (
|
||||
| {
|
||||
minimal: true;
|
||||
onAction?: never;
|
||||
}
|
||||
| {
|
||||
minimal?: false;
|
||||
onAction: (
|
||||
actionName: ScheduleItemAction,
|
||||
id: ScheduleEntity['id'],
|
||||
) => void;
|
||||
}
|
||||
);
|
||||
|
||||
type CompletedScheduleItem = { id: 'show-completed' };
|
||||
type SchedulesTableItem = ScheduleEntity | CompletedScheduleItem;
|
||||
|
||||
@@ -47,7 +47,6 @@ export type BudgetFileHandlers = {
|
||||
'unique-budget-name': typeof handleUniqueBudgetName;
|
||||
'get-budgets': typeof getBudgets;
|
||||
'get-remote-files': typeof getRemoteFiles;
|
||||
'get-user-file-info': typeof getUserFileInfo;
|
||||
'reset-budget-cache': typeof resetBudgetCache;
|
||||
'upload-budget': typeof uploadBudget;
|
||||
'download-budget': typeof downloadBudget;
|
||||
@@ -72,7 +71,6 @@ app.method('validate-budget-name', handleValidateBudgetName);
|
||||
app.method('unique-budget-name', handleUniqueBudgetName);
|
||||
app.method('get-budgets', getBudgets);
|
||||
app.method('get-remote-files', getRemoteFiles);
|
||||
app.method('get-user-file-info', getUserFileInfo);
|
||||
app.method('reset-budget-cache', mutator(resetBudgetCache));
|
||||
app.method('upload-budget', uploadBudget);
|
||||
app.method('download-budget', downloadBudget);
|
||||
@@ -140,10 +138,6 @@ async function getRemoteFiles() {
|
||||
return cloudStorage.listRemoteFiles();
|
||||
}
|
||||
|
||||
async function getUserFileInfo(fileId: string) {
|
||||
return cloudStorage.getRemoteFile(fileId);
|
||||
}
|
||||
|
||||
async function resetBudgetCache() {
|
||||
// Recomputing everything will update the cache
|
||||
await sheet.loadUserBudgets(db);
|
||||
|
||||
@@ -402,38 +402,6 @@ export async function listRemoteFiles(): Promise<RemoteFile[]> {
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
export async function getRemoteFile(
|
||||
fileId: string,
|
||||
): Promise<RemoteFile | null> {
|
||||
const userToken = await asyncStorage.getItem('user-token');
|
||||
if (!userToken) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let res;
|
||||
try {
|
||||
res = await fetchJSON(getServer().SYNC_SERVER + '/get-user-file-info', {
|
||||
headers: {
|
||||
'X-ACTUAL-TOKEN': userToken,
|
||||
'X-ACTUAL-FILE-ID': fileId,
|
||||
},
|
||||
});
|
||||
} catch (e) {
|
||||
logger.log('Unexpected error fetching file from server', e);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (res.status === 'error') {
|
||||
logger.log('Error fetching file from server', res);
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
...res.data,
|
||||
hasKey: encryption.hasKey(res.data.encryptKeyId),
|
||||
};
|
||||
}
|
||||
|
||||
export async function download(cloudFileId) {
|
||||
const userToken = await asyncStorage.getItem('user-token');
|
||||
const syncServer = getServer().SYNC_SERVER;
|
||||
|
||||
6
upcoming-release-notes/6642.md
Normal file
6
upcoming-release-notes/6642.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
category: Maintenance
|
||||
authors: [MatissJanis]
|
||||
---
|
||||
|
||||
lint: patch some no-empty-function violations
|
||||
Reference in New Issue
Block a user