start of projects refactoring
This commit is contained in:
parent
a7a1eca9c3
commit
82586d23b2
7 changed files with 265 additions and 2 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
143
frontend/app/mstore/projectsStore.ts
Normal file
143
frontend/app/mstore/projectsStore.ts
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
30
frontend/app/mstore/types/gdpr.ts
Normal file
30
frontend/app/mstore/types/gdpr.ts
Normal 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,
|
||||
};
|
||||
}
|
||||
}
|
||||
54
frontend/app/mstore/types/project.ts
Normal file
54
frontend/app/mstore/types/project.ts
Normal 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,
|
||||
};
|
||||
}
|
||||
}
|
||||
27
frontend/app/services/ProjectsService.ts
Normal file
27
frontend/app/services/ProjectsService.ts
Normal 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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
];
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue