[WEB-3268] feat: url pattern (#6546)
* feat: meta endpoint for issue * chore: add detail endpoint * chore: getIssueMetaFromURL and retrieveWithIdentifier endpoint added * chore: issue store updated * chore: move issue detail to new route and add redirection for old route * fix: issue details permission * fix: work item detail header * chore: generateWorkItemLink helper function added * chore: copyTextToClipboard helper function updated * chore: workItemLink updated * chore: workItemLink updated * chore: workItemLink updated * fix: issues navigation tab active status * fix: invalid workitem error state * chore: peek view parent issue redirection improvement * fix: issue detail endpoint to not return epics and intake issue * fix: workitem empty state redirection and header * fix: workitem empty state redirection and header * chore: code refactor * chore: project auth wrapper improvement --------- Co-authored-by: pablohashescobar <nikhilschacko@gmail.com>
This commit is contained in:
parent
82eea3e802
commit
4353cc0c4a
51 changed files with 1032 additions and 282 deletions
|
|
@ -32,6 +32,7 @@ export interface IIssueStoreActions {
|
|||
removeModuleIds: string[]
|
||||
) => Promise<void>;
|
||||
removeIssueFromModule: (workspaceSlug: string, projectId: string, moduleId: string, issueId: string) => Promise<void>;
|
||||
fetchIssueWithIdentifier: (workspaceSlug: string, project_identifier: string, sequence_id: string) => Promise<TIssue>;
|
||||
}
|
||||
|
||||
export interface IIssueStore extends IIssueStoreActions {
|
||||
|
|
@ -39,6 +40,7 @@ export interface IIssueStore extends IIssueStoreActions {
|
|||
getIsLocalDBIssueDescription: (issueId: string | undefined) => boolean;
|
||||
// helper methods
|
||||
getIssueById: (issueId: string) => TIssue | undefined;
|
||||
getIssueIdByIdentifier: (issueIdentifier: string) => string | undefined;
|
||||
}
|
||||
|
||||
export class IssueStore implements IIssueStore {
|
||||
|
|
@ -86,6 +88,11 @@ export class IssueStore implements IIssueStore {
|
|||
return this.rootIssueDetailStore.rootIssueStore.issues.getIssueById(issueId) ?? undefined;
|
||||
});
|
||||
|
||||
getIssueIdByIdentifier = computedFn((issueIdentifier: string) => {
|
||||
if (!issueIdentifier) return undefined;
|
||||
return this.rootIssueDetailStore.rootIssueStore.issues.getIssueIdByIdentifier(issueIdentifier) ?? undefined;
|
||||
});
|
||||
|
||||
// actions
|
||||
fetchIssue = async (workspaceSlug: string, projectId: string, issueId: string, issueStatus = "DEFAULT") => {
|
||||
const query = {
|
||||
|
|
@ -285,4 +292,65 @@ export class IssueStore implements IIssueStore {
|
|||
await this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
|
||||
return currentModule;
|
||||
};
|
||||
|
||||
fetchIssueWithIdentifier = async (workspaceSlug: string, project_identifier: string, sequence_id: string) => {
|
||||
const query = {
|
||||
expand: "issue_reactions,issue_attachments,issue_link,parent",
|
||||
};
|
||||
const issue = await this.issueService.retrieveWithIdentifier(workspaceSlug, project_identifier, sequence_id, query);
|
||||
const issueIdentifier = `${project_identifier}-${sequence_id}`;
|
||||
const issueId = issue?.id;
|
||||
const projectId = issue?.project_id;
|
||||
|
||||
if (!issue || !projectId || !issueId) throw new Error("Issue not found");
|
||||
|
||||
const issuePayload = this.addIssueToStore(issue);
|
||||
this.rootIssueDetailStore.rootIssueStore.issues.addIssue([issuePayload]);
|
||||
|
||||
// handle parent issue if exists
|
||||
if (issue?.parent && issue?.parent?.id && issue?.parent?.project_id) {
|
||||
this.issueService.retrieve(workspaceSlug, issue.parent.project_id, issue.parent.id).then((res) => {
|
||||
this.rootIssueDetailStore.rootIssueStore.issues.addIssue([res]);
|
||||
});
|
||||
}
|
||||
|
||||
// add identifiers to map
|
||||
this.rootIssueDetailStore.rootIssueStore.issues.addIssueIdentifier(issueIdentifier, issueId);
|
||||
|
||||
// add related data
|
||||
if (issue.issue_reactions) this.rootIssueDetailStore.addReactions(issue.id, issue.issue_reactions);
|
||||
if (issue.issue_link) this.rootIssueDetailStore.addLinks(issue.id, issue.issue_link);
|
||||
if (issue.issue_attachments) this.rootIssueDetailStore.addAttachments(issue.id, issue.issue_attachments);
|
||||
this.rootIssueDetailStore.addSubscription(issue.id, issue.is_subscribed);
|
||||
|
||||
// fetch related data
|
||||
// issue reactions
|
||||
if (issue.issue_reactions) this.rootIssueDetailStore.addReactions(issueId, issue.issue_reactions);
|
||||
|
||||
// fetch issue links
|
||||
if (issue.issue_link) this.rootIssueDetailStore.addLinks(issueId, issue.issue_link);
|
||||
|
||||
// fetch issue attachments
|
||||
if (issue.issue_attachments) this.rootIssueDetailStore.addAttachments(issueId, issue.issue_attachments);
|
||||
|
||||
this.rootIssueDetailStore.addSubscription(issueId, issue.is_subscribed);
|
||||
|
||||
// fetch issue activity
|
||||
this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
|
||||
|
||||
// fetch issue comments
|
||||
this.rootIssueDetailStore.comment.fetchComments(workspaceSlug, projectId, issueId);
|
||||
|
||||
// fetch sub issues
|
||||
this.rootIssueDetailStore.subIssues.fetchSubIssues(workspaceSlug, projectId, issueId);
|
||||
|
||||
// fetch issue relations
|
||||
this.rootIssueDetailStore.relation.fetchRelations(workspaceSlug, projectId, issueId);
|
||||
|
||||
// fetching states
|
||||
// TODO: check if this function is required
|
||||
this.rootIssueDetailStore.rootIssueStore.rootStore.state.fetchProjectStates(workspaceSlug, projectId);
|
||||
|
||||
return issue;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -259,6 +259,8 @@ export class IssueDetail implements IIssueDetail {
|
|||
issueId: string,
|
||||
issueStatus: "DEFAULT" | "DRAFT" = "DEFAULT"
|
||||
) => this.issue.fetchIssue(workspaceSlug, projectId, issueId, issueStatus);
|
||||
fetchIssueWithIdentifier = async (workspaceSlug: string, projectIdentifier: string, sequenceId: string) =>
|
||||
this.issue.fetchIssueWithIdentifier(workspaceSlug, projectIdentifier, sequenceId);
|
||||
updateIssue = async (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssue>) =>
|
||||
this.issue.updateIssue(workspaceSlug, projectId, issueId, data);
|
||||
removeIssue = async (workspaceSlug: string, projectId: string, issueId: string) =>
|
||||
|
|
|
|||
|
|
@ -15,19 +15,23 @@ import { IssueService } from "@/services/issue";
|
|||
export type IIssueStore = {
|
||||
// observables
|
||||
issuesMap: Record<string, TIssue>; // Record defines issue_id as key and TIssue as value
|
||||
issuesIdentifierMap: Record<string, string>; // Record defines issue_identifier as key and issue_id as value
|
||||
// actions
|
||||
getIssues(workspaceSlug: string, projectId: string, issueIds: string[]): Promise<TIssue[]>;
|
||||
addIssue(issues: TIssue[]): void;
|
||||
addIssueIdentifier(issueIdentifier: string, issueId: string): void;
|
||||
updateIssue(issueId: string, issue: Partial<TIssue>): void;
|
||||
removeIssue(issueId: string): void;
|
||||
// helper methods
|
||||
getIssueById(issueId: string): undefined | TIssue;
|
||||
getIssueIdByIdentifier(issueIdentifier: string): undefined | string;
|
||||
getIssuesByIds(issueIds: string[], type: "archived" | "un-archived"): TIssue[]; // Record defines issue_id as key and TIssue as value
|
||||
};
|
||||
|
||||
export class IssueStore implements IIssueStore {
|
||||
// observables
|
||||
issuesMap: { [issue_id: string]: TIssue } = {};
|
||||
issuesIdentifierMap: { [issue_identifier: string]: string } = {};
|
||||
// service
|
||||
issueService;
|
||||
|
||||
|
|
@ -35,8 +39,10 @@ export class IssueStore implements IIssueStore {
|
|||
makeObservable(this, {
|
||||
// observable
|
||||
issuesMap: observable,
|
||||
issuesIdentifierMap: observable,
|
||||
// actions
|
||||
addIssue: action,
|
||||
addIssueIdentifier: action,
|
||||
updateIssue: action,
|
||||
removeIssue: action,
|
||||
});
|
||||
|
|
@ -59,6 +65,19 @@ export class IssueStore implements IIssueStore {
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @description This method will add issue_identifier to the issuesIdentifierMap
|
||||
* @param issueIdentifier
|
||||
* @param issueId
|
||||
* @returns {void}
|
||||
*/
|
||||
addIssueIdentifier = (issueIdentifier: string, issueId: string) => {
|
||||
if (!issueIdentifier || !issueId) return;
|
||||
runInAction(() => {
|
||||
set(this.issuesIdentifierMap, issueIdentifier, issueId);
|
||||
});
|
||||
};
|
||||
|
||||
getIssues = async (workspaceSlug: string, projectId: string, issueIds: string[]) => {
|
||||
const issues = await this.issueService.retrieveIssues(workspaceSlug, projectId, issueIds);
|
||||
|
||||
|
|
@ -116,6 +135,16 @@ export class IssueStore implements IIssueStore {
|
|||
return this.issuesMap[issueId];
|
||||
});
|
||||
|
||||
/**
|
||||
* @description This method will return the issue_id from the issuesIdentifierMap
|
||||
* @param {string} issueIdentifier
|
||||
* @returns {string | undefined}
|
||||
*/
|
||||
getIssueIdByIdentifier = computedFn((issueIdentifier: string) => {
|
||||
if (!issueIdentifier || !this.issuesIdentifierMap[issueIdentifier]) return undefined;
|
||||
return this.issuesIdentifierMap[issueIdentifier];
|
||||
});
|
||||
|
||||
/**
|
||||
* @description This method will return the issues from the issuesMap
|
||||
* @param {string[]} issueIds
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue