From 4630d4a2215eacc3e32daba4b19fc231348852e8 Mon Sep 17 00:00:00 2001 From: Richard Tan Date: Tue, 21 Jan 2025 18:18:11 +0800 Subject: [PATCH 1/6] New set of crm task filter --- packages/experiments-realm/crm-app.gts | 10 ++++++- packages/experiments-realm/crm/task.gts | 38 +++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/packages/experiments-realm/crm-app.gts b/packages/experiments-realm/crm-app.gts index de0508f52f..e0ab9685b1 100644 --- a/packages/experiments-realm/crm-app.gts +++ b/packages/experiments-realm/crm-app.gts @@ -35,8 +35,10 @@ import HeartHandshakeIcon from '@cardstack/boxel-icons/heart-handshake'; import TargetArrowIcon from '@cardstack/boxel-icons/target-arrow'; import CalendarExclamation from '@cardstack/boxel-icons/calendar-exclamation'; import PresentationAnalytics from '@cardstack/boxel-icons/presentation-analytics'; +import ListDetails from '@cardstack/boxel-icons/list-details'; import { urgencyTagValues } from './crm/account'; import { dealStatusValues } from './crm/deal'; +import { taskStatusValues } from './crm/task'; import type { Deal } from './crm/deal'; import DealSummary from './crm/deal-summary'; import { CRMTaskPlannerIsolated } from './crm/task-planner'; @@ -108,10 +110,16 @@ const ACCOUNT_FILTERS: LayoutFilter[] = [ const TASK_FILTERS: LayoutFilter[] = [ { displayName: 'All Tasks', - icon: CalendarExclamation, + icon: ListDetails, cardTypeName: 'CRM Task', createNewButtonText: 'Create Task', }, + ...taskStatusValues.map((status) => ({ + displayName: status.label, + icon: status.icon, + cardTypeName: 'CRM Task', + createNewButtonText: 'Create Task', + })), ]; // need to use as typeof AppCard rather than CrmApp otherwise tons of lint errors diff --git a/packages/experiments-realm/crm/task.gts b/packages/experiments-realm/crm/task.gts index be0d77f374..c0ecd0f25d 100644 --- a/packages/experiments-realm/crm/task.gts +++ b/packages/experiments-realm/crm/task.gts @@ -14,6 +14,11 @@ import { } from '@cardstack/boxel-ui/components'; import CheckboxIcon from '@cardstack/boxel-icons/checkbox'; import Calendar from '@cardstack/boxel-icons/calendar'; +import AlertHexagon from '@cardstack/boxel-icons/alert-hexagon'; +import CalendarStar from '@cardstack/boxel-icons/calendar-star'; +import CalendarMonth from '@cardstack/boxel-icons/calendar-month'; +import ChevronsUp from '@cardstack/boxel-icons/chevrons-up'; +import UserQuestion from '@cardstack/boxel-icons/user-question'; import { Contact } from './contact'; import { Representative } from './representative'; import { Account } from './account'; @@ -356,6 +361,39 @@ class TaskIsolated extends Component { } } +export const taskStatusValues = [ + { + index: 0, + icon: AlertHexagon, + label: 'Overdue', + value: 'overdue', + }, + { + index: 1, + icon: CalendarStar, + label: 'Due Today', + value: 'due-today', + }, + { + index: 2, + icon: CalendarMonth, + label: 'Due this week', + value: 'due-this-week', + }, + { + index: 3, + icon: ChevronsUp, + label: 'High Priority', + value: 'high-priority', + }, + { + index: 4, + icon: UserQuestion, + label: 'Unassigned', + value: 'unassigned', + }, +]; + export class CRMTaskStatusField extends TaskStatusField { static values = [ { index: 0, label: 'Not Started', color: '#B0BEC5', completed: false }, From 673d2723f6ec226b2ab6f864304367585a0dd18e Mon Sep 17 00:00:00 2001 From: Richard Tan Date: Wed, 22 Jan 2025 00:28:33 +0800 Subject: [PATCH 2/6] Fix circular dependency between crm app and task --- packages/experiments-realm/crm-app.gts | 2 +- packages/experiments-realm/crm/shared.gts | 38 +++++++++++++++++++++++ packages/experiments-realm/crm/task.gts | 38 ----------------------- 3 files changed, 39 insertions(+), 39 deletions(-) create mode 100644 packages/experiments-realm/crm/shared.gts diff --git a/packages/experiments-realm/crm-app.gts b/packages/experiments-realm/crm-app.gts index e0ab9685b1..27d422c28d 100644 --- a/packages/experiments-realm/crm-app.gts +++ b/packages/experiments-realm/crm-app.gts @@ -38,7 +38,7 @@ import PresentationAnalytics from '@cardstack/boxel-icons/presentation-analytics import ListDetails from '@cardstack/boxel-icons/list-details'; import { urgencyTagValues } from './crm/account'; import { dealStatusValues } from './crm/deal'; -import { taskStatusValues } from './crm/task'; +import { taskStatusValues } from './crm/shared'; import type { Deal } from './crm/deal'; import DealSummary from './crm/deal-summary'; import { CRMTaskPlannerIsolated } from './crm/task-planner'; diff --git a/packages/experiments-realm/crm/shared.gts b/packages/experiments-realm/crm/shared.gts new file mode 100644 index 0000000000..4c5bc25e09 --- /dev/null +++ b/packages/experiments-realm/crm/shared.gts @@ -0,0 +1,38 @@ +import AlertHexagon from '@cardstack/boxel-icons/alert-hexagon'; +import CalendarStar from '@cardstack/boxel-icons/calendar-star'; +import CalendarMonth from '@cardstack/boxel-icons/calendar-month'; +import ChevronsUp from '@cardstack/boxel-icons/chevrons-up'; +import UserQuestion from '@cardstack/boxel-icons/user-question'; + +export const taskStatusValues = [ + { + index: 0, + icon: AlertHexagon, + label: 'Overdue', + value: 'overdue', + }, + { + index: 1, + icon: CalendarStar, + label: 'Due Today', + value: 'due-today', + }, + { + index: 2, + icon: CalendarMonth, + label: 'Due this week', + value: 'due-this-week', + }, + { + index: 3, + icon: ChevronsUp, + label: 'High Priority', + value: 'high-priority', + }, + { + index: 4, + icon: UserQuestion, + label: 'Unassigned', + value: 'unassigned', + }, +]; diff --git a/packages/experiments-realm/crm/task.gts b/packages/experiments-realm/crm/task.gts index c0ecd0f25d..be0d77f374 100644 --- a/packages/experiments-realm/crm/task.gts +++ b/packages/experiments-realm/crm/task.gts @@ -14,11 +14,6 @@ import { } from '@cardstack/boxel-ui/components'; import CheckboxIcon from '@cardstack/boxel-icons/checkbox'; import Calendar from '@cardstack/boxel-icons/calendar'; -import AlertHexagon from '@cardstack/boxel-icons/alert-hexagon'; -import CalendarStar from '@cardstack/boxel-icons/calendar-star'; -import CalendarMonth from '@cardstack/boxel-icons/calendar-month'; -import ChevronsUp from '@cardstack/boxel-icons/chevrons-up'; -import UserQuestion from '@cardstack/boxel-icons/user-question'; import { Contact } from './contact'; import { Representative } from './representative'; import { Account } from './account'; @@ -361,39 +356,6 @@ class TaskIsolated extends Component { } } -export const taskStatusValues = [ - { - index: 0, - icon: AlertHexagon, - label: 'Overdue', - value: 'overdue', - }, - { - index: 1, - icon: CalendarStar, - label: 'Due Today', - value: 'due-today', - }, - { - index: 2, - icon: CalendarMonth, - label: 'Due this week', - value: 'due-this-week', - }, - { - index: 3, - icon: ChevronsUp, - label: 'High Priority', - value: 'high-priority', - }, - { - index: 4, - icon: UserQuestion, - label: 'Unassigned', - value: 'unassigned', - }, -]; - export class CRMTaskStatusField extends TaskStatusField { static values = [ { index: 0, label: 'Not Started', color: '#B0BEC5', completed: false }, From f0e15908878c221f1061cd76c7a570124fb17883 Mon Sep 17 00:00:00 2001 From: Richard Tan Date: Wed, 22 Jan 2025 02:03:13 +0800 Subject: [PATCH 3/6] Initial approach on LHS filter, task planner is reactive to crm app --- .../27c5519e-4b58-4e1f-a158-27074d46c782.json | 4 +- .../792c50f2-7d62-425f-bcc7-8e27852731e2.json | 68 +++++++++++++++++ packages/experiments-realm/crm-app.gts | 74 +++++++++++++++---- .../experiments-realm/crm/task-planner.gts | 55 ++++++++++++++ 4 files changed, 184 insertions(+), 17 deletions(-) create mode 100644 packages/experiments-realm/CRMTask/792c50f2-7d62-425f-bcc7-8e27852731e2.json diff --git a/packages/experiments-realm/CRMTask/27c5519e-4b58-4e1f-a158-27074d46c782.json b/packages/experiments-realm/CRMTask/27c5519e-4b58-4e1f-a158-27074d46c782.json index 8779cf92c6..4977e9c7e0 100644 --- a/packages/experiments-realm/CRMTask/27c5519e-4b58-4e1f-a158-27074d46c782.json +++ b/packages/experiments-realm/CRMTask/27c5519e-4b58-4e1f-a158-27074d46c782.json @@ -13,8 +13,8 @@ "end": null }, "priority": { - "index": 2, - "label": "Medium" + "index": 3, + "label": "High" }, "name": "Meet Prospect Customer", "details": null, diff --git a/packages/experiments-realm/CRMTask/792c50f2-7d62-425f-bcc7-8e27852731e2.json b/packages/experiments-realm/CRMTask/792c50f2-7d62-425f-bcc7-8e27852731e2.json new file mode 100644 index 0000000000..489903666f --- /dev/null +++ b/packages/experiments-realm/CRMTask/792c50f2-7d62-425f-bcc7-8e27852731e2.json @@ -0,0 +1,68 @@ +{ + "data": { + "type": "card", + "attributes": { + "status": { + "index": 0, + "label": "Not Started", + "color": null, + "completed": false + }, + "dateRange": { + "start": "2025-01-21", + "end": "2025-01-22" + }, + "priority": { + "index": null, + "label": null + }, + "name": "Today", + "details": null, + "description": null, + "thumbnailURL": null + }, + "relationships": { + "crmApp": { + "links": { + "self": "../CrmApp/4e73712d-2a31-4ffe-9c22-d3de277257a6" + } + }, + "subtasks": { + "links": { + "self": null + } + }, + "assignee": { + "links": { + "self": null + } + }, + "contact": { + "links": { + "self": null + } + }, + "account": { + "links": { + "self": null + } + }, + "deal": { + "links": { + "self": null + } + }, + "tags": { + "links": { + "self": null + } + } + }, + "meta": { + "adoptsFrom": { + "module": "../crm/task", + "name": "CRMTask" + } + } + } +} \ No newline at end of file diff --git a/packages/experiments-realm/crm-app.gts b/packages/experiments-realm/crm-app.gts index 27d422c28d..a7dc9f3c34 100644 --- a/packages/experiments-realm/crm-app.gts +++ b/packages/experiments-realm/crm-app.gts @@ -13,6 +13,9 @@ import type Owner from '@ember/owner'; import { tracked } from '@glimmer/tracking'; import { TrackedMap } from 'tracked-built-ins'; import { restartableTask } from 'ember-concurrency'; +import { format, startOfWeek } from 'date-fns'; + +const dateFormat = `yyyy-MM-dd`; import { Component, realmURL } from 'https://cardstack.com/base/card-api'; @@ -273,7 +276,7 @@ class CrmAppTemplate extends Component { //query for tabs and filters get query() { - const { loadAllFilters, activeFilter, activeTabId, searchKey } = this; + const { loadAllFilters, activeFilter, activeTabId } = this; if (!loadAllFilters.isIdle || !activeFilter?.query) return; @@ -307,19 +310,6 @@ class CrmAppTemplate extends Component { ] : []; - const searchFilter = searchKey - ? [ - { - any: [ - { - on: activeFilter.cardRef, - contains: { name: searchKey }, - }, - ], - }, - ] - : []; - return { filter: { on: activeFilter.cardRef, @@ -327,13 +317,65 @@ class CrmAppTemplate extends Component { defaultFilter, ...accountFilter, ...dealFilter, - ...searchFilter, + ...this.searchFilter, + ...this.taskFilter, ], }, sort: this.selectedSort?.sort ?? sortByCardTitleAsc, } as Query; } + get searchFilter() { + return this.searchKey + ? [ + { + any: [ + { + on: this.activeFilter.cardRef, + contains: { name: this.searchKey }, + }, + ], + }, + ] + : []; + } + + get taskFilter() { + let taskFilter: Query['filter'][] = []; + if ( + this.activeTabId === 'Task' && + this.activeFilter.displayName !== 'All Tasks' + ) { + const today = new Date(); + switch (this.activeFilter.displayName) { + case 'Overdue': + const formattedDate = format(today, dateFormat); + taskFilter = [{ range: { 'dateRange.end': { lt: formattedDate } } }]; + break; + case 'Due Today': + const formattedDueToday = format(today, dateFormat); + taskFilter = [{ eq: { 'dateRange.end': formattedDueToday } }]; + break; + case 'Due this week': + const dueThisWeek = startOfWeek(today, { weekStartsOn: 1 }); + const formattedDueThisWeek = format(dueThisWeek, dateFormat); + taskFilter = [ + { range: { 'dateRange.start': { gt: formattedDueThisWeek } } }, + ]; + break; + case 'High Priority': + taskFilter = [{ eq: { 'priority.label': 'High' } }]; + break; + case 'Unassigned': + taskFilter = [{ eq: { 'assignee.id': null } }]; + break; + default: + break; + } + } + return taskFilter; + } + get searchPlaceholder() { return `Search ${this.activeFilter.displayName}`; } @@ -447,6 +489,8 @@ class CrmAppTemplate extends Component { @fields={{@fields}} @set={{@set}} @fieldName={{@fieldName}} + @searchFilter={{this.searchFilter}} + @taskFilter={{this.taskFilter}} /> {{else if this.query}} {{#if (eq this.selectedView 'card')}} diff --git a/packages/experiments-realm/crm/task-planner.gts b/packages/experiments-realm/crm/task-planner.gts index 47348e2a88..85ab920309 100644 --- a/packages/experiments-realm/crm/task-planner.gts +++ b/packages/experiments-realm/crm/task-planner.gts @@ -10,10 +10,16 @@ import { import type { LooseSingleCardDocument } from '@cardstack/runtime-common'; import type { Query } from '@cardstack/runtime-common/query'; import { getCards } from '@cardstack/runtime-common'; +import { tracked } from '@glimmer/tracking'; +import { restartableTask } from 'ember-concurrency'; export class CRMTaskPlannerIsolated extends BaseTaskPlannerIsolated< typeof CRMTaskPlanner > { + @tracked cardsQuery: { instances: CardDef[]; isLoading?: boolean }; + private lastTaskFilter: any; + private lastSearchFilter: any; + constructor(owner: Owner, args: any) { const config: TaskPlannerConfig = { status: { @@ -119,8 +125,38 @@ export class CRMTaskPlannerIsolated extends BaseTaskPlannerIsolated< }, }; super(owner, args, config); + + // Initialize query once + this.cardsQuery = getCards(this.getTaskQuery, this.realmHrefs, { + isLive: true, + }); + + // Store initial filter states + this.lastTaskFilter = this.args.taskFilter; + this.lastSearchFilter = this.args.searchFilter; + } + + get cardInstances() { + // Check if filters have changed + if ( + this.lastTaskFilter !== this.args.taskFilter || + this.lastSearchFilter !== this.args.searchFilter + ) { + this.lastTaskFilter = this.args.taskFilter; + this.lastSearchFilter = this.args.searchFilter; + // Only reload when filters actually change + this.loadCards.perform(); + } + return this.cardsQuery?.instances ?? []; } + private loadCards = restartableTask(async () => { + this.cardsQuery = getCards(this.getTaskQuery, this.realmHrefs, { + isLive: true, + }); + return this.cardsQuery; + }); + get parentId() { return this.args.model?.id; } @@ -129,6 +165,14 @@ export class CRMTaskPlannerIsolated extends BaseTaskPlannerIsolated< return 'Link a CRM App to continue'; } + get reactiveTaskFilter() { + return this.args.taskFilter || []; + } + + get reactiveSearchFilter() { + return this.args.searchFilter || []; + } + override get getTaskQuery(): Query { let everyArr = []; if (!this.realmURL) { @@ -142,6 +186,17 @@ export class CRMTaskPlannerIsolated extends BaseTaskPlannerIsolated< everyArr.push({ eq: { 'crmApp.id': this.parentId } }); } + const taskFilter = this.args.taskFilter || []; + const searchFilter = this.args.searchFilter || []; + + if (taskFilter.length > 0) { + everyArr.push(...taskFilter); + } + + if (searchFilter.length > 0) { + everyArr.push(...searchFilter); + } + return everyArr.length > 0 ? { filter: { From 9d869da2bcef517f32bd77831d84ab5ecb1bde93 Mon Sep 17 00:00:00 2001 From: Richard Tan Date: Thu, 23 Jan 2025 22:33:45 +0800 Subject: [PATCH 4/6] Better way to trigger parent to reload cards --- packages/experiments-realm/crm-app.gts | 17 ++++++++++ .../experiments-realm/crm/task-planner.gts | 33 +++---------------- 2 files changed, 22 insertions(+), 28 deletions(-) diff --git a/packages/experiments-realm/crm-app.gts b/packages/experiments-realm/crm-app.gts index a7dc9f3c34..219bf38a86 100644 --- a/packages/experiments-realm/crm-app.gts +++ b/packages/experiments-realm/crm-app.gts @@ -14,6 +14,7 @@ import { tracked } from '@glimmer/tracking'; import { TrackedMap } from 'tracked-built-ins'; import { restartableTask } from 'ember-concurrency'; import { format, startOfWeek } from 'date-fns'; +import { debounce } from 'lodash'; const dateFormat = `yyyy-MM-dd`; @@ -134,10 +135,14 @@ class CrmAppTemplate extends Component { ['Account', ACCOUNT_FILTERS], ['Task', TASK_FILTERS], ]); + private taskPlannerAPI: CRMTaskPlannerIsolated; @tracked private activeFilter: LayoutFilter = CONTACT_FILTERS[0]; @action private onFilterChange(filter: LayoutFilter) { this.activeFilter = filter; this.loadDealCards.perform(); + if (this.activeTabId === 'Task') { + this.taskPlannerAPI.loadCards.perform(); + } } //tabs @tracked activeTabId: string | undefined = this.args.model.tabs?.[0]?.tabId; @@ -204,6 +209,16 @@ class CrmAppTemplate extends Component { return result; }); + private setupTaskPlanner = (taskPlanner: CRMTaskPlannerIsolated) => { + this.taskPlannerAPI = taskPlanner; + }; + + private debouncedLoadTaskCards = debounce(() => { + if (this.activeTabId === 'Task') { + this.taskPlannerAPI.loadCards.perform(); + } + }, 300); + get filters() { return this.filterMap.get(this.activeTabId!)!; } @@ -383,6 +398,7 @@ class CrmAppTemplate extends Component { @action private setSearchKey(searchKey: string) { this.searchKey = searchKey; + this.debouncedLoadTaskCards(); } @action private onChangeView(id: ViewOption) { @@ -491,6 +507,7 @@ class CrmAppTemplate extends Component { @fieldName={{@fieldName}} @searchFilter={{this.searchFilter}} @taskFilter={{this.taskFilter}} + @setupTaskPlanner={{this.setupTaskPlanner}} /> {{else if this.query}} {{#if (eq this.selectedView 'card')}} diff --git a/packages/experiments-realm/crm/task-planner.gts b/packages/experiments-realm/crm/task-planner.gts index 85ab920309..27fa4722c7 100644 --- a/packages/experiments-realm/crm/task-planner.gts +++ b/packages/experiments-realm/crm/task-planner.gts @@ -17,8 +17,6 @@ export class CRMTaskPlannerIsolated extends BaseTaskPlannerIsolated< typeof CRMTaskPlanner > { @tracked cardsQuery: { instances: CardDef[]; isLoading?: boolean }; - private lastTaskFilter: any; - private lastSearchFilter: any; constructor(owner: Owner, args: any) { const config: TaskPlannerConfig = { @@ -126,28 +124,11 @@ export class CRMTaskPlannerIsolated extends BaseTaskPlannerIsolated< }; super(owner, args, config); + this.args.setupTaskPlanner(this); // Initialize query once this.cardsQuery = getCards(this.getTaskQuery, this.realmHrefs, { isLive: true, }); - - // Store initial filter states - this.lastTaskFilter = this.args.taskFilter; - this.lastSearchFilter = this.args.searchFilter; - } - - get cardInstances() { - // Check if filters have changed - if ( - this.lastTaskFilter !== this.args.taskFilter || - this.lastSearchFilter !== this.args.searchFilter - ) { - this.lastTaskFilter = this.args.taskFilter; - this.lastSearchFilter = this.args.searchFilter; - // Only reload when filters actually change - this.loadCards.perform(); - } - return this.cardsQuery?.instances ?? []; } private loadCards = restartableTask(async () => { @@ -165,14 +146,6 @@ export class CRMTaskPlannerIsolated extends BaseTaskPlannerIsolated< return 'Link a CRM App to continue'; } - get reactiveTaskFilter() { - return this.args.taskFilter || []; - } - - get reactiveSearchFilter() { - return this.args.searchFilter || []; - } - override get getTaskQuery(): Query { let everyArr = []; if (!this.realmURL) { @@ -217,6 +190,10 @@ export class CRMTaskPlannerIsolated extends BaseTaskPlannerIsolated< }; } + get cardInstances() { + return this.cardsQuery?.instances ?? []; + } + assigneeQuery = getCards( { filter: { From e24c04eb1212c02deff4d885f6352e8578536f1c Mon Sep 17 00:00:00 2001 From: Richard Tan Date: Fri, 24 Jan 2025 16:33:05 +0800 Subject: [PATCH 5/6] Fix lint --- packages/experiments-realm/crm-app.gts | 13 +++++----- .../experiments-realm/crm/task-planner.gts | 25 +++++++++++++------ 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/packages/experiments-realm/crm-app.gts b/packages/experiments-realm/crm-app.gts index 219bf38a86..949c30daab 100644 --- a/packages/experiments-realm/crm-app.gts +++ b/packages/experiments-realm/crm-app.gts @@ -32,6 +32,7 @@ import { Query, CardError, SupportedMimeType, + Filter, getCards, } from '@cardstack/runtime-common'; import ContactIcon from '@cardstack/boxel-icons/contact'; @@ -135,13 +136,13 @@ class CrmAppTemplate extends Component { ['Account', ACCOUNT_FILTERS], ['Task', TASK_FILTERS], ]); - private taskPlannerAPI: CRMTaskPlannerIsolated; + private taskPlannerAPI: CRMTaskPlannerIsolated | undefined; @tracked private activeFilter: LayoutFilter = CONTACT_FILTERS[0]; @action private onFilterChange(filter: LayoutFilter) { this.activeFilter = filter; this.loadDealCards.perform(); if (this.activeTabId === 'Task') { - this.taskPlannerAPI.loadCards.perform(); + this.taskPlannerAPI?.loadCards.perform(); } } //tabs @@ -215,7 +216,7 @@ class CrmAppTemplate extends Component { private debouncedLoadTaskCards = debounce(() => { if (this.activeTabId === 'Task') { - this.taskPlannerAPI.loadCards.perform(); + this.taskPlannerAPI?.loadCards.perform(); } }, 300); @@ -340,7 +341,7 @@ class CrmAppTemplate extends Component { } as Query; } - get searchFilter() { + get searchFilter(): Filter[] { return this.searchKey ? [ { @@ -355,8 +356,8 @@ class CrmAppTemplate extends Component { : []; } - get taskFilter() { - let taskFilter: Query['filter'][] = []; + get taskFilter(): Filter[] { + let taskFilter: Filter[] = []; if ( this.activeTabId === 'Task' && this.activeFilter.displayName !== 'All Tasks' diff --git a/packages/experiments-realm/crm/task-planner.gts b/packages/experiments-realm/crm/task-planner.gts index 27fa4722c7..aa4b782103 100644 --- a/packages/experiments-realm/crm/task-planner.gts +++ b/packages/experiments-realm/crm/task-planner.gts @@ -1,4 +1,4 @@ -import { CardDef } from 'https://cardstack.com/base/card-api'; +import { CardDef, SignatureFor } from 'https://cardstack.com/base/card-api'; import type Owner from '@ember/owner'; import { CRMTaskStatusField } from './task'; import LayoutKanbanIcon from '@cardstack/boxel-icons/layout-kanban'; @@ -8,17 +8,26 @@ import { TaskCard, } from '../components/base-task-planner'; import type { LooseSingleCardDocument } from '@cardstack/runtime-common'; -import type { Query } from '@cardstack/runtime-common/query'; +import type { Query, Filter } from '@cardstack/runtime-common/query'; import { getCards } from '@cardstack/runtime-common'; import { tracked } from '@glimmer/tracking'; import { restartableTask } from 'ember-concurrency'; +interface CRMTaskPlannerSignature extends SignatureFor { + Args: SignatureFor['Args'] & { + setupTaskPlanner?: (planner: CRMTaskPlannerIsolated) => void; + taskFilter?: Filter[]; + searchFilter?: Filter[]; + }; +} + export class CRMTaskPlannerIsolated extends BaseTaskPlannerIsolated< typeof CRMTaskPlanner > { @tracked cardsQuery: { instances: CardDef[]; isLoading?: boolean }; + declare args: CRMTaskPlannerSignature['Args']; - constructor(owner: Owner, args: any) { + constructor(owner: Owner, args: CRMTaskPlannerSignature['Args']) { const config: TaskPlannerConfig = { status: { values: CRMTaskStatusField.values, @@ -124,14 +133,14 @@ export class CRMTaskPlannerIsolated extends BaseTaskPlannerIsolated< }; super(owner, args, config); - this.args.setupTaskPlanner(this); + this.args.setupTaskPlanner?.(this); // Initialize query once this.cardsQuery = getCards(this.getTaskQuery, this.realmHrefs, { isLive: true, }); } - private loadCards = restartableTask(async () => { + loadCards = restartableTask(async () => { this.cardsQuery = getCards(this.getTaskQuery, this.realmHrefs, { isLive: true, }); @@ -147,7 +156,7 @@ export class CRMTaskPlannerIsolated extends BaseTaskPlannerIsolated< } override get getTaskQuery(): Query { - let everyArr = []; + let everyArr: Filter[] = []; if (!this.realmURL) { throw new Error('No realm url'); } @@ -159,8 +168,8 @@ export class CRMTaskPlannerIsolated extends BaseTaskPlannerIsolated< everyArr.push({ eq: { 'crmApp.id': this.parentId } }); } - const taskFilter = this.args.taskFilter || []; - const searchFilter = this.args.searchFilter || []; + const taskFilter = this.args?.taskFilter || []; + const searchFilter = this.args?.searchFilter || []; if (taskFilter.length > 0) { everyArr.push(...taskFilter); From 3ce4c9c4c75db1a88c73ab0c1e56d0b67fd7af80 Mon Sep 17 00:00:00 2001 From: Richard Tan Date: Fri, 24 Jan 2025 16:53:33 +0800 Subject: [PATCH 6/6] Fix lint --- packages/experiments-realm/crm-app.gts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/experiments-realm/crm-app.gts b/packages/experiments-realm/crm-app.gts index 949c30daab..63bc8b7bff 100644 --- a/packages/experiments-realm/crm-app.gts +++ b/packages/experiments-realm/crm-app.gts @@ -506,6 +506,7 @@ class CrmAppTemplate extends Component { @fields={{@fields}} @set={{@set}} @fieldName={{@fieldName}} + {{! @glint-ignore Arguments are extended in CRMTaskPlannerIsolated but still not recognized }} @searchFilter={{this.searchFilter}} @taskFilter={{this.taskFilter}} @setupTaskPlanner={{this.setupTaskPlanner}}