start of projects refactoring

This commit is contained in:
nick-delirium 2024-09-18 15:14:22 +02:00
parent a7a1eca9c3
commit 82586d23b2
No known key found for this signature in database
GPG key ID: 93ABD695DF5FDBA0
7 changed files with 265 additions and 2 deletions

View file

@ -1,6 +1,7 @@
import store from 'App/store';
import { queried } from './routes';
import { setJwt } from 'Duck/user';
import { projectStore } from 'App/mstore';
const siteIdRequiredPaths: string[] = [
'/dashboard',
@ -59,7 +60,7 @@ export default class APIClient {
constructor() {
const jwt = store.getState().getIn(['user', 'jwt']);
const siteId = store.getState().getIn(['site', 'siteId']);
const { siteId } = projectStore.getSiteId();
this.init = {
headers: new Headers({
Accept: 'application/json',
@ -69,7 +70,7 @@ export default class APIClient {
if (jwt !== null) {
(this.init.headers as Headers).set('Authorization', `Bearer ${jwt}`);
}
this.siteId = siteId;
this.siteId = siteId || undefined;
}
private getInit(method: string = 'GET', params?: any, reqHeaders?: Record<string, any>): RequestInit {

View file

@ -28,6 +28,9 @@ import UiPlayerStore from './uiPlayerStore';
import IssueReportingStore from './issueReportingStore';
import CustomFieldStore from './customFieldStore';
import { IntegrationsStore } from "./integrationsStore";
import ProjectsStore from './projectsStore';
export const projectStore = new ProjectsStore();
export class RootStore {
dashboardStore: DashboardStore;
@ -57,6 +60,7 @@ export class RootStore {
issueReportingStore: IssueReportingStore;
customFieldStore: CustomFieldStore;
integrationsStore: IntegrationsStore
projectsStore: ProjectsStore;
constructor() {
this.dashboardStore = new DashboardStore();
@ -86,6 +90,7 @@ export class RootStore {
this.issueReportingStore = new IssueReportingStore();
this.customFieldStore = new CustomFieldStore();
this.integrationsStore = new IntegrationsStore();
this.projectsStore = projectStore;
}
initClient() {

View file

@ -0,0 +1,143 @@
import { makeAutoObservable, runInAction } from 'mobx';
import Project from './types/project';
import GDPR from './types/gdpr';
import { GLOBAL_HAS_NO_RECORDINGS, SITE_ID_STORAGE_KEY } from 'App/constants/storageKeys';
import { projectsService } from "App/services";
export default class ProjectsStore {
list: Project[] = [];
instance: Project | null = null;
siteId: string | null = null;
active: Project | null = null;
sitesLoading = false;
constructor() {
const storedSiteId = localStorage.getItem(SITE_ID_STORAGE_KEY);
this.siteId = storedSiteId ?? null;
makeAutoObservable(this);
}
getSiteId = () => {
return {
siteId: this.siteId,
active: this.active,
};
}
initProject = (project: Partial<Project>) => {
this.instance = new Project(project);
}
setSitesLoading = (loading: boolean) => {
this.sitesLoading = loading;
}
setSiteId(siteId: string) {
this.siteId = siteId;
localStorage.setItem(SITE_ID_STORAGE_KEY, siteId.toString());
this.active = this.list.find((site) => site.id! === siteId) ?? null;
}
editGDPR(gdprData: Partial<GDPR>) {
if (this.instance) {
this.instance.gdpr.edit(gdprData);
}
}
editInstance = (instance: Partial<Project>) => {
if (!this.instance) return;
this.instance.edit(instance);
}
async fetchGDPR(siteId: string) {
try {
const response = await projectsService.fetchGDPR(siteId)
runInAction(() => {
if (this.instance) {
Object.assign(this.instance.gdpr, response.data);
}
});
} catch (error) {
console.error('Failed to fetch GDPR:', error);
}
}
saveGDPR = async (siteId: string) => {
if (!this.instance) return;
try {
const gdprData = this.instance.gdpr.toData();
const response = await projectsService.saveGDPR(siteId, gdprData);
this.editGDPR(response.data);
} catch (error) {
console.error('Failed to save GDPR:', error);
}
}
fetchList = async (siteIdFromPath: string) =>{
this.setSitesLoading(true);
try {
const response = await projectsService.fetchList();
runInAction(() => {
this.list = response.data.map((data) => new Project(data));
const siteIds = this.list.map(site => site.id);
let siteId = this.siteId;
const siteExists = siteId ? siteIds.includes(siteId) : false;
if (siteIdFromPath && siteIds.includes(siteIdFromPath)) {
siteId = siteIdFromPath;
} else if (!siteId || !siteExists) {
siteId = siteIds.includes(this.siteId)
? this.siteId
: response.data[0].projectId;
}
const hasRecordings = this.list.some(site => site.recorded);
if (!hasRecordings) {
localStorage.setItem(GLOBAL_HAS_NO_RECORDINGS, 'true');
} else {
localStorage.removeItem(GLOBAL_HAS_NO_RECORDINGS);
}
if (siteId) {
this.setSiteId(siteId);
}
});
} catch (error) {
console.error('Failed to fetch site list:', error);
} finally {
this.setSitesLoading(false);
}
}
save = async (projectData: Partial<Project>) => {
try {
const response = await projectsService.saveProject(projectData);
runInAction(() => {
const newSite = new Project(response.data);
const index = this.list.findIndex(site => site.id === newSite.id);
if (index !== -1) {
this.list[index] = newSite;
} else {
this.list.push(newSite);
}
this.setSiteId(newSite.id);
this.active = newSite;
});
} catch (error) {
console.error('Failed to save site:', error);
}
}
updateProjectRecordingStatus = (siteId: string, status: boolean) => {
const site = this.list.find(site => site.id === siteId);
if (site) {
site.recorded = status;
const hasRecordings = this.list.some(site => site.recorded);
if (!hasRecordings) {
localStorage.setItem(GLOBAL_HAS_NO_RECORDINGS, 'true');
} else {
localStorage.removeItem(GLOBAL_HAS_NO_RECORDINGS);
}
}
}
}

View file

@ -0,0 +1,30 @@
import { makeAutoObservable } from 'mobx';
export default class GDPR {
id = undefined;
maskEmails = false;
maskNumbers = false;
defaultInputMode = 'plain';
sampleRate = 0;
constructor(data = {}) {
Object.assign(this, data);
makeAutoObservable(this);
}
edit = (data: Partial<GDPR>) => {
Object.keys(data).forEach((key) => {
this[key] = data[key];
})
}
toData = () => {
return {
id: this.id,
maskEmails: this.maskEmails,
maskNumbers: this.maskNumbers,
defaultInputMode: this.defaultInputMode,
sampleRate: this.sampleRate,
};
}
}

View file

@ -0,0 +1,54 @@
import { makeAutoObservable } from 'mobx';
import GDPR from './gdpr';
export default class Project {
id?: string;
name: string = '';
host: string = '';
platform: string = 'web';
lastRecordedSessionAt?: any;
gdpr: GDPR;
recorded: boolean = false;
stackIntegrations: boolean = false;
projectKey?: string;
projectId?: number;
trackerVersion?: string;
saveRequestPayloads: boolean = false;
sampleRate: number = 0;
conditionsCount: number = 0;
constructor(data: Partial<Project> = {}) {
Object.assign(this, data);
this.gdpr = data.gdpr ? new GDPR(data.gdpr) : new GDPR();
this.id = data.projectId?.toString();
this.host = data.name || '';
makeAutoObservable(this);
}
edit = (data: Partial<Project>) => {
Object.keys(data).forEach((key) => {
if (key in this) {
this[key] = data[key];
}
})
}
toData = () => {
return {
id: this.id,
name: this.name,
host: this.host,
platform: this.platform,
lastRecordedSessionAt: this.lastRecordedSessionAt,
gdpr: this.gdpr.toData(),
recorded: this.recorded,
stackIntegrations: this.stackIntegrations,
projectKey: this.projectKey,
projectId: this.projectId,
trackerVersion: this.trackerVersion,
saveRequestPayloads: this.saveRequestPayloads,
sampleRate: this.sampleRate,
conditionsCount: this.conditionsCount,
};
}
}

View file

@ -0,0 +1,27 @@
import BaseService from "./BaseService";
export default class ProjectsService extends BaseService {
fetchGDPR = async (siteId: string) => {
const r = await this.client.get(`/${siteId}/gdpr`);
return await r.json();
}
saveGDPR = async (siteId: string, gdprData: any) => {
const r = await this.client.post(`/${siteId}/gdpr`, gdprData);
return await r.json();
}
fetchList = async () => {
const r = await this.client.get('/projects');
return await r.json();
}
saveProject = async (projectData: any) => {
const r = await this.client.post('/projects', projectData);
return await r.json();
}
}

View file

@ -23,6 +23,7 @@ import FilterService from "./FilterService";
import IssueReportsService from "./IssueReportsService";
import CustomFieldService from './CustomFieldService';
import IntegrationsService from './IntegrationsService';
import ProjectsService from './ProjectsService';
export const dashboardService = new DashboardService();
export const metricService = new MetricService();
@ -48,6 +49,7 @@ export const filterService = new FilterService();
export const issueReportsService = new IssueReportsService();
export const customFieldService = new CustomFieldService();
export const integrationsService = new IntegrationsService();
export const projectsService = new ProjectsService();
export const services = [
dashboardService,
@ -74,4 +76,5 @@ export const services = [
issueReportsService,
customFieldService,
integrationsService,
projectsService,
];