Repository: hashicorp/vault
File: ui/app/components/namespace-picker.ts (TypeScript)

Code before:

import Component from '@glimmer/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import { service } from '@ember/service';
import { KEYS } from 'core/utils/keyboard-keys';

/**
 * @module NamespacePicker
 * @description component is used to display a dropdown listing all namespaces that the current user has access to.
 *  The user can select a namespace from the dropdown to navigate directly to that namespace.
 *  The "Manage" button directs the user to the namespace management page.
 *  The "Refresh List" button refreshes the list of namespaces in the dropdown.
 *
 * @example
 * <NamespacePicker class="hds-side-nav-hide-when-minimized" />
 */

interface NamespaceOption {
  id: string;
  path: string;
  label: string;
}

export default class NamespacePicker extends Component {
  @service declare auth: any;
  @service declare namespace: any;
  @service declare router: any;
  @service declare store: any;

  // Show/hide refresh & manage namespaces buttons
  @tracked hasListPermissions = false;

  @tracked batchSize = 200;

  @tracked allNamespaces: NamespaceOption[] = [];
  @tracked hasNamespaces = false;
  @tracked searchInput = '';
  @tracked searchInputHelpText =
    "Enter a full path in the search bar and hit the 'Enter' ↵ key to navigate faster.";
  @tracked selected: NamespaceOption | null = null;

  constructor(owner: unknown, args: any) {
    super(owner, args);
    this.loadOptions();
  }

  private matchesPath(option: NamespaceOption, currentPath: string): boolean {
    // TODO: Revisit. A hardcoded check for "path" & "/path" seems hacky, but it fixes a breaking test:
    //  "Acceptance | Enterprise | namespaces: it shows nested namespaces if you log in with a namespace starting with a /"
    //  My assumption is that namespace shouldn't start with a "/", but is this a HVD thing? or is the test outdated?

Review comment (security):
would `type AuthService from 'vault/services/auth'` work for this type instead of `any`?

Code after:

import Component from '@glimmer/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import { service } from '@ember/service';
import { KEYS } from 'core/utils/keyboard-keys';
import type Router from 'vault/router';
import type NamespaceService from 'vault/services/namespace';
import type AuthService from 'vault/vault/services/auth';
import type Store from '@ember-data/store';

interface NamespaceOption {
  id: string;
  path: string;
  label: string;
}

/**
 * @module NamespacePicker
 * @description component is used to display a dropdown listing all namespaces that the current user has access to.
 *  The user can select a namespace from the dropdown to navigate directly to that namespace.
 *  The "Manage" button directs the user to the namespace management page.
 *  The "Refresh List" button refreshes the list of namespaces in the dropdown.
 *
 * @example
 * <NamespacePicker class="hds-side-nav-hide-when-minimized" />
 */
export default class NamespacePicker extends Component {
  @service declare auth: AuthService;
  @service declare namespace: NamespaceService;
  @service declare router: Router;
  @service declare store: Store;

  // Show/hide refresh & manage namespaces buttons
  @tracked hasListPermissions = false;

  @tracked batchSize = 200;

  @tracked allNamespaces: NamespaceOption[] = [];
  @tracked hasNamespaces = false;
  @tracked searchInput = '';
  @tracked searchInputHelpText =
    "Enter a full path in the search bar and hit the 'Enter' ↵ key to navigate faster.";
  @tracked selected: NamespaceOption | null = null;

  constructor(owner: unknown, args: Record<string, never>) {
    super(owner, args);
    this.loadOptions();
  }

  private matchesPath(option: NamespaceOption, currentPath: string): boolean {