Repository: hashicorp/vault
File: ui/app/components/namespace-picker.js (JavaScript)

Code before:
import { tracked } from '@glimmer/tracking';
import { service } from '@ember/service';

/**
 * @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 refrehes the list of namespaces in the dropdown.
 *
 * @example
 * <NamespacePicker class="hds-side-nav-hide-when-minimized" />
 */

export default class NamespacePicker extends Component {
  @service namespace;
  @service router;
  @service store;

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

  @tracked selected = {};
  @tracked options = [];
  @tracked search = '';
  @tracked namespaceLabel = 'All Namespaces';

  constructor() {
    super(...arguments);
    this.loadOptions();
  }

  // TODO make private when converting from js to ts
  #matchesPath(option, currentNamespace) {
    // 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?
    return option?.path === currentNamespace?.path || `/${option?.path}` === currentNamespace?.path;
  }

  // TODO make private when converting from js to ts
  #getSelected(options, currentNamespace) {
    return options.find((option) => this.#matchesPath(option, currentNamespace));
  }

  // TODO make private when converting from js to ts
  #getOptions(namespace) {
    /* Each namespace option has 3 properties: { id, path, and label }
     *   - id: node / namespace name (displayed when the namespace picker is closed)
     *   - path: full namespace path (used to navigate to the namespace)
     *   - label: text displayed inside the namespace picker dropdown (if root, then label = id, else label = path)

Review comment (suggestion):
If the title does not change it does not need to be tracked. If there is only one instance of it, hardcode it in the hbs file, otherwise you can assign it here as: namespaceLabel = 'All Namespaces'. Tracked properties are helpful when we expect them to be changed based of of something happening either to arguments passed in or a user action. 
AI overview below:
>In Ember.js, you should use @tracked properties for any property that is mutated and potentially externally visible. This includes properties that are used in templates or computed properties, or that might be accessed or updated by other components or services. Essentially, if a property's change needs to be reflected in the UI or in other parts of your application, it should be tracked. 

Code after:
import { tracked } from '@glimmer/tracking';
import { service } from '@ember/service';

/**
 * @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 refrehes the list of namespaces in the dropdown.
 *
 * @example
 * <NamespacePicker class="hds-side-nav-hide-when-minimized" />
 */

export default class NamespacePicker extends Component {
  @service namespace;
  @service router;
  @service store;

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

  @tracked selected = {};
  @tracked options = [];
  @tracked searchInput = '';

  constructor() {
    super(...arguments);
    this.loadOptions();
  }

  // TODO make private when converting from js to ts
  #matchesPath(option, currentNamespace) {
    // 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?
    return option?.path === currentNamespace?.path || `/${option?.path}` === currentNamespace?.path;
  }

  // TODO make private when converting from js to ts
  #getSelected(options, currentNamespace) {
    return options.find((option) => this.#matchesPath(option, currentNamespace));
  }

  // TODO make private when converting from js to ts
  #getOptions(namespace) {
    /* Each namespace option has 3 properties: { id, path, and label }
     *   - id: node / namespace name (displayed when the namespace picker is closed)
     *   - path: full namespace path (used to navigate to the namespace)
     *   - label: text displayed inside the namespace picker dropdown (if root, then label = id, else label = path)
     *