go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/analysis/frontend/ui/src/tools/problems.ts (about)

     1  // Copyright 2023 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  import { BugManagement, BugManagementPolicy } from '@/proto/go.chromium.org/luci/analysis/proto/v1/projects.pb';
    16  import { BugManagementState, BugManagementState_PolicyState } from '@/proto/go.chromium.org/luci/analysis/proto/v1/rules.pb';
    17  
    18  export interface Problem {
    19    policy: BugManagementPolicy;
    20    state: BugManagementState_PolicyState;
    21  }
    22  
    23  // identifyProblems combines the bug management state with configured
    24  // policies to return details about active and resolved problems.
    25  // Problems are returned in no particular order.
    26  export const identifyProblems = (config: BugManagement | undefined, state: BugManagementState) : Problem[] => {
    27    if (!state.policyState || !config || !config.policies) {
    28      return [];
    29    }
    30    const result: Problem[] = [];
    31    state.policyState.forEach((policyState) => {
    32      if (!policyState.lastActivationTime) {
    33        // Policy was never active.
    34        return;
    35      }
    36      const policy = config.policies?.find((p) => p.id == policyState.policyId);
    37      if (!policy) {
    38        // Policy definition not found; this could be because the config was
    39        // very recently deleted.
    40        return;
    41      }
    42      result.push({
    43        policy: policy,
    44        state: policyState,
    45      });
    46    });
    47    return result;
    48  };
    49  
    50  // sortProblemsByDescendingActiveAndPriority sorts problems in place.
    51  // The sort is active first, then by descending priority, then by ID.
    52  // If focusPolicyID is set, a problem for that policy always appears first,
    53  // regardless of any other sort preference.
    54  export const sortProblemsByDescendingActiveAndPriority = (problems : Problem[], focusPolicyID? : string): void => {
    55    problems.sort((a, b) => {
    56      if ((a.policy.id === focusPolicyID) != (b.policy.id === focusPolicyID)) {
    57        // Focused policy (if any) goes first.
    58        return a.policy.id === focusPolicyID ? -1 : 1;
    59      }
    60      // The active policy goes first.
    61      if (a.state.isActive != b.state.isActive) {
    62        return a.state.isActive ? -1 : 1;
    63      }
    64      // Higher priority goes first (e.g. P0 before P1, etc.).
    65      if (a.policy.priority != b.policy.priority) {
    66        return a.policy.priority < b.policy.priority ? -1 : 1;
    67      }
    68      // Then lower policy ID goes first.
    69      if (a.policy.id != b.policy.id) {
    70        return a.policy.id < b.policy.id ? -1 : 1;
    71      }
    72      // Problems are the same.
    73      return 0;
    74    });
    75  };