From 7c6da77a27e07a49d0a18419a152bf243da3ef8f Mon Sep 17 00:00:00 2001 From: Tan Nhu Date: Thu, 18 Aug 2022 11:44:33 -0700 Subject: [PATCH] Sync UI template with latest updates --- web/.eslintrc.yml | 6 + web/config/moduleFederation.config.js | 74 ++++---- web/cypress/integration/dashboard.spec.js | 12 +- web/cypress/integration/evaluations.spec.js | 9 - web/cypress/integration/policy.spec.js | 7 - web/cypress/integration/policyset.spec.js | 7 - web/package.json | 6 +- web/src/AppContext.tsx | 5 +- web/src/AppProps.ts | 2 - web/src/RouteDefinitions.ts | 8 +- web/src/RouteDestinations.tsx | 141 ++++++--------- web/src/bootstrap.tsx | 2 +- .../OptionsMenuButton/OptionsMenuButton.tsx | 4 +- web/src/framework/strings/String.tsx | 5 +- web/src/framework/strings/stringTypes.ts | 7 + web/src/global.d.ts | 2 +- web/src/i18n/strings.en.yaml | 7 + .../pages/Account/Account.module.scss.d.ts | 15 -- web/src/pages/Account/Account.tsx | 153 ---------------- web/src/pages/Account/account.module.scss | 17 -- web/src/pages/Execution/Settings.tsx | 100 ----------- .../pages/Executions/Executions.module.scss | 30 ---- .../Executions/Executions.module.scss.d.ts | 16 -- web/src/pages/Executions/Executions.tsx | 118 ------------- web/src/pages/Login/Login.tsx | 26 ++- web/src/pages/Pipeline/Settings.tsx | 99 ----------- .../Pipelines/Pipelines.module.scss.d.ts | 16 -- web/src/pages/Pipelines/Pipelines.tsx | 112 ------------ web/src/pages/Pipelines/pipelines.module.scss | 30 ---- web/src/pages/Register/register.js | 165 +++++++++--------- web/src/pages/SignIn/SignIn.tsx | 4 +- web/src/services/config.ts | 2 +- web/src/utils/test/testUtils.tsx | 2 +- web/yarn.lock | 109 +++++++++--- 34 files changed, 318 insertions(+), 1000 deletions(-) delete mode 100644 web/cypress/integration/evaluations.spec.js delete mode 100644 web/cypress/integration/policy.spec.js delete mode 100644 web/cypress/integration/policyset.spec.js delete mode 100644 web/src/pages/Account/Account.module.scss.d.ts delete mode 100644 web/src/pages/Account/Account.tsx delete mode 100644 web/src/pages/Account/account.module.scss delete mode 100644 web/src/pages/Execution/Settings.tsx delete mode 100644 web/src/pages/Executions/Executions.module.scss delete mode 100644 web/src/pages/Executions/Executions.module.scss.d.ts delete mode 100644 web/src/pages/Executions/Executions.tsx delete mode 100644 web/src/pages/Pipeline/Settings.tsx delete mode 100644 web/src/pages/Pipelines/Pipelines.module.scss.d.ts delete mode 100644 web/src/pages/Pipelines/Pipelines.tsx delete mode 100644 web/src/pages/Pipelines/pipelines.module.scss diff --git a/web/.eslintrc.yml b/web/.eslintrc.yml index c36b3101d..f6973ae81 100644 --- a/web/.eslintrc.yml +++ b/web/.eslintrc.yml @@ -35,6 +35,12 @@ settings: typescript: alwaysTryTypes: true rules: + '@typescript-eslint/ban-types': + - error + - extendDefaults: true + types: + '{}': false + # custom rules no-document-body-snapshot: 2 duplicate-data-tooltip-id: 'warn' diff --git a/web/config/moduleFederation.config.js b/web/config/moduleFederation.config.js index 63a537ef9..3c1c0fab0 100644 --- a/web/config/moduleFederation.config.js +++ b/web/config/moduleFederation.config.js @@ -1,48 +1,44 @@ -const packageJSON = require('../package.json'); -const { pick, omit, mapValues } = require('lodash'); +const packageJSON = require('../package.json') +const { pick, omit, mapValues } = require('lodash') /** * These packages must be stricly shared with exact versions */ - const ExactSharedPackages = [ - 'react', - 'react-dom', - 'react-router-dom', - '@harness/use-modal', - '@blueprintjs/core', - '@blueprintjs/select', - '@blueprintjs/datetime', - 'restful-react', - '@harness/monaco-yaml', - 'monaco-editor', - 'monaco-editor-core', - 'monaco-languages', - 'monaco-plugin-helpers', - 'react-monaco-editor' - ] +const ExactSharedPackages = [ + 'react', + 'react-dom', + 'react-router-dom', + '@harness/use-modal', + '@blueprintjs/core', + '@blueprintjs/select', + '@blueprintjs/datetime', + 'restful-react', + '@harness/monaco-yaml', + 'monaco-editor', + 'monaco-editor-core', + 'monaco-languages', + 'monaco-plugin-helpers', + 'react-monaco-editor' +] /** * @type {import('webpack').ModuleFederationPluginOptions} */ module.exports = { - name: 'governance', - filename: 'remoteEntry.js', - library: { - type: 'var', - name: 'governance' - }, - exposes: { - './App': './src/App.tsx', - './EvaluationModal': './src/modals/EvaluationModal/EvaluationModal.tsx', - './PipelineGovernanceView': './src/views/PipelineGovernanceView/PipelineGovernanceView.tsx', - './EvaluationView': './src/views/EvaluationView/EvaluationView.tsx', - './PolicySetWizard': './src/pages/PolicySets/components/PolicySetWizard.tsx' - }, - shared: { - formik: packageJSON.dependencies['formik'], - ...mapValues(pick(packageJSON.dependencies, ExactSharedPackages), version => ({ - singleton: true, - requiredVersion: version - })) - } -}; \ No newline at end of file + name: 'governance', + filename: 'remoteEntry.js', + library: { + type: 'var', + name: 'governance' + }, + exposes: { + './App': './src/App.tsx' + }, + shared: { + formik: packageJSON.dependencies['formik'], + ...mapValues(pick(packageJSON.dependencies, ExactSharedPackages), version => ({ + singleton: true, + requiredVersion: version + })) + } +} diff --git a/web/cypress/integration/dashboard.spec.js b/web/cypress/integration/dashboard.spec.js index d3f3e8424..5612f733b 100644 --- a/web/cypress/integration/dashboard.spec.js +++ b/web/cypress/integration/dashboard.spec.js @@ -1,8 +1,8 @@ describe('dashboard', () => { - it('load the dashboard', () => { - cy.visit('/') - cy.contains('In Effect') - cy.contains('Policy Evaluations') - cy.contains('Failures Recorded') - }) + it('load the dashboard', () => { + // cy.visit('/') + // cy.contains('In Effect') + // cy.contains('Policy Evaluations') + // cy.contains('Failures Recorded') + }) }) diff --git a/web/cypress/integration/evaluations.spec.js b/web/cypress/integration/evaluations.spec.js deleted file mode 100644 index 3bb8c4981..000000000 --- a/web/cypress/integration/evaluations.spec.js +++ /dev/null @@ -1,9 +0,0 @@ -// disabling at the moment because of logic around Evaluations tab being removed in standalone mode (account in NG equivalent) - -// describe('evaluations', () => { -// it('load the table', () => { -// cy.visit('/') -// cy.contains('Evaluations').click() -// cy.contains('Policy evaluations are created when policy sets are enforced on your Harness entities.') -// }) -// }) diff --git a/web/cypress/integration/policy.spec.js b/web/cypress/integration/policy.spec.js deleted file mode 100644 index 3261564e3..000000000 --- a/web/cypress/integration/policy.spec.js +++ /dev/null @@ -1,7 +0,0 @@ -describe('policies', () => { - it('load the table', () => { - cy.visit('/') - cy.contains('Policies').click() - cy.get('[class="TableV2--row TableV2--card TableV2--clickable"]').should('have.length', 12) - }) -}) diff --git a/web/cypress/integration/policyset.spec.js b/web/cypress/integration/policyset.spec.js deleted file mode 100644 index e6291d5f3..000000000 --- a/web/cypress/integration/policyset.spec.js +++ /dev/null @@ -1,7 +0,0 @@ -describe('policy sets', () => { - it('load the table', () => { - cy.visit('/') - cy.contains('Policy Set').click() - cy.contains('A harness policy set allows you to group policies and configure where they will be enforced.') - }) -}) diff --git a/web/package.json b/web/package.json index 50613e2ed..1a8a89798 100644 --- a/web/package.json +++ b/web/package.json @@ -141,8 +141,8 @@ "@types/testing-library__user-event": "^4.1.1", "@types/uuid": "^8.3.0", "@types/yup": "^0.29.0", - "@typescript-eslint/eslint-plugin": "^4.22.0", - "@typescript-eslint/parser": "^4.22.0", + "@typescript-eslint/eslint-plugin": "^5.33.1", + "@typescript-eslint/parser": "^5.33.1", "@urql/devtools": "^2.0.3", "@zerollup/ts-transform-paths": "^1.7.18", "assert": "^2.0.0", @@ -199,7 +199,7 @@ "ts-loader": "^9.2.6", "ts-node": "^10.2.1", "tsconfig-paths-webpack-plugin": "^3.5.1", - "typescript": "^4.2.4", + "typescript": "^4.7.4", "url-loader": "^4.1.1", "webpack": "^5.58.0", "webpack-bugsnag-plugins": "^1.8.0", diff --git a/web/src/AppContext.tsx b/web/src/AppContext.tsx index 9f2b27f05..8a94233bd 100644 --- a/web/src/AppContext.tsx +++ b/web/src/AppContext.tsx @@ -13,7 +13,10 @@ const AppContext = React.createContext({ components: {} }) -export const AppContextProvider: React.FC<{ value: AppProps }> = React.memo(({ value: initialValue, children }) => { +export const AppContextProvider: React.FC<{ value: AppProps }> = React.memo(function AppContextProvider({ + value: initialValue, + children +}) { const [appStates, setAppStates] = useState(initialValue) return ( diff --git a/web/src/AppProps.ts b/web/src/AppProps.ts index 6c8ee73b3..60dd1cf0b 100644 --- a/web/src/AppProps.ts +++ b/web/src/AppProps.ts @@ -1,7 +1,6 @@ import type React from 'react' import type * as History from 'history' import type { PermissionOptionsMenuButtonProps } from 'components/Permissions/PermissionsOptionsMenuButton' -import type { OverviewChartsWithToggleProps } from 'components/OverviewChartsWithToggle/OverviewChartsWithToggle' import type { LangLocale } from './framework/strings/languageLoader' import type { FeatureFlagMap, GitFiltersProps } from './utils/GovernanceUtils' @@ -106,5 +105,4 @@ export interface AppPropsComponent { navigate: (path: string) => void shouldBlockNavigation?: (location: History.Location) => boolean }> - OverviewChartsWithToggle: React.FC } diff --git a/web/src/RouteDefinitions.ts b/web/src/RouteDefinitions.ts index a20413b04..91e3914cd 100644 --- a/web/src/RouteDefinitions.ts +++ b/web/src/RouteDefinitions.ts @@ -3,12 +3,14 @@ import type { AppPathProps } from 'AppProps' export enum RoutePath { SIGNIN = '/signin', + SIGNUP = '/signup', + REGISTER = '/register', POLICY_DASHBOARD = '/dashboard', POLICY_LISTING = '/policies', POLICY_NEW = '/policies/new', POLICY_VIEW = '/policies/view/:policyIdentifier', //POLICY_EDIT = '/policies/edit/:policyIdentifier', - POLICY_EDIT= '/policies/edit/:policyIdentifier/:repo?/:branch?', + POLICY_EDIT = '/policies/edit/:policyIdentifier/:repo?/:branch?', POLICY_SETS_LISTING = '/policy-sets', POLICY_SETS_DETAIL = '/policy-sets/:policySetIdentifier', POLICY_EVALUATIONS_LISTING = '/policy-evaluations', @@ -17,10 +19,12 @@ export enum RoutePath { export default { toSignIn: (): string => toRouteURL(RoutePath.SIGNIN), + toSignUp: (): string => toRouteURL(RoutePath.SIGNUP), + toRegister: (): string => toRouteURL(RoutePath.REGISTER), toPolicyDashboard: (): string => toRouteURL(RoutePath.POLICY_DASHBOARD), toPolicyListing: (): string => toRouteURL(RoutePath.POLICY_LISTING), toPolicyNew: (): string => toRouteURL(RoutePath.POLICY_NEW), - toPolicyView: ({ policyIdentifier }: Required>): string => + toPolicyView: ({ policyIdentifier }: Required>): string => toRouteURL(RoutePath.POLICY_VIEW, { policyIdentifier }), toPolicyEdit: ({ policyIdentifier }: Required>): string => toRouteURL(RoutePath.POLICY_EDIT, { policyIdentifier }), diff --git a/web/src/RouteDestinations.tsx b/web/src/RouteDestinations.tsx index 0f5158cfe..e5d748a67 100644 --- a/web/src/RouteDestinations.tsx +++ b/web/src/RouteDestinations.tsx @@ -1,105 +1,76 @@ /* eslint-disable react/display-name */ import React, { useCallback } from 'react' import { HashRouter, Route, Switch, Redirect } from 'react-router-dom' -import { SignInPage } from 'pages/signin/SignInPage' +// import { SignInPage } from 'pages/signin/SignInPage' import { NotFoundPage } from 'pages/404/NotFoundPage' +import { SignIn } from 'pages/SignIn/SignIn' +import { Register } from 'pages/Register/Register' import { routePath, standaloneRoutePath } from './RouteUtils' import { RoutePath } from './RouteDefinitions' -import PolicyControlPage from './pages/PolicyControl/PolicyControlPage' -import Policies from './pages/Policies/Policies' -import PolicyDashboard from './pages/PolicyDashboard/PolicyDashboard' -import PolicySets from './pages/PolicySets/PolicySets' -import PolicyEvaluations from './pages/PolicyEvaluations/PolicyEvaluations' -import { EditPolicy } from './pages/EditPolicy/EditPolicy' -import { ViewPolicy } from './pages/ViewPolicy/ViewPolicy' -import { PolicySetDetail } from './pages/PolicySetDetail/PolicySetDetail' -import { EvaluationDetail } from './pages/EvaluationDetail/EvaluationDetail' -export const RouteDestinations: React.FC<{ standalone: boolean }> = React.memo( - ({ standalone }) => { - // TODO: Add Auth wrapper - - const Destinations: React.FC = useCallback( - () => ( - - {standalone && ( +export const RouteDestinations: React.FC<{ standalone: boolean }> = React.memo(({ standalone }) => { + const Destinations: React.FC = useCallback( + () => ( + + {standalone && ( + <> - + - )} + + + + + + + + )} - - - - - + +

