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 };