summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/projects_dropdown/service/projects_service.js
blob: fad956b4c2675214f67e2b3785c0d500e3e55f37 (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
120
121
122
123
124
125
126
127
128
129
130
131
132
import Vue from 'vue';
import VueResource from 'vue-resource';

import bp from '../../breakpoints';
import Api from '../../api';
import AccessorUtilities from '../../lib/utils/accessor';

import { FREQUENT_PROJECTS, HOUR_IN_MS, STORAGE_KEY } from '../constants';

Vue.use(VueResource);

export default class ProjectsService {
  constructor(currentUserName) {
    this.isLocalStorageAvailable = AccessorUtilities.isLocalStorageAccessSafe();
    this.currentUserName = currentUserName;
    this.storageKey = `${this.currentUserName}/${STORAGE_KEY}`;
    this.projectsPath = Vue.resource(Api.buildUrl(Api.projectsPath));
  }

  getSearchedProjects(searchQuery) {
    return this.projectsPath.get({
      simple: false,
      per_page: 20,
      membership: !!gon.current_user_id,
      order_by: 'last_activity_at',
      search: searchQuery,
    });
  }

  getFrequentProjects() {
    if (this.isLocalStorageAvailable) {
      return this.getTopFrequentProjects();
    }
    return null;
  }

  logProjectAccess(project) {
    let matchFound = false;
    let storedFrequentProjects;

    if (this.isLocalStorageAvailable) {
      const storedRawProjects = localStorage.getItem(this.storageKey);

      // Check if there's any frequent projects list set
      if (!storedRawProjects) {
        // No frequent projects list set, set one up.
        storedFrequentProjects = [];
        storedFrequentProjects.push({ ...project, frequency: 1 });
      } else {
        // Check if project is already present in frequents list
        // When found, update metadata of it.
        storedFrequentProjects = JSON.parse(storedRawProjects).map((projectItem) => {
          if (projectItem.id === project.id) {
            matchFound = true;
            const diff = Math.abs(project.lastAccessedOn - projectItem.lastAccessedOn) / HOUR_IN_MS;
            const updatedProject = {
              ...project,
              frequency: projectItem.frequency,
              lastAccessedOn: projectItem.lastAccessedOn,
            };

            // Check if duration since last access of this project
            // is over an hour
            if (diff > 1) {
              return {
                ...updatedProject,
                frequency: updatedProject.frequency + 1,
                lastAccessedOn: Date.now(),
              };
            }

            return {
              ...updatedProject,
            };
          }

          return projectItem;
        });

        // Check whether currently logged project is present in frequents list
        if (!matchFound) {
          // We always keep size of frequents collection to 20 projects
          // out of which only 5 projects with
          // highest value of `frequency` and most recent `lastAccessedOn`
          // are shown in projects dropdown
          if (storedFrequentProjects.length === FREQUENT_PROJECTS.MAX_COUNT) {
            storedFrequentProjects.shift(); // Remove an item from head of array
          }

          storedFrequentProjects.push({ ...project, frequency: 1 });
        }
      }

      localStorage.setItem(this.storageKey, JSON.stringify(storedFrequentProjects));
    }
  }

  getTopFrequentProjects() {
    const storedFrequentProjects = JSON.parse(localStorage.getItem(this.storageKey));
    let frequentProjectsCount = FREQUENT_PROJECTS.LIST_COUNT_DESKTOP;

    if (!storedFrequentProjects) {
      return [];
    }

    if (bp.getBreakpointSize() === 'sm' ||
        bp.getBreakpointSize() === 'xs') {
      frequentProjectsCount = FREQUENT_PROJECTS.LIST_COUNT_MOBILE;
    }

    const frequentProjects = storedFrequentProjects
      .filter(project => project.frequency >= FREQUENT_PROJECTS.ELIGIBLE_FREQUENCY);

    // Sort all frequent projects in decending order of frequency
    // and then by lastAccessedOn with recent most first
    frequentProjects.sort((projectA, projectB) => {
      if (projectA.frequency < projectB.frequency) {
        return 1;
      } else if (projectA.frequency > projectB.frequency) {
        return -1;
      } else if (projectA.lastAccessedOn < projectB.lastAccessedOn) {
        return 1;
      } else if (projectA.lastAccessedOn > projectB.lastAccessedOn) {
        return -1;
      }

      return 0;
    });

    return _.first(frequentProjects, frequentProjectsCount);
  }
}