Overview

+
- - - - - + +

New

+
- - - - - + +

View

+
- - - - - + +

Edit

+
- - - - - + +

Listing

+
- - - - - + +

Listing 2

+
- - - - - + +

Detail 1

+
- - - - - + +

Detail 2

+
- - - - - + + {standalone ? : } + +
+ ), + [standalone] + ) - - {standalone ? ( - - ) : ( - - )} - -
- ), - [standalone] - ) - - return standalone ? ( - - - - ) : ( + return standalone ? ( + - ) - } -) + + ) : ( + + ) +}) diff --git a/web/src/bootstrap.tsx b/web/src/bootstrap.tsx index dac29e3ef..73d39fdcb 100644 --- a/web/src/bootstrap.tsx +++ b/web/src/bootstrap.tsx @@ -6,7 +6,7 @@ import './App.scss' // This flag is used in services/config.ts to customize API path when app is run // in multiple modes (standalone vs. embedded). // Also being used in when generating proper URLs inside the app. -window.STRIP_PM_PREFIX = true +window.STRIP_SCM_PREFIX = true ReactDOM.render( )?.text as string} className={Classes.POPOVER_DISMISS} - {...item} + {...(item as IMenuItemProps & React.AnchorHTMLAttributes)} /> ) )} diff --git a/web/src/framework/strings/String.tsx b/web/src/framework/strings/String.tsx index 7a31594e7..93ec5d955 100644 --- a/web/src/framework/strings/String.tsx +++ b/web/src/framework/strings/String.tsx @@ -1,7 +1,6 @@ import React from 'react' import mustache from 'mustache' import { get } from 'lodash-es' - import { useStringsContext, StringKeys } from './StringsContext' export interface UseStringsReturn { @@ -46,9 +45,9 @@ export function String(props: StringProps): React.ReactElement | null { const text = getString(stringID, vars) return useRichText ? ( - + ) : ( - {text} + {text} ) } catch (e) { if (process.env.NODE_ENV !== 'production') { diff --git a/web/src/framework/strings/stringTypes.ts b/web/src/framework/strings/stringTypes.ts index e558d2f2b..a3366fce0 100644 --- a/web/src/framework/strings/stringTypes.ts +++ b/web/src/framework/strings/stringTypes.ts @@ -56,10 +56,12 @@ export interface StringsMap { descriptionPlaceholder: string details: string edit: string + email: string entity: string 'evaluation.evaluatedPoliciesCount': string 'evaluation.onePolicyEvaluated': string executionsText: string + existingAccount: string failed: string fileOverwrite: string finish: string @@ -122,13 +124,18 @@ export interface StringsMap { navigationCheckText: string navigationCheckTitle: string no: string + noAccount: string noSearchResultsFound: string optionalField: string outputLabel: string overview: string + pageNotFound: string + password: string samplePolicies: string saveOverwrite: string search: string + signIn: string + signUp: string source: string status: string success: string diff --git a/web/src/global.d.ts b/web/src/global.d.ts index a31efe33e..1c19ff6ad 100644 --- a/web/src/global.d.ts +++ b/web/src/global.d.ts @@ -45,7 +45,7 @@ declare module '*.gql' { declare interface Window { apiUrl: string bugsnagClient?: any - STRIP_PM_PREFIX?: boolean + STRIP_SCM_PREFIX?: boolean } declare const monaco: any diff --git a/web/src/i18n/strings.en.yaml b/web/src/i18n/strings.en.yaml index b00ad6ed3..12ccb0233 100644 --- a/web/src/i18n/strings.en.yaml +++ b/web/src/i18n/strings.en.yaml @@ -1,3 +1,10 @@ +pageNotFound: Page Not Found +signIn: Sign In +signUp: Sign Up +email: Email +password: Password +noAccount: No Account +existingAccount: Existing Account failed: Failed status: Status success: Success diff --git a/web/src/pages/Account/Account.module.scss.d.ts b/web/src/pages/Account/Account.module.scss.d.ts deleted file mode 100644 index 69ccfe46b..000000000 --- a/web/src/pages/Account/Account.module.scss.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* eslint-disable */ -/** - * Copyright 2021 Harness Inc. All rights reserved. - * Use of this source code is governed by the PolyForm Shield 1.0.0 license - * that can be found in the licenses directory at the root of this repository, also available at - * https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt. - **/ -// this is an auto-generated file, do not update this manually -declare const styles: { - readonly container: string - readonly input: string - readonly minWidth: string - readonly root: string -} -export default styles diff --git a/web/src/pages/Account/Account.tsx b/web/src/pages/Account/Account.tsx deleted file mode 100644 index b9468ffbd..000000000 --- a/web/src/pages/Account/Account.tsx +++ /dev/null @@ -1,153 +0,0 @@ -import React, { useState, useEffect } from 'react' -import { useHistory } from 'react-router-dom' -import { - Container, - Button, - Formik, - FormikForm, - FormInput, - Text, - Color, - Layout, - ButtonVariation, - Page, - useToaster -} from '@harness/uicore' -import { useUpdateUser, useGetUser } from 'services/pm' -import { useStrings } from 'framework/strings' -import routes from 'RouteDefinitions' - -import styles from './Account.module.scss' - -interface UserFormProps { - name: string - email: string - password1: string - password2: string -} - -export const Account = () => { - const history = useHistory() - const { getString } = useStrings() - const { showSuccess, showError } = useToaster() - const { data, loading, error, refetch } = useGetUser({}) - const { mutate } = useUpdateUser({}) - const [editDetails, setEditDetails] = useState(false) - const [name, setName] = useState('') - const [email, setEmail] = useState('') - - useEffect(() => { - setName(data?.name) - setEmail(data?.email) - }, [data]) - - if (error) { - history.push(routes.toLogin()) - } - - const updateUserDetails = async ({ email, name, password1 }: UserFormProps) => { - try { - await mutate({ email, name, password: password1 }) - showSuccess(getString('common.itemUpdated')) - refetch() - } catch (err) { - showError(`Error: ${err}`) - console.error({ err }) - } - } - - const handleSubmit = (data: UserFormProps): void => { - setEditDetails(false) - updateUserDetails(data) - } - - const editUserForm = ( - - initialValues={{ name: name as string, email: email as string, password1: '', password2: '' }} - formName="newPipelineForm" - onSubmit={handleSubmit}> - - - - {getString('common.name')} - - - - - - {getString('common.email')} - - - - - - {getString('password')} - - - - - - - - - - )) - - return ( - - - -