diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml index ccda4a6..102a066 100644 --- a/.github/workflows/automerge.yml +++ b/.github/workflows/automerge.yml @@ -13,10 +13,10 @@ jobs: - name: "Checkout ansible-hub-ui (${{ github.ref }})" uses: actions/checkout@v4 - - name: "Install node 18" + - name: "Install node 20" uses: actions/setup-node@v4 with: - node-version: '18' + node-version: '20' - name: "Check automerge conditions" working-directory: ".github/workflows" diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml index 6526979..7b8035f 100644 --- a/.github/workflows/cypress.yml +++ b/.github/workflows/cypress.yml @@ -109,10 +109,10 @@ jobs: working-directory: 'oci_env' run: 'oci-env compose up &' - - name: "Install node 18" + - name: "Install node 20" uses: actions/setup-node@v4 with: - node-version: '18' + node-version: '20' - name: "Cache ~/.npm & ~/.cache/Cypress" uses: actions/cache@v4 diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 35ea86e..098cb24 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -13,10 +13,10 @@ jobs: - name: "Checkout ansible-hub-ui (${{ github.ref }})" uses: actions/checkout@v4 - - name: "Install node 18" + - name: "Install node 20" uses: actions/setup-node@v4 with: - node-version: '18' + node-version: '20' cache: 'npm' - name: "Checks" @@ -88,10 +88,10 @@ jobs: with: path: 'pr' - - name: "Install node 18" + - name: "Install node 20" uses: actions/setup-node@v4 with: - node-version: '18' + node-version: '20' cache: 'npm' cache-dependency-path: | base/package-lock.json diff --git a/config/standalone.dev.webpack.config.js b/config/standalone.dev.webpack.config.js index 584bec0..7cea33a 100644 --- a/config/standalone.dev.webpack.config.js +++ b/config/standalone.dev.webpack.config.js @@ -4,7 +4,6 @@ const webpackBase = require('./webpack.base.config'); const proxyHost = process.env.API_PROXY_HOST || 'localhost'; const proxyPort = process.env.API_PROXY_PORT || '55001'; const apiBasePath = process.env.API_BASE_PATH || '/api/galaxy/'; -const uiExternalLoginURI = process.env.UI_EXTERNAL_LOGIN_URI || '/login'; module.exports = webpackBase({ // The host where the API lives. EX: https://localhost:55001 @@ -19,9 +18,6 @@ module.exports = webpackBase({ // Port that the UI is served over UI_PORT: 8002, - // dev-mode only, support `IS_COMMUNITY=1 npm run start-standalone` in addition to `npm run start-community` - IS_COMMUNITY: !!process.env.IS_COMMUNITY, - // Serve the UI over http or https. Options: true, false UI_USE_HTTPS: false, @@ -29,7 +25,7 @@ module.exports = webpackBase({ UI_DEBUG: true, // Login URI to allow stand alone with and without keycloak - UI_EXTERNAL_LOGIN_URI: uiExternalLoginURI, + UI_EXTERNAL_LOGIN_URI: '/login', // Value for webpack.devServer.proxy // https://webpack.js.org/configuration/dev-server/#devserverproxy diff --git a/config/webpack.base.config.js b/config/webpack.base.config.js index 83e277b..130c4cc 100644 --- a/config/webpack.base.config.js +++ b/config/webpack.base.config.js @@ -32,8 +32,6 @@ const defaultConfigs = [ { name: 'UI_COMMIT_HASH', default: gitCommit, scope: 'global' }, { name: 'UI_DOCS_URL', default: docsURL, scope: 'global' }, { name: 'UI_EXTERNAL_LOGIN_URI', default: '/login', scope: 'global' }, - { name: 'IS_INSIGHTS', default: false, scope: 'global' }, - { name: 'IS_COMMUNITY', default: false, scope: 'global' }, // Webpack scope: only available in customConfigs here, not exposed to the UI { name: 'UI_PORT', default: 8002, scope: 'webpack' }, diff --git a/cypress/e2e/community/lightspeed-modal.js b/cypress/e2e/community/lightspeed-modal.js deleted file mode 100644 index 030606d..0000000 --- a/cypress/e2e/community/lightspeed-modal.js +++ /dev/null @@ -1,38 +0,0 @@ -const uiPrefix = Cypress.env('uiPrefix'); - -function clickLightspeedSettings() { - cy.get('[data-cy="kebab-toggle"] button[aria-label="Actions"]').click({ - force: true, - }); - cy.contains( - '[data-cy="kebab-toggle"] a', - 'Ansible Lightspeed settings', - ).click({ - force: true, - }); -} - -describe('Ansible Lightspeed Modal Test', () => { - before(() => { - cy.deleteNamespacesAndCollections(); - cy.galaxykit('-i namespace create', 'testns1'); - }); - - it('can opt in or opt out of namespace', () => { - cy.login(null, null, '/', 'Welcome to Galaxy'); - cy.visit(`${uiPrefix}namespaces/testns1`); - - // opt out - clickLightspeedSettings(); - cy.contains('button', 'Opt out of Ansible Lightspeed').click(); - cy.contains('Namespace testns1 is opted out of Ansible Lightspeed.'); - - // opt in - clickLightspeedSettings(); - cy.contains('button', 'Opt in to Ansible Lightspeed').click(); - cy.contains('Namespace testns1 is opted in to Ansible Lightspeed.'); - - clickLightspeedSettings(); - cy.contains('button', 'Opt out of Ansible Lightspeed'); - }); -}); diff --git a/cypress/e2e/community/view-only.js b/cypress/e2e/community/view-only.js deleted file mode 100644 index 468330a..0000000 --- a/cypress/e2e/community/view-only.js +++ /dev/null @@ -1,66 +0,0 @@ -const uiPrefix = Cypress.env('uiPrefix'); - -describe('view-only mode - with download', () => { - before(() => { - cy.galaxykit('collection upload'); - }); - - it('has limited menu, nav', () => { - cy.visit(uiPrefix); - - ['Collections > Collections', 'Collections > Namespaces'].forEach((item) => - cy.menuPresent(item), - ); - - [ - 'Collections > Repositories', - 'Collections > Remotes', - 'Collections > API token', - 'Collections > Approval', - 'Execution Environments > Execution Environments', - 'Execution Environments > Remote Registries', - 'Task Management', - 'Signature Keys', - 'User Access > Users', - 'User Access > Groups', - 'User Access > Roles', - ].forEach((item) => cy.menuMissing(item)); - - // login button in top right nav - cy.contains('.pf-v5-c-masthead__content', 'Login'); - }); - - it('can load Dashboard & Collections', () => { - cy.visit(uiPrefix); - cy.assertTitle('Welcome to Galaxy'); - - cy.visit(`${uiPrefix}collections`); - cy.assertTitle('Collections'); - - // go to a detail screen - cy.get('.pf-v5-c-card__header .name a').first().click(); - - cy.contains('.pf-v5-c-button', 'Download tarball'); - }); - - it('can load Namespaces', () => { - cy.visit(`${uiPrefix}namespaces`); - cy.assertTitle('Namespaces'); - - cy.contains('button', 'Create').should('not.exist'); - cy.contains('.pf-v5-c-tabs__item a', 'My namespaces').should('not.exist'); - - // go to a (namespace) detail screen - cy.contains('a', 'View collections').click(); - cy.assertTitle('admin'); - - cy.contains('button', 'Upload collection').should('not.exist'); - cy.contains('button', 'Upload new version').should('not.exist'); - }); - - it('gets Unauthorized elsewhere', () => { - cy.visit(`${uiPrefix}ansible/repositories`); - cy.contains('You do not have access to Automation Hub'); - cy.contains('.pf-v5-c-button', 'Login'); - }); -}); diff --git a/cypress/e2e/namespaces/docs-menu.js b/cypress/e2e/namespaces/docs-menu.js index 24364e7..98855cd 100644 --- a/cypress/e2e/namespaces/docs-menu.js +++ b/cypress/e2e/namespaces/docs-menu.js @@ -8,19 +8,7 @@ describe('Documentation dropdown', () => { it('user can open docs dropdown menu', () => { cy.get('[data-cy="docs-dropdown"]').click(); - - cy.get('.pf-v5-c-dropdown__menu') - .contains('Customer Support') - .should('have.attr', 'href') - .and('contain', 'https://access.redhat.com/support'); - - cy.get('.pf-v5-c-dropdown__menu') - .contains('Training') - .should('have.attr', 'href') - .and('contain', 'https://www.ansible.com/resources/webinars-training'); - cy.get('.pf-v5-c-dropdown__menu').contains('Documentation'); - cy.get('.pf-v5-c-dropdown__menu').contains('About'); }); diff --git a/cypress/e2e/repo/remote-registry.js b/cypress/e2e/repo/remote-registry.js index 3030c91..8e2a727 100644 --- a/cypress/e2e/repo/remote-registry.js +++ b/cypress/e2e/repo/remote-registry.js @@ -85,29 +85,6 @@ describe('Remote Registry Tests', () => { ).contains('Completed', { timeout: 10000 }); }); - it('users can index only redhat.registry.io', () => { - cy.addRemoteRegistry('registry.test.io', 'https://registry.test.io'); - - cy.get( - 'tr[data-cy="ExecutionEnvironmentRegistryList-row-registry.test.io"] button[aria-label="Actions"]', - ).click(); - cy.contains('Index execution environments').should( - 'have.class', - 'pf-m-disabled', - ); - - cy.addRemoteRegistry('registry.redhat.io', 'https://registry.redhat.io'); - - cy.get( - 'tr[data-cy="ExecutionEnvironmentRegistryList-row-registry.redhat.io"] button[aria-label="Actions"]', - ).click(); - - cy.contains('Index execution environments').click(); - cy.get('[data-cy="AlertList"]').contains( - 'Indexing started for execution environment "registry.redhat.io', - ); - }); - it('admin can edit new remote registry', () => { cy.menuGo('Execution Environments > Remote Registries'); diff --git a/src/api/ai-deny-index.ts b/src/api/ai-deny-index.ts deleted file mode 100644 index 5bf8206..0000000 --- a/src/api/ai-deny-index.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { HubAPI } from './hub'; - -export class API extends HubAPI { - apiPath = '_ui/v1/ai_deny_index/'; - - isInDenyIndex(scope, reference) { - return this.http - .get( - this.apiPath + - `?scope=${encodeURIComponent(scope)}&reference=${encodeURIComponent( - reference, - )}`, - ) - .then(({ data }) => data.count > 0); - } - - removeFromDenyIndex(scope, reference) { - const removePath = - this.apiPath + - encodeURIComponent(scope) + - '/' + - encodeURIComponent(reference) + - '/'; - return this.http.delete(removePath); - } - - addToDenyIndex(scope, reference) { - const params = { reference }; - const addPath = this.apiPath + encodeURIComponent(scope) + '/'; - return this.http.post(addPath, params); - } -} - -export const AIDenyIndexAPI = new API(); diff --git a/src/api/base.ts b/src/api/base.ts index 1dabe16..fe5289b 100644 --- a/src/api/base.ts +++ b/src/api/base.ts @@ -84,14 +84,7 @@ export class BaseAPI { } private async authHandler(request) { - // This runs before every API request and ensures that the user is - // authenticated before the request is executed. On most calls it appears - // to only add ~10ms of latency. - if (IS_INSIGHTS) { - await window.insights.chrome.auth.getUser(); - } else { - request.headers['X-CSRFToken'] = Cookies.get('csrftoken'); - } + request.headers['X-CSRFToken'] = Cookies.get('csrftoken'); return request; } } diff --git a/src/api/gateway-logout.ts b/src/api/gateway-logout.ts deleted file mode 100644 index 358799f..0000000 --- a/src/api/gateway-logout.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { GatewayAPI } from './gateway'; - -class API extends GatewayAPI { - logout() { - return this.http.post('v1/logout/', {}); - } -} - -export const GatewayLogoutAPI = new API(); diff --git a/src/api/gateway.ts b/src/api/gateway.ts deleted file mode 100644 index ff5ead0..0000000 --- a/src/api/gateway.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { BaseAPI } from './base'; - -export class GatewayAPI extends BaseAPI { - mapPageToOffset = false; // page & page_size - - constructor() { - super('/api/gateway'); - } -} diff --git a/src/api/index.ts b/src/api/index.ts index f172509..cbec15d 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -1,6 +1,5 @@ export { ActiveUserAPI } from './active-user'; export { ActivitiesAPI } from './activities'; -export { AIDenyIndexAPI } from './ai-deny-index'; export { AnsibleDistributionAPI } from './ansible-distribution'; export { AnsibleRemoteAPI } from './ansible-remote'; export { AnsibleRepositoryAPI } from './ansible-repository'; @@ -15,17 +14,11 @@ export { ExecutionEnvironmentNamespaceAPI } from './execution-environment-namesp export { ExecutionEnvironmentRegistryAPI } from './execution-environment-registry'; export { ExecutionEnvironmentRemoteAPI } from './execution-environment-remote'; export { FeatureFlagsAPI } from './feature-flags'; -export { GatewayLogoutAPI } from './gateway-logout'; export { GenericPulpAPI } from './generic-pulp'; export { GroupAPI } from './group'; export { GroupRoleAPI } from './group-role'; export { ImportAPI } from './import'; -export { LegacyImportAPI } from './legacy-import'; -export { LegacyNamespaceAPI } from './legacy-namespace'; -export { LegacyRoleAPI } from './legacy-role'; -export { LegacySyncAPI } from './legacy-sync'; export { MyNamespaceAPI } from './my-namespace'; -export { MySyncListAPI } from './my-synclist'; export { NamespaceAPI } from './namespace'; export { PulpAPI } from './pulp'; export { AnsibleRemoteType } from './response-types/ansible-remote'; @@ -54,16 +47,6 @@ export { } from './response-types/execution-environment'; export { FeatureFlagsType } from './response-types/feature-flags'; export { ImportDetailType, ImportListType } from './response-types/import'; -export { LegacyRoleImportDetailType } from './response-types/legacy-import'; -export { - LegacyNamespaceDetailType, - LegacyNamespaceListType, -} from './response-types/legacy-namespace'; -export { - LegacyRoleDetailType, - LegacyRoleListType, - LegacyRoleVersionDetailType, -} from './response-types/legacy-role'; export { NamespaceLinkType, NamespaceListType, @@ -74,7 +57,6 @@ export { PulpStatus } from './response-types/pulp'; export { RemoteType } from './response-types/remote'; export { GroupRoleType, RoleType } from './response-types/role'; export { SettingsType } from './response-types/settings'; -export { SyncListType } from './response-types/synclists'; export { TaskType } from './response-types/task'; export { GroupType, diff --git a/src/api/legacy-import.ts b/src/api/legacy-import.ts deleted file mode 100644 index c2d9bdd..0000000 --- a/src/api/legacy-import.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { LegacyAPI } from './legacy'; - -export class API extends LegacyAPI { - apiPath = 'v1/imports/'; - sortParam = 'order_by'; - - // list(params?) - - import(data) { - return this.http.post(this.apiPath, data); - } -} - -export const LegacyImportAPI = new API(); diff --git a/src/api/legacy-namespace.ts b/src/api/legacy-namespace.ts deleted file mode 100644 index 4f8e96b..0000000 --- a/src/api/legacy-namespace.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { LegacyAPI } from './legacy'; - -export class API extends LegacyAPI { - apiPath = 'v1/namespaces/'; - sortParam = 'sort'; - - // create(data) - // get(id) - // list(params?) - - changeProvider(role_namespace_id, collection_namespace_id) { - return this.http.post(this.apiPath + `${role_namespace_id}/providers/`, { - id: collection_namespace_id, - }); - } -} - -export const LegacyNamespaceAPI = new API(); diff --git a/src/api/legacy-role.ts b/src/api/legacy-role.ts deleted file mode 100644 index 5e54821..0000000 --- a/src/api/legacy-role.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { LegacyAPI } from './legacy'; - -export class API extends LegacyAPI { - apiPath = 'v1/roles/'; - sortParam = 'order_by'; - - getContent(id) { - return super.get(id + '/content'); - } - - getVersions(id) { - return super.get(id + '/versions'); - } - - // get(id) - // list(params?) -} - -export const LegacyRoleAPI = new API(); diff --git a/src/api/legacy-sync.ts b/src/api/legacy-sync.ts deleted file mode 100644 index 638e40d..0000000 --- a/src/api/legacy-sync.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { LegacyAPI } from './legacy'; - -export class API extends LegacyAPI { - apiPath = 'v1/sync/'; - - sync(data) { - return this.http.post(this.apiPath, data); - } -} - -export const LegacySyncAPI = new API(); diff --git a/src/api/legacy.ts b/src/api/legacy.ts deleted file mode 100644 index cf155fb..0000000 --- a/src/api/legacy.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { BaseAPI } from './base'; - -export class LegacyAPI extends BaseAPI { - mapPageToOffset = false; // page & page_size - sortParam = 'order_by'; - - constructor() { - super(API_BASE_PATH); - } -} diff --git a/src/api/my-synclist.ts b/src/api/my-synclist.ts deleted file mode 100644 index 9202448..0000000 --- a/src/api/my-synclist.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { HubAPI } from './hub'; - -class API extends HubAPI { - apiPath = '_ui/v1/my-synclists/'; - - curate(id) { - return this.http.post(this.apiPath + id + '/curate/', {}); - } -} - -export const MySyncListAPI = new API(); diff --git a/src/api/response-types/feature-flags.ts b/src/api/response-types/feature-flags.ts index 4d3d209..83aa939 100644 --- a/src/api/response-types/feature-flags.ts +++ b/src/api/response-types/feature-flags.ts @@ -3,14 +3,11 @@ export class FeatureFlagsType { container_signing: boolean; execution_environments: boolean; - // gateway / keycloak - dab_resource_registry: boolean; + // keycloak external_authentication: boolean; // community mode - ai_deny_index: boolean; display_repositories: boolean; - legacy_roles: boolean; // collection signing can_create_signatures: boolean; diff --git a/src/api/response-types/legacy-import.ts b/src/api/response-types/legacy-import.ts deleted file mode 100644 index 8b8b7dc..0000000 --- a/src/api/response-types/legacy-import.ts +++ /dev/null @@ -1,24 +0,0 @@ -export class LegacyRoleImportDetailType { - id: number; - pulp_id: string; - role_id: number; - state: string; - error: { - code: string; - description: string; - traceback: string; - }; - summary_fields: { - request_username: string; - github_user: string; - github_repo: string; - github_reference: string; - alternate_role_name: string; - task_messages: { - id: string; - state: string; - message_type: string; - message_text: string; - }[]; - }; -} diff --git a/src/api/response-types/legacy-namespace.ts b/src/api/response-types/legacy-namespace.ts deleted file mode 100644 index 36ec28e..0000000 --- a/src/api/response-types/legacy-namespace.ts +++ /dev/null @@ -1,29 +0,0 @@ -export class LegacyNamespaceListType { - id: number; - url: string; - summary_fields: { - owners?: { username: string }[]; - provider_namespaces?: { id: number; name: string; pulp_href: string }[]; - }; - created: string; - modified: string; - name: string; - date_joined: string; - avatar_url: string; - active: boolean; -} - -export class LegacyNamespaceDetailType { - id: number; - url: string; - summary_fields: { - owners?: { username: string }[]; - provider_namespaces?: { id: number; name: string; pulp_href: string }[]; - }; - created: string; - modified: string; - name: string; - date_joined: string; - avatar_url: string; - active: boolean; -} diff --git a/src/api/response-types/legacy-role.ts b/src/api/response-types/legacy-role.ts deleted file mode 100644 index 40ad6af..0000000 --- a/src/api/response-types/legacy-role.ts +++ /dev/null @@ -1,118 +0,0 @@ -/* -{ - "id": 1, - "created": "2022-04-12T03:40:14.210482Z", - "modified": "2022-04-12T03:40:14.227106Z", - "github_user": "geerlingguy", - "github_repo": "ansible-role-memcached", - "github_branch": "1.0.0", - "commit": "a63ebf48564db594ad45d7e4a48079067c6621f0", - "name": "memcached", - "description": "Memcached for Linux", - "summary_fields": { - "dependencies": [], - "namespace": { - "id": 1, - "name": "geerlingguy" - }, - "provider_namespace": { - "id": 1, - "name": "geerlingguy" - }, - "repository": { - "name": "memcached", - "original_name": "ansible-role-memcached" - }, - "tags": [], - "versions": [ - { - "name": "1.0.0", - "release_date": "2022-04-12T03:40:14.220596" - } - ] - } -}, -*/ - -export class LegacyRoleListType { - id: number; - created: string; - modified: string; - github_user: string; - github_repo: string; - github_branch: string; - commit: string; - name: string; - description: string; - download_count: number; - summary_fields: { - dependencies: string[]; - namespace: { - id: number; - name: string; - avatar_url: string; - }; - provider_namespace: { - id: number; - name: string; - }; - repository: { - name: string; - original_name: string; - }; - tags: string[]; - versions: { - name: string; - release_date: string; - }[]; - }; -} - -export class LegacyRoleDetailType { - id: number; - created: string; - modified: string; - github_user: string; - github_repo: string; - github_branch: string; - commit: string; - name: string; - description: string; - download_count: number; - summary_fields: { - dependencies: string[]; - namespace: { - id: number; - name: string; - avatar_url: string; - }; - provider_namespace: { - id: number; - name: string; - }; - repository: { - name: string; - original_name: string; - }; - tags: string[]; - versions: { - name: string; - release_date: string; - }[]; - }; -} - -export class LegacyRoleVersionDetailType { - id: number; - url: string; - related: unknown; - summary_fields: unknown; - created: string; - modified: string; - name: string; - version: string; - commit_date: string; - commit_sha: string; - download_url: string; - active: boolean; -} diff --git a/src/api/response-types/synclists.ts b/src/api/response-types/synclists.ts deleted file mode 100644 index d9f76ec..0000000 --- a/src/api/response-types/synclists.ts +++ /dev/null @@ -1,9 +0,0 @@ -export class SyncListType { - id: number; - name: string; - policy: 'include' | 'exclude'; - collections: { namespace: string; name: string }[]; - namespaces: string[]; - users: string[]; - groups: string[]; -} diff --git a/src/components/alert-list.tsx b/src/components/alert-list.tsx index d1467ee..653efe4 100644 --- a/src/components/alert-list.tsx +++ b/src/components/alert-list.tsx @@ -25,9 +25,7 @@ export const AlertList = ({ alerts, closeAlert }: IProps) => ( style={{ position: 'fixed', right: '5px', - top: IS_INSIGHTS - ? '124px' // 70 + 50 + 4 - : '80px', // 76 + 4 + top: '80px', // 76 + 4 zIndex: 300, display: 'flex', flexDirection: 'column', diff --git a/src/components/collection-card.tsx b/src/components/collection-card.tsx index 5afe8f9..ebfa45f 100644 --- a/src/components/collection-card.tsx +++ b/src/components/collection-card.tsx @@ -3,7 +3,6 @@ import { Button, Card, CardBody, - CardFooter, CardHeader, Text, TextContent, @@ -21,11 +20,10 @@ import { Tooltip, } from 'src/components'; import { Paths, formatPath } from 'src/paths'; -import { convertContentSummaryCounts, namespaceTitle } from 'src/utilities'; +import { convertContentSummaryCounts } from 'src/utilities'; interface IProps extends CollectionVersionSearch { displaySignatures: boolean; - footer?: ReactNode; menu?: ReactNode; } @@ -61,11 +59,8 @@ export const CollectionCard = ({ is_signed, displaySignatures, menu, - footer, }: IProps) => { - const nsTitle = namespaceTitle( - namespace || { name: collection_version.namespace }, - ); + const nsTitle = namespace?.name || collection_version.namespace; const contentSummary = convertContentSummaryCounts(collection_version); return ( @@ -134,7 +129,6 @@ export const CollectionCard = ({ renderTypeCount(k, contentSummary.contents[k]), )} - {footer && {footer}} ); }; diff --git a/src/components/collection-filter.ts b/src/components/collection-filter.ts index c347640..efe909d 100644 --- a/src/components/collection-filter.ts +++ b/src/components/collection-filter.ts @@ -12,34 +12,16 @@ const loadRepos = (inputText) => })), ); -// insights-only -const defaultTags = [ - 'application', - 'cloud', - 'database', - 'eda', - 'infrastructure', - 'linux', - 'monitoring', - 'networking', - 'security', - 'storage', - 'tools', - 'windows', -].map((tag) => ({ id: tag, title: tag })); - const loadTags = (inputText) => - !inputText && IS_INSIGHTS - ? Promise.resolve(defaultTags) - : TagAPI.listCollections({ - name__icontains: inputText, - sort: '-count', - }).then(({ data: { data } }) => - data.map(({ name, count }) => ({ - id: name, - title: count === undefined ? name : t`${name} (${count})`, - })), - ); + TagAPI.listCollections({ + name__icontains: inputText, + sort: '-count', + }).then(({ data: { data } }) => + data.map(({ name, count }) => ({ + id: name, + title: count === undefined ? name : t`${name} (${count})`, + })), + ); export const collectionFilter = ({ featureFlags: { display_signatures, display_repositories }, diff --git a/src/components/collection-header.tsx b/src/components/collection-header.tsx index 10daeba..a1ee7f5 100644 --- a/src/components/collection-header.tsx +++ b/src/components/collection-header.tsx @@ -34,7 +34,6 @@ import { type BreadcrumbType, Breadcrumbs, CollectionDropdown, - CollectionRatings, CopyCollectionToRepositoryModal, DateComponent, DeleteCollectionModal, @@ -59,7 +58,6 @@ import { ParamHelper, canSignNamespace, jsxErrorMessage, - namespaceTitle, parsePulpIDFromURL, repositoryRemoveCollection, waitForTask, @@ -173,9 +171,7 @@ export const CollectionHeader = ({ .filter(Boolean) .map((b, i) => (i ? {b} : b)); // join with spaces - const nsTitle = namespaceTitle( - namespace_metadata || { name: collection_version.namespace }, - ); + const nsTitle = namespace_metadata?.name || collection_version.namespace; if (redirect) { return ; @@ -183,12 +179,6 @@ export const CollectionHeader = ({ const canSign = canSignNamespace(context, namespace); - const issueUrl = - 'https://access.redhat.com/support/cases/#/case/new/open-case/describe-issue/recommendations?caseCreate=true&product=Ansible%20Automation%20Hub&version=Online&summary=' + - encodeURIComponent( - `${collection_version.namespace}-${collectionName}-${version}`, - ); - const deleteFromRepo = deleteAll ? null : collection.repository.name; const deleteFn = (deleteAll) => ({ @@ -432,21 +422,12 @@ export const CollectionHeader = ({ ) : null}
-
} pageControls={ - {IS_INSIGHTS ? ( - - {t`Create issue`} - - ) : null} ; diff --git a/src/components/collection-info.tsx b/src/components/collection-info.tsx index bf3c178..be57dc7 100644 --- a/src/components/collection-info.tsx +++ b/src/components/collection-info.tsx @@ -109,24 +109,22 @@ export const CollectionInfo = ({ /> ) : ( - {!IS_COMMUNITY ? ( -
- - To download this collection, configure your client to - connect to one of the{' '} - - distributions - {' '} - of this repository. - -
- ) : null} +
+ + To download this collection, configure your client to + connect to one of the{' '} + + distributions + {' '} + of this repository. + +
, - ); - } else { - actions.push( - , - ); - } - - actions.push( - , - ); - } - - const expandableTitle = t`Additional details`; - return ( - - closeAlert(i, { alerts, setAlerts })} - /> - {loading ? ( - - ) : ( -
- -
-
- {!loading && isInDenyIndex ? areYouSureToOptIn : areYouSureToOptOut} -
-
- {props.reference} -
- )} - - ); -}; diff --git a/src/components/login-link.tsx b/src/components/login-link.tsx index 46b972b..2015faf 100644 --- a/src/components/login-link.tsx +++ b/src/components/login-link.tsx @@ -17,12 +17,7 @@ export const LoginLink = ({ button }: IProps) => { // NOTE: also update AuthHandler#render (src/loaders/standalone/routes.tsx) when changing this if (featureFlags?.external_authentication && UI_EXTERNAL_LOGIN_URI) { - return ( - {t`Login`} - ); + return {t`Login`}; } else { return ( void }) => {
@@ -49,14 +47,13 @@ export const NamespaceNextPageCard = ({ onClick }: { onClick: () => void }) => { export const NamespaceCard = ({ namespace, showDetailLink }: IProps) => { const { avatar_url, name } = namespace; - const title = namespaceTitle(namespace); return (
{ />
- - {getDescription(title)} + + {getDescription(name)} - {title !== name ? ( - - {getDescription(name)} - - ) : null} {showDetailLink ? ( diff --git a/src/components/namespace-list-item.tsx b/src/components/namespace-list-item.tsx index 5124774..9fbf390 100644 --- a/src/components/namespace-list-item.tsx +++ b/src/components/namespace-list-item.tsx @@ -9,7 +9,6 @@ import React from 'react'; import { Link } from 'react-router-dom'; import { Logo } from 'src/components'; import { Paths, formatPath } from 'src/paths'; -import { namespaceTitle } from 'src/utilities'; export function NamespaceListItem({ namespace, @@ -20,7 +19,6 @@ export function NamespaceListItem({ const namespace_url = formatPath(Paths.namespaceDetail, { namespace: name, }); - const title = namespaceTitle(namespace); return ( @@ -29,7 +27,7 @@ export function NamespaceListItem({ dataListCells={[ ,
- {title} + {name}
, - title !== name ? ( - -
{name}
-
- ) : null, ].filter(Boolean)} /> diff --git a/src/components/partner-header.tsx b/src/components/partner-header.tsx index d4cb68a..6225deb 100644 --- a/src/components/partner-header.tsx +++ b/src/components/partner-header.tsx @@ -10,7 +10,6 @@ import { type LinkTabsProps, Logo, } from 'src/components'; -import { namespaceTitle } from 'src/utilities'; interface IProps { breadcrumbs: BreadcrumbType[]; @@ -27,15 +26,13 @@ export const PartnerHeader = ({ pageControls, tabs, }: IProps) => { - const title = namespaceTitle(namespace); - return ( () => { - if (!IS_COMMUNITY) { - return; - } - - const setScores = (data) => { - if (namespace && name && callback) { - callback(data?.[namespace]?.[name]); - } - }; - - if (!cache[type]) { - // not in cache, trigger load - cache[type] = fetch(`/static/scores/${type}.json`) - .then((response) => response.json()) - .then((data) => { - cache[type] = data; - setScores(data); - }); - } else if (typeof cache[type].then === 'function') { - // waiting for load - cache[type].then(() => setScores(cache[type])); - } else { - // already loaded - setScores(cache[type]); - } -}; - -export function CollectionRatings({ - namespace, - name, - isList, -}: IProps & { isList?: boolean }) { - const [scores, setScores] = useState(null); - const loader = loadScore('collection', namespace, name, setScores); - useEffect(loader, [namespace, name]); - - return isList ? ( - - ) : ( - - - - ); -} - -export function RoleRatings({ namespace, name }: IProps) { - const [scores, setScores] = useState(null); - const loader = loadScore('role', namespace, name, setScores); - useEffect(loader, [namespace, name]); - - return ; -} - -function Ratings({ scores }: { scores: Record }) { - if (!scores) { - return null; - } - - const help = t`This is the rating from old-galaxy.ansible.com. We are working on redoing the rating for the new version of galaxy.`; - const more = ( - - {scores.quality_score !== null ? ( - - - - - - ) : null} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{t`Quality score`} - {' '} - - {scores.quality_score} / 5 -
{t`Community score`} - {' '} - - {scores.score} / 5 -
- Based on {scores.count} surveys. -
{t`Quality of docs`} - {' '} - - {scores.docs} / 5 -
{t`Ease of use`} - {' '} - - {scores.ease_of_use} / 5 -
{t`Does what it promises`} - {' '} - - {scores.does_what_it_says} / 5 -
{t`Works without change`} - {' '} - - {scores.works_as_is} / 5 -
{t`Ready for production`} - {' '} - - {scores.used_in_production} / 5 -
- ); - - return ( - - {' '} - {scores.score} - - ); -} diff --git a/src/components/repository-badge.tsx b/src/components/repository-badge.tsx index 87761da..d7511ef 100644 --- a/src/components/repository-badge.tsx +++ b/src/components/repository-badge.tsx @@ -35,7 +35,7 @@ export const RepositoryBadge = ({ { 'rh-certified': t`Red Hat Certified`, community: t`Community`, - published: IS_INSIGHTS ? t`Certified` : t`Published`, + published: t`Published`, rejected: t`Rejected`, staging: t`Staging`, validated: t`Validated`, diff --git a/src/components/role-import-form.tsx b/src/components/role-import-form.tsx deleted file mode 100644 index 52ce3a7..0000000 --- a/src/components/role-import-form.tsx +++ /dev/null @@ -1,348 +0,0 @@ -import { Trans, t } from '@lingui/macro'; -import { - ActionGroup, - Button, - HelperText, - HelperTextItem, -} from '@patternfly/react-core'; -import React, { useEffect, useState } from 'react'; -import { Link, useLocation, useNavigate } from 'react-router-dom'; -import { LegacyImportAPI, LegacyNamespaceAPI } from 'src/api'; -import { - type AlertType, - DataForm, - ExternalLink, - RoleNamespaceEditModal, -} from 'src/components'; -import { useHubContext } from 'src/loaders/app-context'; -import { Paths, formatPath } from 'src/paths'; -import { - type ErrorMessagesType, - ParamHelper, - handleHttpError, - taskAlert, -} from 'src/utilities'; - -interface IProps { - addAlert: (alert: AlertType) => void; -} - -const NamespaceCheck = ({ - addAlert, - is_superuser, - user, -}: { - addAlert: IProps['addAlert']; - is_superuser: boolean; - user: string; -}) => { - const [error, setError] = useState(null); - const [loading, setLoading] = useState(false); - const [namespace, setNamespace] = useState(null); - const [providerModal, setProviderModal] = useState(false); - - const recheck = () => { - setError(null); - setNamespace(null); - - if (!user) { - setLoading(false); - return; - } - - setLoading(true); - LegacyNamespaceAPI.list({ - name: user, - page_size: 1, - }) - .then( - ({ - data: { - results: [first], - }, - }) => setNamespace(first), - ) - .catch(setError) - .finally(() => setLoading(false)); - }; - - useEffect(recheck, [user]); - - useEffect(() => { - if (providerModal === null) { - recheck(); - setProviderModal(false); - } - }, [providerModal]); - - const provider = namespace?.summary_fields?.provider_namespaces?.[0]; - - return user ? ( - <> - {providerModal && namespace && ( - setProviderModal(null)} - namespace={namespace} - /> - )} - - {loading ? ( - {t`Checking ...`} - ) : null} - {namespace && provider ? ( - - {t`Found`} ( - - - {namespace.name} - - , provided by{' '} - - {provider.name} - - - ) - - ) : null} - {error ? ( - - {t`Failed`}: {error?.message || error} - - ) : null} - {!namespace && !loading && !error ? ( - - {t`No matching namespace found`} - {is_superuser ? ' ' : null} - {is_superuser ? ( - - ) : null} - - ) : null} - {namespace && !provider && !loading && !error ? ( - - - Found a standalone namespace ( - - {namespace.name} - - ), but NOT a provider namespace. - - {is_superuser ? ' ' : null} - {is_superuser ? ( - - ) : null} - - ) : null} - - - ) : null; -}; - -export const RoleImportForm = ({ addAlert }: IProps) => { - const { queueAlert, user } = useHubContext(); - const navigate = useNavigate(); - const location = useLocation(); - const params = ParamHelper.parseParamString(location.search) as { - github_branch?: string; - github_repo?: string; - github_user?: string; - back?: string; - }; - const [data, setData] = useState<{ - alternate_namespace_name?: string; - alternate_role_name?: string; - github_reference?: string; - github_repo?: string; - github_user?: string; - }>({ - alternate_namespace_name: '', - alternate_role_name: '', - github_reference: params.github_branch || '', - github_repo: params.github_repo || '', - github_user: - params.github_user || (user.is_superuser ? '' : user.username) || '', - }); - const [errors, setErrors] = useState(null); - - const formFields = [ - { - id: 'github_user', - title: t`GitHub user`, - helper: ( - - ), - }, - { - id: 'github_repo', - title: t`GitHub repository`, - helper: - !data.github_repo || - data.github_repo.startsWith('ansible-role-') || - 'ansible-role-'.startsWith(data.github_repo) ? null : ( - - - {t`Did you mean ${`ansible-role-${data.github_repo}`}?`}{' '} - - - - ), - }, - { - id: 'github_reference', - title: t`GitHub ref (a commit, branch or tag)`, - placeholder: t`Automatic`, - }, - { - id: 'alternate_namespace_name', - title: t`Namespace name`, - placeholder: t`Overrides any galaxy_info.namespace metadata`, - }, - { - id: 'alternate_role_name', - title: t`Role name`, - placeholder: t`Overrides any galaxy_info.role_name metadata`, - }, - ]; - - const requiredFields = ['github_user', 'github_repo']; - - const nonempty = (o) => - Object.fromEntries(Object.entries(o).filter(([_k, v]) => v)); - - const onCancel = () => - navigate(params.back || formatPath(Paths.standaloneRoles)); - - const onSaved = ({ - data: { - results: [{ pulp_id }], - }, - }) => { - // the role import_log tab is not available before the role gets imported, go to list - // TODO waitForTask (needs galaxy_ng#2012) and go to my role imports to see the import - queueAlert(taskAlert(pulp_id, t`Import started`)); - navigate(params.back || formatPath(Paths.standaloneRoles)); - }; - - const onSave = () => - LegacyImportAPI.import(nonempty(data)) - .then(onSaved) - .catch(handleHttpError(t`Failed to import role`, null, addAlert)); - - const link = - data.github_user && - data.github_repo && - `https://github.com/${data.github_user}/${data.github_repo}`; - - const anyErrors = - !!Object.keys(errors || {}).length || requiredFields.some((k) => !data[k]); - - const formSuffix = ( - <> - {link ? ( -
- - Will clone {link} - -
- ) : null} - - - - - - ); - - const updateField = (k, v) => { - if (k === 'github_user' && v.includes('github.com/')) { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const [_proto, _empty, _host, github_user, github_repo] = v.split('/'); - setData((data) => ({ - ...data, - github_user, - github_repo: github_repo.replace(/\.git$/, ''), - })); - } else if (k === 'github_user' && v.includes('/')) { - const [github_user, github_repo] = v.split('/'); - setData((data) => ({ - ...data, - github_user, - github_repo, - })); - } else { - setData((data) => ({ ...data, [k]: v })); - } - - setErrors((errors) => { - const e = { ...errors }; - delete e[k]; - if (k === 'github_user' && v.includes('/')) { - delete e.github_repo; - } - return e; - }); - - if (requiredFields.includes(k) && !v) { - setErrors((errors) => ({ ...errors, [k]: t`Field is required.` })); - } - }; - - return ( - updateField(e.target.id, v)} - onSave={onSave} - /> - ); -}; diff --git a/src/components/role-import-list.tsx b/src/components/role-import-list.tsx deleted file mode 100644 index e65b9b9..0000000 --- a/src/components/role-import-list.tsx +++ /dev/null @@ -1,200 +0,0 @@ -import { t } from '@lingui/macro'; -import cx from 'classnames'; -import React, { useEffect, useState } from 'react'; -import { LegacyImportAPI, type LegacyRoleImportDetailType } from 'src/api'; -import { - type AlertType, - DateComponent, - EmptyStateFilter, - EmptyStateNoData, - HubListToolbar, - HubPagination, - LoadingSpinner, -} from 'src/components'; -import { filterIsSet, handleHttpError } from 'src/utilities'; - -interface IProps { - addAlert: (alert: AlertType) => void; - params: { - page?: number; - page_size?: number; - role_id?: number; - sort?: string; - state?: string; - }; - selectImport: (item: LegacyRoleImportDetailType) => void; - selectedImport?: LegacyRoleImportDetailType; - updateParams: (params) => void; -} - -const StatusIcon = ({ state }: { state: string }) => ( - -); - -export function RoleImportList({ - addAlert, - params, - selectImport, - selectedImport, - updateParams, -}: IProps) { - const [count, setCount] = useState(0); - const [imports, setImports] = useState([]); - const [loading, setLoading] = useState(false); - - const query = () => { - setLoading(true); - LegacyImportAPI.list({ - page: 1, - page_size: 10, - sort: '-created', - ...params, - detail: true, - }) - .then(({ data: { count, results } }) => { - setImports(results); - setCount(count); - }) - .catch( - handleHttpError(t`Failed to list role imports`, () => null, addAlert), - ) - .finally(() => setLoading(false)); - }; - - useEffect(() => { - query(); - }, [params]); - - const statusMap = { - SUCCESS: t`Completed`, - FAILED: t`Failed`, - RUNNING: t`Running`, - WAITING: t`Waiting`, - }; - - return ( -
- - -
- {loading ? ( -
- -
- ) : !count && - filterIsSet(params, ['role_name', 'namespace_name', 'state']) ? ( - - ) : !count ? ( - - ) : ( -
- {imports.map((item) => ( -
selectImport(item)} - key={item.pulp_id} - className={cx({ - clickable: true, - 'list-container': true, - 'hub-c-toolbar__item-selected-item': - item.pulp_id === selectedImport?.pulp_id, - })} - data-cy={`RoleImportList-row-${item.role_id}`} - > -
- -
-
-
-
- - {item.summary_fields?.github_user}/ - {item.summary_fields?.github_repo} - {' '} -
-
- Status: {statusMap[item.state] || item.state}{' '} - {item.summary_fields?.task_messages?.at(-1)?.id ? ( - - ) : null} -
-
-
-
- ))} -
- )} -
- - {!loading && count ? ( - - ) : null} -
- ); -} diff --git a/src/components/role-item.tsx b/src/components/role-item.tsx deleted file mode 100644 index b5c8325..0000000 --- a/src/components/role-item.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import { Trans, t } from '@lingui/macro'; -import { - DataListCell, - DataListItem, - DataListItemCells, - DataListItemRow, -} from '@patternfly/react-core'; -import React from 'react'; -import { Link } from 'react-router-dom'; -import { type LegacyRoleDetailType } from 'src/api'; -import { - DateComponent, - DownloadCount, - LabelGroup, - Logo, - ProviderLink, - RoleRatings, - Tag, -} from 'src/components'; -import { Paths, formatPath } from 'src/paths'; -import { roleNamespaceInfo } from 'src/utilities'; -import './list-item.scss'; - -interface RoleProps { - role: LegacyRoleDetailType; - show_thumbnail?: boolean; -} - -export function RoleItem({ role, show_thumbnail }: RoleProps) { - const { - description, - modified, - name, - summary_fields: { namespace, versions, tags }, - } = role; - const latest = versions[0]; - - const role_url = formatPath(Paths.standaloneRole, { - namespace: namespace.name, - name, - }); - const release_date = latest?.release_date || modified; - const release_name = latest?.name || ''; - const provider = roleNamespaceInfo(role); - const cells = []; - - if (show_thumbnail) { - cells.push( - - - , - ); - } - - cells.push( - -
- - {namespace.name}.{name} - - -
-
{description}
-
- - {tags.map((tag, index) => ( - {tag} - ))} - -
-
, - ); - - cells.push( - -
- - Updated - -
-
{release_name}
-
- - -
-
, - ); - - return ( - - - - - - ); -} diff --git a/src/components/role-namespace-edit-modal.tsx b/src/components/role-namespace-edit-modal.tsx deleted file mode 100644 index 887c408..0000000 --- a/src/components/role-namespace-edit-modal.tsx +++ /dev/null @@ -1,171 +0,0 @@ -import { t } from '@lingui/macro'; -import { Button, Label, Modal } from '@patternfly/react-core'; -import { Table, Td } from '@patternfly/react-table'; -import React, { useEffect, useState } from 'react'; -import { Link } from 'react-router-dom'; -import { - LegacyNamespaceAPI, - type LegacyNamespaceListType, - NamespaceAPI, -} from 'src/api'; -import { - EmptyStateFilter, - EmptyStateNoData, - HubListToolbar, - LoadingSpinner, - RadioRow, - SortTable, -} from 'src/components'; -import { filterIsSet, handleHttpError, roleNamespaceInfo } from 'src/utilities'; - -interface IProps { - addAlert: (alert) => void; - closeAction: () => void; - namespace: LegacyNamespaceListType; -} - -export const RoleNamespaceEditModal = ({ - addAlert, - closeAction, - namespace, -}: IProps) => { - const finishAction = () => - LegacyNamespaceAPI.changeProvider(namespace.id, selected.id) - .then(() => { - closeAction(); - - addAlert({ - title: t`Successfully changed provider namespace.`, - variant: 'success', - }); - }) - .catch( - handleHttpError( - t`Failed to change provider namespace.`, - closeAction, - addAlert, - ), - ); - - const provider = roleNamespaceInfo(namespace); - - const [count, setCount] = useState(0); - const [items, setItems] = useState([]); - const [loading, setLoading] = useState(true); - const [params, setParams] = useState<{ keywords?: string }>({}); - const [selected, setSelected] = useState(null); - - const actions = [ - , - , - ]; - - useEffect(() => { - setLoading(true); - NamespaceAPI.list({ keywords: params.keywords || '', sort: 'name' }).then( - ({ - data: { - data, - meta: { count }, - }, - }) => { - setCount(count); - setItems(data); - setLoading(false); - }, - ); - }, [params.keywords]); - - return ( - - {t`Role namespace`}: {namespace.name} -
- {t`Current provider namespace`}:{' '} - {provider.url ? ( - {provider.name} - ) : ( - <>{t`None`} - )} -
- {t`Selected provider namespace`}:{' '} - {selected ? : <>{t`None`}} -
- setParams(newParams)} - /> - {loading ? ( - - ) : !count ? ( - filterIsSet(params, ['keywords']) ? ( - - ) : ( - - ) - ) : ( - - null} - options={{ - headers: [ - { title: '', type: 'none', id: 'radio' }, - { title: t`Name`, type: 'none', id: 'name' }, - { title: t`Description`, type: 'none', id: 'description' }, - { title: t`Access`, type: 'none', id: 'owners' }, - ], - }} - /> - {items.map(({ id, name, description, groups, users }) => ( - setSelected({ id, name })} - isDisabled={provider?.name === name} - > - - - - - ))} -
{name}{description} - {users.length ? ( - <> - {t`Users`}:{' '} - {users.map(({ name }) => name).join(', ')} - - ) : null} - {users.length && groups.length ?
: null} - {groups.length ? ( - <> - {t`Groups`}:{' '} - {groups.map(({ name }) => name).join(', ')} - - ) : null} -
- )} -
- ); -}; diff --git a/src/components/role-namespace-item.tsx b/src/components/role-namespace-item.tsx deleted file mode 100644 index 8051337..0000000 --- a/src/components/role-namespace-item.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import { t } from '@lingui/macro'; -import { - DataListCell, - DataListItem, - DataListItemCells, - DataListItemRow, -} from '@patternfly/react-core'; -import { DropdownItem } from '@patternfly/react-core/deprecated'; -import React from 'react'; -import { Link, useLocation, useNavigate } from 'react-router-dom'; -import { type LegacyNamespaceDetailType } from 'src/api'; -import { Logo, StatefulDropdown } from 'src/components'; -import { useHubContext } from 'src/loaders/app-context'; -import { Paths, formatPath } from 'src/paths'; -import './list-item.scss'; - -interface RoleNamespaceProps { - namespace: LegacyNamespaceDetailType; - openEditModal?: (namespace) => void; - openLightspeedModal?: (namespace) => void; -} - -export function RoleNamespaceItem({ - namespace, - openEditModal, - openLightspeedModal, -}: RoleNamespaceProps) { - const { - featureFlags: { ai_deny_index }, - user: { username, is_superuser }, - } = useHubContext(); - const location = useLocation(); - const navigate = useNavigate(); - const { id, avatar_url, name, summary_fields } = namespace; - - const namespace_url = formatPath(Paths.standaloneNamespace, { - namespaceid: id, - }); - - const cells = [ - - - , - -
- {name} -
-
, - ]; - - const isOwner = !!summary_fields.owners.find((n) => n.username == username); - const showLightspeed = ai_deny_index && (is_superuser || isOwner); - const canImport = is_superuser || isOwner; - - const dropdownItems = [ - showLightspeed && openLightspeedModal && ( - openLightspeedModal(namespace)} - >{t`Ansible Lightspeed settings`} - ), - is_superuser && openEditModal && ( - openEditModal(namespace)} - >{t`Change provider namespace`} - ), - canImport && ( - - navigate( - formatPath( - Paths.standaloneRoleImport, - {}, - { - github_user: namespace.name, - back: location.pathname, - }, - ), - ) - } - >{t`Import role`} - ), - ].filter(Boolean); - - if (dropdownItems.length) { - cells.push( - -
- -
-
, - ); - } - - return ( - - - - - - ); -} diff --git a/src/components/role-namespace-modal.tsx b/src/components/role-namespace-modal.tsx deleted file mode 100644 index 9dfd0fb..0000000 --- a/src/components/role-namespace-modal.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import { t } from '@lingui/macro'; -import { - Button, - Form, - FormGroup, - InputGroup, - InputGroupItem, - Modal, - ModalVariant, - TextInput, -} from '@patternfly/react-core'; -import React, { useState } from 'react'; -import { LegacyNamespaceAPI } from 'src/api'; -import { handleHttpError } from 'src/utilities'; - -interface IProps { - addAlert: (alert) => void; - onClose: () => void; - onSaved: () => void; -} - -export function RoleNamespaceModal({ addAlert, onClose, onSaved }: IProps) { - const [name, setName] = useState(''); - - const onSave = () => - LegacyNamespaceAPI.create({ name }) - .then(() => { - addAlert({ - title: t`Successfully created role namespace ${name}`, - variant: 'success', - }); - onSaved(); - }) - .catch( - handleHttpError(t`Failed to create role namespace`, onClose, addAlert), - ); - - return ( - - {t`Create`} - , - , - ]} - > -
{ - e.preventDefault(); - onSave(); - }} - > - - - - setName(val)} - /> - - - -
-
- ); -} diff --git a/src/components/role-sync-form.tsx b/src/components/role-sync-form.tsx deleted file mode 100644 index c75d9b4..0000000 --- a/src/components/role-sync-form.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import { Trans, t } from '@lingui/macro'; -import { ActionGroup, Button } from '@patternfly/react-core'; -import React, { useState } from 'react'; -import { useNavigate } from 'react-router-dom'; -import { LegacySyncAPI } from 'src/api'; -import { type AlertType, DataForm, ExternalLink } from 'src/components'; -import { Paths, formatPath } from 'src/paths'; -import { - type ErrorMessagesType, - handleHttpError, - taskAlert, -} from 'src/utilities'; - -interface IProps { - addAlert: (alert: AlertType) => void; -} - -export const RoleSyncForm = ({ addAlert }: IProps) => { - const [data, setData] = useState<{ - github_user: string; - role_name: string; - }>({ github_user: '', role_name: '' }); - const [errors, setErrors] = useState(null); - const navigate = useNavigate(); - - const formFields = [ - { id: 'github_user', title: t`GitHub user` }, - { id: 'role_name', title: t`Role name` }, - ]; - - const requiredFields = ['github_user', 'role_name']; - - const onCancel = () => navigate(formatPath(Paths.standaloneRoles)); - - const onSaved = ({ data: { pulp_id } }) => - addAlert(taskAlert(pulp_id, t`Sync started`)); - - const onSave = () => - LegacySyncAPI.sync(data) - .then(onSaved) - .catch(handleHttpError(t`Failed to sync role`, null, addAlert)); - - const link = - data.github_user && - data.role_name && - `https://galaxy.ansible.com/ui/standalone/roles/${data.github_user}/${data.role_name}/`; - - const anyErrors = - !!Object.keys(errors || {}).length || requiredFields.some((k) => !data[k]); - - const formSuffix = ( - <> - {link ? ( -
- - Will sync {link} - -
- ) : null} - - - - - - ); - - const updateField = (k, v) => { - if (k === 'github_user' && v.includes('.')) { - const [github_user, role_name] = v.split('.'); - setData((data) => ({ - ...data, - github_user, - role_name, - })); - } else { - setData((data) => ({ ...data, [k]: v })); - } - - setErrors((errors) => { - const e = { ...errors }; - delete e[k]; - if (k === 'github_user' && v.includes('.')) { - delete e.role_name; - } - return e; - }); - - if (requiredFields.includes(k) && !v) { - setErrors((errors) => ({ ...errors, [k]: t`Field is required.` })); - } - }; - - return ( - updateField(e.target.id, v)} - onSave={onSave} - /> - ); -}; diff --git a/src/containers/ansible-role/imports.tsx b/src/containers/ansible-role/imports.tsx deleted file mode 100644 index 4104cc2..0000000 --- a/src/containers/ansible-role/imports.tsx +++ /dev/null @@ -1,230 +0,0 @@ -import { t } from '@lingui/macro'; -import React, { - Component, - type RefObject, - createRef, - useEffect, - useState, -} from 'react'; -import { Link } from 'react-router-dom'; -import { - LegacyImportAPI, - LegacyRoleAPI, - type LegacyRoleImportDetailType, -} from 'src/api'; -import { - AlertList, - type AlertType, - BaseHeader, - ImportConsole, - Main, - RoleImportList, - closeAlert, -} from 'src/components'; -import { Paths, formatPath } from 'src/paths'; -import { ParamHelper, type RouteProps, withRouter } from 'src/utilities'; - -interface IState { - alerts: AlertType[]; - error; - followLogs: boolean; - params; - role; - selectedImport: LegacyRoleImportDetailType; -} - -const RoleLink = ({ role_id }: { role_id?: number }) => { - const [role, setRole] = useState(null); - - useEffect(() => { - if (!role_id) { - setRole(null); - return; - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - LegacyRoleAPI.get(role_id as any).then( - ({ - data: { - name, - summary_fields: { - namespace: { name: namespace }, - }, - }, - }) => setRole({ namespace, name }), - ); - }, [role_id]); - - if (!role) { - return null; - } - - const { namespace, name } = role; - - return ( -
- {!role ? ( - `${namespace}.${name}` - ) : ( - - {namespace}.{name} - - )} -
- ); -}; - -class AnsibleRoleImports extends Component { - polling: ReturnType; - topOfPage: RefObject; - - constructor(props) { - super(props); - - const params = ParamHelper.parseParamString(props.location.search, [ - 'page', - 'page_size', - ]); - - this.topOfPage = createRef(); - - this.state = { - alerts: [], - error: null, - followLogs: false, - params, - role: null, - selectedImport: null, - }; - } - - componentDidMount() { - this.polling = setInterval(() => { - this.loadTaskDetails(); - }, 10000); - } - - componentWillUnmount() { - clearInterval(this.polling); - } - - private addAlert(alert) { - this.setState({ - alerts: [...this.state.alerts, alert], - }); - } - - render() { - const { alerts, error, followLogs, params, selectedImport } = this.state; - - return ( - <> -
- - - closeAlert(i, { - alerts, - setAlerts: (alerts) => this.setState({ alerts }), - }) - } - /> -
-
-
-
- this.addAlert(alert)} - params={params} - selectImport={(s) => this.selectImport(s)} - selectedImport={selectedImport} - updateParams={(params) => this.updateParams(params)} - /> -
- -
- - - - this.setState({ followLogs }) - } - /> -
-
-
-
- - ); - } - - private updateParams(params, callback = null) { - ParamHelper.updateParams({ - params, - navigate: (to) => this.props.navigate(to), - setState: (state) => this.setState(state, callback), - }); - } - - private selectImport(selectedImport) { - this.setState({ selectedImport }, () => this.loadTaskDetails()); - window.requestAnimationFrame(() => - this.topOfPage.current?.scrollIntoView({ behavior: 'smooth' }), - ); - } - - private loadTaskDetails() { - const { selectedImport } = this.state; - - if (!selectedImport) { - return null; - } - - if (!['RUNNING', 'WAITING'].includes(selectedImport.state)) { - return; - } - - this.setState({ error: null }); - return LegacyImportAPI.list({ - detail: true, - page_size: 1, - role_id: selectedImport.role_id, - sort: '-created', - }) - .then( - ({ - data: { - results: [first], - }, - }) => - this.setState({ - error: null, - selectedImport: first || selectedImport, - }), - ) - .catch(() => - this.setState({ - error: t`Error fetching import from API`, - selectedImport: null, - }), - ); - } -} - -export default withRouter(AnsibleRoleImports); diff --git a/src/containers/ansible-role/namespace-detail.tsx b/src/containers/ansible-role/namespace-detail.tsx deleted file mode 100644 index 0ec9e2d..0000000 --- a/src/containers/ansible-role/namespace-detail.tsx +++ /dev/null @@ -1,408 +0,0 @@ -import { t } from '@lingui/macro'; -import { DataList } from '@patternfly/react-core'; -import { DropdownItem } from '@patternfly/react-core/deprecated'; -import React, { Component } from 'react'; -import { Link } from 'react-router-dom'; -import { - LegacyNamespaceAPI, - type LegacyNamespaceListType, - LegacyRoleAPI, - type LegacyRoleListType, - TagAPI, -} from 'src/api'; -import { - AlertList, - type AlertType, - BaseHeader, - EmptyStateFilter, - EmptyStateNoData, - HubListToolbar, - HubPagination, - LightspeedModal, - LoadingSpinner, - Logo, - ProviderLink, - RoleItem, - RoleNamespaceEditModal, - StatefulDropdown, - closeAlert, -} from 'src/components'; -import { NotFound } from 'src/containers/not-found/not-found'; -import { AppContext, type IAppContextType } from 'src/loaders/app-context'; -import { Paths, formatPath } from 'src/paths'; -import { - ParamHelper, - type RouteProps, - filterIsSet, - handleHttpError, - roleNamespaceInfo, - withRouter, -} from 'src/utilities'; - -interface NamespaceRolesProps { - addAlert: (alert: AlertType) => void; - location: RouteProps['location']; - namespace: LegacyNamespaceListType; - navigate: RouteProps['navigate']; -} - -interface NamespaceRolesState { - count: number; - loading: boolean; - params: { - keywords?: string; - page?: number; - page_size?: number; - sort?: string; - tags?: string[]; - }; - roles: LegacyRoleListType[]; -} - -class NamespaceRoles extends Component< - NamespaceRolesProps, - NamespaceRolesState -> { - // This is the list of roles that is shown on - // the legacy namespace details page. - - constructor(props) { - super(props); - - const params = ParamHelper.parseParamString(props.location.search, [ - 'page', - 'page_size', - ]); - - this.state = { - count: 0, - loading: true, - params: { - page: 1, - page_size: 10, - sort: '-created', - ...params, - }, - roles: [], - }; - } - - componentDidMount() { - this.query(this.state.params); - } - - query(params) { - const { addAlert, namespace } = this.props; - - this.setState({ loading: true }); - LegacyRoleAPI.list({ - ...params, - namespace: namespace.name, - }) - .then(({ data: { count, results } }) => - this.setState({ - count, - loading: false, - roles: results, - }), - ) - .catch( - handleHttpError( - t`Failed to load roles`, - () => this.setState({ loading: false }), - addAlert, - ), - ); - } - - loadTags(inputText) { - return TagAPI.listRoles({ name__icontains: inputText, sort: '-count' }) - .then(({ data: { data } }) => - data.map(({ name, count }) => ({ - id: name, - title: count === undefined ? name : t`${name} (${count})`, - })), - ) - .catch(() => []); - } - - private updateParams(params, callback = null) { - ParamHelper.updateParams({ - params, - navigate: (to) => this.props.navigate(to), - setState: (state) => this.setState(state, callback), - }); - } - - render() { - const { count, loading, params, roles } = this.state; - - const updateParams = (params) => - this.updateParams(params, () => this.query(params)); - - const filterConfig = [ - { - id: 'keywords', - title: t`Keywords`, - }, - { - id: 'tags', - title: t`Tags`, - inputType: 'typeahead' as const, - // options handled by `typeaheads` - }, - ]; - - const sortOptions = [ - { title: t`Name`, id: 'name', type: 'alpha' as const }, - { - title: t`Download count`, - id: 'download_count', - type: 'numeric' as const, - }, - { - title: t`Created`, - id: 'created', - type: 'numeric' as const, - }, - ]; - - const noData = - count === 0 && - !filterIsSet( - params, - filterConfig.map(({ id }) => id), - ); - - return ( -
- {loading ? ( - - ) : noData ? ( - - ) : ( -
- - {!count ? ( - - ) : ( -
- - {roles && - roles.map((lrole) => ( - - ))} - - - -
- )} -
- )} -
- ); - } -} - -interface RoleNamespaceState { - alerts: AlertType[]; - editModal: boolean; - lightspeedModal: boolean; - loading: boolean; - namespace: LegacyNamespaceListType; -} - -class AnsibleRoleNamespaceDetail extends Component< - RouteProps, - RoleNamespaceState -> { - static contextType = AppContext; - - // This is the details page for a standalone namespace - - constructor(props) { - super(props); - - this.state = { - alerts: [], - editModal: false, - lightspeedModal: false, - loading: true, - namespace: null, - }; - } - - private addAlert(alert: AlertType) { - this.setState({ - alerts: [...this.state.alerts, alert], - }); - } - - componentDidMount() { - LegacyNamespaceAPI.get(this.props.routeParams.namespaceid) - .then((response) => - this.setState({ - loading: false, - namespace: response.data, - }), - ) - .catch( - handleHttpError( - t`Failed to load role namespace`, - () => this.setState({ loading: false }), - (alert) => this.addAlert(alert), - ), - ); - } - - render() { - const { alerts, editModal, lightspeedModal, loading, namespace } = - this.state; - const { - featureFlags: { ai_deny_index }, - user: { is_superuser, username }, - } = this.context as IAppContextType; - const { location, navigate } = this.props; - - if (loading) { - return ; - } - - if (!namespace) { - return ( - <> - - closeAlert(i, { - alerts, - setAlerts: (alerts) => this.setState({ alerts }), - }) - } - /> - - - ); - } - - const namespace_url = formatPath(Paths.standaloneNamespace, { - namespaceid: namespace.id, - }); - - const provider = roleNamespaceInfo(namespace); - - const userOwnsLegacyNamespace = !!namespace.summary_fields?.owners?.find( - (n) => n.username == username, - ); - const showLightspeed = - ai_deny_index && (is_superuser || userOwnsLegacyNamespace); - const canImport = is_superuser || userOwnsLegacyNamespace; - - const dropdownItems = [ - showLightspeed && ( - this.setState({ lightspeedModal: true })} - >{t`Ansible Lightspeed settings`} - ), - is_superuser && ( - this.setState({ editModal: true })} - >{t`Change provider namespace`} - ), - canImport && ( - - navigate( - formatPath( - Paths.standaloneRoleImport, - {}, - { - github_user: namespace.name, - back: location.pathname, - }, - ), - ) - } - >{t`Import role`} - ), - ].filter(Boolean); - - return ( - <> - - closeAlert(i, { - alerts, - setAlerts: (alerts) => this.setState({ alerts }), - }) - } - /> - - - {namespace.name} - - - } - title={namespace.name} - pageControls={ - dropdownItems.length && ( -
- -
- ) - } - /> - - {lightspeedModal && ( - this.addAlert(alert)} - closeAction={() => this.setState({ lightspeedModal: false })} - reference={namespace.name} - scope={'legacy_namespace'} - /> - )} - {editModal && ( - this.addAlert(alert)} - closeAction={() => this.setState({ editModal: false })} - namespace={namespace} - /> - )} - - this.addAlert(alert)} - namespace={namespace} - location={location} - navigate={navigate} - /> - - ); - } -} - -export default withRouter(AnsibleRoleNamespaceDetail); diff --git a/src/containers/ansible-role/namespace-list.tsx b/src/containers/ansible-role/namespace-list.tsx deleted file mode 100644 index 850fd9c..0000000 --- a/src/containers/ansible-role/namespace-list.tsx +++ /dev/null @@ -1,255 +0,0 @@ -import { t } from '@lingui/macro'; -import { Button, DataList } from '@patternfly/react-core'; -import React, { Component } from 'react'; -import { LegacyNamespaceAPI, type LegacyNamespaceListType } from 'src/api'; -import { - AlertList, - type AlertType, - BaseHeader, - EmptyStateFilter, - EmptyStateNoData, - HubListToolbar, - HubPagination, - LightspeedModal, - LoadingSpinner, - RoleNamespaceEditModal, - RoleNamespaceItem, - RoleNamespaceModal, - closeAlert, -} from 'src/components'; -import { AppContext, type IAppContextType } from 'src/loaders/app-context'; -import { - ParamHelper, - type RouteProps, - filterIsSet, - handleHttpError, - withRouter, -} from 'src/utilities'; - -interface RoleNamespacesState { - alerts: AlertType[]; - createModal?: boolean; - count: number; - editModal?: LegacyNamespaceListType; - lightspeedModal?: string; - loading: boolean; - params: { - page?: number; - page_size?: number; - sort?: string; - }; - roleNamespaces: LegacyNamespaceListType[]; -} - -class AnsibleRoleNamespaceList extends Component< - RouteProps, - RoleNamespacesState -> { - static contextType = AppContext; - - constructor(props) { - super(props); - - const params = ParamHelper.parseParamString(props.location.search, [ - 'page', - 'page_size', - ]); - - this.state = { - alerts: [], - count: 0, - createModal: false, - editModal: null, - lightspeedModal: null, - loading: true, - params: { - page: 1, - page_size: 10, - sort: '-created', - ...params, - }, - roleNamespaces: [], - }; - } - - componentDidMount() { - this.setState({ alerts: (this.context as IAppContextType).alerts || [] }); - (this.context as IAppContextType).setAlerts([]); - - this.query(this.state.params); - } - - query(params) { - this.setState({ loading: true }); - LegacyNamespaceAPI.list(params) - .then(({ data: { count, results } }) => - this.setState({ - count, - loading: false, - roleNamespaces: results, - }), - ) - .catch( - handleHttpError( - t`Failed to load role namespaces`, - () => this.setState({ loading: false }), - (alert) => this.addAlert(alert), - ), - ); - } - - private updateParams(params, callback = null) { - ParamHelper.updateParams({ - params, - navigate: (to) => this.props.navigate(to), - setState: (state) => this.setState(state, callback), - }); - } - - private addAlert(alert: AlertType) { - this.setState({ - alerts: [...this.state.alerts, alert], - }); - } - - render() { - const updateParams = (params) => - this.updateParams(params, () => this.query(params)); - - const filterConfig = [ - { - id: 'keywords', - title: t`Keywords`, - }, - { id: 'provider', title: t`Provider`, hidden: true }, - ]; - - const sortOptions = [ - { title: t`Name`, id: 'name', type: 'alpha' as const }, - { - title: t`Created`, - id: 'created', - type: 'numeric' as const, - }, - ]; - - const { - alerts, - count, - createModal, - editModal, - lightspeedModal, - loading, - params, - roleNamespaces, - } = this.state; - - const { - user: { is_superuser: canCreate }, - } = this.context as IAppContextType; - - const noData = - count === 0 && - !filterIsSet( - params, - filterConfig.map(({ id }) => id), - ); - - return ( -
- - closeAlert(i, { - alerts, - setAlerts: (alerts) => this.setState({ alerts }), - }) - } - /> - {createModal && ( - this.addAlert(alert)} - onClose={() => this.setState({ createModal: false })} - onSaved={() => { - this.setState({ createModal: false }); - this.query(params); - }} - /> - )} - {lightspeedModal && ( - this.addAlert(alert)} - closeAction={() => this.setState({ lightspeedModal: null })} - reference={lightspeedModal} - scope={'legacy_namespace'} - /> - )} - {editModal && ( - this.addAlert(alert)} - closeAction={() => this.setState({ editModal: null })} - namespace={editModal} - /> - )} - - {loading ? ( - - ) : noData ? ( - - ) : ( -
- this.setState({ createModal: true })} - >{t`Create`} - ), - ].filter(Boolean)} - count={count} - filterConfig={filterConfig} - ignoredParams={['page', 'page_size', 'sort']} - params={params} - sortOptions={sortOptions} - updateParams={updateParams} - /> - - {!count ? ( - - ) : ( - <> - - {roleNamespaces && - roleNamespaces.map((lnamespace) => ( - - this.setState({ editModal: namespace }) - } - openLightspeedModal={({ name }) => - this.setState({ lightspeedModal: name }) - } - /> - ))} - - - - - )} -
- )} -
- ); - } -} - -export default withRouter(AnsibleRoleNamespaceList); diff --git a/src/containers/ansible-role/role-detail.tsx b/src/containers/ansible-role/role-detail.tsx deleted file mode 100644 index 7412296..0000000 --- a/src/containers/ansible-role/role-detail.tsx +++ /dev/null @@ -1,597 +0,0 @@ -import { Trans, t } from '@lingui/macro'; -import { - Button, - DataList, - DataListCell, - DataListItem, - DataListItemRow, - Nav, - NavItem, - Panel, -} from '@patternfly/react-core'; -import DownloadIcon from '@patternfly/react-icons/dist/esm/icons/download-icon'; -import React, { Component } from 'react'; -import { Link } from 'react-router-dom'; -import { - LegacyImportAPI, - LegacyNamespaceAPI, - type LegacyNamespaceDetailType, - LegacyRoleAPI, - type LegacyRoleDetailType, - type LegacyRoleImportDetailType, - type LegacyRoleVersionDetailType, -} from 'src/api'; -import { - AlertList, - type AlertType, - BaseHeader, - Breadcrumbs, - CopyURL, - DateComponent, - DownloadCount, - EmptyStateNoData, - ExternalLink, - ImportConsole, - LabelGroup, - LoadingPage, - Logo, - Main, - NavList, - RoleRatings, - Tag, - closeAlert, -} from 'src/components'; -import { NotFound } from 'src/containers/not-found/not-found'; -import { AppContext, type IAppContextType } from 'src/loaders/app-context'; -import { Paths, formatPath } from 'src/paths'; -import { type RouteProps, handleHttpError, withRouter } from 'src/utilities'; - -const DownloadLink = ({ href, text }: { href: string; text: string }) => ( - - {text} - -); - -interface RoleMetaProps { - addAlert: (alert: AlertType) => void; - name: string; - namespace: string; - role: LegacyRoleDetailType; -} - -interface RoleMetaReadmeState { - readme_html: string; -} - -const RoleInstall = ({ namespace, name }: RoleMetaProps) => ( - <> -

- Installation: -

- - -); - -class RoleDocs extends Component { - constructor(props) { - super(props); - this.state = { - readme_html: null, - }; - } - - componentDidMount() { - LegacyRoleAPI.getContent(this.props.role.id) - .then(({ data: { readme_html } }) => - this.setState({ - readme_html, - }), - ) - .catch( - handleHttpError( - t`Failed to load role content`, - () => null, - this.props.addAlert, - ), - ); - } - - render() { - return ( -
-
-
- ); - } -} - -interface RoleVersionProps { - role_version: LegacyRoleVersionDetailType; -} - -class RoleVersion extends Component { - render() { - return ( - - {this.props.role_version.name} - - - - Released - - - - {/* Release tarballs hosted on github */} - - - - - ); - } -} - -interface RoleVersionsState { - role_versions: LegacyRoleVersionDetailType[]; - loading: boolean; -} - -interface RoleVersionsProps extends RoleMetaProps { - repository: string; -} - -class RoleVersions extends Component { - constructor(props) { - super(props); - this.state = { - role_versions: [], - loading: true, - }; - } - - componentDidMount() { - LegacyRoleAPI.getVersions(this.props.role.id) - .then(({ data: { results } }) => - this.setState({ - role_versions: results, - loading: false, - }), - ) - .catch( - handleHttpError( - t`Failed to load role versions`, - () => this.setState({ loading: false }), - this.props.addAlert, - ), - ); - } - - render() { - const { - repository, - role: { github_branch }, - } = this.props; - const { loading, role_versions } = this.state; - - return ( -
- {!loading && role_versions && role_versions.length == 0 ? ( - - } - /> - ) : null} - - - {role_versions.reverse().map((rversion) => ( - - - - ))} - -
- ); - } -} - -interface RoleImportDetailProps { - addAlert: (alert: AlertType) => void; - role: LegacyRoleDetailType; -} - -interface RoleImportDetailState { - lastImport: LegacyRoleImportDetailType; - loading: boolean; -} - -class RoleImportLog extends Component< - RoleImportDetailProps, - RoleImportDetailState -> { - constructor(props) { - super(props); - this.state = { - loading: true, - lastImport: null, - }; - } - - componentDidMount() { - const { addAlert, role } = this.props; - this.setState({ loading: true, lastImport: null }); - - LegacyImportAPI.list({ - detail: true, - page_size: 1, - role_id: role.id, - sort: '-created', - state: 'SUCCESS', - }) - .then( - ({ - data: { - results: [lastImport], - }, - }) => - this.setState({ - lastImport, - loading: false, - }), - ) - .catch( - handleHttpError( - t`Failed to get import log`, - () => this.setState({ loading: false, lastImport: null }), - addAlert, - ), - ); - } - - render() { - const { role } = this.props; - const { lastImport, loading } = this.state; - - return ( - <> - {!loading && !lastImport ? ( - - ) : null} - - {lastImport && ( - - )} - - ); - } -} - -interface RoleState { - activeItem: string; - alerts: AlertType[]; - fullNamespace: LegacyNamespaceDetailType; - loading: boolean; - name: string; - namespace: string; - role: LegacyRoleDetailType; -} - -class AnsibleRoleDetail extends Component { - static contextType = AppContext; - - constructor(props) { - super(props); - - const { namespace, name, tab } = props.routeParams; - this.state = { - activeItem: tab || 'install', - alerts: [], - loading: true, - name, - namespace, - fullNamespace: null, - role: null, - }; - } - - componentDidMount() { - const { name, namespace } = this.state; - - LegacyRoleAPI.list({ - name, - namespace, - page_size: 1, - }) - .then( - ({ - data: { - results: [role], - }, - }) => { - this.setState({ role, loading: false }); - - const namespace = role?.summary_fields?.namespace; - if (namespace?.id) { - return LegacyNamespaceAPI.get(namespace.id).then( - ({ data: fullNamespace }) => this.setState({ fullNamespace }), - ); - } - }, - ) - .catch( - handleHttpError( - t`Failed to find role`, - () => this.setState({ loading: false }), - (alert) => this.addAlert(alert), - ), - ); - } - - private addAlert(alert: AlertType) { - this.setState({ - alerts: [...this.state.alerts, alert], - }); - } - - render() { - const { activeItem, alerts, fullNamespace, loading, name, role } = - this.state; - const { - user: { username, is_superuser }, - } = this.context as IAppContextType; - - if (loading) { - return ; - } - - if (!role) { - return ( - <> - - closeAlert(i, { - alerts, - setAlerts: (alerts) => this.setState({ alerts }), - }) - } - /> - - - ); - } - - const repository = - 'https://github.com/' + - encodeURIComponent(role.github_user) + - '/' + - encodeURIComponent(role.github_repo); - const namespace = role.summary_fields.namespace; - const namespace_url = formatPath(Paths.standaloneNamespace, { - namespaceid: namespace.id, - }); - let release_date = null; - let release_name = null; - const last_version = role.summary_fields.versions[0]; - if (last_version) { - release_date = last_version.release_date; - release_name = last_version.name; - } - if (!release_date) { - release_date = role.modified; - } - if (!release_name) { - release_name = ''; - } - - const tabs = { - install: t`Install`, - documentation: t`Documentation`, - versions: t`Versions`, - import_log: t`Import log`, - }; - - const addAlert = (alert) => this.addAlert(alert); - - const renderContent = () => { - if (activeItem == 'install') { - return ( - - ); - } else if (activeItem === 'documentation') { - return ( - - ); - } else if (activeItem === 'versions') { - return ( - - ); - } else if (activeItem === 'import_log') { - return ; - } else { - return
; - } - }; - - const breadcrumbs = [ - { - name: t`Roles`, - url: formatPath(Paths.standaloneRoles), - }, - { - name: namespace.name, - url: formatPath(Paths.standaloneNamespace, { - namespaceid: namespace.id, - }), - }, - { - name, - url: formatPath(Paths.standaloneRole, { - namespace: namespace.name, - name, - }), - }, - { name: tabs[activeItem || 'install'] }, - ]; - - const onTabSelect = (newTab) => { - this.setState({ activeItem: newTab }); - - this.props.navigate( - formatPath(Paths.standaloneRole, { - namespace: namespace.name, - name, - tab: newTab, - }), - ); - }; - - const canImport = - is_superuser || - !!fullNamespace?.summary_fields?.owners?.find( - (n) => n.username == username, - ); - - return ( - <> - - closeAlert(i, { - alerts, - setAlerts: (alerts) => this.setState({ alerts }), - }) - } - /> - } - title={`${namespace.name}.${role.name}`} - subTitle={ - <> -
{role.description}
-
- - {role.summary_fields.tags.map((tag, index) => ( - {tag} - ))} - -
- - } - logo={ - - - {namespace.name} - - } - pageControls={ -
-
- - Updated - -
- {release_name &&
{release_name}
} -
- {t`GitHub Repository`} -
-
- - -
- {canImport && ( - - )} -
- } - > - {/* FIXME: replace with LinkTabs */} - - - -
- -
-
{renderContent()}
-
- - ); - } -} - -export default withRouter(AnsibleRoleDetail); diff --git a/src/containers/ansible-role/role-import.tsx b/src/containers/ansible-role/role-import.tsx deleted file mode 100644 index 9d8b2f5..0000000 --- a/src/containers/ansible-role/role-import.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import { t } from '@lingui/macro'; -import React, { Component } from 'react'; -import { - AlertList, - type AlertType, - BaseHeader, - Main, - RoleImportForm, - closeAlert, -} from 'src/components'; -import { type RouteProps, withRouter } from 'src/utilities'; - -interface RoleState { - alerts: AlertType[]; -} - -class AnsibleRoleImport extends Component { - constructor(props) { - super(props); - this.state = { - alerts: [], - }; - } - - private addAlert(alert: AlertType) { - this.setState({ - alerts: [...this.state.alerts, alert], - }); - } - - render() { - const { alerts } = this.state; - const addAlert = (alert) => this.addAlert(alert); - - return ( - <> - - closeAlert(i, { - alerts, - setAlerts: (alerts) => this.setState({ alerts }), - }) - } - /> - -
-
- -
-
- - ); - } -} - -export default withRouter(AnsibleRoleImport); diff --git a/src/containers/ansible-role/role-list.tsx b/src/containers/ansible-role/role-list.tsx deleted file mode 100644 index 1ae9571..0000000 --- a/src/containers/ansible-role/role-list.tsx +++ /dev/null @@ -1,239 +0,0 @@ -import { t } from '@lingui/macro'; -import { Button, DataList } from '@patternfly/react-core'; -import React, { Component } from 'react'; -import { LegacyRoleAPI, type LegacyRoleListType, TagAPI } from 'src/api'; -import { - AlertList, - type AlertType, - BaseHeader, - EmptyStateFilter, - EmptyStateNoData, - HubListToolbar, - HubPagination, - LoadingSpinner, - RoleItem, - closeAlert, -} from 'src/components'; -import { AppContext, type IAppContextType } from 'src/loaders/app-context'; -import { Paths, formatPath } from 'src/paths'; -import { - ParamHelper, - type RouteProps, - filterIsSet, - handleHttpError, - withRouter, -} from 'src/utilities'; - -interface RolesState { - alerts: AlertType[]; - count: number; - loading: boolean; - params: { - page?: number; - page_size?: number; - sort?: string; - }; - roles: LegacyRoleListType[]; -} - -class AnsibleRoleList extends Component { - static contextType = AppContext; - - constructor(props) { - super(props); - - const params = ParamHelper.parseParamString(props.location.search, [ - 'page', - 'page_size', - ]); - - this.state = { - alerts: [], - count: 0, - loading: true, - params: { - page: 1, - page_size: 10, - sort: '-created', - ...params, - }, - roles: [], - }; - } - - componentDidMount() { - this.setState({ alerts: (this.context as IAppContextType).alerts || [] }); - (this.context as IAppContextType).setAlerts([]); - - this.query(this.state.params); - } - - query(params) { - this.setState({ loading: true }); - LegacyRoleAPI.list(params) - .then(({ data: { count, results } }) => - this.setState({ - count, - loading: false, - roles: results, - }), - ) - .catch( - handleHttpError( - t`Failed to load roles`, - () => this.setState({ loading: false }), - (alert) => this.addAlert(alert), - ), - ); - } - - loadTags(inputText) { - return TagAPI.listRoles({ name__icontains: inputText, sort: '-count' }) - .then(({ data: { data } }) => - data.map(({ name, count }) => ({ - id: name, - title: count === undefined ? name : t`${name} (${count})`, - })), - ) - .catch(() => []); - } - - private updateParams(params, callback = null) { - ParamHelper.updateParams({ - params, - navigate: (to) => this.props.navigate(to), - setState: (state) => this.setState(state, callback), - }); - } - - private addAlert(alert: AlertType) { - this.setState({ - alerts: [...this.state.alerts, alert], - }); - } - - render() { - const { alerts, count, loading, params, roles } = this.state; - const { user } = this.context as IAppContextType; - - const updateParams = (params) => - this.updateParams(params, () => this.query(params)); - - const filterConfig = [ - { - id: 'keywords', - title: t`Keywords`, - }, - { - id: 'namespace', - title: t`Namespace`, - }, - { - id: 'tags', - title: t`Tags`, - inputType: 'typeahead' as const, - // options handled by `typeaheads` - }, - ]; - - const sortOptions = [ - { title: t`Name`, id: 'name', type: 'alpha' as const }, - { - title: t`Download count`, - id: 'download_count', - type: 'numeric' as const, - }, - { - title: t`Created`, - id: 'created', - type: 'numeric' as const, - }, - ]; - - const noData = - count === 0 && - !filterIsSet( - params, - filterConfig.map(({ id }) => id), - ); - - const canImport = user && !user.is_anonymous; - const canSync = user?.is_superuser && !IS_COMMUNITY; - - return ( -
- - closeAlert(i, { - alerts, - setAlerts: (alerts) => this.setState({ alerts }), - }) - } - /> - - {loading ? ( - - ) : noData ? ( - - ) : ( -
- - this.props.navigate( - formatPath(Paths.standaloneRoleImport), - ) - } - >{t`Import role`} - ), - canSync && ( - - ), - ].filter(Boolean)} - count={count} - filterConfig={filterConfig} - ignoredParams={['page', 'page_size', 'sort']} - params={params} - sortOptions={sortOptions} - typeaheads={{ tags: this.loadTags }} - updateParams={updateParams} - /> - - {!count ? ( - - ) : ( - <> - - {roles && - roles.map((lrole) => ( - - ))} - - - - - )} -
- )} -
- ); - } -} - -export default withRouter(AnsibleRoleList); diff --git a/src/containers/ansible-role/role-sync.tsx b/src/containers/ansible-role/role-sync.tsx deleted file mode 100644 index b70bf78..0000000 --- a/src/containers/ansible-role/role-sync.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import { t } from '@lingui/macro'; -import React, { Component } from 'react'; -import { - AlertList, - type AlertType, - BaseHeader, - Main, - RoleSyncForm, - closeAlert, -} from 'src/components'; -import { type RouteProps, withRouter } from 'src/utilities'; - -interface RoleState { - alerts: AlertType[]; -} - -class AnsibleRoleSync extends Component { - constructor(props) { - super(props); - this.state = { - alerts: [], - }; - } - - private addAlert(alert: AlertType) { - this.setState({ - alerts: [...this.state.alerts, alert], - }); - } - - render() { - const { alerts } = this.state; - const addAlert = (alert) => this.addAlert(alert); - - return ( - <> - - closeAlert(i, { - alerts, - setAlerts: (alerts) => this.setState({ alerts }), - }) - } - /> - -
-
- -
-
- - ); - } -} - -export default withRouter(AnsibleRoleSync); diff --git a/src/containers/collection-detail/collection-content.tsx b/src/containers/collection-detail/collection-content.tsx index 6345720..b38a494 100644 --- a/src/containers/collection-detail/collection-content.tsx +++ b/src/containers/collection-detail/collection-content.tsx @@ -7,7 +7,7 @@ import { Main, } from 'src/components'; import { AppContext } from 'src/loaders/app-context'; -import { Paths, formatPath, namespaceBreadcrumb } from 'src/paths'; +import { Paths, formatPath } from 'src/paths'; import { ParamHelper, type RouteProps, withRouter } from 'src/utilities'; import { type IBaseCollectionState, loadCollection } from './base'; @@ -51,7 +51,7 @@ class CollectionContent extends Component { const { collection_version, repository } = collection; const breadcrumbs = [ - namespaceBreadcrumb(), + { name: t`Namespaces`, url: formatPath(Paths.namespaces) }, { url: formatPath(Paths.namespaceDetail, { namespace: collection_version.namespace, diff --git a/src/containers/collection-detail/collection-dependencies.tsx b/src/containers/collection-detail/collection-dependencies.tsx index 9cb2cda..230fc4b 100644 --- a/src/containers/collection-detail/collection-dependencies.tsx +++ b/src/containers/collection-detail/collection-dependencies.tsx @@ -17,7 +17,7 @@ import { closeAlert, } from 'src/components'; import { AppContext } from 'src/loaders/app-context'; -import { Paths, formatPath, namespaceBreadcrumb } from 'src/paths'; +import { Paths, formatPath } from 'src/paths'; import { ParamHelper, type RouteProps, @@ -96,7 +96,7 @@ class CollectionDependencies extends Component { const { collection_version: version, repository } = collection; const breadcrumbs = [ - namespaceBreadcrumb(), + { name: t`Namespaces`, url: formatPath(Paths.namespaces) }, { url: formatPath(Paths.namespaceDetail, { namespace: version.namespace, diff --git a/src/containers/collection-detail/collection-detail.tsx b/src/containers/collection-detail/collection-detail.tsx index eb22fd5..f4207e6 100644 --- a/src/containers/collection-detail/collection-detail.tsx +++ b/src/containers/collection-detail/collection-detail.tsx @@ -1,3 +1,4 @@ +import { t } from '@lingui/macro'; import { isEqual } from 'lodash'; import React, { Component } from 'react'; import { @@ -9,7 +10,7 @@ import { closeAlert, } from 'src/components'; import { AppContext } from 'src/loaders/app-context'; -import { Paths, formatPath, namespaceBreadcrumb } from 'src/paths'; +import { Paths, formatPath } from 'src/paths'; import { ParamHelper, type RouteProps, withRouter } from 'src/utilities'; import { type IBaseCollectionState, loadCollection } from './base'; @@ -62,7 +63,7 @@ class CollectionDetail extends Component { const { collection_version: version } = collection; const breadcrumbs = [ - namespaceBreadcrumb(), + { name: t`Namespaces`, url: formatPath(Paths.namespaces) }, { url: formatPath(Paths.namespaceDetail, { namespace: version.namespace, diff --git a/src/containers/collection-detail/collection-distributions.tsx b/src/containers/collection-detail/collection-distributions.tsx index bc22fea..bff0582 100644 --- a/src/containers/collection-detail/collection-distributions.tsx +++ b/src/containers/collection-detail/collection-distributions.tsx @@ -17,7 +17,7 @@ import { Main, SortTable, } from 'src/components'; -import { Paths, formatPath, namespaceBreadcrumb } from 'src/paths'; +import { Paths, formatPath } from 'src/paths'; import { ParamHelper, type RouteProps, @@ -98,7 +98,7 @@ const CollectionDistributions = (props: RouteProps) => { const { collection_version, repository } = collection; const breadcrumbs = [ - namespaceBreadcrumb(), + { name: t`Namespaces`, url: formatPath(Paths.namespaces) }, { url: formatPath(Paths.namespaceDetail, { namespace: collection_version.namespace, diff --git a/src/containers/collection-detail/collection-docs.tsx b/src/containers/collection-detail/collection-docs.tsx index cdc4c2c..e6d3122 100644 --- a/src/containers/collection-detail/collection-docs.tsx +++ b/src/containers/collection-detail/collection-docs.tsx @@ -16,7 +16,7 @@ import { TableOfContents, } from 'src/components'; import { AppContext } from 'src/loaders/app-context'; -import { Paths, formatPath, namespaceBreadcrumb } from 'src/paths'; +import { Paths, formatPath } from 'src/paths'; import { ParamHelper, type RouteProps, withRouter } from 'src/utilities'; import { type IBaseCollectionState, loadCollection } from './base'; import './collection-detail.scss'; @@ -106,7 +106,7 @@ class CollectionDocs extends Component { const { collection_version, repository } = collection; const breadcrumbs = [ - namespaceBreadcrumb(), + { name: t`Namespaces`, url: formatPath(Paths.namespaces) }, { url: formatPath(Paths.namespaceDetail, { namespace: collection_version.namespace, diff --git a/src/containers/collection-detail/collection-import-log.tsx b/src/containers/collection-detail/collection-import-log.tsx index fc1da68..dda7a26 100644 --- a/src/containers/collection-detail/collection-import-log.tsx +++ b/src/containers/collection-detail/collection-import-log.tsx @@ -8,7 +8,7 @@ import { Main, } from 'src/components'; import { AppContext } from 'src/loaders/app-context'; -import { Paths, formatPath, namespaceBreadcrumb } from 'src/paths'; +import { Paths, formatPath } from 'src/paths'; import { ParamHelper, type RouteProps, withRouter } from 'src/utilities'; import { type IBaseCollectionState, loadCollection } from './base'; @@ -66,7 +66,7 @@ class CollectionImportLog extends Component { const { collection_version, repository } = collection; const breadcrumbs = [ - namespaceBreadcrumb(), + { name: t`Namespaces`, url: formatPath(Paths.namespaces) }, { url: formatPath(Paths.namespaceDetail, { namespace: collection_version.namespace, diff --git a/src/containers/edit-namespace/edit-namespace.tsx b/src/containers/edit-namespace/edit-namespace.tsx index e9f6ebd..859e69f 100644 --- a/src/containers/edit-namespace/edit-namespace.tsx +++ b/src/containers/edit-namespace/edit-namespace.tsx @@ -22,7 +22,7 @@ import { validateURL, } from 'src/components'; import { AppContext, type IAppContextType } from 'src/loaders/app-context'; -import { Paths, formatPath, namespaceBreadcrumb } from 'src/paths'; +import { Paths, formatPath } from 'src/paths'; import { type ErrorMessagesType, ParamHelper, @@ -144,7 +144,7 @@ class EditNamespace extends Component { { content={ item.is_indexable ? t`Find execution environments in this registry` - : t`Indexing execution environments is only supported on registry.redhat.io` + : t`Indexing execution environments is not supported` } > { - constructor(props) { - super(props); - - this.state = { - alerts: [], - redirect: false, - }; - } - - componentDidMount() { - if (!IS_COMMUNITY) { - this.setState({ redirect: true }); - } - } - - render() { - const { alerts, redirect } = this.state; - - if (redirect) { - setTimeout(() => this.props.navigate(formatPath(Paths.collections))); - return null; - } - - return ( - <> - - closeAlert(i, { - alerts, - setAlerts: (alerts) => this.setState({ alerts }), - }) - } - /> - -
- - this.props.navigate(formatPath(Paths.search, {}, { keywords })) - } - style={{ marginBottom: '16px' }} - /> - -
- - =2.13.9`} - > - {t`Please, check it running the command:`}{' '} - ansible --version - -
-

{t`Jump-start your automation project with great content from the Ansible community. Galaxy provides pre-packaged units of work known to Ansible as roles and collections.`}

-
-

- {t`Content from roles and collections can be referenced in Ansible playbooks and immediately put to work. You'll find content for provisioning infrastructure, deploying applications, and all of the tasks you do everyday.`}{' '} -

-
-

- - Use the{' '} - Search page - to find content for your project, then download them onto - your Ansible host using{' '} - - ansible-galaxy - - , the command line tool that comes bundled with Ansible. - -

- - } - /> - -

{t`Help other Ansible users by sharing the awesome roles and collections you create.`}

-
-

{t`Maybe you have automation for installing and configuring a popular software package, or for deploying software built by your company. Whatever it is, use Galaxy to share it with the community.`}

-
- -

- - Red Hat is working on exciting new Ansible content - development capabilities within the context of{' '} - - Ansible Lightspeed - {' '} - to help other automators build Ansible content. Your roles - and collections may be used as training data for a machine - learning model that provides Ansible automation content - recommendations. If you have concerns, please contact the - Ansible team at{' '} - - ansible-content-ai@redhat.com - - -

- - } - /> - - -

{t`Ansible Lightspeed`}

-
-
-

- - Generative Ai, The Ansible way. Try Ansible Lightspeed with IBM watsonx Code Assistant - -

-
-

- - {t`Extend the power of Ansible to your entire team.`}{' '} - -

-
-

{t`Try Red Hat Ansible Automation Platform`}

-
-

- {t`Get the trial`} -

- - } - /> - - - {t`Privacy statement`} - - - {t`Terms of use`} - - - {t`All policies and guidelines`} - - - {t`Digital accessibility`} - - - {t`Cookie preferences`} - - - } - /> -
-
- - ); - } - - private addAlert(alert: AlertType) { - this.setState({ - alerts: [...this.state.alerts, alert], - }); - } - - private cookiePreferences() { - ( - window.document.querySelector( - '#teconsent > a', - ) as HTMLAnchorElement | null - )?.click(); - } -} - -export default withRouter(LandingPage); diff --git a/src/containers/login/login.tsx b/src/containers/login/login.tsx index 9824233..e003418 100644 --- a/src/containers/login/login.tsx +++ b/src/containers/login/login.tsx @@ -31,7 +31,7 @@ class LoginPage extends Component { }; const params = ParamHelper.parseParamString(this.props.location.search); - this.redirectPage = params['next'] || formatPath(Paths.landingPage); + this.redirectPage = params['next'] || formatPath(Paths.search); } render() { diff --git a/src/containers/namespace-detail/namespace-detail.tsx b/src/containers/namespace-detail/namespace-detail.tsx index 52daf3c..d9adb94 100644 --- a/src/containers/namespace-detail/namespace-detail.tsx +++ b/src/containers/namespace-detail/namespace-detail.tsx @@ -1,7 +1,6 @@ import { Trans, t } from '@lingui/macro'; import { Button, Checkbox, Text } from '@patternfly/react-core'; import { DropdownItem } from '@patternfly/react-core/deprecated'; -import ArrowRightIcon from '@patternfly/react-icons/dist/esm/icons/arrow-right-icon'; import React, { Component } from 'react'; import ReactMarkdown from 'react-markdown'; import { Link, Navigate } from 'react-router-dom'; @@ -29,7 +28,6 @@ import { ExternalLink, HubListToolbar, ImportModal, - LightspeedModal, LoadingPage, Main, PartnerHeader, @@ -39,7 +37,7 @@ import { collectionFilter, } from 'src/components'; import { AppContext, type IAppContextType } from 'src/loaders/app-context'; -import { Paths, formatPath, namespaceBreadcrumb } from 'src/paths'; +import { Paths, formatPath } from 'src/paths'; import { DeleteCollectionUtils, ParamHelper, @@ -69,7 +67,6 @@ interface IState { group: GroupType; isDeletionPending: boolean; isNamespacePending: boolean; - isOpenLightspeedModal: boolean; isOpenNamespaceModal: boolean; isOpenSignModal: boolean; namespace: NamespaceType; @@ -128,7 +125,6 @@ export class NamespaceDetail extends Component { group: null, isDeletionPending: false, isNamespacePending: false, - isOpenLightspeedModal: false, isOpenNamespaceModal: false, isOpenSignModal: false, namespace: null, @@ -249,7 +245,6 @@ export class NamespaceDetail extends Component { filteredCount, isDeletionPending, isNamespacePending, - isOpenLightspeedModal, isOpenNamespaceModal, namespace, params, @@ -259,7 +254,7 @@ export class NamespaceDetail extends Component { updateCollection, } = this.state; const { featureFlags } = this.context as IAppContextType; - const { legacy_roles, display_signatures } = featureFlags; + const { display_signatures } = featureFlags; if (redirect) { return ; @@ -309,20 +304,10 @@ export class NamespaceDetail extends Component { { tab: 'access' }, ), }, - legacy_roles && { - active: tab === 'role-namespaces', - title: t`Role namespaces`, - icon: , - link: formatPath( - Paths.standaloneNamespaces, - {}, - { provider: namespace.name }, - ), - }, ]; const breadcrumbs = [ - namespaceBreadcrumb(), + { name: t`Namespaces`, url: formatPath(Paths.namespaces) }, { name: namespace.name, url: @@ -450,14 +435,6 @@ export class NamespaceDetail extends Component { /> )} - {isOpenLightspeedModal && ( - this.addAlert(alert)} - closeAction={() => this.setState({ isOpenLightspeedModal: false })} - scope={'namespace'} - reference={this.state.namespace.name} - /> - )} { /> ) : null} - {tab === 'role-namespaces' ? ( - - ) : null} {canSign && ( { } const { canSign, collections, unfilteredCount } = this.state; - const { ai_deny_index, can_upload_signatures } = ( - this.context as IAppContextType - ).featureFlags; + const { can_upload_signatures } = (this.context as IAppContextType) + .featureFlags; const repository = this.state.params.repository_name || null; const dropdownItems = [ @@ -964,14 +930,6 @@ export class NamespaceDetail extends Component { {t`Sign all collections`}
)), - ai_deny_index && ( - this.setState({ isOpenLightspeedModal: true })} - > - {t`Ansible Lightspeed settings`} - - ), ].filter(Boolean); return ( diff --git a/src/containers/namespace-list/namespace-list.tsx b/src/containers/namespace-list/namespace-list.tsx index 7b34784..54e503d 100644 --- a/src/containers/namespace-list/namespace-list.tsx +++ b/src/containers/namespace-list/namespace-list.tsx @@ -201,7 +201,7 @@ export class NamespaceList extends Component { }) } /> - + {!(this.context as IAppContextType).user.is_anonymous && (
diff --git a/src/containers/not-found/dispatch.tsx b/src/containers/not-found/dispatch.tsx index 1e6b46a..4835bbd 100644 --- a/src/containers/not-found/dispatch.tsx +++ b/src/containers/not-found/dispatch.tsx @@ -2,14 +2,13 @@ import { Trans, t } from '@lingui/macro'; import { Bullseye, DataList } from '@patternfly/react-core'; import React, { type ReactNode, useEffect, useState } from 'react'; import { Link } from 'react-router-dom'; -import { CollectionVersionAPI, LegacyRoleAPI } from 'src/api'; +import { CollectionVersionAPI } from 'src/api'; import { BaseHeader, CollectionListItem, EmptyStateNoData, LoadingSpinner, Main, - RoleItem, } from 'src/components'; import { useHubContext } from 'src/loaders/app-context'; import { Paths, formatPath } from 'src/paths'; @@ -38,59 +37,28 @@ const Dispatch = ({ location, navigate }: RouteProps) => { const [namespace, name] = pathname.split('/').filter(Boolean); const [collections, setCollections] = useState(null); - const [roles, setRoles] = useState(null); useEffect(() => { - const wait = []; - - wait.push( - CollectionVersionAPI.list({ namespace, name, is_highest: true }) - .then(({ data: { data } }) => data || []) - .catch(() => []) - .then((c) => (setCollections(c), c)), - ); - - if (featureFlags.legacy_roles) { - wait.push( - LegacyRoleAPI.list({ name, namespace }) - .then(({ data: { results } }) => results || []) - .catch(() => []) - .then((r) => (setRoles(r), r)), - ); - } - - Promise.all(wait).then(([collections, roles]) => { - if (collections.length === 1 && !roles?.length) { - const { - collection_version: { name: collection, namespace }, - repository: { name: repo }, - } = collections[0]; - - navigate( - formatPath(Paths.collectionByRepo, { - collection, - namespace, - repo, - }), - ); - } - - if (roles.length === 1 && !collections.length) { - const { - name, - summary_fields: { - namespace: { name: namespace }, - }, - } = roles[0]; - - navigate( - formatPath(Paths.standaloneRole, { - namespace, - name, - }), - ); - } - }); + CollectionVersionAPI.list({ namespace, name, is_highest: true }) + .then(({ data: { data } }) => data || []) + .catch(() => []) + .then((c) => (setCollections(c), c)) + .then((collections) => { + if (collections.length === 1) { + const { + collection_version: { name: collection, namespace }, + repository: { name: repo }, + } = collections[0]; + + navigate( + formatPath(Paths.collectionByRepo, { + collection, + namespace, + repo, + }), + ); + } + }); }, [pathname]); return ( @@ -106,11 +74,8 @@ const Dispatch = ({ location, navigate }: RouteProps) => { Pathname{' '}
{pathname}
{' '} - could refer to a collection or a role. + could refer to a collection.
{' '} - {featureFlags.legacy_roles ? null : ( - Roles are not currently enabled. - )}
@@ -148,38 +113,6 @@ const Dispatch = ({ location, navigate }: RouteProps) => { )} - {featureFlags.legacy_roles ? ( - <> - - - {t`Roles`} - - {roles === null ? ( - - ) : roles.length === 0 ? ( - {t`Show all roles`} - } - /> - ) : ( - <> - - {roles.map((r) => ( - - ))} - - {t`Show all roles`} - - )} - - - ) : null} ); diff --git a/src/containers/search/multi-search.tsx b/src/containers/search/multi-search.tsx index 7c52492..fa25764 100644 --- a/src/containers/search/multi-search.tsx +++ b/src/containers/search/multi-search.tsx @@ -5,8 +5,6 @@ import { Link } from 'react-router-dom'; import { CollectionVersionAPI, ExecutionEnvironmentAPI, - LegacyNamespaceAPI, - LegacyRoleAPI, NamespaceAPI, } from 'src/api'; import { @@ -19,8 +17,6 @@ import { Main, MultiSearchSearch, NamespaceListItem, - RoleItem, - RoleNamespaceItem, Tooltip, closeAlert, } from 'src/components'; @@ -69,9 +65,7 @@ const MultiSearch = (props: RouteProps) => { const [params, setParams] = useState({}); const [collections, setCollections] = useState([]); - const [roles, setRoles] = useState([]); const [namespaces, setNamespaces] = useState([]); - const [roleNamespaces, setRoleNamespaces] = useState([]); const [containers, setContainers] = useState([]); const keywords = (params as { keywords: string })?.keywords || ''; @@ -84,8 +78,6 @@ const MultiSearch = (props: RouteProps) => { if (!keywords) { setCollections([]); setNamespaces([]); - setRoles([]); - setRoleNamespaces([]); setContainers([]); return; } @@ -114,30 +106,6 @@ const MultiSearch = (props: RouteProps) => { ), ); - if (featureFlags.legacy_roles) { - setRoles(loading); - LegacyRoleAPI.list({ ...shared, keywords }) - .then(({ data: { results } }) => setRoles(results || [])) - .catch( - handleHttpError( - t`Failed to search roles (${keywords})`, - () => setRoles([]), - addAlert, - ), - ); - - setRoleNamespaces(loading); - LegacyNamespaceAPI.list({ ...shared, keywords }) - .then(({ data: { results } }) => setRoleNamespaces(results || [])) - .catch( - handleHttpError( - t`Failed to search role namespaces (${keywords})`, - () => setRoleNamespaces([]), - addAlert, - ), - ); - } - if (featureFlags.execution_environments) { setContainers(loading); ExecutionEnvironmentAPI.list({ ...shared, name__icontains: keywords }) @@ -278,52 +246,6 @@ const MultiSearch = (props: RouteProps) => { - {featureFlags.legacy_roles ? ( - {t`Show all roles`} - } - showMoreLink={ - {t`Show more roles`} - } - > - - {roles.map((r) => ( - - ))} - - - ) : null} - - {featureFlags.legacy_roles ? ( - {t`Show all role namespaces`} - } - showMoreLink={ - {t`Show more role namespaces`} - } - > - - {roleNamespaces.map((r) => ( - - ))} - - - ) : null} - {featureFlags.execution_environments ? ( { } /> - {featureFlags.legacy_roles ? ( - {t`Show all roles`} - } - /> - ) : null} - - {featureFlags.legacy_roles ? ( - {t`Show all role namespaces`} - } - /> - ) : null} - {featureFlags.execution_environments ? ( { params, count: 0, loading: true, - synclist: undefined, alerts: [], updateCollection: null, showImportModal: false, @@ -118,10 +114,6 @@ class Search extends Component { private load() { this.queryCollections(); - - if (IS_INSIGHTS) { - this.getSynclist(); - } } private addAlert(alert: AlertType) { @@ -310,10 +302,6 @@ class Search extends Component { { return dropdownMenu; } - private renderSyncToogle(name: string, namespace: string): ReactNode { - const { synclist } = this.state; - - if (!synclist) { - return null; - } - - return ( - this.toggleCollectionSync(name, namespace)} - /> - ); - } - private checkUploadPrivilleges(collection) { const addAlert = () => { this.setState({ @@ -479,34 +449,6 @@ class Search extends Component { }); } - private toggleCollectionSync(name: string, namespace: string) { - const synclist = { ...this.state.synclist }; - - const colIndex = synclist.collections.findIndex( - (el) => el.name === name && el.namespace === namespace, - ); - - if (colIndex < 0) { - synclist.collections.push({ name: name, namespace: namespace }); - } else { - synclist.collections.splice(colIndex, 1); - } - - MySyncListAPI.update(synclist.id, synclist).then((response) => { - this.setState({ synclist: response.data }); - MySyncListAPI.curate(synclist.id).then(() => null); - }); - } - - private isCollectionSynced(name: string, namespace: string): boolean { - const { synclist } = this.state; - const found = synclist.collections.find( - (el) => el.name === name && el.namespace === namespace, - ); - - return synclist.policy === 'include' ? !!found : !found; - } - private renderList(collections) { return (
@@ -521,10 +463,6 @@ class Search extends Component { .display_signatures } showNamespace - synclistSwitch={this.renderSyncToogle( - c.collection_version.name, - c.collection_version.namespace, - )} {...this.renderMenu(true, c)} /> ))} @@ -534,20 +472,6 @@ class Search extends Component { ); } - private getSynclist() { - MySyncListAPI.list().then((result) => { - // ignore results if more than 1 is returned - // TODO: should we throw an error for this or just ignore it? - if (result.data.meta.count === 1) { - this.setState({ synclist: result.data.data[0] }); - } else { - console.error( - `my-synclist returned ${result.data.meta.count} synclists`, - ); - } - }); - } - private queryCollections() { this.setState({ loading: true }, () => { CollectionVersionAPI.list({ diff --git a/src/index.d.ts b/src/index.d.ts index 76b986c..0dff56b 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -8,57 +8,8 @@ declare module '*.svg'; declare var API_BASE_PATH; declare var API_HOST; declare var APPLICATION_NAME; -declare var IS_COMMUNITY: boolean; -declare var IS_INSIGHTS: boolean; declare var PULP_API_BASE_PATH; declare var UI_BASE_PATH; declare var UI_COMMIT_HASH; declare var UI_DOCS_URL; declare var UI_EXTERNAL_LOGIN_URI; - -// when IS_INSIGHTS only -interface Window { - insights: { - chrome: { - auth: { - doOffline: () => void; - getOfflineToken: () => Promise<{ - data: { - access_token: string; - expires_in: number; - id_token: string; - refresh_expires_in: number; - refresh_token: string; - scope: string; - session_state: string; - token_type: string; - }; - }>; - getUser: () => Promise<{ - identity: { - account_number: string; - internal: { - account_id: number; - org_id: string; - }; - org_id: string; - type?: string; - user: { - email: string; - first_name: string; - is_active?: boolean; - is_internal: boolean; - is_org_admin: boolean; - last_name: string; - locale?: string; - username: string; - }; - }; - }>; - }; - identifyApp: (s: string, title?: string) => void; - init: () => void; - on: (s: string, f: (event) => void) => () => void; - }; - }; -} diff --git a/src/loaders/standalone/layout.tsx b/src/loaders/standalone/layout.tsx index d7b85f4..42f6046 100644 --- a/src/loaders/standalone/layout.tsx +++ b/src/loaders/standalone/layout.tsx @@ -21,7 +21,6 @@ import { Link } from 'react-router-dom'; import { ActiveUserAPI, type FeatureFlagsType, - GatewayLogoutAPI, type SettingsType, type UserType, } from 'src/api'; @@ -54,7 +53,6 @@ export const StandaloneLayout = ({ user, }: IProps) => { const [aboutModalVisible, setAboutModalVisible] = useState(false); - const isGateway = featureFlags?.dab_resource_registry; let aboutModal = null; let docsDropdownItems = []; @@ -85,11 +83,6 @@ export const StandaloneLayout = ({ aria-label={'logout'} onClick={() => ActiveUserAPI.logout() - .then( - isGateway - ? () => GatewayLogoutAPI.logout().catch(() => null) - : () => null, - ) .then(() => ActiveUserAPI.getUser().catch(() => null)) .then((user) => setUser(user)) } @@ -99,68 +92,15 @@ export const StandaloneLayout = ({ ]; docsDropdownItems = [ - !IS_COMMUNITY && ( - {t`Documentation`} - } - /> - ), - {t`Customer Support`} - } - />, {t`Training`} + >{t`Documentation`} } />, - IS_COMMUNITY && ( - {t`Ansible Community Forum`} - } - /> - ), - IS_COMMUNITY && ( - {t`Communicating with the Ansible community`} - } - /> - ), - IS_COMMUNITY && ( - {t`Community User Guide`} - } - /> - ), setAboutModalVisible(true)}> {t`About`} , @@ -185,7 +125,7 @@ export const StandaloneLayout = ({ - + diff --git a/src/loaders/standalone/menu.tsx b/src/loaders/standalone/menu.tsx index 6be4e8d..38bc423 100644 --- a/src/loaders/standalone/menu.tsx +++ b/src/loaders/standalone/menu.tsx @@ -88,25 +88,6 @@ function standaloneMenu() { }), ], ), - menuSection( - t`Roles`, - { - condition: ({ featureFlags }) => featureFlags.legacy_roles, - }, - [ - menuItem(t`Roles`, { - url: formatPath(Paths.standaloneRoles), - }), - menuItem(t`Role Namespaces`, { - url: formatPath(Paths.standaloneNamespaces), - }), - menuItem(t`Role Imports`, { - url: formatPath(Paths.standaloneImports), - condition: ({ featureFlags, user }) => - featureFlags.legacy_roles && !user.is_anonymous, - }), - ], - ), menuItem(t`Task Management`, { url: formatPath(Paths.taskList), condition: isLoggedIn, @@ -134,19 +115,6 @@ function standaloneMenu() { alternativeUrls: [altPath(Paths.roleEdit)], }), ]), - menuItem(t`Documentation`, { - url: 'https://ansible.readthedocs.io/projects/galaxy-ng/en/latest/community/userguide/', - external: true, - condition: ({ settings, user }) => - IS_COMMUNITY && - (settings.GALAXY_ENABLE_UNAUTHENTICATED_COLLECTION_ACCESS || - !user.is_anonymous), - }), - menuItem(t`Terms of Use`, { - url: 'https://www.redhat.com/en/about/terms-use', - external: true, - condition: ({ featureFlags }) => featureFlags.legacy_roles, - }), ]; } diff --git a/src/loaders/standalone/routes.tsx b/src/loaders/standalone/routes.tsx index aa5d195..df204dc 100644 --- a/src/loaders/standalone/routes.tsx +++ b/src/loaders/standalone/routes.tsx @@ -13,13 +13,6 @@ import { AnsibleRepositoryDetail, AnsibleRepositoryEdit, AnsibleRepositoryList, - AnsibleRoleDetail, - AnsibleRoleImport, - AnsibleRoleImports, - AnsibleRoleList, - AnsibleRoleNamespaceDetail, - AnsibleRoleNamespaceList, - AnsibleRoleSync, CertificationDashboard, CollectionContent, CollectionDependencies, @@ -40,7 +33,6 @@ import { ExecutionEnvironmentRegistryList, GroupDetail, GroupList, - LandingPage, LoginPage, MultiSearch, MyImports, @@ -131,7 +123,7 @@ const AuthHandler = ({ const isExternalAuth = featureFlags.external_authentication; // NOTE: also update LoginLink when changing this if (isExternalAuth && UI_EXTERNAL_LOGIN_URI) { - window.location.replace(loginURL(pathname, featureFlags)); + window.location.replace(loginURL(pathname)); return null; } @@ -197,16 +189,6 @@ export class StandaloneRoutes extends Component { path: Paths.executionEnvironmentsRegistries, isDisabled: isContainerDisabled, }, - { component: AnsibleRoleDetail, path: Paths.standaloneRole }, - { component: AnsibleRoleImport, path: Paths.standaloneRoleImport }, - { component: AnsibleRoleImports, path: Paths.standaloneImports }, - { component: AnsibleRoleList, path: Paths.standaloneRoles }, - { - component: AnsibleRoleNamespaceDetail, - path: Paths.standaloneNamespace, - }, - { component: AnsibleRoleNamespaceList, path: Paths.standaloneNamespaces }, - { component: AnsibleRoleSync, path: Paths.standaloneRoleSync }, { component: TaskListView, path: Paths.taskList, @@ -252,8 +234,6 @@ export class StandaloneRoutes extends Component { { component: TokenStandalone, path: Paths.token }, { component: Partners, path: Paths.namespaces }, { component: EditNamespace, path: Paths.editNamespace }, - { component: NamespaceDetail, path: Paths.myCollections }, - { component: NamespaceDetail, path: Paths.myCollectionsByRepo }, { component: MyNamespaces, path: Paths.myNamespaces }, { component: LoginPage, path: Paths.login, noAuth: true }, { component: CollectionDocs, path: Paths.collectionDocsPageByRepo }, @@ -270,17 +250,10 @@ export class StandaloneRoutes extends Component { path: Paths.collectionDependenciesByRepo, }, { component: CollectionDetail, path: Paths.collectionByRepo }, - { component: NamespaceDetail, path: Paths.namespaceDetail }, { component: Search, path: Paths.collections }, - { component: CollectionDocs, path: Paths.collectionDocsPage }, - { component: CollectionDocs, path: Paths.collectionDocsIndex }, - { component: CollectionDocs, path: Paths.collectionContentDocs }, - { component: CollectionContent, path: Paths.collectionContentList }, - { component: CollectionImportLog, path: Paths.collectionImportLog }, { component: MyImports, path: Paths.myImports }, - { component: NamespaceDetail, path: Paths.namespace }, + { component: NamespaceDetail, path: Paths.namespaceDetail }, { component: Search, path: Paths.collections }, - { component: LandingPage, path: Paths.landingPage }, { component: Dispatch, path: Paths.dispatch }, { component: MultiSearch, path: Paths.search }, ]; diff --git a/src/paths.ts b/src/paths.ts index fc4faed..aedff60 100644 --- a/src/paths.ts +++ b/src/paths.ts @@ -1,4 +1,3 @@ -import { t } from '@lingui/macro'; import { ParamHelper, type ParamType } from 'src/utilities'; export function formatPath( @@ -7,16 +6,8 @@ export function formatPath( params?: ParamType, options?, ) { - // insights router has basename="/", "/beta/" or "/preview/", with hub under a nested "ansible/automation-hub" route - our urls are relative to that - let url = IS_INSIGHTS - ? UI_BASE_PATH.replace('/preview/', '/') - .replace('/beta/', '/') - .replace(/\/$/, '') - : ''; - url += (path as string) + '/'; - url = url.replaceAll('//', '/'); - - url = url + const url = ((path as string) + '/') + .replaceAll('//', '/') .split('/') .map((fragment) => { const match = fragment.match(/^:(\w+)\??$/); @@ -68,20 +59,15 @@ export const Paths = { ansibleRepositoryEdit: '/ansible/repositories/:name/edit', approvalDashboard: '/approval-dashboard', collectionByRepo: '/repo/:repo/:namespace/:collection', - collectionContentDocs: '/:namespace/:collection/content/:type/:name', // compat collectionContentDocsByRepo: '/repo/:repo/:namespace/:collection/content/:type/:name', - collectionContentList: '/:namespace/:collection/content', // compat collectionContentListByRepo: '/repo/:repo/:namespace/:collection/content', collectionDependenciesByRepo: '/repo/:repo/:namespace/:collection/dependencies', collectionDistributionsByRepo: '/repo/:repo/:namespace/:collection/distributions', - collectionDocsIndex: '/:namespace/:collection/docs', // compat collectionDocsIndexByRepo: '/repo/:repo/:namespace/:collection/docs', - collectionDocsPage: '/:namespace/:collection/docs/:page', // compat collectionDocsPageByRepo: '/repo/:repo/:namespace/:collection/docs/:page', - collectionImportLog: '/:namespace/:collection/import-log', // compat collectionImportLogByRepo: '/repo/:repo/:namespace/:collection/import-log', collections: '/collections', createRole: '/roles/create', @@ -102,27 +88,16 @@ export const Paths = { executionEnvironmentsRegistries: '/registries', groupDetail: '/group/:group', groupList: '/group-list', - landingPage: '/', login: '/login', - myCollections: '/my-namespaces/:namespace', // compat - myCollectionsByRepo: '/repo/:repo/my-namespaces/:namespace', // compat myImports: '/my-imports', myNamespaces: '/my-namespaces', - namespace: '/:namespace', // compat namespaceDetail: '/namespaces/:namespace', - namespaces: IS_INSIGHTS ? '/partners' : '/namespaces', + namespaces: '/namespaces', notFound: '/not-found', // FIXME don't redirect roleEdit: '/role/:role', roleList: '/roles', - search: '/search', + search: '/', signatureKeys: '/signature-keys', - standaloneImports: '/standalone/imports', - standaloneNamespace: '/standalone/namespaces/:namespaceid', - standaloneNamespaces: '/standalone/namespaces', - standaloneRole: '/standalone/roles/:namespace/:name/:tab?', - standaloneRoleImport: '/standalone/roles/import', - standaloneRoleSync: '/standalone/roles/sync', - standaloneRoles: '/standalone/roles', taskDetail: '/task/:task', taskList: '/tasks', token: '/token', @@ -130,8 +105,3 @@ export const Paths = { userList: '/users', userProfileSettings: '/settings/user-profile', }; - -export const namespaceBreadcrumb = () => ({ - name: IS_INSIGHTS ? t`Partners` : t`Namespaces`, - url: formatPath(Paths.namespaces), -}); diff --git a/src/utilities/index.ts b/src/utilities/index.ts index 6cd3a74..dc63b81 100644 --- a/src/utilities/index.ts +++ b/src/utilities/index.ts @@ -18,13 +18,11 @@ export { mapErrorMessages, } from './map-error-messages'; export { mapNetworkErrors, validateInput } from './map-role-errors'; -export { namespaceTitle } from './namespace-title'; export { ParamHelper, type ParamType } from './param-helper'; export { parsePulpIDFromURL } from './parse-pulp-id'; export { RepoSigningUtils } from './repo-signing'; export { repositoryBasePath } from './repository-base-path'; export { repositoryRemoveCollection } from './repository-remove-collection'; -export { roleNamespaceInfo } from './role-namespace-info'; export { taskAlert } from './task-alert'; export { translateLockedRole } from './translate-locked-role'; export { translateTask } from './translate-task'; diff --git a/src/utilities/login-url.ts b/src/utilities/login-url.ts index a064a9c..7388a44 100644 --- a/src/utilities/login-url.ts +++ b/src/utilities/login-url.ts @@ -1,8 +1,8 @@ // external login URL, assuming UI_EXETRNAL_LOGIN_URI and featureFlags.external_authentication are set -export const loginURL = (next, featureFlags) => { - if (featureFlags.dab_resource_registry && next) { +export const loginURL = (next) => { + if (next) { const fullPath = `${UI_BASE_PATH}/${next}`.replaceAll(/\/+/g, '/'); - return `/redirect/?next=${encodeURIComponent(fullPath)}`; + return `${UI_EXTERNAL_LOGIN_URI}?next=${encodeURIComponent(fullPath)}`; } return UI_EXTERNAL_LOGIN_URI; diff --git a/src/utilities/namespace-title.ts b/src/utilities/namespace-title.ts deleted file mode 100644 index 5ea3568..0000000 --- a/src/utilities/namespace-title.ts +++ /dev/null @@ -1,9 +0,0 @@ -export function namespaceTitle({ - name, - company, -}: { - name: string; - company?: string; -}): string { - return IS_INSIGHTS ? company || name : name; -} diff --git a/src/utilities/role-namespace-info.ts b/src/utilities/role-namespace-info.ts deleted file mode 100644 index 8eebf26..0000000 --- a/src/utilities/role-namespace-info.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Paths, formatPath } from 'src/paths'; - -export function roleNamespaceInfo(data) { - const summary_fields = data.summary_fields; - let provider = null; - - if (summary_fields) { - if ('provider_namespace' in summary_fields) { - // role summary - provider = data.summary_fields.provider_namespace; - } else if ( - 'provider_namespaces' in summary_fields && - summary_fields.provider_namespaces.length > 0 - ) { - // role namespace summary - provider = data.summary_fields.provider_namespaces[0]; - } - } - - if (!provider) { - return { - id: null, - name: null, - url: null, - }; - } - - return { - id: provider.id || null, - name: provider.name || null, - url: provider.name - ? formatPath(Paths.namespaceDetail, { namespace: provider.name }) - : null, - }; -} diff --git a/src/utilities/translate-locked-role.ts b/src/utilities/translate-locked-role.ts index 2618cbe..152ac37 100644 --- a/src/utilities/translate-locked-role.ts +++ b/src/utilities/translate-locked-role.ts @@ -17,7 +17,6 @@ export const translateLockedRole = (name, description) => 'galaxy.execution_environment_namespace_owner': t`Create and update execution environments under existing container namespaces.`, 'galaxy.execution_environment_publisher': t`Push and change execution environments.`, 'galaxy.group_admin': t`View, add, remove and change groups.`, - 'galaxy.synclist_owner': t`View, add, remove and change synclists.`, 'galaxy.task_admin': t`View and cancel any task.`, 'galaxy.user_admin': t`View, add, remove and change users.`, })[name] || description; diff --git a/src/utilities/translate-task.ts b/src/utilities/translate-task.ts index 8e373f4..34ff283 100644 --- a/src/utilities/translate-task.ts +++ b/src/utilities/translate-task.ts @@ -2,13 +2,10 @@ import { t } from '@lingui/macro'; export const translateTask = (name) => ({ - 'galaxy_ng.app.tasks.curate_all_synclist_repository': t`Curate all synclist repositories`, - 'galaxy_ng.app.tasks.curate_synclist_repository': t`Curate synclist repository`, 'galaxy_ng.app.tasks.import_and_auto_approve': t`Import and auto approve`, 'galaxy_ng.app.tasks.import_and_move_to_staging': t`Import and move to staging`, 'galaxy_ng.app.tasks.promotion._remove_content_from_repository': t`Remove content from repository`, 'galaxy_ng.app.tasks.publishing.import_and_auto_approve': t`Import and auto approve`, - 'galaxy_ng.app.tasks.synclist.curate_synclist_repository_batch': t`Curate synclist repository batch`, 'pulp_ansible.app.tasks.collections.collection_sync': t`Collections sync`, 'pulp_ansible.app.tasks.collections.import_collection': t`Import collection`, 'pulp_ansible.app.tasks.collections.sync': t`Collections sync`,