Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | 1x 1x 1x 1x 197x 197x 197x 167x 167x 1x 166x 166x 6x 160x 93x 67x 67x 67x 67x 30x 4x 116x 4x 173x 171x 171x 167x 167x 167x | import { WorkItemWidgetType, WorkItemWidgetTypes } from "../graphql/workItems";
import { ConnectionManager } from "./ConnectionManager";
import { GitLabTier } from "./GitLabVersionDetector";
interface WidgetRequirement {
tier: GitLabTier | "free";
minVersion: number;
}
export class WidgetAvailability {
private static widgetRequirements: Record<WorkItemWidgetType, WidgetRequirement> = {
// Free tier widgets (available to all)
[WorkItemWidgetTypes.ASSIGNEES]: { tier: "free", minVersion: 15.0 },
[WorkItemWidgetTypes.DESCRIPTION]: { tier: "free", minVersion: 15.0 },
[WorkItemWidgetTypes.HIERARCHY]: { tier: "free", minVersion: 15.0 },
[WorkItemWidgetTypes.LABELS]: { tier: "free", minVersion: 15.0 },
[WorkItemWidgetTypes.MILESTONE]: { tier: "free", minVersion: 15.0 },
[WorkItemWidgetTypes.NOTES]: { tier: "free", minVersion: 15.0 },
[WorkItemWidgetTypes.START_AND_DUE_DATE]: { tier: "free", minVersion: 15.0 },
[WorkItemWidgetTypes.STATUS]: { tier: "free", minVersion: 15.0 },
[WorkItemWidgetTypes.NOTIFICATIONS]: { tier: "free", minVersion: 15.0 },
[WorkItemWidgetTypes.CURRENT_USER_TODOS]: { tier: "free", minVersion: 15.0 },
[WorkItemWidgetTypes.AWARD_EMOJI]: { tier: "free", minVersion: 15.0 },
[WorkItemWidgetTypes.PARTICIPANTS]: { tier: "free", minVersion: 15.0 },
[WorkItemWidgetTypes.DESIGNS]: { tier: "free", minVersion: 15.0 },
[WorkItemWidgetTypes.DEVELOPMENT]: { tier: "free", minVersion: 15.0 },
[WorkItemWidgetTypes.TIME_TRACKING]: { tier: "free", minVersion: 15.0 },
[WorkItemWidgetTypes.ERROR_TRACKING]: { tier: "free", minVersion: 15.0 },
// Premium tier widgets
[WorkItemWidgetTypes.WEIGHT]: { tier: "premium", minVersion: 15.0 },
[WorkItemWidgetTypes.ITERATION]: { tier: "premium", minVersion: 15.0 },
[WorkItemWidgetTypes.LINKED_ITEMS]: { tier: "premium", minVersion: 15.0 },
[WorkItemWidgetTypes.CRM_CONTACTS]: { tier: "premium", minVersion: 16.0 },
[WorkItemWidgetTypes.EMAIL_PARTICIPANTS]: { tier: "premium", minVersion: 16.0 },
[WorkItemWidgetTypes.LINKED_RESOURCES]: { tier: "premium", minVersion: 16.5 },
// Ultimate tier widgets
[WorkItemWidgetTypes.HEALTH_STATUS]: { tier: "ultimate", minVersion: 15.0 },
[WorkItemWidgetTypes.CUSTOM_FIELDS]: { tier: "ultimate", minVersion: 17.0 },
[WorkItemWidgetTypes.VULNERABILITIES]: { tier: "ultimate", minVersion: 15.0 },
// Legacy widgets (may not be available)
[WorkItemWidgetTypes.PROGRESS]: { tier: "free", minVersion: 15.0 },
[WorkItemWidgetTypes.REQUIREMENT_LEGACY]: { tier: "ultimate", minVersion: 13.1 },
[WorkItemWidgetTypes.TEST_REPORTS]: { tier: "ultimate", minVersion: 13.6 },
[WorkItemWidgetTypes.COLOR]: { tier: "free", minVersion: 15.0 },
};
public static isWidgetAvailable(widget: WorkItemWidgetType): boolean {
const connectionManager = ConnectionManager.getInstance();
try {
const instanceInfo = connectionManager.getInstanceInfo();
const requirement = this.widgetRequirements[widget];
if (!requirement) {
// Unknown widget, assume not available
return false;
}
// Check version requirement
const version = this.parseVersion(instanceInfo.version);
if (version < requirement.minVersion) {
return false;
}
// Check tier requirement
if (requirement.tier === "free") {
return true; // Available to all tiers
}
const tierHierarchy: Record<GitLabTier, number> = {
free: 0,
premium: 1,
ultimate: 2,
};
const requiredTierLevel = tierHierarchy[requirement.tier as GitLabTier];
const actualTierLevel = tierHierarchy[instanceInfo.tier];
return actualTierLevel >= requiredTierLevel;
} catch {
// If connection not initialized, assume widget not available
return false;
}
}
public static getAvailableWidgets(): WorkItemWidgetType[] {
return Object.values(WorkItemWidgetTypes).filter(
(widget): widget is WorkItemWidgetType =>
typeof widget === "string" && this.isWidgetAvailable(widget as WorkItemWidgetType)
);
}
public static getWidgetRequirement(widget: WorkItemWidgetType): WidgetRequirement | undefined {
return this.widgetRequirements[widget];
}
private static parseVersion(version: string): number {
if (version === "unknown") return 0;
const match = version.match(/^(\d+)\.(\d+)/);
if (!match) return 0;
const major = parseInt(match[1], 10);
const minor = parseInt(match[2], 10);
return major + minor / 10;
}
}
|