{"version":3,"sources":["webpack:////build/source/node_modules/lodash/_arrayIncludesWith.js","webpack:///./analytics/shared/constants.js","webpack:////build/source/node_modules/lodash/_createSet.js","webpack:///./vue_shared/components/filtered_search_bar/filtered_search_utils.js","webpack:////build/source/node_modules/lodash/_baseUniq.js","webpack:///./analytics/shared/utils.js","webpack:////build/source/node_modules/lodash/uniqWith.js"],"names":["module","exports","array","value","comparator","index","length","DATE_RANGE_LIMIT","PROJECTS_PER_PAGE","isoDate","masks","dateFormats","defaultDate","defaultDateTime","month","TODAY","getCurrentUtcDate","startOfToday","getStartOfDay","Date","utc","LAST_30_DAYS","nDaysBefore","lastXDays","__","lastWeek","nWeeksBefore","last90Days","last180Days","mrThroughputStartDate","formatDateParam","d","dateFormat","DATE_RANGE_CUSTOM_VALUE","DATE_RANGE_LAST_30_DAYS_VALUE","DEFAULT_DROPDOWN_DATE_RANGES","text","startDate","endDate","sprintf","days","MAX_DATE_RANGE_TEXT","maxDateRange","MAX_METRIC_PRECISION","UNITS","COUNT","DAYS","PER_DAY","PERCENT","NUMBER_OF_DAYS_SELECTED","numDays","n__","METRIC_POPOVER_LABEL","s__","ALL_METRICS_QUERY_TYPE","DORA_METRICS_QUERY_TYPE","FLOW_METRICS_QUERY_TYPE","FLOW_METRICS","LEAD_TIME","CYCLE_TIME","ISSUES","ISSUES_COMPLETED","COMMITS","DEPLOYS","MEDIAN_TIME_TO_MERGE","DORA_METRICS","DEPLOYMENT_FREQUENCY","LEAD_TIME_FOR_CHANGES","TIME_TO_RESTORE_SERVICE","CHANGE_FAILURE_RATE","LEAD_TIME_NO_DATA_MESSAGE","DORA_METRICS_NULL_SERIES_TITLE","LEAD_TIME_FOR_CHANGES_SECONDARY_SERIES_NAME","DEPLOYMENT_FREQUENCY_SECONDARY_SERIES_NAME","CHANGE_FAILURE_RATE_SECONDARY_SERIES_NAME","TIME_TO_RESTORE_SERVICE_SECONDARY_SERIES_NAME","DORA_METRICS_SECONDARY_SERIES_NAME","VSA_METRICS_GROUPS","key","title","keys","VULNERABILITY_METRICS","CRITICAL","HIGH","MERGE_REQUEST_METRICS","THROUGHPUT","CONTRIBUTOR_METRICS","AI_METRICS","CODE_SUGGESTIONS_USAGE_RATE","CODE_SUGGESTIONS_ACCEPTANCE_RATE","DUO_CHAT_USAGE_RATE","DUO_USAGE_RATE","VALUE_STREAM_METRIC_DISPLAY_UNITS","VALUE_STREAM_METRIC_TILE_METADATA","label","unit","description","groupLink","projectLink","docsLink","helpPagePath","anchor","VALUE_STREAM_METRIC_METADATA","USAGE_OVERVIEW_NO_DATA_ERROR","USAGE_OVERVIEW_DEFAULT_DATE_RANGE","nYearsBefore","USAGE_OVERVIEW_IDENTIFIER_GROUPS","USAGE_OVERVIEW_IDENTIFIER_PROJECTS","USAGE_OVERVIEW_IDENTIFIER_USERS","USAGE_OVERVIEW_IDENTIFIER_ISSUES","USAGE_OVERVIEW_IDENTIFIER_MERGE_REQUESTS","USAGE_OVERVIEW_IDENTIFIER_PIPELINES","USAGE_OVERVIEW_METADATA","options","titleIcon","USAGE_OVERVIEW_QUERY_INCLUDE_KEYS","USAGE_OVERVIEW_GROUP_ONLY_IDENTIFIERS","Set","noop","setToArray","createSet","values","uniqueTokens","tokens","knownTokens","reduce","uniques","token","type","FILTERED_SEARCH_TERM","tokenString","operator","data","includes","push","createToken","filter","prepareTokens","filters","Object","memo","Array","isArray","map","filterValue","processFilters","acc","_token$value","_token$value2","filteredSearchQueryParam","join","trim","filterToQueryObject","filteredSearchTermKey","customOperators","shouldExcludeEmpty","operators","prefix","result","op","applyOnlyToKey","_value","item","_isEmpty","filteredSearchTermValue","term","urlQueryToFilter","query","filterNamesAllowList","_isString","queryToObject","gatherArrays","filterName","find","startsWith","endsWith","slice","extractNameAndOperator","previousValues","newAdditions","Boolean","getRecentlyUsedSuggestions","recentSuggestionsStorageKey","appliedTokens","valueIdentifier","recentlyUsedSuggestions","AccessorUtilities","canUseLocalStorage","JSON","parse","localStorage","getItem","suggestion","some","appliedToken","setTokenValueToRecentlyUsed","tokenValue","splice","setItem","stringify","_uniqWith","_isEqual","MAX_RECENT_TOKENS_SIZE","filterEmptySearchTerm","filterTokens","SetCache","arrayIncludes","arrayIncludesWith","cacheHas","iteratee","isCommon","seen","set","outer","computed","seenIndex","filterBySearchTerm","searchTerm","filterByKey","toLowerCase","toYmd","date","extractFilterQueryParameters","url","source_branch_name","selectedSourceBranch","target_branch_name","selectedTargetBranch","author_username","selectedAuthor","milestone_title","selectedMilestone","assignee_username","selectedAssigneeList","label_name","selectedLabelList","extractPaginationQueryParameters","sort","direction","page","getDataZoomOption","totalItems","maxItemsPerPage","dataZoom","bottom","start","intervalEnd","Math","ceil","end","formatAsPercentageWithoutSymbol","decimalValue","precision","Number","isNaN","toFixed","secondsToDays","seconds","SECONDS_IN_DAY","scaledValueForDisplay","units","prepareMetricValue","identifier","rawMetricToMetricTile","metric","metricRest","metadataRest","generateValueStreamsDashboardLink","namespacePath","isProjectNamespace","formattedNamespacePath","segments","gon","relative_url_root","joinPaths","extractVSAFeaturesFromGON","_gon","_gon2","_gon3","cycleAnalyticsForGroups","licensed_features","cycleAnalyticsForProjects","groupLevelAnalyticsDashboard","extractQueryResponseFromNamespace","resultKey","group","project","overviewMetricsRequestParams","params","createdAfter","createdBefore","labelName","labelNames","assigneeUsername","assigneeUsernames","rest","convertObjectPropsToCamelCase","baseUniq","undefined"],"mappings":"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","file":"16.18f3aa66.chunk.js","sourcesContent":["/**\n * This function is like `arrayIncludes` except that it accepts a comparator.\n *\n * @private\n * @param {Array} [array] The array to inspect.\n * @param {*} target The value to search for.\n * @param {Function} comparator The comparator invoked per element.\n * @returns {boolean} Returns `true` if `target` is found, else `false`.\n */\nfunction arrayIncludesWith(array, value, comparator) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (comparator(value, array[index])) {\n return true;\n }\n }\n return false;\n}\n\nmodule.exports = arrayIncludesWith;\n","import dateFormat, { masks } from '~/lib/dateformat';\nimport {\n nDaysBefore,\n getStartOfDay,\n getCurrentUtcDate,\n nWeeksBefore,\n nYearsBefore,\n} from '~/lib/utils/datetime_utility';\nimport { s__, __, sprintf, n__ } from '~/locale';\nimport { helpPagePath } from '~/helpers/help_page_helper';\n\nexport const DATE_RANGE_LIMIT = 180;\nexport const PROJECTS_PER_PAGE = 50;\n\nconst { isoDate } = masks;\nexport const dateFormats = {\n isoDate,\n defaultDate: 'mmm dd, yyyy',\n defaultDateTime: 'mmm dd, yyyy h:MMtt',\n month: 'mmmm',\n};\n\nconst TODAY = getCurrentUtcDate();\nconst SAME_DAY_OFFSET = 1;\n\nconst startOfToday = getStartOfDay(new Date(), { utc: true });\n\nexport const LAST_30_DAYS = nDaysBefore(TODAY, 30 - SAME_DAY_OFFSET, { utc: true });\n\nconst lastXDays = __('Last %{days} days');\nconst lastWeek = nWeeksBefore(TODAY, 1, { utc: true });\nconst last90Days = nDaysBefore(TODAY, 90 - SAME_DAY_OFFSET, { utc: true });\nconst last180Days = nDaysBefore(TODAY, 180 - SAME_DAY_OFFSET, { utc: true });\nconst mrThroughputStartDate = nDaysBefore(startOfToday, DATE_RANGE_LIMIT, { utc: true });\nconst formatDateParam = (d) => dateFormat(d, dateFormats.isoDate, true);\n\nexport const DATE_RANGE_CUSTOM_VALUE = 'custom';\nexport const DATE_RANGE_LAST_30_DAYS_VALUE = 'last_30_days';\n\nexport const DEFAULT_DROPDOWN_DATE_RANGES = [\n {\n text: __('Last week'),\n value: 'last_week',\n startDate: lastWeek,\n endDate: TODAY,\n },\n {\n text: sprintf(lastXDays, { days: 30 }),\n value: DATE_RANGE_LAST_30_DAYS_VALUE,\n startDate: LAST_30_DAYS,\n endDate: TODAY,\n },\n {\n text: sprintf(lastXDays, { days: 90 }),\n value: 'last_90_days',\n startDate: last90Days,\n endDate: TODAY,\n },\n {\n text: sprintf(lastXDays, { days: 180 }),\n value: 'last_180_days',\n startDate: last180Days,\n endDate: TODAY,\n },\n];\n\nexport const MAX_DATE_RANGE_TEXT = (maxDateRange) => {\n return sprintf(\n __(\n 'Showing data for workflow items completed in this date range. Date range limited to %{maxDateRange} days.',\n ),\n {\n maxDateRange,\n },\n );\n};\n\n// Limits the number of decimals we round values to\nexport const MAX_METRIC_PRECISION = 4;\n\nexport const UNITS = {\n COUNT: 'COUNT',\n DAYS: 'DAYS',\n PER_DAY: 'PER_DAY',\n PERCENT: 'PERCENT',\n};\n\nexport const NUMBER_OF_DAYS_SELECTED = (numDays) => {\n return n__('1 day selected', '%d days selected', numDays);\n};\n\nexport const METRIC_POPOVER_LABEL = s__('ValueStreamAnalytics|View details');\n\nexport const ISSUES_COMPLETED_TYPE = 'issues_completed';\n\nexport const ALL_METRICS_QUERY_TYPE = 'ALL_METRICS_QUERY_TYPE';\nexport const DORA_METRICS_QUERY_TYPE = 'DORA_METRICS_QUERY_TYPE';\nexport const FLOW_METRICS_QUERY_TYPE = 'FLOW_METRICS_QUERY_TYPE';\n\nexport const FLOW_METRICS = {\n LEAD_TIME: 'lead_time',\n CYCLE_TIME: 'cycle_time',\n ISSUES: 'issues',\n ISSUES_COMPLETED: ISSUES_COMPLETED_TYPE,\n COMMITS: 'commits',\n DEPLOYS: 'deploys',\n MEDIAN_TIME_TO_MERGE: 'median_time_to_merge',\n};\n\nexport const DORA_METRICS = {\n DEPLOYMENT_FREQUENCY: 'deployment_frequency',\n LEAD_TIME_FOR_CHANGES: 'lead_time_for_changes',\n TIME_TO_RESTORE_SERVICE: 'time_to_restore_service',\n CHANGE_FAILURE_RATE: 'change_failure_rate',\n};\n\nexport const LEAD_TIME_NO_DATA_MESSAGE = s__(\n 'DORA4Metrics|No merge requests were deployed during this period',\n);\n\nexport const DORA_METRICS_NULL_SERIES_TITLE = {\n [DORA_METRICS.CHANGE_FAILURE_RATE]: s__('DORA4Metrics|No incidents during this period'),\n [DORA_METRICS.TIME_TO_RESTORE_SERVICE]: s__('DORA4Metrics|No incidents during this period'),\n [DORA_METRICS.LEAD_TIME_FOR_CHANGES]: LEAD_TIME_NO_DATA_MESSAGE,\n [DORA_METRICS.DEPLOYMENT_FREQUENCY]: s__('DORA4Metrics|No deployments during this period'),\n};\n\nexport const LEAD_TIME_FOR_CHANGES_SECONDARY_SERIES_NAME = s__(\n 'DORA4Metrics|Median (last %{days}d)',\n);\nexport const DEPLOYMENT_FREQUENCY_SECONDARY_SERIES_NAME = s__(\n 'DORA4Metrics|Average (last %{days}d)',\n);\nexport const CHANGE_FAILURE_RATE_SECONDARY_SERIES_NAME = s__(\n 'DORA4Metrics|Median time (last %{days}d)',\n);\nexport const TIME_TO_RESTORE_SERVICE_SECONDARY_SERIES_NAME = s__(\n 'DORA4Metrics|Median time (last %{days}d)',\n);\n\nexport const DORA_METRICS_SECONDARY_SERIES_NAME = {\n [DORA_METRICS.CHANGE_FAILURE_RATE]: CHANGE_FAILURE_RATE_SECONDARY_SERIES_NAME,\n [DORA_METRICS.DEPLOYMENT_FREQUENCY]: DEPLOYMENT_FREQUENCY_SECONDARY_SERIES_NAME,\n [DORA_METRICS.TIME_TO_RESTORE_SERVICE]: TIME_TO_RESTORE_SERVICE_SECONDARY_SERIES_NAME,\n [DORA_METRICS.LEAD_TIME_FOR_CHANGES]: LEAD_TIME_FOR_CHANGES_SECONDARY_SERIES_NAME,\n};\n\nexport const VSA_METRICS_GROUPS = [\n {\n key: 'lifecycle_metrics',\n title: s__('ValueStreamAnalytics|Lifecycle metrics'),\n keys: [\n FLOW_METRICS.LEAD_TIME,\n FLOW_METRICS.CYCLE_TIME,\n FLOW_METRICS.ISSUES,\n FLOW_METRICS.COMMITS,\n FLOW_METRICS.DEPLOYS,\n ],\n },\n];\n\nexport const VULNERABILITY_CRITICAL_TYPE = 'vulnerability_critical';\nexport const VULNERABILITY_HIGH_TYPE = 'vulnerability_high';\n\nexport const VULNERABILITY_METRICS = {\n CRITICAL: VULNERABILITY_CRITICAL_TYPE,\n HIGH: VULNERABILITY_HIGH_TYPE,\n};\n\nexport const MERGE_REQUEST_THROUGHPUT_TYPE = 'merge_request_throughput';\n\nexport const MERGE_REQUEST_METRICS = {\n THROUGHPUT: MERGE_REQUEST_THROUGHPUT_TYPE,\n};\n\nexport const CONTRIBUTOR_COUNT_TYPE = 'contributor_count';\n\nexport const CONTRIBUTOR_METRICS = {\n COUNT: CONTRIBUTOR_COUNT_TYPE,\n};\n\nexport const AI_METRICS = {\n CODE_SUGGESTIONS_USAGE_RATE: 'code_suggestions_usage_rate',\n CODE_SUGGESTIONS_ACCEPTANCE_RATE: 'code_suggestions_acceptance_rate',\n DUO_CHAT_USAGE_RATE: 'duo_chat_usage_rate',\n DUO_USAGE_RATE: 'duo_usage_rate',\n};\n\nexport const VALUE_STREAM_METRIC_DISPLAY_UNITS = {\n [UNITS.COUNT]: '',\n [UNITS.DAYS]: __('days'),\n [UNITS.PER_DAY]: __('/day'),\n [UNITS.PERCENT]: '%',\n};\n\n// NOTE: ideally we would return these fields in the metrics queries\n// the flow metrics query returns some but not all fields we need\n// while the DORA query do not return any.\nexport const VALUE_STREAM_METRIC_TILE_METADATA = {\n [DORA_METRICS.DEPLOYMENT_FREQUENCY]: {\n label: s__('DORA4Metrics|Deployment frequency'),\n unit: UNITS.PER_DAY,\n description: s__(\n 'ValueStreamAnalytics|Average number of deployments to production per day. This metric measures how often value is delivered to end users.',\n ),\n groupLink: '-/analytics/ci_cd?tab=deployment-frequency',\n projectLink: '-/pipelines/charts?chart=deployment-frequency',\n docsLink: helpPagePath('user/analytics/dora_metrics', { anchor: 'deployment-frequency' }),\n },\n [DORA_METRICS.LEAD_TIME_FOR_CHANGES]: {\n label: s__('DORA4Metrics|Lead time for changes'),\n unit: UNITS.DAYS,\n description: s__(\n 'ValueStreamAnalytics|The time to successfully deliver a commit into production. This metric reflects the efficiency of CI/CD pipelines.',\n ),\n groupLink: '-/analytics/ci_cd?tab=lead-time',\n projectLink: '-/pipelines/charts?chart=lead-time',\n docsLink: helpPagePath('user/analytics/dora_metrics', { anchor: 'lead-time-for-changes' }),\n },\n [DORA_METRICS.TIME_TO_RESTORE_SERVICE]: {\n label: s__('DORA4Metrics|Time to restore service'),\n unit: UNITS.DAYS,\n description: s__(\n 'ValueStreamAnalytics|The time it takes an organization to recover from a failure in production.',\n ),\n groupLink: '-/analytics/ci_cd?tab=time-to-restore-service',\n projectLink: '-/pipelines/charts?chart=time-to-restore-service',\n docsLink: helpPagePath('user/analytics/dora_metrics', { anchor: 'time-to-restore-service' }),\n },\n [DORA_METRICS.CHANGE_FAILURE_RATE]: {\n label: s__('DORA4Metrics|Change failure rate'),\n description: s__(\n 'ValueStreamAnalytics|Percentage of deployments that cause an incident in production.',\n ),\n groupLink: '-/analytics/ci_cd?tab=change-failure-rate',\n projectLink: '-/pipelines/charts?chart=change-failure-rate',\n docsLink: helpPagePath('user/analytics/dora_metrics', { anchor: 'change-failure-rate' }),\n unit: UNITS.PERCENT,\n },\n [FLOW_METRICS.LEAD_TIME]: {\n label: s__('DORA4Metrics|Lead time'),\n description: s__('ValueStreamAnalytics|Median time from issue created to issue closed.'),\n groupLink: '-/analytics/value_stream_analytics',\n projectLink: '-/value_stream_analytics',\n docsLink: helpPagePath('user/group/value_stream_analytics/_index', {\n anchor: 'lifecycle-metrics',\n }),\n unit: UNITS.DAYS,\n },\n [FLOW_METRICS.CYCLE_TIME]: {\n label: s__('DORA4Metrics|Cycle time'),\n description: s__(\n \"ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed.\",\n ),\n groupLink: '-/analytics/value_stream_analytics',\n projectLink: '-/value_stream_analytics',\n docsLink: helpPagePath('user/group/value_stream_analytics/_index', {\n anchor: 'lifecycle-metrics',\n }),\n unit: UNITS.DAYS,\n },\n [FLOW_METRICS.ISSUES]: {\n label: s__('DORA4Metrics|New issues'),\n unit: UNITS.COUNT,\n description: s__('ValueStreamAnalytics|Number of new issues created.'),\n groupLink: '-/issues_analytics',\n projectLink: '-/analytics/issues_analytics',\n docsLink: helpPagePath('user/group/issues_analytics/_index'),\n },\n [FLOW_METRICS.COMMITS]: {\n label: s__('DORA4Metrics|Commits'),\n unit: UNITS.COUNT,\n description: s__('ValueStreamAnalytics|Number of commits pushed to the default branch'),\n },\n [FLOW_METRICS.DEPLOYS]: {\n label: s__('DORA4Metrics|Deploys'),\n unit: UNITS.COUNT,\n description: s__('ValueStreamAnalytics|Total number of deploys to production.'),\n groupLink: '-/analytics/productivity_analytics',\n projectLink: '-/analytics/merge_request_analytics',\n docsLink: helpPagePath('user/analytics/merge_request_analytics'),\n },\n};\n\nexport const VALUE_STREAM_METRIC_METADATA = {\n ...VALUE_STREAM_METRIC_TILE_METADATA,\n [FLOW_METRICS.ISSUES_COMPLETED]: {\n description: s__('ValueStreamAnalytics|Number of issues closed by month.'),\n groupLink: '-/issues_analytics',\n projectLink: '-/analytics/issues_analytics',\n docsLink: helpPagePath('user/group/issues_analytics/_index'),\n },\n [CONTRIBUTOR_METRICS.COUNT]: {\n description: s__(\n 'ValueStreamAnalytics|Number of monthly unique users with contributions in the group.',\n ),\n groupLink: '-/contribution_analytics',\n docsLink: helpPagePath('user/profile/contributions_calendar.html', {\n anchor: 'user-contribution-events',\n }),\n },\n [VULNERABILITY_METRICS.CRITICAL]: {\n description: s__(\n 'ValueStreamAnalytics|Number of critical vulnerabilities identified per month.',\n ),\n groupLink: '-/security/vulnerabilities?severity=CRITICAL',\n projectLink: '-/security/vulnerability_report?severity=CRITICAL',\n docsLink: helpPagePath('user/application_security/vulnerabilities/severities.html'),\n },\n [VULNERABILITY_METRICS.HIGH]: {\n description: s__('ValueStreamAnalytics|High vulnerabilities over time.'),\n groupLink: '-/security/vulnerabilities?severity=HIGH',\n projectLink: '-/security/vulnerability_report?severity=HIGH',\n docsLink: helpPagePath('user/application_security/vulnerabilities/severities.html'),\n },\n [MERGE_REQUEST_METRICS.THROUGHPUT]: {\n description: s__('ValueStreamAnalytics|Number of merge requests merged by month.'),\n groupLink: '-/analytics/productivity_analytics',\n projectLink: `-/analytics/merge_request_analytics?start_date=${formatDateParam(\n mrThroughputStartDate,\n )}&end_date=${formatDateParam(startOfToday)}`,\n docsLink: helpPagePath('user/analytics/merge_request_analytics', {\n anchor: 'view-the-number-of-merge-requests-in-a-date-range',\n }),\n },\n [FLOW_METRICS.MEDIAN_TIME_TO_MERGE]: {\n description: s__(\n 'ValueStreamAnalytics|Median time between merge request created and merge request merged.',\n ),\n groupLink: '-/analytics/productivity_analytics',\n projectLink: '-/analytics/merge_request_analytics',\n docsLink: helpPagePath('user/analytics/merge_request_analytics'),\n },\n [AI_METRICS.CODE_SUGGESTIONS_USAGE_RATE]: {\n description: s__(\n 'AiImpactAnalytics|Monthly user engagement with GitLab Duo Code Suggestions. Percentage ratio calculated as monthly unique Code Suggestions users / total monthly unique code contributors.',\n ),\n groupLink: '',\n projectLink: '',\n docsLink: helpPagePath('user/project/repository/code_suggestions/_index'),\n },\n [AI_METRICS.CODE_SUGGESTIONS_ACCEPTANCE_RATE]: {\n description: s__(\n 'AiImpactAnalytics|Monthly GitLab Duo Code Suggestions accepted / total Code Suggestions generated.',\n ),\n groupLink: '',\n projectLink: '',\n docsLink: helpPagePath('user/project/repository/code_suggestions/_index', {\n anchor: 'use-code-suggestions',\n }),\n },\n [AI_METRICS.DUO_CHAT_USAGE_RATE]: {\n description: s__(\n 'AiImpactAnalytics|Monthly user engagement with AI Code Suggestions. Percentage ratio calculated as monthly unique Code Suggestions users / total monthly unique code contributors.',\n ),\n groupLink: '',\n projectLink: '',\n docsLink: helpPagePath('user/gitlab_duo_chat/_index'),\n },\n};\n\nexport const USAGE_OVERVIEW_NO_DATA_ERROR = s__(\n 'ValueStreamAnalytics|Failed to load usage overview data',\n);\n\nexport const USAGE_OVERVIEW_DEFAULT_DATE_RANGE = {\n endDate: TODAY,\n startDate: nYearsBefore(TODAY, 1),\n};\n\nexport const USAGE_OVERVIEW_IDENTIFIER_GROUPS = 'groups';\nexport const USAGE_OVERVIEW_IDENTIFIER_PROJECTS = 'projects';\nexport const USAGE_OVERVIEW_IDENTIFIER_USERS = 'users';\nexport const USAGE_OVERVIEW_IDENTIFIER_ISSUES = 'issues';\nexport const USAGE_OVERVIEW_IDENTIFIER_MERGE_REQUESTS = 'merge_requests';\nexport const USAGE_OVERVIEW_IDENTIFIER_PIPELINES = 'pipelines';\n\n// Defines the constants used for querying the API as well as the order they appear\nexport const USAGE_OVERVIEW_METADATA = {\n [USAGE_OVERVIEW_IDENTIFIER_GROUPS]: { options: { title: __('Groups'), titleIcon: 'group' } },\n [USAGE_OVERVIEW_IDENTIFIER_PROJECTS]: {\n options: { title: __('Projects'), titleIcon: 'project' },\n },\n [USAGE_OVERVIEW_IDENTIFIER_USERS]: {\n options: { title: __('Users'), titleIcon: 'user' },\n },\n [USAGE_OVERVIEW_IDENTIFIER_ISSUES]: {\n options: { title: __('Issues'), titleIcon: 'issues' },\n },\n [USAGE_OVERVIEW_IDENTIFIER_MERGE_REQUESTS]: {\n options: { title: __('Merge requests'), titleIcon: 'merge-request' },\n },\n [USAGE_OVERVIEW_IDENTIFIER_PIPELINES]: {\n options: { title: __('Pipelines'), titleIcon: 'pipeline' },\n },\n};\n\nexport const USAGE_OVERVIEW_QUERY_INCLUDE_KEYS = {\n [USAGE_OVERVIEW_IDENTIFIER_GROUPS]: 'includeGroups',\n [USAGE_OVERVIEW_IDENTIFIER_PROJECTS]: 'includeProjects',\n [USAGE_OVERVIEW_IDENTIFIER_USERS]: 'includeUsers',\n [USAGE_OVERVIEW_IDENTIFIER_ISSUES]: 'includeIssues',\n [USAGE_OVERVIEW_IDENTIFIER_MERGE_REQUESTS]: 'includeMergeRequests',\n [USAGE_OVERVIEW_IDENTIFIER_PIPELINES]: 'includePipelines',\n};\n\nexport const USAGE_OVERVIEW_GROUP_ONLY_IDENTIFIERS = [\n USAGE_OVERVIEW_IDENTIFIER_GROUPS,\n USAGE_OVERVIEW_IDENTIFIER_USERS,\n USAGE_OVERVIEW_IDENTIFIER_PROJECTS,\n];\n","var Set = require('./_Set'),\n noop = require('./noop'),\n setToArray = require('./_setToArray');\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0;\n\n/**\n * Creates a set object of `values`.\n *\n * @private\n * @param {Array} values The values to add to the set.\n * @returns {Object} Returns the new set.\n */\nvar createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {\n return new Set(values);\n};\n\nmodule.exports = createSet;\n","import { isEmpty, uniqWith, isEqual, isString } from 'lodash';\nimport AccessorUtilities from '~/lib/utils/accessor';\nimport { queryToObject } from '~/lib/utils/url_utility';\n\nimport { MAX_RECENT_TOKENS_SIZE, FILTERED_SEARCH_TERM } from './constants';\n\n/**\n * This method removes duplicate tokens from tokens array.\n *\n * @param {Array} tokens Array of tokens as defined by `GlFilteredSearch`\n *\n * @returns {Array} Unique array of tokens\n */\nexport const uniqueTokens = (tokens) => {\n const knownTokens = [];\n return tokens.reduce((uniques, token) => {\n if (typeof token === 'object' && token.type !== FILTERED_SEARCH_TERM) {\n const tokenString = `${token.type}${token.value.operator}${token.value.data}`;\n if (!knownTokens.includes(tokenString)) {\n uniques.push(token);\n knownTokens.push(tokenString);\n }\n } else {\n uniques.push(token);\n }\n return uniques;\n }, []);\n};\n\n/**\n * Creates a token from a type and a filter. Example returned object\n * { type: 'myType', value: { data: 'myData', operator: '= '} }\n * @param {String} type the name of the filter\n * @param {Object}\n * @param {Object.value} filter value to be returned as token data\n * @param {Object.operator} filter operator to be retuned as token operator\n * @return {Object}\n * @return {Object.type} token type\n * @return {Object.value} token value\n */\nfunction createToken(type, filter) {\n return { type, value: { data: filter.value, operator: filter.operator } };\n}\n\n/**\n * This function takes a filter object and translates it into a token array\n * @param {Object} filters\n * @param {Object.myFilterName} a single filter value or an array of filters\n * @return {Array} tokens an array of tokens created from filter values\n */\nexport function prepareTokens(filters = {}) {\n return Object.keys(filters).reduce((memo, key) => {\n const value = filters[key];\n if (!value) {\n return memo;\n }\n if (Array.isArray(value)) {\n return [...memo, ...value.map((filterValue) => createToken(key, filterValue))];\n }\n\n return [...memo, createToken(key, value)];\n }, []);\n}\n\n/**\n * This function takes a token array and translates it into a filter object\n * @param filters\n * @returns A Filter Object\n */\nexport function processFilters(filters) {\n return filters.reduce((acc, token) => {\n let type;\n let value;\n let operator;\n if (typeof token === 'string') {\n type = FILTERED_SEARCH_TERM;\n value = token;\n } else {\n type = token?.type;\n operator = token?.value?.operator;\n value = token?.value?.data;\n }\n\n if (!acc[type]) {\n acc[type] = [];\n }\n\n acc[type].push({ value, operator });\n return acc;\n }, {});\n}\n\nfunction filteredSearchQueryParam(filter) {\n return filter\n .map(({ value }) => value)\n .join(' ')\n .trim();\n}\n\n/**\n * This function takes a filter object and maps it into a query object. Example filter:\n * { myFilterName: { value: 'foo', operator: '=' }, search: [{ value: 'my' }, { value: 'search' }] }\n * gets translated into:\n * { myFilterName: 'foo', 'not[myFilterName]': null, search: 'my search' }\n * By default it supports '=' and '!=' operators. This can be extended by providing the `customOperators` option\n * @param {Object} filters\n * @param {Object} filters.myFilterName a single filter value or an array of filters\n * @param {Object} options\n * @param {Object} [options.filteredSearchTermKey] if set, 'filtered-search-term' filters are assigned to this key, 'search' is suggested\n * @param {Object} [options.customOperators] Allows to extend the supported operators, e.g.\n *\n * filterToQueryObject({foo: [{ value: '100', operator: '>' }]}, {customOperators: {operator: '>',prefix: 'gt'}})\n * returns {gt[foo]: '100'}\n * It's also possible to restrict custom operators to a given key by setting `applyOnlyToKey` string attribute.\n *\n * @return {Object} query object with both filter name and not-name with values\n */\nexport function filterToQueryObject(filters = {}, options = {}) {\n const { filteredSearchTermKey, customOperators, shouldExcludeEmpty = false } = options;\n\n return Object.keys(filters).reduce((memo, key) => {\n const filter = filters[key];\n\n if (typeof filteredSearchTermKey === 'string' && key === FILTERED_SEARCH_TERM && filter) {\n const combinedFilteredSearchTerm = filteredSearchQueryParam(filter);\n if (combinedFilteredSearchTerm === '' && shouldExcludeEmpty) {\n return memo;\n }\n\n return { ...memo, [filteredSearchTermKey]: filteredSearchQueryParam(filter) };\n }\n\n const operators = [\n { operator: '=' },\n { operator: '!=', prefix: 'not' },\n ...(customOperators ?? []),\n ];\n\n const result = {};\n\n for (const op of operators) {\n const { operator, prefix, applyOnlyToKey } = op;\n\n if (!applyOnlyToKey || applyOnlyToKey === key) {\n let value;\n if (Array.isArray(filter)) {\n value = filter.filter((item) => item.operator === operator).map((item) => item.value);\n } else {\n value = filter?.operator === operator ? filter.value : null;\n }\n\n if (isEmpty(value)) {\n value = null;\n }\n\n if (shouldExcludeEmpty && (value?.[0] === '' || value === '' || value === null)) {\n // eslint-disable-next-line no-continue\n continue;\n }\n\n if (prefix) {\n result[`${prefix}[${key}]`] = value;\n } else {\n result[key] = value;\n }\n }\n }\n\n return { ...memo, ...result };\n }, {});\n}\n\n/**\n * Extracts filter name from url name and operator, e.g.\n * e.g. input: not[my_filter]` output: {filterName: `my_filter`, operator: '!='}`\n *\n * By default it supports filter with the format `my_filter=foo` and `not[my_filter]=bar`. This can be extended with the `customOperators` option.\n * @param {String} filterName from url\n * @param {Object.customOperators} It allows to extend the supported parameter, e.g.\n * input: 'gt[filter]', { customOperators: [{ operator: '>', prefix: 'gt' }]})\n * output: '{filterName: 'filter', operator: '>'}\n * @return {Object}\n * @return {Object.filterName} extracted filter name\n * @return {Object.operator} `=` or `!=`\n */\nfunction extractNameAndOperator(filterName, customOperators) {\n const ops = [\n {\n prefix: 'not',\n operator: '!=',\n },\n ...(customOperators ?? []),\n ];\n\n const operator = ops.find(\n ({ prefix }) => filterName.startsWith(`${prefix}[`) && filterName.endsWith(']'),\n );\n\n if (!operator) {\n return { filterName, operator: '=' };\n }\n const { prefix } = operator;\n return { filterName: filterName.slice(prefix.length + 1, -1), operator: operator.operator };\n}\n\n/**\n * Gathers search term as values\n * @param {String|Array} value\n * @returns {Array} List of search terms split by word\n */\nfunction filteredSearchTermValue(value) {\n const values = Array.isArray(value) ? value : [value];\n return [{ value: values.filter((term) => term).join(' ') }];\n}\n\n/**\n * This function takes a URL query string and maps it into a filter object. Example query string:\n * '?myFilterName=foo'\n * gets translated into:\n * { myFilterName: { value: 'foo', operator: '=' } }\n * By default it only support '=' and '!=' operators. This can be extended with the customOperator option.\n * @param {String|Object} query URL query string or object, e.g. from `window.location.search` or `this.$route.query`\n * @param {Object} options\n * @param {String} [options.filteredSearchTermKey] if set, a FILTERED_SEARCH_TERM filter is created to this parameter. `'search'` is suggested\n * @param {String[]} [options.filterNamesAllowList] if set, only this list of filters names is mapped\n * @param {Object} [options.customOperator] It allows to extend the supported parameter, e.g.\n * input: 'gt[myFilter]=100', { customOperators: [{ operator: '>', prefix: 'gt' }]})\n * output: '{ myFilter: {value: '100', operator: '>'}}\n * @return {Object} filter object with filter names and their values\n */\nexport function urlQueryToFilter(\n query = '',\n { filteredSearchTermKey, filterNamesAllowList, customOperators } = {},\n) {\n const filters = isString(query) ? queryToObject(query, { gatherArrays: true }) : query;\n return Object.keys(filters).reduce((memo, key) => {\n const value = filters[key];\n if (!value) {\n return memo;\n }\n if (key === filteredSearchTermKey) {\n return {\n ...memo,\n [FILTERED_SEARCH_TERM]: filteredSearchTermValue(value),\n };\n }\n\n const { filterName, operator } = extractNameAndOperator(key, customOperators);\n if (filterNamesAllowList && !filterNamesAllowList.includes(filterName)) {\n return memo;\n }\n let previousValues = [];\n if (Array.isArray(memo[filterName])) {\n previousValues = memo[filterName];\n }\n if (Array.isArray(value)) {\n const newAdditions = value.filter(Boolean).map((item) => ({ value: item, operator }));\n return { ...memo, [filterName]: [...previousValues, ...newAdditions] };\n }\n\n return { ...memo, [filterName]: { value, operator } };\n }, {});\n}\n\n/**\n * Returns array of token values from localStorage\n * based on provided recentSuggestionsStorageKey\n *\n * @param {String} recentSuggestionsStorageKey\n * @param {Array} appliedTokens\n * @param {Function} valueIdentifier\n * @returns\n */\nexport function getRecentlyUsedSuggestions(\n recentSuggestionsStorageKey,\n appliedTokens,\n valueIdentifier,\n) {\n let recentlyUsedSuggestions = [];\n if (AccessorUtilities.canUseLocalStorage()) {\n recentlyUsedSuggestions = JSON.parse(localStorage.getItem(recentSuggestionsStorageKey)) || [];\n }\n return recentlyUsedSuggestions.filter((suggestion) => {\n return !appliedTokens?.some(\n (appliedToken) => appliedToken.value.data === valueIdentifier(suggestion),\n );\n });\n}\n\n/**\n * Sets provided token value to recently used array\n * within localStorage for provided recentSuggestionsStorageKey\n *\n * @param {String} recentSuggestionsStorageKey\n * @param {Object} tokenValue\n */\nexport function setTokenValueToRecentlyUsed(recentSuggestionsStorageKey, tokenValue) {\n const recentlyUsedSuggestions = getRecentlyUsedSuggestions(recentSuggestionsStorageKey);\n\n recentlyUsedSuggestions.splice(0, 0, { ...tokenValue });\n\n if (AccessorUtilities.canUseLocalStorage()) {\n localStorage.setItem(\n recentSuggestionsStorageKey,\n JSON.stringify(uniqWith(recentlyUsedSuggestions, isEqual).slice(0, MAX_RECENT_TOKENS_SIZE)),\n );\n }\n}\n\n/**\n * Removes `FILTERED_SEARCH_TERM` tokens with empty data\n *\n * @param filterTokens array of filtered search tokens\n * @return {Array} array of filtered search tokens\n */\nexport const filterEmptySearchTerm = (filterTokens = []) =>\n filterTokens.filter((token) => token.type === FILTERED_SEARCH_TERM && token.value.data);\n","var SetCache = require('./_SetCache'),\n arrayIncludes = require('./_arrayIncludes'),\n arrayIncludesWith = require('./_arrayIncludesWith'),\n cacheHas = require('./_cacheHas'),\n createSet = require('./_createSet'),\n setToArray = require('./_setToArray');\n\n/** Used as the size to enable large array optimizations. */\nvar LARGE_ARRAY_SIZE = 200;\n\n/**\n * The base implementation of `_.uniqBy` without support for iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new duplicate free array.\n */\nfunction baseUniq(array, iteratee, comparator) {\n var index = -1,\n includes = arrayIncludes,\n length = array.length,\n isCommon = true,\n result = [],\n seen = result;\n\n if (comparator) {\n isCommon = false;\n includes = arrayIncludesWith;\n }\n else if (length >= LARGE_ARRAY_SIZE) {\n var set = iteratee ? null : createSet(array);\n if (set) {\n return setToArray(set);\n }\n isCommon = false;\n includes = cacheHas;\n seen = new SetCache;\n }\n else {\n seen = iteratee ? [] : result;\n }\n outer:\n while (++index < length) {\n var value = array[index],\n computed = iteratee ? iteratee(value) : value;\n\n value = (comparator || value !== 0) ? value : 0;\n if (isCommon && computed === computed) {\n var seenIndex = seen.length;\n while (seenIndex--) {\n if (seen[seenIndex] === computed) {\n continue outer;\n }\n }\n if (iteratee) {\n seen.push(computed);\n }\n result.push(value);\n }\n else if (!includes(seen, computed, comparator)) {\n if (seen !== result) {\n seen.push(computed);\n }\n result.push(value);\n }\n }\n return result;\n}\n\nmodule.exports = baseUniq;\n","import dateFormat from '~/lib/dateformat';\nimport { SECONDS_IN_DAY } from '~/lib/utils/datetime_utility';\nimport { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';\nimport { joinPaths } from '~/lib/utils/url_utility';\nimport { urlQueryToFilter } from '~/vue_shared/components/filtered_search_bar/filtered_search_utils';\nimport {\n dateFormats,\n FLOW_METRICS,\n MAX_METRIC_PRECISION,\n UNITS,\n VALUE_STREAM_METRIC_DISPLAY_UNITS,\n VALUE_STREAM_METRIC_TILE_METADATA,\n} from './constants';\n\nexport const filterBySearchTerm = (data = [], searchTerm = '', filterByKey = 'name') => {\n if (!searchTerm?.length) return data;\n return data.filter((item) => item[filterByKey].toLowerCase().includes(searchTerm.toLowerCase()));\n};\n\nexport const toYmd = (date) => dateFormat(date, dateFormats.isoDate);\n\n/**\n * Takes a url and extracts query parameters used for the shared\n * filter bar\n *\n * @param {string} url The URL to extract query parameters from\n * @returns {Object}\n */\nexport const extractFilterQueryParameters = (url = '') => {\n const {\n source_branch_name: selectedSourceBranch = null,\n target_branch_name: selectedTargetBranch = null,\n author_username: selectedAuthor = null,\n milestone_title: selectedMilestone = null,\n assignee_username: selectedAssigneeList = [],\n label_name: selectedLabelList = [],\n } = urlQueryToFilter(url);\n\n return {\n selectedSourceBranch,\n selectedTargetBranch,\n selectedAuthor,\n selectedMilestone,\n selectedAssigneeList,\n selectedLabelList,\n };\n};\n\n/**\n * Takes a url and extracts sorting and pagination query parameters into an object\n *\n * @param {string} url The URL to extract query parameters from\n * @returns {Object}\n */\nexport const extractPaginationQueryParameters = (url = '') => {\n const { sort, direction, page } = urlQueryToFilter(url);\n return {\n sort: sort?.value || null,\n direction: direction?.value || null,\n page: page?.value || null,\n };\n};\n\nexport const getDataZoomOption = ({\n totalItems = 0,\n maxItemsPerPage = 40,\n dataZoom = [{ type: 'slider', bottom: 10, start: 0 }],\n}) => {\n if (totalItems <= maxItemsPerPage) {\n return {};\n }\n\n const intervalEnd = Math.ceil((maxItemsPerPage / totalItems) * 100);\n\n return dataZoom.map((item) => {\n return {\n ...item,\n end: intervalEnd,\n };\n });\n};\n\n/**\n * Formats any valid number as percentage\n *\n * @param {number|string} decimalValue Decimal value between 0 and 1 to be converted to a percentage\n * @param {number} precision The number of decimal places to round to\n *\n * @returns {string} Returns a formatted string multiplied by 100\n */\nexport const formatAsPercentageWithoutSymbol = (decimalValue = 0, precision = 1) => {\n const parsed = Number.isNaN(Number(decimalValue)) ? 0 : decimalValue;\n return (parsed * 100).toFixed(precision);\n};\n\n/**\n * Converts a time in seconds to number of days, with variable precision\n *\n * @param {Number} seconds Time in seconds\n * @param {Number} precision Specifies the number of digits after the decimal\n *\n * @returns {Float} The number of days\n */\nexport const secondsToDays = (seconds, precision = 1) =>\n (seconds / SECONDS_IN_DAY).toFixed(precision);\n\nexport const scaledValueForDisplay = (value, units, precision = MAX_METRIC_PRECISION) => {\n switch (units) {\n case UNITS.PERCENT:\n return formatAsPercentageWithoutSymbol(value);\n case UNITS.DAYS:\n return secondsToDays(value, precision);\n default:\n return value;\n }\n};\n\nconst prepareMetricValue = ({ identifier, value, unit }) => {\n // NOTE: the flow metrics graphql endpoint returns values already scaled for display\n if (!value) {\n // ensures we return `-` for 0/null etc\n return '-';\n }\n return Object.values(FLOW_METRICS).includes(identifier)\n ? value\n : scaledValueForDisplay(value, unit);\n};\n\n/**\n * Prepares metric data to be rendered in the metric_tile component\n *\n * @param {MetricData[]} data - The metric data to be rendered\n * @returns {TransformedMetricData[]} An array of metrics ready to render in the metric_tile\n */\nexport const rawMetricToMetricTile = (metric) => {\n const { identifier, value, ...metricRest } = metric;\n const { unit, label, ...metadataRest } = VALUE_STREAM_METRIC_TILE_METADATA[identifier];\n return {\n ...metadataRest,\n ...metricRest,\n title: label,\n identifier,\n label,\n unit: VALUE_STREAM_METRIC_DISPLAY_UNITS[unit],\n value: prepareMetricValue({ value, unit, identifier }),\n };\n};\n\n/**\n * Generates a URL link to the VSD dashboard based on the\n * namespace path passed into the method.\n *\n * @param {String} namespacePath - Path of the specified namespace\n * @param {Boolean} isProjectNamespace\n * @returns a URL or blank string if there is no namespacePath set\n */\nexport const generateValueStreamsDashboardLink = (\n namespacePath = null,\n isProjectNamespace = false,\n) => {\n if (!namespacePath) return '';\n\n const dashboardsSlug = '/-/analytics/dashboards/value_streams_dashboard';\n const formattedNamespacePath = isProjectNamespace ? namespacePath : `groups/${namespacePath}`;\n const segments = [gon.relative_url_root || '', '/', formattedNamespacePath, dashboardsSlug];\n\n return joinPaths(...segments);\n};\n\n/**\n * Extracts the relevant feature and license flags needed for VSA\n *\n * @param {Object} gon the global `window.gon` object populated when the page loads\n * @returns an object containing the extracted feature flags and their boolean status\n */\nexport const extractVSAFeaturesFromGON = () => ({\n // licensed feature toggles\n cycleAnalyticsForGroups: Boolean(gon?.licensed_features?.cycleAnalyticsForGroups),\n cycleAnalyticsForProjects: Boolean(gon?.licensed_features?.cycleAnalyticsForProjects),\n groupLevelAnalyticsDashboard: Boolean(gon?.licensed_features?.groupLevelAnalyticsDashboard),\n});\n\n/**\n * Takes a raw GraphQL response which could contain data for a group or project namespace,\n * and returns the data for the namespace which is present in the response.\n *\n * @param {Object} params\n * @param {string} params.resultKey - The data to be extracted from the namespace.\n * @param {Object} params.result\n * @param {Object} params.result.data\n * @param {Object} params.result.data.group - The group GraphQL response.\n * @param {Object} params.result.data.project - The project GraphQL response.\n * @returns {Object} The data extracted from either group[resultKey] or project[resultKey].\n */\nexport const extractQueryResponseFromNamespace = ({ result, resultKey }) => {\n const { group = null, project = null } = result.data;\n if (group || project) {\n const namespace = group ?? project;\n return namespace[resultKey] || {};\n }\n return {};\n};\n\n/**\n * Takes the raw snake_case query parameters and extracts + converts the relevant values\n * for the overview metrics component\n * @param {Object} params - Object containing the supported query parameters\n * @param {Date} params.created_before\n * @param {Date} params.created_after\n * @param {string} params.author_username\n * @param {string} params.milestone_title\n * @param {Array} params.label_name\n * @param {Array} params.assignee_username\n *\n * @returns {Object} CamelCased parameter names\n */\nexport const overviewMetricsRequestParams = (params = {}) => {\n const {\n createdAfter: startDate,\n createdBefore: endDate,\n labelName: labelNames,\n assigneeUsername: assigneeUsernames,\n ...rest\n } = convertObjectPropsToCamelCase(params);\n return {\n startDate,\n endDate,\n labelNames,\n assigneeUsernames,\n ...rest,\n };\n};\n","var baseUniq = require('./_baseUniq');\n\n/**\n * This method is like `_.uniq` except that it accepts `comparator` which\n * is invoked to compare elements of `array`. The order of result values is\n * determined by the order they occur in the array.The comparator is invoked\n * with two arguments: (arrVal, othVal).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new duplicate free array.\n * @example\n *\n * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];\n *\n * _.uniqWith(objects, _.isEqual);\n * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]\n */\nfunction uniqWith(array, comparator) {\n comparator = typeof comparator == 'function' ? comparator : undefined;\n return (array && array.length) ? baseUniq(array, undefined, comparator) : [];\n}\n\nmodule.exports = uniqWith;\n"],"sourceRoot":""}