summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/search/store/utils.js
blob: 1e6619ca6d573f37cdcbcb4cabefbc481016e9ad (plain)
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
113
114
115
116
117
118
119
import { isEqual } from 'lodash';
import AccessorUtilities from '~/lib/utils/accessor';
import { formatNumber } from '~/locale';
import { joinPaths } from '~/lib/utils/url_utility';
import {
  MAX_FREQUENT_ITEMS,
  MAX_FREQUENCY,
  SIDEBAR_PARAMS,
  NUMBER_FORMATING_OPTIONS,
} from './constants';

function extractKeys(object, keyList) {
  return Object.fromEntries(keyList.map((key) => [key, object[key]]));
}

export const loadDataFromLS = (key) => {
  if (!AccessorUtilities.canUseLocalStorage()) {
    return [];
  }

  try {
    return JSON.parse(localStorage.getItem(key)) || [];
  } catch {
    // The LS got in a bad state, let's wipe it
    localStorage.removeItem(key);
    return [];
  }
};

export const setFrequentItemToLS = (key, data, itemData) => {
  if (!AccessorUtilities.canUseLocalStorage()) {
    return [];
  }

  const keyList = [
    'id',
    'avatar_url',
    'name',
    'full_name',
    'name_with_namespace',
    'frequency',
    'lastUsed',
  ];

  try {
    const frequentItems = data[key].map((obj) => extractKeys(obj, keyList));
    const item = extractKeys(itemData, keyList);
    const existingItemIndex = frequentItems.findIndex((i) => i.id === item.id);

    if (existingItemIndex >= 0) {
      // Up the frequency (Max 5)
      const currentFrequency = frequentItems[existingItemIndex].frequency;
      frequentItems[existingItemIndex].frequency = Math.min(currentFrequency + 1, MAX_FREQUENCY);
      frequentItems[existingItemIndex].lastUsed = new Date().getTime();
    } else {
      // Only store a max of 5 items
      if (frequentItems.length >= MAX_FREQUENT_ITEMS) {
        frequentItems.pop();
      }

      frequentItems.push({ ...item, frequency: 1, lastUsed: new Date().getTime() });
    }

    // Sort by frequency and lastUsed
    frequentItems.sort((a, b) => {
      if (a.frequency > b.frequency) {
        return -1;
      } else if (a.frequency < b.frequency) {
        return 1;
      }
      return b.lastUsed - a.lastUsed;
    });

    // Note we do not need to commit a mutation here as immediately after this we refresh the page to
    // update the search results.
    localStorage.setItem(key, JSON.stringify(frequentItems));
    return frequentItems;
  } catch {
    // The LS got in a bad state, let's wipe it
    localStorage.removeItem(key);
    return [];
  }
};

export const mergeById = (inflatedData, storedData) => {
  return inflatedData.map((data) => {
    const stored = storedData?.find((d) => d.id === data.id) || {};
    return { ...stored, ...data };
  });
};

export const isSidebarDirty = (currentQuery, urlQuery) => {
  return SIDEBAR_PARAMS.some((param) => {
    // userAddParam ensures we don't get a false dirty from null !== undefined
    const userAddedParam = !urlQuery[param] && currentQuery[param];
    const userChangedExistingParam = urlQuery[param] && urlQuery[param] !== currentQuery[param];

    if (Array.isArray(currentQuery[param]) || Array.isArray(urlQuery[param])) {
      return !isEqual(currentQuery[param], urlQuery[param]);
    }

    return userAddedParam || userChangedExistingParam;
  });
};

export const formatSearchResultCount = (count) => {
  if (!count) {
    return '0';
  }

  const countNumber = typeof count === 'string' ? parseInt(count.replace(/,/g, ''), 10) : count;
  return formatNumber(countNumber, NUMBER_FORMATING_OPTIONS);
};

export const getAggregationsUrl = () => {
  const currentUrl = new URL(window.location.href);
  currentUrl.pathname = joinPaths('/search', 'aggregations');
  return currentUrl.toString();
};