Turn on strict mode in tsconfig.json, some helpful lints, and required cleanup where strictness necessitates it (#5195)

* Turn on strict mode in tsconfig.json

- Add route, clusterRoute, and payloadValidatedClusterRoute helper
  functions to improve types with backend routes

- Turn on the following new lints:
  - react/jsx-first-prop-new-line
  - react/jsx-wrap-multilines
  - react/jsx-one-expression-per-line
  - react/jsx-max-props-per-line
  - react/jsx-indent
  - react/jsx-indent-props

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix build

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Replace KubeObject scope strings with enum

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Revert package.json version changes

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* revert move hostedCluster(Id)

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* change some type param names to be not single letters

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove copy-extension-themes

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* add new make clean action

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix build to not use webpack for generating types

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix kube-object-menu.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix select.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix catalog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* revert move fileNameMigration to index

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix ref logic error

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix log-resource-selector.test.tsx tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix dock-store.test.ts test by overriding createStorage to not touch file system

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix cluster.test.ts tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix kube=api.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fixed hotbar-store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix kubeconfig-manager.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix cluster-role-bindings/__tests__/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix role-bindings/__tests__/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix pods.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix delete-cluster-dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix daemonset.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix replicaset.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix statefulsets/dialog/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix replicasets/scale-dialog/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix deployments.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix deployments/scale/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix cronjob.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix stateful-set.api.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix deployment.api.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix api-manager.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix statefulset.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix job.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix pods.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix scroll-spy.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix hotbar-remove-command.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix catalog-entity-registry.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix welcome.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix verify-that-all-routes-have-route-component.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix pod-tolerations.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* better fix for previous 3 fixes, plus also select.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix kube-object-menu.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix app-paths.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix dock-tabs.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix isReactNode typing

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix sub-title.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix drawer.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix list-layout.tsx and header.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix error-boundary.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix upgrade-chart/store.ts and dock-tab.store.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix install-chart/store.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix edit-resource/store.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix create-resource/store.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix namespace-select.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix namespace-select-filter.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix crd-list.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix wrong types for extensions

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix circular dependency

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix circular dependency on catalogCategoryRegistry

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix api-kube

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix type errors, most <Select /> errors

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fixing more type errors

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* some more fixing type errors

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* convert all KubeApis to injectable with legacy global backups

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* factor out into a common file all the exports

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* convert all KubeObjectStores to injectable with legacy global backups

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix lint

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove unused legacy KubeApi globals

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix bad previous commit

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* more crash fixing

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* try and fix behavioural tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix sidebar-and-tab-navigation-for-core.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix sidebar-and-tab-navigation-for-extensions.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-using-application-menu.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix catalog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Make ThemeStore non-singleton and fix navigation-to-terminal-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* extensions.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix catalog-entity-registry.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-using-application-menu.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix log-resource-selector.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix dock-tabs.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix delete-cluster-dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-kubernetes-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-editor-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-proxy-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-using-application-menu.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-application-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix dock-store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix select.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix role-bindings/__tests__/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix hotbar-remove-command.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix cluster-role-bindings/__tests__/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-extension-specific-preferences.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-telemetry-preferences.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix closing-preferences.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-editor-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-proxy-preferences.test.ts

- Fix other type errors too

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* final tweaks

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add more tsconfig files, fix bug in <Catalog>

- Make all of history, navigation injectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix type errors

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Convert all of kube-details-params/ and navigate/ to injectable

- This fixes a runtime error that was encountered during testing

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix runtime errors on renderer

- remove all static uses of `createPageParam` (and then removed the
  legacy global)
- Made LensRendererExtension and LensMainExtension just used
  dependencies and not the getLegacyDi
- Fixed circular dep in extension-loader

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Move registerStore calls to after injectMany

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* replace all the rest of the legacy uses of apiManager

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix stack overflow and cycles in DI

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix NamespaceSelectFilter not opening

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix WizardStep and AddNamespaceDialog

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix KubeApi's not being registered

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* cleanup WindowManager

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Proper fix for Wizard, fix NamespaceStore.subscribe

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Rewrite withTooltip to be more type correct

- Fixes mobx related "too many recursive actions" error

- Change all the uses of withTooltips to be functional components

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add e2e test to cover kube api registration

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* cleanup internal-commands

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove cast in <Animate>

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix command-palette e2e test

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix type error after rebase

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix test name

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix lint

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix code to help CodeQL scanner

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* update intree extension lock files

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix build-extensions picking wrong @types/react

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix tests from rebase

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix type error

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Make KubeconfigSyncManager more injectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix crash in test mode for Dialog

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* make Select snapshots deterministic

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix new type error

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix kube-object.store.test.ts typing

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix merge build issues

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix snapshots after merge

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix lint after merge

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* reexport BaseKubeJsonApiObjectMetadata

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix typo in terminalSpawningPool

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove duplicate license header

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix typo to waitUntilDefined

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove iter use from getLegacyGlobalDiForExtensionApi

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove complex createStorage override

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* override logger with mocks only when needed for tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove specialized overrideStore flags for getDiForUnitTesting

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove unnecessary | undefined types from the exactOptionalFieldTypes experiment

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* use more descriptive name for local test mocks

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove unnecessary addition to 'make clean' target

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove oddity of KubeObjectStore.getById(undefined) being allowed

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* rename KubeObject.getDescriptor in favour of name without fundemental JS meaning

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Simplify legacyRegisterApi when working in behaviour unit tests

- Don't emit within main environment as there should be no auto
  registering there

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* change confusing variable name in ReactiveDuration

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* make visitor pattern more explicit for Entity contextMenuOpen

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* toggleDetails -> toggleKubeDetailsPane is more specific

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove outdated comment

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix bug where LensExtension dependencies are not set

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix tests from the revert of react 18

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix more tests from merge

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix typings with new is-compatible-extension tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* more type fixing

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Revert in-tree extension versions

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Improve name of guarding injectable for stores and apis

- New name better implies that it is just a guard state and does not do
  anything

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add helper for <Select>.isMulti for storing in a Set<Value>

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix is-compatible-extension.test.ts types

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton authored and GitHub committed 2022-05-16 07:17:57 -04:00
1 parent 381d77c633
commit dfcb7c3330
1062 files changed
+26512 -28689

No files matched your search

@@ -11,8 +11,8 @@ import { KubernetesCluster } from "../../../../common/catalog-entities";
import { getDiForUnitTesting } from "../../../getDiForUnitTesting";
import type { DiRender } from "../../test-utils/renderFor";
import { renderFor } from "../../test-utils/renderFor";
import hotbarStoreInjectable from "../../../../common/hotbar-store.injectable";
import type { HotbarStore } from "../../../../common/hotbar-store";
import hotbarStoreInjectable from "../../../../common/hotbars/store.injectable";
import type { HotbarStore } from "../../../../common/hotbars/store";
const clusterEntity = new KubernetesCluster({
metadata: {
@@ -15,7 +15,11 @@ export interface CloseButtonProps extends HTMLAttributes<HTMLDivElement> {
export function CloseButton(props: CloseButtonProps) {
return (
<div {...props}>
<div className={styles.closeButton} role="button" aria-label="Close">
<div
className={styles.closeButton}
role="button"
aria-label="Close"
>
<Icon material="close" className={styles.icon}/>
</div>
<div className={styles.esc} aria-hidden="true">
@@ -2,9 +2,7 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { DiContainer } from "@ogre-tools/injectable";
import { getInjectable } from "@ogre-tools/injectable";
import type { LensRendererExtension } from "../../../extensions/lens-renderer-extension";
import React from "react";
import { extensionRegistratorInjectionToken } from "../../../extensions/extension-loader/extension-registrator-injection-token";
import type { SidebarItemRegistration } from "./sidebar-items.injectable";
@@ -13,71 +11,70 @@ import { computed } from "mobx";
import routesInjectable from "../../routes/routes.injectable";
import { matches, noop } from "lodash/fp";
import routeIsActiveInjectable from "../../routes/route-is-active.injectable";
import { getExtensionRoutePath } from "../../routes/get-extension-route-path";
import { navigateToRouteInjectionToken } from "../../../common/front-end-routing/navigate-to-route-injection-token";
import { getExtensionRoutePath } from "../../routes/for-extension";
import type { LensRendererExtension } from "../../../extensions/lens-renderer-extension";
const extensionSidebarItemRegistratorInjectable = getInjectable({
id: "extension-sidebar-item-registrator",
instantiate:
(di: DiContainer) =>
(
extension: LensRendererExtension,
extensionInstallationCount: number,
) => {
const sidebarItemsForExtensionInjectable = getInjectable({
id: `sidebar-items-for-extension-${extension.sanitizedExtensionId}-instance-${extensionInstallationCount}`,
injectionToken: sidebarItemsInjectionToken,
instantiate: (di) => (ext, extensionInstallationCount) => {
const extension = ext as LensRendererExtension;
instantiate: (di) => {
const navigateToRoute = di.inject(navigateToRouteInjectionToken);
const routes = di.inject(routesInjectable);
const sidebarItemsForExtensionInjectable = getInjectable({
id: `sidebar-items-for-extension-${extension.sanitizedExtensionId}-instance-${extensionInstallationCount}`,
injectionToken: sidebarItemsInjectionToken,
return computed((): SidebarItemRegistration[] => {
const extensionRoutes = routes.get().filter(matches({ extension }));
instantiate: (di) => {
const navigateToRoute = di.inject(navigateToRouteInjectionToken);
const routes = di.inject(routesInjectable);
return extension.clusterPageMenus.map((registration) => {
const targetRoutePath = getExtensionRoutePath(
extension,
registration.target?.pageId,
);
return computed(() => {
const extensionRoutes = routes.get().filter(matches({ extension }));
const targetRoute = extensionRoutes.find(
matches({ path: targetRoutePath }),
);
return extension.clusterPageMenus.map((registration) => {
const targetRoutePath = getExtensionRoutePath(
extension,
registration.target?.pageId,
);
return {
id: `${extension.sanitizedExtensionId}-${registration.id}`,
extension,
orderNumber: 9999,
const targetRoute = extensionRoutes.find(
matches({ path: targetRoutePath }),
);
parentId: registration.parentId
? `${extension.sanitizedExtensionId}-${registration.parentId}`
: null,
const res: SidebarItemRegistration = {
id: `${extension.sanitizedExtensionId}-${registration.id}`,
extension,
orderNumber: 9999,
title: registration.title,
getIcon: registration.components.Icon
? () => <registration.components.Icon />
: null,
parentId: registration.parentId
? `${extension.sanitizedExtensionId}-${registration.parentId}`
: null,
...(targetRoute
? {
onClick: () => navigateToRoute(targetRoute),
title: registration.title,
getIcon: registration.components.Icon
? () => <registration.components.Icon />
: undefined,
...(targetRoute
? {
onClick: () => navigateToRoute(targetRoute),
isActive: di.inject(
routeIsActiveInjectable,
targetRoute,
),
}
: { onClick: noop }),
};
});
});
},
isActive: di.inject(
routeIsActiveInjectable,
targetRoute,
),
}
: { onClick: noop }),
};
return res;
});
});
di.register(sidebarItemsForExtensionInjectable);
},
});
di.register(sidebarItemsForExtensionInjectable);
},
injectionToken: extensionRegistratorInjectionToken,
});
+11 -18
View File
@@ -7,21 +7,19 @@ import styles from "./main-layout.module.scss";
import React from "react";
import { observer } from "mobx-react";
import type { StorageHelper } from "../../utils";
import type { StorageLayer } from "../../utils";
import { cssNames } from "../../utils";
import { ErrorBoundary } from "../error-boundary";
import { ResizeDirection, ResizeGrowthDirection, ResizeSide, ResizingAnchor } from "../resizing-anchor";
import { withInjectables } from "@ogre-tools/injectable-react";
import type {
SidebarStorageState } from "./sidebar-storage/sidebar-storage.injectable";
import sidebarStorageInjectable, {
defaultSidebarWidth,
} from "./sidebar-storage/sidebar-storage.injectable";
import type { SidebarStorageState } from "./sidebar-storage/sidebar-storage.injectable";
import sidebarStorageInjectable, { defaultSidebarWidth } from "./sidebar-storage/sidebar-storage.injectable";
export interface MainLayoutProps {
sidebar: React.ReactNode;
className?: string;
footer?: React.ReactNode;
children?: React.ReactNode | React.ReactNode[];
}
/**
@@ -31,7 +29,7 @@ export interface MainLayoutProps {
*/
interface Dependencies {
sidebarStorage: StorageHelper<SidebarStorageState>;
sidebarStorage: StorageLayer<SidebarStorageState>;
}
@observer
@@ -71,15 +69,10 @@ class NonInjectedMainLayout extends React.Component<MainLayoutProps & Dependenci
}
}
export const MainLayout = withInjectables<Dependencies, MainLayoutProps>(
NonInjectedMainLayout,
{
getProps: (di, props) => ({
sidebarStorage: di.inject(sidebarStorageInjectable),
...props,
}),
},
);
export const MainLayout = withInjectables<Dependencies, MainLayoutProps>(NonInjectedMainLayout, {
getProps: (di, props) => ({
...props,
sidebarStorage: di.inject(sidebarStorageInjectable),
}),
});
@@ -69,7 +69,7 @@ export class SettingLayout extends React.Component<SettingLayoutProps> {
if (evt.code === "Escape") {
evt.stopPropagation();
this.props.back(evt);
this.props.back?.(evt);
}
};
@@ -24,7 +24,8 @@ const NonInjectedSiblingsInTabLayout = observer(
if (dereferencedTabs.length) {
return (
<TabLayout tabs={dereferencedTabs}
<TabLayout
tabs={dereferencedTabs}
>
{children}
</TabLayout>
@@ -14,31 +14,36 @@ import { Icon } from "../icon";
import { Menu, MenuItem } from "../menu";
import { Tooltip } from "../tooltip";
import { withInjectables } from "@ogre-tools/injectable-react";
import hotbarStoreInjectable from "../../../common/hotbar-store.injectable";
import type { HotbarStore } from "../../../common/hotbar-store";
import hotbarStoreInjectable from "../../../common/hotbars/store.injectable";
import type { HotbarStore } from "../../../common/hotbars/store";
import { observer } from "mobx-react";
import type { VisitEntityContextMenu } from "../../../common/catalog/visit-entity-context-menu.injectable";
import visitEntityContextMenuInjectable from "../../../common/catalog/visit-entity-context-menu.injectable";
import type { Navigate } from "../../navigation/navigate.injectable";
import type { NormalizeCatalogEntityContextMenu } from "../../catalog/normalize-menu-item.injectable";
import navigateInjectable from "../../navigation/navigate.injectable";
import normalizeCatalogEntityContextMenuInjectable from "../../catalog/normalize-menu-item.injectable";
export interface SidebarClusterProps {
clusterEntity: CatalogEntity;
clusterEntity: CatalogEntity | null | undefined;
}
interface Dependencies {
navigate: Navigate;
normalizeMenuItem: NormalizeCatalogEntityContextMenu;
hotbarStore: HotbarStore;
visitEntityContextMenu: VisitEntityContextMenu;
}
function NonInjectedSidebarCluster({
const NonInjectedSidebarCluster = observer(({
clusterEntity,
hotbarStore,
visitEntityContextMenu: onContextMenuOpen,
navigate,
normalizeMenuItem,
}: SidebarClusterProps & Dependencies) {
const [opened, setOpened] = useState(false);
}: Dependencies & SidebarClusterProps) => {
const [menuItems] = useState(observable.array<CatalogEntityContextMenu>());
const [opened, setOpened] = useState(false );
if (!clusterEntity) {
// render a Loading version of the SidebarCluster
@@ -65,7 +70,7 @@ function NonInjectedSidebarCluster({
: () => hotbarStore.addToHotbar(clusterEntity);
menuItems.replace([{ title, onClick }]);
clusterEntity.onContextMenuOpen({
onContextMenuOpen(clusterEntity, {
menuItems,
navigate: (url, forceMainFrame = true) => {
if (forceMainFrame) {
@@ -114,7 +119,7 @@ function NonInjectedSidebarCluster({
<Tooltip targetId={tooltipId}>
{clusterEntity.getName()}
</Tooltip>
<Icon material="arrow_drop_down" className={styles.dropdown}/>
<Icon material="arrow_drop_down" className={styles.dropdown} />
<Menu
usePortal
htmlFor={id}
@@ -137,12 +142,13 @@ function NonInjectedSidebarCluster({
</Menu>
</div>
);
}
});
export const SidebarCluster = withInjectables<Dependencies, SidebarClusterProps>(NonInjectedSidebarCluster, {
getProps: (di, props) => ({
...props,
hotbarStore: di.inject(hotbarStoreInjectable),
visitEntityContextMenu: di.inject(visitEntityContextMenuInjectable),
navigate: di.inject(navigateInjectable),
normalizeMenuItem: di.inject(normalizeCatalogEntityContextMenuInjectable),
}),
@@ -7,20 +7,18 @@ import "./sidebar-item.scss";
import React from "react";
import { computed, makeObservable } from "mobx";
import type { StorageHelper } from "../../utils";
import type { StorageLayer } from "../../utils";
import { cssNames } from "../../utils";
import { observer } from "mobx-react";
import { NavLink } from "react-router-dom";
import { Icon } from "../icon";
import { withInjectables } from "@ogre-tools/injectable-react";
import type {
SidebarStorageState,
} from "./sidebar-storage/sidebar-storage.injectable";
import type { SidebarStorageState } from "./sidebar-storage/sidebar-storage.injectable";
import sidebarStorageInjectable from "./sidebar-storage/sidebar-storage.injectable";
import type { HierarchicalSidebarItem } from "./sidebar-items.injectable";
interface Dependencies {
sidebarStorage: StorageHelper<SidebarStorageState>;
sidebarStorage: StorageLayer<SidebarStorageState>;
}
export interface SidebarItemProps {
@@ -125,13 +123,9 @@ class NonInjectedSidebarItem extends React.Component<
}
}
export const SidebarItem = withInjectables<Dependencies, SidebarItemProps>(
NonInjectedSidebarItem,
{
getProps: (di, props) => ({
sidebarStorage: di.inject(sidebarStorageInjectable),
...props,
}),
},
);
export const SidebarItem = withInjectables<Dependencies, SidebarItemProps>(NonInjectedSidebarItem, {
getProps: (di, props) => ({
...props,
sidebarStorage: di.inject(sidebarStorageInjectable),
}),
});
@@ -68,12 +68,8 @@ const sidebarItemsInjectable = getInjectable({
),
);
const getSidebarItemsHierarchy = (
registrations: SidebarItemRegistration[],
) => {
const _getSidebarItemsHierarchy = (
parentId: string,
): HierarchicalSidebarItem[] =>
const getSidebarItemsHierarchy = (registrations: SidebarItemRegistration[]) => {
const _getSidebarItemsHierarchy = (parentId: string | null): HierarchicalSidebarItem[] =>
pipeline(
registrations,
+27 -38
View File
@@ -9,57 +9,46 @@ import React from "react";
import { observer } from "mobx-react";
import { cssNames } from "../../utils";
import { SidebarItem } from "./sidebar-item";
import { catalogEntityRegistry } from "../../api/catalog-entity-registry";
import type { CatalogEntityRegistry } from "../../api/catalog/entity/registry";
import { SidebarCluster } from "./sidebar-cluster";
import { withInjectables } from "@ogre-tools/injectable-react";
import type {
HierarchicalSidebarItem,
} from "./sidebar-items.injectable";
import type { HierarchicalSidebarItem } from "./sidebar-items.injectable";
import sidebarItemsInjectable from "./sidebar-items.injectable";
import type { IComputedValue } from "mobx";
import catalogEntityRegistryInjectable from "../../api/catalog/entity/registry.injectable";
interface Dependencies {
sidebarItems: IComputedValue<HierarchicalSidebarItem[]>;
entityRegistry: CatalogEntityRegistry;
}
@observer
class NonInjectedSidebar extends React.Component<Dependencies> {
static displayName = "Sidebar";
export const NonInjectedSidebar = observer(({
sidebarItems,
entityRegistry,
}: Dependencies) => (
<div className={cssNames("flex flex-col")} data-testid="cluster-sidebar">
<SidebarCluster clusterEntity={entityRegistry.activeEntity} />
get clusterEntity() {
return catalogEntityRegistry.activeEntity;
}
render() {
return (
<div className={cssNames("flex flex-col")} data-testid="cluster-sidebar">
<SidebarCluster clusterEntity={this.clusterEntity} />
<div className={`${styles.sidebarNav} sidebar-active-status`}>
{this.props.sidebarItems.get().map((
hierarchicalSidebarItem: HierarchicalSidebarItem,
) => (
<div className={`${styles.sidebarNav} sidebar-active-status`}>
{
sidebarItems.get()
.map(hierarchicalSidebarItem => (
<SidebarItem
item={hierarchicalSidebarItem}
key={hierarchicalSidebarItem.registration.id}
/>
))}
</div>
</div>
);
}
}
export const Sidebar = withInjectables<Dependencies>(
NonInjectedSidebar,
{
getProps: (di, props) => ({
sidebarItems: di.inject(sidebarItemsInjectable),
...props,
}),
},
);
))
}
</div>
</div>
));
export const Sidebar = withInjectables<Dependencies>(NonInjectedSidebar, {
getProps: (di, props) => ({
...props,
sidebarItems: di.inject(sidebarItemsInjectable),
entityRegistry: di.inject(catalogEntityRegistryInjectable),
}),
});
Sidebar.displayName = "Sidebar";
@@ -5,12 +5,14 @@
import "./sub-header.scss";
import React from "react";
import type { SingleOrMany } from "../../utils";
import { cssNames } from "../../utils";
export interface SubHeaderProps {
className?: string;
withLine?: boolean; // add bottom line
compact?: boolean; // no extra padding around content
children: SingleOrMany<React.ReactNode>;
}
export class SubHeader extends React.Component<SubHeaderProps> {
+5 -1
View File
@@ -5,6 +5,7 @@
import "./sub-title.scss";
import React from "react";
import type { SingleOrMany } from "../../utils";
import { cssNames } from "../../utils";
export interface SubTitleProps {
@@ -12,6 +13,7 @@ export interface SubTitleProps {
title: React.ReactNode;
compact?: boolean; // no bottom padding
id?: string;
children?: SingleOrMany<React.ReactNode>;
}
export class SubTitle extends React.Component<SubTitleProps> {
@@ -23,7 +25,9 @@ export class SubTitle extends React.Component<SubTitleProps> {
return (
<div className={classNames} id={id}>
{title} {children}
{title}
{" "}
{children}
</div>
);
}
+17 -9
View File
@@ -40,21 +40,29 @@ export const TabLayout = observer(({ className, contentClass, tabs = [], childre
<div className={cssNames("TabLayout", className)}>
{hasTabs && (
<Tabs center onChange={(url) => navigate(url)}>
{tabs.map(({ title, routePath, url = routePath, exact }) => {
const isActive = !!matchPath(currentLocation, { path: routePath, exact });
return <Tab key={url} label={title} value={url} active={isActive}/>;
})}
{tabs.map(({ title, routePath, url = routePath, exact }) => (
<Tab
key={url}
label={title}
value={url}
active={!!matchPath(currentLocation, { path: routePath, exact })}
/>
))}
</Tabs>
)}
<main className={cssNames(contentClass)}>
<ErrorBoundary>
{hasTabs && (
<Switch>
{tabs.map(({ routePath, exact, component }) => {
return <Route key={routePath} exact={exact} path={routePath} component={component}/>;
})}
<Redirect to={startTabUrl}/>
{tabs.map(({ routePath, exact, component }) => (
<Route
key={routePath}
exact={exact}
path={routePath}
component={component}
/>
))}
{startTabUrl && <Redirect to={startTabUrl}/>}
</Switch>
)}
{children}
@@ -43,8 +43,14 @@ ipcRendererOn("history:can-go-forward", (event, state: boolean) => {
nextEnabled.set(state);
});
const NonInjectedTopBar = observer(({ items, navigateToCatalog, catalogRouteIsActive, isWindows, isLinux }: Dependencies) => {
const elem = useRef<HTMLDivElement>();
const NonInjectedTopBar = observer(({
items,
navigateToCatalog,
catalogRouteIsActive,
isWindows,
isLinux,
}: Dependencies) => {
const elem = useRef<HTMLDivElement | null>(null);
const openAppContextMenu = () => {
emitOpenAppMenuAsContextMenu();
@@ -83,15 +89,24 @@ const NonInjectedTopBar = observer(({ items, navigateToCatalog, catalogRouteIsAc
useEffect(() => watchHistoryState(), []);
return (
<div className={styles.topBar} onDoubleClick={windowSizeToggle} ref={elem}>
<div
className={styles.topBar}
onDoubleClick={windowSizeToggle}
ref={elem}
>
<div className={styles.items}>
{(isWindows || isLinux) && (
<div className={styles.winMenu}>
<div onClick={openAppContextMenu} data-testid="window-menu">
<svg width="12" height="12" viewBox="0 0 12 12" shapeRendering="crispEdges">
<path fill="currentColor" d="M0,8.5h12v1H0V8.5z"/>
<path fill="currentColor" d="M0,5.5h12v1H0V5.5z"/>
<path fill="currentColor" d="M0,2.5h12v1H0V2.5z"/>
<svg
width="12"
height="12"
viewBox="0 0 12 12"
shapeRendering="crispEdges"
>
<path fill="currentColor" d="M0,8.5h12v1H0V8.5z" />
<path fill="currentColor" d="M0,5.5h12v1H0V5.5z" />
<path fill="currentColor" d="M0,2.5h12v1H0V2.5z" />
</svg>
</div>
</div>
@@ -119,17 +134,42 @@ const NonInjectedTopBar = observer(({ items, navigateToCatalog, catalogRouteIsAc
{renderRegisteredItems(items.get())}
{(isWindows || isLinux) && (
<div className={cssNames(styles.windowButtons, { [styles.linuxButtons]: isLinux })}>
<div className={styles.minimize} data-testid="window-minimize" onClick={minimizeWindow}>
<div
className={styles.minimize}
data-testid="window-minimize"
onClick={minimizeWindow}
>
<svg shapeRendering="crispEdges" viewBox="0 0 12 12">
<rect fill="currentColor" width="10" height="1" x="1" y="9" />
<rect
fill="currentColor"
width="10"
height="1"
x="1"
y="9"
/>
</svg>
</div>
<div className={styles.maximize} data-testid="window-maximize" onClick={toggleMaximize}>
<div
className={styles.maximize}
data-testid="window-maximize"
onClick={toggleMaximize}
>
<svg shapeRendering="crispEdges" viewBox="0 0 12 12">
<rect width="9" height="9" x="1.5" y="1.5" fill="none" stroke="currentColor" />
<rect
width="9"
height="9"
x="1.5"
y="1.5"
fill="none"
stroke="currentColor"
/>
</svg>
</div>
<div className={styles.close} data-testid="window-close" onClick={closeWindow}>
<div
className={styles.close}
data-testid="window-close"
onClick={closeWindow}
>
<svg shapeRendering="crispEdges" viewBox="0 0 12 12">
<polygon fill="currentColor" points="11 1.576 6.583 6 11 10.424 10.424 11 6 6.583 1.576 11 1 10.424 5.417 6 1 1.576 1.576 1 6 5.417 10.424 1" />
</svg>