debian-mirror-gitlab/app/assets/javascripts/projects_dropdown/service/projects_service.js
2018-10-15 14:42:47 +05:30

137 lines
4.3 KiB
JavaScript

import _ from 'underscore';
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: true,
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,
);
if (!frequentProjects || frequentProjects.length === 0) {
return [];
}
// 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);
}
}