',
type: 'delete',
oldNumber: 52
},
{
- content: '+
',
type: 'insert',
newNumber: 52
},
@@ -4802,7 +4804,7 @@ export const commitDetailsStore: ICommitDetailsStore = {
newNumber: 88
},
{
- content: ' {file}',
+ content: ' {file}',
type: 'context',
oldNumber: 89,
newNumber: 89
@@ -4840,7 +4842,7 @@ export const commitDetailsStore: ICommitDetailsStore = {
'packages/ui/src/views/repo/pull-request/details/components/conversation/sections/pull-request-merge-section.tsx::::packages/ui/src/views/repo/pull-request/details/components/conversation/sections/pull-request-merge-section.tsx',
filePath:
'packages/ui/src/views/repo/pull-request/details/components/conversation/sections/pull-request-merge-section.tsx',
- raw: 'diff --git a/packages/ui/src/views/repo/pull-request/details/components/conversation/sections/pull-request-merge-section.tsx b/packages/ui/src/views/repo/pull-request/details/components/conversation/sections/pull-request-merge-section.tsx\nindex 2078a8fdb8f70cdb4548232c33a4fe548aa33bdd..8fee0e7e1c8c4581117f8866e01086a715161a7c 100644\n--- a/packages/ui/src/views/repo/pull-request/details/components/conversation/sections/pull-request-merge-section.tsx\n+++ b/packages/ui/src/views/repo/pull-request/details/components/conversation/sections/pull-request-merge-section.tsx\n@@ -49,7 +49,7 @@ const PullRequestMergeSection = ({\n \n ) : !mergeable ? (\n
\n-
\n+
\n Use the\n {\n@@ -84,7 +84,7 @@ const PullRequestMergeSection = ({\n {!isEmpty(conflictingFiles) && (\n \n {conflictingFiles?.map((file, idx) => (\n-
\n+
\n \n {file}\n
\n'
+ raw: 'diff --git a/packages/ui/src/views/repo/pull-request/details/components/conversation/sections/pull-request-merge-section.tsx b/packages/ui/src/views/repo/pull-request/details/components/conversation/sections/pull-request-merge-section.tsx\nindex 2078a8fdb8f70cdb4548232c33a4fe548aa33bdd..8fee0e7e1c8c4581117f8866e01086a715161a7c 100644\n--- a/packages/ui/src/views/repo/pull-request/details/components/conversation/sections/pull-request-merge-section.tsx\n+++ b/packages/ui/src/views/repo/pull-request/details/components/conversation/sections/pull-request-merge-section.tsx\n@@ -49,7 +49,7 @@ const PullRequestMergeSection = ({\n
\n ) : !mergeable ? (\n
\n-
\n+
\n Use the\n {\n@@ -84,7 +84,7 @@ const PullRequestMergeSection = ({\n {!isEmpty(conflictingFiles) && (\n \n {conflictingFiles?.map((file, idx) => (\n-
\n+
\n \n {file}\n
\n'
}
] as unknown as DiffFileEntry[],
commitData: {
diff --git a/apps/design-system/src/subjects/views/commit-details/index.tsx b/apps/design-system/src/subjects/views/commit-details/index.tsx
index 53621b956d..7aaa089f24 100644
--- a/apps/design-system/src/subjects/views/commit-details/index.tsx
+++ b/apps/design-system/src/subjects/views/commit-details/index.tsx
@@ -1,7 +1,5 @@
import { useCallback } from 'react'
-import { useTranslationStore } from '@utils/viewUtils'
-
import { ICommitDetailsStore, RepoCommitDetailsView } from '@harnessio/ui/views'
import { commitDetailsStore } from './commit-details-store'
@@ -9,7 +7,5 @@ import { commitDetailsStore } from './commit-details-store'
export const CommitDetailsView = () => {
const useCommitDetailsStore = useCallback((): ICommitDetailsStore => commitDetailsStore, [])
- return (
-
- )
+ return
}
diff --git a/apps/design-system/src/subjects/views/connectors/connector-details.tsx b/apps/design-system/src/subjects/views/connectors/connector-details.tsx
new file mode 100644
index 0000000000..305363c0a0
--- /dev/null
+++ b/apps/design-system/src/subjects/views/connectors/connector-details.tsx
@@ -0,0 +1,108 @@
+import { getHarnessConnectorDefinition } from '@utils/connectors/utils'
+import { noop } from 'lodash-es'
+
+import { InputFactory } from '@harnessio/forms'
+import { Tabs } from '@harnessio/ui/components'
+import {
+ ArrayFormInput,
+ BooleanFormInput,
+ CardsFormInput,
+ ConnectorDetailsActivities,
+ ConnectorDetailsConfiguration,
+ ConnectorDetailsItem,
+ ConnectorDetailsLayout,
+ ConnectorDetailsReference,
+ ConnectorDetailsTabsKeys,
+ GroupFormInput,
+ ListFormInput,
+ NumberFormInput,
+ SelectFormInput,
+ SeparatorFormInput,
+ TextareaFormInput,
+ TextFormInput
+} from '@harnessio/ui/views'
+
+import { mockConnectorActivityList } from './mock-connector-activity-list'
+import mockConnectorDetails from './mock-connector-details.json'
+import { mockConnectorRefList } from './mock-connector-ref-list'
+
+const inputComponentFactory = new InputFactory()
+inputComponentFactory.registerComponent(new TextFormInput())
+inputComponentFactory.registerComponent(new BooleanFormInput())
+inputComponentFactory.registerComponent(new NumberFormInput())
+inputComponentFactory.registerComponent(new ArrayFormInput())
+inputComponentFactory.registerComponent(new ListFormInput())
+inputComponentFactory.registerComponent(new TextareaFormInput())
+inputComponentFactory.registerComponent(new GroupFormInput())
+inputComponentFactory.registerComponent(new SelectFormInput())
+inputComponentFactory.registerComponent(new SeparatorFormInput())
+inputComponentFactory.registerComponent(new CardsFormInput())
+
+const ConnectorsDetailsPageWrapper = (): JSX.Element => {
+ const connectorDetails = {
+ name: mockConnectorDetails.connector.name,
+ identifier: mockConnectorDetails.connector.identifier,
+ type: mockConnectorDetails.connector.type,
+ status: mockConnectorDetails.status.status,
+ lastTestedAt: mockConnectorDetails.status.lastTestedAt,
+ lastModifiedAt: mockConnectorDetails.lastModifiedAt,
+ spec: {
+ url: mockConnectorDetails.connector.spec.url
+ },
+ gitDetails: {
+ repoIdentifier: mockConnectorDetails.gitDetails.repoIdentifier || '',
+ branch: mockConnectorDetails.gitDetails.branch || '',
+ objectId: mockConnectorDetails.gitDetails.objectId || ''
+ },
+ lastConnectedAt: mockConnectorDetails.status.lastConnectedAt,
+ createdAt: mockConnectorDetails.createdAt,
+ icon: 'github',
+ description: mockConnectorDetails.connector.description,
+ tags: mockConnectorDetails.connector.tags
+ } as ConnectorDetailsItem
+ return (
+
'/connectors'}
+ >
+
+ getHarnessConnectorDefinition(type, { autoExpandGroups: true })}
+ apiError={''}
+ />
+
+
+
+
+
+
+
+
+ )
+}
+
+export { ConnectorsDetailsPageWrapper }
diff --git a/apps/design-system/src/subjects/views/connectors/connectors-input.tsx b/apps/design-system/src/subjects/views/connectors/connectors-input.tsx
new file mode 100644
index 0000000000..78d8fdb124
--- /dev/null
+++ b/apps/design-system/src/subjects/views/connectors/connectors-input.tsx
@@ -0,0 +1,34 @@
+import { useState } from 'react'
+
+import { Link } from '@harnessio/ui/components'
+import { ConnectorInput, ConnectorItem } from '@harnessio/ui/views'
+
+import { ConnectorsRefPage } from './connectors-ref'
+
+export const ConnectorInputExample = () => {
+ const [isDrawerOpen, setIsDrawerOpen] = useState(false)
+ const [selectedConnector, setSelectedConnector] = useState
(null)
+
+ return (
+ <>
+ Please select a connector}
+ value={selectedConnector}
+ onClick={() => {
+ setIsDrawerOpen(true)
+ }}
+ onEdit={() => {
+ setIsDrawerOpen(true)
+ }}
+ onClear={() => setSelectedConnector(null)}
+ renderValue={connector => connector.name}
+ />
+
+ >
+ )
+}
diff --git a/apps/design-system/src/subjects/views/connectors/connectors-list.tsx b/apps/design-system/src/subjects/views/connectors/connectors-list.tsx
new file mode 100644
index 0000000000..1365a1a2ef
--- /dev/null
+++ b/apps/design-system/src/subjects/views/connectors/connectors-list.tsx
@@ -0,0 +1,76 @@
+import { useState } from 'react'
+
+import { noop } from 'lodash-es'
+
+import { DeleteAlertDialog } from '@harnessio/ui/components'
+import { ConnectorListFilters, ConnectorListItem, ConnectorsListPage } from '@harnessio/ui/views'
+
+import mockConnectorsList from './mock-connectors-list.json'
+
+const ConnectorsListPageWrapper = (): JSX.Element => {
+ const [alertDeleteParams, setAlertDeleteParams] = useState('')
+ const [isAlertDeleteDialogOpen, setIsAlertDeleteDialogOpen] = useState(false)
+
+ const closeAlertDeleteDialog = () => setIsAlertDeleteDialogOpen(false)
+ const openAlertDeleteDialog = (identifier: string) => {
+ setAlertDeleteParams(identifier)
+ setIsAlertDeleteDialogOpen(true)
+ }
+ const [filterValues, setFilterValues] = useState({})
+ const filteredMockConnectorsList = mockConnectorsList.filter(connector => {
+ return filterValues?.favorite ? connector.isFavorite : true
+ })
+
+ const handleFilterChange = (selectedValues: ConnectorListFilters) => {
+ setFilterValues(selectedValues)
+ }
+
+ return (
+ <>
+ ({
+ name: connector.connector.name,
+ identifier: connector.connector.identifier,
+ type: connector.connector.type,
+ status: connector.status,
+ lastTestedAt: connector.status.lastTestedAt,
+ lastModifiedAt: connector.lastModifiedAt,
+ spec: {
+ url: connector.connector.spec.url
+ },
+ gitDetails: {
+ repoIdentifier: connector.gitDetails.repoIdentifier || '',
+ branch: connector.gitDetails.branch || '',
+ objectId: connector.gitDetails.objectId || ''
+ },
+ isFavorite: connector.isFavorite
+ })) as ConnectorListItem[]
+ }
+ isLoading={false}
+ onFilterChange={handleFilterChange}
+ setSearchQuery={noop}
+ onEditConnector={noop}
+ onDeleteConnector={openAlertDeleteDialog}
+ onTestConnection={noop}
+ onToggleFavoriteConnector={noop}
+ currentPage={1}
+ totalItems={filteredMockConnectorsList.length}
+ pageSize={10}
+ goToPage={noop}
+ onCreate={noop}
+ />
+
+
+ >
+ )
+}
+
+export { ConnectorsListPageWrapper }
diff --git a/apps/design-system/src/subjects/views/connectors/connectors-ref.tsx b/apps/design-system/src/subjects/views/connectors/connectors-ref.tsx
new file mode 100644
index 0000000000..51933f8c89
--- /dev/null
+++ b/apps/design-system/src/subjects/views/connectors/connectors-ref.tsx
@@ -0,0 +1,200 @@
+import { useState } from 'react'
+
+import { getHarnessConnectorDefinition, harnessConnectors } from '@utils/connectors/utils'
+import { noop } from '@utils/viewUtils'
+
+import { InputFactory } from '@harnessio/forms'
+import { Button, ButtonLayout, Drawer, FormSeparator, Spacer, Text } from '@harnessio/ui/components'
+import {
+ ArrayFormInput,
+ BooleanFormInput,
+ CardsFormInput,
+ ConnectorEntity,
+ ConnectorEntityForm,
+ ConnectorHeader,
+ ConnectorItem,
+ ConnectorReference,
+ ConnectorSelectionType,
+ ConnectorsPalette,
+ DirectionEnum,
+ EntityIntent,
+ GroupFormInput,
+ ListFormInput,
+ NumberFormInput,
+ SelectFormInput,
+ SeparatorFormInput,
+ TextareaFormInput,
+ TextFormInput
+} from '@harnessio/ui/views'
+
+import mockAccountsData from '../secrets/mock-account-data.json'
+import mockOrgData from '../secrets/mock-org-data.json'
+import mockProjectsData from '../secrets/mock-project-data.json'
+import { Scope, ScopeEnum, scopeHierarchy } from '../secrets/types'
+import mockConnectorsData from './mock-connectors-data.json'
+
+const inputComponentFactory = new InputFactory()
+inputComponentFactory.registerComponent(new TextFormInput())
+inputComponentFactory.registerComponent(new BooleanFormInput())
+inputComponentFactory.registerComponent(new NumberFormInput())
+inputComponentFactory.registerComponent(new ArrayFormInput())
+inputComponentFactory.registerComponent(new ListFormInput())
+inputComponentFactory.registerComponent(new TextareaFormInput())
+inputComponentFactory.registerComponent(new GroupFormInput())
+inputComponentFactory.registerComponent(new SelectFormInput())
+inputComponentFactory.registerComponent(new SeparatorFormInput())
+inputComponentFactory.registerComponent(new CardsFormInput())
+
+export const ConnectorsRefPage = ({
+ isDrawerOpen,
+ setIsDrawerOpen,
+ selectedConnector,
+ setSelectedConnector
+}: {
+ isDrawerOpen: boolean
+ setIsDrawerOpen: (open: boolean) => void
+ selectedConnector: ConnectorItem | null
+ setSelectedConnector: (connector: ConnectorItem | null) => void
+}) => {
+ const [selectedType, setSelectedType] = useState(ConnectorSelectionType.EXISTING)
+ const [activeScope, setActiveScope] = useState(ScopeEnum.ORGANIZATION)
+ const [connectorEntity, setConnectorEntity] = useState(null)
+
+ // State for existing connectors
+ const [parentFolder, setParentFolder] = useState(mockAccountsData[0].accountName)
+ const [currentFolder, setCurrentFolder] = useState(
+ mockOrgData[0].organizationResponse.organization.identifier
+ )
+ const [childFolder, setChildFolder] = useState(mockProjectsData[0].projectResponse.project.identifier)
+ const [isConnectorSelected, setIsConnectorSelected] = useState(false)
+
+ const [search, setSearch] = useState('')
+
+ // Handlers for existing connectors
+ const handleSelectConnector = (connector: ConnectorItem) => {
+ setSelectedConnector(connector)
+ console.log('Selected connector:', connector)
+ setIsDrawerOpen(false)
+ }
+
+ const handleScopeChange = (direction: DirectionEnum) => {
+ setActiveScope(prevScope => {
+ const newScope =
+ direction === DirectionEnum.PARENT ? scopeHierarchy[prevScope].parent! : scopeHierarchy[prevScope].child!
+ switch (newScope) {
+ case ScopeEnum.ACCOUNT:
+ setParentFolder(null)
+ setCurrentFolder(mockAccountsData[0].accountName)
+ setChildFolder(mockOrgData[0].organizationResponse.organization.identifier)
+ break
+ case ScopeEnum.ORGANIZATION:
+ setParentFolder(mockAccountsData[0].accountName)
+ setCurrentFolder(mockOrgData[0].organizationResponse.organization.identifier)
+ setChildFolder(mockProjectsData[0].projectResponse.project.identifier)
+ break
+ case ScopeEnum.PROJECT:
+ setParentFolder(mockOrgData[0].organizationResponse.organization.identifier)
+ setCurrentFolder(mockProjectsData[0].projectResponse.project.identifier)
+ setChildFolder(null)
+ break
+ }
+ return newScope
+ })
+ }
+
+ const handleCancel = () => {
+ setIsDrawerOpen(false)
+ }
+
+ const renderConnectorContent = () => {
+ switch (selectedType) {
+ case ConnectorSelectionType.NEW:
+ return (
+
+ {/* Render create connector flow from here */}
+ setIsConnectorSelected(true)}
+ setConnectorEntity={setConnectorEntity}
+ />
+
+
+ {!!connectorEntity && (
+ setIsConnectorSelected(false)}
+ // onFormSubmit={handleFormSubmit}
+ getConnectorDefinition={getHarnessConnectorDefinition}
+ inputComponentFactory={inputComponentFactory}
+ isDrawer
+ />
+ )}
+
+
+
+ )
+ case ConnectorSelectionType.EXISTING:
+ return (
+ {
+ return {
+ ...connector,
+ name: connector.connector.name,
+ id: connector.connector.identifier
+ }
+ }) as ConnectorItem[]
+ }
+ parentFolder={parentFolder}
+ childFolder={childFolder}
+ selectedEntity={selectedConnector}
+ onSelectEntity={handleSelectConnector}
+ onScopeChange={handleScopeChange}
+ isLoading={false}
+ apiError="Could not fetch connectors, unauthorized"
+ currentFolder={currentFolder}
+ showBreadcrumbEllipsis={activeScope === ScopeEnum.PROJECT}
+ onFilterChange={noop}
+ searchValue={search}
+ handleChangeSearchValue={setSearch}
+ isDrawer
+ />
+ )
+ default:
+ return null
+ }
+ }
+
+ return (
+
+
+
+ Connectors
+
+
+ Choose type
+
+
+
+
+
+
+ {renderConnectorContent()}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/design-system/src/subjects/views/connectors/connectors.tsx b/apps/design-system/src/subjects/views/connectors/connectors.tsx
new file mode 100644
index 0000000000..6c876baf16
--- /dev/null
+++ b/apps/design-system/src/subjects/views/connectors/connectors.tsx
@@ -0,0 +1,155 @@
+import { useState } from 'react'
+
+import { getHarnessConnectorDefinition, harnessConnectors } from '@utils/connectors/utils'
+
+import { InputFactory } from '@harnessio/forms'
+import { Button, Drawer, ListActions, Spacer } from '@harnessio/ui/components'
+import {
+ ArrayFormInput,
+ BooleanFormInput,
+ CardsFormInput,
+ ConnectorEntity,
+ ConnectorEntityForm,
+ ConnectorsPalette,
+ ConnectorTestConnectionDialog,
+ EntityIntent,
+ GroupFormInput,
+ ListFormInput,
+ NumberFormInput,
+ SandboxLayout,
+ SelectFormInput,
+ SeparatorFormInput,
+ TextareaFormInput,
+ TextFormInput
+} from '@harnessio/ui/views'
+
+const inputComponentFactory = new InputFactory()
+inputComponentFactory.registerComponent(new TextFormInput())
+inputComponentFactory.registerComponent(new BooleanFormInput())
+inputComponentFactory.registerComponent(new NumberFormInput())
+inputComponentFactory.registerComponent(new ArrayFormInput())
+inputComponentFactory.registerComponent(new ListFormInput())
+inputComponentFactory.registerComponent(new TextareaFormInput())
+inputComponentFactory.registerComponent(new GroupFormInput())
+inputComponentFactory.registerComponent(new SelectFormInput())
+inputComponentFactory.registerComponent(new SeparatorFormInput())
+inputComponentFactory.registerComponent(new CardsFormInput())
+
+const ConnectorsListPageContent = (): JSX.Element => {
+ const [connectorEntity, setConnectorEntity] = useState(null)
+ const [isConnectorDrawerOpen, setIsConnectorDrawerOpen] = useState(false)
+ const [isEditConnectorDrawerOpen, setIsEditConnectorDrawerOpen] = useState(false)
+ const [isConnectorSelected, setIsConnectorSelected] = useState(false)
+ const [intent, setIntent] = useState(EntityIntent.CREATE)
+ const [testConnectionOpen, setTestConnectionOpen] = useState(false)
+
+ const onCloseConnectorDrawer = () => {
+ setIsConnectorDrawerOpen(false)
+ setConnectorEntity(null)
+ }
+
+ return (
+
+
+ <>
+ Connectors
+
+
+
+
+
+
+
+
+
+ >
+
+
+ setTestConnectionOpen(false)}
+ viewDocClick={() => {
+ console.log('')
+ }}
+ errorData={{ errors: [{ reason: 'Unexpected Error', message: 'Bad credentials' }] }}
+ />
+
+
+ setIsConnectorSelected(true)}
+ setConnectorEntity={setConnectorEntity}
+ requestClose={onCloseConnectorDrawer}
+ isDrawer
+ >
+
+
+ {!!connectorEntity && (
+ setIsConnectorSelected(false)}
+ // onFormSubmit={handleFormSubmit}
+ getConnectorDefinition={getHarnessConnectorDefinition}
+ inputComponentFactory={inputComponentFactory}
+ intent={intent}
+ isDrawer
+ />
+ )}
+
+
+
+
+
+
+ {!!connectorEntity && (
+ setIsEditConnectorDrawerOpen(false)}
+ getConnectorDefinition={getHarnessConnectorDefinition}
+ inputComponentFactory={inputComponentFactory}
+ intent={intent}
+ isDrawer
+ />
+ )}
+
+
+
+ )
+}
+
+// temp component for testing in standalone
+const ConnectorsPage = (): JSX.Element => {
+ return
+}
+
+export { ConnectorsPage }
diff --git a/apps/design-system/src/subjects/views/connectors/mock-connector-activity-list.ts b/apps/design-system/src/subjects/views/connectors/mock-connector-activity-list.ts
new file mode 100644
index 0000000000..bd511dc8e5
--- /dev/null
+++ b/apps/design-system/src/subjects/views/connectors/mock-connector-activity-list.ts
@@ -0,0 +1,32 @@
+import { ConnectorActivityList } from '@harnessio/ui/views'
+
+export const mockConnectorActivityList = {
+ content: [
+ {
+ referredEntity: {
+ type: 'Connectors',
+ entityRef: {
+ scope: 'project',
+ identifier: 'bittest1',
+ accountIdentifier: 'px7xd_BFRCi-pfWPYXVjvw',
+ orgIdentifier: 'default',
+ projectIdentifier: 'abhinavtest3',
+ parentUniqueId: 'vUF6sjOUR6ycGYYGxn9Njw',
+ metadata: {
+ connectorType: 'BITBUCKET'
+ },
+ repoIdentifier: null,
+ branch: null,
+ isDefault: false,
+ default: false,
+ fullyQualifiedScopeIdentifier: 'px7xd_BFRCi-pfWPYXVjvw/default/abhinavtest3'
+ },
+ name: 'bittest1',
+ entityGitMetadata: null
+ },
+ activityStatus: 'SUCCESS',
+ activityTime: 1744997551429,
+ description: 'Connector Created'
+ }
+ ]
+} as ConnectorActivityList
diff --git a/apps/design-system/src/subjects/views/connectors/mock-connector-details.json b/apps/design-system/src/subjects/views/connectors/mock-connector-details.json
new file mode 100644
index 0000000000..2b5e1aa561
--- /dev/null
+++ b/apps/design-system/src/subjects/views/connectors/mock-connector-details.json
@@ -0,0 +1,72 @@
+{
+ "connector": {
+ "name": "Github Connector",
+ "identifier": "connector3",
+ "description": "Preconfigured Docker connector for use in Harness",
+ "accountIdentifier": "account123",
+ "orgIdentifier": "org1",
+ "projectIdentifier": "project1",
+ "tags": {
+ "connector": "",
+ "new": "",
+ "main": ""
+ },
+ "type": "Github",
+ "spec": {
+ "url": "https://github.com/organization/repository3",
+ "validationRepo": null,
+ "authentication": {
+ "type": "Http",
+ "spec": {
+ "type": "UsernameToken",
+ "spec": {
+ "username": "username3",
+ "usernameRef": null,
+ "tokenRef": "token3"
+ }
+ }
+ },
+ "apiAccess": null,
+ "delegateSelectors": ["delegate-1"],
+ "executeOnDelegate": true,
+ "proxy": false,
+ "ignoreTestConnection": false,
+ "type": "Repo"
+ }
+ },
+ "createdAt": 1733229200306,
+ "lastModifiedAt": 1733229200304,
+ "status": {
+ "status": "SUCCESS",
+ "errorSummary": null,
+ "errors": null,
+ "testedAt": 1733229203620,
+ "lastTestedAt": 1733229203620,
+ "lastConnectedAt": 1733229203620,
+ "lastAlertSent": null
+ },
+ "activityDetails": {
+ "lastActivityTime": 1733229200304
+ },
+ "harnessManaged": false,
+ "gitDetails": {
+ "objectId": null,
+ "branch": null,
+ "repoIdentifier": null,
+ "rootFolder": null,
+ "filePath": null,
+ "repoName": null,
+ "commitId": null,
+ "fileUrl": null,
+ "repoUrl": null,
+ "parentEntityConnectorRef": null,
+ "parentEntityRepoName": null,
+ "isHarnessCodeRepo": null
+ },
+ "entityValidityDetails": {
+ "valid": true,
+ "invalidYaml": null
+ },
+ "governanceMetadata": null,
+ "isFavorite": false
+}
diff --git a/apps/design-system/src/subjects/views/connectors/mock-connector-ref-list.ts b/apps/design-system/src/subjects/views/connectors/mock-connector-ref-list.ts
new file mode 100644
index 0000000000..1bd06e4d9e
--- /dev/null
+++ b/apps/design-system/src/subjects/views/connectors/mock-connector-ref-list.ts
@@ -0,0 +1,339 @@
+import { ConnectorReferenceList } from '@harnessio/ui/views'
+
+export const mockConnectorRefList = {
+ content: [
+ {
+ accountIdentifier: 'account123456789',
+ referredEntity: {
+ type: 'Connectors',
+ entityRef: {
+ scope: 'org',
+ identifier: 'connector-id-1',
+ accountIdentifier: 'account123456789',
+ orgIdentifier: 'default',
+ projectIdentifier: null,
+ parentUniqueId: 'parent-unique-id-1',
+ metadata: {
+ fqn: 'pipeline.stages.test.spec.execution.steps.Run_1.spec.connectorRef'
+ },
+ repoIdentifier: null,
+ branch: null,
+ isDefault: true,
+ default: true,
+ fullyQualifiedScopeIdentifier: 'account123456789/default'
+ },
+ name: '',
+ entityGitMetadata: null
+ },
+ referredByEntity: {
+ type: 'Pipelines',
+ entityRef: {
+ scope: 'project',
+ identifier: 'project-1',
+ accountIdentifier: 'account123456789',
+ orgIdentifier: 'default',
+ projectIdentifier: 'project-demo-1',
+ parentUniqueId: 'parent-pipeline-id-1',
+ metadata: {},
+ repoIdentifier: null,
+ branch: null,
+ isDefault: true,
+ default: true,
+ fullyQualifiedScopeIdentifier: 'account123456789/default/project-demo-1'
+ },
+ name: 'project-1',
+ entityGitMetadata: null
+ },
+ detail: {
+ type: 'EntityReferredByPipelineSetupUsageDetail',
+ identifier: 'test',
+ referenceType: 'STAGE_IDENTIFIER'
+ },
+ createdAt: 1600000000000
+ },
+ {
+ accountIdentifier: 'account123456789',
+ referredEntity: {
+ type: 'Connectors',
+ entityRef: {
+ scope: 'org',
+ identifier: 'connector-id-1',
+ accountIdentifier: 'account123456789',
+ orgIdentifier: 'default',
+ projectIdentifier: null,
+ parentUniqueId: 'parent-unique-id-1',
+ metadata: {
+ fqn: 'pipeline.stages.CustomCDK.spec.execution.steps.Cdk_Step_Group.steps.Background_1.spec.connectorRef'
+ },
+ repoIdentifier: null,
+ branch: null,
+ isDefault: true,
+ default: true,
+ fullyQualifiedScopeIdentifier: 'account123456789/default'
+ },
+ name: '',
+ entityGitMetadata: null
+ },
+ referredByEntity: {
+ type: 'Pipelines',
+ entityRef: {
+ scope: 'project',
+ identifier: 'project-2',
+ accountIdentifier: 'account123456789',
+ orgIdentifier: 'default',
+ projectIdentifier: 'project-demo-2',
+ parentUniqueId: 'parent-pipeline-id-2',
+ metadata: {},
+ repoIdentifier: null,
+ branch: null,
+ isDefault: true,
+ default: true,
+ fullyQualifiedScopeIdentifier: 'account123456789/default/project-demo-2'
+ },
+ name: 'project-pipeline-2',
+ entityGitMetadata: null
+ },
+ detail: {
+ type: 'EntityReferredByPipelineSetupUsageDetail',
+ identifier: 'CustomCDK',
+ referenceType: 'STAGE_IDENTIFIER'
+ },
+ createdAt: 1600100000000
+ },
+ {
+ accountIdentifier: 'account123456789',
+ referredEntity: {
+ type: 'Connectors',
+ entityRef: {
+ scope: 'org',
+ identifier: 'connector-id-1',
+ accountIdentifier: 'account123456789',
+ orgIdentifier: 'default',
+ projectIdentifier: null,
+ parentUniqueId: 'parent-unique-id-1',
+ metadata: {
+ fqn: 'service.serviceDefinition.spec.artifacts.primary.sources.harness_idp_ui_gar.spec.connectorRef'
+ },
+ repoIdentifier: null,
+ branch: null,
+ isDefault: true,
+ default: true,
+ fullyQualifiedScopeIdentifier: 'account123456789/default'
+ },
+ name: '',
+ entityGitMetadata: null
+ },
+ referredByEntity: {
+ type: 'Service',
+ entityRef: {
+ scope: 'project',
+ identifier: 'service-1',
+ accountIdentifier: 'account123456789',
+ orgIdentifier: 'default',
+ projectIdentifier: 'project-demo-3',
+ parentUniqueId: 'parent-service-id-1',
+ metadata: {},
+ repoIdentifier: null,
+ branch: null,
+ isDefault: true,
+ default: true,
+ fullyQualifiedScopeIdentifier: 'account123456789/default/project-demo-3'
+ },
+ name: 'service-app',
+ entityGitMetadata: null
+ },
+ detail: null,
+ createdAt: 1600200000000
+ },
+ {
+ accountIdentifier: 'account123456789',
+ referredEntity: {
+ type: 'Connectors',
+ entityRef: {
+ scope: 'org',
+ identifier: 'connector-id-1',
+ accountIdentifier: 'account123456789',
+ orgIdentifier: 'default',
+ projectIdentifier: null,
+ parentUniqueId: 'parent-unique-id-1',
+ metadata: {
+ fqn: 'service.serviceDefinition.spec.artifacts.primary.sources.artifactId.spec.connectorRef'
+ },
+ repoIdentifier: null,
+ branch: null,
+ isDefault: true,
+ default: true,
+ fullyQualifiedScopeIdentifier: 'account123456789/default'
+ },
+ name: '',
+ entityGitMetadata: null
+ },
+ referredByEntity: {
+ type: 'Service',
+ entityRef: {
+ scope: 'project',
+ identifier: 'service-2',
+ accountIdentifier: 'account123456789',
+ orgIdentifier: 'default',
+ projectIdentifier: 'project-demo-2',
+ parentUniqueId: 'parent-pipeline-id-2',
+ metadata: {},
+ repoIdentifier: null,
+ branch: null,
+ isDefault: true,
+ default: true,
+ fullyQualifiedScopeIdentifier: 'account123456789/default/project-demo-2'
+ },
+ name: 'service-2',
+ entityGitMetadata: null
+ },
+ detail: null,
+ createdAt: 1600300000000
+ },
+ {
+ accountIdentifier: 'account123456789',
+ referredEntity: {
+ type: 'Connectors',
+ entityRef: {
+ scope: 'org',
+ identifier: 'connector-id-1',
+ accountIdentifier: 'account123456789',
+ orgIdentifier: 'default',
+ projectIdentifier: null,
+ parentUniqueId: 'parent-unique-id-1',
+ metadata: {
+ fqn: 'pipeline.stages.buildStg.spec.execution.steps.Run_1.spec.connectorRef'
+ },
+ repoIdentifier: null,
+ branch: null,
+ isDefault: true,
+ default: true,
+ fullyQualifiedScopeIdentifier: 'account123456789/default'
+ },
+ name: '',
+ entityGitMetadata: null
+ },
+ referredByEntity: {
+ type: 'Pipelines',
+ entityRef: {
+ scope: 'project',
+ identifier: 'project-3',
+ accountIdentifier: 'account123456789',
+ orgIdentifier: 'default',
+ projectIdentifier: 'project-demo-2',
+ parentUniqueId: 'parent-pipeline-id-2',
+ metadata: {},
+ repoIdentifier: null,
+ branch: null,
+ isDefault: true,
+ default: true,
+ fullyQualifiedScopeIdentifier: 'account123456789/default/project-demo-2'
+ },
+ name: 'test-nested-template',
+ entityGitMetadata: null
+ },
+ detail: {
+ type: 'EntityReferredByPipelineSetupUsageDetail',
+ identifier: 'buildStg',
+ referenceType: 'STAGE_IDENTIFIER'
+ },
+ createdAt: 1600400000000
+ },
+ {
+ accountIdentifier: 'account123456789',
+ referredEntity: {
+ type: 'Connectors',
+ entityRef: {
+ scope: 'org',
+ identifier: 'connector-id-1',
+ accountIdentifier: 'account123456789',
+ orgIdentifier: 'default',
+ projectIdentifier: null,
+ parentUniqueId: 'parent-unique-id-1',
+ metadata: {
+ fqn: 'templateInputs.spec.execution.steps.BuildAndPushGAR_1.spec.connectorRef'
+ },
+ repoIdentifier: null,
+ branch: null,
+ isDefault: true,
+ default: true,
+ fullyQualifiedScopeIdentifier: 'account123456789/default'
+ },
+ name: '',
+ entityGitMetadata: null
+ },
+ referredByEntity: {
+ type: 'Template',
+ entityRef: {
+ accountIdentifier: 'account123456789',
+ orgIdentifier: 'default',
+ projectIdentifier: 'project-demo-4',
+ parentUniqueId: 'parent-template-id-1',
+ identifier: 'template-1',
+ versionLabel: '1.0',
+ repoIdentifier: null,
+ branch: null,
+ isDefault: true,
+ scope: 'project',
+ default: true,
+ metadata: {
+ versionLabel: '1.0'
+ }
+ },
+ name: 'build-machine-image',
+ entityGitMetadata: null
+ },
+ detail: null,
+ createdAt: 1600500000000
+ },
+ {
+ accountIdentifier: 'account123456789',
+ referredEntity: {
+ type: 'Connectors',
+ entityRef: {
+ scope: 'org',
+ identifier: 'connector-id-1',
+ accountIdentifier: 'account123456789',
+ orgIdentifier: 'default',
+ projectIdentifier: null,
+ parentUniqueId: 'parent-unique-id-1',
+ metadata: {
+ fqn: 'pipeline.stages.BuildLinuxx64.spec.execution.steps.BuildAndPushGAR_1.spec.connectorRef'
+ },
+ repoIdentifier: null,
+ branch: null,
+ isDefault: true,
+ default: true,
+ fullyQualifiedScopeIdentifier: 'account123456789/default'
+ },
+ name: '',
+ entityGitMetadata: null
+ },
+ referredByEntity: {
+ type: 'Pipelines',
+ entityRef: {
+ scope: 'project',
+ identifier: 'project-4',
+ accountIdentifier: 'account123456789',
+ orgIdentifier: 'default',
+ projectIdentifier: 'project-demo-4',
+ parentUniqueId: 'parent-template-id-1',
+ metadata: {},
+ repoIdentifier: null,
+ branch: null,
+ isDefault: true,
+ default: true,
+ fullyQualifiedScopeIdentifier: 'account123456789/default/project-demo-4'
+ },
+ name: 'build-machines',
+ entityGitMetadata: null
+ },
+ detail: {
+ type: 'EntityReferredByPipelineSetupUsageDetail',
+ identifier: 'BuildLinux',
+ referenceType: 'STAGE_IDENTIFIER'
+ },
+ createdAt: 1600600000000
+ }
+ ]
+} as ConnectorReferenceList
diff --git a/apps/design-system/src/subjects/views/connectors/mock-connectors-data.json b/apps/design-system/src/subjects/views/connectors/mock-connectors-data.json
new file mode 100644
index 0000000000..a7f3d3ca7d
--- /dev/null
+++ b/apps/design-system/src/subjects/views/connectors/mock-connectors-data.json
@@ -0,0 +1,223 @@
+[
+ {
+ "connector": {
+ "name": "connector-1",
+ "identifier": "connector1",
+ "description": "",
+ "accountIdentifier": "account123",
+ "orgIdentifier": "org1",
+ "projectIdentifier": "project1",
+ "tags": {},
+ "type": "Github",
+ "spec": {
+ "url": "https://github.com/organization/repository",
+ "validationRepo": null,
+ "authentication": {
+ "type": "Http",
+ "spec": {
+ "type": "UsernameToken",
+ "spec": {
+ "username": "username1",
+ "usernameRef": null,
+ "tokenRef": "token1"
+ }
+ }
+ },
+ "apiAccess": {
+ "type": "Token",
+ "spec": {
+ "tokenRef": "token1"
+ }
+ },
+ "delegateSelectors": [],
+ "executeOnDelegate": false,
+ "proxy": false,
+ "ignoreTestConnection": false,
+ "type": "Repo"
+ }
+ },
+ "createdAt": 1719353669620,
+ "lastModifiedAt": 1719353669616,
+ "status": {
+ "status": "SUCCESS",
+ "errorSummary": null,
+ "errors": null,
+ "testedAt": 1719353671202,
+ "lastTestedAt": 0,
+ "lastConnectedAt": 1719353671202,
+ "lastAlertSent": null
+ },
+ "activityDetails": {
+ "lastActivityTime": 1719353669616
+ },
+ "harnessManaged": false,
+ "gitDetails": {
+ "objectId": null,
+ "branch": null,
+ "repoIdentifier": null,
+ "rootFolder": null,
+ "filePath": null,
+ "repoName": null,
+ "commitId": null,
+ "fileUrl": null,
+ "repoUrl": null,
+ "parentEntityConnectorRef": null,
+ "parentEntityRepoName": null,
+ "isHarnessCodeRepo": null
+ },
+ "entityValidityDetails": {
+ "valid": true,
+ "invalidYaml": null
+ },
+ "governanceMetadata": null,
+ "isFavorite": false
+ },
+ {
+ "connector": {
+ "name": "connector-2",
+ "identifier": "connector2",
+ "description": "",
+ "accountIdentifier": "account123",
+ "orgIdentifier": "org1",
+ "projectIdentifier": "project1",
+ "tags": {},
+ "type": "Github",
+ "spec": {
+ "url": "https://github.com/organization/repository2",
+ "validationRepo": null,
+ "authentication": {
+ "type": "Http",
+ "spec": {
+ "type": "UsernameToken",
+ "spec": {
+ "username": "username2",
+ "usernameRef": null,
+ "tokenRef": "token2"
+ }
+ }
+ },
+ "apiAccess": null,
+ "delegateSelectors": ["delegate-1"],
+ "executeOnDelegate": true,
+ "proxy": false,
+ "ignoreTestConnection": false,
+ "type": "Repo"
+ }
+ },
+ "createdAt": 1700007726035,
+ "lastModifiedAt": 1700007726032,
+ "status": {
+ "status": "FAILURE",
+ "errorSummary": "Error Encountered (Please ensure that the api access credentials are correct.)",
+ "errors": [
+ {
+ "reason": "Unexpected Error",
+ "message": "Please ensure that the api access credentials are correct.",
+ "code": 450
+ }
+ ],
+ "testedAt": 1700010337928,
+ "lastTestedAt": 0,
+ "lastConnectedAt": 0,
+ "lastAlertSent": null
+ },
+ "activityDetails": {
+ "lastActivityTime": 1700007726157
+ },
+ "harnessManaged": false,
+ "gitDetails": {
+ "objectId": null,
+ "branch": null,
+ "repoIdentifier": null,
+ "rootFolder": null,
+ "filePath": null,
+ "repoName": null,
+ "commitId": null,
+ "fileUrl": null,
+ "repoUrl": null,
+ "parentEntityConnectorRef": null,
+ "parentEntityRepoName": null,
+ "isHarnessCodeRepo": null
+ },
+ "entityValidityDetails": {
+ "valid": true,
+ "invalidYaml": null
+ },
+ "governanceMetadata": null,
+ "isFavorite": false
+ },
+ {
+ "connector": {
+ "name": "connector-3",
+ "identifier": "connector3",
+ "description": "",
+ "accountIdentifier": "account123",
+ "orgIdentifier": "org1",
+ "projectIdentifier": "project1",
+ "tags": {},
+ "type": "Github",
+ "spec": {
+ "url": "https://github.com/organization/repository3",
+ "validationRepo": null,
+ "authentication": {
+ "type": "Http",
+ "spec": {
+ "type": "UsernameToken",
+ "spec": {
+ "username": "username3",
+ "usernameRef": null,
+ "tokenRef": "token3"
+ }
+ }
+ },
+ "apiAccess": null,
+ "delegateSelectors": ["delegate-1"],
+ "executeOnDelegate": true,
+ "proxy": false,
+ "ignoreTestConnection": false,
+ "type": "Repo"
+ }
+ },
+ "createdAt": 1700005553911,
+ "lastModifiedAt": 1700005642847,
+ "status": {
+ "status": "FAILURE",
+ "errorSummary": "Error Encountered (There are no eligible delegates available in the account to execute the task.\n\nNon active delegates , Delegate(s) don't have selectors [delegate-1])",
+ "errors": [
+ {
+ "reason": "Unexpected Error",
+ "message": "There are no eligible delegates available in the account to execute the task.\n\nNon active delegates , Delegate(s) don't have selectors [delegate-1]",
+ "code": 450
+ }
+ ],
+ "testedAt": 1700007688566,
+ "lastTestedAt": 0,
+ "lastConnectedAt": 0,
+ "lastAlertSent": null
+ },
+ "activityDetails": {
+ "lastActivityTime": 1700005642977
+ },
+ "harnessManaged": false,
+ "gitDetails": {
+ "objectId": null,
+ "branch": null,
+ "repoIdentifier": null,
+ "rootFolder": null,
+ "filePath": null,
+ "repoName": null,
+ "commitId": null,
+ "fileUrl": null,
+ "repoUrl": null,
+ "parentEntityConnectorRef": null,
+ "parentEntityRepoName": null,
+ "isHarnessCodeRepo": null
+ },
+ "entityValidityDetails": {
+ "valid": true,
+ "invalidYaml": null
+ },
+ "governanceMetadata": null,
+ "isFavorite": false
+ }
+]
diff --git a/apps/design-system/src/subjects/views/connectors/mock-connectors-list.json b/apps/design-system/src/subjects/views/connectors/mock-connectors-list.json
new file mode 100644
index 0000000000..86c6f9ce1a
--- /dev/null
+++ b/apps/design-system/src/subjects/views/connectors/mock-connectors-list.json
@@ -0,0 +1,755 @@
+[
+ {
+ "connector": {
+ "name": "idp_automation_gitlab_repo_token_delegate_with_api_accessTqIO4qjN8S",
+ "identifier": "idp_automation_gitlab_repo_token_delegate_with_api_accessTqIO4qjN8S",
+ "description": "",
+ "accountIdentifier": "vpCkHKsDSxK9_KYfjCTMKA",
+ "orgIdentifier": null,
+ "projectIdentifier": null,
+ "tags": {},
+ "type": "Gitlab",
+ "spec": {
+ "url": "https://gitlab.com/sathish1293/sathish",
+ "validationRepo": null,
+ "authentication": {
+ "type": "Http",
+ "spec": {
+ "type": "UsernameToken",
+ "spec": {
+ "username": "sathish1293",
+ "usernameRef": null,
+ "tokenRef": "account.idp_integrations_git_gitlab_repo_tokenmKcPW7X8I4"
+ }
+ }
+ },
+ "apiAccess": {
+ "type": "Token",
+ "spec": {
+ "tokenRef": "account.idp_integrations_git_gitlab_repo_tokenmKcPW7X8I4",
+ "apiUrl": ""
+ }
+ },
+ "delegateSelectors": [],
+ "executeOnDelegate": true,
+ "proxy": false,
+ "ignoreTestConnection": false,
+ "type": "Repo"
+ }
+ },
+ "createdAt": 1733229200306,
+ "lastModifiedAt": 1745418900000,
+ "status": {
+ "status": "SUCCESS",
+ "errorSummary": null,
+ "errors": null,
+ "testedAt": 1733229203620,
+ "lastTestedAt": 0,
+ "lastConnectedAt": 1733229203620,
+ "lastAlertSent": null
+ },
+ "activityDetails": {
+ "lastActivityTime": 1733229200304
+ },
+ "harnessManaged": false,
+ "gitDetails": {
+ "objectId": null,
+ "branch": null,
+ "repoIdentifier": null,
+ "rootFolder": null,
+ "filePath": null,
+ "repoName": null,
+ "commitId": null,
+ "fileUrl": null,
+ "repoUrl": null,
+ "parentEntityConnectorRef": null,
+ "parentEntityRepoName": null,
+ "isHarnessCodeRepo": null
+ },
+ "entityValidityDetails": {
+ "valid": true,
+ "invalidYaml": null
+ },
+ "governanceMetadata": null,
+ "isFavorite": true
+ },
+ {
+ "connector": {
+ "name": "idp_automation_gitlab_repo_token_delegate_with_api_accessfyRKtovEDP",
+ "identifier": "idp_automation_gitlab_repo_token_delegate_with_api_accessfyRKtovEDP",
+ "description": "",
+ "accountIdentifier": "vpCkHKsDSxK9_KYfjCTMKA",
+ "orgIdentifier": null,
+ "projectIdentifier": null,
+ "tags": {},
+ "type": "Gitlab",
+ "spec": {
+ "url": "https://gitlab.com/sathish1293/sathish",
+ "validationRepo": null,
+ "authentication": {
+ "type": "Http",
+ "spec": {
+ "type": "UsernameToken",
+ "spec": {
+ "username": "sathish1293",
+ "usernameRef": null,
+ "tokenRef": "account.idp_integrations_git_gitlab_repo_tokenN2i3hdz0AB"
+ }
+ }
+ },
+ "apiAccess": {
+ "type": "Token",
+ "spec": {
+ "tokenRef": "account.idp_integrations_git_gitlab_repo_tokenN2i3hdz0AB",
+ "apiUrl": ""
+ }
+ },
+ "delegateSelectors": [],
+ "executeOnDelegate": true,
+ "proxy": false,
+ "ignoreTestConnection": false,
+ "type": "Repo"
+ }
+ },
+ "createdAt": 1733229191871,
+ "lastModifiedAt": 1733229191867,
+ "status": {
+ "status": "FAILURE",
+ "errorSummary": "Error Encountered (Please ensure that the api access credentials are correct.)",
+ "errors": [
+ {
+ "reason": "Unexpected Error",
+ "message": "Please ensure that the api access credentials are correct.",
+ "code": 450
+ }
+ ],
+ "testedAt": 1733229196534,
+ "lastTestedAt": 0,
+ "lastConnectedAt": 1733229196534,
+ "lastAlertSent": null
+ },
+ "activityDetails": {
+ "lastActivityTime": 1733229191867
+ },
+ "harnessManaged": false,
+ "gitDetails": {
+ "objectId": null,
+ "branch": null,
+ "repoIdentifier": null,
+ "rootFolder": null,
+ "filePath": null,
+ "repoName": null,
+ "commitId": null,
+ "fileUrl": null,
+ "repoUrl": null,
+ "parentEntityConnectorRef": null,
+ "parentEntityRepoName": null,
+ "isHarnessCodeRepo": null
+ },
+ "entityValidityDetails": {
+ "valid": true,
+ "invalidYaml": null
+ },
+ "governanceMetadata": null,
+ "isFavorite": false
+ },
+ {
+ "connector": {
+ "name": "idp_automation_gitlab_account_token_manager_with_api_accessnyRvINsPm3",
+ "identifier": "idp_automation_gitlab_account_token_manager_with_api_accessnyRvINsPm3",
+ "description": "",
+ "accountIdentifier": "vpCkHKsDSxK9_KYfjCTMKA",
+ "orgIdentifier": null,
+ "projectIdentifier": null,
+ "tags": {},
+ "type": "Gitlab",
+ "spec": {
+ "url": "https://gitlab.com/sathish1293",
+ "validationRepo": "sathish",
+ "authentication": {
+ "type": "Http",
+ "spec": {
+ "type": "UsernameToken",
+ "spec": {
+ "username": "sathish1293",
+ "usernameRef": null,
+ "tokenRef": "account.idp_integrations_git_gitlab_account_tokendhosPoZS9T"
+ }
+ }
+ },
+ "apiAccess": {
+ "type": "Token",
+ "spec": {
+ "tokenRef": "account.idp_integrations_git_gitlab_account_tokendhosPoZS9T",
+ "apiUrl": ""
+ }
+ },
+ "delegateSelectors": [],
+ "executeOnDelegate": false,
+ "proxy": false,
+ "ignoreTestConnection": false,
+ "type": "Account"
+ }
+ },
+ "createdAt": 1733229189527,
+ "lastModifiedAt": 1733229189525,
+ "status": {
+ "status": "SUCCESS",
+ "errorSummary": null,
+ "errors": null,
+ "testedAt": 1733229190997,
+ "lastTestedAt": 0,
+ "lastConnectedAt": 1733229190997,
+ "lastAlertSent": null
+ },
+ "activityDetails": {
+ "lastActivityTime": 1733229189525
+ },
+ "harnessManaged": false,
+ "gitDetails": {
+ "objectId": null,
+ "branch": null,
+ "repoIdentifier": null,
+ "rootFolder": null,
+ "filePath": null,
+ "repoName": null,
+ "commitId": null,
+ "fileUrl": null,
+ "repoUrl": null,
+ "parentEntityConnectorRef": null,
+ "parentEntityRepoName": null,
+ "isHarnessCodeRepo": null
+ },
+ "entityValidityDetails": {
+ "valid": true,
+ "invalidYaml": null
+ },
+ "governanceMetadata": null,
+ "isFavorite": true
+ },
+ {
+ "connector": {
+ "name": "idp_automation_gitlab_account_token_delegate_with_api_access9piJ0v8Hu7",
+ "identifier": "idp_automation_gitlab_account_token_delegate_with_api_access9piJ0v8Hu7",
+ "description": "",
+ "accountIdentifier": "vpCkHKsDSxK9_KYfjCTMKA",
+ "orgIdentifier": null,
+ "projectIdentifier": null,
+ "tags": {},
+ "type": "Gitlab",
+ "spec": {
+ "url": "https://gitlab.com/sathish1293",
+ "validationRepo": "sathish",
+ "authentication": {
+ "type": "Http",
+ "spec": {
+ "type": "UsernameToken",
+ "spec": {
+ "username": "sathish1293",
+ "usernameRef": null,
+ "tokenRef": "account.idp_integrations_git_gitlab_account_tokensjKVKRWDEU"
+ }
+ }
+ },
+ "apiAccess": {
+ "type": "Token",
+ "spec": {
+ "tokenRef": "account.idp_integrations_git_gitlab_account_tokensjKVKRWDEU",
+ "apiUrl": ""
+ }
+ },
+ "delegateSelectors": [],
+ "executeOnDelegate": true,
+ "proxy": false,
+ "ignoreTestConnection": false,
+ "type": "Account"
+ }
+ },
+ "createdAt": 1733229183940,
+ "lastModifiedAt": 1745280000000,
+ "status": {
+ "status": "SUCCESS",
+ "errorSummary": null,
+ "errors": null,
+ "testedAt": 1733229187135,
+ "lastTestedAt": 0,
+ "lastConnectedAt": 1733229187135,
+ "lastAlertSent": null
+ },
+ "activityDetails": {
+ "lastActivityTime": 1733229183938
+ },
+ "harnessManaged": false,
+ "gitDetails": {
+ "objectId": null,
+ "branch": null,
+ "repoIdentifier": null,
+ "rootFolder": null,
+ "filePath": null,
+ "repoName": null,
+ "commitId": null,
+ "fileUrl": null,
+ "repoUrl": null,
+ "parentEntityConnectorRef": null,
+ "parentEntityRepoName": null,
+ "isHarnessCodeRepo": null
+ },
+ "entityValidityDetails": {
+ "valid": true,
+ "invalidYaml": null
+ },
+ "governanceMetadata": null,
+ "isFavorite": false
+ },
+ {
+ "connector": {
+ "name": "idp_automation_gitlab_account_token_delegate_with_api_accessNsHoen6Sia",
+ "identifier": "idp_automation_gitlab_account_token_delegate_with_api_accessNsHoen6Sia",
+ "description": "",
+ "accountIdentifier": "vpCkHKsDSxK9_KYfjCTMKA",
+ "orgIdentifier": null,
+ "projectIdentifier": null,
+ "tags": {},
+ "type": "Gitlab",
+ "spec": {
+ "url": "https://gitlab.com/sathish1293",
+ "validationRepo": "sathish",
+ "authentication": {
+ "type": "Http",
+ "spec": {
+ "type": "UsernameToken",
+ "spec": {
+ "username": "sathish1293",
+ "usernameRef": null,
+ "tokenRef": "account.idp_integrations_git_gitlab_account_tokenC0zTA80pjU"
+ }
+ }
+ },
+ "apiAccess": {
+ "type": "Token",
+ "spec": {
+ "tokenRef": "account.idp_integrations_git_gitlab_account_tokenC0zTA80pjU",
+ "apiUrl": ""
+ }
+ },
+ "delegateSelectors": [],
+ "executeOnDelegate": true,
+ "proxy": false,
+ "ignoreTestConnection": false,
+ "type": "Account"
+ }
+ },
+ "createdAt": 1733229176811,
+ "lastModifiedAt": 1744934400000,
+ "status": {
+ "status": "SUCCESS",
+ "errorSummary": null,
+ "errors": null,
+ "testedAt": 1733229180994,
+ "lastTestedAt": 0,
+ "lastConnectedAt": 1733229180994,
+ "lastAlertSent": null
+ },
+ "activityDetails": {
+ "lastActivityTime": 1733229176807
+ },
+ "harnessManaged": false,
+ "gitDetails": {
+ "objectId": null,
+ "branch": null,
+ "repoIdentifier": null,
+ "rootFolder": null,
+ "filePath": null,
+ "repoName": null,
+ "commitId": null,
+ "fileUrl": null,
+ "repoUrl": null,
+ "parentEntityConnectorRef": null,
+ "parentEntityRepoName": null,
+ "isHarnessCodeRepo": null
+ },
+ "entityValidityDetails": {
+ "valid": true,
+ "invalidYaml": null
+ },
+ "governanceMetadata": null,
+ "isFavorite": false
+ },
+ {
+ "connector": {
+ "name": "idp_automation_github_repo_token_manager_with_api_accesslI57BbIiO8",
+ "identifier": "idp_automation_github_repo_token_manager_with_api_accesslI57BbIiO8",
+ "description": "",
+ "accountIdentifier": "vpCkHKsDSxK9_KYfjCTMKA",
+ "orgIdentifier": null,
+ "projectIdentifier": null,
+ "tags": {},
+ "type": "Github",
+ "spec": {
+ "url": "https://github.com/sathish-soundarapandian/onboarding-test",
+ "validationRepo": null,
+ "authentication": {
+ "type": "Http",
+ "spec": {
+ "type": "UsernameToken",
+ "spec": {
+ "username": "sathish-soundarapandian",
+ "usernameRef": null,
+ "tokenRef": "account.idp_integrations_git_github_repo_tokenPe9FVjWpgt"
+ }
+ }
+ },
+ "apiAccess": {
+ "type": "Token",
+ "spec": {
+ "tokenRef": "account.idp_integrations_git_github_repo_tokenPe9FVjWpgt"
+ }
+ },
+ "delegateSelectors": [],
+ "executeOnDelegate": false,
+ "proxy": false,
+ "ignoreTestConnection": false,
+ "type": "Repo"
+ }
+ },
+ "createdAt": 1733229174390,
+ "lastModifiedAt": 1745193600000,
+ "status": {
+ "status": "SUCCESS",
+ "errorSummary": null,
+ "errors": null,
+ "testedAt": 1733229175369,
+ "lastTestedAt": 0,
+ "lastConnectedAt": 1733229175369,
+ "lastAlertSent": null
+ },
+ "activityDetails": {
+ "lastActivityTime": 1733229174387
+ },
+ "harnessManaged": false,
+ "gitDetails": {
+ "objectId": null,
+ "branch": null,
+ "repoIdentifier": null,
+ "rootFolder": null,
+ "filePath": null,
+ "repoName": null,
+ "commitId": null,
+ "fileUrl": null,
+ "repoUrl": null,
+ "parentEntityConnectorRef": null,
+ "parentEntityRepoName": null,
+ "isHarnessCodeRepo": null
+ },
+ "entityValidityDetails": {
+ "valid": true,
+ "invalidYaml": null
+ },
+ "governanceMetadata": null,
+ "isFavorite": true
+ },
+ {
+ "connector": {
+ "name": "idp_automation_github_repo_token_delegate_with_api_accessEpB5zc4UBb",
+ "identifier": "idp_automation_github_repo_token_delegate_with_api_accessEpB5zc4UBb",
+ "description": "",
+ "accountIdentifier": "vpCkHKsDSxK9_KYfjCTMKA",
+ "orgIdentifier": null,
+ "projectIdentifier": null,
+ "tags": {},
+ "type": "Github",
+ "spec": {
+ "url": "https://github.com/sathish-soundarapandian/onboarding-test",
+ "validationRepo": null,
+ "authentication": {
+ "type": "Http",
+ "spec": {
+ "type": "UsernameToken",
+ "spec": {
+ "username": "sathish-soundarapandian",
+ "usernameRef": null,
+ "tokenRef": "account.idp_integrations_git_github_repo_tokenUmdYZQwOww"
+ }
+ }
+ },
+ "apiAccess": {
+ "type": "Token",
+ "spec": {
+ "tokenRef": "account.idp_integrations_git_github_repo_tokenUmdYZQwOww"
+ }
+ },
+ "delegateSelectors": [],
+ "executeOnDelegate": true,
+ "proxy": false,
+ "ignoreTestConnection": false,
+ "type": "Repo"
+ }
+ },
+ "createdAt": 1733229168140,
+ "lastModifiedAt": 1733229168137,
+ "status": {
+ "status": "SUCCESS",
+ "errorSummary": null,
+ "errors": null,
+ "testedAt": 1733229172390,
+ "lastTestedAt": 0,
+ "lastConnectedAt": 1733229172390,
+ "lastAlertSent": null
+ },
+ "activityDetails": {
+ "lastActivityTime": 1733229168137
+ },
+ "harnessManaged": false,
+ "gitDetails": {
+ "objectId": null,
+ "branch": null,
+ "repoIdentifier": null,
+ "rootFolder": null,
+ "filePath": null,
+ "repoName": null,
+ "commitId": null,
+ "fileUrl": null,
+ "repoUrl": null,
+ "parentEntityConnectorRef": null,
+ "parentEntityRepoName": null,
+ "isHarnessCodeRepo": null
+ },
+ "entityValidityDetails": {
+ "valid": true,
+ "invalidYaml": null
+ },
+ "governanceMetadata": null,
+ "isFavorite": false
+ },
+ {
+ "connector": {
+ "name": "idp_automation_github_repo_token_delegate_with_api_accessgs6FHpUozM",
+ "identifier": "idp_automation_github_repo_token_delegate_with_api_accessgs6FHpUozM",
+ "description": "",
+ "accountIdentifier": "vpCkHKsDSxK9_KYfjCTMKA",
+ "orgIdentifier": null,
+ "projectIdentifier": null,
+ "tags": {},
+ "type": "Github",
+ "spec": {
+ "url": "https://github.com/sathish-soundarapandian/onboarding-test",
+ "validationRepo": null,
+ "authentication": {
+ "type": "Http",
+ "spec": {
+ "type": "UsernameToken",
+ "spec": {
+ "username": "sathish-soundarapandian",
+ "usernameRef": null,
+ "tokenRef": "account.idp_integrations_git_github_repo_tokenPImmNIqBEy"
+ }
+ }
+ },
+ "apiAccess": {
+ "type": "Token",
+ "spec": {
+ "tokenRef": "account.idp_integrations_git_github_repo_tokenPImmNIqBEy"
+ }
+ },
+ "delegateSelectors": [],
+ "executeOnDelegate": true,
+ "proxy": false,
+ "ignoreTestConnection": false,
+ "type": "Repo"
+ }
+ },
+ "createdAt": 1733229158922,
+ "lastModifiedAt": 1733229158917,
+ "status": {
+ "status": "SUCCESS",
+ "errorSummary": null,
+ "errors": null,
+ "testedAt": 1733229161468,
+ "lastTestedAt": 0,
+ "lastConnectedAt": 1733229161468,
+ "lastAlertSent": null
+ },
+ "activityDetails": {
+ "lastActivityTime": 1733229158917
+ },
+ "harnessManaged": false,
+ "gitDetails": {
+ "objectId": null,
+ "branch": null,
+ "repoIdentifier": null,
+ "rootFolder": null,
+ "filePath": null,
+ "repoName": null,
+ "commitId": null,
+ "fileUrl": null,
+ "repoUrl": null,
+ "parentEntityConnectorRef": null,
+ "parentEntityRepoName": null,
+ "isHarnessCodeRepo": null
+ },
+ "entityValidityDetails": {
+ "valid": true,
+ "invalidYaml": null
+ },
+ "governanceMetadata": null,
+ "isFavorite": true
+ },
+ {
+ "connector": {
+ "name": "idp_automation_github_repo_github_app_manager_with_api_accessCbEHVnGnKG",
+ "identifier": "idp_automation_github_repo_github_app_manager_with_api_accessCbEHVnGnKG",
+ "description": "",
+ "accountIdentifier": "vpCkHKsDSxK9_KYfjCTMKA",
+ "orgIdentifier": null,
+ "projectIdentifier": null,
+ "tags": {},
+ "type": "Github",
+ "spec": {
+ "url": "https://github.com/sathish-soundarapandian/onboarding-test",
+ "validationRepo": null,
+ "authentication": {
+ "type": "Http",
+ "spec": {
+ "type": "GithubApp",
+ "spec": {
+ "installationId": "36899459",
+ "applicationId": "307885",
+ "installationIdRef": null,
+ "applicationIdRef": null,
+ "privateKeyRef": "account.idp_integrations_git_github_repo_github_app_private_keyxcBsgQ6nkY"
+ }
+ }
+ },
+ "apiAccess": {
+ "type": "GithubApp",
+ "spec": {
+ "installationId": "36899459",
+ "applicationId": "307885",
+ "installationIdRef": null,
+ "applicationIdRef": null,
+ "privateKeyRef": "account.idp_integrations_git_github_repo_github_app_private_keyxcBsgQ6nkY"
+ }
+ },
+ "delegateSelectors": [],
+ "executeOnDelegate": false,
+ "proxy": false,
+ "ignoreTestConnection": false,
+ "type": "Repo"
+ }
+ },
+ "createdAt": 1733229155967,
+ "lastModifiedAt": 1733229155962,
+ "status": {
+ "status": "SUCCESS",
+ "errorSummary": null,
+ "errors": null,
+ "testedAt": 1733229156585,
+ "lastTestedAt": 0,
+ "lastConnectedAt": 1733229156585,
+ "lastAlertSent": null
+ },
+ "activityDetails": {
+ "lastActivityTime": 1733229155962
+ },
+ "harnessManaged": false,
+ "gitDetails": {
+ "objectId": null,
+ "branch": null,
+ "repoIdentifier": null,
+ "rootFolder": null,
+ "filePath": null,
+ "repoName": null,
+ "commitId": null,
+ "fileUrl": null,
+ "repoUrl": null,
+ "parentEntityConnectorRef": null,
+ "parentEntityRepoName": null,
+ "isHarnessCodeRepo": null
+ },
+ "entityValidityDetails": {
+ "valid": true,
+ "invalidYaml": null
+ },
+ "governanceMetadata": null,
+ "isFavorite": false
+ },
+ {
+ "connector": {
+ "name": "idp_automation_github_repo_github_app_delegate_with_api_accessnHXHYyYHSB",
+ "identifier": "idp_automation_github_repo_github_app_delegate_with_api_accessnHXHYyYHSB",
+ "description": "",
+ "accountIdentifier": "vpCkHKsDSxK9_KYfjCTMKA",
+ "orgIdentifier": null,
+ "projectIdentifier": null,
+ "tags": {},
+ "type": "Github",
+ "spec": {
+ "url": "https://github.com/sathish-soundarapandian/onboarding-test",
+ "validationRepo": null,
+ "authentication": {
+ "type": "Http",
+ "spec": {
+ "type": "GithubApp",
+ "spec": {
+ "installationId": "36899459",
+ "applicationId": "307885",
+ "installationIdRef": null,
+ "applicationIdRef": null,
+ "privateKeyRef": "account.idp_integrations_git_github_repo_github_app_private_key6l0fFUCFfi"
+ }
+ }
+ },
+ "apiAccess": {
+ "type": "GithubApp",
+ "spec": {
+ "installationId": "36899459",
+ "applicationId": "307885",
+ "installationIdRef": null,
+ "applicationIdRef": null,
+ "privateKeyRef": "account.idp_integrations_git_github_repo_github_app_private_key6l0fFUCFfi"
+ }
+ },
+ "delegateSelectors": [],
+ "executeOnDelegate": true,
+ "proxy": false,
+ "ignoreTestConnection": false,
+ "type": "Repo"
+ }
+ },
+ "createdAt": 1733229148812,
+ "lastModifiedAt": 1733229148807,
+ "status": {
+ "status": "SUCCESS",
+ "errorSummary": null,
+ "errors": null,
+ "testedAt": 1733229154306,
+ "lastTestedAt": 0,
+ "lastConnectedAt": 1733229154306,
+ "lastAlertSent": null
+ },
+ "activityDetails": {
+ "lastActivityTime": 1733229148807
+ },
+ "harnessManaged": false,
+ "gitDetails": {
+ "objectId": null,
+ "branch": null,
+ "repoIdentifier": null,
+ "rootFolder": null,
+ "filePath": null,
+ "repoName": null,
+ "commitId": null,
+ "fileUrl": null,
+ "repoUrl": null,
+ "parentEntityConnectorRef": null,
+ "parentEntityRepoName": null,
+ "isHarnessCodeRepo": null
+ },
+ "entityValidityDetails": {
+ "valid": true,
+ "invalidYaml": null
+ },
+ "governanceMetadata": null,
+ "isFavorite": false
+ }
+]
diff --git a/apps/design-system/src/subjects/views/data-table-demo.tsx b/apps/design-system/src/subjects/views/data-table-demo.tsx
new file mode 100644
index 0000000000..c126d9f096
--- /dev/null
+++ b/apps/design-system/src/subjects/views/data-table-demo.tsx
@@ -0,0 +1,190 @@
+import { useMemo, useState } from 'react'
+
+import type { ColumnDef, ExpandedState, OnChangeFn, Row, RowSelectionState, SortingState } from '@tanstack/react-table'
+
+import { DataTable, StatusBadge } from '@harnessio/ui/components'
+import { SandboxLayout } from '@harnessio/ui/views'
+
+type User = {
+ name: string
+ email: string
+ role: string
+ status: 'active' | 'inactive' | 'pending'
+ lastLogin: string
+}
+
+const users: User[] = [
+ {
+ name: 'John Doe',
+ email: 'john.doe@example.com',
+ role: 'Admin',
+ status: 'active',
+ lastLogin: '2025-06-01'
+ },
+ {
+ name: 'Jane Smith',
+ email: 'jane.smith@example.com',
+ role: 'Developer',
+ status: 'active',
+ lastLogin: '2025-06-02'
+ },
+ {
+ name: 'Bob Johnson',
+ email: 'bob.johnson@example.com',
+ role: 'Designer',
+ status: 'inactive',
+ lastLogin: '2025-05-28'
+ },
+ {
+ name: 'Alice Williams',
+ email: 'alice.williams@example.com',
+ role: 'Product Manager',
+ status: 'pending',
+ lastLogin: '2025-06-03'
+ },
+ {
+ name: 'Charlie Brown',
+ email: 'charlie.brown@example.com',
+ role: 'Developer',
+ status: 'active',
+ lastLogin: '2025-06-01'
+ }
+]
+
+export const DataTableDemo: React.FC = () => {
+ // Row selection state
+ const [rowSelection, setRowSelection] = useState({})
+
+ // Row expansion state
+ const [expanded, setExpanded] = useState({})
+
+ // Sorting state for server-side sorting
+ const [tableSorting, setTableSorting] = useState([])
+
+ // Log selection changes
+ const handleRowSelectionChange: OnChangeFn = updaterOrValue => {
+ const newSelection = typeof updaterOrValue === 'function' ? updaterOrValue(rowSelection) : updaterOrValue
+ setRowSelection(newSelection)
+ }
+
+ // Handle expanded state changes
+ const handleExpandedChange: OnChangeFn = updaterOrValue => {
+ const newExpanded = typeof updaterOrValue === 'function' ? updaterOrValue(expanded) : updaterOrValue
+ setExpanded(newExpanded)
+ }
+
+ // Render expanded row content
+ const renderSubComponent = ({ row }: { row: Row }) => {
+ const user = row.original
+ return (
+
+
This is a placeholder for expanded content for {user.name}
+
+ )
+ }
+
+ // Define columns for the data table
+ const columns: ColumnDef[] = useMemo(
+ () => [
+ {
+ accessorKey: 'name',
+ header: 'Name',
+ enableSorting: true,
+ cell: info => {String(info.getValue())}
+ },
+ {
+ accessorKey: 'email',
+ header: 'Email',
+ enableSorting: true
+ },
+ {
+ accessorKey: 'role',
+ header: 'Role',
+ enableSorting: false
+ },
+ {
+ accessorKey: 'status',
+ header: 'Status',
+ enableSorting: true,
+ cell: info => {
+ const status = String(info.getValue())
+ return (
+
+ {status}
+
+ )
+ }
+ },
+ {
+ accessorKey: 'lastLogin',
+ header: 'Last Login',
+ enableSorting: true
+ }
+ ],
+ []
+ )
+
+ // This function would typically make an API call to fetch sorted data
+ // In a real app, you would fetch data from the server with the new sorting parameters
+ // For this demo, we'll just sort the data client-side to simulate server-side sorting
+ const handleSortingChange: OnChangeFn = updaterOrValue => {
+ const newSorting = typeof updaterOrValue === 'function' ? updaterOrValue(tableSorting) : updaterOrValue
+
+ setTableSorting(newSorting)
+ }
+
+ // Simulate server-side sorting and pagination
+ const sortedData = [...users].sort((a, b) => {
+ if (tableSorting.length === 0) return 0
+
+ const sort = tableSorting[0]
+ const key = sort.id as keyof User
+
+ if (a[key] < b[key]) return sort.desc ? 1 : -1
+ if (a[key] > b[key]) return sort.desc ? -1 : 1
+ return 0
+ })
+
+ // Handler for row clicks
+ const handleRowClick = (data: User, index: number) => {
+ console.log('Row clicked:', { data, index })
+ }
+
+ return (
+
+
+
+ columns={columns}
+ data={sortedData}
+ getRowId={row => row.email}
+ size="compact"
+ currentSorting={tableSorting}
+ onSortingChange={handleSortingChange}
+ pagination={{
+ currentPage: 1,
+ pageSize: 3,
+ totalItems: users.length,
+ goToPage: () => {}
+ }}
+ onRowClick={handleRowClick}
+ enableRowSelection
+ currentRowSelection={rowSelection}
+ onRowSelectionChange={handleRowSelectionChange}
+ enableExpanding
+ currentExpanded={expanded}
+ onExpandedChange={handleExpandedChange}
+ renderSubComponent={renderSubComponent}
+ getRowCanExpand={(row: Row) => row.original.status === 'active'}
+ getRowCanSelect={(row: Row) => row.original.status === 'active'}
+ />
+
+
+ )
+}
+
+export default DataTableDemo
diff --git a/apps/design-system/src/subjects/views/delegates/delegate-connectivity.tsx b/apps/design-system/src/subjects/views/delegates/delegate-connectivity.tsx
new file mode 100644
index 0000000000..52e02ed8da
--- /dev/null
+++ b/apps/design-system/src/subjects/views/delegates/delegate-connectivity.tsx
@@ -0,0 +1,28 @@
+import { defaultTo } from 'lodash-es'
+
+import { DelegateConnectivityList, SandboxLayout } from '@harnessio/ui/views'
+
+import mockDelegatesList from './mock-delegates-list.json'
+import { isDelegateSelected } from './utils'
+
+const DelegateConnectivityWrapper = (): JSX.Element => (
+
+
+ ({
+ groupId: delegate.groupId,
+ groupName: delegate.groupName,
+ lastHeartBeat: delegate.lastHeartBeat,
+ activelyConnected: delegate.activelyConnected,
+ groupCustomSelectors: delegate.groupCustomSelectors || [],
+ groupImplicitSelectors: [...Object.keys(defaultTo(delegate.groupImplicitSelectors, {}))]
+ }))}
+ isLoading={false}
+ selectedTags={[]}
+ isDelegateSelected={isDelegateSelected}
+ />
+
+
+)
+
+export { DelegateConnectivityWrapper }
diff --git a/apps/design-system/src/subjects/views/delegates/delegate-selector.tsx b/apps/design-system/src/subjects/views/delegates/delegate-selector.tsx
new file mode 100644
index 0000000000..b3ffb94d17
--- /dev/null
+++ b/apps/design-system/src/subjects/views/delegates/delegate-selector.tsx
@@ -0,0 +1,137 @@
+import { useState } from 'react'
+
+import { defaultTo } from 'lodash-es'
+
+import { Drawer, Link } from '@harnessio/ui/components'
+import {
+ DelegateSelectionTypes,
+ DelegateSelectorForm,
+ DelegateSelectorFormFields,
+ DelegateSelectorInput
+} from '@harnessio/ui/views'
+
+import mockDelegatesList from './mock-delegates-list.json'
+import { getMatchedDelegatesCount, isDelegateSelected } from './utils'
+
+const delegatesData = mockDelegatesList.map(delegate => ({
+ groupId: delegate.groupId,
+ groupName: delegate.groupName,
+ lastHeartBeat: delegate.lastHeartBeat,
+ activelyConnected: delegate.activelyConnected,
+ groupCustomSelectors: delegate.groupCustomSelectors || [],
+ groupImplicitSelectors: [...Object.keys(defaultTo(delegate.groupImplicitSelectors, {}))]
+}))
+
+const mockTagsList = [
+ 'sanity-windows',
+ 'eightfivetwoold',
+ 'qa-automation',
+ 'sanity',
+ 'self-hosted-vpc-delegate',
+ 'local',
+ '_testDocker',
+ 'myrunner',
+ 'macos-arm64',
+ 'west1-delegate-qa',
+ 'linux-amd64',
+ 'eightfivetwo',
+ 'automation-eks-delegate'
+]
+
+const renderSelectedValue = (type: DelegateSelectionTypes | null, tags: string[]) =>
+ type === DelegateSelectionTypes.TAGS ? tags.join(', ') : type === DelegateSelectionTypes.ANY ? 'any delegate' : null
+
+/* ---------- DRAWER COMPONENT -------------- */
+interface DrawerProps {
+ open: boolean
+ setOpen: (open: boolean) => void
+ preSelectedTags: string[]
+ onSubmit: (data: DelegateSelectorFormFields) => void
+ disableAnyDelegate?: boolean
+}
+
+const DelegateSelectorDrawer = ({ open, setOpen, preSelectedTags, onSubmit, disableAnyDelegate }: DrawerProps) => (
+
+
+
+ Delegate selector
+
+
+ setOpen(false)}
+ isDelegateSelected={isDelegateSelected}
+ getMatchedDelegatesCount={getMatchedDelegatesCount}
+ preSelectedTags={preSelectedTags}
+ disableAnyDelegate={disableAnyDelegate}
+ isDrawer
+ />
+
+
+)
+
+/* ---------- MAIN COMPONENT -------------------------- */
+export const DelegateSelector = () => {
+ /* ---- FIRST (ANY allowed) ---- */
+ const [openA, setOpenA] = useState(false)
+ const [typeA, setTypeA] = useState(null)
+ const [tagsA, setTagsA] = useState([])
+
+ /* ---- SECOND (ANY disabled) --- */
+ const [openB, setOpenB] = useState(false)
+ const [typeB, setTypeB] = useState(null)
+ const [tagsB, setTagsB] = useState([])
+
+ const handleSubmitA = ({ type, tags }: DelegateSelectorFormFields) => {
+ setTypeA(type === DelegateSelectionTypes.ANY ? DelegateSelectionTypes.ANY : DelegateSelectionTypes.TAGS)
+ setTagsA(type === DelegateSelectionTypes.TAGS ? tags.map(t => t.id) : [])
+ setOpenA(false)
+ }
+
+ const handleSubmitB = ({ tags }: DelegateSelectorFormFields) => {
+ setTypeB(DelegateSelectionTypes.TAGS)
+ setTagsB(tags.map(t => t.id))
+ setOpenB(false)
+ }
+
+ return (
+
+
select a delegate}
+ value={renderSelectedValue(typeA, tagsA)}
+ label="Delegate selector"
+ onClick={() => setOpenA(true)}
+ onEdit={() => setOpenA(true)}
+ onClear={() => setTagsA([])}
+ renderValue={tag => tag}
+ className="mb-8 max-w-xs"
+ />
+
+
+
+
+ select a delegate (any disabled)}
+ value={renderSelectedValue(typeB, tagsB)}
+ label="Delegate selector"
+ onClick={() => setOpenB(true)}
+ onEdit={() => setOpenB(true)}
+ onClear={() => setTagsB([])}
+ renderValue={tag => tag}
+ className="mb-8 max-w-xs"
+ />
+
+
+
+
+ )
+}
diff --git a/apps/design-system/src/subjects/views/delegates/mock-delegates-list.json b/apps/design-system/src/subjects/views/delegates/mock-delegates-list.json
new file mode 100644
index 0000000000..828d119a2f
--- /dev/null
+++ b/apps/design-system/src/subjects/views/delegates/mock-delegates-list.json
@@ -0,0 +1,267 @@
+[
+ {
+ "groupId": "randomId1",
+ "delegateGroupIdentifier": "_testDocker",
+ "delegateType": "DOCKER",
+ "groupName": "_testDocker",
+ "groupImplicitSelectors": { "viaksdcoker": "GROUP_NAME" },
+ "groupCustomSelectors": ["linux-amd64", "testing", "local"],
+ "lastHeartBeat": 0,
+ "connectivityStatus": "disconnected",
+ "activelyConnected": false,
+ "grpcActive": false,
+ "delegateInstanceDetails": [],
+ "tokenActive": true,
+ "autoUpgrade": "OFF",
+ "delegateGroupExpirationTime": 0,
+ "upgraderLastUpdated": 0,
+ "immutable": false
+ },
+ {
+ "groupId": "randomId2",
+ "delegateGroupIdentifier": "_eightfivetwoold",
+ "delegateType": "KUBERNETES",
+ "groupName": "eightfivetwoold",
+ "groupImplicitSelectors": { "eightfivetwoold": "GROUP_NAME" },
+ "lastHeartBeat": 1744646981427,
+ "connectivityStatus": "connected",
+ "activelyConnected": true,
+ "grpcActive": false,
+ "delegateInstanceDetails": [
+ {
+ "uuid": "QKXGf323QTK9urDK0T_Prw",
+ "lastHeartbeat": 1744646981427,
+ "activelyConnected": true,
+ "hostName": "eightfivetwoold-7f4b7bbd47-hgxv4",
+ "tokenActive": true,
+ "version": "25.04.85601",
+ "delegateExpirationTime": 1758557385064,
+ "polllingModeEnabled": false
+ }
+ ],
+ "tokenActive": true,
+ "autoUpgrade": "ON",
+ "delegateGroupExpirationTime": 1758557385064,
+ "upgraderLastUpdated": 1744646404670,
+ "immutable": true,
+ "groupVersion": "25.04.85601"
+ },
+ {
+ "groupId": "randomId3",
+ "delegateGroupIdentifier": "_sanity",
+ "delegateType": "KUBERNETES",
+ "groupName": "sanity",
+ "groupImplicitSelectors": { "sanity": "GROUP_NAME" },
+ "lastHeartBeat": 1744646989404,
+ "connectivityStatus": "connected",
+ "activelyConnected": true,
+ "grpcActive": false,
+ "delegateInstanceDetails": [
+ {
+ "uuid": "qNs5n8h4Tn-xgHpWPQyJPA",
+ "lastHeartbeat": 1744646989404,
+ "activelyConnected": true,
+ "hostName": "sanity-8b579d6fc-gr9fm",
+ "tokenActive": true,
+ "version": "25.04.85601",
+ "delegateExpirationTime": 1758557385217,
+ "polllingModeEnabled": false
+ }
+ ],
+ "tokenActive": true,
+ "autoUpgrade": "OFF",
+ "delegateGroupExpirationTime": 1758557385217,
+ "upgraderLastUpdated": 0,
+ "immutable": true,
+ "groupVersion": "25.04.85601"
+ },
+ {
+ "groupId": "Ou-randomId4",
+ "delegateGroupIdentifier": "_west1_delegate_qa",
+ "delegateType": "KUBERNETES",
+ "groupName": "west1-delegate-qa",
+ "groupImplicitSelectors": { "west1-delegate-qa": "GROUP_NAME" },
+ "lastHeartBeat": 0,
+ "connectivityStatus": "disconnected",
+ "activelyConnected": false,
+ "grpcActive": false,
+ "delegateInstanceDetails": [],
+ "tokenActive": true,
+ "autoUpgrade": "ON",
+ "delegateGroupExpirationTime": 0,
+ "upgraderLastUpdated": 0,
+ "immutable": false
+ },
+ {
+ "groupId": "randomId5",
+ "delegateGroupIdentifier": "_qa_automation",
+ "delegateType": "KUBERNETES",
+ "groupName": "qa-automation",
+ "groupImplicitSelectors": { "qa-automation": "GROUP_NAME" },
+ "lastHeartBeat": 1744646977479,
+ "connectivityStatus": "connected",
+ "activelyConnected": true,
+ "grpcActive": false,
+ "delegateInstanceDetails": [
+ {
+ "uuid": "EZbHXutlRK29uK7RlrHM-w",
+ "lastHeartbeat": 1744646977479,
+ "activelyConnected": true,
+ "hostName": "qa-automation-b74cb6776-d8gt8",
+ "tokenActive": true,
+ "version": "25.03.85504",
+ "delegateExpirationTime": 1755533385358,
+ "polllingModeEnabled": false
+ }
+ ],
+ "tokenActive": true,
+ "autoUpgrade": "ON",
+ "delegateGroupExpirationTime": 1755533385359,
+ "upgraderLastUpdated": 1744646403144,
+ "immutable": true,
+ "groupVersion": "25.03.85504"
+ },
+ {
+ "groupId": "randomId6-g",
+ "delegateGroupIdentifier": "_sanity_windows",
+ "delegateType": "KUBERNETES",
+ "groupName": "sanity-windows",
+ "groupImplicitSelectors": { "sanity-windows": "GROUP_NAME" },
+ "lastHeartBeat": 1744646974708,
+ "connectivityStatus": "connected",
+ "activelyConnected": true,
+ "grpcActive": false,
+ "delegateInstanceDetails": [
+ {
+ "uuid": "h7NHZN9HRkC5ri1H7zGfVA",
+ "lastHeartbeat": 1744646943982,
+ "activelyConnected": true,
+ "hostName": "sanity-windows-687c7cd8c5-tpmqd",
+ "tokenActive": true,
+ "version": "25.04.85601",
+ "delegateExpirationTime": 1758557385512,
+ "polllingModeEnabled": false
+ },
+ {
+ "uuid": "_YKkwZbGRS6a4j3w4Sse5A",
+ "lastHeartbeat": 1744646974708,
+ "activelyConnected": true,
+ "hostName": "sanity-windows-687c7cd8c5-fb2v7",
+ "tokenActive": true,
+ "version": "25.04.85601",
+ "delegateExpirationTime": 1758557385512,
+ "polllingModeEnabled": false
+ }
+ ],
+ "tokenActive": true,
+ "autoUpgrade": "ON",
+ "delegateGroupExpirationTime": 1758557385512,
+ "upgraderLastUpdated": 1744646403993,
+ "immutable": true,
+ "groupVersion": "25.04.85601"
+ },
+ {
+ "groupId": "randomId7",
+ "delegateGroupIdentifier": "_myRunner",
+ "delegateType": "DOCKER",
+ "groupName": "myRunner",
+ "groupImplicitSelectors": { "myrunner-ivan": "GROUP_NAME" },
+ "groupCustomSelectors": ["macos-arm64", "local", "fast-pace"],
+ "lastHeartBeat": 1744639645019,
+ "connectivityStatus": "disconnected",
+ "activelyConnected": false,
+ "grpcActive": false,
+ "delegateInstanceDetails": [
+ {
+ "uuid": "JmnNGefCTSe8ntmuy4IyTA",
+ "lastHeartbeat": 1744639645019,
+ "activelyConnected": false,
+ "hostName": "runner-Shobhit-Singh",
+ "tokenActive": true,
+ "version": "v0.1",
+ "delegateExpirationTime": 1759162185514,
+ "polllingModeEnabled": true
+ }
+ ],
+ "tokenActive": true,
+ "autoUpgrade": "OFF",
+ "delegateGroupExpirationTime": 0,
+ "upgraderLastUpdated": 0,
+ "immutable": false
+ },
+ {
+ "groupId": "randomId8",
+ "delegateGroupIdentifier": "_eightfivetwo",
+ "delegateType": "KUBERNETES",
+ "groupName": "eightfivetwo",
+ "groupImplicitSelectors": { "eightfivetwo": "GROUP_NAME" },
+ "lastHeartBeat": 1744646949409,
+ "connectivityStatus": "connected",
+ "activelyConnected": true,
+ "grpcActive": false,
+ "delegateInstanceDetails": [
+ {
+ "uuid": "S0BdENJaRA2AwUSpW2f67w",
+ "lastHeartbeat": 1744646949409,
+ "activelyConnected": true,
+ "hostName": "eightfivetwo-78bb67b9cb-sbs77",
+ "tokenActive": true,
+ "version": "25.04.85601",
+ "delegateExpirationTime": 1758557385665,
+ "polllingModeEnabled": false
+ }
+ ],
+ "tokenActive": true,
+ "autoUpgrade": "ON",
+ "delegateGroupExpirationTime": 1758557385665,
+ "upgraderLastUpdated": 1744646403840,
+ "immutable": true,
+ "groupVersion": "25.04.85601"
+ },
+ {
+ "groupId": "randomId9",
+ "delegateGroupIdentifier": "_self_hosted_vpc_delegate",
+ "delegateType": "DOCKER",
+ "groupName": "self-hosted-vpc-delegate",
+ "groupImplicitSelectors": { "self-hosted-vpc-delegate": "GROUP_NAME" },
+ "lastHeartBeat": 0,
+ "connectivityStatus": "disconnected",
+ "activelyConnected": false,
+ "grpcActive": false,
+ "delegateInstanceDetails": [],
+ "tokenActive": true,
+ "autoUpgrade": "OFF",
+ "delegateGroupExpirationTime": 0,
+ "upgraderLastUpdated": 0,
+ "immutable": false
+ },
+ {
+ "groupId": "randomId10",
+ "delegateGroupIdentifier": "_automation_eks_delegate",
+ "delegateType": "KUBERNETES",
+ "groupName": "automation-eks-delegate",
+ "groupImplicitSelectors": { "automation-eks-delegate": "GROUP_NAME" },
+ "lastHeartBeat": 1744646945706,
+ "connectivityStatus": "connected",
+ "activelyConnected": true,
+ "grpcActive": false,
+ "delegateInstanceDetails": [
+ {
+ "uuid": "EO0XslI2TDSEmG0IBAFTNA",
+ "lastHeartbeat": 1744646945706,
+ "activelyConnected": true,
+ "hostName": "automation-eks-delegate-8665557bdf-wxt26",
+ "tokenActive": true,
+ "version": "25.03.85405",
+ "delegateExpirationTime": 1755533385868,
+ "polllingModeEnabled": false
+ }
+ ],
+ "tokenActive": true,
+ "autoUpgrade": "OFF",
+ "delegateGroupExpirationTime": 1755533385868,
+ "upgraderLastUpdated": 0,
+ "immutable": true,
+ "groupVersion": "25.03.85405"
+ }
+]
diff --git a/apps/design-system/src/subjects/views/delegates/utils.ts b/apps/design-system/src/subjects/views/delegates/utils.ts
new file mode 100644
index 0000000000..c3f1cec36f
--- /dev/null
+++ b/apps/design-system/src/subjects/views/delegates/utils.ts
@@ -0,0 +1,24 @@
+import { DelegateItem } from '@harnessio/ui/views'
+
+export const isDelegateSelected = (delegateSelectors: string[], tags: string[] = []) => {
+ if (!tags?.length) {
+ return false
+ }
+ return tags?.some(tag => delegateSelectors.includes(tag))
+}
+
+export const getMatchedDelegatesCount = (delegates: DelegateItem[] = [], tags: string[] = []): number => {
+ if (!delegates.length || !tags.length) {
+ return 0
+ }
+
+ const tagSet = new Set(tags)
+
+ return delegates.reduce((count, delegate) => {
+ const implicit = delegate.groupImplicitSelectors ?? []
+ const custom = delegate.groupCustomSelectors ?? []
+ const delegateTags = [...implicit, ...custom]
+ const matches = delegateTags.some(tag => tagSet.has(tag))
+ return matches ? count + 1 : count
+ }, 0)
+}
diff --git a/apps/design-system/src/subjects/views/draggable-cards-demo.tsx b/apps/design-system/src/subjects/views/draggable-cards-demo.tsx
new file mode 100644
index 0000000000..8a57f5926b
--- /dev/null
+++ b/apps/design-system/src/subjects/views/draggable-cards-demo.tsx
@@ -0,0 +1,93 @@
+import { useState } from 'react'
+
+import {
+ Accordion,
+ CardData,
+ Checkbox,
+ DraggableCardList,
+ Drawer,
+ IconV2,
+ MoreActionsTooltip,
+ Select
+} from '@harnessio/ui/components'
+
+export const DraggableCardsDemo = () => {
+ // Sample card data
+ const [cards, setCards] = useState([
+ {
+ id: '1',
+ title: (
+
+
+
+ First Card
+
+ {}
+ },
+ {
+ title: 'Action 2',
+ onClick: () => {}
+ }
+ ]}
+ iconName="more-horizontal"
+ />
+
+ ),
+ description: (
+
+
+ )
+ },
+ {
+ id: '2',
+ title: 'Second Card',
+ description: 'This is the second card. Try reordering it.'
+ },
+ {
+ id: '3',
+ title: 'Third Card',
+ description: 'This is the third card. Drag and drop to reorder.'
+ }
+ ])
+
+ return (
+
+ Open
+
+
+ Environment
+
+
+
+
+
+
+ )
+}
+
+export default DraggableCardsDemo
diff --git a/apps/design-system/src/subjects/views/execution-list/execution-list.store.ts b/apps/design-system/src/subjects/views/execution-list/execution-list.store.ts
index e3f78b8363..8772bf9144 100644
--- a/apps/design-system/src/subjects/views/execution-list/execution-list.store.ts
+++ b/apps/design-system/src/subjects/views/execution-list/execution-list.store.ts
@@ -39,6 +39,7 @@ export const useExecutionListStore = (): IExecutionListStore => ({
page: 1,
executions,
setPage: noop,
- totalPages: 10,
+ totalItems: 10,
+ pageSize: 10,
setExecutionsData: noop
})
diff --git a/apps/design-system/src/subjects/views/execution-list/execution-list.tsx b/apps/design-system/src/subjects/views/execution-list/execution-list.tsx
index afa5df6dd6..476c52ae60 100644
--- a/apps/design-system/src/subjects/views/execution-list/execution-list.tsx
+++ b/apps/design-system/src/subjects/views/execution-list/execution-list.tsx
@@ -1,7 +1,7 @@
import { FC } from 'react'
import { Link } from 'react-router-dom'
-import { noop, useTranslationStore } from '@utils/viewUtils'
+import { noop } from '@utils/viewUtils'
import { ExecutionListPage, RepoSummaryViewProps, TLinkComponent } from '@harnessio/ui/views'
@@ -13,7 +13,6 @@ const ExecutionListWrapper: FC> = () => {
return (
{
return (
-
+
{
return (
-
{
createdTime={createdTimeElapsed}
pipelineName="build scan push test - k8s - Clone 2"
/>
-
-
+
+
+
{
}}
/>
-
+
{}} onDownload={() => {}} onEdit={() => {}} />
diff --git a/apps/design-system/src/subjects/views/execution/mocks/mock-data.ts b/apps/design-system/src/subjects/views/execution/mocks/mock-data.ts
index 0e6733990b..720b38587c 100644
--- a/apps/design-system/src/subjects/views/execution/mocks/mock-data.ts
+++ b/apps/design-system/src/subjects/views/execution/mocks/mock-data.ts
@@ -1,4 +1,4 @@
-import { ExecutionState, ExecutionTreeProps, LivelogLine } from '@harnessio/ui/views'
+import { ExecutionState, ExecutionTreeProps, LivelogLine, LivelogLineType } from '@harnessio/ui/views'
export const logs: LivelogLine[] = [
{ out: 'Starting dependency installation...', pos: 1, time: 1700000001, duration: 2 },
@@ -46,7 +46,13 @@ export const logsBank: { [key: string]: LivelogLine[] } = {
{ out: 'Initializing repository fetch...', pos: 1, time: 1700000001, duration: 1 },
{ out: 'Cloning repository from GitHub...', pos: 2, time: 1700000002, duration: 2 },
{ out: "Checking out branch 'main'...", pos: 3, time: 1700000004, duration: 1 },
- { out: 'Repository fetch completed successfully.', pos: 4, time: 1700000005, duration: 1 },
+ {
+ out: '[INFO] Repository fetch completed successfully.',
+ pos: 4,
+ time: 1700000005,
+ duration: 1,
+ type: LivelogLineType.INFO
+ },
...Array.from({ length: 46 }, (_, i) => ({
out: `Fetch Repository log ${i + 5}`,
pos: i + 5,
@@ -59,7 +65,7 @@ export const logsBank: { [key: string]: LivelogLine[] } = {
{ out: 'Fetching latest commit SHA...', pos: 2, time: 1700000052, duration: 1 },
{ out: "Checking out to commit 'abc123'...", pos: 3, time: 1700000053, duration: 2 },
{ out: 'Verifying code integrity...', pos: 4, time: 1700000055, duration: 1 },
- { out: 'Checkout process completed.', pos: 5, time: 1700000056, duration: 1 },
+ { out: '[INFO] Checkout process completed.', pos: 5, time: 1700000056, duration: 1, type: LivelogLineType.INFO },
...Array.from({ length: 46 }, (_, i) => ({
out: `Checkout Code log ${i + 5}`,
pos: i + 5,
@@ -72,26 +78,46 @@ export const logsBank: { [key: string]: LivelogLine[] } = {
{ out: 'Downloading required packages...', pos: 2, time: 1700000102, duration: 2 },
{ out: 'Resolving dependency tree...', pos: 3, time: 1700000104, duration: 1 },
{ out: 'Compiling dependencies...', pos: 4, time: 1700000105, duration: 3 },
- { out: 'Dependency installation complete.', pos: 5, time: 1700000108, duration: 1 },
+ {
+ out: '[INFO] Dependency installation complete.',
+ pos: 5,
+ time: 1700000108,
+ duration: 1,
+ type: LivelogLineType.INFO
+ },
...Array.from({ length: 46 }, (_, i) => ({
out: `Install dependencies log ${i + 5}`,
pos: i + 5,
time: 1700000109 + i,
- duration: 1
+ duration: 1,
+ type: Math.random() > 0.5 ? undefined : LivelogLineType.WARNING
}))
],
'run-tests': [
{ out: 'Initializing test suite...', pos: 1, time: 1700000151, duration: 1 },
{ out: 'Running unit tests...', pos: 2, time: 1700000152, duration: 1 },
- { out: '✔ Authentication tests passed', pos: 3, time: 1700000153, duration: 1 },
- { out: '✔ API response tests passed', pos: 4, time: 1700000154, duration: 1 },
- { out: '✔ Database connection tests passed', pos: 5, time: 1700000155, duration: 1 },
- { out: 'Test suite completed successfully.', pos: 6, time: 1700000156, duration: 1 },
+ { out: '[INFO] Authentication tests passed', pos: 3, time: 1700000153, duration: 1, type: LivelogLineType.INFO },
+ { out: '[INFO] API response tests passed', pos: 4, time: 1700000154, duration: 1, type: LivelogLineType.INFO },
+ {
+ out: '[INFO] Database connection tests passed',
+ pos: 5,
+ time: 1700000155,
+ duration: 1,
+ type: LivelogLineType.INFO
+ },
+ {
+ out: '[INFO] Test suite completed successfully.',
+ pos: 6,
+ time: 1700000156,
+ duration: 1,
+ type: LivelogLineType.INFO
+ },
...Array.from({ length: 46 }, (_, i) => ({
out: `Run tests log ${i + 5}`,
pos: i + 5,
time: 1700000157 + i,
- duration: 1
+ duration: 1,
+ type: Math.random() > 0.5 ? undefined : LivelogLineType.ERROR
}))
],
'build-golang-project': [
@@ -100,7 +126,7 @@ export const logsBank: { [key: string]: LivelogLine[] } = {
{ out: 'Compiling utils.go...', pos: 3, time: 1700000205, duration: 2 },
{ out: 'Linking dependencies...', pos: 4, time: 1700000207, duration: 2 },
{ out: 'Generating executable binary...', pos: 5, time: 1700000209, duration: 2 },
- { out: 'Build completed successfully.', pos: 6, time: 1700000211, duration: 1 },
+ { out: '[INFO] Build completed successfully.', pos: 6, time: 1700000211, duration: 1, type: LivelogLineType.INFO },
...Array.from({ length: 46 }, (_, i) => ({
out: `Build Golang project log ${i + 5}`,
pos: i + 5,
@@ -114,7 +140,7 @@ export const logsBank: { [key: string]: LivelogLine[] } = {
{ out: 'Compiling utils.go...', pos: 3, time: 1700000205, duration: 2 },
{ out: 'Linking dependencies...', pos: 4, time: 1700000207, duration: 2 },
{ out: 'Running tests...', pos: 5, time: 1700000209, duration: 2 },
- { out: 'Generating test reports...', pos: 6, time: 1700000211, duration: 1 },
+ { out: '[INFO] Generating test reports...', pos: 6, time: 1700000211, duration: 1, type: LivelogLineType.INFO },
...Array.from({ length: 46 }, (_, i) => ({
out: `Build Golang project log ${i + 5}`,
pos: i + 5,
@@ -125,10 +151,22 @@ export const logsBank: { [key: string]: LivelogLine[] } = {
'docker-template-stage': [
{ out: 'Starting Golang test execution...', pos: 1, time: 1700000251, duration: 1 },
{ out: 'Running unit tests...', pos: 2, time: 1700000252, duration: 1 },
- { out: '✔ Database tests passed', pos: 3, time: 1700000253, duration: 1 },
- { out: '✔ API tests passed', pos: 4, time: 1700000254, duration: 1 },
- { out: '✔ Performance benchmarks completed', pos: 5, time: 1700000255, duration: 1 },
- { out: 'Test suite finished with no errors.', pos: 6, time: 1700000256, duration: 1 },
+ { out: '[INFO] Database tests passed', pos: 3, time: 1700000253, duration: 1, type: LivelogLineType.INFO },
+ { out: '[INFO] API tests passed', pos: 4, time: 1700000254, duration: 1, type: LivelogLineType.INFO },
+ {
+ out: '[INFO] Performance benchmarks completed',
+ pos: 5,
+ time: 1700000255,
+ duration: 1,
+ type: LivelogLineType.INFO
+ },
+ {
+ out: '[INFO] Test suite finished with no errors.',
+ pos: 6,
+ time: 1700000256,
+ duration: 1,
+ type: LivelogLineType.INFO
+ },
...Array.from({ length: 46 }, (_, i) => ({
out: `Run Golang tests log ${i + 5}`,
pos: i + 5,
@@ -141,7 +179,7 @@ export const logsBank: { [key: string]: LivelogLine[] } = {
{ out: 'Authenticating Docker credentials...', pos: 2, time: 1700000302, duration: 2 },
{ out: 'Pulling image harness/petstore:latest...', pos: 3, time: 1700000304, duration: 3 },
{ out: 'Verifying image integrity...', pos: 4, time: 1700000307, duration: 1 },
- { out: 'Docker image pull complete.', pos: 5, time: 1700000308, duration: 1 },
+ { out: '[INFO] Docker image pull complete.', pos: 5, time: 1700000308, duration: 1, type: LivelogLineType.INFO },
...Array.from({ length: 46 }, (_, i) => ({
out: `Pull Docker image log ${i + 5}`,
pos: i + 5,
@@ -154,12 +192,19 @@ export const logsBank: { [key: string]: LivelogLine[] } = {
{ out: 'Authenticating Slack bot token...', pos: 2, time: 1700000352, duration: 2 },
{ out: 'Sending message to #general...', pos: 3, time: 1700000354, duration: 1 },
{ out: 'Message successfully posted.', pos: 4, time: 1700000355, duration: 1 },
- { out: 'Slack notification process completed.', pos: 5, time: 1700000356, duration: 1 },
+ {
+ out: '[INFO] Slack notification process completed.',
+ pos: 5,
+ time: 1700000356,
+ duration: 1,
+ type: LivelogLineType.INFO
+ },
...Array.from({ length: 46 }, (_, i) => ({
out: `Send Slack notification log ${i + 5}`,
pos: i + 5,
time: 1700000357 + i,
- duration: 1
+ duration: 1,
+ type: Math.random() > 0.5 ? undefined : LivelogLineType.ERROR
}))
]
}
@@ -253,14 +298,14 @@ export const elements: ExecutionTreeProps['elements'] = [
{
id: 'slack-notification-stage',
name: 'Slack Notification Stage',
- status: ExecutionState.PENDING,
+ status: ExecutionState.FAILURE,
duration: '--:--',
isSelectable: true,
children: [
{
id: 'send-slack-notification',
name: 'Send Slack notification',
- status: ExecutionState.PENDING,
+ status: ExecutionState.FAILURE,
duration: '--:--',
isSelectable: true
}
diff --git a/apps/design-system/src/subjects/views/execution/pipeline-execution-graph.tsx b/apps/design-system/src/subjects/views/execution/pipeline-execution-graph.tsx
index b0476d9ac9..6a476cca88 100644
--- a/apps/design-system/src/subjects/views/execution/pipeline-execution-graph.tsx
+++ b/apps/design-system/src/subjects/views/execution/pipeline-execution-graph.tsx
@@ -10,7 +10,7 @@ import {
SerialNodeContent,
SerialNodeInternalType
} from '@harnessio/pipeline-graph'
-import { Button, Drawer, Icon, PipelineNodes } from '@harnessio/ui/components'
+import { Button, ButtonLayout, Drawer, IconV2, PipelineNodes } from '@harnessio/ui/components'
// *****************************************************
// 1. Import CSS
@@ -76,10 +76,10 @@ export function StepNodeComponent({
}
return (
-
+
{stepNode}
-
-
+
+
-
+
({ logs })}
@@ -99,7 +99,7 @@ export function StepNodeComponent({
onDownload={() => {}}
onEdit={() => {}}
/>
-
+
)
@@ -119,7 +119,7 @@ export function ApprovalStepNodeComponent({
const approvalNode = (
{name}
@@ -131,23 +131,31 @@ export function ApprovalStepNodeComponent({
}
return (
-
+
{approvalNode}
-
-
-
- Approval
- Approve/Reject step execution
-
-
-
-
-
-
+
+
+ Approval
+ Approve/Reject step execution
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
@@ -265,7 +273,7 @@ const data: AnyContainerNodeType[] = [
type: ContentNodeTypes.step,
data: {
name: 'Step 1',
- icon: ,
+ icon: ,
logs: logs
} satisfies StepNodeDataType,
config: {
@@ -277,7 +285,7 @@ const data: AnyContainerNodeType[] = [
type: ContentNodeTypes.approval,
data: {
name: 'Approval 1',
- icon:
+ icon:
} satisfies StepNodeDataType,
config: {
width: 120,
@@ -298,7 +306,7 @@ const data: AnyContainerNodeType[] = [
type: ContentNodeTypes.step,
data: {
name: 'Step 2',
- icon:
+ icon:
} satisfies StepNodeDataType,
config: {
width: 160,
@@ -309,7 +317,7 @@ const data: AnyContainerNodeType[] = [
type: ContentNodeTypes.step,
data: {
name: 'Step 3',
- icon:
+ icon:
} satisfies StepNodeDataType,
config: {
width: 160,
@@ -332,7 +340,7 @@ const data: AnyContainerNodeType[] = [
type: ContentNodeTypes.step,
data: {
name: 'Step 4',
- icon:
+ icon:
} satisfies StepNodeDataType,
config: {
width: 160,
@@ -343,7 +351,7 @@ const data: AnyContainerNodeType[] = [
type: ContentNodeTypes.step,
data: {
name: 'Step 4',
- icon:
+ icon:
} satisfies StepNodeDataType,
config: {
width: 160,
diff --git a/apps/design-system/src/subjects/views/labels/labels-form.tsx b/apps/design-system/src/subjects/views/labels/labels-form.tsx
index 9571b0c889..3c9b5bca3e 100644
--- a/apps/design-system/src/subjects/views/labels/labels-form.tsx
+++ b/apps/design-system/src/subjects/views/labels/labels-form.tsx
@@ -1,5 +1,4 @@
import { LabelsListStore } from '@subjects/stores/labels-store.tsx'
-import { useTranslationStore } from '@utils/viewUtils.ts'
import { LabelFormPage } from '@harnessio/ui/views'
@@ -7,7 +6,6 @@ export const LabelsForm = () => {
return (
{}}
onFormCancel={() => {}}
diff --git a/apps/design-system/src/subjects/views/labels/project-labels-list.tsx b/apps/design-system/src/subjects/views/labels/project-labels-list.tsx
index 8ced6145bd..8518c9d18c 100644
--- a/apps/design-system/src/subjects/views/labels/project-labels-list.tsx
+++ b/apps/design-system/src/subjects/views/labels/project-labels-list.tsx
@@ -1,7 +1,7 @@
import { useState } from 'react'
import { LabelsListStore } from '@subjects/stores/labels-store'
-import { noop, useTranslationStore } from '@utils/viewUtils'
+import { noop } from '@utils/viewUtils'
import { DeleteAlertDialog } from '@harnessio/ui/components'
import { LabelsListPage } from '@harnessio/ui/views'
@@ -13,7 +13,6 @@ export const ProjectLabelsList = () => {
<>
{
type="label"
deleteFn={noop}
isLoading={false}
- useTranslationStore={useTranslationStore}
/>
>
)
diff --git a/apps/design-system/src/subjects/views/labels/repo-labels-list.tsx b/apps/design-system/src/subjects/views/labels/repo-labels-list.tsx
index 7704416937..dda43bd6c5 100644
--- a/apps/design-system/src/subjects/views/labels/repo-labels-list.tsx
+++ b/apps/design-system/src/subjects/views/labels/repo-labels-list.tsx
@@ -1,7 +1,7 @@
import { useState } from 'react'
import { LabelsListStore } from '@subjects/stores/labels-store'
-import { noop, useTranslationStore } from '@utils/viewUtils'
+import { noop } from '@utils/viewUtils'
import { DeleteAlertDialog } from '@harnessio/ui/components'
import { LabelsListPage } from '@harnessio/ui/views'
@@ -13,7 +13,6 @@ export const RepoLabelsList = () => {
<>
{
type="label"
deleteFn={noop}
isLoading={false}
- useTranslationStore={useTranslationStore}
/>
>
)
diff --git a/apps/design-system/src/subjects/views/landing-page/landing-page-view.tsx b/apps/design-system/src/subjects/views/landing-page/landing-page-view.tsx
index 7e482a7e73..6d03fae59e 100644
--- a/apps/design-system/src/subjects/views/landing-page/landing-page-view.tsx
+++ b/apps/design-system/src/subjects/views/landing-page/landing-page-view.tsx
@@ -1,14 +1,5 @@
-import { useTranslationStore } from '@utils/viewUtils'
-
import { LandingPageView } from '@harnessio/ui/views'
export const LandingPagePreview = () => {
- return (
- ''}
- toCreateProject={() => ''}
- />
- )
+ return ''} toCreateProject={() => ''} />
}
diff --git a/apps/design-system/src/subjects/views/multi-select-demo.tsx b/apps/design-system/src/subjects/views/multi-select-demo.tsx
new file mode 100644
index 0000000000..e2a9d10cb9
--- /dev/null
+++ b/apps/design-system/src/subjects/views/multi-select-demo.tsx
@@ -0,0 +1,33 @@
+import { useState } from 'react'
+
+import { MultiSelect, MultiSelectOption } from '@harnessio/ui/components'
+
+const OPTIONS: MultiSelectOption[] = [
+ { key: 'nextjs', id: 'nextjs' },
+ { key: 'Vite', id: 'Vite' },
+ { key: 'Nuxt', id: 'Nuxt' },
+ { key: 'Vue', id: 'Vue' },
+ { key: 'Remix', id: 'Remix' },
+ { key: 'Svelte', id: 'Svelte' },
+ { key: 'Angular', id: 'Angular' },
+ { key: 'Ember', id: 'Ember' },
+ { key: 'React', id: 'React' },
+ { key: 'Gatsby', id: 'Gatsby' },
+ { key: 'Astro', id: 'Astro' }
+]
+
+export const MultipleSelectorWithDisabledOption = () => {
+ const [value, setValue] = useState([OPTIONS[0]])
+ return (
+ <>
+ setValue(options)}
+ value={value}
+ options={OPTIONS}
+ placeholder="Select frameworks you like..."
+ // isLoading
+ // disabled
+ />
+ >
+ )
+}
diff --git a/apps/design-system/src/subjects/views/pipeline-graph/pipeline-graph-minimal.tsx b/apps/design-system/src/subjects/views/pipeline-graph/pipeline-graph-minimal.tsx
index 4ca27318b7..89edf296ed 100644
--- a/apps/design-system/src/subjects/views/pipeline-graph/pipeline-graph-minimal.tsx
+++ b/apps/design-system/src/subjects/views/pipeline-graph/pipeline-graph-minimal.tsx
@@ -10,7 +10,7 @@ import {
SerialNodeContent,
SerialNodeInternalType
} from '@harnessio/pipeline-graph'
-import { Icon, Text } from '@harnessio/ui/components'
+import { IconV2, Text } from '@harnessio/ui/components'
// *****************************************************
// 1. Import CSS
@@ -45,9 +45,9 @@ export function StepNodeComponent({ node }: { node: LeafNodeInternalType
+
@@ -71,9 +71,9 @@ export function SerialGroupNodeComponent({
return (
<>
-
+
-
@@ -100,9 +100,9 @@ export function ParallelGroupNodeComponent({
return (
<>
-
+
-
@@ -143,7 +143,7 @@ const data: AnyContainerNodeType[] = [
type: ContentNodeTypes.step,
data: {
name: 'Step 1',
- icon:
+ icon:
} satisfies StepNodeDataType,
config: {
width: 160,
@@ -164,7 +164,7 @@ const data: AnyContainerNodeType[] = [
type: ContentNodeTypes.step,
data: {
name: 'Step 2',
- icon:
+ icon:
} satisfies StepNodeDataType,
config: {
width: 160,
@@ -175,7 +175,7 @@ const data: AnyContainerNodeType[] = [
type: ContentNodeTypes.step,
data: {
name: 'Step 3',
- icon:
+ icon:
} satisfies StepNodeDataType,
config: {
width: 160,
@@ -198,7 +198,7 @@ const data: AnyContainerNodeType[] = [
type: ContentNodeTypes.step,
data: {
name: 'Step 4',
- icon:
+ icon:
} satisfies StepNodeDataType,
config: {
width: 160,
@@ -209,7 +209,7 @@ const data: AnyContainerNodeType[] = [
type: ContentNodeTypes.step,
data: {
name: 'Step 4',
- icon:
+ icon:
} satisfies StepNodeDataType,
config: {
width: 160,
@@ -224,9 +224,9 @@ const PipelineGraphMinimalWrapper = () => {
// const [view, setView] = useState
('visual')
return (
-
- {/* */}
-
+ {/*
+
+
*/}
)
diff --git a/apps/design-system/src/subjects/views/pipeline-graph/pipeline-graph.tsx b/apps/design-system/src/subjects/views/pipeline-graph/pipeline-graph.tsx
index 54bfaba6f1..a4ddf56934 100644
--- a/apps/design-system/src/subjects/views/pipeline-graph/pipeline-graph.tsx
+++ b/apps/design-system/src/subjects/views/pipeline-graph/pipeline-graph.tsx
@@ -10,7 +10,7 @@ import {
SerialNodeContent,
SerialNodeInternalType
} from '@harnessio/pipeline-graph'
-import { Icon, PipelineNodes } from '@harnessio/ui/components'
+import { IconV2, PipelineNodes } from '@harnessio/ui/components'
// import { PipelineStudioFooter } from '@harnessio/ui/views'
@@ -70,7 +70,7 @@ export function ApprovalStepNodeComponent({ node }: { node: LeafNodeInternalType
return (
{name}
@@ -189,7 +189,7 @@ const data: AnyContainerNodeType[] = [
type: ContentNodeTypes.step,
data: {
name: 'Step 1',
- icon:
+ icon:
} satisfies StepNodeDataType,
config: {
width: 160,
@@ -200,7 +200,7 @@ const data: AnyContainerNodeType[] = [
type: ContentNodeTypes.approval,
data: {
name: 'Approval 1',
- icon:
+ icon:
} satisfies StepNodeDataType,
config: {
width: 120,
@@ -221,7 +221,7 @@ const data: AnyContainerNodeType[] = [
type: ContentNodeTypes.step,
data: {
name: 'Step 2',
- icon:
+ icon:
} satisfies StepNodeDataType,
config: {
width: 160,
@@ -232,7 +232,7 @@ const data: AnyContainerNodeType[] = [
type: ContentNodeTypes.step,
data: {
name: 'Step 3',
- icon:
+ icon:
} satisfies StepNodeDataType,
config: {
width: 160,
@@ -255,7 +255,7 @@ const data: AnyContainerNodeType[] = [
type: ContentNodeTypes.step,
data: {
name: 'Step 4',
- icon:
+ icon:
} satisfies StepNodeDataType,
config: {
width: 160,
@@ -266,7 +266,7 @@ const data: AnyContainerNodeType[] = [
type: ContentNodeTypes.step,
data: {
name: 'Step 4',
- icon:
+ icon:
} satisfies StepNodeDataType,
config: {
width: 160,
diff --git a/apps/design-system/src/subjects/views/pipeline-list/pipeline-list.store.ts b/apps/design-system/src/subjects/views/pipeline-list/pipeline-list.store.ts
index 7d36d283b9..7dcf0a68cd 100644
--- a/apps/design-system/src/subjects/views/pipeline-list/pipeline-list.store.ts
+++ b/apps/design-system/src/subjects/views/pipeline-list/pipeline-list.store.ts
@@ -60,5 +60,6 @@ export const usePipelineListStore = (): IPipelineListStore => ({
pipelines,
setPage: noop,
setPipelinesData: noop,
- totalPages: 10
+ totalItems: 10,
+ pageSize: 10
})
diff --git a/apps/design-system/src/subjects/views/pipeline-list/pipeline-list.tsx b/apps/design-system/src/subjects/views/pipeline-list/pipeline-list.tsx
index b5033eb6dd..d7098bdbc6 100644
--- a/apps/design-system/src/subjects/views/pipeline-list/pipeline-list.tsx
+++ b/apps/design-system/src/subjects/views/pipeline-list/pipeline-list.tsx
@@ -1,7 +1,7 @@
import { FC, useState } from 'react'
import { Link } from 'react-router-dom'
-import { noop, useTranslationStore } from '@utils/viewUtils'
+import { noop } from '@utils/viewUtils'
import { CreatePipelineDialog, PipelineListPage, RepoSummaryViewProps, TLinkComponent } from '@harnessio/ui/views'
@@ -15,7 +15,6 @@ const PipelineListWrapper: FC
> = () => {
<>
{
openSshKeyDialog={() => setIsKeysDialogOpen(true)}
openAlertDeleteDialog={() => setIsDeleteDialogOpen(true)}
error={null}
- useTranslationStore={useTranslationStore}
isLoadingTokenList={false}
isLoadingKeysList={false}
/>
@@ -34,7 +33,6 @@ export const ProfileSettingsKeysView = () => {
handleCreateToken={noop}
error={null}
isLoading={false}
- useTranslationStore={useTranslationStore}
useProfileSettingsStore={mockProfileSettingsStore}
/>
{
onClose={() => setIsKeysDialogOpen(false)}
handleCreateSshKey={noop}
error={null}
- useTranslationStore={useTranslationStore}
/>
{
deleteFn={noop}
error={null}
isLoading={false}
- useTranslationStore={useTranslationStore}
/>
>
)
diff --git a/apps/design-system/src/subjects/views/profile-settings/index.tsx b/apps/design-system/src/subjects/views/profile-settings/index.tsx
index 4c276b1cd2..16fbc4bba9 100644
--- a/apps/design-system/src/subjects/views/profile-settings/index.tsx
+++ b/apps/design-system/src/subjects/views/profile-settings/index.tsx
@@ -1,6 +1,6 @@
import { useEffect, useState } from 'react'
-import { noop, useTranslationStore } from '@utils/viewUtils'
+import { noop } from '@utils/viewUtils'
import { SettingsAccountGeneralPage } from '@harnessio/ui/views'
@@ -16,7 +16,6 @@ export const ProfileSettingsView = () => {
return (
+ return (
+
+ )
}
- return
+ return
}
diff --git a/apps/design-system/src/subjects/views/project-settings/project-settings.tsx b/apps/design-system/src/subjects/views/project-settings/project-settings.tsx
index ef64ec458f..79ec3d974d 100644
--- a/apps/design-system/src/subjects/views/project-settings/project-settings.tsx
+++ b/apps/design-system/src/subjects/views/project-settings/project-settings.tsx
@@ -1,5 +1,3 @@
-import { useTranslationStore } from '@utils/viewUtils'
-
import { ProjectSettingsGeneralPage } from '@harnessio/ui/views'
export const ProjectSettingsView = () => {
@@ -10,7 +8,6 @@ export const ProjectSettingsView = () => {
isUpdateSuccess={false}
updateError={null}
setOpenDeleteDialog={() => {}}
- useTranslationStore={useTranslationStore}
/>
)
}
diff --git a/apps/design-system/src/subjects/views/pull-request-compare/pull-request-compare.tsx b/apps/design-system/src/subjects/views/pull-request-compare/pull-request-compare.tsx
index 360484f5ca..1862fa6a08 100644
--- a/apps/design-system/src/subjects/views/pull-request-compare/pull-request-compare.tsx
+++ b/apps/design-system/src/subjects/views/pull-request-compare/pull-request-compare.tsx
@@ -1,6 +1,6 @@
import { FC, useCallback } from 'react'
-import { noop, useTranslationStore } from '@utils/viewUtils'
+import { noop } from '@utils/viewUtils'
import { BranchSelectorV2, PullRequestComparePage, PullRequestComparePageProps } from '@harnessio/ui/views'
@@ -17,6 +17,7 @@ const PullRequestCompareWrapper: FC> = prop
return (
> = prop
title: 'bot.txt',
lang: 'txt',
addedLines: 1,
- removedLines: 0
+ deletedLines: 0,
+ isDeleted: false,
+ filePath: 'bot.txt',
+ diffData: {
+ fileId: 'some-id',
+ containerId: 'some-container-id',
+ contentId: 'some-content-id',
+ isCombined: false,
+ addedLines: 1,
+ deletedLines: 0,
+ isDeleted: false,
+ filePath: 'bot.txt',
+ isGitDiff: false,
+ language: 'txt',
+ blocks: [],
+ oldName: 'bot.txt',
+ newName: 'bot.txt'
+ }
}
]}
+ onGetFullDiff={async (path?: string) => {
+ return path ?? ''
+ }}
diffStats={{
additions: 0,
commits: 1,
@@ -49,10 +70,7 @@ const PullRequestCompareWrapper: FC> = prop
useRepoCommitsStore={useRepoCommitsListStore}
searchCommitQuery={null}
setSearchCommitQuery={noop}
- useTranslationStore={useTranslationStore}
isLoading={false}
- searchReviewersQuery=""
- setSearchReviewersQuery={noop}
jumpToDiff=""
setJumpToDiff={noop}
editLabelsProps={{ to: '' }}
@@ -67,10 +85,10 @@ const PullRequestCompareWrapper: FC> = prop
onSelectBranch={noop}
isBranchOnly={false}
dynamicWidth={false}
- useTranslationStore={useTranslationStore}
setSearchQuery={noop}
/>
}
+ setSearchLabelQuery={noop}
{...props}
/>
)
diff --git a/apps/design-system/src/subjects/views/pull-request-conversation/pull-request-changes.tsx b/apps/design-system/src/subjects/views/pull-request-conversation/pull-request-changes.tsx
index f2ce36edf3..c8b0c0a2dd 100644
--- a/apps/design-system/src/subjects/views/pull-request-conversation/pull-request-changes.tsx
+++ b/apps/design-system/src/subjects/views/pull-request-conversation/pull-request-changes.tsx
@@ -1,6 +1,6 @@
import { FC, PropsWithChildren, useCallback } from 'react'
-import { noop, useTranslationStore } from '@utils/viewUtils'
+import { noop } from '@utils/viewUtils'
import { CommitSuggestionsDialog } from '@harnessio/ui/components'
import { PullRequestChangesPage, TypesCommit, TypesPullReqActivity } from '@harnessio/ui/views'
@@ -53,9 +53,9 @@ const PullRequestChanges: FC = ({ state }) => {
isSubmitting={false}
/>
[]
)
- return (
-
- )
+ return
}
export default PullRequestCommits
diff --git a/apps/design-system/src/subjects/views/pull-request-conversation/pull-request-conversation.tsx b/apps/design-system/src/subjects/views/pull-request-conversation/pull-request-conversation.tsx
index 4f2474216c..b846057b55 100644
--- a/apps/design-system/src/subjects/views/pull-request-conversation/pull-request-conversation.tsx
+++ b/apps/design-system/src/subjects/views/pull-request-conversation/pull-request-conversation.tsx
@@ -1,7 +1,7 @@
-import { FC, PropsWithChildren } from 'react'
+import { FC, PropsWithChildren, useState } from 'react'
import { usePrFilters } from '@subjects/views/pull-request-conversation/hooks/use-pr-filters'
-import { noop, useTranslationStore } from '@utils/viewUtils'
+import { noop } from '@utils/viewUtils'
import { CommitSuggestionsDialog } from '@harnessio/ui/components'
import {
@@ -61,14 +61,17 @@ const PullRequestConversation: FC = ({ state }) =>
const comment = ''
+ const codeOwnersData = {
+ codeOwners,
+ codeOwnerPendingEntries
+ }
+
const processReviewDecision = (): EnumPullReqReviewDecision | PullReqReviewDecision.outdated => {
// Example implementation
return 'approved'
}
const activities = state === 'complex-1' ? mockActivities : undefined
- const searchReviewers = ''
-
const labelsList: ILabelType[] = state === 'complex-1' ? mockLabelList : []
const PRLabels = state === 'complex-1' ? mockPrLabels : { label_data: [] as LabelAssignmentType[] }
const searchLabel = ''
@@ -77,6 +80,9 @@ const PullRequestConversation: FC = ({ state }) =>
const filtersData = usePrFilters()
+ const [mergeTitle, setMergeTitle] = useState('Fix: Update user authentication flow')
+ const [mergeMessage, setMergeMessage] = useState('')
+
return (
<>
= ({ state }) =>
= ({ state }) =>
// TODO: add dry merge check into pr context
approvedEvaluations,
changeReqEvaluations,
- codeOwners,
+ codeOwnersData,
latestApprovalArr,
changeReqReviewer,
- codeOwnerPendingEntries,
actions: mockPullRequestActions,
checkboxBypass: false,
setCheckboxBypass: noop,
onRestoreBranch: noop,
onDeleteBranch: noop,
+ onRevertPR: noop,
showDeleteBranchButton,
showRestoreBranchButton,
headerMsg: errorMsg,
@@ -125,7 +131,12 @@ const PullRequestConversation: FC = ({ state }) =>
onCommitSuggestions: noop,
toPRCheck: _ => '',
spaceId: '',
- repoId: ''
+ repoId: '',
+ pullReqCommits: undefined,
+ mergeTitle,
+ mergeMessage,
+ setMergeTitle,
+ setMergeMessage
}}
overviewProps={{
toCommitDetails: _ => '',
@@ -142,6 +153,7 @@ const PullRequestConversation: FC = ({ state }) =>
uid: currentUserData?.uid
},
onCopyClick: noop,
+
toggleConversationStatus: noop,
onCommitSuggestion: noop,
addSuggestionToBatch: noop,
@@ -159,7 +171,6 @@ const PullRequestConversation: FC = ({ state }) =>
}}
sideBarProps={{
addReviewers: noop,
- usersList: undefined,
currentUserId: currentUserData?.uid,
pullRequestMetadata: { source_sha: pullReqMetadata?.source_sha || '' },
processReviewDecision,
@@ -168,8 +179,6 @@ const PullRequestConversation: FC = ({ state }) =>
addReviewerError: '',
removeReviewerError: '',
reviewers,
- searchQuery: searchReviewers,
- setSearchQuery: noop,
labelsList,
PRLabels: PRLabels?.label_data,
searchLabelQuery: searchLabel,
diff --git a/apps/design-system/src/subjects/views/pull-request-conversation/pull-request-panelData.ts b/apps/design-system/src/subjects/views/pull-request-conversation/pull-request-panelData.ts
index 19a26845a3..6ee855f9e7 100644
--- a/apps/design-system/src/subjects/views/pull-request-conversation/pull-request-panelData.ts
+++ b/apps/design-system/src/subjects/views/pull-request-conversation/pull-request-panelData.ts
@@ -67,7 +67,7 @@ export const changesInfoData = {
export const pendingChangesInfoData = {
title: 'Approvals pending',
statusMessage: 'Changes are pending approval from required reviewers',
- statusColor: 'text-warning',
+ statusColor: 'text-cn-foreground-warning',
statusIcon: 'pending',
isNotRequired: false
}
@@ -121,13 +121,13 @@ export const pullReqChecksDecisionSucceeded = {
}
]
},
- color: 'text-success',
- background: 'text-success',
+ color: 'text-cn-foreground-success',
+ background: 'text-cn-foreground-success',
message: '1/1 check succeeded.',
checkInfo: {
title: 'All checks have succeeded',
content: '1 succeeded',
- color: 'text-tertiary-background',
+ color: 'text-cn-foreground-3',
status: 'success'
},
summaryText: '1 succeeded'
diff --git a/apps/design-system/src/subjects/views/pull-request-list/pull-request-list-store.ts b/apps/design-system/src/subjects/views/pull-request-list/pull-request-list-store.ts
index 3748879b72..e74578daac 100644
--- a/apps/design-system/src/subjects/views/pull-request-list/pull-request-list-store.ts
+++ b/apps/design-system/src/subjects/views/pull-request-list/pull-request-list-store.ts
@@ -31,9 +31,11 @@ export const pullRequestListStore: PullRequestListStore = {
]
}
],
- totalPages: 1,
+ totalItems: 10,
+ pageSize: 10,
page: 1,
openPullReqs: 1,
closedPullReqs: 0,
- setPage: noop
+ setPage: noop,
+ setLabelsQuery: noop
}
diff --git a/apps/design-system/src/subjects/views/pull-request-list/pull-request-list.tsx b/apps/design-system/src/subjects/views/pull-request-list/pull-request-list.tsx
index c02f7b5e54..119926b781 100644
--- a/apps/design-system/src/subjects/views/pull-request-list/pull-request-list.tsx
+++ b/apps/design-system/src/subjects/views/pull-request-list/pull-request-list.tsx
@@ -1,9 +1,10 @@
import { FC, useCallback } from 'react'
-import { noop, useTranslationStore } from '@utils/viewUtils'
+import { noop } from '@utils/viewUtils'
import { PullRequestListPage, PullRequestPageProps } from '@harnessio/ui/views'
+import { LabelsListStore } from './../../stores/labels-store'
import { pullRequestListStore } from './pull-request-list-store'
const PullRequestListWrapper: FC> = props => {
@@ -17,9 +18,12 @@ const PullRequestListWrapper: FC> = props => {
return (
)
diff --git a/apps/design-system/src/subjects/views/repo-branches/index.tsx b/apps/design-system/src/subjects/views/repo-branches/index.tsx
index 4763884eb0..ea6448e4f8 100644
--- a/apps/design-system/src/subjects/views/repo-branches/index.tsx
+++ b/apps/design-system/src/subjects/views/repo-branches/index.tsx
@@ -1,6 +1,6 @@
import { useCallback, useState } from 'react'
-import { noop, useTranslationStore } from '@utils/viewUtils'
+import { noop } from '@utils/viewUtils'
import { IBranchSelectorStore, RepoBranchListView } from '@harnessio/ui/views'
@@ -14,9 +14,8 @@ export function RepoBranchesView() {
{}}
useRepoBranchesStore={useRepoBranchesStore}
- useTranslationStore={useTranslationStore}
isCreateBranchDialogOpen={isCreateBranchDialogOpen}
setCreateBranchDialogOpen={setCreateBranchDialogOpen}
searchQuery={''}
@@ -26,7 +25,6 @@ export function RepoBranchesView() {
toBranchRules={() => ''}
toPullRequestCompare={() => ''}
onDeleteBranch={noop}
- searchBranches={[]}
setCreateBranchSearchQuery={noop}
/>
)
diff --git a/apps/design-system/src/subjects/views/repo-commits/index.tsx b/apps/design-system/src/subjects/views/repo-commits/index.tsx
index a3a3d9fa7f..b06d4d5a74 100644
--- a/apps/design-system/src/subjects/views/repo-commits/index.tsx
+++ b/apps/design-system/src/subjects/views/repo-commits/index.tsx
@@ -1,4 +1,4 @@
-import { noop, useTranslationStore } from '@utils/viewUtils'
+import { noop } from '@utils/viewUtils'
import { BranchSelectorV2, RepoCommitsView as RepoCommitsUiView } from '@harnessio/ui/views'
@@ -13,7 +13,6 @@ export const RepoCommitsView = () => {
setPage={noop}
xNextPage={2}
xPrevPage={NaN}
- useTranslationStore={useTranslationStore}
renderProp={() => (
{
onSelectBranch={noop}
isBranchOnly={false}
dynamicWidth={false}
- useTranslationStore={useTranslationStore}
setSearchQuery={noop}
/>
)}
diff --git a/apps/design-system/src/subjects/views/repo-commits/repo-commits-store.ts b/apps/design-system/src/subjects/views/repo-commits/repo-commits-store.ts
index 2d7fe1cc9e..2cefc9076a 100644
--- a/apps/design-system/src/subjects/views/repo-commits/repo-commits-store.ts
+++ b/apps/design-system/src/subjects/views/repo-commits/repo-commits-store.ts
@@ -1941,7 +1941,7 @@ export const repoCommitsStore: RepoCommitsStore = {
changes: 47
},
{
- path: 'packages/ui/src/styles.css',
+ path: 'packages/ui/src/styles/styles.css',
status: 'MODIFIED',
insertions: 35,
deletions: 0,
@@ -2336,7 +2336,7 @@ export const repoCommitsStore: RepoCommitsStore = {
changes: 66
},
{
- path: 'packages/ui/src/styles.css',
+ path: 'packages/ui/src/styles/styles.css',
status: 'MODIFIED',
insertions: 24,
deletions: 0,
diff --git a/apps/design-system/src/subjects/views/repo-create-rule.tsx b/apps/design-system/src/subjects/views/repo-create-rule.tsx
index 82042d4e1e..b3bfc37016 100644
--- a/apps/design-system/src/subjects/views/repo-create-rule.tsx
+++ b/apps/design-system/src/subjects/views/repo-create-rule.tsx
@@ -1,7 +1,6 @@
import { useCallback, useEffect, useState } from 'react'
import { useRepoRulesStore } from '@subjects/views/repo-general-settings/use-repo-rules-store'
-import { useTranslationStore } from '@utils/viewUtils'
import { SkeletonForm } from '@harnessio/ui/components'
import { RepoBranchSettingsRulesPage } from '@harnessio/ui/views'
@@ -20,7 +19,8 @@ export const RepoCreateRule = () => {
const useBranchRulesStore = useCallback(
() => ({
rules: [],
- dispatch: () => {}
+ dispatch: () => {},
+ resetRules: () => {}
}),
[]
)
@@ -51,7 +51,6 @@ export const RepoCreateRule = () => {
handleSelectChangeForRule={() => {}}
handleInputChange={() => {}}
handleInitialRules={() => {}}
- useTranslationStore={useTranslationStore}
setPrincipalsSearchQuery={setPrincipalsSearchQuery}
principalsSearchQuery={principalsSearchQuery}
/>
diff --git a/apps/design-system/src/subjects/views/repo-create/index.tsx b/apps/design-system/src/subjects/views/repo-create/index.tsx
index 926f796ad9..0ccfc0017d 100644
--- a/apps/design-system/src/subjects/views/repo-create/index.tsx
+++ b/apps/design-system/src/subjects/views/repo-create/index.tsx
@@ -1,4 +1,4 @@
-import { noop, useTranslationStore } from '@utils/viewUtils'
+import { noop } from '@utils/viewUtils'
import { RepoCreatePage } from '@harnessio/ui/views'
@@ -15,7 +15,6 @@ export const CreateRepoView = () => {
isSuccess={false}
gitIgnoreOptions={gitIgnoreOptions}
licenseOptions={licenseOptions}
- useTranslationStore={useTranslationStore}
/>
)
}
diff --git a/apps/design-system/src/subjects/views/repo-empty/repo-empty-view.tsx b/apps/design-system/src/subjects/views/repo-empty/repo-empty-view.tsx
index 9ae0ab0092..6226e837df 100644
--- a/apps/design-system/src/subjects/views/repo-empty/repo-empty-view.tsx
+++ b/apps/design-system/src/subjects/views/repo-empty/repo-empty-view.tsx
@@ -1,7 +1,7 @@
import { FC, useMemo } from 'react'
import repoSummaryProps from '@subjects/views/repo-summary/repo-summary-props.json'
-import { noop, useTranslationStore } from '@utils/viewUtils'
+import { noop } from '@utils/viewUtils'
import { BranchSelectorV2, RepoSummaryView, RepoSummaryViewProps } from '@harnessio/ui/views'
@@ -18,7 +18,6 @@ export const RepoEmpty: FC> = props => {
saveDescription={noop}
handleCreateToken={noop}
navigateToFile={noop}
- useTranslationStore={useTranslationStore}
gitRef=""
updateRepoError=""
isEditDialogOpen={false}
@@ -36,7 +35,6 @@ export const RepoEmpty: FC> = props => {
onSelectBranch={noop}
isBranchOnly={false}
dynamicWidth={false}
- useTranslationStore={useTranslationStore}
setSearchQuery={noop}
/>
}
diff --git a/apps/design-system/src/subjects/views/repo-files/components/repo-file-content-viewer.tsx b/apps/design-system/src/subjects/views/repo-files/components/repo-file-content-viewer.tsx
index af05934f3d..304ac9f5a6 100644
--- a/apps/design-system/src/subjects/views/repo-files/components/repo-file-content-viewer.tsx
+++ b/apps/design-system/src/subjects/views/repo-files/components/repo-file-content-viewer.tsx
@@ -44,7 +44,7 @@ export const RepoFileContentViewer = ({ isMarkdown = false }: { isMarkdown?: boo
dryRun={noop}
violation={false}
bypassable={false}
- currentBranch={repoFilesStore.branchSelectorStore.selectedBranchTag.name}
+ currentBranch={repoFilesStore.branchSelectorStore.selectedBranchTag?.name || ''}
setAllStates={noop}
isSubmitting={false}
/>
@@ -60,7 +60,7 @@ export const RepoFileContentViewer = ({ isMarkdown = false }: { isMarkdown?: boo
handleOpenDeleteDialog={() => handleToggleDeleteDialog(true)}
/>
{isMarkdown && view === 'preview' ? (
-
+
) : view === 'code' ? (
)}
>
diff --git a/apps/design-system/src/subjects/views/repo-files/components/repo-file-edit.tsx b/apps/design-system/src/subjects/views/repo-files/components/repo-file-edit.tsx
index 0e74873cd7..e711906c2b 100644
--- a/apps/design-system/src/subjects/views/repo-files/components/repo-file-edit.tsx
+++ b/apps/design-system/src/subjects/views/repo-files/components/repo-file-edit.tsx
@@ -1,19 +1,26 @@
import { useCallback, useState } from 'react'
-import { noop, useTranslationStore } from '@utils/viewUtils'
+import { noop } from '@utils/viewUtils'
-import { EditViewTypeValue, FileEditorControlBar, GitCommitDialog, GitCommitFormType } from '@harnessio/ui/components'
-import { CodeModes, PathActionBar } from '@harnessio/ui/views'
+import {
+ EditViewTypeValue,
+ FileEditorControlBar,
+ getIsMarkdown,
+ GitCommitDialog,
+ GitCommitFormType,
+ MarkdownViewer
+} from '@harnessio/ui/components'
+import { BranchSelectorTab, CodeModes, PathActionBar } from '@harnessio/ui/views'
import { CodeDiffEditor, CodeEditor } from '@harnessio/yaml-editor'
import { useExitConfirm } from '../hooks/use-exit-confirm'
-import { themes } from '../theme/monaco-theme'
import { repoFilesStore } from './repo-files-store'
export const RepoFileEdit = () => {
const [view, setView] = useState('edit')
const [isCommitDialogOpen, setIsCommitDialogOpen] = useState(false)
const [fileName, setFileName] = useState('README.md')
+ const [language, _setLanguage] = useState('markdown')
const { show } = useExitConfirm()
const toggleOpenCommitDialog = (value: boolean) => {
@@ -37,6 +44,49 @@ export const RepoFileEdit = () => {
})
}, [show])
+ const renderFileView = () => {
+ switch (view) {
+ case 'preview':
+ if (getIsMarkdown(language)) {
+ return (
+
+ )
+ }
+
+ return (
+
+ )
+
+ case 'edit':
+ return (
+ undefined}
+ options={{
+ readOnly: false
+ }}
+ />
+ )
+
+ default:
+ return null
+ }
+ }
+
return (
<>
{
dryRun={noop}
violation={false}
bypassable={false}
- currentBranch={repoFilesStore.branchSelectorStore.selectedBranchTag.name}
+ currentBranch={repoFilesStore.branchSelectorStore.selectedBranchTag?.name || ''}
setAllStates={noop}
isSubmitting={false}
/>
@@ -55,47 +105,18 @@ export const RepoFileEdit = () => {
setFileName(vel)}
onBlurFileName={noop}
- gitRefName={repoFilesStore.branchSelectorStore.selectedBranchTag.name}
+ gitRefName={repoFilesStore.branchSelectorStore.selectedBranchTag?.name || ''}
fileName={fileName}
handleOpenCommitDialog={() => toggleOpenCommitDialog(true)}
handleCancelFileEdit={handleCancelFileEdit}
+ selectedRefType={BranchSelectorTab.BRANCHES}
/>
- {view === 'edit' ? (
- undefined}
- themeConfig={{
- defaultTheme: 'dark',
- themes
- }}
- options={{
- readOnly: false
- }}
- />
- ) : (
-
- )}
+ {renderFileView()}
>
)
}
diff --git a/apps/design-system/src/subjects/views/repo-files/components/repo-files-store.ts b/apps/design-system/src/subjects/views/repo-files/components/repo-files-store.ts
index 2f3680c5c7..f5669a0fd6 100644
--- a/apps/design-system/src/subjects/views/repo-files/components/repo-files-store.ts
+++ b/apps/design-system/src/subjects/views/repo-files/components/repo-files-store.ts
@@ -48,6 +48,7 @@ export interface RepoFilesStoreType {
latestCommitInfo: LatestFileTypes
repository: RepoRepositoryOutput
jsonFileContent: string
+ mdFileContent: string
blameJsonFileContent: BlameItem[]
markdownFileContent: string
pathParts: PathParts[]
@@ -852,7 +853,7 @@ export const repoFilesStore: RepoFilesStoreType = {
'packages/ui/src/icons/wrench-icon.svg',
'packages/ui/src/icons/x-mark.svg',
'packages/ui/src/index.ts',
- 'packages/ui/src/styles.css',
+ 'packages/ui/src/styles/styles.css',
'packages/ui/src/types/index.ts',
'packages/ui/src/utils/CanaryOutletFactory.ts',
'packages/ui/src/utils/cn.ts',
@@ -1517,7 +1518,7 @@ export const repoFilesStore: RepoFilesStoreType = {
type: 0,
name: 'apps',
lastCommitMessage: 'fix: branch/gitRef normalization from routes (#505)',
- timestamp: '3 hours ago',
+ timestamp: new Date(Date.now() - 1000 * 60 * 60 * 3).toISOString(),
user: {
name: 'Shaurya Kalia'
},
@@ -1555,7 +1556,7 @@ export const repoFilesStore: RepoFilesStoreType = {
type: 0,
name: 'packages',
lastCommitMessage: 'fix: branch/gitRef normalization from routes (#505)',
- timestamp: '3 hours ago',
+ timestamp: new Date(Date.now() - 1000 * 60 * 60 * 3).toISOString(),
user: {
name: 'Shaurya Kalia'
},
@@ -1592,7 +1593,7 @@ export const repoFilesStore: RepoFilesStoreType = {
name: 'Shaurya Kalia'
},
lastCommitMessage: 'fix: branch/gitRef normalization from routes (#505)',
- timestamp: '3 hours ago',
+ timestamp: new Date(Date.now() - 1000 * 60 * 60 * 3).toISOString(),
sha: 'ec92d11'
},
repository: {
@@ -1666,6 +1667,51 @@ export const repoFilesStore: RepoFilesStoreType = {
' "typescript-eslint": "^8.14.0"\n' +
' }\n' +
'}\n',
+ mdFileContent:
+ '# Harness Canary\n' +
+ '\n' +
+ 'This repository contains the code for Harness Canary, a platform for continuous integration and deployment.\n' +
+ '\n' +
+ '## Getting Started\n' +
+ '\n' +
+ 'To get started with Harness Canary, follow these steps:\n' +
+ '\n' +
+ '1. Clone the repository:\n' +
+ ' ```bash\n' +
+ ' git clone http://localhost:3000/git/canary/canary.git\n' +
+ ' ```\n' +
+ '2. Navigate to the project directory:\n' +
+ ' ```bash\n' +
+ ' cd canary\n' +
+ ' ```\n' +
+ '3. Install the dependencies:\n' +
+ ' ```bash\n' +
+ ' pnpm install\n' +
+ ' ```\n' +
+ '4. Run the application:\n' +
+ ' ```bash\n' +
+ ' pnpm start\n' +
+ ' ```\n' +
+ '\n' +
+ '## Contributing\n' +
+ '\n' +
+ 'We welcome contributions to Harness Canary! If you would like to contribute, please follow these steps:\n' +
+ '\n' +
+ '1. Fork the repository on GitHub.\n' +
+ '2. Create a new branch for your feature or bug fix:\n' +
+ ' ```bash\n' +
+ ' git checkout -b my-feature\n' +
+ ' ```\n' +
+ '3. Make your changes and commit them:\n' +
+ ' ```bash\n' +
+ ' git commit -m "Add my feature"\n' +
+ ' ```\n' +
+ '4. Push your changes to your forked repository:\n' +
+ ' ```bash\n' +
+ ' git push origin my-feature\n' +
+ ' ```\n' +
+ '5. Create a pull request on the main repository.\n' +
+ '\n',
blameJsonFileContent: [
{
fromLineNumber: 1,
diff --git a/apps/design-system/src/subjects/views/repo-files/components/repo-files-wrapper.tsx b/apps/design-system/src/subjects/views/repo-files/components/repo-files-wrapper.tsx
index 38c006dab1..3f54360cd7 100644
--- a/apps/design-system/src/subjects/views/repo-files/components/repo-files-wrapper.tsx
+++ b/apps/design-system/src/subjects/views/repo-files/components/repo-files-wrapper.tsx
@@ -1,8 +1,6 @@
-import { FC, useCallback, useMemo } from 'react'
+import { FC, useMemo } from 'react'
-import { noop, useTranslationStore } from '@utils/viewUtils'
-
-import { BranchSelectorTab, CodeModes, IBranchSelectorStore, RepoFiles } from '@harnessio/ui/views'
+import { BranchSelectorTab, CodeModes, RepoFiles } from '@harnessio/ui/views'
import { RepoFileContentViewer } from './repo-file-content-viewer'
import { RepoFileEdit } from './repo-file-edit'
@@ -15,26 +13,10 @@ interface RepoFilesWrapperProps {
}
export const RepoFilesWrapper: FC = ({ codeMode, isDir, isMarkdown = false }) => {
- const useRepoBranchesStore = useCallback(
- (): IBranchSelectorStore => ({
- ...repoFilesStore.branchSelectorStore,
- selectedRefType: BranchSelectorTab.BRANCHES,
- setSelectedBranchTag: noop,
- setSelectedRefType: noop,
- xNextPage: 0,
- xPrevPage: 0,
- page: 1,
- setPage: noop,
- defaultBranch: '',
- branchList: [],
- setTagList: noop,
- setSpaceIdAndRepoId: noop,
- setBranchList: noop,
- setDefaultBranch: noop,
- setPaginationFromHeaders: noop
- }),
- []
- )
+ const selectedBranchTag = { name: 'main', sha: '1d0e5a9461b340ebb3d7e092a2d35ff6d0d5c952', default: true }
+ const selectedRefType = 'branches' as BranchSelectorTab
+ const spaceId = 'canary'
+ const repoId = 'canary'
/**
* Render File content view or Edit file view
@@ -60,11 +42,13 @@ export const RepoFilesWrapper: FC = ({ codeMode, isDir, i
isDir={isDir}
isShowSummary={true}
latestFile={repoFilesStore.latestCommitInfo}
- useTranslationStore={useTranslationStore}
pathNewFile=""
pathUploadFiles=""
codeMode={codeMode}
- useRepoBranchesStore={useRepoBranchesStore}
+ selectedBranchTag={selectedBranchTag}
+ repoId={repoId}
+ spaceId={spaceId}
+ selectedRefType={selectedRefType}
defaultBranchName={repoFilesStore.repository.default_branch}
currentBranchDivergence={{ behind: 0, ahead: 0 }}
isLoadingRepoDetails={false}
diff --git a/apps/design-system/src/subjects/views/repo-general-settings/repo-general-settings.tsx b/apps/design-system/src/subjects/views/repo-general-settings/repo-general-settings.tsx
index 398da9cd53..2bfdac2307 100644
--- a/apps/design-system/src/subjects/views/repo-general-settings/repo-general-settings.tsx
+++ b/apps/design-system/src/subjects/views/repo-general-settings/repo-general-settings.tsx
@@ -1,8 +1,7 @@
-import { useCallback, useState } from 'react'
+import { useState } from 'react'
-import { repoBranchListStore } from '@subjects/stores/repo-branch-store'
import { useRepoRulesStore } from '@subjects/views/repo-general-settings/use-repo-rules-store'
-import { useTranslationStore } from '@utils/viewUtils'
+import { noop } from 'lodash-es'
import { DeleteAlertDialog } from '@harnessio/ui/components'
import { ErrorTypes, RepoSettingsGeneralPage } from '@harnessio/ui/views'
@@ -12,47 +11,38 @@ const loadingStates = {
isUpdatingRepoData: false,
isLoadingSecuritySettings: false,
isUpdatingSecuritySettings: false,
- isRulesLoading: false
+ isRulesLoading: false,
+ isLoadingFeaturesSettings: false,
+ isUpdatingFeaturesSettings: false
}
+// Simple dummy component that satisfies the type requirement
+const DummyComponent = () => null
+
export const RepoGeneralSettings = () => {
- const [branchQuery, setBranchQuery] = useState('')
- const [rulesSearchQuery, setRulesSearchQuery] = useState('')
const [isRulesAlertDeleteDialogOpen, setIsRulesAlertDeleteDialogOpen] = useState(false)
const [isRepoAlertDeleteDialogOpen, setRepoAlertDeleteDialogOpen] = useState(false)
- const [alertDeleteParams, setAlertDeleteParams] = useState('')
+ const [alertDeleteParams] = useState('')
const [apiError, _setApiError] = useState<{ type: ErrorTypes; message: string } | null>(null)
const closeRulesAlertDeleteDialog = () => setIsRulesAlertDeleteDialogOpen(false)
- const openRulesAlertDeleteDialog = (identifier: string) => {
- setAlertDeleteParams(identifier)
- setIsRulesAlertDeleteDialogOpen(true)
- }
const closeRepoAlertDeleteDialog = () => setRepoAlertDeleteDialogOpen(false)
const openRepoAlertDeleteDialog = () => setRepoAlertDeleteDialogOpen(true)
- const useRepoBranchesStore = useCallback(() => ({ ...repoBranchListStore }), [])
-
return (
<>
{}}
- selectBranchOrTag={() => {}}
handleUpdateSecuritySettings={() => {}}
apiError={null}
loadingStates={loadingStates}
isRepoUpdateSuccess={false}
useRepoRulesStore={useRepoRulesStore}
- useRepoBranchesStore={useRepoBranchesStore}
- useTranslationStore={useTranslationStore}
- handleRuleClick={() => {}}
- openRulesAlertDeleteDialog={openRulesAlertDeleteDialog}
openRepoAlertDeleteDialog={openRepoAlertDeleteDialog}
- searchQuery={branchQuery}
- setSearchQuery={setBranchQuery}
- rulesSearchQuery={rulesSearchQuery}
- setRulesSearchQuery={setRulesSearchQuery}
+ branchSelectorRenderer={DummyComponent}
+ openRepoArchiveDialog={() => {}}
+ handleUpdateFeaturesSettings={noop}
/>
{
type="rule"
identifier={alertDeleteParams}
isLoading={false}
- useTranslationStore={useTranslationStore}
/>
{
error={apiError?.type === ErrorTypes.DELETE_REPO ? apiError : null}
type="repository"
isLoading={false}
- useTranslationStore={useTranslationStore}
withForm
/>
>
diff --git a/apps/design-system/src/subjects/views/repo-general-settings/use-repo-rules-store.ts b/apps/design-system/src/subjects/views/repo-general-settings/use-repo-rules-store.ts
index 69efaa29f3..a5975689b0 100644
--- a/apps/design-system/src/subjects/views/repo-general-settings/use-repo-rules-store.ts
+++ b/apps/design-system/src/subjects/views/repo-general-settings/use-repo-rules-store.ts
@@ -5,7 +5,8 @@ export const useRepoRulesStore = (): IRepoStore => ({
name: 'canary',
description: '',
defaultBranch: 'main',
- isPublic: true
+ isPublic: true,
+ archived: false
},
rules: [
{
@@ -17,7 +18,10 @@ export const useRepoRulesStore = (): IRepoStore => ({
}
],
securityScanning: false,
+ verifyCommitterIdentity: false,
+ gitLfsEnabled: false,
presetRuleData: null,
+ vulnerabilityScanning: 'disabled',
principals: [
{
id: 4,
@@ -38,5 +42,21 @@ export const useRepoRulesStore = (): IRepoStore => ({
updated: 1736833375578
}
],
+ userGroups: [
+ {
+ id: 6,
+ identifier: 'test3',
+ name: 'Test 3',
+ description: 'usergroup description',
+ scope: 0
+ },
+ {
+ id: 7,
+ identifier: 'test4',
+ name: 'Test 4',
+ description: 'usergroup description',
+ scope: 0
+ }
+ ],
recentStatusChecks: null
})
diff --git a/apps/design-system/src/subjects/views/repo-import/index.tsx b/apps/design-system/src/subjects/views/repo-import/index.tsx
index 0d33686ff5..941ae877b3 100644
--- a/apps/design-system/src/subjects/views/repo-import/index.tsx
+++ b/apps/design-system/src/subjects/views/repo-import/index.tsx
@@ -1,17 +1,11 @@
-import { noop, useTranslationStore } from '@utils/viewUtils'
+import { noop } from '@utils/viewUtils'
import { RepoImportPage } from '@harnessio/ui/views'
export const ImportRepoView = () => {
return (
<>
-
+
>
)
}
diff --git a/apps/design-system/src/subjects/views/repo-list/repo-list-store.json b/apps/design-system/src/subjects/views/repo-list/repo-list-store.json
index 84cf65a776..35d75dc2c6 100644
--- a/apps/design-system/src/subjects/views/repo-list/repo-list-store.json
+++ b/apps/design-system/src/subjects/views/repo-list/repo-list-store.json
@@ -10,7 +10,8 @@
"pulls": 0,
"timestamp": "Dec 6, 2024",
"createdAt": 1733489262454,
- "importing": false
+ "importing": false,
+ "path": "accountId/repoId"
}
],
"totalPages": 1,
diff --git a/apps/design-system/src/subjects/views/repo-list/repo-list.tsx b/apps/design-system/src/subjects/views/repo-list/repo-list.tsx
index 9ff8cd6faa..a206939a8c 100644
--- a/apps/design-system/src/subjects/views/repo-list/repo-list.tsx
+++ b/apps/design-system/src/subjects/views/repo-list/repo-list.tsx
@@ -1,16 +1,19 @@
import { FC, useCallback } from 'react'
-import { noop, useTranslationStore } from '@utils/viewUtils'
+import { noop } from '@utils/viewUtils'
-import { RepoListProps, SandboxRepoListPage } from '@harnessio/ui/views'
+import { RepoListPageProps, SandboxRepoListPage } from '@harnessio/ui/views'
import repoListStore from './repo-list-store.json'
-const RepoListWrapper: FC> = props => {
+const RepoListWrapper: FC> = props => {
const useRepoListStore = useCallback(
() => ({
...repoListStore,
- importToastId: null,
+ totalItems: 100,
+ pageSize: 10,
+ setPaginationFromHeaders: (_?: Headers) => {},
+ importToastId: '',
setImportToastId: noop,
updateRepository: noop,
setPage: noop,
@@ -23,15 +26,23 @@ const RepoListWrapper: FC> = props => {
)
return (
-
+ <>
+
+ >
)
}
diff --git a/apps/design-system/src/subjects/views/repo-summary/repo-summary-props.json b/apps/design-system/src/subjects/views/repo-summary/repo-summary-props.json
index 02b16c5f7c..7ae9fccd9d 100644
--- a/apps/design-system/src/subjects/views/repo-summary/repo-summary-props.json
+++ b/apps/design-system/src/subjects/views/repo-summary/repo-summary-props.json
@@ -794,7 +794,7 @@
"packages/ui/src/icons/wrench-icon.svg",
"packages/ui/src/icons/x-mark.svg",
"packages/ui/src/index.ts",
- "packages/ui/src/styles.css",
+ "packages/ui/src/styles/styles.css",
"packages/ui/src/types/index.ts",
"packages/ui/src/utils/CanaryOutletFactory.ts",
"packages/ui/src/utils/cn.ts",
@@ -1378,7 +1378,7 @@
"type": 0,
"name": "apps",
"lastCommitMessage": "fix: branch/gitRef normalization from routes (#505)",
- "timestamp": "3 hours ago",
+ "timestamp": "Nov 14, 2024",
"user": {
"name": "Shaurya Kalia"
},
@@ -1414,7 +1414,7 @@
"type": 0,
"name": "packages",
"lastCommitMessage": "fix: branch/gitRef normalization from routes (#505)",
- "timestamp": "3 hours ago",
+ "timestamp": "Nov 14, 2024",
"user": {
"name": "Shaurya Kalia"
},
@@ -1460,7 +1460,7 @@
"latestCommitInfo": {
"userName": "Shaurya Kalia",
"message": "fix: branch/gitRef normalization from routes (#505)",
- "timestamp": "3 hours ago",
+ "timestamp": "Nov 14, 2024",
"sha": "ec92d11"
},
"isEditingDescription": false,
diff --git a/apps/design-system/src/subjects/views/repo-summary/repo-summary.tsx b/apps/design-system/src/subjects/views/repo-summary/repo-summary.tsx
index 70afeed4c9..add94db230 100644
--- a/apps/design-system/src/subjects/views/repo-summary/repo-summary.tsx
+++ b/apps/design-system/src/subjects/views/repo-summary/repo-summary.tsx
@@ -1,7 +1,5 @@
import { FC, useMemo } from 'react'
-import { useTranslationStore } from '@utils/viewUtils'
-
import { BranchSelectorV2, RepoSummaryView, RepoSummaryViewProps } from '@harnessio/ui/views'
import repoSummaryProps from './repo-summary-props.json'
@@ -21,7 +19,6 @@ const RepoSummaryViewWrapper: FC> = props => {
saveDescription={noop}
handleCreateToken={noop}
navigateToFile={noop}
- useTranslationStore={useTranslationStore}
gitRef=""
updateRepoError=""
isEditDialogOpen={false}
@@ -38,7 +35,6 @@ const RepoSummaryViewWrapper: FC> = props => {
onSelectBranch={noop}
isBranchOnly={false}
dynamicWidth={false}
- useTranslationStore={useTranslationStore}
setSearchQuery={noop}
/>
}
diff --git a/apps/design-system/src/subjects/views/repo-tags/repo-tags-list.tsx b/apps/design-system/src/subjects/views/repo-tags/repo-tags-list.tsx
index 0034d60733..a212eefa05 100644
--- a/apps/design-system/src/subjects/views/repo-tags/repo-tags-list.tsx
+++ b/apps/design-system/src/subjects/views/repo-tags/repo-tags-list.tsx
@@ -1,38 +1,109 @@
import { useCallback, useState } from 'react'
-import { noop, useTranslationStore } from '@utils/viewUtils.ts'
+import { asyncNoop, noop } from '@utils/viewUtils.ts'
-import { CreateTagDialog, IBranchSelectorStore, RepoTagsListView } from '@harnessio/ui/views'
+import { DeleteAlertDialog } from '@harnessio/ui/components'
+import {
+ BranchSelectorListItem,
+ BranchSelectorTab,
+ BranchSelectorV2,
+ CreateBranchDialog,
+ CreateTagDialog,
+ RepoTagsListView
+} from '@harnessio/ui/views'
-import { repoBranchesStore } from '../repo-branches/repo-branches-store'
import { tagsStore } from './repo-tags-store'
export const RepoTagsList = () => {
const [openCreateTagDialog, setOpenCreateTagDialog] = useState(false)
- const useRepoBranchesStore = useCallback((): IBranchSelectorStore => repoBranchesStore, [])
+ const [openCreateBranchDialog, setOpenCreateBranchDialog] = useState(false)
+ const [selectedTagInList, setSelectedTagInList] = useState(null)
+ const [preSelectedTab, setPreSelectedTab] = useState(BranchSelectorTab.BRANCHES)
+
+ const [openDeleteTagDialog, setOpenDeleteTagDialog] = useState(false)
+
+ const tags = tagsStore.tags
+ const branches = [
+ {
+ id: 0,
+ name: 'branch',
+ sha: 'sha',
+ default: false,
+ timestamp: '',
+ user: {
+ name: '',
+ avatarUrl: ''
+ }
+ }
+ ]
const useRepoTagsStore = useCallback(() => tagsStore, [])
return (
<>
setOpenCreateTagDialog(true)}
+ openCreateBranchDialog={(selectedTagInList: BranchSelectorListItem) => {
+ setOpenCreateBranchDialog(true)
+ setSelectedTagInList(selectedTagInList)
+ setPreSelectedTab(BranchSelectorTab.TAGS)
+ }}
searchQuery={''}
setSearchQuery={noop}
- onDeleteTag={noop}
+ onDeleteTag={() => setOpenDeleteTagDialog(true)}
useRepoTagsStore={useRepoTagsStore}
toCommitDetails={() => ''}
- openCreateTagDialog={noop}
+ openCreateTagDialog={() => setOpenCreateTagDialog(true)}
/>
setOpenCreateTagDialog(false)}
onSubmit={noop}
- branchQuery={''}
- setBranchQuery={noop}
- useRepoBranchesStore={useRepoBranchesStore}
+ isLoading={false}
+ error=""
+ selectedBranchOrTag={null}
+ branchSelectorRenderer={() => (
+
+ )}
+ />
+ setOpenCreateBranchDialog(false)}
+ selectedBranchOrTag={selectedTagInList}
+ onSubmit={asyncNoop}
+ isCreatingBranch={false}
+ error=""
+ renderProp={() => (
+
+ )}
+ />
+ setOpenDeleteTagDialog(false)}
+ deleteFn={noop}
+ type="tag"
isLoading={false}
/>
>
diff --git a/apps/design-system/src/subjects/views/repo-tags/repo-tags-store.ts b/apps/design-system/src/subjects/views/repo-tags/repo-tags-store.ts
index 99c57cf43b..604270465d 100644
--- a/apps/design-system/src/subjects/views/repo-tags/repo-tags-store.ts
+++ b/apps/design-system/src/subjects/views/repo-tags/repo-tags-store.ts
@@ -4,23 +4,31 @@ export const tagsStore: RepoTagsStore = {
tags: [
{
name: 'v2.4.0',
- sha: '947bcbe92a5d40aacf861269b6605226adda0daf',
- is_annotated: false
- },
- {
- name: 'v2.3.1',
- sha: '794bdb1c56d885ae02f799c6cce13942e8614516',
- is_annotated: false
+ sha: 'dd6135add66c91c74b21aa7514a57fdc8d5dc320',
+ is_annotated: true,
+ title: 'v2.4.0',
+ message: 'v2.4.0',
+ tagger: {
+ identity: {
+ name: 'user',
+ email: 'user@gmail.com'
+ },
+ when: '2025-04-07T10:08:00Z'
+ }
},
{
name: 'v2.3.0',
- sha: '87f1c74cd8a14ea90635c56a627d5e99a4950c73',
- is_annotated: false
- },
- {
- name: 'v2.25.1-debug',
- sha: '3e7ecf16153e88919951725c3ecc69ff076c00b9',
- is_annotated: false
+ sha: 'f067dc95f956b2b195f30635e6d6e74e774d2108',
+ is_annotated: true,
+ title: 'v2.3.0',
+ message: 'v2.3.0',
+ tagger: {
+ identity: {
+ name: 'user',
+ email: 'user@gmail.com'
+ },
+ when: '2025-04-07T09:04:05Z'
+ }
}
],
page: 1,
diff --git a/apps/design-system/src/subjects/views/repo-webhooks-create/repo-webhooks-list.tsx b/apps/design-system/src/subjects/views/repo-webhooks-create/repo-webhooks-list.tsx
index c9bda09fde..5f9689b2b5 100644
--- a/apps/design-system/src/subjects/views/repo-webhooks-create/repo-webhooks-list.tsx
+++ b/apps/design-system/src/subjects/views/repo-webhooks-create/repo-webhooks-list.tsx
@@ -1,5 +1,3 @@
-import { useTranslationStore } from '@utils/viewUtils.ts'
-
import { RepoWebhooksCreatePage } from '@harnessio/ui/views'
import { repoWebhooksListStore } from '../repo-webhooks-list/repo-webhooks-list-store'
@@ -12,7 +10,6 @@ export const RepoWebhooksCreate = () => {
apiError={null}
isLoading={false}
useWebhookStore={repoWebhooksListStore.useWebhookStore}
- useTranslationStore={useTranslationStore}
/>
)
}
diff --git a/apps/design-system/src/subjects/views/repo-webhooks-list/repo-webhooks-list-store.ts b/apps/design-system/src/subjects/views/repo-webhooks-list/repo-webhooks-list-store.ts
index 0203c2b71c..21b8d9ef93 100644
--- a/apps/design-system/src/subjects/views/repo-webhooks-list/repo-webhooks-list-store.ts
+++ b/apps/design-system/src/subjects/views/repo-webhooks-list/repo-webhooks-list-store.ts
@@ -49,6 +49,9 @@ export const repoWebhooksListStore: RepoWebhooksListStore = {
setPreSetWebhookData: (_: CreateWebhookFormFields | null) => {},
executionId: null,
setExecutionId: (_: number | null) => {},
- updateExecution: () => {}
+ updateExecution: () => {},
+ pageSize: 10,
+ setPaginationFromHeaders: (_?: Headers) => {},
+ totalItems: 10
})
}
diff --git a/apps/design-system/src/subjects/views/repo-webhooks-list/repo-webhooks-list.tsx b/apps/design-system/src/subjects/views/repo-webhooks-list/repo-webhooks-list.tsx
index e99f6d1376..e9ab2adfc5 100644
--- a/apps/design-system/src/subjects/views/repo-webhooks-list/repo-webhooks-list.tsx
+++ b/apps/design-system/src/subjects/views/repo-webhooks-list/repo-webhooks-list.tsx
@@ -1,6 +1,6 @@
import { useCallback, useState } from 'react'
-import { noop, useTranslationStore } from '@utils/viewUtils.ts'
+import { noop } from '@utils/viewUtils.ts'
import { DeleteAlertDialog } from '@harnessio/ui/components'
import { RepoWebhookListPage } from '@harnessio/ui/views'
@@ -25,7 +25,6 @@ export const RepoWebhooksList = () => {
<>
{
onClose={closeDeleteWebhookDialog}
deleteFn={() => closeDeleteWebhookDialog()}
type="webhook"
- useTranslationStore={useTranslationStore}
/>
>
)
diff --git a/apps/design-system/src/subjects/views/search-page/search-page-preview.tsx b/apps/design-system/src/subjects/views/search-page/search-page-preview.tsx
new file mode 100644
index 0000000000..25c59220eb
--- /dev/null
+++ b/apps/design-system/src/subjects/views/search-page/search-page-preview.tsx
@@ -0,0 +1,30 @@
+import { useCallback, useState } from 'react'
+
+import { SearchPageView } from '@harnessio/ui/views'
+
+import { searchResultsStore } from './search-results-store'
+
+export const SearchPagePreview = () => {
+ const [searchQuery, setSearchQuery] = useState(null)
+ const [regexEnabled, setRegexEnabled] = useState(false)
+ const [semanticEnabled, setSemanticEnabled] = useState(false)
+ const useSearchResultsStore = useCallback(() => searchResultsStore, [])
+
+ return (
+ '#'}
+ onRepoSelect={() => {}}
+ onLanguageSelect={() => {}}
+ onClearFilters={() => {}}
+ isProjectScope={false}
+ />
+ )
+}
diff --git a/apps/design-system/src/subjects/views/search-page/search-results-store.ts b/apps/design-system/src/subjects/views/search-page/search-results-store.ts
new file mode 100644
index 0000000000..4109407868
--- /dev/null
+++ b/apps/design-system/src/subjects/views/search-page/search-results-store.ts
@@ -0,0 +1,142 @@
+import { SearchResultItem } from '@harnessio/ui/views'
+
+export interface SearchResultsStore {
+ results: SearchResultItem[]
+ page: number
+ xNextPage: number
+ xPrevPage: number
+ setPage: (page: number) => void
+ setPaginationFromHeaders: () => void
+ setResults: (results: SearchResultItem[]) => void
+ addResult: (result: SearchResultItem) => void
+ removeResult: (id: string) => void
+}
+
+export const searchResultsStore: SearchResultsStore = {
+ results: [
+ {
+ file_name: 'user-service.ts',
+ repo_path: 'packages/api/services',
+ repo_branch: 'main',
+ language: 'typescript',
+ matches: [
+ {
+ line_num: 42,
+ before: 'export const userService = {',
+ after: '};',
+ fragments: [
+ {
+ pre: ' ',
+ match: 'searchUsers',
+ post: ': async (query: string) => {'
+ }
+ ]
+ },
+ {
+ line_num: 124,
+ before: 'const searchUsersByName = async (name: string) => {',
+ after: ' return results;',
+ fragments: [
+ {
+ pre: ' const results = await db.users.find({ name: { $regex: ',
+ match: 'searchPattern',
+ post: ', $options: "i" } });'
+ }
+ ]
+ }
+ ]
+ },
+ {
+ file_name: 'SearchComponent.tsx',
+ repo_path: 'packages/ui/components/search',
+ repo_branch: 'feature/search-improvements',
+ language: 'tsx',
+ matches: [
+ {
+ line_num: 15,
+ before: 'interface SearchProps {',
+ after: '}',
+ fragments: [
+ {
+ pre: ' ',
+ match: 'onSearch',
+ post: ': (query: string) => void;'
+ }
+ ]
+ },
+ {
+ line_num: 57,
+ before: 'const handleSearch = useCallback(() => {',
+ after: '}, [searchTerm, onSearch]);',
+ fragments: [
+ {
+ pre: ' ',
+ match: 'onSearch',
+ post: '(searchTerm);'
+ }
+ ]
+ }
+ ]
+ },
+ {
+ file_name: 'search-api.test.js',
+ repo_path: 'tests/api',
+ repo_branch: 'main',
+ language: 'javascript',
+ matches: [
+ {
+ line_num: 32,
+ before: 'describe("Search API", () => {',
+ after: ' });',
+ fragments: [
+ {
+ pre: ' it("should return results when ',
+ match: 'search',
+ post: 'ing by valid term", async () => {'
+ }
+ ]
+ }
+ ]
+ },
+ {
+ file_name: 'SearchService.java',
+ repo_path: 'src/main/java/com/harness/services',
+ repo_branch: 'main',
+ language: 'java',
+ matches: [
+ {
+ line_num: 45,
+ before: '@Service',
+ after: '}',
+ fragments: [
+ {
+ pre: 'public class ',
+ match: 'SearchService',
+ post: ' implements ISearchService {'
+ }
+ ]
+ },
+ {
+ line_num: 78,
+ before: ' @Override',
+ after: ' }',
+ fragments: [
+ {
+ pre: ' public List ',
+ match: 'search',
+ post: '(String query, SearchOptions options) {'
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ page: 1,
+ xNextPage: 2,
+ xPrevPage: 0,
+ setPage: () => {},
+ setPaginationFromHeaders: () => {},
+ setResults: () => {},
+ addResult: () => {},
+ removeResult: () => {}
+}
diff --git a/apps/design-system/src/subjects/views/secrets/mock-secrets-data.json b/apps/design-system/src/subjects/views/secrets/mock-secrets-data.json
index 8333730ed6..baf52709c6 100644
--- a/apps/design-system/src/subjects/views/secrets/mock-secrets-data.json
+++ b/apps/design-system/src/subjects/views/secrets/mock-secrets-data.json
@@ -2,7 +2,7 @@
{
"secret": {
"type": "SecretFile",
- "name": "secret-file-1",
+ "name": "Really-really-really-really-really-really-really-really-really-long-secret-file-1-name",
"identifier": "secret-id-1",
"orgIdentifier": "org-default",
"projectIdentifier": "project-xyz",
@@ -124,5 +124,257 @@
"updatedAt": 1700005592914,
"draft": false,
"governanceMetadata": null
+ },
+ {
+ "secret": {
+ "type": "SecretFile",
+ "name": "secret-file-1",
+ "identifier": "secret-id-5",
+ "orgIdentifier": "org-default",
+ "projectIdentifier": "project-xyz",
+ "tags": {},
+ "description": "",
+ "spec": {
+ "secretManagerIdentifier": "secret-manager",
+ "additionalMetadata": null
+ }
+ },
+ "createdAt": 1741279791821,
+ "updatedAt": 1741279791821,
+ "draft": false,
+ "governanceMetadata": null
+ },
+ {
+ "secret": {
+ "type": "SecretFile",
+ "name": "secret-file-2",
+ "identifier": "secret-id-6",
+ "orgIdentifier": "org-default",
+ "projectIdentifier": "project-xyz",
+ "tags": {},
+ "description": "",
+ "spec": {
+ "secretManagerIdentifier": "secret-manager",
+ "additionalMetadata": null
+ }
+ },
+ "createdAt": 1741213431403,
+ "updatedAt": 1741213431403,
+ "draft": false,
+ "governanceMetadata": null
+ },
+ {
+ "secret": {
+ "type": "SecretText",
+ "name": "secret-text-1",
+ "identifier": "secret-text-id-7",
+ "orgIdentifier": "org-default",
+ "projectIdentifier": "project-xyz",
+ "tags": {
+ "tag1": "",
+ "tag2": "",
+ "tag3": ""
+ },
+ "description": "desc",
+ "spec": {
+ "secretManagerIdentifier": "secret-manager",
+ "valueType": "Inline",
+ "value": null,
+ "additionalMetadata": null
+ }
+ },
+ "createdAt": 1740785306341,
+ "updatedAt": 1740785306341,
+ "draft": false,
+ "governanceMetadata": null
+ },
+ {
+ "secret": {
+ "type": "SecretText",
+ "name": "secret-text-2",
+ "identifier": "secret-text-id-8",
+ "orgIdentifier": "org-default",
+ "projectIdentifier": "project-xyz",
+ "tags": {},
+ "description": "github token",
+ "spec": {
+ "secretManagerIdentifier": "secret-manager",
+ "valueType": "Inline",
+ "value": null,
+ "additionalMetadata": null
+ }
+ },
+ "createdAt": 1719353653579,
+ "updatedAt": 1719353653579,
+ "draft": false,
+ "governanceMetadata": null
+ },
+ {
+ "secret": {
+ "type": "SecretText",
+ "name": "secret-text-3",
+ "identifier": "secret-text-id-9",
+ "orgIdentifier": "org-default",
+ "projectIdentifier": "project-xyz",
+ "tags": {},
+ "description": "",
+ "spec": {
+ "secretManagerIdentifier": "secret-manager",
+ "valueType": "Inline",
+ "value": null,
+ "additionalMetadata": null
+ }
+ },
+ "createdAt": 1710968557986,
+ "updatedAt": 1710968557986,
+ "draft": false,
+ "governanceMetadata": null
+ },
+ {
+ "secret": {
+ "type": "SecretText",
+ "name": "secret-text-4",
+ "identifier": "secret-text-id-10",
+ "orgIdentifier": "org-default",
+ "projectIdentifier": "project-xyz",
+ "tags": {},
+ "description": "",
+ "spec": {
+ "secretManagerIdentifier": "secret-manager",
+ "valueType": "Inline",
+ "value": null,
+ "additionalMetadata": null
+ }
+ },
+ "createdAt": 1700005592914,
+ "updatedAt": 1700005592914,
+ "draft": false,
+ "governanceMetadata": null
+ },
+ {
+ "secret": {
+ "type": "SecretFile",
+ "name": "secret-file-1",
+ "identifier": "secret-id-11",
+ "orgIdentifier": "org-default",
+ "projectIdentifier": "project-xyz",
+ "tags": {},
+ "description": "",
+ "spec": {
+ "secretManagerIdentifier": "secret-manager",
+ "additionalMetadata": null
+ }
+ },
+ "createdAt": 1741279791821,
+ "updatedAt": 1741279791821,
+ "draft": false,
+ "governanceMetadata": null
+ },
+ {
+ "secret": {
+ "type": "SecretFile",
+ "name": "secret-file-2",
+ "identifier": "secret-id-12",
+ "orgIdentifier": "org-default",
+ "projectIdentifier": "project-xyz",
+ "tags": {},
+ "description": "",
+ "spec": {
+ "secretManagerIdentifier": "secret-manager",
+ "additionalMetadata": null
+ }
+ },
+ "createdAt": 1741213431403,
+ "updatedAt": 1741213431403,
+ "draft": false,
+ "governanceMetadata": null
+ },
+ {
+ "secret": {
+ "type": "SecretText",
+ "name": "secret-text-1",
+ "identifier": "secret-text-id-13",
+ "orgIdentifier": "org-default",
+ "projectIdentifier": "project-xyz",
+ "tags": {
+ "tag1": "",
+ "tag2": "",
+ "tag3": ""
+ },
+ "description": "desc",
+ "spec": {
+ "secretManagerIdentifier": "secret-manager",
+ "valueType": "Inline",
+ "value": null,
+ "additionalMetadata": null
+ }
+ },
+ "createdAt": 1740785306341,
+ "updatedAt": 1740785306341,
+ "draft": false,
+ "governanceMetadata": null
+ },
+ {
+ "secret": {
+ "type": "SecretText",
+ "name": "secret-text-2",
+ "identifier": "secret-text-id-14",
+ "orgIdentifier": "org-default",
+ "projectIdentifier": "project-xyz",
+ "tags": {},
+ "description": "github token",
+ "spec": {
+ "secretManagerIdentifier": "secret-manager",
+ "valueType": "Inline",
+ "value": null,
+ "additionalMetadata": null
+ }
+ },
+ "createdAt": 1719353653579,
+ "updatedAt": 1719353653579,
+ "draft": false,
+ "governanceMetadata": null
+ },
+ {
+ "secret": {
+ "type": "SecretText",
+ "name": "secret-text-3",
+ "identifier": "secret-text-id-15",
+ "orgIdentifier": "org-default",
+ "projectIdentifier": "project-xyz",
+ "tags": {},
+ "description": "",
+ "spec": {
+ "secretManagerIdentifier": "secret-manager",
+ "valueType": "Inline",
+ "value": null,
+ "additionalMetadata": null
+ }
+ },
+ "createdAt": 1710968557986,
+ "updatedAt": 1710968557986,
+ "draft": false,
+ "governanceMetadata": null
+ },
+ {
+ "secret": {
+ "type": "SecretText",
+ "name": "secret-text-4",
+ "identifier": "secret-text-id-16",
+ "orgIdentifier": "org-default",
+ "projectIdentifier": "project-xyz",
+ "tags": {},
+ "description": "",
+ "spec": {
+ "secretManagerIdentifier": "secret-manager",
+ "valueType": "Inline",
+ "value": null,
+ "additionalMetadata": null
+ }
+ },
+ "createdAt": 1700005592914,
+ "updatedAt": 1700005592914,
+ "draft": false,
+ "governanceMetadata": null
}
]
diff --git a/apps/design-system/src/subjects/views/secrets/secret-input.tsx b/apps/design-system/src/subjects/views/secrets/secret-input.tsx
new file mode 100644
index 0000000000..46080b5c3b
--- /dev/null
+++ b/apps/design-system/src/subjects/views/secrets/secret-input.tsx
@@ -0,0 +1,37 @@
+import { useState } from 'react'
+
+import { Link } from '@harnessio/ui/components'
+import { SecretInput, SecretItem } from '@harnessio/ui/views'
+
+import { SecretsPage } from './secrets'
+
+export const SecretInputExample = () => {
+ const [isDrawerOpen, setIsDrawerOpen] = useState(false)
+ const [selectedSecret, setSelectedSecret] = useState(null)
+
+ return (
+ <>
+ Please select a secret}
+ value={selectedSecret}
+ label="Select a Secret"
+ icon="key"
+ onClick={() => {
+ setIsDrawerOpen(true)
+ }}
+ onEdit={() => {
+ setIsDrawerOpen(true)
+ }}
+ onClear={() => setSelectedSecret(null)}
+ renderValue={secret => secret.name}
+ className="mb-8 max-w-xs"
+ />
+
+ >
+ )
+}
diff --git a/apps/design-system/src/subjects/views/secrets/secrets-list.tsx b/apps/design-system/src/subjects/views/secrets/secrets-list.tsx
new file mode 100644
index 0000000000..b7196aa467
--- /dev/null
+++ b/apps/design-system/src/subjects/views/secrets/secrets-list.tsx
@@ -0,0 +1,30 @@
+import { noop } from 'lodash-es'
+
+import { SecretListPage } from '@harnessio/ui/views'
+
+import mockSecretsList from './mock-secrets-data.json'
+
+const SecretsListPage = (): JSX.Element => (
+ ({
+ name: secret.secret.identifier,
+ identifier: secret.secret.identifier,
+ spec: {
+ secretManagerIdentifier: secret.secret.spec.secretManagerIdentifier
+ },
+ updatedAt: secret.updatedAt,
+ createdAt: secret.createdAt
+ }))}
+ isLoading={false}
+ setSearchQuery={noop}
+ onEditSecret={noop}
+ onDeleteSecret={noop}
+ currentPage={1}
+ totalItems={10}
+ pageSize={10}
+ goToPage={noop}
+ onCreate={noop}
+ />
+)
+
+export { SecretsListPage }
diff --git a/apps/design-system/src/subjects/views/secrets/secrets-multi-select.tsx b/apps/design-system/src/subjects/views/secrets/secrets-multi-select.tsx
new file mode 100644
index 0000000000..077c53c320
--- /dev/null
+++ b/apps/design-system/src/subjects/views/secrets/secrets-multi-select.tsx
@@ -0,0 +1,130 @@
+import { useRef, useState } from 'react'
+
+import { noop } from '@utils/viewUtils'
+
+import { Button, ButtonLayout, Drawer, FormSeparator, Spacer, Text } from '@harnessio/ui/components'
+import {
+ DirectionEnum,
+ EntityReference,
+ SecretEntityFormHandle,
+ SecretItem,
+ SecretsHeader,
+ SecretType
+} from '@harnessio/ui/views'
+
+import mockAccountsData from './mock-account-data.json'
+import mockOrgData from './mock-org-data.json'
+import mockProjectsData from './mock-project-data.json'
+import mockSecretsData from './mock-secrets-data.json'
+import { Scope, ScopeEnum, scopeHierarchy } from './types'
+
+export const SecretsMultiSelectPage = () => {
+ const formRef = useRef(null)
+
+ const [isDrawerOpen, setIsDrawerOpen] = useState(true)
+ const [selectedSecret, setSelectedSecret] = useState(null)
+
+ const [selectedType, setSelectedType] = useState(SecretType.NEW)
+
+ const [activeScope, setActiveScope] = useState(ScopeEnum.ORGANIZATION)
+
+ const [parentFolder, setParentFolder] = useState(mockAccountsData[0].accountName)
+ const [childFolder, setChildFolder] = useState(mockProjectsData[0].projectResponse.project.identifier)
+ const [currentFolder, setCurrentFolder] = useState(
+ mockOrgData[0].organizationResponse.organization.identifier
+ )
+
+ // Handlers for existing secrets
+ const handleSelectSecret = (secret: SecretItem[]) => {
+ setSelectedSecret(secret)
+ }
+
+ const handleScopeChange = (direction: DirectionEnum) => {
+ setActiveScope(prevScope => {
+ const newScope =
+ direction === DirectionEnum.PARENT ? scopeHierarchy[prevScope].parent! : scopeHierarchy[prevScope].child!
+ switch (newScope) {
+ case ScopeEnum.ACCOUNT:
+ setParentFolder(null)
+ setCurrentFolder(mockAccountsData[0].accountName)
+ setChildFolder(mockOrgData[0].organizationResponse.organization.identifier)
+ break
+ case ScopeEnum.ORGANIZATION:
+ setParentFolder(mockAccountsData[0].accountName)
+ setCurrentFolder(mockOrgData[0].organizationResponse.organization.identifier)
+ setChildFolder(mockProjectsData[0].projectResponse.project.identifier)
+ break
+ case ScopeEnum.PROJECT:
+ setParentFolder(mockOrgData[0].organizationResponse.organization.identifier)
+ setCurrentFolder(mockProjectsData[0].projectResponse.project.identifier)
+ setChildFolder(null)
+ break
+ }
+ return newScope
+ })
+ }
+
+ const handleCancel = () => {
+ setIsDrawerOpen(false)
+ }
+
+ const handleSubmitEntityForm = () => {
+ formRef.current?.submitForm()
+ }
+
+ const renderSecretContent = () => {
+ return (
+
+ entities={
+ mockSecretsData.map(secret => ({
+ ...secret,
+ id: secret.secret.identifier,
+ name: secret.secret.name,
+ folderPath: currentFolder
+ })) as SecretItem[]
+ }
+ selectedEntities={selectedSecret || []}
+ onSelectEntity={handleSelectSecret}
+ onScopeChange={handleScopeChange}
+ parentFolder={parentFolder}
+ childFolder={childFolder}
+ currentFolder={currentFolder}
+ showBreadcrumbEllipsis={activeScope === ScopeEnum.PROJECT}
+ handleChangeSearchValue={noop}
+ enableMultiSelect
+ />
+ )
+ }
+
+ return (
+ <>
+
+
+
+ Secret
+
+
+ Choose type
+
+
+
+
+ {renderSecretContent()}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ )
+}
diff --git a/apps/design-system/src/subjects/views/secrets/secrets.tsx b/apps/design-system/src/subjects/views/secrets/secrets.tsx
index 4edeb89288..cc5c9788dc 100644
--- a/apps/design-system/src/subjects/views/secrets/secrets.tsx
+++ b/apps/design-system/src/subjects/views/secrets/secrets.tsx
@@ -1,48 +1,87 @@
-import { useState } from 'react'
+import { useRef, useState } from 'react'
-import { useTranslationStore } from '@utils/viewUtils'
+import { secretsFormDefinition } from '@utils/secrets/secrets-form-schema'
+import { noop } from '@utils/viewUtils'
-import { Button, Drawer, Spacer } from '@harnessio/ui/components'
+import { InputFactory } from '@harnessio/forms'
+import { Button, ButtonLayout, Drawer, FormSeparator, Spacer, Text } from '@harnessio/ui/components'
import {
- CreateSecretFormFields,
- CreateSecretPage,
+ ArrayFormInput,
+ BooleanFormInput,
+ CalendarInput,
+ CardsFormInput,
DirectionEnum,
- SecretCreationType,
+ EntityIntent,
+ GroupFormInput,
+ ListFormInput,
+ NumberFormInput,
+ onSubmitSecretProps,
+ SecretEntityForm,
+ SecretEntityFormHandle,
SecretItem,
SecretReference,
SecretsHeader,
- SecretType
+ SecretType,
+ SelectFormInput,
+ SeparatorFormInput,
+ TextareaFormInput,
+ TextFormInput
} from '@harnessio/ui/views'
import mockAccountsData from './mock-account-data.json'
import mockOrgData from './mock-org-data.json'
import mockProjectsData from './mock-project-data.json'
import mockSecretsData from './mock-secrets-data.json'
-import { ScopeEnum, SecretScope } from './types'
+import { Scope, ScopeEnum, scopeHierarchy } from './types'
-export const SecretsPage = () => {
- const scopeHierarchy: Record = {
- account: { parent: null, child: ScopeEnum.ORGANIZATION },
- organization: { parent: ScopeEnum.ACCOUNT, child: ScopeEnum.PROJECT },
- project: { parent: ScopeEnum.ORGANIZATION, child: null }
- }
+const inputComponentFactory = new InputFactory()
+inputComponentFactory.registerComponent(new TextFormInput())
+inputComponentFactory.registerComponent(new BooleanFormInput())
+inputComponentFactory.registerComponent(new NumberFormInput())
+inputComponentFactory.registerComponent(new ArrayFormInput())
+inputComponentFactory.registerComponent(new ListFormInput())
+inputComponentFactory.registerComponent(new TextareaFormInput())
+inputComponentFactory.registerComponent(new GroupFormInput())
+inputComponentFactory.registerComponent(new SelectFormInput())
+inputComponentFactory.registerComponent(new SeparatorFormInput())
+inputComponentFactory.registerComponent(new CardsFormInput())
+inputComponentFactory.registerComponent(new CalendarInput())
+
+export const SecretsPage = ({
+ isDrawerOpen,
+ setIsDrawerOpen,
+ selectedSecret,
+ setSelectedSecret
+}: {
+ isDrawerOpen: boolean
+ setIsDrawerOpen: (isDrawerOpen: boolean) => void
+ selectedSecret: SecretItem | null
+ setSelectedSecret: (selectedSecret: SecretItem | null) => void
+}) => {
+ const formRef = useRef(null)
const [selectedType, setSelectedType] = useState(SecretType.NEW)
- // State for existing secrets
- const [, setActiveScope] = useState(ScopeEnum.ORGANIZATION)
- const [selectedSecret, setSelectedSecret] = useState(null)
+ const [activeScope, setActiveScope] = useState(ScopeEnum.ORGANIZATION)
+
const [parentFolder, setParentFolder] = useState(mockAccountsData[0].accountName)
const [childFolder, setChildFolder] = useState(mockProjectsData[0].projectResponse.project.identifier)
+ const [currentFolder, setCurrentFolder] = useState(
+ mockOrgData[0].organizationResponse.organization.identifier
+ )
- const onSubmit = (data: CreateSecretFormFields) => {
+ const [search, setSearch] = useState('')
+
+ const onSubmit = (data: onSubmitSecretProps) => {
console.log('Submitted data:', data)
+ setIsDrawerOpen(false)
}
// Handlers for existing secrets
const handleSelectSecret = (secret: SecretItem) => {
setSelectedSecret(secret)
console.log('Selected secret:', secret)
+ setIsDrawerOpen(false)
}
const handleScopeChange = (direction: DirectionEnum) => {
@@ -52,14 +91,17 @@ export const SecretsPage = () => {
switch (newScope) {
case ScopeEnum.ACCOUNT:
setParentFolder(null)
+ setCurrentFolder(mockAccountsData[0].accountName)
setChildFolder(mockOrgData[0].organizationResponse.organization.identifier)
break
case ScopeEnum.ORGANIZATION:
setParentFolder(mockAccountsData[0].accountName)
+ setCurrentFolder(mockOrgData[0].organizationResponse.organization.identifier)
setChildFolder(mockProjectsData[0].projectResponse.project.identifier)
break
case ScopeEnum.PROJECT:
setParentFolder(mockOrgData[0].organizationResponse.organization.identifier)
+ setCurrentFolder(mockProjectsData[0].projectResponse.project.identifier)
setChildFolder(null)
break
}
@@ -69,43 +111,50 @@ export const SecretsPage = () => {
const handleCancel = () => {
console.log('Cancelled')
+ setIsDrawerOpen(false)
+ }
+
+ const handleSubmitEntityForm = () => {
+ formRef.current?.submitForm()
}
const renderSecretContent = () => {
switch (selectedType) {
case SecretType.NEW:
return (
-
)
case SecretType.EXISTING:
return (
({
- ...secret,
- id: secret.secret.identifier,
- name: secret.secret.name
- }))}
+ secretsData={
+ mockSecretsData.map(secret => ({
+ ...secret,
+ id: secret.secret.identifier,
+ name: secret.secret.name
+ })) as SecretItem[]
+ }
parentFolder={parentFolder}
+ currentFolder={currentFolder}
childFolder={childFolder}
selectedEntity={selectedSecret}
onSelectEntity={handleSelectSecret}
onScopeChange={handleScopeChange}
onCancel={handleCancel}
+ showBreadcrumbEllipsis={activeScope === ScopeEnum.PROJECT}
isLoading={false}
apiError="Could not fetch secrets, unauthorized"
+ searchValue={search}
+ handleChangeSearchValue={setSearch}
+ isDrawer
/>
)
default:
@@ -114,20 +163,34 @@ export const SecretsPage = () => {
}
return (
-
-
-
-
-
-
- Secrets
-
-
-
-
-
- {renderSecretContent()}
-
-
+ <>
+
+
+
+ Secret
+
+
+ Choose type
+
+
+
+
+ {renderSecretContent()}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
)
}
diff --git a/apps/design-system/src/subjects/views/secrets/types.ts b/apps/design-system/src/subjects/views/secrets/types.ts
index b3ddd7150e..d428676a8b 100644
--- a/apps/design-system/src/subjects/views/secrets/types.ts
+++ b/apps/design-system/src/subjects/views/secrets/types.ts
@@ -4,4 +4,10 @@ export enum ScopeEnum {
PROJECT = 'project'
}
-export type SecretScope = 'account' | 'organization' | 'project'
+export type Scope = 'account' | 'organization' | 'project'
+
+export const scopeHierarchy: Record = {
+ account: { parent: null, child: ScopeEnum.ORGANIZATION },
+ organization: { parent: ScopeEnum.ACCOUNT, child: ScopeEnum.PROJECT },
+ project: { parent: ScopeEnum.ORGANIZATION, child: null }
+}
diff --git a/apps/design-system/src/subjects/views/space-settings-members/space-settings-members.tsx b/apps/design-system/src/subjects/views/space-settings-members/space-settings-members.tsx
index bb79765b65..8183341a49 100644
--- a/apps/design-system/src/subjects/views/space-settings-members/space-settings-members.tsx
+++ b/apps/design-system/src/subjects/views/space-settings-members/space-settings-members.tsx
@@ -1,6 +1,6 @@
import { useState } from 'react'
-import { noop, useTranslationStore } from '@utils/viewUtils'
+import { noop } from '@utils/viewUtils'
import { DeleteAlertDialog } from '@harnessio/ui/components'
import { PrincipalType } from '@harnessio/ui/types'
@@ -34,7 +34,7 @@ const useMemberListStore = () => {
role: 'space_owner',
email: 'test@test.com',
avatarUrl: '',
- timestamp: '2 hours ago',
+ timestamp: 'Aug 30, 2023',
uid: 'test1'
},
{
@@ -49,7 +49,8 @@ const useMemberListStore = () => {
spaceId: '',
page: 1,
setPage: noop,
- totalPages: 10
+ totalItems: 10,
+ pageSize: 10
}
}
@@ -70,7 +71,6 @@ export const SpaceSettingsMembers = () => {
<>
{
type="member"
identifier={deleteMemberId ?? undefined}
isLoading={false}
- useTranslationStore={useTranslationStore}
withForm
/>
>
diff --git a/apps/design-system/src/subjects/views/table-v2-demo.tsx b/apps/design-system/src/subjects/views/table-v2-demo.tsx
new file mode 100644
index 0000000000..35d6979e56
--- /dev/null
+++ b/apps/design-system/src/subjects/views/table-v2-demo.tsx
@@ -0,0 +1,89 @@
+import { Table } from '@harnessio/ui/components'
+import { SandboxLayout } from '@harnessio/ui/views'
+
+// Sample data types
+type User = {
+ id: string
+ name: string
+ email: string
+ role: string
+ status: 'active' | 'inactive' | 'pending'
+ lastLogin: string
+}
+
+// Sample data
+const users: User[] = [
+ {
+ id: '1',
+ name: 'John Doe',
+ email: 'john.doe@example.com',
+ role: 'Admin',
+ status: 'active',
+ lastLogin: '2025-06-01'
+ },
+ {
+ id: '2',
+ name: 'Jane Smith',
+ email: 'jane.smith@example.com',
+ role: 'Developer',
+ status: 'active',
+ lastLogin: '2025-06-02'
+ },
+ {
+ id: '3',
+ name: 'Bob Johnson',
+ email: 'bob.johnson@example.com',
+ role: 'Designer',
+ status: 'inactive',
+ lastLogin: '2025-05-28'
+ },
+ {
+ id: '4',
+ name: 'Alice Williams',
+ email: 'alice.williams@example.com',
+ role: 'Product Manager',
+ status: 'pending',
+ lastLogin: '2025-06-03'
+ },
+ {
+ id: '5',
+ name: 'Charlie Brown',
+ email: 'charlie.brown@example.com',
+ role: 'Developer',
+ status: 'active',
+ lastLogin: '2025-06-01'
+ }
+]
+
+export const TableV2Demo: React.FC = () => {
+ return (
+
+
+
+
+
+ Name
+ Email
+ Role
+ Status
+ Last Login
+
+
+
+ {users.map(user => (
+
+ {user.name}
+ {user.email}
+ {user.role}
+ {user.status}
+ {user.lastLogin}
+
+ ))}
+
+
+
+
+ )
+}
+
+export default TableV2Demo
diff --git a/apps/design-system/src/subjects/views/templates/view-only.tsx b/apps/design-system/src/subjects/views/templates/view-only.tsx
new file mode 100644
index 0000000000..e21ecc70ca
--- /dev/null
+++ b/apps/design-system/src/subjects/views/templates/view-only.tsx
@@ -0,0 +1,390 @@
+import {
+ IconV2,
+ Layout,
+ Link,
+ LogoV2,
+ StatsPanel,
+ StatusBadge,
+ Table,
+ Tabs,
+ Tag,
+ Text,
+ TimeAgoCard,
+ Toggle,
+ ViewOnly,
+ ViewOnlyProps,
+ Widgets
+} from '@harnessio/ui/components'
+import { Page } from '@harnessio/ui/views'
+
+const dataMock: ViewOnlyProps[] = [
+ {
+ title: 'Overview',
+ data: [
+ {
+ label: 'Connector name',
+ value: 'Harness Docker'
+ },
+ {
+ label: 'Connector ID',
+ value: 'harnessdocker'
+ },
+ {
+ label: 'Type',
+ value: 'Docker'
+ },
+ {
+ label: 'Created On',
+ value: '02/08/2024'
+ },
+ {
+ label: 'Created By',
+ value: 'brad.rydzewski'
+ },
+ {
+ label: 'Terms of service agreed to',
+ value: '02/08/2024'
+ },
+ {
+ label: 'Updated By',
+ value: 'brad.rydzewski'
+ }
+ ]
+ },
+ {
+ title: 'Cloning',
+ data: [
+ {
+ label: 'SSH Key',
+ value: (
+
+ secret-1
+
+ )
+ }
+ ]
+ },
+ {
+ title: 'Connection',
+ data: [
+ {
+ label: 'Delegates',
+ value: (
+
+
+ delegate-1
+
+
+ delegate-2
+
+
+ )
+ }
+ ]
+ },
+ {
+ title: 'Resources',
+ data: [
+ {
+ label: 'Organization',
+ value: 'Octocat'
+ },
+ {
+ label: 'Repository',
+ value: 'Octocat'
+ },
+ {
+ label: 'Test Repository',
+ value: 'Octocat'
+ },
+ {
+ label: 'Branch',
+ value: 'main'
+ },
+ {
+ label: 'Connector',
+ value: 'Docker'
+ },
+ {
+ label: 'Secret',
+ value: 'AWS secret'
+ }
+ ]
+ },
+ {
+ title: 'Metadata',
+ data: [
+ {
+ label: 'Labels',
+ value: (
+
+
+
+
+
+
+
+
+
+
+ )
+ },
+ {
+ label: 'Description',
+ value: 'Preconfigured Docker connector for use in Harness.'
+ }
+ ]
+ }
+]
+
+export const ViewOnlyView = () => {
+ return (
+
+ console.log('Click')
+ },
+ text: 'Test Connection'
+ }}
+ moreActions={[
+ { title: 'Action 1', onClick: () => console.log('Action 1') },
+ { title: 'Action 2', onClick: () => console.log('Action 2') }
+ ]}
+ >
+
+ Labels:
+
+
+
+
+
+
+
+
+ },
+ { label: 'Last updated', value: null },
+ {
+ label: 'Last status check',
+ value:
+ },
+ { label: 'Last successful check', value: null },
+ {
+ label: 'Connection status',
+ value: (
+
+ Success
+
+ )
+ }
+ ]}
+ />
+
+
+
+
+ Сonfiguration
+ References
+ Activity History
+
+
+
+
+
+ {dataMock.map((props, index) => (
+
+ ))}
+
+
+
+ {dataMock.slice(0, 2).map((props, index) => (
+
+ ))}
+
+
+
+
+
+
+ Event
+ Type
+ Scope
+ Created
+
+
+
+
+
+
+
+
+
+ secretfile
+
+
+
+ Pipeline
+
+ default_project
+
+
+
+
+
+
+
+
+
+
+
+
+
+ testsecret
+
+
+
+ Secret
+
+ default_project
+
+
+
+
+
+
+
+
+
+
+
+
+
+ jamiegit
+
+
+
+ Service
+
+ default_project
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nofar123
+
+
+
+ Template
+
+ default_project
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nofarb
+
+
+
+ Secret
+
+ default_project
+
+
+
+
+
+
+
+
+
+
+
+
+
+ githubtoken
+
+
+
+ Pipeline
+
+ default_project
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/design-system/src/subjects/views/unified-pipeline-studio/mocks/pipeline.ts b/apps/design-system/src/subjects/views/unified-pipeline-studio/mocks/pipeline.ts
index b2cbdca315..47205e8cab 100644
--- a/apps/design-system/src/subjects/views/unified-pipeline-studio/mocks/pipeline.ts
+++ b/apps/design-system/src/subjects/views/unified-pipeline-studio/mocks/pipeline.ts
@@ -4,16 +4,24 @@ export const pipeline1 = `pipeline:
stages:
- parallel:
stages:
- - steps:
+ - name: CI Stage
+ steps:
- run: go build
- - run: go test
- - steps:
+ - run: go test
+ - name: CD Stage
+ steps:
- run: npm test
+ environment:
+ id: prod
+ deploy-to: dev-cluster
+ service: nginx
- group:
stages:
- - steps:
+ - name: Custom Stage 1
+ steps:
- run: go build
- - steps:
+ - name: Custom Stage 2
+ steps:
- run: npm run
- run: npm test
`
diff --git a/apps/design-system/src/subjects/views/unified-pipeline-studio/mocks/template-step-form.ts b/apps/design-system/src/subjects/views/unified-pipeline-studio/mocks/template-step-form.ts
index 641526345f..cfe3faec21 100644
--- a/apps/design-system/src/subjects/views/unified-pipeline-studio/mocks/template-step-form.ts
+++ b/apps/design-system/src/subjects/views/unified-pipeline-studio/mocks/template-step-form.ts
@@ -1,18 +1,18 @@
-import { IInputConfigWithConfig, InputType } from '@harnessio/ui/views'
+import { IInputConfigWithConfig } from '@harnessio/ui/views'
const inputs: IInputConfigWithConfig[] = [
{
- inputType: InputType.text,
+ inputType: 'text',
path: `template.with.testpath1`,
label: 'Input 1'
},
{
- inputType: InputType.text,
+ inputType: 'text',
path: `template.with.testpath2`,
label: 'Input 2'
},
{
- inputType: InputType.text,
+ inputType: 'text',
path: `template.with.testpath3`,
label: 'Input 3'
}
diff --git a/apps/design-system/src/subjects/views/unified-pipeline-studio/run-pipeline-drawer-content.tsx b/apps/design-system/src/subjects/views/unified-pipeline-studio/run-pipeline-drawer-content.tsx
new file mode 100644
index 0000000000..121e0e052a
--- /dev/null
+++ b/apps/design-system/src/subjects/views/unified-pipeline-studio/run-pipeline-drawer-content.tsx
@@ -0,0 +1,162 @@
+import { useState } from 'react'
+
+import { InputFactory } from '@harnessio/forms'
+import {
+ AccordionFormInput,
+ BooleanFormInput,
+ CalendarInput,
+ GroupFormInput,
+ NumberFormInput,
+ RunPipelineDrawerContent as RunPipelineDrawerContentView,
+ SelectFormInput,
+ TextFormInput,
+ VisualYamlValue,
+ type InputLayout
+} from '@harnessio/ui/views'
+import { YamlRevision } from '@harnessio/yaml-editor'
+
+const inputComponentFactory = new InputFactory()
+inputComponentFactory.registerComponent(new TextFormInput())
+inputComponentFactory.registerComponent(new BooleanFormInput())
+inputComponentFactory.registerComponent(new NumberFormInput())
+inputComponentFactory.registerComponent(new GroupFormInput())
+inputComponentFactory.registerComponent(new SelectFormInput())
+inputComponentFactory.registerComponent(new CalendarInput())
+inputComponentFactory.registerComponent(new AccordionFormInput())
+
+const pipelineInputs = {
+ stringRequired: { type: 'string', required: true },
+
+ A1: { type: 'string' },
+ A2: { type: 'string' },
+ A3: { type: 'string' },
+ B1: { type: 'string' },
+ B2Sub1: { type: 'string' },
+ B2Sub2: { type: 'string' },
+ B3: { type: 'string' },
+ C1: { type: 'string' },
+ C2: { type: 'string' },
+ C3: { type: 'string' },
+
+ stringPattern: { type: 'string', pattern: '^[A-Z]*$' },
+ stringRequiredPattern: { type: 'string', required: true, pattern: '^[A-Z]*$' },
+ stringEnum: { type: 'string', enum: ['Option 1', 'Option 2', 'Option 3'] },
+ stringEnumDefault: { type: 'string', enum: ['Option 1', 'Option 2', 'Option 3'], default: 'Option 2' },
+ stringDefault: { type: 'string', default: 'Default value 1' },
+ stringRequiredDefault: { type: 'string', required: true, default: 'Default value 2' },
+ boolean: { type: 'boolean' },
+ booleanDefaultTrue: { type: 'boolean', default: true },
+ booleanDefaultFalse: { type: 'boolean', default: false },
+ nonComponentFactory: {
+ type: 'string',
+ required: true,
+ ui: {
+ component: 'non-component-factory'
+ }
+ },
+ stringCalendarUIcel: {
+ type: 'string',
+ required: true,
+ ui: {
+ component: 'calendar',
+ placeholder: 'select a date',
+ tooltip: 'todays date will be selected by default',
+ visible: "${{stringSelectWithDefaultUI=='kubernetes'}}"
+ }
+ },
+ booleanUIcel: {
+ type: 'boolean',
+ required: true,
+ ui: {
+ component: 'boolean',
+ visible: "${{stringSelectWithDefaultUI=='helm'}}"
+ }
+ },
+ stringSelectWithDefaultUI: {
+ type: 'string',
+ required: true,
+ options: ['docker', 'kubernetes', 'helm'],
+ default: 'docker',
+ ui: {
+ component: 'select',
+ placeholder: 'select a connector type',
+ tooltip: 'docker connector will be selected by default'
+ }
+ }
+}
+
+const layout: InputLayout = [
+ 'stringSelectWithDefaultUI',
+ 'stringCalendarUIcel',
+ 'booleanUIcel',
+ 'nonComponentFactory',
+ 'stringRequired',
+ {
+ title: 'A',
+
+ items: ['A1', 'A2']
+ },
+ {
+ title: 'B',
+ items: ['B1', { title: 'B2', items: ['B2Sub1', 'B2Sub2'] }, 'B3']
+ },
+ {
+ title: 'C',
+ items: ['C1', 'C2', 'C3']
+ },
+ 'stringRequired',
+ {
+ items: ['stringPattern', 'stringRequiredPattern']
+ },
+ {
+ title: 'Advanced',
+ open: true,
+ items: [
+ 'stringEnum',
+ 'stringEnumDefault',
+ {
+ title: 'Subgroup',
+ items: [
+ 'stringRequiredDefault',
+ {
+ title: 'Nested Subgroup',
+ items: ['boolean', 'booleanDefaultTrue', 'booleanDefaultFalse']
+ }
+ ]
+ }
+ ]
+ }
+ /* excluding "stringDefault" deliberately */
+]
+
+export interface RunPipelineFormProps {
+ onClose: () => void
+}
+
+export default function RunPipelineDrawerContent({ onClose }: RunPipelineFormProps) {
+ const [yamlRevision, setYamlRevision] = useState({ yaml: '' })
+ const [view, setView] = useState('visual')
+ const [isLoadingPipeline] = useState(false)
+ const [isValid, setIsValid] = useState(true)
+ const [error, setError] = useState<{ message?: string } | undefined>()
+
+ return (
+ setError({ message: 'Pipeline execution failed. Error message ...' })}
+ pipelineInputs={pipelineInputs}
+ pipelineInputLayout={layout}
+ inputComponentFactory={inputComponentFactory}
+ theme={'dark'}
+ error={error}
+ isExecutingPipeline={false}
+ />
+ )
+}
diff --git a/apps/design-system/src/subjects/views/unified-pipeline-studio/template-list.store.ts b/apps/design-system/src/subjects/views/unified-pipeline-studio/template-list.store.ts
index 70d45007b1..45911618e5 100644
--- a/apps/design-system/src/subjects/views/unified-pipeline-studio/template-list.store.ts
+++ b/apps/design-system/src/subjects/views/unified-pipeline-studio/template-list.store.ts
@@ -1,16 +1,15 @@
import { useEffect, useState } from 'react'
-import { ITemplateListStore } from '@harnessio/ui/views'
+import { ITemplateListItem, ITemplateListStore } from '@harnessio/ui/views'
import { templateStepForm } from './mocks/template-step-form'
export const useTemplateListStore = (): ITemplateListStore => {
- const [templates, setTemplates] = useState<{ identifier: string; description?: string }[] | null>([])
- const [totalPages, setTotalPages] = useState(1)
+ const [templates, setTemplates] = useState([])
+ const [searchQuery, setSearchQuery] = useState('')
- const setTemplatesData = (templates: { identifier: string; description?: string }[] | null, pagesCount: number) => {
+ const setTemplatesData = (templates: ITemplateListItem[] | null) => {
setTemplates(templates)
- setTotalPages(pagesCount)
}
const [page, setPage] = useState(1)
@@ -22,6 +21,7 @@ export const useTemplateListStore = (): ITemplateListStore => {
const itemIdx = index + 10 * (page - 1)
return {
identifier: `template-${itemIdx}`,
+ version: '1.0.0',
description: `Description for template ${itemIdx}`
}
})
@@ -35,8 +35,10 @@ export const useTemplateListStore = (): ITemplateListStore => {
setPage,
setTemplatesData,
templates,
- totalPages,
- xNextPage: page + 1,
- xPrevPage: page - 1
+ totalItems: 10,
+ pageSize: 10,
+ searchQuery,
+ setSearchQuery,
+ isLoading: false
}
}
diff --git a/apps/design-system/src/subjects/views/unified-pipeline-studio/unified-pipeline-studio.store.ts b/apps/design-system/src/subjects/views/unified-pipeline-studio/unified-pipeline-studio.store.ts
deleted file mode 100644
index dbb70867e2..0000000000
--- a/apps/design-system/src/subjects/views/unified-pipeline-studio/unified-pipeline-studio.store.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import { useState } from 'react'
-
-import { IUnifiedPipelineStudioStore } from '@harnessio/ui/views'
-import { YamlRevision } from '@harnessio/yaml-editor/dist/components/YamlEditor'
-
-import { pipeline1 } from './mocks/pipeline'
-
-export const usePipelineStudioStore = (): IUnifiedPipelineStudioStore => {
- const [selectedPath, onSelectedPathChange] = useState()
- const [yamlRevision, onYamlRevisionChange] = useState({ yaml: pipeline1 })
- const [panelOpen, onPanelOpenChange] = useState(true)
- const [errors, onErrorsChange] = useState({
- isYamlValid: true,
- problems: [],
- problemsCount: { all: 0, error: 0, info: 0, warning: 0 }
- })
-
- return {
- yamlRevision,
- onYamlRevisionChange,
- selectedPath,
- onSelectedPathChange,
- errors,
- onErrorsChange,
- panelOpen,
- onPanelOpenChange
- }
-}
diff --git a/apps/design-system/src/subjects/views/unified-pipeline-studio/unified-pipeline-studio.tsx b/apps/design-system/src/subjects/views/unified-pipeline-studio/unified-pipeline-studio.tsx
index f92bae4c38..b5a5cc42ee 100644
--- a/apps/design-system/src/subjects/views/unified-pipeline-studio/unified-pipeline-studio.tsx
+++ b/apps/design-system/src/subjects/views/unified-pipeline-studio/unified-pipeline-studio.tsx
@@ -1,17 +1,64 @@
-import { useTranslationStore } from '@utils/viewUtils'
+import { useState } from 'react'
-import { UnifiedPipelineStudio } from '@harnessio/ui/views'
+import { noop } from '@utils/viewUtils'
+import { Drawer } from '@harnessio/ui/components'
+import { UnifiedPipelineStudio, UnifiedPipelineStudioProps } from '@harnessio/ui/views'
+import { YamlRevision } from '@harnessio/yaml-editor/dist/components/YamlEditor'
+
+import { pipeline1 } from './mocks/pipeline'
+import RunPipelineDrawerContent from './run-pipeline-drawer-content'
import { useTemplateListStore } from './template-list.store'
-import { usePipelineStudioStore } from './unified-pipeline-studio.store'
const PipelineStudioViewWrapper = () => {
+ const [yamlRevision, onYamlRevisionChange] = useState({ yaml: pipeline1 })
+ const [selectedPath, onSelectedPathChange] = useState<{
+ stages?: string | undefined
+ steps?: string | undefined
+ onecanvas?: string | undefined
+ }>({})
+
+ const [panelOpen, onPanelOpenChange] = useState(false)
+ const [errors, onErrorsChange] = useState({
+ isYamlValid: true,
+ problems: [],
+ problemsCount: { all: 0, error: 0, info: 0, warning: 0 }
+ })
+
+ const [view, setView] = useState('visual')
+ const [isYamlDirty, setYamlDirty] = useState(false)
+ const [runPipelineOpen, setRunPipelineOpen] = useState(false)
+
return (
-
+ <>
+ setYamlDirty(false)}
+ selectedPath={selectedPath}
+ onSelectedPathChange={onSelectedPathChange}
+ errors={errors}
+ onErrorsChange={onErrorsChange}
+ panelOpen={panelOpen}
+ onPanelOpenChange={onPanelOpenChange}
+ setView={setView}
+ view={view}
+ onRun={() => setRunPipelineOpen(true)}
+ />
+ {
+ if (!isOpen) {
+ setRunPipelineOpen(false)
+ }
+ }}
+ >
+ setRunPipelineOpen(false)} />
+
+ >
)
}
diff --git a/apps/design-system/src/utils/connectors/aws-kms-connector.tsx b/apps/design-system/src/utils/connectors/aws-kms-connector.tsx
new file mode 100644
index 0000000000..6ce3e8e962
--- /dev/null
+++ b/apps/design-system/src/utils/connectors/aws-kms-connector.tsx
@@ -0,0 +1,112 @@
+import { IFormDefinition } from '@harnessio/forms'
+import { IInputConfigWithConfigInterface, InputConfigType } from '@harnessio/ui/views'
+
+export const AWS_KMS_CONNECTOR_CATEGORY = 'Secrets Manager'
+
+export enum AwsCredTypeValues {
+ ManualConfig = 'ManualConfig',
+ AssumeIAMRole = 'AssumeIAMRole',
+ AssumeRoleSTS = 'AssumeSTSRole',
+ PermanentTokenConfig = 'PermanentTokenConfig'
+}
+export enum DelegateTypes {
+ DELEGATE_OIDC = 'DelegateOidc'
+}
+
+const inputs: IInputConfigWithConfigInterface[] = [
+ {
+ inputType: 'select',
+ path: `credential`,
+ label: 'Credential Type',
+ inputConfig: {
+ options: [
+ { label: 'AWS access key', value: AwsCredTypeValues.ManualConfig },
+ { label: 'Assume Role on Delegate (IAM)', value: AwsCredTypeValues.AssumeIAMRole },
+ { label: 'Assume Role on Delegate (STS)', value: AwsCredTypeValues.AssumeRoleSTS },
+ { label: 'OIDC', value: DelegateTypes.DELEGATE_OIDC }
+ ]
+ }
+ },
+ {
+ inputType: 'select',
+ path: `test`,
+ label: 'test Type',
+ readonly: true,
+ default: AwsCredTypeValues.ManualConfig,
+ inputConfig: {
+ options: [
+ { label: 'AWS access key', value: AwsCredTypeValues.ManualConfig },
+ { label: 'Assume Role on Delegate (IAM)', value: AwsCredTypeValues.AssumeIAMRole },
+ { label: 'Assume Role on Delegate (STS)', value: AwsCredTypeValues.AssumeRoleSTS },
+ { label: 'OIDC', value: DelegateTypes.DELEGATE_OIDC }
+ ],
+ disabledValue: AwsCredTypeValues.AssumeIAMRole
+ }
+ },
+ {
+ inputType: 'text',
+ path: `accessKey`,
+ label: 'AWS - Access Key',
+ isVisible: values => values?.credential === AwsCredTypeValues.ManualConfig
+ },
+ {
+ inputType: 'text',
+ path: `secretKey`,
+ label: 'AWS - Secret Key',
+ isVisible: values => values?.credential === AwsCredTypeValues.ManualConfig
+ },
+ {
+ inputType: 'text',
+ path: `roleArn`,
+ label: 'Role ARN',
+ isVisible: values => values?.credential === AwsCredTypeValues.AssumeRoleSTS
+ },
+ {
+ inputType: 'text',
+ path: `externalName`,
+ label: 'External Id',
+ isVisible: values => values?.credential === AwsCredTypeValues.AssumeRoleSTS
+ },
+ {
+ inputType: 'number',
+ path: `assumeStsRoleDuration`,
+ label: 'Assumed Role duration',
+ isVisible: values => values?.credential === AwsCredTypeValues.AssumeRoleSTS
+ },
+ {
+ inputType: 'text',
+ path: `region`,
+ label: 'Region'
+ },
+ {
+ inputType: 'text',
+ path: `iamRole`,
+ label: 'IAM Role',
+ isVisible: values => values?.credential === DelegateTypes.DELEGATE_OIDC
+ },
+ {
+ inputType: 'group',
+ path: `connection`,
+ label: 'Connection',
+ inputs: [
+ {
+ inputType: 'select',
+ path: `delegate`,
+ label: 'Delegate',
+ default: false,
+ inputConfig: {
+ options: [
+ { label: 'off', value: false },
+ { label: 'on', value: true }
+ ],
+ isDisabled: (values: any) => values?.credential === DelegateTypes.DELEGATE_OIDC,
+ disabledValue: true
+ }
+ }
+ ]
+ }
+]
+
+export const awsKmsConnectorFormDefinition: IFormDefinition = {
+ inputs
+}
diff --git a/apps/design-system/src/utils/connectors/common-connector-utils.ts b/apps/design-system/src/utils/connectors/common-connector-utils.ts
new file mode 100644
index 0000000000..8671f82295
--- /dev/null
+++ b/apps/design-system/src/utils/connectors/common-connector-utils.ts
@@ -0,0 +1,102 @@
+import { IInputConfigWithConfigInterface } from '@harnessio/ui/views'
+
+export const getResourcesContainer = (): IInputConfigWithConfigInterface => ({
+ inputType: 'group',
+ path: `resources`,
+ label: 'Resources',
+ inputs: [
+ {
+ inputType: 'text',
+ path: `resources.organization`,
+ label: 'Organization',
+ inputConfig: {
+ tooltip: 'Limits access to resources in the named organization.'
+ }
+ },
+ {
+ inputType: 'text',
+ path: `resources.repository`,
+ label: 'Repository',
+ inputConfig: {
+ tooltip: 'Limits access to the named repository.'
+ }
+ },
+ {
+ inputType: 'text',
+ path: `resources.testRepo`,
+ label: 'Test Repository',
+ inputConfig: {
+ tooltip: 'Check access to this repository when testing the health of this connector.'
+ }
+ }
+ ]
+})
+
+export const getCloningContainer = (): IInputConfigWithConfigInterface => ({
+ inputType: 'group',
+ path: `cloning`,
+ label: 'Cloning',
+ inputs: [
+ {
+ inputType: 'text',
+ path: `cloning.sshKey`,
+ label: 'SSH Key',
+ inputConfig: {
+ tooltip:
+ 'Repositories are cloned using tokens by default. You can optionall provide an ssh key to override this behavior and clone using git+ssh. '
+ }
+ }
+ ]
+})
+
+export const getConnectionContainer = (): IInputConfigWithConfigInterface => ({
+ inputType: 'group',
+ path: `connection`,
+ label: 'Connection',
+ inputs: [
+ {
+ inputType: 'select',
+ path: `connection.delegate`,
+ label: 'Delegate',
+ inputConfig: {
+ options: [
+ { label: 'off', value: 'off' },
+ { label: 'on', value: 'on' }
+ ],
+ tooltip:
+ 'Route traffic through the Delegate for behind-the-firewall access. You must install the Delegate to use this feature.'
+ }
+ },
+ {
+ inputType: 'select',
+ path: `connection.tunnel`,
+ label: 'Secure Tunnel',
+ inputConfig: {
+ options: [
+ { label: 'off', value: 'off' },
+ { label: 'on', value: 'on' }
+ ],
+ tooltip:
+ 'Route traffic through the Harness Secure Tunnel™ for behind-the-firewall access. You must install the Secure Connect client to use this feature'
+ }
+ }
+ ]
+})
+
+export const getMetadataContainer = (): IInputConfigWithConfigInterface => ({
+ inputType: 'group',
+ path: `metadata`,
+ label: 'Metadata',
+ inputs: [
+ {
+ inputType: 'text',
+ path: `metadata.description`,
+ label: 'Description'
+ },
+ {
+ inputType: 'text',
+ path: `metadata.tags`,
+ label: 'Tags'
+ }
+ ]
+})
diff --git a/apps/design-system/src/utils/connectors/github-connector.tsx b/apps/design-system/src/utils/connectors/github-connector.tsx
new file mode 100644
index 0000000000..2178efd62f
--- /dev/null
+++ b/apps/design-system/src/utils/connectors/github-connector.tsx
@@ -0,0 +1,82 @@
+import { AnyFormikValue, IFormDefinition } from '@harnessio/forms'
+import { IInputConfigWithConfigInterface, InputConfigType } from '@harnessio/ui/views'
+
+import {
+ getCloningContainer,
+ getConnectionContainer,
+ getMetadataContainer,
+ getResourcesContainer
+} from './common-connector-utils'
+
+export const GITHUB_CONNECTOR_CATEOGRY = 'Code Repository'
+
+const inputs: IInputConfigWithConfigInterface[] = [
+ {
+ inputType: 'cards',
+ path: 'githubType',
+ label: 'GitHub Type',
+ inputConfig: {
+ options: [
+ { label: 'Cloud', value: 'Cloud', description: 'Connect to Github Cloud', id: 'cloud', title: 'Cloud' },
+ {
+ label: 'Enterprise',
+ value: 'Enterprise',
+ description: 'Connect to Github Enterprise',
+ id: 'enterprise',
+ title: 'Enterprise'
+ }
+ ]
+ },
+ default: 'Cloud'
+ // required: true,
+ // validation: {
+ // schema: zod.string().min(1, 'Required input')
+ // }
+ },
+ {
+ inputType: 'select',
+ path: `auth`,
+ label: 'Authentication',
+ default: 'Oauth',
+ inputConfig: {
+ options: [
+ { label: 'Oauth', value: 'Oauth' },
+ { label: 'GitHub Application', value: 'GithubApp' },
+ { label: 'Personal Token', value: 'UsernameToken' }
+ ]
+ }
+ },
+ {
+ inputType: 'text',
+ path: `pat`,
+ label: 'Personal Token',
+ isVisible: (values: { auth: string }) => {
+ return values?.auth === 'UsernameToken'
+ }
+ },
+ {
+ inputType: 'group',
+ path: `connection`,
+ label: 'Connection',
+ placeholder: 'Optional',
+ inputs: [
+ {
+ inputType: 'text',
+ path: `delegateSelectors`,
+ label: 'Delegate Selector',
+ required: true,
+ inputConfig: {
+ disableAnyDelegate: (values: AnyFormikValue) => values?.auth === 'UsernameToken'
+ }
+ }
+ ]
+ },
+ getResourcesContainer(),
+ getCloningContainer(),
+ getConnectionContainer(),
+ getMetadataContainer()
+]
+
+export const githubConnectorFormDefinition: IFormDefinition = {
+ inputs
+}
diff --git a/apps/design-system/src/utils/connectors/terraform-connector.tsx b/apps/design-system/src/utils/connectors/terraform-connector.tsx
new file mode 100644
index 0000000000..c761fc729d
--- /dev/null
+++ b/apps/design-system/src/utils/connectors/terraform-connector.tsx
@@ -0,0 +1,21 @@
+import { IFormDefinition } from '@harnessio/forms'
+import { IInputConfigWithConfigInterface, InputConfigType } from '@harnessio/ui/views'
+
+export const TERRAFORM_CONNECTOR_CATEGORY = 'Infrastructure'
+
+const inputs: IInputConfigWithConfigInterface[] = [
+ {
+ inputType: 'text',
+ path: `endpoint`,
+ label: 'Endpoint'
+ },
+ {
+ inputType: 'text',
+ path: `token`,
+ label: 'Token'
+ }
+]
+
+export const terraformConnectorFormDefinition: IFormDefinition = {
+ inputs
+}
diff --git a/apps/design-system/src/utils/connectors/utils.tsx b/apps/design-system/src/utils/connectors/utils.tsx
new file mode 100644
index 0000000000..3e156bcc9b
--- /dev/null
+++ b/apps/design-system/src/utils/connectors/utils.tsx
@@ -0,0 +1,61 @@
+import { AnyConnectorDefinition } from '@harnessio/ui/views'
+
+import { AWS_KMS_CONNECTOR_CATEGORY, awsKmsConnectorFormDefinition } from './aws-kms-connector'
+import { GITHUB_CONNECTOR_CATEOGRY, githubConnectorFormDefinition } from './github-connector'
+import { TERRAFORM_CONNECTOR_CATEGORY, terraformConnectorFormDefinition } from './terraform-connector'
+
+export const GITHUB_CONNECTOR_IDENTIFIER = 'Github'
+export const TERRAFORM_CONNECTOR_IDENTIFIER = 'Terraform'
+export const AWS_KMS_CONNECTOR_IDENTIFIER = 'AWS KMS'
+
+export const harnessConnectors: AnyConnectorDefinition[] = [
+ {
+ type: 'Github',
+ name: GITHUB_CONNECTOR_IDENTIFIER,
+ category: GITHUB_CONNECTOR_CATEOGRY,
+ formDefinition: githubConnectorFormDefinition
+ },
+ {
+ type: 'Terraform',
+ name: TERRAFORM_CONNECTOR_IDENTIFIER,
+ category: TERRAFORM_CONNECTOR_CATEGORY,
+ formDefinition: terraformConnectorFormDefinition
+ },
+ {
+ type: 'AwsKms',
+ name: AWS_KMS_CONNECTOR_IDENTIFIER,
+ category: AWS_KMS_CONNECTOR_CATEGORY,
+ formDefinition: awsKmsConnectorFormDefinition
+ }
+]
+export interface ConnectorDefinitionOptions {
+ autoExpandGroups?: boolean
+}
+
+export function getHarnessConnectorDefinition(type: string, options?: ConnectorDefinitionOptions): any | undefined {
+ const connector = harnessConnectors.find(harnessConnector => harnessConnector.type === type)
+ return {
+ ...connector,
+ formDefinition: {
+ ...connector?.formDefinition,
+ inputs: connector?.formDefinition?.inputs?.map(input => {
+ if (!input) return input
+
+ if (input.inputType === 'group') {
+ return {
+ ...input,
+ inputConfig: {
+ ...(input.inputConfig || {}),
+ autoExpandGroups: options?.autoExpandGroups
+ }
+ }
+ }
+ return input
+ })
+ }
+ }
+}
+
+export const getExecuteOnDelegateValue = () => {
+ return true
+}
diff --git a/apps/design-system/src/utils/secrets/secrets-form-schema.tsx b/apps/design-system/src/utils/secrets/secrets-form-schema.tsx
new file mode 100644
index 0000000000..44b5a8569f
--- /dev/null
+++ b/apps/design-system/src/utils/secrets/secrets-form-schema.tsx
@@ -0,0 +1,73 @@
+import { IFormDefinition } from '@harnessio/forms'
+import { IInputConfigWithConfigInterface, InputConfigType } from '@harnessio/ui/views'
+
+const metadataInputs: IInputConfigWithConfigInterface[] = [
+ {
+ inputType: 'text',
+ path: `secret.description`,
+ label: 'Description'
+ },
+ {
+ inputType: 'text',
+ path: `secret.tags`,
+ label: 'Tags',
+ inputConfig: {
+ tooltip: 'Separate labels with commas or press Enter. Use key:value for objects.'
+ }
+ }
+]
+
+const inputs: IInputConfigWithConfigInterface[] = [
+ {
+ inputType: 'text',
+ label: 'Secret Manager',
+ path: 'secret.spec.secretManagerIdentifier'
+ },
+ {
+ inputType: 'text',
+ path: `secret.name`,
+ label: 'Name'
+ },
+ {
+ inputType: 'text',
+ label: 'ID',
+ path: `secret.identifier`,
+ inputConfig: {
+ tooltip: 'When you create an entity, Harness assigns a unique ID. You can change it until the entity is saved.'
+ }
+ },
+ {
+ inputType: 'text',
+ path: `secret.spec.value`,
+ label: 'Enter the Secret Text'
+ },
+ {
+ inputType: 'cards',
+ path: `secret.spec.valueType`,
+ inputConfig: {
+ options: [
+ { label: 'Inline Secret Value', value: 'inline', description: '', id: 'inline', title: 'Inline Secret Value' },
+ { label: 'Reference Secret', value: 'reference', description: '', id: 'reference', title: 'Reference Secret' }
+ ]
+ },
+ default: 'inline'
+ },
+ {
+ inputType: 'group',
+ path: `secret.metadata`,
+ label: 'Metadata',
+ inputs: metadataInputs,
+ inputConfig: {
+ autoExpandGroups: true
+ }
+ },
+ {
+ inputType: 'calendar',
+ path: `secret.spec.expiryDate`,
+ label: 'Expiry Date'
+ }
+]
+
+export const secretsFormDefinition: IFormDefinition = {
+ inputs
+}
diff --git a/apps/design-system/src/utils/viewUtils.ts b/apps/design-system/src/utils/viewUtils.ts
index 50aea0e158..5ecf045610 100644
--- a/apps/design-system/src/utils/viewUtils.ts
+++ b/apps/design-system/src/utils/viewUtils.ts
@@ -1,17 +1,3 @@
export const noop = () => void 0
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-export const mockT = (key: string, options?: { [key: string]: any }) => {
- if (typeof options === 'string') {
- return options
- }
-
- if (typeof options === 'object' && options?.defaultValue) {
- return options.defaultValue.replace(/{{\s*(\w+)\s*}}/g, (_: string, variable: string) => options[variable] || '')
- }
-
- return key
-}
-
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-export const useTranslationStore = () => ({ t: mockT as any, changeLanguage: noop, i18n: {} as any })
+export const asyncNoop = async () => void 0
diff --git a/apps/gitness/package.json b/apps/gitness/package.json
index 2b2195dfbd..666f23bd50 100644
--- a/apps/gitness/package.json
+++ b/apps/gitness/package.json
@@ -17,16 +17,14 @@
"test:changed": "vitest --run --changed=origin/main",
"extract": "i18next --config './i18n.config.ts'",
"typecheck": "tsc -b",
- "build:webpack": "rm -rf dist && webpack --config webpack.config.cjs",
- "start:webpack": "webpack serve --config webpack.config.cjs"
+ "build:webpack": "rm -rf dist && webpack --config webpack.config.cjs --mode=production",
+ "start:webpack": "webpack serve --config webpack.config.cjs --mode=development"
},
"dependencies": {
- "@harnessio/canary": "workspace:*",
- "@harnessio/code-service-client": "3.5.0",
+ "@harnessio/code-service-client": "3.8.0",
"@harnessio/forms": "workspace:*",
"@harnessio/pipeline-graph": "workspace:*",
"@harnessio/ui": "workspace:*",
- "@harnessio/views": "workspace:*",
"@harnessio/yaml-editor": "workspace:*",
"@hookform/resolvers": "^3.6.0",
"@tanstack/react-query": "4.20.4",
@@ -34,7 +32,6 @@
"clsx": "^2.1.1",
"diff2html": "3.4.22",
"event-source-polyfill": "^1.0.22",
- "highlight.js": "^11.11.1",
"i18next": "^24.0.2",
"i18next-browser-languagedetector": "^8.0.0",
"jotai": "^2.6.3",
@@ -56,7 +53,7 @@
"devDependencies": {
"@eslint/js": "^9.9.0",
"@git-diff-view/react": "^0.0.16",
- "@swc/core": "^1.9.3",
+ "@swc/core": "^1.12.1",
"@testing-library/dom": "^10.4.0",
"@testing-library/react": "^12.1.5",
"@types/event-source-polyfill": "^1.0.0",
diff --git a/apps/gitness/src/App.tsx b/apps/gitness/src/App.tsx
index 1fb9c95bf4..6357f8e3bc 100644
--- a/apps/gitness/src/App.tsx
+++ b/apps/gitness/src/App.tsx
@@ -1,25 +1,18 @@
import { I18nextProvider } from 'react-i18next'
-import {
- createBrowserRouter,
- Link,
- NavLink,
- Outlet,
- RouterProvider,
- useMatches,
- useSearchParams
-} from 'react-router-dom'
+import { createBrowserRouter, RouterProvider } from 'react-router-dom'
import { QueryClientProvider } from '@tanstack/react-query'
import { CodeServiceAPIClient } from '@harnessio/code-service-client'
-import { Toast, Tooltip } from '@harnessio/ui/components'
-import { RouterContextProvider } from '@harnessio/ui/context'
+import { Toast, TooltipProvider } from '@harnessio/ui/components'
+import { TranslationProvider } from '@harnessio/ui/context'
import { ExitConfirmProvider } from './framework/context/ExitConfirmContext'
import { NavigationProvider } from './framework/context/NavigationContext'
import { ThemeProvider } from './framework/context/ThemeContext'
import { queryClient } from './framework/queryClient'
import i18n from './i18n/i18n'
+import { useTranslationStore } from './i18n/stores/i18n-store'
import { routes } from './routes'
const BASE_URL_PREFIX = `${window.apiUrl || ''}/api/v1`
@@ -40,30 +33,24 @@ export default function App() {
// Router Configuration
const router = createBrowserRouter(routes)
+ const { t } = useTranslationStore()
+
return (
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
)
diff --git a/apps/gitness/src/AppMFE.tsx b/apps/gitness/src/AppMFE.tsx
index 73dc41ce31..c16f86750a 100644
--- a/apps/gitness/src/AppMFE.tsx
+++ b/apps/gitness/src/AppMFE.tsx
@@ -1,35 +1,23 @@
-import './styles/AppMFE.css'
-
import { useEffect, useMemo, useRef } from 'react'
import { I18nextProvider } from 'react-i18next'
-import {
- createBrowserRouter,
- Link,
- matchPath,
- NavLink,
- Outlet,
- RouterProvider,
- useLocation,
- useMatches,
- useNavigate,
- useSearchParams
-} from 'react-router-dom'
+import { createBrowserRouter, matchPath, RouterProvider, useLocation, useNavigate } from 'react-router-dom'
import { QueryClientProvider } from '@tanstack/react-query'
import { CodeServiceAPIClient } from '@harnessio/code-service-client'
-import { Toast, Tooltip } from '@harnessio/ui/components'
-import { PortalProvider, RouterContextProvider } from '@harnessio/ui/context'
+import { Toast, TooltipProvider } from '@harnessio/ui/components'
+import { PortalProvider, TranslationProvider } from '@harnessio/ui/context'
import ShadowRootWrapper from './components-v2/shadow-root-wrapper'
import { ExitConfirmProvider } from './framework/context/ExitConfirmContext'
-import { MFEContext, Unknown } from './framework/context/MFEContext'
+import { Hooks, MFEContext, Scope, Unknown } from './framework/context/MFEContext'
import { NavigationProvider } from './framework/context/NavigationContext'
import { ThemeProvider, useThemeStore } from './framework/context/ThemeContext'
import { queryClient } from './framework/queryClient'
import { extractRedirectRouteObjects } from './framework/routing/utils'
import { useLoadMFEStyles } from './hooks/useLoadMFEStyles'
import i18n from './i18n/i18n'
+import { useTranslationStore } from './i18n/stores/i18n-store'
import { mfeRoutes, repoRoutes } from './routes'
import { decodeURIComponentIfValid } from './utils/path-utils'
@@ -82,17 +70,10 @@ function MFERouteRenderer({ renderUrl, parentLocationPath, onRouteChange }: MFER
}
interface AppMFEProps {
- /**
- * These types will be later referred from "ChildComponentProps" from @harness/microfrontends
- * */
- scope: {
- accountId?: string
- orgIdentifier?: string
- projectIdentifier?: string
- }
+ scope: Scope
renderUrl: string
on401?: () => void
- useMFEThemeContext: () => { theme: string }
+ useMFEThemeContext: () => { theme: string; setTheme: (newTheme: string) => void }
parentLocationPath: string
onRouteChange: (updatedLocationPathname: string) => void
customHooks: Partial<{
@@ -101,6 +82,15 @@ interface AppMFEProps {
customUtils: Partial<{
navigateToUserProfile: Unknown
}>
+ customPromises: Partial<{
+ getCurrentUser: Promise
+ }>
+ routes: Partial<{
+ toAccountSettings: () => string
+ toOrgSettings: () => string
+ toProjectSettings: () => string
+ }>
+ hooks: Hooks
}
function decode(arg: string): T {
@@ -115,7 +105,10 @@ export default function AppMFE({
parentLocationPath,
onRouteChange,
customHooks,
- customUtils
+ customUtils,
+ customPromises,
+ routes,
+ hooks
}: AppMFEProps) {
new CodeServiceAPIClient({
urlInterceptor: (url: string) =>
@@ -137,7 +130,7 @@ export default function AppMFE({
})
// Apply host theme to MFE
- const { theme } = useMFEThemeContext()
+ const { theme, setTheme: setMFETheme } = useMFEThemeContext()
const { setTheme } = useThemeStore()
useEffect(() => {
@@ -148,10 +141,15 @@ export default function AppMFE({
}
}, [theme])
+ // Styles will be loaded inside shadowRoot
+ const shadowRef = useRef(null)
+ const shadowRoot = shadowRef.current?.shadowRoot
+
+ // Radix UI elements will be rendered inside portalContainer
const portalRef = useRef(null)
- const portalContainer = portalRef.current?.shadowRoot as Element | undefined
+ const portalContainer = portalRef.current
- const isStylesLoaded = useLoadMFEStyles(portalContainer)
+ const isStylesLoaded = useLoadMFEStyles(shadowRoot)
// Router Configuration
const basename = `/ng${renderUrl}`
@@ -162,11 +160,13 @@ export default function AppMFE({
)
const router = createBrowserRouter(routesToRender, { basename })
+ const { t } = useTranslationStore()
return (
-
+
-
+ {/* Radix UI elements need to be rendered inside the following div with the theme class */}
+
{!isStylesLoaded ? (
// Replace it with spinner once it is available
@@ -177,32 +177,28 @@ export default function AppMFE({
scope,
renderUrl,
customHooks,
- customUtils
+ customUtils,
+ customPromises,
+ routes,
+ hooks,
+ setMFETheme
}}
>
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/apps/gitness/src/RouteDefinitions.ts b/apps/gitness/src/RouteDefinitions.ts
index dffedb6c73..697c16e83a 100644
--- a/apps/gitness/src/RouteDefinitions.ts
+++ b/apps/gitness/src/RouteDefinitions.ts
@@ -10,6 +10,8 @@ export type PathParams = {
diffRefs?: string
webhookId?: string
labelId?: string
+ branchId?: string
+ tagId?: string
}
export const PathProps = {
@@ -21,7 +23,9 @@ export const PathProps = {
gitRef: ':gitRef*',
resourcePath: ':resourcePath*',
diffRefs: ':diffRefs*',
- webhookId: ':webhookId*'
+ webhookId: ':webhookId*',
+ branchId: ':branchId',
+ tagId: ':tagId'
}
export type PullRequestRoutePathParams = Omit
diff --git a/apps/gitness/src/components/FileExplorer.tsx b/apps/gitness/src/components-v2/FileExplorer.tsx
similarity index 94%
rename from apps/gitness/src/components/FileExplorer.tsx
rename to apps/gitness/src/components-v2/FileExplorer.tsx
index be4d17078e..e876513556 100644
--- a/apps/gitness/src/components/FileExplorer.tsx
+++ b/apps/gitness/src/components-v2/FileExplorer.tsx
@@ -4,7 +4,7 @@ import { useLocation, useParams } from 'react-router-dom'
import { useQuery, useQueryClient } from '@tanstack/react-query'
import { getContent, OpenapiContentInfo, OpenapiGetContentOutput } from '@harnessio/code-service-client'
-import { FileExplorer } from '@harnessio/ui/components'
+import { Alert, FileExplorer, IconV2 } from '@harnessio/ui/components'
import { useOpenFolderPaths } from '../framework/context/ExplorerPathsContext'
import { useRoutes } from '../framework/context/NavigationContext'
@@ -145,11 +145,15 @@ export default function Explorer({ selectedBranch, repoDetails }: ExplorerProps)
}
if (isLoading) {
- return Loading...
+ return
}
if (error) {
- return Error loading folder contents
+ return (
+
+ Error loading folder contents
+
+ )
}
return (
@@ -234,9 +238,11 @@ export default function Explorer({ selectedBranch, repoDetails }: ExplorerProps)
value={openFolderPaths}
>
{isRootLoading ? (
- Loading...
+
) : rootError ? (
- Error loading root folder
+
+ Error loading root folder
+
) : (
rootEntries && renderEntries(rootEntries, '')
)}
diff --git a/apps/gitness/src/components/GitBlame.tsx b/apps/gitness/src/components-v2/GitBlame.tsx
similarity index 89%
rename from apps/gitness/src/components/GitBlame.tsx
rename to apps/gitness/src/components-v2/GitBlame.tsx
index 927c6349db..49348bc8c9 100644
--- a/apps/gitness/src/components/GitBlame.tsx
+++ b/apps/gitness/src/components-v2/GitBlame.tsx
@@ -5,9 +5,9 @@ import { getInitials } from '@harnessio/ui/utils'
import { BlameEditor, BlameEditorProps, ThemeDefinition } from '@harnessio/yaml-editor'
import { BlameItem } from '@harnessio/yaml-editor/dist/types/blame'
+import { useThemeStore } from '../framework/context/ThemeContext'
import { useGetRepoRef } from '../framework/hooks/useGetRepoPath'
import useCodePathDetails from '../hooks/useCodePathDetails'
-import { timeAgoFromISOTime } from '../pages/pipeline-edit/utils/time-utils'
import { normalizeGitRef } from '../utils/git-utils'
interface GitBlameProps {
@@ -38,7 +38,7 @@ export default function GitBlame({ themeConfig, codeContent, language, height }:
const authorInfo = {
identity: { ...commit?.author?.identity },
- when: timeAgoFromISOTime(commit?.author?.when || ''),
+ when: commit?.author?.when ?? '',
initials: getInitials(commit?.author?.identity?.name || commit?.author?.identity?.email || '')
}
@@ -61,6 +61,9 @@ export default function GitBlame({ themeConfig, codeContent, language, height }:
}
}, [gitBlame])
+ const { theme } = useThemeStore()
+ const monacoTheme = (theme ?? '').startsWith('dark') ? 'dark' : 'light'
+
return !isFetching && blameBlocks.length ? (
) : (
<>>
diff --git a/apps/gitness/src/components/LinkComponent.tsx b/apps/gitness/src/components-v2/LinkComponent.tsx
similarity index 100%
rename from apps/gitness/src/components/LinkComponent.tsx
rename to apps/gitness/src/components-v2/LinkComponent.tsx
diff --git a/apps/gitness/src/components-v2/app-shell.tsx b/apps/gitness/src/components-v2/app-shell.tsx
deleted file mode 100644
index 9b82acdbba..0000000000
--- a/apps/gitness/src/components-v2/app-shell.tsx
+++ /dev/null
@@ -1,244 +0,0 @@
-import { useCallback, useEffect, useMemo, useState } from 'react'
-import { Outlet, useLocation, useNavigate, useParams } from 'react-router-dom'
-
-import { cn } from '@harnessio/canary'
-import {
- AppSidebar,
- ManageNavigation,
- MenuGroupType,
- MenuGroupTypes,
- MoreSubmenu,
- NavbarItemType,
- SettingsMenu,
- Sidebar
-} from '@harnessio/ui/components'
-
-import { useNav } from '../components/stores/recent-pinned-nav-links.store'
-import { getNavbarMenuData } from '../data/navbar-menu-data'
-import { getPinnedMenuItemsData } from '../data/pinned-menu-items-data'
-import { useAppContext } from '../framework/context/AppContext'
-import { useRoutes } from '../framework/context/NavigationContext'
-import { useThemeStore } from '../framework/context/ThemeContext'
-import { useLocationChange } from '../framework/hooks/useLocationChange'
-import { useRepoImportEvents } from '../framework/hooks/useRepoImportEvent'
-import { useSelectedSpaceId } from '../framework/hooks/useSelectedSpaceId'
-import { useTranslationStore } from '../i18n/stores/i18n-store'
-import { PathParams } from '../RouteDefinitions'
-import Breadcrumbs from './breadcrumbs/breadcrumbs'
-import { Toaster } from './toaster'
-
-interface NavLinkStorageInterface {
- state: {
- recent: NavbarItemType[]
- pinned: NavbarItemType[]
- }
-}
-
-export const AppShell = () => {
- const routes = useRoutes()
- const { currentUser } = useAppContext()
- const navigate = useNavigate()
- const location = useLocation()
- const { pinnedMenu, recentMenu, setPinned, setRecent, setNavLinks } = useNav()
- const { t } = useTranslationStore()
- const { spaceId, repoId } = useParams()
- const selectedSpaceId = useSelectedSpaceId(spaceId)
- const spaceIdPathParam = spaceId ?? selectedSpaceId ?? ''
-
- const [showMoreMenu, setShowMoreMenu] = useState(false)
- const [showSettingMenu, setShowSettingMenu] = useState(false)
- const [showCustomNav, setShowCustomNav] = useState(false)
-
- const pinnedMenuItemsData = useMemo(
- () => getPinnedMenuItemsData({ t, routes, spaceId: spaceIdPathParam }),
- [t, routes, spaceIdPathParam]
- )
-
- useLocationChange({ t, onRouteChange: setRecent })
-
- useEffect(() => {
- const linksFromStorage = localStorage.getItem('nav-items')
- let parsedLinksFromStorage: NavLinkStorageInterface | undefined
-
- if (linksFromStorage) {
- parsedLinksFromStorage = JSON.parse(linksFromStorage)
- }
-
- /**
- * Logic for setting initial pinned links
- *
- * setting initial pinned link only if no pinned links are stored in local storage.
- * Pinned links cannot be empty as we will have some links permanantly.
- */
- if (parsedLinksFromStorage && !parsedLinksFromStorage?.state?.pinned?.length) {
- const pinnedItems = pinnedMenu.filter(
- item => !pinnedMenuItemsData.some(staticPinned => staticPinned.id === item.id)
- )
- setNavLinks({ pinnedMenu: [...pinnedMenuItemsData, ...pinnedItems] })
- }
- }, [spaceIdPathParam])
-
- /**
- * Map mock data menu by type to Settings and More
- */
- const { moreMenu, settingsMenu } = useMemo(() => {
- const navbarMenuData = getNavbarMenuData({
- t,
- routes,
- spaceId: spaceIdPathParam,
- repoId
- })
- return navbarMenuData.reduce<{
- moreMenu: MenuGroupType[]
- settingsMenu: MenuGroupType[]
- }>(
- (acc, item) => {
- if (item.type === MenuGroupTypes.SETTINGS) {
- acc.settingsMenu.push(item)
- } else {
- acc.moreMenu.push(item)
- }
-
- return acc
- },
- {
- moreMenu: [],
- settingsMenu: []
- }
- )
- }, [t, routes, spaceIdPathParam, repoId])
-
- /**
- * Handle logout
- */
- const handleLogOut = () => navigate(routes.toLogout())
-
- /**
- * Toggle show more menu
- */
- const handleMoreMenu = useCallback(() => {
- setShowSettingMenu(false)
- setShowMoreMenu(prevState => !prevState)
- }, [])
-
- /**
- * Toggle system settings menu
- */
- const handleSettingsMenu = useCallback(() => {
- setShowMoreMenu(false)
- setShowSettingMenu(prevState => !prevState)
- }, [])
-
- /**
- * Toggle custom navigation modal
- */
- const handleCustomNav = useCallback(() => {
- setShowCustomNav(prevState => !prevState)
- }, [])
-
- /**
- * Close all menu when location changed
- */
- useEffect(() => {
- setShowMoreMenu(false)
- setShowSettingMenu(false)
- setShowCustomNav(false)
- }, [location])
-
- /**
- * Handle save recent and pinned items
- */
- const handleSave = (nextRecentItems: NavbarItemType[], nextPinnedItems: NavbarItemType[]) => {
- setNavLinks({
- pinnedMenu: nextPinnedItems,
- recentMenu: nextRecentItems
- })
- }
-
- /**
- * Remove recent menu item
- */
- const handleRemoveRecentMenuItem = useCallback(
- (item: NavbarItemType) => {
- setRecent(item, true)
- },
- [setRecent]
- )
-
- /**
- * Change pinned menu items
- */
- const handleChangePinnedMenuItem = useCallback(
- (item: NavbarItemType, pin: boolean) => {
- setPinned(item, pin)
- },
- [setPinned]
- )
- useRepoImportEvents()
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
- >
- )
-}
-
-export const AppShellMFE = () => {
- useRepoImportEvents()
-
- return (
- <>
-
-
- >
- )
-}
-
-function BreadcrumbsAndOutlet({ className }: { className?: string }) {
- return (
-
- )
-}
diff --git a/apps/gitness/src/components-v2/branch-selector-container.tsx b/apps/gitness/src/components-v2/branch-selector-container.tsx
index 403eb94353..8f87306350 100644
--- a/apps/gitness/src/components-v2/branch-selector-container.tsx
+++ b/apps/gitness/src/components-v2/branch-selector-container.tsx
@@ -5,7 +5,6 @@ import { useFindRepositoryQuery, useListBranchesQuery, useListTagsQuery } from '
import { BranchData, BranchSelectorListItem, BranchSelectorTab, BranchSelectorV2 } from '@harnessio/ui/views'
import { useGetRepoRef } from '../framework/hooks/useGetRepoPath'
-import { useTranslationStore } from '../i18n/stores/i18n-store'
import { transformBranchList } from '../pages-v2/repo/transform-utils/branch-transform'
import { PathParams } from '../RouteDefinitions'
import { orderSortDate } from '../types'
@@ -15,12 +14,22 @@ interface BranchSelectorContainerProps {
onSelectBranchorTag: (branchTag: BranchSelectorListItem, type: BranchSelectorTab) => void
isBranchOnly?: boolean
dynamicWidth?: boolean
+ preSelectedTab?: BranchSelectorTab
+ isFilesPage?: boolean
+ setCreateBranchDialogOpen?: (open: boolean) => void
+ onBranchQueryChange?: (query: string) => void
+ className?: string
}
export const BranchSelectorContainer: React.FC = ({
selectedBranch,
onSelectBranchorTag,
isBranchOnly = false,
- dynamicWidth = false
+ dynamicWidth = false,
+ preSelectedTab,
+ setCreateBranchDialogOpen,
+ isFilesPage = false,
+ onBranchQueryChange,
+ className
}) => {
const repoRef = useGetRepoRef()
const { spaceId, repoId } = useParams()
@@ -30,7 +39,7 @@ export const BranchSelectorContainer: React.FC = (
const { data: { body: repository } = {} } = useFindRepositoryQuery({ repo_ref: repoRef })
- const { data: { body: branches } = {} } = useListBranchesQuery({
+ const { data: { body: branches } = {}, refetch: refetchBranches } = useListBranchesQuery({
repo_ref: repoRef,
queryParams: {
include_commit: false,
@@ -64,11 +73,15 @@ export const BranchSelectorContainer: React.FC = (
}
}, [branches, repository])
+ useEffect(() => {
+ refetchBranches()
+ }, [refetchBranches])
+
useEffect(() => {
if (branches) {
setBranchList(transformBranchList(branches, repository?.default_branch))
}
- }, [branches, repository?.default_branch, setBranchList])
+ }, [branches, repository?.default_branch, setBranchList, selectedBranch])
useEffect(() => {
if (tags) {
@@ -82,9 +95,13 @@ export const BranchSelectorContainer: React.FC = (
}
}, [setTagList, tags])
+ useEffect(() => {
+ onBranchQueryChange?.(branchTagQuery ?? '')
+ }, [branchTagQuery, onBranchQueryChange])
+
return (
= (
onSelectBranch={onSelectBranchorTag}
isBranchOnly={isBranchOnly}
dynamicWidth={dynamicWidth}
+ preSelectedTab={preSelectedTab}
+ isFilesPage={isFilesPage}
+ setCreateBranchDialogOpen={setCreateBranchDialogOpen}
/>
)
}
diff --git a/apps/gitness/src/components-v2/breadcrumbs/breadcrumbs.tsx b/apps/gitness/src/components-v2/breadcrumbs/breadcrumbs.tsx
index 62fa6aa6d4..589d17025f 100644
--- a/apps/gitness/src/components-v2/breadcrumbs/breadcrumbs.tsx
+++ b/apps/gitness/src/components-v2/breadcrumbs/breadcrumbs.tsx
@@ -1,45 +1,58 @@
-import { Link, useMatches } from 'react-router-dom'
+import { UIMatch } from 'react-router-dom'
import { Breadcrumb, Separator, Sidebar, Topbar } from '@harnessio/ui/components'
+import { useRouterContext } from '@harnessio/ui/context'
+import { cn } from '@harnessio/ui/utils'
-import { useIsMFE } from '../../framework/hooks/useIsMFE'
import { CustomHandle } from '../../framework/routing/types'
-function Breadcrumbs() {
- const matches = useMatches()
- const matchesWithBreadcrumb = matches.filter(match => (match.handle as CustomHandle)?.breadcrumb)
- const isMFE = useIsMFE()
+export interface BreadcrumbsProps {
+ breadcrumbs: UIMatch[]
+ withMobileSidebarToggle?: boolean
+ isMobile?: boolean
+ breadcrumbClassName?: string
+}
+
+export const Breadcrumbs = ({
+ breadcrumbs,
+ withMobileSidebarToggle = false,
+ isMobile = false,
+ breadcrumbClassName
+}: BreadcrumbsProps) => {
+ const { Link } = useRouterContext()
+
+ if (!breadcrumbs.length) return null
return (
-
+
- {!isMFE ? (
+ {withMobileSidebarToggle && isMobile && (
<>
-
-
+
+
>
- ) : null}
-
+ )}
+
- {matchesWithBreadcrumb.map((match, index) => {
- const { breadcrumb, asLink = true } = (match.handle || {}) as CustomHandle
+ {breadcrumbs.map((match, index) => {
+ const { breadcrumb, asLink = true } = match.handle ?? {}
const isFirst = index === 0
- const isLast = index === matchesWithBreadcrumb.length - 1
+ const isLast = index === breadcrumbs.length - 1
const breadcrumbContent = breadcrumb!(match.params)
return (
-
- {!isFirst ?