mirror of
https://github.com/makeplane/plane
synced 2025-08-07 19:59:33 +00:00
chore: linting warning resolved
This commit is contained in:
@@ -124,36 +124,27 @@ export class ArchivedIssuesFilter extends IssueFilterHelperStore implements IArc
|
||||
);
|
||||
|
||||
fetchFilters = async (workspaceSlug: string, projectId: string) => {
|
||||
try {
|
||||
const _filters = this.handleIssuesLocalFilters.get(
|
||||
EIssuesStoreType.ARCHIVED,
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
undefined
|
||||
);
|
||||
const _filters = this.handleIssuesLocalFilters.get(EIssuesStoreType.ARCHIVED, workspaceSlug, projectId, undefined);
|
||||
|
||||
const filters: IIssueFilterOptions = this.computedFilters(_filters?.filters);
|
||||
const displayFilters: IIssueDisplayFilterOptions = this.computedDisplayFilters({
|
||||
..._filters?.display_filters,
|
||||
sub_issue: true,
|
||||
});
|
||||
const displayProperties: IIssueDisplayProperties = this.computedDisplayProperties(_filters?.display_properties);
|
||||
const kanbanFilters = {
|
||||
group_by: [],
|
||||
sub_group_by: [],
|
||||
};
|
||||
kanbanFilters.group_by = _filters?.kanban_filters?.group_by || [];
|
||||
kanbanFilters.sub_group_by = _filters?.kanban_filters?.sub_group_by || [];
|
||||
const filters: IIssueFilterOptions = this.computedFilters(_filters?.filters);
|
||||
const displayFilters: IIssueDisplayFilterOptions = this.computedDisplayFilters({
|
||||
..._filters?.display_filters,
|
||||
sub_issue: true,
|
||||
});
|
||||
const displayProperties: IIssueDisplayProperties = this.computedDisplayProperties(_filters?.display_properties);
|
||||
const kanbanFilters = {
|
||||
group_by: [],
|
||||
sub_group_by: [],
|
||||
};
|
||||
kanbanFilters.group_by = _filters?.kanban_filters?.group_by || [];
|
||||
kanbanFilters.sub_group_by = _filters?.kanban_filters?.sub_group_by || [];
|
||||
|
||||
runInAction(() => {
|
||||
set(this.filters, [projectId, "filters"], filters);
|
||||
set(this.filters, [projectId, "displayFilters"], displayFilters);
|
||||
set(this.filters, [projectId, "displayProperties"], displayProperties);
|
||||
set(this.filters, [projectId, "kanbanFilters"], kanbanFilters);
|
||||
});
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
runInAction(() => {
|
||||
set(this.filters, [projectId, "filters"], filters);
|
||||
set(this.filters, [projectId, "displayFilters"], displayFilters);
|
||||
set(this.filters, [projectId, "displayProperties"], displayProperties);
|
||||
set(this.filters, [projectId, "kanbanFilters"], kanbanFilters);
|
||||
});
|
||||
};
|
||||
|
||||
updateFilters = async (
|
||||
|
||||
@@ -179,22 +179,18 @@ export class ArchivedIssues extends BaseIssuesStore implements IArchivedIssues {
|
||||
* @returns
|
||||
*/
|
||||
restoreIssue = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
try {
|
||||
// call API to restore the issue
|
||||
const response = await this.issueArchiveService.restoreIssue(workspaceSlug, projectId, issueId);
|
||||
// call API to restore the issue
|
||||
const response = await this.issueArchiveService.restoreIssue(workspaceSlug, projectId, issueId);
|
||||
|
||||
// update the store and remove from the archived issues list once restored
|
||||
runInAction(() => {
|
||||
this.rootIssueStore.issues.updateIssue(issueId, {
|
||||
archived_at: null,
|
||||
});
|
||||
this.removeIssueFromList(issueId);
|
||||
// update the store and remove from the archived issues list once restored
|
||||
runInAction(() => {
|
||||
this.rootIssueStore.issues.updateIssue(issueId, {
|
||||
archived_at: null,
|
||||
});
|
||||
this.removeIssueFromList(issueId);
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
return response;
|
||||
};
|
||||
|
||||
// Setting them as undefined as they can not performed on Archived issues
|
||||
|
||||
@@ -127,39 +127,35 @@ export class CycleIssuesFilter extends IssueFilterHelperStore implements ICycleI
|
||||
);
|
||||
|
||||
fetchFilters = async (workspaceSlug: string, projectId: string, cycleId: string) => {
|
||||
try {
|
||||
const _filters = await this.issueFilterService.fetchCycleIssueFilters(workspaceSlug, projectId, cycleId);
|
||||
const _filters = await this.issueFilterService.fetchCycleIssueFilters(workspaceSlug, projectId, cycleId);
|
||||
|
||||
const filters: IIssueFilterOptions = this.computedFilters(_filters?.filters);
|
||||
const displayFilters: IIssueDisplayFilterOptions = this.computedDisplayFilters(_filters?.display_filters);
|
||||
const displayProperties: IIssueDisplayProperties = this.computedDisplayProperties(_filters?.display_properties);
|
||||
const filters: IIssueFilterOptions = this.computedFilters(_filters?.filters);
|
||||
const displayFilters: IIssueDisplayFilterOptions = this.computedDisplayFilters(_filters?.display_filters);
|
||||
const displayProperties: IIssueDisplayProperties = this.computedDisplayProperties(_filters?.display_properties);
|
||||
|
||||
// fetching the kanban toggle helpers in the local storage
|
||||
const kanbanFilters = {
|
||||
group_by: [],
|
||||
sub_group_by: [],
|
||||
};
|
||||
const currentUserId = this.rootIssueStore.currentUserId;
|
||||
if (currentUserId) {
|
||||
const _kanbanFilters = this.handleIssuesLocalFilters.get(
|
||||
EIssuesStoreType.CYCLE,
|
||||
workspaceSlug,
|
||||
cycleId,
|
||||
currentUserId
|
||||
);
|
||||
kanbanFilters.group_by = _kanbanFilters?.kanban_filters?.group_by || [];
|
||||
kanbanFilters.sub_group_by = _kanbanFilters?.kanban_filters?.sub_group_by || [];
|
||||
}
|
||||
|
||||
runInAction(() => {
|
||||
set(this.filters, [cycleId, "filters"], filters);
|
||||
set(this.filters, [cycleId, "displayFilters"], displayFilters);
|
||||
set(this.filters, [cycleId, "displayProperties"], displayProperties);
|
||||
set(this.filters, [cycleId, "kanbanFilters"], kanbanFilters);
|
||||
});
|
||||
} catch (error) {
|
||||
throw error;
|
||||
// fetching the kanban toggle helpers in the local storage
|
||||
const kanbanFilters = {
|
||||
group_by: [],
|
||||
sub_group_by: [],
|
||||
};
|
||||
const currentUserId = this.rootIssueStore.currentUserId;
|
||||
if (currentUserId) {
|
||||
const _kanbanFilters = this.handleIssuesLocalFilters.get(
|
||||
EIssuesStoreType.CYCLE,
|
||||
workspaceSlug,
|
||||
cycleId,
|
||||
currentUserId
|
||||
);
|
||||
kanbanFilters.group_by = _kanbanFilters?.kanban_filters?.group_by || [];
|
||||
kanbanFilters.sub_group_by = _kanbanFilters?.kanban_filters?.sub_group_by || [];
|
||||
}
|
||||
|
||||
runInAction(() => {
|
||||
set(this.filters, [cycleId, "filters"], filters);
|
||||
set(this.filters, [cycleId, "displayFilters"], displayFilters);
|
||||
set(this.filters, [cycleId, "displayProperties"], displayProperties);
|
||||
set(this.filters, [cycleId, "kanbanFilters"], kanbanFilters);
|
||||
});
|
||||
};
|
||||
|
||||
updateFilters = async (
|
||||
|
||||
@@ -273,14 +273,9 @@ export class CycleIssues extends BaseIssuesStore implements ICycleIssues {
|
||||
* @returns
|
||||
*/
|
||||
override createIssue = async (workspaceSlug: string, projectId: string, data: Partial<TIssue>, cycleId: string) => {
|
||||
try {
|
||||
const response = await super.createIssue(workspaceSlug, projectId, data, cycleId, false);
|
||||
await this.addIssueToCycle(workspaceSlug, projectId, cycleId, [response.id], false);
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
const response = await super.createIssue(workspaceSlug, projectId, data, cycleId, false);
|
||||
await this.addIssueToCycle(workspaceSlug, projectId, cycleId, [response.id], false);
|
||||
return response;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -299,22 +294,17 @@ export class CycleIssues extends BaseIssuesStore implements ICycleIssues {
|
||||
new_cycle_id: string;
|
||||
}
|
||||
) => {
|
||||
try {
|
||||
// call API call to transfer issues
|
||||
const response = await this.cycleService.transferIssues(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
cycleId as string,
|
||||
payload
|
||||
);
|
||||
// call fetch issues
|
||||
this.paginationOptions &&
|
||||
(await this.fetchIssues(workspaceSlug, projectId, "mutation", this.paginationOptions, cycleId));
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
// call API call to transfer issues
|
||||
const response = await this.cycleService.transferIssues(
|
||||
workspaceSlug as string,
|
||||
projectId as string,
|
||||
cycleId as string,
|
||||
payload
|
||||
);
|
||||
// call fetch issues
|
||||
this.paginationOptions &&
|
||||
(await this.fetchIssues(workspaceSlug, projectId, "mutation", this.paginationOptions, cycleId));
|
||||
return response;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -327,35 +317,31 @@ export class CycleIssues extends BaseIssuesStore implements ICycleIssues {
|
||||
* @returns
|
||||
*/
|
||||
fetchActiveCycleIssues = async (workspaceSlug: string, projectId: string, perPageCount: number, cycleId: string) => {
|
||||
try {
|
||||
// set loader
|
||||
set(this.activeCycleIds, [cycleId], undefined);
|
||||
// set loader
|
||||
set(this.activeCycleIds, [cycleId], undefined);
|
||||
|
||||
// set params for urgent and high
|
||||
const params = { priority: `urgent,high`, cursor: `${perPageCount}:0:0`, per_page: perPageCount };
|
||||
// call the fetch issues API
|
||||
const response = await this.cycleService.getCycleIssues(workspaceSlug, projectId, cycleId, params);
|
||||
// set params for urgent and high
|
||||
const params = { priority: `urgent,high`, cursor: `${perPageCount}:0:0`, per_page: perPageCount };
|
||||
// call the fetch issues API
|
||||
const response = await this.cycleService.getCycleIssues(workspaceSlug, projectId, cycleId, params);
|
||||
|
||||
// Process issue response
|
||||
const { issueList, groupedIssues } = this.processIssueResponse(response);
|
||||
// Process issue response
|
||||
const { issueList, groupedIssues } = this.processIssueResponse(response);
|
||||
|
||||
// add issues to the main Issue Map
|
||||
this.rootIssueStore.issues.addIssue(issueList);
|
||||
const activeIssueIds = groupedIssues[ALL_ISSUES] as string[];
|
||||
// add issues to the main Issue Map
|
||||
this.rootIssueStore.issues.addIssue(issueList);
|
||||
const activeIssueIds = groupedIssues[ALL_ISSUES] as string[];
|
||||
|
||||
// store the processed data in the current store
|
||||
set(this.activeCycleIds, [cycleId], {
|
||||
issueIds: activeIssueIds,
|
||||
issueCount: response.total_count,
|
||||
nextCursor: response.next_cursor,
|
||||
nextPageResults: response.next_page_results,
|
||||
perPageCount: perPageCount,
|
||||
});
|
||||
// store the processed data in the current store
|
||||
set(this.activeCycleIds, [cycleId], {
|
||||
issueIds: activeIssueIds,
|
||||
issueCount: response.total_count,
|
||||
nextCursor: response.next_cursor,
|
||||
nextPageResults: response.next_page_results,
|
||||
perPageCount: perPageCount,
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
return response;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -367,39 +353,35 @@ export class CycleIssues extends BaseIssuesStore implements ICycleIssues {
|
||||
* @returns
|
||||
*/
|
||||
fetchNextActiveCycleIssues = async (workspaceSlug: string, projectId: string, cycleId: string) => {
|
||||
try {
|
||||
//get the previous pagination data for the cycle id
|
||||
const activeCycle = get(this.activeCycleIds, [cycleId]);
|
||||
//get the previous pagination data for the cycle id
|
||||
const activeCycle = get(this.activeCycleIds, [cycleId]);
|
||||
|
||||
// if there is no active cycle and the next pages does not exist return
|
||||
if (!activeCycle || !activeCycle.nextPageResults) return;
|
||||
// if there is no active cycle and the next pages does not exist return
|
||||
if (!activeCycle || !activeCycle.nextPageResults) return;
|
||||
|
||||
// create params
|
||||
const params = { priority: `urgent,high`, cursor: activeCycle.nextCursor, per_page: activeCycle.perPageCount };
|
||||
// fetch API response
|
||||
const response = await this.cycleService.getCycleIssues(workspaceSlug, projectId, cycleId, params);
|
||||
// create params
|
||||
const params = { priority: `urgent,high`, cursor: activeCycle.nextCursor, per_page: activeCycle.perPageCount };
|
||||
// fetch API response
|
||||
const response = await this.cycleService.getCycleIssues(workspaceSlug, projectId, cycleId, params);
|
||||
|
||||
// Process the response
|
||||
const { issueList, groupedIssues } = this.processIssueResponse(response);
|
||||
// Process the response
|
||||
const { issueList, groupedIssues } = this.processIssueResponse(response);
|
||||
|
||||
// add issues to main issue Map
|
||||
this.rootIssueStore.issues.addIssue(issueList);
|
||||
// add issues to main issue Map
|
||||
this.rootIssueStore.issues.addIssue(issueList);
|
||||
|
||||
const activeIssueIds = groupedIssues[ALL_ISSUES] as string[];
|
||||
const activeIssueIds = groupedIssues[ALL_ISSUES] as string[];
|
||||
|
||||
// store the processed data for subsequent pages
|
||||
set(this.activeCycleIds, [cycleId, "issueCount"], response.total_count);
|
||||
set(this.activeCycleIds, [cycleId, "nextCursor"], response.next_cursor);
|
||||
set(this.activeCycleIds, [cycleId, "nextPageResults"], response.next_page_results);
|
||||
set(this.activeCycleIds, [cycleId, "issueCount"], response.total_count);
|
||||
update(this.activeCycleIds, [cycleId, "issueIds"], (issueIds: string[] = []) =>
|
||||
this.issuesSortWithOrderBy(uniq(concat(issueIds, activeIssueIds)), this.orderBy)
|
||||
);
|
||||
// store the processed data for subsequent pages
|
||||
set(this.activeCycleIds, [cycleId, "issueCount"], response.total_count);
|
||||
set(this.activeCycleIds, [cycleId, "nextCursor"], response.next_cursor);
|
||||
set(this.activeCycleIds, [cycleId, "nextPageResults"], response.next_page_results);
|
||||
set(this.activeCycleIds, [cycleId, "issueCount"], response.total_count);
|
||||
update(this.activeCycleIds, [cycleId, "issueIds"], (issueIds: string[] = []) =>
|
||||
this.issuesSortWithOrderBy(uniq(concat(issueIds, activeIssueIds)), this.orderBy)
|
||||
);
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
return response;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -411,30 +393,26 @@ export class CycleIssues extends BaseIssuesStore implements ICycleIssues {
|
||||
* @returns
|
||||
*/
|
||||
quickAddIssue = async (workspaceSlug: string, projectId: string, data: TIssue, cycleId: string) => {
|
||||
try {
|
||||
// add temporary issue to store list
|
||||
this.addIssue(data);
|
||||
// add temporary issue to store list
|
||||
this.addIssue(data);
|
||||
|
||||
// call overridden create issue
|
||||
const response = await this.createIssue(workspaceSlug, projectId, data, cycleId);
|
||||
// call overridden create issue
|
||||
const response = await this.createIssue(workspaceSlug, projectId, data, cycleId);
|
||||
|
||||
// remove temp Issue from store list
|
||||
runInAction(() => {
|
||||
this.removeIssueFromList(data.id);
|
||||
this.rootIssueStore.issues.removeIssue(data.id);
|
||||
});
|
||||
// remove temp Issue from store list
|
||||
runInAction(() => {
|
||||
this.removeIssueFromList(data.id);
|
||||
this.rootIssueStore.issues.removeIssue(data.id);
|
||||
});
|
||||
|
||||
const currentModuleIds =
|
||||
data.module_ids && data.module_ids.length > 0 ? data.module_ids.filter((moduleId) => moduleId != "None") : [];
|
||||
const currentModuleIds =
|
||||
data.module_ids && data.module_ids.length > 0 ? data.module_ids.filter((moduleId) => moduleId != "None") : [];
|
||||
|
||||
if (currentModuleIds.length > 0) {
|
||||
await this.changeModulesInIssue(workspaceSlug, projectId, response.id, currentModuleIds, []);
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
if (currentModuleIds.length > 0) {
|
||||
await this.changeModulesInIssue(workspaceSlug, projectId, response.id, currentModuleIds, []);
|
||||
}
|
||||
|
||||
return response;
|
||||
};
|
||||
|
||||
// Using aliased names as they cannot be overridden in other stores
|
||||
|
||||
@@ -124,28 +124,24 @@ export class DraftIssuesFilter extends IssueFilterHelperStore implements IDraftI
|
||||
);
|
||||
|
||||
fetchFilters = async (workspaceSlug: string, projectId: string) => {
|
||||
try {
|
||||
const _filters = this.handleIssuesLocalFilters.get(EIssuesStoreType.DRAFT, workspaceSlug, projectId, undefined);
|
||||
const _filters = this.handleIssuesLocalFilters.get(EIssuesStoreType.DRAFT, workspaceSlug, projectId, undefined);
|
||||
|
||||
const filters: IIssueFilterOptions = this.computedFilters(_filters?.filters);
|
||||
const displayFilters: IIssueDisplayFilterOptions = this.computedDisplayFilters(_filters?.display_filters);
|
||||
const displayProperties: IIssueDisplayProperties = this.computedDisplayProperties(_filters?.display_properties);
|
||||
const kanbanFilters = {
|
||||
group_by: [],
|
||||
sub_group_by: [],
|
||||
};
|
||||
kanbanFilters.group_by = _filters?.kanban_filters?.group_by || [];
|
||||
kanbanFilters.sub_group_by = _filters?.kanban_filters?.sub_group_by || [];
|
||||
const filters: IIssueFilterOptions = this.computedFilters(_filters?.filters);
|
||||
const displayFilters: IIssueDisplayFilterOptions = this.computedDisplayFilters(_filters?.display_filters);
|
||||
const displayProperties: IIssueDisplayProperties = this.computedDisplayProperties(_filters?.display_properties);
|
||||
const kanbanFilters = {
|
||||
group_by: [],
|
||||
sub_group_by: [],
|
||||
};
|
||||
kanbanFilters.group_by = _filters?.kanban_filters?.group_by || [];
|
||||
kanbanFilters.sub_group_by = _filters?.kanban_filters?.sub_group_by || [];
|
||||
|
||||
runInAction(() => {
|
||||
set(this.filters, [projectId, "filters"], filters);
|
||||
set(this.filters, [projectId, "displayFilters"], displayFilters);
|
||||
set(this.filters, [projectId, "displayProperties"], displayProperties);
|
||||
set(this.filters, [projectId, "kanbanFilters"], kanbanFilters);
|
||||
});
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
runInAction(() => {
|
||||
set(this.filters, [projectId, "filters"], filters);
|
||||
set(this.filters, [projectId, "displayFilters"], displayFilters);
|
||||
set(this.filters, [projectId, "displayProperties"], displayProperties);
|
||||
set(this.filters, [projectId, "kanbanFilters"], kanbanFilters);
|
||||
});
|
||||
};
|
||||
|
||||
updateFilters = async (
|
||||
|
||||
@@ -517,20 +517,16 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore {
|
||||
id?: string,
|
||||
shouldUpdateList = true
|
||||
) {
|
||||
try {
|
||||
// perform an API call
|
||||
const response = await this.issueService.createIssue(workspaceSlug, projectId, data);
|
||||
// perform an API call
|
||||
const response = await this.issueService.createIssue(workspaceSlug, projectId, data);
|
||||
|
||||
// add Issue to Store
|
||||
this.addIssue(response, shouldUpdateList);
|
||||
// add Issue to Store
|
||||
this.addIssue(response, shouldUpdateList);
|
||||
|
||||
// If shouldUpdateList is true, call fetchParentStats
|
||||
shouldUpdateList && (await this.fetchParentStats(workspaceSlug, projectId));
|
||||
// If shouldUpdateList is true, call fetchParentStats
|
||||
shouldUpdateList && (await this.fetchParentStats(workspaceSlug, projectId));
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -586,20 +582,13 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore {
|
||||
* @returns
|
||||
*/
|
||||
async createDraftIssue(workspaceSlug: string, projectId: string, data: Partial<TIssue>) {
|
||||
try {
|
||||
// call API to create a Draft issue
|
||||
const response = await this.issueDraftService.createDraftIssue(workspaceSlug, projectId, data);
|
||||
|
||||
// call Fetch parent stats
|
||||
this.fetchParentStats(workspaceSlug, projectId);
|
||||
|
||||
// Add issue to store
|
||||
this.addIssue(response);
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
// call API to create a Draft issue
|
||||
const response = await this.issueDraftService.createDraftIssue(workspaceSlug, projectId, data);
|
||||
// call Fetch parent stats
|
||||
this.fetchParentStats(workspaceSlug, projectId);
|
||||
// Add issue to store
|
||||
this.addIssue(response);
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -640,29 +629,20 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore {
|
||||
* @param issueId
|
||||
*/
|
||||
async removeIssue(workspaceSlug: string, projectId: string, issueId: string) {
|
||||
try {
|
||||
// Store Before state of the issue
|
||||
const issueBeforeRemoval = clone(this.rootIssueStore.issues.getIssueById(issueId));
|
||||
|
||||
// update parent stats optimistically
|
||||
this.updateParentStats(issueBeforeRemoval, undefined);
|
||||
|
||||
// Male API call
|
||||
await this.issueService.deleteIssue(workspaceSlug, projectId, issueId);
|
||||
|
||||
// Remove from Respective issue Id list
|
||||
runInAction(() => {
|
||||
this.removeIssueFromList(issueId);
|
||||
});
|
||||
|
||||
// call fetch Parent stats
|
||||
this.fetchParentStats(workspaceSlug, projectId);
|
||||
|
||||
// Remove issue from main issue Map store
|
||||
this.rootIssueStore.issues.removeIssue(issueId);
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
// Store Before state of the issue
|
||||
const issueBeforeRemoval = clone(this.rootIssueStore.issues.getIssueById(issueId));
|
||||
// update parent stats optimistically
|
||||
this.updateParentStats(issueBeforeRemoval, undefined);
|
||||
// Male API call
|
||||
await this.issueService.deleteIssue(workspaceSlug, projectId, issueId);
|
||||
// Remove from Respective issue Id list
|
||||
runInAction(() => {
|
||||
this.removeIssueFromList(issueId);
|
||||
});
|
||||
// call fetch Parent stats
|
||||
this.fetchParentStats(workspaceSlug, projectId);
|
||||
// Remove issue from main issue Map store
|
||||
this.rootIssueStore.issues.removeIssue(issueId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -672,29 +652,21 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore {
|
||||
* @param issueId
|
||||
*/
|
||||
async issueArchive(workspaceSlug: string, projectId: string, issueId: string) {
|
||||
try {
|
||||
const issueBeforeArchive = clone(this.rootIssueStore.issues.getIssueById(issueId));
|
||||
|
||||
// update parent stats optimistically
|
||||
this.updateParentStats(issueBeforeArchive, undefined);
|
||||
|
||||
// Male API call
|
||||
const response = await this.issueArchiveService.archiveIssue(workspaceSlug, projectId, issueId);
|
||||
|
||||
// call fetch Parent stats
|
||||
this.fetchParentStats(workspaceSlug, projectId);
|
||||
|
||||
runInAction(() => {
|
||||
// Update the Archived at of the issue from store
|
||||
this.rootIssueStore.issues.updateIssue(issueId, {
|
||||
archived_at: response.archived_at,
|
||||
});
|
||||
// Since Archived remove the issue Id from the current store
|
||||
this.removeIssueFromList(issueId);
|
||||
const issueBeforeArchive = clone(this.rootIssueStore.issues.getIssueById(issueId));
|
||||
// update parent stats optimistically
|
||||
this.updateParentStats(issueBeforeArchive, undefined);
|
||||
// Male API call
|
||||
const response = await this.issueArchiveService.archiveIssue(workspaceSlug, projectId, issueId);
|
||||
// call fetch Parent stats
|
||||
this.fetchParentStats(workspaceSlug, projectId);
|
||||
runInAction(() => {
|
||||
// Update the Archived at of the issue from store
|
||||
this.rootIssueStore.issues.updateIssue(issueId, {
|
||||
archived_at: response.archived_at,
|
||||
});
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
// Since Archived remove the issue Id from the current store
|
||||
this.removeIssueFromList(issueId);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -705,38 +677,28 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore {
|
||||
* @returns
|
||||
*/
|
||||
async issueQuickAdd(workspaceSlug: string, projectId: string, data: TIssue) {
|
||||
try {
|
||||
// Add issue to store with a temporary Id
|
||||
this.addIssue(data);
|
||||
|
||||
// call Create issue method
|
||||
const response = await this.createIssue(workspaceSlug, projectId, data);
|
||||
|
||||
runInAction(() => {
|
||||
this.removeIssueFromList(data.id);
|
||||
this.rootIssueStore.issues.removeIssue(data.id);
|
||||
});
|
||||
|
||||
const currentCycleId = data.cycle_id !== "" && data.cycle_id === "None" ? undefined : data.cycle_id;
|
||||
const currentModuleIds =
|
||||
data.module_ids && data.module_ids.length > 0 ? data.module_ids.filter((moduleId) => moduleId != "None") : [];
|
||||
|
||||
const promiseRequests = [];
|
||||
if (currentCycleId) {
|
||||
promiseRequests.push(this.addCycleToIssue(workspaceSlug, projectId, currentCycleId, response.id));
|
||||
}
|
||||
if (currentModuleIds.length > 0) {
|
||||
promiseRequests.push(this.changeModulesInIssue(workspaceSlug, projectId, response.id, currentModuleIds, []));
|
||||
}
|
||||
|
||||
if (promiseRequests && promiseRequests.length > 0) {
|
||||
await Promise.all(promiseRequests);
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
// Add issue to store with a temporary Id
|
||||
this.addIssue(data);
|
||||
// call Create issue method
|
||||
const response = await this.createIssue(workspaceSlug, projectId, data);
|
||||
runInAction(() => {
|
||||
this.removeIssueFromList(data.id);
|
||||
this.rootIssueStore.issues.removeIssue(data.id);
|
||||
});
|
||||
const currentCycleId = data.cycle_id !== "" && data.cycle_id === "None" ? undefined : data.cycle_id;
|
||||
const currentModuleIds =
|
||||
data.module_ids && data.module_ids.length > 0 ? data.module_ids.filter((moduleId) => moduleId != "None") : [];
|
||||
const promiseRequests = [];
|
||||
if (currentCycleId) {
|
||||
promiseRequests.push(this.addCycleToIssue(workspaceSlug, projectId, currentCycleId, response.id));
|
||||
}
|
||||
if (currentModuleIds.length > 0) {
|
||||
promiseRequests.push(this.changeModulesInIssue(workspaceSlug, projectId, response.id, currentModuleIds, []));
|
||||
}
|
||||
if (promiseRequests && promiseRequests.length > 0) {
|
||||
await Promise.all(promiseRequests);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -747,24 +709,18 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore {
|
||||
* @returns
|
||||
*/
|
||||
async removeBulkIssues(workspaceSlug: string, projectId: string, issueIds: string[]) {
|
||||
try {
|
||||
// Make API call to bulk delete issues
|
||||
const response = await this.issueService.bulkDeleteIssues(workspaceSlug, projectId, { issue_ids: issueIds });
|
||||
|
||||
// call fetch parent stats
|
||||
this.fetchParentStats(workspaceSlug, projectId);
|
||||
|
||||
// Remove issues from the store
|
||||
runInAction(() => {
|
||||
issueIds.forEach((issueId) => {
|
||||
this.removeIssueFromList(issueId);
|
||||
this.rootIssueStore.issues.removeIssue(issueId);
|
||||
});
|
||||
// Make API call to bulk delete issues
|
||||
const response = await this.issueService.bulkDeleteIssues(workspaceSlug, projectId, { issue_ids: issueIds });
|
||||
// call fetch parent stats
|
||||
this.fetchParentStats(workspaceSlug, projectId);
|
||||
// Remove issues from the store
|
||||
runInAction(() => {
|
||||
issueIds.forEach((issueId) => {
|
||||
this.removeIssueFromList(issueId);
|
||||
this.rootIssueStore.issues.removeIssue(issueId);
|
||||
});
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -774,26 +730,22 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore {
|
||||
* @param issueIds
|
||||
*/
|
||||
bulkArchiveIssues = async (workspaceSlug: string, projectId: string, issueIds: string[]) => {
|
||||
try {
|
||||
const response = await this.issueService.bulkArchiveIssues(workspaceSlug, projectId, { issue_ids: issueIds });
|
||||
const response = await this.issueService.bulkArchiveIssues(workspaceSlug, projectId, { issue_ids: issueIds });
|
||||
|
||||
runInAction(() => {
|
||||
issueIds.forEach((issueId) => {
|
||||
this.issueUpdate(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
issueId,
|
||||
{
|
||||
archived_at: response.archived_at,
|
||||
},
|
||||
false
|
||||
);
|
||||
this.removeIssueFromList(issueId);
|
||||
});
|
||||
runInAction(() => {
|
||||
issueIds.forEach((issueId) => {
|
||||
this.issueUpdate(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
issueId,
|
||||
{
|
||||
archived_at: response.archived_at,
|
||||
},
|
||||
false
|
||||
);
|
||||
this.removeIssueFromList(issueId);
|
||||
});
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -802,40 +754,36 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore {
|
||||
*/
|
||||
bulkUpdateProperties = async (workspaceSlug: string, projectId: string, data: TBulkOperationsPayload) => {
|
||||
const issueIds = data.issue_ids;
|
||||
try {
|
||||
// make request to update issue properties
|
||||
await this.issueService.bulkOperations(workspaceSlug, projectId, data);
|
||||
// update issues in the store
|
||||
runInAction(() => {
|
||||
issueIds.forEach((issueId) => {
|
||||
const issueBeforeUpdate = clone(this.rootIssueStore.issues.getIssueById(issueId));
|
||||
if (!issueBeforeUpdate) throw new Error("Issue not found");
|
||||
Object.keys(data.properties).forEach((key) => {
|
||||
const property = key as keyof TBulkOperationsPayload["properties"];
|
||||
const propertyValue = data.properties[property];
|
||||
// update root issue map properties
|
||||
if (Array.isArray(propertyValue)) {
|
||||
// if property value is array, append it to the existing values
|
||||
const existingValue = issueBeforeUpdate[property];
|
||||
// convert existing value to an array
|
||||
const newExistingValue = Array.isArray(existingValue) ? existingValue : [];
|
||||
this.rootIssueStore.issues.updateIssue(issueId, {
|
||||
[property]: uniq([...newExistingValue, ...propertyValue]),
|
||||
});
|
||||
} else {
|
||||
// if property value is not an array, simply update the value
|
||||
this.rootIssueStore.issues.updateIssue(issueId, {
|
||||
[property]: propertyValue,
|
||||
});
|
||||
}
|
||||
});
|
||||
const issueDetails = this.rootIssueStore.issues.getIssueById(issueId);
|
||||
this.updateIssueList(issueDetails, issueBeforeUpdate);
|
||||
// make request to update issue properties
|
||||
await this.issueService.bulkOperations(workspaceSlug, projectId, data);
|
||||
// update issues in the store
|
||||
runInAction(() => {
|
||||
issueIds.forEach((issueId) => {
|
||||
const issueBeforeUpdate = clone(this.rootIssueStore.issues.getIssueById(issueId));
|
||||
if (!issueBeforeUpdate) throw new Error("Issue not found");
|
||||
Object.keys(data.properties).forEach((key) => {
|
||||
const property = key as keyof TBulkOperationsPayload["properties"];
|
||||
const propertyValue = data.properties[property];
|
||||
// update root issue map properties
|
||||
if (Array.isArray(propertyValue)) {
|
||||
// if property value is array, append it to the existing values
|
||||
const existingValue = issueBeforeUpdate[property];
|
||||
// convert existing value to an array
|
||||
const newExistingValue = Array.isArray(existingValue) ? existingValue : [];
|
||||
this.rootIssueStore.issues.updateIssue(issueId, {
|
||||
[property]: uniq([...newExistingValue, ...propertyValue]),
|
||||
});
|
||||
} else {
|
||||
// if property value is not an array, simply update the value
|
||||
this.rootIssueStore.issues.updateIssue(issueId, {
|
||||
[property]: propertyValue,
|
||||
});
|
||||
}
|
||||
});
|
||||
const issueDetails = this.rootIssueStore.issues.getIssueById(issueId);
|
||||
this.updateIssueList(issueDetails, issueBeforeUpdate);
|
||||
});
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -853,33 +801,29 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore {
|
||||
issueIds: string[],
|
||||
fetchAddedIssues = true
|
||||
) {
|
||||
try {
|
||||
// Perform an APi call to add issue to cycle
|
||||
await this.issueService.addIssueToCycle(workspaceSlug, projectId, cycleId, {
|
||||
issues: issueIds,
|
||||
});
|
||||
// Perform an APi call to add issue to cycle
|
||||
await this.issueService.addIssueToCycle(workspaceSlug, projectId, cycleId, {
|
||||
issues: issueIds,
|
||||
});
|
||||
|
||||
// if cycle Id is the current Cycle Id then call fetch parent stats
|
||||
if (this.cycleId === cycleId) this.fetchParentStats(workspaceSlug, projectId);
|
||||
// if cycle Id is the current Cycle Id then call fetch parent stats
|
||||
if (this.cycleId === cycleId) this.fetchParentStats(workspaceSlug, projectId);
|
||||
|
||||
// if true, fetch the issue data for all the issueIds
|
||||
if (fetchAddedIssues) await this.rootIssueStore.issues.getIssues(workspaceSlug, projectId, issueIds);
|
||||
// if true, fetch the issue data for all the issueIds
|
||||
if (fetchAddedIssues) await this.rootIssueStore.issues.getIssues(workspaceSlug, projectId, issueIds);
|
||||
|
||||
// Update issueIds from current store
|
||||
runInAction(() => {
|
||||
// If cycle Id is the current cycle Id, then, add issue to list of issueIds
|
||||
if (this.cycleId === cycleId) issueIds.forEach((issueId) => this.addIssueToList(issueId));
|
||||
// If cycle Id is not the current cycle Id, then, remove issue to list of issueIds
|
||||
else if (this.cycleId) issueIds.forEach((issueId) => this.removeIssueFromList(issueId));
|
||||
});
|
||||
// Update issueIds from current store
|
||||
runInAction(() => {
|
||||
// If cycle Id is the current cycle Id, then, add issue to list of issueIds
|
||||
if (this.cycleId === cycleId) issueIds.forEach((issueId) => this.addIssueToList(issueId));
|
||||
// If cycle Id is not the current cycle Id, then, remove issue to list of issueIds
|
||||
else if (this.cycleId) issueIds.forEach((issueId) => this.removeIssueFromList(issueId));
|
||||
});
|
||||
|
||||
// For Each issue update cycle Id by calling current store's update Issue, without making an API call
|
||||
issueIds.forEach((issueId) => {
|
||||
this.issueUpdate(workspaceSlug, projectId, issueId, { cycle_id: cycleId }, false);
|
||||
});
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
// For Each issue update cycle Id by calling current store's update Issue, without making an API call
|
||||
issueIds.forEach((issueId) => {
|
||||
this.issueUpdate(workspaceSlug, projectId, issueId, { cycle_id: cycleId }, false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -890,28 +834,24 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore {
|
||||
* @param issueId
|
||||
*/
|
||||
async removeIssueFromCycle(workspaceSlug: string, projectId: string, cycleId: string, issueId: string) {
|
||||
try {
|
||||
const issueBeforeRemoval = clone(this.rootIssueStore.issues.getIssueById(issueId));
|
||||
const issueBeforeRemoval = clone(this.rootIssueStore.issues.getIssueById(issueId));
|
||||
|
||||
// update parent stats optimistically
|
||||
if (this.cycleId === cycleId) this.updateParentStats(issueBeforeRemoval, undefined, cycleId);
|
||||
// update parent stats optimistically
|
||||
if (this.cycleId === cycleId) this.updateParentStats(issueBeforeRemoval, undefined, cycleId);
|
||||
|
||||
// Perform an APi call to remove issue from cycle
|
||||
await this.issueService.removeIssueFromCycle(workspaceSlug, projectId, cycleId, issueId);
|
||||
// Perform an APi call to remove issue from cycle
|
||||
await this.issueService.removeIssueFromCycle(workspaceSlug, projectId, cycleId, issueId);
|
||||
|
||||
// if cycle Id is the current Cycle Id then call fetch parent stats
|
||||
if (this.cycleId === cycleId) this.fetchParentStats(workspaceSlug, projectId, cycleId);
|
||||
// if cycle Id is the current Cycle Id then call fetch parent stats
|
||||
if (this.cycleId === cycleId) this.fetchParentStats(workspaceSlug, projectId, cycleId);
|
||||
|
||||
runInAction(() => {
|
||||
// If cycle Id is the current cycle Id, then, remove issue from list of issueIds
|
||||
this.cycleId === cycleId && this.removeIssueFromList(issueId);
|
||||
});
|
||||
runInAction(() => {
|
||||
// If cycle Id is the current cycle Id, then, remove issue from list of issueIds
|
||||
this.cycleId === cycleId && this.removeIssueFromList(issueId);
|
||||
});
|
||||
|
||||
// update Issue cycle Id to null by calling current store's update Issue, without making an API call
|
||||
this.issueUpdate(workspaceSlug, projectId, issueId, { cycle_id: null }, false);
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
// update Issue cycle Id to null by calling current store's update Issue, without making an API call
|
||||
this.issueUpdate(workspaceSlug, projectId, issueId, { cycle_id: null }, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1024,32 +964,28 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore {
|
||||
issueIds: string[],
|
||||
fetchAddedIssues = true
|
||||
) {
|
||||
try {
|
||||
// Perform an APi call to add issue to module
|
||||
await this.moduleService.addIssuesToModule(workspaceSlug, projectId, moduleId, {
|
||||
issues: issueIds,
|
||||
});
|
||||
// Perform an APi call to add issue to module
|
||||
await this.moduleService.addIssuesToModule(workspaceSlug, projectId, moduleId, {
|
||||
issues: issueIds,
|
||||
});
|
||||
|
||||
// if true, fetch the issue data for all the issueIds
|
||||
if (fetchAddedIssues) await this.rootIssueStore.issues.getIssues(workspaceSlug, projectId, issueIds);
|
||||
// if true, fetch the issue data for all the issueIds
|
||||
if (fetchAddedIssues) await this.rootIssueStore.issues.getIssues(workspaceSlug, projectId, issueIds);
|
||||
|
||||
// if module Id is the current Module Id then call fetch parent stats
|
||||
if (this.moduleId === moduleId) this.fetchParentStats(workspaceSlug, projectId);
|
||||
// if module Id is the current Module Id then call fetch parent stats
|
||||
if (this.moduleId === moduleId) this.fetchParentStats(workspaceSlug, projectId);
|
||||
|
||||
runInAction(() => {
|
||||
// if module Id is the current Module Id, then, add issue to list of issueIds
|
||||
this.moduleId === moduleId && issueIds.forEach((issueId) => this.addIssueToList(issueId));
|
||||
});
|
||||
runInAction(() => {
|
||||
// if module Id is the current Module Id, then, add issue to list of issueIds
|
||||
this.moduleId === moduleId && issueIds.forEach((issueId) => this.addIssueToList(issueId));
|
||||
});
|
||||
|
||||
// For Each issue update module Ids by calling current store's update Issue, without making an API call
|
||||
issueIds.forEach((issueId) => {
|
||||
const issueModuleIds = get(this.rootIssueStore.issues.issuesMap, [issueId, "module_ids"]) ?? [];
|
||||
const updatedIssueModuleIds = uniq(concat(issueModuleIds, [moduleId]));
|
||||
this.issueUpdate(workspaceSlug, projectId, issueId, { module_ids: updatedIssueModuleIds }, false);
|
||||
});
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
// For Each issue update module Ids by calling current store's update Issue, without making an API call
|
||||
issueIds.forEach((issueId) => {
|
||||
const issueModuleIds = get(this.rootIssueStore.issues.issuesMap, [issueId, "module_ids"]) ?? [];
|
||||
const updatedIssueModuleIds = uniq(concat(issueModuleIds, [moduleId]));
|
||||
this.issueUpdate(workspaceSlug, projectId, issueId, { module_ids: updatedIssueModuleIds }, false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1061,36 +997,27 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore {
|
||||
* @returns
|
||||
*/
|
||||
async removeIssuesFromModule(workspaceSlug: string, projectId: string, moduleId: string, issueIds: string[]) {
|
||||
try {
|
||||
// Perform an APi call to remove issue to module
|
||||
const response = await this.moduleService.removeIssuesFromModuleBulk(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
moduleId,
|
||||
issueIds
|
||||
);
|
||||
// Perform an APi call to remove issue to module
|
||||
const response = await this.moduleService.removeIssuesFromModuleBulk(workspaceSlug, projectId, moduleId, issueIds);
|
||||
|
||||
// if module Id is the current Module Id then call fetch parent stats
|
||||
if (this.moduleId === moduleId) this.fetchParentStats(workspaceSlug, projectId);
|
||||
// if module Id is the current Module Id then call fetch parent stats
|
||||
if (this.moduleId === moduleId) this.fetchParentStats(workspaceSlug, projectId);
|
||||
|
||||
runInAction(() => {
|
||||
// if module Id is the current Module Id, then remove issue from list of issueIds
|
||||
this.moduleId === moduleId && issueIds.forEach((issueId) => this.removeIssueFromList(issueId));
|
||||
runInAction(() => {
|
||||
// if module Id is the current Module Id, then remove issue from list of issueIds
|
||||
this.moduleId === moduleId && issueIds.forEach((issueId) => this.removeIssueFromList(issueId));
|
||||
});
|
||||
|
||||
// For Each issue update module Ids by calling current store's update Issue, without making an API call
|
||||
runInAction(() => {
|
||||
issueIds.forEach((issueId) => {
|
||||
const issueModuleIds = get(this.rootIssueStore.issues.issuesMap, [issueId, "module_ids"]) ?? [];
|
||||
const updatedIssueModuleIds = pull(issueModuleIds, moduleId);
|
||||
this.issueUpdate(workspaceSlug, projectId, issueId, { module_ids: updatedIssueModuleIds }, false);
|
||||
});
|
||||
});
|
||||
|
||||
// For Each issue update module Ids by calling current store's update Issue, without making an API call
|
||||
runInAction(() => {
|
||||
issueIds.forEach((issueId) => {
|
||||
const issueModuleIds = get(this.rootIssueStore.issues.issuesMap, [issueId, "module_ids"]) ?? [];
|
||||
const updatedIssueModuleIds = pull(issueModuleIds, moduleId);
|
||||
this.issueUpdate(workspaceSlug, projectId, issueId, { module_ids: updatedIssueModuleIds }, false);
|
||||
});
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1103,30 +1030,26 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore {
|
||||
async addModulesToIssue(workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) {
|
||||
// keep a copy of the original module ids
|
||||
const originalModuleIds = get(this.rootIssueStore.issues.issuesMap, [issueId, "module_ids"]) ?? [];
|
||||
try {
|
||||
//Perform API call
|
||||
await this.moduleService.addModulesToIssue(workspaceSlug, projectId, issueId, {
|
||||
modules: moduleIds,
|
||||
removed_modules: [],
|
||||
});
|
||||
//Perform API call
|
||||
await this.moduleService.addModulesToIssue(workspaceSlug, projectId, issueId, {
|
||||
modules: moduleIds,
|
||||
removed_modules: [],
|
||||
});
|
||||
|
||||
runInAction(() => {
|
||||
// get current Module Ids of the issue
|
||||
let currentModuleIds = [...originalModuleIds];
|
||||
runInAction(() => {
|
||||
// get current Module Ids of the issue
|
||||
let currentModuleIds = [...originalModuleIds];
|
||||
|
||||
// If current Module Id is included in the modules list, then add Issue to List
|
||||
if (moduleIds.includes(this.moduleId ?? "")) this.addIssueToList(issueId);
|
||||
currentModuleIds = uniq(concat([...currentModuleIds], moduleIds));
|
||||
// If current Module Id is included in the modules list, then add Issue to List
|
||||
if (moduleIds.includes(this.moduleId ?? "")) this.addIssueToList(issueId);
|
||||
currentModuleIds = uniq(concat([...currentModuleIds], moduleIds));
|
||||
|
||||
// For current Issue, update module Ids by calling current store's update Issue, without making an API call
|
||||
this.issueUpdate(workspaceSlug, projectId, issueId, { module_ids: currentModuleIds }, false);
|
||||
});
|
||||
// For current Issue, update module Ids by calling current store's update Issue, without making an API call
|
||||
this.issueUpdate(workspaceSlug, projectId, issueId, { module_ids: currentModuleIds }, false);
|
||||
});
|
||||
|
||||
if (moduleIds.includes(this.moduleId ?? "")) {
|
||||
this.fetchParentStats(workspaceSlug, projectId, this.moduleId);
|
||||
}
|
||||
} catch (error) {
|
||||
throw error;
|
||||
if (moduleIds.includes(this.moduleId ?? "")) {
|
||||
this.fetchParentStats(workspaceSlug, projectId, this.moduleId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -99,62 +99,48 @@ export class IssueAttachmentStore implements IIssueAttachmentStore {
|
||||
};
|
||||
|
||||
fetchAttachments = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
try {
|
||||
const response = await this.issueAttachmentService.getIssueAttachment(workspaceSlug, projectId, issueId);
|
||||
|
||||
this.addAttachments(issueId, response);
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
const response = await this.issueAttachmentService.getIssueAttachment(workspaceSlug, projectId, issueId);
|
||||
this.addAttachments(issueId, response);
|
||||
return response;
|
||||
};
|
||||
|
||||
createAttachment = async (workspaceSlug: string, projectId: string, issueId: string, data: FormData) => {
|
||||
try {
|
||||
const response = await this.issueAttachmentService.uploadIssueAttachment(workspaceSlug, projectId, issueId, data);
|
||||
const issueAttachmentsCount = this.getAttachmentsByIssueId(issueId)?.length ?? 0;
|
||||
const response = await this.issueAttachmentService.uploadIssueAttachment(workspaceSlug, projectId, issueId, data);
|
||||
const issueAttachmentsCount = this.getAttachmentsByIssueId(issueId)?.length ?? 0;
|
||||
|
||||
if (response && response.id) {
|
||||
runInAction(() => {
|
||||
update(this.attachments, [issueId], (attachmentIds = []) => uniq(concat(attachmentIds, [response.id])));
|
||||
set(this.attachmentMap, response.id, response);
|
||||
this.rootIssueStore.issues.updateIssue(issueId, {
|
||||
attachment_count: issueAttachmentsCount + 1, // increment attachment count
|
||||
});
|
||||
if (response && response.id) {
|
||||
runInAction(() => {
|
||||
update(this.attachments, [issueId], (attachmentIds = []) => uniq(concat(attachmentIds, [response.id])));
|
||||
set(this.attachmentMap, response.id, response);
|
||||
this.rootIssueStore.issues.updateIssue(issueId, {
|
||||
attachment_count: issueAttachmentsCount + 1, // increment attachment count
|
||||
});
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
return response;
|
||||
};
|
||||
|
||||
removeAttachment = async (workspaceSlug: string, projectId: string, issueId: string, attachmentId: string) => {
|
||||
try {
|
||||
const response = await this.issueAttachmentService.deleteIssueAttachment(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
issueId,
|
||||
attachmentId
|
||||
);
|
||||
const issueAttachmentsCount = this.getAttachmentsByIssueId(issueId)?.length ?? 1;
|
||||
const response = await this.issueAttachmentService.deleteIssueAttachment(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
issueId,
|
||||
attachmentId
|
||||
);
|
||||
const issueAttachmentsCount = this.getAttachmentsByIssueId(issueId)?.length ?? 1;
|
||||
|
||||
runInAction(() => {
|
||||
update(this.attachments, [issueId], (attachmentIds = []) => {
|
||||
if (attachmentIds.includes(attachmentId)) pull(attachmentIds, attachmentId);
|
||||
return attachmentIds;
|
||||
});
|
||||
delete this.attachmentMap[attachmentId];
|
||||
this.rootIssueStore.issues.updateIssue(issueId, {
|
||||
attachment_count: issueAttachmentsCount - 1, // decrement attachment count
|
||||
});
|
||||
runInAction(() => {
|
||||
update(this.attachments, [issueId], (attachmentIds = []) => {
|
||||
if (attachmentIds.includes(attachmentId)) pull(attachmentIds, attachmentId);
|
||||
return attachmentIds;
|
||||
});
|
||||
delete this.attachmentMap[attachmentId];
|
||||
this.rootIssueStore.issues.updateIssue(issueId, {
|
||||
attachment_count: issueAttachmentsCount - 1, // decrement attachment count
|
||||
});
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
return response;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -90,53 +90,45 @@ export class IssueCommentStore implements IIssueCommentStore {
|
||||
issueId: string,
|
||||
loaderType: TCommentLoader = "fetch"
|
||||
) => {
|
||||
try {
|
||||
this.loader = loaderType;
|
||||
this.loader = loaderType;
|
||||
|
||||
let props = {};
|
||||
const _commentIds = this.getCommentsByIssueId(issueId);
|
||||
if (_commentIds && _commentIds.length > 0) {
|
||||
const _comment = this.getCommentById(_commentIds[_commentIds.length - 1]);
|
||||
if (_comment) props = { created_at__gt: _comment.created_at };
|
||||
}
|
||||
|
||||
const comments = await this.issueCommentService.getIssueComments(workspaceSlug, projectId, issueId, props);
|
||||
|
||||
const commentIds = comments.map((comment) => comment.id);
|
||||
runInAction(() => {
|
||||
update(this.comments, issueId, (_commentIds) => {
|
||||
if (!_commentIds) return commentIds;
|
||||
return uniq(concat(_commentIds, commentIds));
|
||||
});
|
||||
comments.forEach((comment) => {
|
||||
this.rootIssueDetail.commentReaction.applyCommentReactions(comment.id, comment?.comment_reactions || []);
|
||||
set(this.commentMap, comment.id, comment);
|
||||
});
|
||||
this.loader = undefined;
|
||||
});
|
||||
|
||||
return comments;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
let props = {};
|
||||
const _commentIds = this.getCommentsByIssueId(issueId);
|
||||
if (_commentIds && _commentIds.length > 0) {
|
||||
const _comment = this.getCommentById(_commentIds[_commentIds.length - 1]);
|
||||
if (_comment) props = { created_at__gt: _comment.created_at };
|
||||
}
|
||||
|
||||
const comments = await this.issueCommentService.getIssueComments(workspaceSlug, projectId, issueId, props);
|
||||
|
||||
const commentIds = comments.map((comment) => comment.id);
|
||||
runInAction(() => {
|
||||
update(this.comments, issueId, (_commentIds) => {
|
||||
if (!_commentIds) return commentIds;
|
||||
return uniq(concat(_commentIds, commentIds));
|
||||
});
|
||||
comments.forEach((comment) => {
|
||||
this.rootIssueDetail.commentReaction.applyCommentReactions(comment.id, comment?.comment_reactions || []);
|
||||
set(this.commentMap, comment.id, comment);
|
||||
});
|
||||
this.loader = undefined;
|
||||
});
|
||||
|
||||
return comments;
|
||||
};
|
||||
|
||||
createComment = async (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssueComment>) => {
|
||||
try {
|
||||
const response = await this.issueCommentService.createIssueComment(workspaceSlug, projectId, issueId, data);
|
||||
const response = await this.issueCommentService.createIssueComment(workspaceSlug, projectId, issueId, data);
|
||||
|
||||
runInAction(() => {
|
||||
update(this.comments, issueId, (_commentIds) => {
|
||||
if (!_commentIds) return [response.id];
|
||||
return uniq(concat(_commentIds, [response.id]));
|
||||
});
|
||||
set(this.commentMap, response.id, response);
|
||||
runInAction(() => {
|
||||
update(this.comments, issueId, (_commentIds) => {
|
||||
if (!_commentIds) return [response.id];
|
||||
return uniq(concat(_commentIds, [response.id]));
|
||||
});
|
||||
set(this.commentMap, response.id, response);
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
return response;
|
||||
};
|
||||
|
||||
updateComment = async (
|
||||
@@ -169,17 +161,13 @@ export class IssueCommentStore implements IIssueCommentStore {
|
||||
};
|
||||
|
||||
removeComment = async (workspaceSlug: string, projectId: string, issueId: string, commentId: string) => {
|
||||
try {
|
||||
const response = await this.issueCommentService.deleteIssueComment(workspaceSlug, projectId, issueId, commentId);
|
||||
const response = await this.issueCommentService.deleteIssueComment(workspaceSlug, projectId, issueId, commentId);
|
||||
|
||||
runInAction(() => {
|
||||
pull(this.comments[issueId], commentId);
|
||||
delete this.commentMap[commentId];
|
||||
});
|
||||
runInAction(() => {
|
||||
pull(this.comments[issueId], commentId);
|
||||
delete this.commentMap[commentId];
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
return response;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -92,33 +92,24 @@ export class IssueLinkStore implements IIssueLinkStore {
|
||||
};
|
||||
|
||||
fetchLinks = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
try {
|
||||
const response = await this.issueService.fetchIssueLinks(workspaceSlug, projectId, issueId);
|
||||
this.addLinks(issueId, response);
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
const response = await this.issueService.fetchIssueLinks(workspaceSlug, projectId, issueId);
|
||||
this.addLinks(issueId, response);
|
||||
return response;
|
||||
};
|
||||
|
||||
createLink = async (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssueLink>) => {
|
||||
try {
|
||||
const response = await this.issueService.createIssueLink(workspaceSlug, projectId, issueId, data);
|
||||
const issueLinkCount = this.getLinksByIssueId(issueId)?.length ?? 0;
|
||||
runInAction(() => {
|
||||
this.links[issueId].push(response.id);
|
||||
set(this.linkMap, response.id, response);
|
||||
this.rootIssueDetailStore.rootIssueStore.issues.updateIssue(issueId, {
|
||||
link_count: issueLinkCount + 1, // increment link count
|
||||
});
|
||||
const response = await this.issueService.createIssueLink(workspaceSlug, projectId, issueId, data);
|
||||
const issueLinkCount = this.getLinksByIssueId(issueId)?.length ?? 0;
|
||||
runInAction(() => {
|
||||
this.links[issueId].push(response.id);
|
||||
set(this.linkMap, response.id, response);
|
||||
this.rootIssueDetailStore.rootIssueStore.issues.updateIssue(issueId, {
|
||||
link_count: issueLinkCount + 1, // increment link count
|
||||
});
|
||||
|
||||
// fetching activity
|
||||
this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
// fetching activity
|
||||
this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
|
||||
return response;
|
||||
};
|
||||
|
||||
updateLink = async (
|
||||
@@ -128,43 +119,34 @@ export class IssueLinkStore implements IIssueLinkStore {
|
||||
linkId: string,
|
||||
data: Partial<TIssueLink>
|
||||
) => {
|
||||
try {
|
||||
runInAction(() => {
|
||||
Object.keys(data).forEach((key) => {
|
||||
set(this.linkMap, [linkId, key], data[key as keyof TIssueLink]);
|
||||
});
|
||||
runInAction(() => {
|
||||
Object.keys(data).forEach((key) => {
|
||||
set(this.linkMap, [linkId, key], data[key as keyof TIssueLink]);
|
||||
});
|
||||
});
|
||||
|
||||
const response = await this.issueService.updateIssueLink(workspaceSlug, projectId, issueId, linkId, data);
|
||||
const response = await this.issueService.updateIssueLink(workspaceSlug, projectId, issueId, linkId, data);
|
||||
|
||||
// fetching activity
|
||||
this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
|
||||
return response;
|
||||
} catch (error) {
|
||||
// TODO: fetch issue detail
|
||||
throw error;
|
||||
}
|
||||
// fetching activity
|
||||
this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
|
||||
return response;
|
||||
};
|
||||
|
||||
removeLink = async (workspaceSlug: string, projectId: string, issueId: string, linkId: string) => {
|
||||
try {
|
||||
const issueLinkCount = this.getLinksByIssueId(issueId)?.length ?? 0;
|
||||
await this.issueService.deleteIssueLink(workspaceSlug, projectId, issueId, linkId);
|
||||
const issueLinkCount = this.getLinksByIssueId(issueId)?.length ?? 0;
|
||||
await this.issueService.deleteIssueLink(workspaceSlug, projectId, issueId, linkId);
|
||||
|
||||
const linkIndex = this.links[issueId].findIndex((_comment) => _comment === linkId);
|
||||
if (linkIndex >= 0)
|
||||
runInAction(() => {
|
||||
this.links[issueId].splice(linkIndex, 1);
|
||||
delete this.linkMap[linkId];
|
||||
this.rootIssueDetailStore.rootIssueStore.issues.updateIssue(issueId, {
|
||||
link_count: issueLinkCount - 1, // decrement link count
|
||||
});
|
||||
const linkIndex = this.links[issueId].findIndex((_comment) => _comment === linkId);
|
||||
if (linkIndex >= 0)
|
||||
runInAction(() => {
|
||||
this.links[issueId].splice(linkIndex, 1);
|
||||
delete this.linkMap[linkId];
|
||||
this.rootIssueDetailStore.rootIssueStore.issues.updateIssue(issueId, {
|
||||
link_count: issueLinkCount - 1, // decrement link count
|
||||
});
|
||||
});
|
||||
|
||||
// fetching activity
|
||||
this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
// fetching activity
|
||||
this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -109,37 +109,27 @@ export class IssueReactionStore implements IIssueReactionStore {
|
||||
|
||||
// actions
|
||||
fetchReactions = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
try {
|
||||
const response = await this.issueReactionService.listIssueReactions(workspaceSlug, projectId, issueId);
|
||||
|
||||
this.addReactions(issueId, response);
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
const response = await this.issueReactionService.listIssueReactions(workspaceSlug, projectId, issueId);
|
||||
this.addReactions(issueId, response);
|
||||
return response;
|
||||
};
|
||||
|
||||
createReaction = async (workspaceSlug: string, projectId: string, issueId: string, reaction: string) => {
|
||||
try {
|
||||
const response = await this.issueReactionService.createIssueReaction(workspaceSlug, projectId, issueId, {
|
||||
reaction,
|
||||
});
|
||||
const response = await this.issueReactionService.createIssueReaction(workspaceSlug, projectId, issueId, {
|
||||
reaction,
|
||||
});
|
||||
|
||||
runInAction(() => {
|
||||
update(this.reactions, [issueId, reaction], (reactionId) => {
|
||||
if (!reactionId) return [response.id];
|
||||
return concat(reactionId, response.id);
|
||||
});
|
||||
set(this.reactionMap, response.id, response);
|
||||
runInAction(() => {
|
||||
update(this.reactions, [issueId, reaction], (reactionId) => {
|
||||
if (!reactionId) return [response.id];
|
||||
return concat(reactionId, response.id);
|
||||
});
|
||||
set(this.reactionMap, response.id, response);
|
||||
});
|
||||
|
||||
// fetching activity
|
||||
this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
// fetching activity
|
||||
this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
|
||||
return response;
|
||||
};
|
||||
|
||||
removeReaction = async (
|
||||
@@ -149,24 +139,20 @@ export class IssueReactionStore implements IIssueReactionStore {
|
||||
reaction: string,
|
||||
userId: string
|
||||
) => {
|
||||
try {
|
||||
const userReactions = this.reactionsByUser(issueId, userId);
|
||||
const currentReaction = find(userReactions, { actor: userId, reaction: reaction });
|
||||
const userReactions = this.reactionsByUser(issueId, userId);
|
||||
const currentReaction = find(userReactions, { actor: userId, reaction: reaction });
|
||||
|
||||
if (currentReaction && currentReaction.id) {
|
||||
runInAction(() => {
|
||||
pull(this.reactions[issueId][reaction], currentReaction.id);
|
||||
delete this.reactionMap[reaction];
|
||||
});
|
||||
}
|
||||
|
||||
const response = await this.issueReactionService.deleteIssueReaction(workspaceSlug, projectId, issueId, reaction);
|
||||
|
||||
// fetching activity
|
||||
this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
if (currentReaction && currentReaction.id) {
|
||||
runInAction(() => {
|
||||
pull(this.reactions[issueId][reaction], currentReaction.id);
|
||||
delete this.reactionMap[reaction];
|
||||
});
|
||||
}
|
||||
|
||||
const response = await this.issueReactionService.deleteIssueReaction(workspaceSlug, projectId, issueId, reaction);
|
||||
|
||||
// fetching activity
|
||||
this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
|
||||
return response;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -113,88 +113,75 @@ export class IssueSubIssuesStore implements IIssueSubIssuesStore {
|
||||
};
|
||||
|
||||
fetchSubIssues = async (workspaceSlug: string, projectId: string, parentIssueId: string) => {
|
||||
try {
|
||||
const response = await this.issueService.subIssues(workspaceSlug, projectId, parentIssueId);
|
||||
const subIssuesStateDistribution = response?.state_distribution ?? {};
|
||||
const subIssues = (response.sub_issues ?? []) as TIssue[];
|
||||
|
||||
this.rootIssueDetailStore.rootIssueStore.issues.addIssue(subIssues);
|
||||
|
||||
// fetch other issues states and members when sub-issues are from different project
|
||||
if (subIssues && subIssues.length > 0) {
|
||||
const otherProjectIds = uniq(
|
||||
subIssues.map((issue) => issue.project_id).filter((id) => !!id && id !== projectId)
|
||||
) as string[];
|
||||
this.fetchOtherProjectProperties(workspaceSlug, otherProjectIds);
|
||||
}
|
||||
|
||||
if (subIssues) {
|
||||
this.rootIssueDetailStore.rootIssueStore.issues.updateIssue(parentIssueId, {
|
||||
sub_issues_count: subIssues.length,
|
||||
});
|
||||
}
|
||||
|
||||
runInAction(() => {
|
||||
set(this.subIssuesStateDistribution, parentIssueId, subIssuesStateDistribution);
|
||||
set(
|
||||
this.subIssues,
|
||||
parentIssueId,
|
||||
subIssues.map((issue) => issue.id)
|
||||
);
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
const response = await this.issueService.subIssues(workspaceSlug, projectId, parentIssueId);
|
||||
const subIssuesStateDistribution = response?.state_distribution ?? {};
|
||||
const subIssues = (response.sub_issues ?? []) as TIssue[];
|
||||
this.rootIssueDetailStore.rootIssueStore.issues.addIssue(subIssues);
|
||||
// fetch other issues states and members when sub-issues are from different project
|
||||
if (subIssues && subIssues.length > 0) {
|
||||
const otherProjectIds = uniq(
|
||||
subIssues.map((issue) => issue.project_id).filter((id) => !!id && id !== projectId)
|
||||
) as string[];
|
||||
this.fetchOtherProjectProperties(workspaceSlug, otherProjectIds);
|
||||
}
|
||||
if (subIssues) {
|
||||
this.rootIssueDetailStore.rootIssueStore.issues.updateIssue(parentIssueId, {
|
||||
sub_issues_count: subIssues.length,
|
||||
});
|
||||
}
|
||||
runInAction(() => {
|
||||
set(this.subIssuesStateDistribution, parentIssueId, subIssuesStateDistribution);
|
||||
set(
|
||||
this.subIssues,
|
||||
parentIssueId,
|
||||
subIssues.map((issue) => issue.id)
|
||||
);
|
||||
});
|
||||
return response;
|
||||
};
|
||||
|
||||
createSubIssues = async (workspaceSlug: string, projectId: string, parentIssueId: string, issueIds: string[]) => {
|
||||
try {
|
||||
const response = await this.issueService.addSubIssues(workspaceSlug, projectId, parentIssueId, {
|
||||
sub_issue_ids: issueIds,
|
||||
});
|
||||
const response = await this.issueService.addSubIssues(workspaceSlug, projectId, parentIssueId, {
|
||||
sub_issue_ids: issueIds,
|
||||
});
|
||||
|
||||
const subIssuesStateDistribution = response?.state_distribution;
|
||||
const subIssues = response.sub_issues as TIssue[];
|
||||
const subIssuesStateDistribution = response?.state_distribution;
|
||||
const subIssues = response.sub_issues as TIssue[];
|
||||
|
||||
// fetch other issues states and members when sub-issues are from different project
|
||||
if (subIssues && subIssues.length > 0) {
|
||||
const otherProjectIds = uniq(
|
||||
subIssues.map((issue) => issue.project_id).filter((id) => !!id && id !== projectId)
|
||||
) as string[];
|
||||
this.fetchOtherProjectProperties(workspaceSlug, otherProjectIds);
|
||||
}
|
||||
|
||||
runInAction(() => {
|
||||
Object.keys(subIssuesStateDistribution).forEach((key) => {
|
||||
const stateGroup = key as keyof TSubIssuesStateDistribution;
|
||||
update(this.subIssuesStateDistribution, [parentIssueId, stateGroup], (stateDistribution) => {
|
||||
if (!stateDistribution) return subIssuesStateDistribution[stateGroup];
|
||||
return concat(stateDistribution, subIssuesStateDistribution[stateGroup]);
|
||||
});
|
||||
});
|
||||
|
||||
const issueIds = subIssues.map((issue) => issue.id);
|
||||
update(this.subIssues, [parentIssueId], (issues) => {
|
||||
if (!issues) return issueIds;
|
||||
return concat(issues, issueIds);
|
||||
});
|
||||
});
|
||||
|
||||
this.rootIssueDetailStore.rootIssueStore.issues.addIssue(subIssues);
|
||||
|
||||
// update sub-issues_count of the parent issue
|
||||
set(
|
||||
this.rootIssueDetailStore.rootIssueStore.issues.issuesMap,
|
||||
[parentIssueId, "sub_issues_count"],
|
||||
this.subIssues[parentIssueId].length
|
||||
);
|
||||
|
||||
return;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
// fetch other issues states and members when sub-issues are from different project
|
||||
if (subIssues && subIssues.length > 0) {
|
||||
const otherProjectIds = uniq(
|
||||
subIssues.map((issue) => issue.project_id).filter((id) => !!id && id !== projectId)
|
||||
) as string[];
|
||||
this.fetchOtherProjectProperties(workspaceSlug, otherProjectIds);
|
||||
}
|
||||
|
||||
runInAction(() => {
|
||||
Object.keys(subIssuesStateDistribution).forEach((key) => {
|
||||
const stateGroup = key as keyof TSubIssuesStateDistribution;
|
||||
update(this.subIssuesStateDistribution, [parentIssueId, stateGroup], (stateDistribution) => {
|
||||
if (!stateDistribution) return subIssuesStateDistribution[stateGroup];
|
||||
return concat(stateDistribution, subIssuesStateDistribution[stateGroup]);
|
||||
});
|
||||
});
|
||||
|
||||
const issueIds = subIssues.map((issue) => issue.id);
|
||||
update(this.subIssues, [parentIssueId], (issues) => {
|
||||
if (!issues) return issueIds;
|
||||
return concat(issues, issueIds);
|
||||
});
|
||||
});
|
||||
|
||||
this.rootIssueDetailStore.rootIssueStore.issues.addIssue(subIssues);
|
||||
|
||||
// update sub-issues_count of the parent issue
|
||||
set(
|
||||
this.rootIssueDetailStore.rootIssueStore.issues.issuesMap,
|
||||
[parentIssueId, "sub_issues_count"],
|
||||
this.subIssues[parentIssueId].length
|
||||
);
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
updateSubIssue = async (
|
||||
@@ -206,164 +193,148 @@ export class IssueSubIssuesStore implements IIssueSubIssuesStore {
|
||||
oldIssue: Partial<TIssue> = {},
|
||||
fromModal: boolean = false
|
||||
) => {
|
||||
try {
|
||||
if (!fromModal)
|
||||
await this.rootIssueDetailStore.rootIssueStore.projectIssues.updateIssue(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
issueId,
|
||||
issueData
|
||||
);
|
||||
if (!fromModal)
|
||||
await this.rootIssueDetailStore.rootIssueStore.projectIssues.updateIssue(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
issueId,
|
||||
issueData
|
||||
);
|
||||
|
||||
// parent update
|
||||
if (issueData.hasOwnProperty("parent_id") && issueData.parent_id !== oldIssue.parent_id) {
|
||||
// parent update
|
||||
if (issueData.hasOwnProperty("parent_id") && issueData.parent_id !== oldIssue.parent_id) {
|
||||
runInAction(() => {
|
||||
if (oldIssue.parent_id) pull(this.subIssues[oldIssue.parent_id], issueId);
|
||||
if (issueData.parent_id)
|
||||
set(this.subIssues, [issueData.parent_id], concat(this.subIssues[issueData.parent_id], issueId));
|
||||
});
|
||||
}
|
||||
|
||||
// state update
|
||||
if (issueData.hasOwnProperty("state_id") && issueData.state_id !== oldIssue.state_id) {
|
||||
let oldIssueStateGroup: string | undefined = undefined;
|
||||
let issueStateGroup: string | undefined = undefined;
|
||||
|
||||
if (oldIssue.state_id) {
|
||||
const state = this.rootIssueDetailStore.rootIssueStore.state.getStateById(oldIssue.state_id);
|
||||
if (state?.group) oldIssueStateGroup = state.group;
|
||||
}
|
||||
|
||||
if (issueData.state_id) {
|
||||
const state = this.rootIssueDetailStore.rootIssueStore.state.getStateById(issueData.state_id);
|
||||
if (state?.group) issueStateGroup = state.group;
|
||||
}
|
||||
|
||||
if (oldIssueStateGroup && issueStateGroup && issueStateGroup !== oldIssueStateGroup) {
|
||||
runInAction(() => {
|
||||
if (oldIssue.parent_id) pull(this.subIssues[oldIssue.parent_id], issueId);
|
||||
if (issueData.parent_id)
|
||||
set(this.subIssues, [issueData.parent_id], concat(this.subIssues[issueData.parent_id], issueId));
|
||||
if (oldIssueStateGroup)
|
||||
update(this.subIssuesStateDistribution, [parentIssueId, oldIssueStateGroup], (stateDistribution) => {
|
||||
if (!stateDistribution) return;
|
||||
return pull(stateDistribution, issueId);
|
||||
});
|
||||
|
||||
if (issueStateGroup)
|
||||
update(this.subIssuesStateDistribution, [parentIssueId, issueStateGroup], (stateDistribution) => {
|
||||
if (!stateDistribution) return [issueId];
|
||||
return concat(stateDistribution, issueId);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// state update
|
||||
if (issueData.hasOwnProperty("state_id") && issueData.state_id !== oldIssue.state_id) {
|
||||
let oldIssueStateGroup: string | undefined = undefined;
|
||||
let issueStateGroup: string | undefined = undefined;
|
||||
|
||||
if (oldIssue.state_id) {
|
||||
const state = this.rootIssueDetailStore.rootIssueStore.state.getStateById(oldIssue.state_id);
|
||||
if (state?.group) oldIssueStateGroup = state.group;
|
||||
}
|
||||
|
||||
if (issueData.state_id) {
|
||||
const state = this.rootIssueDetailStore.rootIssueStore.state.getStateById(issueData.state_id);
|
||||
if (state?.group) issueStateGroup = state.group;
|
||||
}
|
||||
|
||||
if (oldIssueStateGroup && issueStateGroup && issueStateGroup !== oldIssueStateGroup) {
|
||||
runInAction(() => {
|
||||
if (oldIssueStateGroup)
|
||||
update(this.subIssuesStateDistribution, [parentIssueId, oldIssueStateGroup], (stateDistribution) => {
|
||||
if (!stateDistribution) return;
|
||||
return pull(stateDistribution, issueId);
|
||||
});
|
||||
|
||||
if (issueStateGroup)
|
||||
update(this.subIssuesStateDistribution, [parentIssueId, issueStateGroup], (stateDistribution) => {
|
||||
if (!stateDistribution) return [issueId];
|
||||
return concat(stateDistribution, issueId);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
removeSubIssue = async (workspaceSlug: string, projectId: string, parentIssueId: string, issueId: string) => {
|
||||
try {
|
||||
await this.rootIssueDetailStore.rootIssueStore.projectIssues.updateIssue(workspaceSlug, projectId, issueId, {
|
||||
parent_id: null,
|
||||
});
|
||||
await this.rootIssueDetailStore.rootIssueStore.projectIssues.updateIssue(workspaceSlug, projectId, issueId, {
|
||||
parent_id: null,
|
||||
});
|
||||
|
||||
const issue = this.rootIssueDetailStore.issue.getIssueById(issueId);
|
||||
if (issue && issue.state_id) {
|
||||
let issueStateGroup: string | undefined = undefined;
|
||||
const state = this.rootIssueDetailStore.rootIssueStore.state.getStateById(issue.state_id);
|
||||
if (state?.group) issueStateGroup = state.group;
|
||||
const issue = this.rootIssueDetailStore.issue.getIssueById(issueId);
|
||||
if (issue && issue.state_id) {
|
||||
let issueStateGroup: string | undefined = undefined;
|
||||
const state = this.rootIssueDetailStore.rootIssueStore.state.getStateById(issue.state_id);
|
||||
if (state?.group) issueStateGroup = state.group;
|
||||
|
||||
if (issueStateGroup) {
|
||||
runInAction(() => {
|
||||
if (issueStateGroup)
|
||||
update(this.subIssuesStateDistribution, [parentIssueId, issueStateGroup], (stateDistribution) => {
|
||||
if (!stateDistribution) return;
|
||||
return pull(stateDistribution, issueId);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (issueStateGroup) {
|
||||
runInAction(() => {
|
||||
if (issueStateGroup)
|
||||
update(this.subIssuesStateDistribution, [parentIssueId, issueStateGroup], (stateDistribution) => {
|
||||
if (!stateDistribution) return;
|
||||
return pull(stateDistribution, issueId);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
runInAction(() => {
|
||||
pull(this.subIssues[parentIssueId], issueId);
|
||||
// update sub-issues_count of the parent issue
|
||||
set(
|
||||
this.rootIssueDetailStore.rootIssueStore.issues.issuesMap,
|
||||
[parentIssueId, "sub_issues_count"],
|
||||
this.subIssues[parentIssueId].length
|
||||
);
|
||||
});
|
||||
|
||||
return;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
runInAction(() => {
|
||||
pull(this.subIssues[parentIssueId], issueId);
|
||||
// update sub-issues_count of the parent issue
|
||||
set(
|
||||
this.rootIssueDetailStore.rootIssueStore.issues.issuesMap,
|
||||
[parentIssueId, "sub_issues_count"],
|
||||
this.subIssues[parentIssueId].length
|
||||
);
|
||||
});
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
deleteSubIssue = async (workspaceSlug: string, projectId: string, parentIssueId: string, issueId: string) => {
|
||||
try {
|
||||
await this.rootIssueDetailStore.rootIssueStore.projectIssues.removeIssue(workspaceSlug, projectId, issueId);
|
||||
await this.rootIssueDetailStore.rootIssueStore.projectIssues.removeIssue(workspaceSlug, projectId, issueId);
|
||||
|
||||
const issue = this.rootIssueDetailStore.issue.getIssueById(issueId);
|
||||
if (issue && issue.state_id) {
|
||||
let issueStateGroup: string | undefined = undefined;
|
||||
const state = this.rootIssueDetailStore.rootIssueStore.state.getStateById(issue.state_id);
|
||||
if (state?.group) issueStateGroup = state.group;
|
||||
const issue = this.rootIssueDetailStore.issue.getIssueById(issueId);
|
||||
if (issue && issue.state_id) {
|
||||
let issueStateGroup: string | undefined = undefined;
|
||||
const state = this.rootIssueDetailStore.rootIssueStore.state.getStateById(issue.state_id);
|
||||
if (state?.group) issueStateGroup = state.group;
|
||||
|
||||
if (issueStateGroup) {
|
||||
runInAction(() => {
|
||||
if (issueStateGroup)
|
||||
update(this.subIssuesStateDistribution, [parentIssueId, issueStateGroup], (stateDistribution) => {
|
||||
if (!stateDistribution) return;
|
||||
return pull(stateDistribution, issueId);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (issueStateGroup) {
|
||||
runInAction(() => {
|
||||
if (issueStateGroup)
|
||||
update(this.subIssuesStateDistribution, [parentIssueId, issueStateGroup], (stateDistribution) => {
|
||||
if (!stateDistribution) return;
|
||||
return pull(stateDistribution, issueId);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
runInAction(() => {
|
||||
pull(this.subIssues[parentIssueId], issueId);
|
||||
// update sub-issues_count of the parent issue
|
||||
set(
|
||||
this.rootIssueDetailStore.rootIssueStore.issues.issuesMap,
|
||||
[parentIssueId, "sub_issues_count"],
|
||||
this.subIssues[parentIssueId].length
|
||||
);
|
||||
});
|
||||
|
||||
return;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
runInAction(() => {
|
||||
pull(this.subIssues[parentIssueId], issueId);
|
||||
// update sub-issues_count of the parent issue
|
||||
set(
|
||||
this.rootIssueDetailStore.rootIssueStore.issues.issuesMap,
|
||||
[parentIssueId, "sub_issues_count"],
|
||||
this.subIssues[parentIssueId].length
|
||||
);
|
||||
});
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
fetchOtherProjectProperties = async (workspaceSlug: string, projectIds: string[]) => {
|
||||
try {
|
||||
if (projectIds.length > 0) {
|
||||
for (const projectId of projectIds) {
|
||||
// fetching other project states
|
||||
this.rootIssueDetailStore.rootIssueStore.rootStore.state.fetchProjectStates(workspaceSlug, projectId);
|
||||
// fetching other project members
|
||||
this.rootIssueDetailStore.rootIssueStore.rootStore.memberRoot.project.fetchProjectMembers(
|
||||
workspaceSlug,
|
||||
projectId
|
||||
);
|
||||
// fetching other project labels
|
||||
this.rootIssueDetailStore.rootIssueStore.rootStore.label.fetchProjectLabels(workspaceSlug, projectId);
|
||||
// fetching other project cycles
|
||||
this.rootIssueDetailStore.rootIssueStore.rootStore.cycle.fetchAllCycles(workspaceSlug, projectId);
|
||||
// fetching other project modules
|
||||
this.rootIssueDetailStore.rootIssueStore.rootStore.module.fetchModules(workspaceSlug, projectId);
|
||||
// fetching other project estimates
|
||||
this.rootIssueDetailStore.rootIssueStore.rootStore.projectEstimate.getProjectEstimates(
|
||||
workspaceSlug,
|
||||
projectId
|
||||
);
|
||||
}
|
||||
if (projectIds.length > 0) {
|
||||
for (const projectId of projectIds) {
|
||||
// fetching other project states
|
||||
this.rootIssueDetailStore.rootIssueStore.rootStore.state.fetchProjectStates(workspaceSlug, projectId);
|
||||
// fetching other project members
|
||||
this.rootIssueDetailStore.rootIssueStore.rootStore.memberRoot.project.fetchProjectMembers(
|
||||
workspaceSlug,
|
||||
projectId
|
||||
);
|
||||
// fetching other project labels
|
||||
this.rootIssueDetailStore.rootIssueStore.rootStore.label.fetchProjectLabels(workspaceSlug, projectId);
|
||||
// fetching other project cycles
|
||||
this.rootIssueDetailStore.rootIssueStore.rootStore.cycle.fetchAllCycles(workspaceSlug, projectId);
|
||||
// fetching other project modules
|
||||
this.rootIssueDetailStore.rootIssueStore.rootStore.module.fetchModules(workspaceSlug, projectId);
|
||||
// fetching other project estimates
|
||||
this.rootIssueDetailStore.rootIssueStore.rootStore.projectEstimate.getProjectEstimates(
|
||||
workspaceSlug,
|
||||
projectId
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -61,19 +61,13 @@ export class IssueSubscriptionStore implements IIssueSubscriptionStore {
|
||||
};
|
||||
|
||||
fetchSubscriptions = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
try {
|
||||
const subscription = await this.issueService.getIssueNotificationSubscriptionStatus(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
issueId
|
||||
);
|
||||
|
||||
this.addSubscription(issueId, subscription?.subscribed);
|
||||
|
||||
return subscription?.subscribed;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
const subscription = await this.issueService.getIssueNotificationSubscriptionStatus(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
issueId
|
||||
);
|
||||
this.addSubscription(issueId, subscription?.subscribed);
|
||||
return subscription?.subscribed;
|
||||
};
|
||||
|
||||
createSubscription = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
|
||||
@@ -31,6 +31,7 @@ export interface ICalendarStore {
|
||||
|
||||
export class CalendarStore implements ICalendarStore {
|
||||
loader: boolean = false;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
error: any | null = null;
|
||||
|
||||
// observables
|
||||
|
||||
46
yarn.lock
46
yarn.lock
@@ -3819,6 +3819,13 @@
|
||||
"@types/connect" "*"
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/compression@^1.7.5":
|
||||
version "1.7.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/compression/-/compression-1.7.5.tgz#0f80efef6eb031be57b12221c4ba6bc3577808f7"
|
||||
integrity sha512-AAQvK5pxMpaT+nDvhHrsBhLSYG5yQdtkaJE1WYieSNY2mVFKAgmU4ks65rkZD5oqnGCFLyQpUr1CqI4DmUMyDg==
|
||||
dependencies:
|
||||
"@types/express" "*"
|
||||
|
||||
"@types/connect@*":
|
||||
version "3.4.38"
|
||||
resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858"
|
||||
@@ -4607,7 +4614,7 @@ abort-controller@^3.0.0:
|
||||
dependencies:
|
||||
event-target-shim "^5.0.0"
|
||||
|
||||
accepts@~1.3.8:
|
||||
accepts@~1.3.5, accepts@~1.3.8:
|
||||
version "1.3.8"
|
||||
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
|
||||
integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
|
||||
@@ -5216,6 +5223,11 @@ busboy@1.6.0:
|
||||
dependencies:
|
||||
streamsearch "^1.1.0"
|
||||
|
||||
bytes@3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
|
||||
integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==
|
||||
|
||||
bytes@3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
|
||||
@@ -5583,6 +5595,26 @@ commondir@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
|
||||
integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==
|
||||
|
||||
compressible@~2.0.16:
|
||||
version "2.0.18"
|
||||
resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
|
||||
integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==
|
||||
dependencies:
|
||||
mime-db ">= 1.43.0 < 2"
|
||||
|
||||
compression@^1.7.4:
|
||||
version "1.7.4"
|
||||
resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f"
|
||||
integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==
|
||||
dependencies:
|
||||
accepts "~1.3.5"
|
||||
bytes "3.0.0"
|
||||
compressible "~2.0.16"
|
||||
debug "2.6.9"
|
||||
on-headers "~1.0.2"
|
||||
safe-buffer "5.1.2"
|
||||
vary "~1.1.2"
|
||||
|
||||
compute-scroll-into-view@^3.0.2:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz#753f11d972596558d8fe7c6bcbc8497690ab4c87"
|
||||
@@ -7594,6 +7626,11 @@ header-case@^2.0.4:
|
||||
capital-case "^1.0.4"
|
||||
tslib "^2.0.3"
|
||||
|
||||
helmet@^7.1.0:
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/helmet/-/helmet-7.1.0.tgz#287279e00f8a3763d5dccbaf1e5ee39b8c3784ca"
|
||||
integrity sha512-g+HZqgfbpXdCkme/Cd/mZkV0aV3BZZZSugecH03kl38m/Kmdx8jKjBikpDj2cr+Iynv4KpYEviojNdTJActJAg==
|
||||
|
||||
help-me@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/help-me/-/help-me-5.0.0.tgz#b1ebe63b967b74060027c2ac61f9be12d354a6f6"
|
||||
@@ -9034,6 +9071,11 @@ mime-db@1.52.0:
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
|
||||
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
|
||||
|
||||
"mime-db@>= 1.43.0 < 2":
|
||||
version "1.53.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.53.0.tgz#3cb63cd820fc29896d9d4e8c32ab4fcd74ccb447"
|
||||
integrity sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==
|
||||
|
||||
mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.24, mime-types@~2.1.34:
|
||||
version "2.1.35"
|
||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
|
||||
@@ -13146,4 +13188,4 @@ zeed-dom@^0.10.9:
|
||||
zxcvbn@^4.4.2:
|
||||
version "4.4.2"
|
||||
resolved "https://registry.yarnpkg.com/zxcvbn/-/zxcvbn-4.4.2.tgz#28ec17cf09743edcab056ddd8b1b06262cc73c30"
|
||||
integrity sha512-Bq0B+ixT/DMyG8kgX2xWcI5jUvCwqrMxSFam7m0lAf78nf04hv6lNCsyLYdyYTrCVMqNDY/206K7eExYCeSyUQ==
|
||||
integrity sha512-Bq0B+ixT/DMyG8kgX2xWcI5jUvCwqrMxSFam7m0lAf78nf04hv6lNCsyLYdyYTrCVMqNDY/206K7eExYCeSyUQ==
|
||||
|
||||
Reference in New Issue
Block a user