diff --git a/specifyweb/analyze_cov.py b/specifyweb/analyze_cov.py new file mode 100644 index 00000000000..9098d8f4491 --- /dev/null +++ b/specifyweb/analyze_cov.py @@ -0,0 +1,103 @@ +import sys +import json + +with open(sys.argv[1]) as f: + cov = json.loads(f.read()) + +apps = { + key: value["summary"] + for (key, value) in cov["files"].items() + if key.startswith("specifyweb/") +} + +data = {} +for key, value in apps.items(): + key_split = key.split("/") + assert len(key_split) >= 2 + context = data + previous_context = context + for node in key_split[:-1]: + context[node] = context.get(node, dict(report=None, children={})) + context = context[node]["children"] + + context[key_split[-1]] = dict(report=value, children={}) + + +def make_report(cov_lines, num_lines): + return dict( + covered_lines=cov_lines, + num_statements=num_lines, + percent_covered=100 if num_lines == 0 else (cov_lines * 100 / num_lines), + ) + + +def get_lines(current_context): + previous_report = current_context["report"] + if previous_report is not None: + return previous_report["covered_lines"], previous_report["num_statements"] + cov_lines = 0 + num_stmts = 0 + for child in current_context["children"].values(): + child_cov_lines, child_num_stmts = get_lines(child) + cov_lines += child_cov_lines + num_stmts += child_num_stmts + + current_context["report"] = make_report(cov_lines, num_stmts) + return (cov_lines, num_stmts) + + +get_lines(data["specifyweb"]) + +with open("dumped.json", "w") as f: + f.write(json.dumps(data, indent=4)) + + +def _get_tuples(obj): + to_return = [ + dict(appName=key, report=value.get("report")) for (key, value) in obj.items() + ] + + tuples = [ + ",".join( + [ + obj["appName"], + str(obj["report"]["covered_lines"]), + str(obj["report"]["num_statements"]), + str(obj["report"]["percent_covered"]), + ] + ) + for obj in to_return + ] + + tuples = [ + ",".join(["appname", "covered_lines", "num_statements", "percent covered"]), + *tuples, + ] + + return to_return, tuples + + +specifyweb_children, tuples = _get_tuples(data["specifyweb"]["children"]) + + +# with open("dumped_per_app.json", "w") as f: + +# f.write(json.dumps(specifyweb_children, indent=4)) + +# with open("/mnt/c/Users/realv/Desktop/specify/apps_report.csv", "w") as f: + +# f.write("\n".join(tuples)) + + +specify_app, specify_tuples = _get_tuples( + data["specifyweb"]["children"]["specify"]["children"] +) + + +with open("dumped_specify_app.json", "w") as f: + + f.write(json.dumps(specify_app, indent=4)) + +with open("/mnt/c/Users/realv/Desktop/specify/apps_report_specify.csv", "w") as f: + + f.write("\n".join(specify_tuples)) diff --git a/specifyweb/frontend/js_src/lib/components/DataModel/__tests__/businessRules.test.ts b/specifyweb/frontend/js_src/lib/components/DataModel/__tests__/businessRules.test.ts index 26226f396f9..a16a9b761b2 100644 --- a/specifyweb/frontend/js_src/lib/components/DataModel/__tests__/businessRules.test.ts +++ b/specifyweb/frontend/js_src/lib/components/DataModel/__tests__/businessRules.test.ts @@ -893,9 +893,8 @@ describe('treeBusinessRules', () => { expect(fieldChangeResult.current[0]).toStrictEqual(['Bad tree structure.']); }); test('saveBlocker not on synonymized parent w/preference', async () => { - const { collectionPreferences } = await import( - '../../Preferences/collectionPreferences' - ); + const { collectionPreferences } = + await import('../../Preferences/collectionPreferences'); const originalRaw = collectionPreferences.getRaw(); collectionPreferences.setRaw({ ...originalRaw, diff --git a/specifyweb/frontend/js_src/lib/components/DataModel/businessRuleDefs.ts b/specifyweb/frontend/js_src/lib/components/DataModel/businessRuleDefs.ts index 5b0fe4fe7d0..d8921c1df49 100644 --- a/specifyweb/frontend/js_src/lib/components/DataModel/businessRuleDefs.ts +++ b/specifyweb/frontend/js_src/lib/components/DataModel/businessRuleDefs.ts @@ -201,9 +201,10 @@ export const businessRuleDefs: MappedBusinessRuleDefs = { return undefined; }, catalogNumber: async (resource): Promise => { - const preferences = await import( - '../Preferences/collectionPreferences' - ).then(({ collectionPreferences }) => collectionPreferences); + const preferences = + await import('../Preferences/collectionPreferences').then( + ({ collectionPreferences }) => collectionPreferences + ); const uniqueCatalogNumberAccrossComponentAndCOPref = preferences.get( 'uniqueCatalogNumberAccrossComponentAndCO', @@ -429,9 +430,10 @@ export const businessRuleDefs: MappedBusinessRuleDefs = { return undefined; }, catalogNumber: async (resource): Promise => { - const preferences = await import( - '../Preferences/collectionPreferences' - ).then(({ collectionPreferences }) => collectionPreferences); + const preferences = + await import('../Preferences/collectionPreferences').then( + ({ collectionPreferences }) => collectionPreferences + ); const uniqueCatalogNumberAccrossComponentAndCOPref = preferences.get( 'uniqueCatalogNumberAccrossComponentAndCO', diff --git a/specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/ExpressSearchConfigDialog.tsx b/specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/ExpressSearchConfigDialog.tsx index 6c5b8a531b5..81cc07e0bd3 100644 --- a/specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/ExpressSearchConfigDialog.tsx +++ b/specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/ExpressSearchConfigDialog.tsx @@ -14,7 +14,7 @@ type ExpressSearchConfigDialogProps = { readonly isOpen: boolean; readonly onClose: () => void; readonly onSave?: () => void; -} +}; export function ExpressSearchConfigDialog({ isOpen, @@ -76,7 +76,7 @@ export function ExpressSearchConfigDialog({ isOpen={isOpen} onClose={onClose} > - diff --git a/specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/ResultsOrderingTab.tsx b/specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/ResultsOrderingTab.tsx index 4478fd66f5a..437e55abc1b 100644 --- a/specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/ResultsOrderingTab.tsx +++ b/specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/ResultsOrderingTab.tsx @@ -11,12 +11,17 @@ import { genericTables } from '../DataModel/tables'; function tableLabel(tableName: string): string { return ( - (genericTables[tableName as keyof typeof genericTables]?.label as string | undefined) ?? - camelToHuman(tableName) + (genericTables[tableName as keyof typeof genericTables]?.label as + | string + | undefined) ?? camelToHuman(tableName) ); } -export function ResultsOrderingTab({ config, relatedQueriesDefinitions = [], onChangeConfig }: any) { +export function ResultsOrderingTab({ + config, + relatedQueriesDefinitions = [], + onChangeConfig, +}: any) { const baseTables = config.tables .filter((t: any) => t.searchFields.some((sf: any) => sf.inUse !== false)) .map((t: any) => ({ @@ -29,8 +34,12 @@ export function ResultsOrderingTab({ config, relatedQueriesDefinitions = [], onC const activeQueries = config.relatedQueries .filter((rq: any) => rq.isActive) .map((rq: any) => { - const def = relatedQueriesDefinitions.find((def: any) => def.id === rq.id); - const title = def?.name ? getExpressSearchQueryTitle(def.name) : undefined; + const def = relatedQueriesDefinitions.find( + (def: any) => def.id === rq.id + ); + const title = def?.name + ? getExpressSearchQueryTitle(def.name) + : undefined; if (!def || !title || title === String(def.name)) { return undefined; @@ -86,7 +95,9 @@ export function ResultsOrderingTab({ config, relatedQueriesDefinitions = [], onC return (
-

{expressSearchConfigText.configureResultsOrdering()}

+

+ {expressSearchConfigText.configureResultsOrdering()} +

{expressSearchConfigText.reorderResultsOrderingDescription()}

@@ -99,7 +110,10 @@ export function ResultsOrderingTab({ config, relatedQueriesDefinitions = [], onC > {item.label}
- moveItem(index, 'up')}> + moveItem(index, 'up')} + > {icons.chevronUp} { @@ -65,42 +65,43 @@ describe('ExpressSearchConfigEditor', () => { }); expect(onChangeJSON).toHaveBeenCalled(); - const latestConfig = onChangeJSON.mock.calls[onChangeJSON.mock.calls.length - 1][0]; + const latestConfig = + onChangeJSON.mock.calls[onChangeJSON.mock.calls.length - 1][0]; expect(latestConfig.tables[0].tableName).toBe('Agent'); expect(latestConfig.tables[0].searchFields[0].fieldName).toBe('firstName'); }); test('renders loading state initially', async () => { const { getByText } = mount( - ); expect(getByText('Loading...')).toBeInTheDocument(); - + // Wait for it to finish loading to avoid act warnings await act(async () => { - await new Promise(resolve => setTimeout(resolve, 0)); + await new Promise((resolve) => setTimeout(resolve, 0)); }); }); test('renders tabs after data load', async () => { const { findByRole } = mount( - ); - + expect(await findByRole('tablist')).toBeInTheDocument(); }); test('switches tabs correctly', async () => { const { findByText, getByRole, user } = mount( - ); @@ -112,7 +113,7 @@ describe('ExpressSearchConfigEditor', () => { await act(async () => { await user.click(relatedTab); }); - + expect(await findByText('Related Tables Tab')).toBeInTheDocument(); // Click Results Ordering diff --git a/specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/__tests__/RelatedTablesTab.test.tsx b/specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/__tests__/RelatedTablesTab.test.tsx index bacba609689..e096a045a54 100644 --- a/specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/__tests__/RelatedTablesTab.test.tsx +++ b/specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/__tests__/RelatedTablesTab.test.tsx @@ -43,7 +43,9 @@ describe('RelatedTablesTab', () => { expect(onChangeConfig).toHaveBeenCalledTimes(1); const newConfig = onChangeConfig.mock.calls[0][0]; - expect(newConfig.relatedQueries.find((rq: any) => rq.id === '2').isActive).toBe(true); + expect( + newConfig.relatedQueries.find((rq: any) => rq.id === '2').isActive + ).toBe(true); const activeRow = rows[0]; const activeCheckbox = activeRow.querySelector('input[type="checkbox"]'); @@ -54,6 +56,8 @@ describe('RelatedTablesTab', () => { expect(onChangeConfig).toHaveBeenCalledTimes(2); const secondConfig = onChangeConfig.mock.calls[1][0]; - expect(secondConfig.relatedQueries.find((rq: any) => rq.id === '1').isActive).toBe(false); + expect( + secondConfig.relatedQueries.find((rq: any) => rq.id === '1').isActive + ).toBe(false); }); }); diff --git a/specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/__tests__/ResultsOrderingTab.test.tsx b/specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/__tests__/ResultsOrderingTab.test.tsx index 5997fc65f7c..4b15f595931 100644 --- a/specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/__tests__/ResultsOrderingTab.test.tsx +++ b/specifyweb/frontend/js_src/lib/components/ExpressSearchConfig/__tests__/ResultsOrderingTab.test.tsx @@ -39,9 +39,7 @@ describe('ResultsOrderingTab', () => { displayFields: [], }, ], - relatedQueries: [ - { id: '8', isActive: true, displayOrder: 1 }, - ], + relatedQueries: [{ id: '8', isActive: true, displayOrder: 1 }], }; const onChangeConfig = jest.fn(); diff --git a/specifyweb/frontend/js_src/lib/components/FormCells/FormTable.tsx b/specifyweb/frontend/js_src/lib/components/FormCells/FormTable.tsx index 0eaae790141..baf13a48768 100644 --- a/specifyweb/frontend/js_src/lib/components/FormCells/FormTable.tsx +++ b/specifyweb/frontend/js_src/lib/components/FormCells/FormTable.tsx @@ -214,8 +214,8 @@ export function FormTable({ resource.cid, Boolean( resource.specifyTable.name === 'Preparation' && - collectionPreparationPref && - resource.isNew() + collectionPreparationPref && + resource.isNew() ), ]) ) diff --git a/specifyweb/frontend/js_src/lib/components/Header/ExpressSearchHooks.tsx b/specifyweb/frontend/js_src/lib/components/Header/ExpressSearchHooks.tsx index a59d68078c7..62177d62253 100644 --- a/specifyweb/frontend/js_src/lib/components/Header/ExpressSearchHooks.tsx +++ b/specifyweb/frontend/js_src/lib/components/Header/ExpressSearchHooks.tsx @@ -52,14 +52,13 @@ export function usePrimarySearch( } async function fetchRelatedSearches(): Promise> { - return contextUnlockedPromise.then( - async (entrypoint) => - entrypoint === 'main' - ? ajax>('/context/available_related_searches.json', { - headers: { Accept: 'application/json' }, - cache: 'no-store', - }).then(({ data }) => data) - : foreverFetch>() + return contextUnlockedPromise.then(async (entrypoint) => + entrypoint === 'main' + ? ajax>('/context/available_related_searches.json', { + headers: { Accept: 'application/json' }, + cache: 'no-store', + }).then(({ data }) => data) + : foreverFetch>() ); } diff --git a/specifyweb/frontend/js_src/lib/components/Header/ExpressSearchTask.tsx b/specifyweb/frontend/js_src/lib/components/Header/ExpressSearchTask.tsx index 60686c9bccf..b392a409b6d 100644 --- a/specifyweb/frontend/js_src/lib/components/Header/ExpressSearchTask.tsx +++ b/specifyweb/frontend/js_src/lib/components/Header/ExpressSearchTask.tsx @@ -125,11 +125,7 @@ function ExpressSearchInstructions({ {headerText.documentation()} )} - +
    @@ -147,10 +143,8 @@ export function ExpressSearchView(): JSX.Element { const [pendingQuery] = value; const [isConfigOpen, setIsConfigOpen] = React.useState(false); const [configRefreshTrigger, setConfigRefreshTrigger] = React.useState(0); - const [showInstructions = true, setShowExpressSearchInstructions] = useCachedState( - 'expressSearch', - 'showSearchTips' - ); + const [showInstructions = true, setShowExpressSearchInstructions] = + useCachedState('expressSearch', 'showSearchTips'); const canEditExpressSearchConfig = hasToolPermission('resources', 'read') && hasToolPermission('resources', 'create') && @@ -176,11 +170,15 @@ export function ExpressSearchView(): JSX.Element { setShowExpressSearchInstructions((value) => !value)} + onClick={(): void => + setShowExpressSearchInstructions((value) => !value) + } /> {showInstructions && ( - setShowExpressSearchInstructions(false)} /> + setShowExpressSearchInstructions(false)} + /> )}
    setQuery(pendingQuery)}>
    diff --git a/specifyweb/frontend/js_src/lib/components/Notifications/NotificationRenderers.tsx b/specifyweb/frontend/js_src/lib/components/Notifications/NotificationRenderers.tsx index 26f4696c407..790b3373284 100644 --- a/specifyweb/frontend/js_src/lib/components/Notifications/NotificationRenderers.tsx +++ b/specifyweb/frontend/js_src/lib/components/Notifications/NotificationRenderers.tsx @@ -395,9 +395,7 @@ export const notificationRenderers: IR< ); }, 'collection-creation-starting'() { - return ( -

    {setupToolText.collectionCreationStarted()}

    - ); + return

    {setupToolText.collectionCreationStarted()}

    ; }, default(notification) { console.error('Unknown notification type', { notification }); diff --git a/specifyweb/frontend/js_src/lib/components/PickLists/__tests__/fetch.test.ts b/specifyweb/frontend/js_src/lib/components/PickLists/__tests__/fetch.test.ts index 0fc5433771f..659ac3d50ba 100644 --- a/specifyweb/frontend/js_src/lib/components/PickLists/__tests__/fetch.test.ts +++ b/specifyweb/frontend/js_src/lib/components/PickLists/__tests__/fetch.test.ts @@ -162,9 +162,8 @@ describe('fetchPickListItems', () => { }); test('Picklistitems unscoped for sp7_scope_table_picklists', async () => { - const { collectionPreferences } = await import( - '../../Preferences/collectionPreferences' - ); + const { collectionPreferences } = + await import('../../Preferences/collectionPreferences'); const originalRaw = collectionPreferences.getRaw(); diff --git a/specifyweb/frontend/js_src/lib/components/WbPlanView/navigator.ts b/specifyweb/frontend/js_src/lib/components/WbPlanView/navigator.ts index fca97e9c6be..fbc359e53b4 100644 --- a/specifyweb/frontend/js_src/lib/components/WbPlanView/navigator.ts +++ b/specifyweb/frontend/js_src/lib/components/WbPlanView/navigator.ts @@ -713,4 +713,4 @@ export function getMappingLineData({ : filtered.filter( ({ customSelectSubtype }) => customSelectSubtype !== 'tree' ); -} \ No newline at end of file +} diff --git a/specifyweb/frontend/js_src/lib/localization/README.md b/specifyweb/frontend/js_src/lib/localization/README.md index 064780d7ec8..2941dd0bdec 100644 --- a/specifyweb/frontend/js_src/lib/localization/README.md +++ b/specifyweb/frontend/js_src/lib/localization/README.md @@ -42,7 +42,6 @@ 11. Weblate should do automatic translation for the language using Google Translate. If this did not happen automatically, you can trigger it manually: - 1. In [the list of language for the Specify 7 project](https://hosted.weblate.org/projects/specify-7/#languages), find the new language (it should be automatically added to the list once @@ -155,7 +154,6 @@ reasons: migration was made. Type safety provides awesome side effects: - - Developers get autocomplete in the IDE - Developers can go to definition of the string with just one click - Developers get inline errors if they forget to pass parameter or use diff --git a/specifyweb/frontend/js_src/lib/localization/common.ts b/specifyweb/frontend/js_src/lib/localization/common.ts index 6ad133cdc01..d75f8bb7f83 100644 --- a/specifyweb/frontend/js_src/lib/localization/common.ts +++ b/specifyweb/frontend/js_src/lib/localization/common.ts @@ -104,13 +104,16 @@ export const commonText = createDictionary({ 'hr-hr': 'Savjeti za pretraživanje', }, expressSearchInstructions: { - 'en-us': 'Separate multiple search terms with spaces, use % anywhere, * at the beginning or end, and wrap terms in quotes for exact multi-word matches.', + 'en-us': + 'Separate multiple search terms with spaces, use % anywhere, * at the beginning or end, and wrap terms in quotes for exact multi-word matches.', }, expressSearchDateFormats: { - 'en-us': 'Dates can be searched using either the YYYY-MM-DD or MM/DD/YYYY format.', + 'en-us': + 'Dates can be searched using either the YYYY-MM-DD or MM/DD/YYYY format.', }, expressSearchPhraseExample: { - 'en-us': 'To search a term with spaces, wrap the phrase in quotes, for example "Clinton Lake".', + 'en-us': + 'To search a term with spaces, wrap the phrase in quotes, for example "Clinton Lake".', }, apply: { 'en-us': 'Apply', diff --git a/specifyweb/frontend/js_src/lib/localization/utils/config.ts b/specifyweb/frontend/js_src/lib/localization/utils/config.ts index e358f61952f..b70b574e01a 100644 --- a/specifyweb/frontend/js_src/lib/localization/utils/config.ts +++ b/specifyweb/frontend/js_src/lib/localization/utils/config.ts @@ -24,7 +24,7 @@ export const languageCodeMapper = { 'de-ch': 'de_CH', 'pt-br': 'pt_BR', 'hr-hr': 'hr', - 'nb': 'nb_NO' + nb: 'nb_NO', } as const; export const languages = Object.keys(languageCodeMapper); diff --git a/specifyweb/frontend/js_src/lib/utils/schemaVisibility.ts b/specifyweb/frontend/js_src/lib/utils/schemaVisibility.ts index fe41c0b752e..9c483b4168b 100644 --- a/specifyweb/frontend/js_src/lib/utils/schemaVisibility.ts +++ b/specifyweb/frontend/js_src/lib/utils/schemaVisibility.ts @@ -5,4 +5,4 @@ export function isSchemaFieldVisible( defaultFieldName?: string ): boolean { return showHiddenFields || !isHidden || fieldName === defaultFieldName; -} \ No newline at end of file +}