-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy path.eslintcache
1 lines (1 loc) · 59.8 KB
/
.eslintcache
1
[{"/Users/alex/Code/progress/rpstrackerreact_kendo/src/index.tsx":"1","/Users/alex/Code/progress/rpstrackerreact_kendo/src/serviceWorker.ts":"2","/Users/alex/Code/progress/rpstrackerreact_kendo/src/App.tsx":"3","/Users/alex/Code/progress/rpstrackerreact_kendo/src/shared/components/side-menu/side-menu.tsx":"4","/Users/alex/Code/progress/rpstrackerreact_kendo/src/shared/components/main-menu/main-menu.tsx":"5","/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/backlog/pages/backlog/backlog-page.tsx":"6","/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/backlog/pages/detail/detail-page.tsx":"7","/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/dashboard/pages/dashboard/dashboard-page.tsx":"8","/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/backlog/repositories/backlog.repository.ts":"9","/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/backlog/services/backlog.service.ts":"10","/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/dashboard/repositories/dashboard.repository.ts":"11","/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/dashboard/services/dashboard.service.ts":"12","/Users/alex/Code/progress/rpstrackerreact_kendo/src/shared/helpers/priority-styling.ts":"13","/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/helpers/date-utils.ts":"14","/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/state/app-store.ts":"15","/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/services/pt-user-service.ts":"16","/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/dashboard/pages/dashboard/dashboard-chart.tsx":"17","/Users/alex/Code/progress/rpstrackerreact_kendo/src/shared/components/preset-filter/preset-filter.tsx":"18","/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/backlog/components/item-tasks/pt-item-tasks.tsx":"19","/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/backlog/components/item-details/pt-item-details.tsx":"20","/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/backlog/components/item-chitchat/pt-item-chitchat.tsx":"21","/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/dashboard/components/active-issues/active-issues.tsx":"22","/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/helpers/index.ts":"23","/Users/alex/Code/progress/rpstrackerreact_kendo/src/config.ts":"24","/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/helpers/user-avatar-helper.ts":"25","/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/constants/index.ts":"26","/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/state/app-state.ts":"27","/Users/alex/Code/progress/rpstrackerreact_kendo/src/shared/models/forms/pt-item-details-edit-form.ts":"28","/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/helpers/string-helpers.ts":"29","/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/constants/pt-item-statuses.ts":"30","/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/constants/pt-item-types.ts":"31","/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/constants/pt-item-priorities.ts":"32","/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/models/domain/enums/index.ts":"33","/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/models/domain/enums/item-type-enum.ts":"34","/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/models/domain/enums/item-status.enum.ts":"35","/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/models/domain/enums/item-priority.enum.ts":"36"},{"size":494,"mtime":1612368760347,"results":"37","hashOfConfig":"38"},{"size":5198,"mtime":1612368760352,"results":"39","hashOfConfig":"38"},{"size":1869,"mtime":1612368760342,"results":"40","hashOfConfig":"38"},{"size":9503,"mtime":1612368760353,"results":"41","hashOfConfig":"38"},{"size":774,"mtime":1612368760352,"results":"42","hashOfConfig":"38"},{"size":11255,"mtime":1612493315422,"results":"43","hashOfConfig":"38"},{"size":6921,"mtime":1612368760349,"results":"44","hashOfConfig":"38"},{"size":6773,"mtime":1612368760351,"results":"45","hashOfConfig":"38"},{"size":4850,"mtime":1612368760349,"results":"46","hashOfConfig":"38"},{"size":7291,"mtime":1612368760349,"results":"47","hashOfConfig":"38"},{"size":2308,"mtime":1612368760351,"results":"48","hashOfConfig":"38"},{"size":826,"mtime":1612368760352,"results":"49","hashOfConfig":"38"},{"size":486,"mtime":1612368760353,"results":"50","hashOfConfig":"38"},{"size":784,"mtime":1612368760342,"results":"51","hashOfConfig":"38"},{"size":635,"mtime":1612368760346,"results":"52","hashOfConfig":"38"},{"size":771,"mtime":1612368760346,"results":"53","hashOfConfig":"38"},{"size":2654,"mtime":1612368760351,"results":"54","hashOfConfig":"38"},{"size":991,"mtime":1612368760353,"results":"55","hashOfConfig":"38"},{"size":4743,"mtime":1612368760348,"results":"56","hashOfConfig":"38"},{"size":9339,"mtime":1612368760347,"results":"57","hashOfConfig":"38"},{"size":3339,"mtime":1612368760347,"results":"58","hashOfConfig":"38"},{"size":2132,"mtime":1612368760350,"results":"59","hashOfConfig":"38"},{"size":112,"mtime":1612368760343,"results":"60","hashOfConfig":"38"},{"size":74,"mtime":1612368760342,"results":"61","hashOfConfig":"38"},{"size":119,"mtime":1612368760343,"results":"62","hashOfConfig":"38"},{"size":107,"mtime":1612368760342,"results":"63","hashOfConfig":"38"},{"size":598,"mtime":1612368760346,"results":"64","hashOfConfig":"38"},{"size":678,"mtime":1612368760354,"results":"65","hashOfConfig":"38"},{"size":32,"mtime":1612368760343,"results":"66","hashOfConfig":"38"},{"size":193,"mtime":1612368760342,"results":"67","hashOfConfig":"38"},{"size":2439,"mtime":1612368760342,"results":"68","hashOfConfig":"38"},{"size":199,"mtime":1612368760342,"results":"69","hashOfConfig":"38"},{"size":108,"mtime":1612368760343,"results":"70","hashOfConfig":"38"},{"size":114,"mtime":1612368760344,"results":"71","hashOfConfig":"38"},{"size":125,"mtime":1612368760344,"results":"72","hashOfConfig":"38"},{"size":2143,"mtime":1612368760344,"results":"73","hashOfConfig":"38"},{"filePath":"74","messages":"75","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},"1x93fl7",{"filePath":"77","messages":"78","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"79","messages":"80","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"81","messages":"82","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"83","messages":"84","errorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":"85","usedDeprecatedRules":"76"},{"filePath":"86","messages":"87","errorCount":0,"warningCount":6,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"88","messages":"89","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"90","usedDeprecatedRules":"76"},{"filePath":"91","messages":"92","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"93","usedDeprecatedRules":"76"},{"filePath":"94","messages":"95","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"96","messages":"97","errorCount":0,"warningCount":4,"fixableErrorCount":0,"fixableWarningCount":0,"source":"98","usedDeprecatedRules":"76"},{"filePath":"99","messages":"100","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"101","usedDeprecatedRules":"76"},{"filePath":"102","messages":"103","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"104","messages":"105","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"106","messages":"107","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"108","messages":"109","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"110","messages":"111","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"112","messages":"113","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"114","usedDeprecatedRules":"76"},{"filePath":"115","messages":"116","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"117","usedDeprecatedRules":"76"},{"filePath":"118","messages":"119","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"120","messages":"121","errorCount":0,"warningCount":4,"fixableErrorCount":0,"fixableWarningCount":0,"source":"122","usedDeprecatedRules":"76"},{"filePath":"123","messages":"124","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"125","usedDeprecatedRules":"76"},{"filePath":"126","messages":"127","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"128","messages":"129","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"130","messages":"131","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"132","messages":"133","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"134","messages":"135","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"136","messages":"137","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"138","messages":"139","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"140","messages":"141","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"142","messages":"143","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"144","messages":"145","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"146","messages":"147","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"148","messages":"149","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"150","messages":"151","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"152","messages":"153","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"154","messages":"155","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},"/Users/alex/Code/progress/rpstrackerreact_kendo/src/index.tsx",[],["156","157"],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/serviceWorker.ts",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/App.tsx",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/shared/components/side-menu/side-menu.tsx",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/shared/components/main-menu/main-menu.tsx",["158","159","160"],"import React from \"react\";\nimport { Link } from \"react-router-dom\";\n\n\n\nexport class MainMenu extends React.PureComponent<any, any> {\n\n constructor(props: any) {\n super(props);\n }\n\n public render() {\n return (\n <div className=\"navbar navbar-dark fixed-top bg-dark flex-md-nowrap p-0 shadow\">\n <a className=\"navbar-brand col-sm-3 col-md-2 mr-0\">\n <img src=\"/assets/img/rpslogo.png\" className=\"logo\" />\n </a>\n <nav className=\"my-2 my-md-0 mr-md-3\">\n <Link className=\"p-2 text-light\" to=\"/dashboard\">Dashboard</Link>\n <Link className=\"p-2 text-light\" to=\"/backlog\">Backlog</Link>\n </nav>\n </div>\n );\n }\n};\n","/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/backlog/pages/backlog/backlog-page.tsx",["161","162","163","164","165","166"],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/backlog/pages/detail/detail-page.tsx",["167"],"import React from \"react\";\n\nimport { TabStrip, TabStripTab } from '@progress/kendo-react-layout';\n\nimport { PtItem, PtUser, PtTask, PtComment } from \"../../../../core/models/domain\";\nimport { DetailScreenType } from \"../../../../shared/models/ui/types/detail-screens\";\nimport { Store } from \"../../../../core/state/app-store\";\nimport { BacklogRepository } from \"../../repositories/backlog.repository\";\nimport { BacklogService } from \"../../services/backlog.service\";\nimport { PtItemDetailsComponent } from \"../../components/item-details/pt-item-details\";\nimport { PtItemTasksComponent } from \"../../components/item-tasks/pt-item-tasks\";\nimport { PtUserService } from \"../../../../core/services/pt-user-service\";\nimport { Observable, BehaviorSubject } from \"rxjs\";\nimport { PtNewTask } from \"../../../../shared/models/dto/pt-new-task\";\nimport { PtTaskUpdate } from \"../../../../shared/models/dto/pt-task-update\";\nimport { PtItemChitchatComponent } from \"../../components/item-chitchat/pt-item-chitchat\";\nimport { PtNewComment } from \"../../../../shared/models/dto/pt-new-comment\";\nimport './detail-page.css';\n\ninterface DetailPageState {\n item: PtItem | undefined;\n selectedDetailsScreen: DetailScreenType;\n}\n\nexport class DetailPage extends React.Component<any, DetailPageState> {\n\n private store: Store = new Store();\n private backlogRepo: BacklogRepository = new BacklogRepository();\n private backlogService: BacklogService = new BacklogService(this.backlogRepo, this.store);\n private ptUserService: PtUserService = new PtUserService(this.store);\n\n private itemId = 0;\n private users$: Observable<PtUser[]> = this.store.select<PtUser[]>('users');\n public tasks$: BehaviorSubject<PtTask[]> = new BehaviorSubject<PtTask[]>([]);\n public comments$: BehaviorSubject<PtComment[]> = new BehaviorSubject<PtComment[]>([]);\n public currentUser: PtUser | undefined;\n\n private screenPositionMap: { [key in DetailScreenType | number]: number | DetailScreenType } = {\n 0: 'details',\n 1: 'tasks',\n 2: 'chitchat',\n 'details': 0,\n 'tasks': 1,\n 'chitchat': 2\n };\n\n constructor(props: any) {\n super(props);\n\n const { id, screen } = this.props.match.params;\n this.itemId = id;\n this.currentUser = this.store.value.currentUser;\n\n this.state = {\n item: undefined,\n selectedDetailsScreen: screen ? screen : 'details'\n };\n }\n\n public componentDidMount() {\n this.refresh();\n }\n\n public componentDidUpdate(prevsProps: any, prevState: DetailPageState) {\n\n }\n\n private refresh() {\n this.backlogService.getPtItem(this.itemId)\n .then(item => {\n this.setState({\n item: item\n });\n this.tasks$.next(item.tasks);\n this.comments$.next(item.comments);\n });\n }\n\n public onScreenSelected(screen: DetailScreenType) {\n this.setState({\n selectedDetailsScreen: screen\n });\n this.props.history.push(`/detail/${this.itemId}/${screen}`);\n }\n\n public onTabSelect(e: any) {\n const screen = this.screenPositionMap[(e.selected as number)] as DetailScreenType;\n this.setState({\n selectedDetailsScreen: screen\n });\n this.props.history.push(`/detail/${this.itemId}/${screen}`);\n }\n\n public onItemSaved(item: PtItem) {\n this.backlogService.updatePtItem(item)\n .then((updateItem: PtItem) => {\n this.setState({\n item: updateItem\n });\n });\n }\n\n public onAddNewTask(newTask: PtNewTask) {\n if (this.state.item) {\n this.backlogService.addNewPtTask(newTask, this.state.item).then(nextTask => {\n this.tasks$.next([nextTask].concat(this.tasks$.value));\n });\n }\n }\n\n public onUpdateTask(taskUpdate: PtTaskUpdate) {\n if (this.state.item) {\n if (taskUpdate.delete) {\n this.backlogService.deletePtTask(this.state.item, taskUpdate.task).then(ok => {\n if (ok) {\n const newTasks = this.tasks$.value.filter(task => {\n if (task.id !== taskUpdate.task.id) {\n return task;\n }\n });\n this.tasks$.next(newTasks);\n }\n });\n } else {\n this.backlogService.updatePtTask(this.state.item, taskUpdate.task, taskUpdate.toggle, taskUpdate.newTitle).then(updatedTask => {\n const newTasks = this.tasks$.value.map(task => {\n if (task.id === updatedTask.id) {\n return updatedTask;\n } else {\n return task;\n }\n });\n this.tasks$.next(newTasks);\n });\n }\n }\n }\n\n\n public onAddNewComment(newComment: PtNewComment) {\n if (this.state.item) {\n this.backlogService.addNewPtComment(newComment, this.state.item).then(nextComment => {\n this.comments$.next([nextComment].concat(this.comments$.value));\n });\n }\n }\n\n public onUsersRequested() {\n this.ptUserService.fetchUsers();\n }\n\n public getSelectedTabNum() {\n return this.screenPositionMap[this.state.selectedDetailsScreen] as number;\n }\n\n public render() {\n const item = this.state.item;\n\n if (!item) {\n return null;\n }\n return (\n\n <div>\n <div className=\"d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3\">\n <h1 className=\"h2\"><span className=\"k-icon k-i-edit\"></span> {item.title}</h1>\n </div>\n\n <TabStrip onSelect={(e) => this.onTabSelect(e)} selected={this.getSelectedTabNum()}>\n <TabStripTab title=\"Details\">\n <PtItemDetailsComponent item={item} users$={this.users$} usersRequested={() => this.onUsersRequested()} itemSaved={(item) => this.onItemSaved(item)} />\n </TabStripTab>\n <TabStripTab title=\"Tasks\">\n <PtItemTasksComponent tasks$={this.tasks$} addNewTask={(newTask) => this.onAddNewTask(newTask)} updateTask={(taskUpdate) => this.onUpdateTask(taskUpdate)} />\n </TabStripTab>\n <TabStripTab title=\"Chitchat\">\n <PtItemChitchatComponent comments$={this.comments$} currentUser={this.currentUser!} addNewComment={(newComment) => this.onAddNewComment(newComment)} />\n </TabStripTab>\n </TabStrip>\n\n </div>\n );\n }\n}\n","/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/dashboard/pages/dashboard/dashboard-page.tsx",["168"],"import React from \"react\";\n\nimport { Button, ButtonGroup } from '@progress/kendo-react-buttons';\nimport { ComboBox, ComboBoxChangeEvent } from '@progress/kendo-react-dropdowns';\n\nimport { DashboardFilter, DashboardRepository, FilteredIssues } from \"../../repositories/dashboard.repository\";\nimport { formatDateEnUs } from \"../../../../core/helpers/date-utils\";\nimport { ActiveIssuesComponent } from \"../../components/active-issues/active-issues\";\nimport { DashboardService } from \"../../services/dashboard.service\";\nimport { StatusCounts } from \"../../models\";\nimport { PtUser } from \"../../../../core/models/domain\";\nimport { Store } from \"../../../../core/state/app-store\";\nimport { Observable } from \"rxjs\";\nimport { PtUserService } from \"../../../../core/services/pt-user-service\";\nimport { DashboardChart } from \"./dashboard-chart\";\n\ninterface DateRange {\n dateStart: Date;\n dateEnd: Date;\n}\n\ninterface DashboardPageState {\n statusCounts: StatusCounts;\n filter: DashboardFilter;\n users: PtUser[];\n issuesAll: FilteredIssues;\n}\n\nexport class DashboardPage extends React.Component<any, DashboardPageState> {\n\n private store: Store = new Store();\n private dashboardRepo: DashboardRepository = new DashboardRepository();\n private dashboardService: DashboardService = new DashboardService(this.dashboardRepo);\n private ptUserService: PtUserService = new PtUserService(this.store);\n\n public users$: Observable<PtUser[]> = this.store.select<PtUser[]>('users');\n\n constructor(props: any) {\n super(props);\n this.state = {\n statusCounts: {\n activeItemsCount: 0,\n closeRate: 0,\n closedItemsCount: 0,\n openItemsCount: 0\n },\n filter: {},\n users: [],\n issuesAll: {\n categories: [],\n items: []\n }\n };\n }\n\n public componentDidMount() {\n this.users$.subscribe(users => {\n this.setState({\n users: users\n });\n });\n this.refresh();\n }\n\n public componentDidUpdate(prevProps: any, prevState: DashboardPageState) {\n if (this.state.filter.userId !== prevState.filter.userId ||\n this.state.filter.dateStart !== prevState.filter.dateStart ||\n this.state.filter.dateEnd !== prevState.filter.dateEnd) {\n this.refresh();\n }\n }\n\n private onMonthRangeTap(months: number) {\n const range = this.getDateRange(months);\n this.setState({\n filter: {\n userId: this.state.filter.userId,\n dateEnd: range.dateEnd,\n dateStart: range.dateStart\n }\n });\n }\n\n private getDateRange(months: number): DateRange {\n const now = new Date();\n const start = new Date();\n start.setMonth(start.getMonth() - months);\n return {\n dateStart: start,\n dateEnd: now\n };\n }\n\n private refresh() {\n\n Promise.all<StatusCounts, FilteredIssues>([\n this.dashboardService.getStatusCounts(this.state.filter),\n this.dashboardService.getFilteredIssues(this.state.filter)\n ]\n ).then(results => {\n this.setState({\n statusCounts: results[0],\n issuesAll: results[1]\n });\n });\n }\n\n public userFilterOpen() {\n this.ptUserService.fetchUsers();\n }\n\n private filterItemRender(li: any, itemProps: any) {\n const userItem = itemProps.dataItem as PtUser;\n const renderedRow = (\n <div className=\"row\" style={{ marginLeft: 5 }}>\n <img className=\"li-avatar rounded mx-auto d-block\" src={userItem.avatar} />\n <span style={{ marginLeft: 5 }}>{userItem.fullName}</span>\n </div>\n );\n return React.cloneElement(li, li.props, renderedRow);\n }\n\n public userFilterValueChange(e: ComboBoxChangeEvent) {\n const user = e.target.value;\n if (user) {\n this.setState({\n filter: { ...this.state.filter, userId: user.id }\n });\n } else {\n this.setState({\n filter: { ...this.state.filter, userId: undefined }\n });\n }\n }\n\n public render() {\n return (\n <div className=\"dashboard\">\n\n <div className=\"d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3\">\n\n <div className=\"col-md order-md-first text-center text-md-left\">\n <h2>\n <span className=\"small text-uppercase text-muted d-block\">Statistics</span>\n {\n (this.state.filter.dateStart && this.state.filter.dateEnd) && (\n <span> {formatDateEnUs(this.state.filter.dateStart)} - {formatDateEnUs(this.state.filter.dateEnd)}</span>\n )\n }\n </h2>\n </div>\n\n <div className=\"btn-toolbar mb-2 mb-md-0\">\n <div className=\"btn-group mr-2\">\n\n <ComboBox data={this.state.users} itemRender={this.filterItemRender} textField=\"fullName\"\n dataItemKey=\"id\" onOpen={() => this.userFilterOpen()} onChange={(e) => this.userFilterValueChange(e)} style={{ width: 250 }} />\n\n <ButtonGroup>\n <Button type=\"button\" look=\"flat\" icon=\"calendar\" onClick={(e) => this.onMonthRangeTap(3)}>3 Months</Button>\n <Button type=\"button\" look=\"flat\" icon=\"calendar\" onClick={(e) => this.onMonthRangeTap(6)}>6 Months</Button>\n <Button type=\"button\" look=\"flat\" icon=\"calendar\" onClick={(e) => this.onMonthRangeTap(12)}>1 Year</Button>\n </ButtonGroup>\n\n </div >\n\n </div >\n </div >\n\n\n <div className=\"card\">\n <h3 className=\"card-header\">Active Issues</h3>\n <div className=\"card-block\">\n\n <ActiveIssuesComponent statusCounts={this.state.statusCounts} />\n\n <div className=\"row\">\n <div className=\"col-sm-12\">\n <h3>All issues</h3>\n\n <DashboardChart issuesAll={this.state.issuesAll} />\n\n </div>\n </div>\n </div>\n </div >\n\n </div >\n );\n }\n}\n","/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/backlog/repositories/backlog.repository.ts",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/backlog/services/backlog.service.ts",["169","170","171","172"],"import { Store } from '../../../core/state/app-store';\nimport { BacklogRepository } from '../repositories/backlog.repository';\n\nimport { PtItem, PtUser, PtTask, PtComment } from '../../../core/models/domain';\n\nimport { PriorityEnum, StatusEnum } from '../../../core/models/domain/enums';\nimport { getUserAvatarUrl } from '../../../core/helpers/user-avatar-helper';\nimport { Observable } from 'rxjs';\nimport { map, tap } from 'rxjs/operators';\n\nimport { CONFIG } from '../../../config';\nimport { PresetType } from '../../../core/models/domain/types';\nimport { datesForTask, datesForPtItem } from '../../../core/helpers/date-utils';\nimport { PtNewItem } from '../../../shared/models/dto/pt-new-item';\nimport { PtNewTask } from '../../../shared/models/dto/pt-new-task';\nimport { PtNewComment } from '../../../shared/models/dto/pt-new-comment';\n\n\nexport const tempCurrentUser = {\n avatar: getUserAvatarUrl(CONFIG.apiEndpoint, 21),\n dateCreated: new Date(),\n dateModified: new Date(),\n fullName: 'Alex Ziskind',\n id: 21\n};\n\n\nexport class BacklogService {\n\n\n private get currentPreset() {\n return this.store.value.selectedPreset;\n }\n\n private get currentUserId() {\n if (this.store.value.currentUser) {\n return this.store.value.currentUser.id;\n } else {\n return undefined;\n }\n }\n\n\n constructor(\n private repo: BacklogRepository,\n private store: Store\n ) {\n this.store.value.currentUser = tempCurrentUser;\n }\n\n public getItems(preset: PresetType): Promise<PtItem[]> {\n return this.repo.getPtItems(preset, this.currentUserId)\n .then((ptItems: PtItem[]) => {\n\n ptItems.forEach(i => {\n datesForPtItem(i);\n this.setUserAvatarUrl(i.assignee);\n i.comments.forEach(c => this.setUserAvatarUrl(c.user));\n });\n return ptItems;\n });\n }\n\n /*\n public getItemFromCacheOrServer(id: number) {\n // const selectedItem = _.find(this.store.value.backlogItems, i => i.id === id);\n const selectedItem = this.store.value.backlogItems.find(i => i.id === id);\n if (selectedItem) {\n\n this.store.set('currentSelectedItem', selectedItem);\n\n } else {\n this.getPtItem(id);\n }\n }\n*/\n\n\n public getPtItem(id: number): Promise<PtItem> {\n return this.repo.getPtItem(id)\n .then((ptItem: PtItem) => {\n datesForPtItem(ptItem);\n this.setUserAvatarUrl(ptItem.assignee);\n ptItem.comments.forEach(c => this.setUserAvatarUrl(c.user));\n ptItem.tasks.forEach(t => datesForTask(t));\n return ptItem;\n });\n }\n\n\n public addNewPtItem(newItem: PtNewItem, assignee: PtUser): Promise<PtItem> {\n const item: PtItem = {\n id: 0,\n title: newItem.title,\n description: newItem.description,\n type: newItem.typeStr,\n estimate: 0,\n priority: PriorityEnum.Medium,\n status: StatusEnum.Open,\n assignee: assignee,\n tasks: [],\n comments: [],\n dateCreated: new Date(),\n dateModified: new Date()\n };\n return new Promise<PtItem>((resolve, reject) => {\n this.repo.insertPtItem(item)\n .then((nextItem: PtItem) => {\n datesForPtItem(nextItem);\n this.setUserAvatar(nextItem.assignee);\n\n nextItem.tasks.forEach(t => datesForTask(t));\n resolve(nextItem);\n });\n });\n }\n\n\n public updatePtItem(item: PtItem): Promise<PtItem> {\n return this.repo.updatePtItem(item);\n }\n\n /*\n\n public deletePtItem(item: PtItem) {\n this.repo.deletePtItem(item.id,\n () => {\n\n const updatedItems = this.store.value.backlogItems.filter((i) => {\n return i.id !== item.id;\n });\n this.store.set('backlogItems', updatedItems);\n\n }\n );\n }\n*/\n\n public addNewPtTask(newTask: PtNewTask, currentItem: PtItem): Promise<PtTask> {\n const task: PtTask = {\n id: 0,\n title: newTask.title,\n completed: false,\n dateCreated: new Date(),\n dateModified: new Date(),\n dateStart: newTask.dateStart ? newTask.dateStart : undefined,\n dateEnd: newTask.dateEnd ? newTask.dateEnd : undefined\n };\n return new Promise<PtTask>((resolve, reject) => {\n this.repo.insertPtTask(\n task,\n currentItem.id)\n .then((nextTask: PtTask) => {\n datesForTask(nextTask);\n resolve(nextTask);\n }\n );\n });\n }\n\n\n public updatePtTask(currentItem: PtItem, task: PtTask, toggle: boolean, newTitle?: string): Promise<PtTask> {\n const taskToUpdate: PtTask = {\n id: task.id,\n title: newTitle ? newTitle : task.title,\n completed: toggle ? !task.completed : task.completed,\n dateCreated: task.dateCreated,\n dateModified: new Date(),\n dateStart: task.dateStart ? task.dateStart : undefined,\n dateEnd: task.dateEnd ? task.dateEnd : undefined\n };\n return new Promise<PtTask>((resolve, reject) => {\n this.repo.updatePtTask(\n taskToUpdate,\n currentItem.id)\n .then((updatedTask: PtTask) => {\n datesForTask(updatedTask);\n resolve(updatedTask);\n }\n );\n });\n }\n\n public deletePtTask(currentItem: PtItem, task: PtTask): Promise<boolean> {\n return new Promise<boolean>((resolve, reject) => {\n this.repo.deletePtTask(task, currentItem.id)\n .then((ok: boolean) => {\n const updatedTasks = currentItem.tasks.filter(t => {\n if (t.id !== task.id) {\n return t;\n }\n });\n currentItem.tasks = updatedTasks;\n resolve(ok);\n }\n );\n });\n }\n\n public addNewPtComment(newComment: PtNewComment, currentItem: PtItem): Promise<PtComment> {\n const comment: PtComment = {\n id: 0,\n title: newComment.title,\n user: this.store.value.currentUser,\n dateCreated: new Date(),\n dateModified: new Date()\n };\n return new Promise<PtComment>((resolve, reject) => {\n this.repo.insertPtComment(\n comment,\n currentItem.id\n )\n .then((nextComment: PtComment) => {\n resolve(nextComment);\n }\n );\n });\n }\n\n private setUserAvatarUrl(user: PtUser | undefined) {\n if (user) {\n user.avatar = `${CONFIG.apiEndpoint}/photo/${user.id}`;\n }\n }\n\n private setUserAvatar(user: PtUser) {\n user.avatar = getUserAvatarUrl(CONFIG.apiEndpoint, user.id);\n }\n\n}\n","/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/dashboard/repositories/dashboard.repository.ts",["173"],"import { StatusCounts, PriorityCounts, TypeCounts } from '../models';\nimport { CONFIG } from '../../../config';\nimport { PtItem } from '../../../core/models/domain';\n\n\nexport interface DashboardFilter {\n userId?: number;\n dateStart?: Date;\n dateEnd?: Date;\n}\n\nexport interface ItemsForMonth {\n closed: PtItem[];\n open: PtItem[];\n}\n\nexport interface FilteredIssues {\n categories: Date[];\n items: ItemsForMonth[];\n}\n\nexport class DashboardRepository {\n constructor() { }\n\n private getFilterParamString(filter: DashboardFilter): string {\n const params = [\n filter.userId ? `userId=${filter.userId}` : '',\n filter.dateStart ? `dateStart=${filter.dateStart.toDateString()}` : '',\n filter.dateEnd ? `dateEnd=${filter.dateEnd.toDateString()}` : ''\n ];\n const paramStr = params.join('&');\n return paramStr;\n }\n private getStatusCountsUrl(paramStr: string): string {\n return `${CONFIG.apiEndpoint}/stats/statuscounts?${paramStr}`;\n }\n\n private getPriorityCountsUrl(paramStr: string): string {\n return `${CONFIG.apiEndpoint}/stats/prioritycounts?${paramStr}`;\n }\n\n private getTypeCountsUrl(paramStr: string): string {\n return `${CONFIG.apiEndpoint}/stats/prioritycounts?${paramStr}`;\n }\n\n private getFilteredIssuesUrl(paramStr: string): string {\n return `${CONFIG.apiEndpoint}/stats/filteredissues?${paramStr}`;\n }\n\n public getStatusCounts(filter: DashboardFilter): Promise<StatusCounts> {\n return fetch(this.getStatusCountsUrl(this.getFilterParamString(filter)))\n .then(response => response.json());\n }\n\n public getPriorityCounts(filter: DashboardFilter): Promise<PriorityCounts> {\n return fetch(this.getPriorityCountsUrl(this.getFilterParamString(filter)))\n .then(response => response.json());\n }\n\n public getTypeCounts(filter: DashboardFilter): Promise<TypeCounts> {\n return fetch(this.getTypeCountsUrl(this.getFilterParamString(filter)))\n .then(response => response.json());\n }\n\n public getFilteredIssues(filter: DashboardFilter): Promise<FilteredIssues> {\n return fetch(this.getFilteredIssuesUrl(this.getFilterParamString(filter)))\n .then(response => response.json());\n }\n}\n","/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/dashboard/services/dashboard.service.ts",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/shared/helpers/priority-styling.ts",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/helpers/date-utils.ts",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/state/app-store.ts",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/services/pt-user-service.ts",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/dashboard/pages/dashboard/dashboard-chart.tsx",["174"],"import React from \"react\";\n\nimport {\n Chart,\n ChartSeries,\n ChartSeriesItem,\n ChartCategoryAxis,\n ChartCategoryAxisItem,\n ChartTitle,\n ChartLegend,\n ChartSeriesDefaults\n} from '@progress/kendo-react-charts';\nimport 'hammerjs';\nimport { FilteredIssues } from \"../../repositories/dashboard.repository\";\n\n\ninterface DashboardChartProps {\n issuesAll: FilteredIssues\n //categories: any[];\n //itemsOpenByMonth: any[];\n //itemsClosedByMonth: any[];\n}\n\ninterface DashboardChartState {\n categories: Date[];\n itemsOpenByMonth: number[];\n itemsClosedByMonth: number[];\n}\n\nexport class DashboardChart extends React.Component<DashboardChartProps, DashboardChartState> {\n\n constructor(props: DashboardChartProps) {\n super(props);\n this.state = {\n categories: [],\n itemsOpenByMonth: [],\n itemsClosedByMonth: []\n };\n }\n\n public componentDidUpdate(prevProps: DashboardChartProps, prevState: DashboardChartState) {\n const cats = this.props.issuesAll.categories.map(c => new Date(c));\n\n const itemsOpenByMonth: number[] = [];\n const itemsClosedByMonth: number[] = [];\n\n this.props.issuesAll.items.forEach((item, index) => {\n itemsOpenByMonth.push(item.open.length);\n itemsClosedByMonth.push(item.closed.length);\n });\n\n if (prevState.categories.length !== cats.length ||\n prevState.itemsOpenByMonth.length !== itemsOpenByMonth.length ||\n prevState.itemsClosedByMonth.length !== itemsClosedByMonth.length) {\n this.setState({\n categories: cats,\n itemsOpenByMonth: itemsOpenByMonth,\n itemsClosedByMonth: itemsClosedByMonth\n });\n }\n }\n\n public render() {\n if (this.state.categories.length < 1) {\n return null;\n }\n return (\n <Chart>\n <ChartTitle text=\"Active Issues\" />\n\n <ChartSeriesDefaults type=\"column\" stack={true} gap={0.06} />\n\n <ChartCategoryAxis>\n <ChartCategoryAxisItem categories={this.state.categories} baseUnit=\"months\" majorGridLines={{ visible: false }} labels={{ rotation: 'auto', margin: { top: 20 } }}></ChartCategoryAxisItem>\n </ChartCategoryAxis>\n\n <ChartSeries>\n <ChartSeriesItem data={this.state.itemsOpenByMonth} opacity={0.7} color=\"#CC3458\" />\n\n <ChartSeriesItem data={this.state.itemsClosedByMonth} opacity={0.7} color=\"#35C473\" />\n </ChartSeries>\n </Chart>\n );\n }\n\n}\n","/Users/alex/Code/progress/rpstrackerreact_kendo/src/shared/components/preset-filter/preset-filter.tsx",["175","176"],"import React, { ReactNode } from \"react\";\nimport { PresetType } from \"../../../core/models/domain/types\";\n\n\ninterface AppPresetFilterProps {\n selectedPreset: PresetType;\n onSelectPresetTap: (preset: PresetType) => void;\n}\n\nexport class AppPresetFilter extends React.PureComponent<AppPresetFilterProps, any> {\n\n constructor(props: AppPresetFilterProps) {\n super(props);\n }\n\n public render() {\n return (\n <div className=\"btn-group mr-2\">\n <button type=\"button\" className=\"btn btn-sm btn-outline-secondary\" onClick={(e) => this.props.onSelectPresetTap('my')}>My Items</button>\n <button type=\"button\" className=\"btn btn-sm btn-outline-secondary\" onClick={(e) => this.props.onSelectPresetTap('open')} > Open Items</button >\n <button type=\"button\" className=\"btn btn-sm btn-outline-secondary\" onClick={(e) => this.props.onSelectPresetTap('closed')} > Done Items</button >\n </div >\n );\n }\n};\n","/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/backlog/components/item-tasks/pt-item-tasks.tsx",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/backlog/components/item-details/pt-item-details.tsx",["177","178","179","180"],"import React from \"react\";\nimport { Observable } from \"rxjs\";\nimport { Modal, ModalBody, ModalFooter } from \"reactstrap\";\nimport { Input } from '@progress/kendo-react-inputs';\n\nimport { DropDownList, ListItemProps } from '@progress/kendo-react-dropdowns';\n\nimport { PtItem, PtUser } from \"../../../../core/models/domain\";\nimport { PtItemDetailsEditFormModel, ptItemToFormModel } from \"../../../../shared/models/forms/pt-item-details-edit-form\";\nimport { ItemType, PT_ITEM_STATUSES, PT_ITEM_PRIORITIES } from \"../../../../core/constants\";\nimport { PriorityEnum } from \"../../../../core/models/domain/enums\";\nimport { getIndicatorClass } from \"../../../../shared/helpers/priority-styling\";\n\n\n\ninterface PtItemDetailsComponentProps {\n item: PtItem;\n itemSaved: (item: PtItem) => void;\n usersRequested: () => void;\n users$: Observable<PtUser[]>;\n}\n\ninterface PtItemDetailsComponentState {\n showAddModal: boolean;\n users: PtUser[];\n}\n\nexport class PtItemDetailsComponent extends React.Component<PtItemDetailsComponentProps, PtItemDetailsComponentState> {\n\n private itemForm: PtItemDetailsEditFormModel | undefined;\n public itemTypesProvider = ItemType.List.map((t) => t.PtItemType);\n public statusesProvider = PT_ITEM_STATUSES;\n public prioritiesProvider = PT_ITEM_PRIORITIES;\n private selectedAssignee: PtUser | undefined;\n\n constructor(props: any) {\n super(props);\n\n this.itemForm = ptItemToFormModel(this.props.item);\n this.state = {\n showAddModal: false,\n users: []\n };\n this.selectedAssignee = this.props.item.assignee;\n }\n\n public onFieldChange(e: any, formFieldName: string) {\n if (!this.itemForm) {\n return;\n }\n (this.itemForm as any)[formFieldName] = e.target.value;\n }\n\n public onNonTextFieldChange(e: any, formFieldName: string) {\n this.onFieldChange(e, formFieldName);\n this.notifyUpdateItem();\n }\n\n public onBlurTextField() {\n this.notifyUpdateItem();\n }\n\n private notifyUpdateItem() {\n if (!this.itemForm) {\n return;\n }\n const updatedItem = this.getUpdatedItem(this.props.item, this.itemForm, this.selectedAssignee!);\n this.props.itemSaved(updatedItem);\n }\n\n private getUpdatedItem(item: PtItem, itemForm: PtItemDetailsEditFormModel, assignee: PtUser): PtItem {\n const updatedItem = Object.assign({}, item, {\n title: itemForm.title,\n description: itemForm.description,\n type: itemForm.typeStr,\n status: itemForm.statusStr,\n priority: itemForm.priorityStr,\n estimate: itemForm.estimate,\n assignee: assignee\n });\n return updatedItem;\n }\n\n public assigneePickerOpen() {\n this.props.users$.subscribe((users: PtUser[]) => {\n if (users.length > 0) {\n this.setState({\n users: users,\n showAddModal: true\n });\n }\n });\n\n this.props.usersRequested();\n }\n\n private toggleModal() {\n this.setState({\n showAddModal: !this.state.showAddModal\n });\n return false;\n }\n\n private selectAssignee(u: PtUser) {\n this.selectedAssignee = u;\n this.itemForm!.assigneeName = u.fullName;\n this.setState({\n showAddModal: false,\n });\n this.notifyUpdateItem();\n }\n\n private itemTypeRender(li: any, itemProps: any) {\n const dataItem = itemProps.dataItem;\n const itemTypeRow = (\n <React.Fragment>\n <img src={ItemType.imageResFromType(dataItem)} className=\"backlog-icon\" />\n <span>{dataItem}</span>\n </React.Fragment>\n );\n return React.cloneElement(li, li.props, itemTypeRow);\n }\n\n private priorityRender(li: any, itemProps: ListItemProps) {\n const dataItem = itemProps.dataItem;\n const priorityRow = (\n <span className={'badge ' + getIndicatorClass(dataItem)}>{dataItem}</span>\n );\n return React.cloneElement(li, li.props, priorityRow);\n }\n\n public render() {\n if (!this.itemForm) {\n return null;\n }\n const itemForm = this.itemForm;\n return (\n <React.Fragment>\n <form>\n <div className=\"form-group row\">\n <label className=\"col-sm-2 col-form-label\">Title</label>\n <div className=\"col-sm-10\">\n\n <Input label=\"Title\" defaultValue={itemForm.title} onBlur={() => this.onBlurTextField()} onChange={(e) => this.onFieldChange(e, 'title')} name=\"title\" style={{ width: '60%' }} />\n\n </div>\n </div>\n\n <div className=\"form-group row\">\n <label className=\"col-sm-2 col-form-label\">Description</label>\n <div className=\"col-sm-10\">\n <Input label=\"Description\" multiple={true} defaultValue={itemForm.description} onBlur={() => this.onBlurTextField()} onChange={(e) => this.onFieldChange(e, 'description')} name=\"description\" style={{ width: '60%', height: 100 }} />\n </div>\n </div>\n\n <div className=\"form-group row\">\n <label className=\"col-sm-2 col-form-label\">Item Type</label>\n <div className=\"col-sm-10\">\n\n <DropDownList data={this.itemTypesProvider} itemRender={this.itemTypeRender} defaultValue={itemForm.typeStr} onChange={(e) => this.onNonTextFieldChange(e, 'typeStr')} name=\"itemType\" />\n\n </div>\n </div>\n\n <div className=\"form-group row\">\n <label className=\"col-sm-2 col-form-label\">Status</label>\n <div className=\"col-sm-10\">\n\n <DropDownList data={this.statusesProvider} defaultValue={itemForm.statusStr} onChange={(e) => this.onNonTextFieldChange(e, 'statusStr')} name=\"status\" />\n\n </div>\n </div>\n\n <div className=\"form-group row\">\n <label className=\"col-sm-2 col-form-label\">Estimate</label>\n <div className=\"col-sm-10\">\n <input className=\"form-control\" type=\"range\" step=\"1\" min=\"0\" max=\"20\" value={itemForm.estimate} onChange={(e) => this.onNonTextFieldChange(e, 'estimate')} name=\"estimate\" style={{ width: 300 }} />\n </div>\n </div>\n\n <div className=\"form-group row\">\n <label className=\"col-sm-2 col-form-label\">Priority</label>\n <div className=\"col-sm-10\">\n\n <DropDownList data={this.prioritiesProvider} itemRender={(li, props) => this.priorityRender(li, props)} defaultValue={itemForm.priorityStr} onChange={(e) => this.onNonTextFieldChange(e, 'priorityStr')} name=\"priority\" />\n\n </div>\n </div>\n\n <div className=\"form-group row\">\n <label className=\"col-sm-2 col-form-label\">Assignee</label>\n\n <div className=\"col-sm-10\">\n <img src={this.selectedAssignee!.avatar} className=\"li-avatar rounded\" />\n <span>{itemForm.assigneeName}</span>\n\n <button type=\"button\" className=\"btn btn-sm btn-outline-secondary\" onClick={() => this.assigneePickerOpen()}>Pick assignee</button>\n </div>\n </div>\n </form>\n\n <Modal isOpen={this.state.showAddModal} toggle={() => this.toggleModal()}>\n <div className=\"modal-header\">\n <h4 className=\"modal-title\" id=\"modal-basic-title\">Select Assignee</h4>\n <button type=\"button\" className=\"close\" onClick={() => this.toggleModal()} aria-label=\"Close\">\n <span aria-hidden=\"true\">×</span>\n </button>\n </div>\n <ModalBody>\n <ul className=\"list-group list-group-flush\">\n {\n this.state.users.map((u: PtUser) => {\n return (\n <li key={u.id} className=\"list-group-item d-flex justify-content-between align-items-center\" onClick={() => this.selectAssignee(u)}>\n <span>{u.fullName}</span>\n <span className=\"badge \">\n <img src={u.avatar} className=\"li-avatar rounded mx-auto d-block\" />\n </span>\n </li>\n );\n })\n }\n </ul>\n </ModalBody >\n <ModalFooter />\n </Modal >\n\n </React.Fragment>\n );\n }\n}\n","/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/backlog/components/item-chitchat/pt-item-chitchat.tsx",["181","182"],"import React from \"react\";\nimport { PtComment, PtUser } from \"../../../../core/models/domain\";\nimport { EMPTY_STRING } from \"../../../../core/helpers\";\nimport { BehaviorSubject } from \"rxjs\";\nimport { PtNewComment } from \"../../../../shared/models/dto/pt-new-comment\";\n\nimport './pt-item-chitchat.css';\n\ninterface PtItemChitchatComponentProps {\n comments$: BehaviorSubject<PtComment[]>;\n currentUser: PtUser;\n addNewComment: (newComment: PtNewComment) => void;\n}\n\ninterface PtItemChitchatComponentState {\n newCommentText: string;\n comments: PtComment[];\n}\n\nexport class PtItemChitchatComponent extends React.Component<PtItemChitchatComponentProps, PtItemChitchatComponentState> {\n\n constructor(props: PtItemChitchatComponentProps) {\n super(props);\n this.state = {\n newCommentText: EMPTY_STRING,\n comments: []\n };\n }\n\n public componentDidMount() {\n this.props.comments$.subscribe((comments: PtComment[]) => {\n this.setState({\n comments: comments\n });\n });\n }\n\n public onNewCommentChanged(e: any) {\n this.setState({\n newCommentText: e.target.value\n });\n }\n\n public onAddTapped() {\n const newTitle = this.state.newCommentText.trim();\n if (newTitle.length === 0) {\n return;\n }\n const newComment: PtNewComment = {\n title: newTitle\n };\n this.props.addNewComment(newComment);\n\n this.setState({\n newCommentText: EMPTY_STRING\n });\n }\n\n public render() {\n return (\n <React.Fragment>\n <form>\n <div className=\"form-row align-items-center\">\n\n <img src={this.props.currentUser.avatar} className=\"mr-3 li-avatar rounded\" />\n\n <div className=\"col-sm-6\">\n <textarea defaultValue={this.state.newCommentText} onChange={(e) => this.onNewCommentChanged(e)} placeholder=\"Enter new comment...\" className=\"form-control pt-text-comment-add\"\n name=\"newComment\"></textarea>\n </div>\n <button type=\"button\" onClick={() => this.onAddTapped()} className=\"btn btn-primary\" disabled={!this.state.newCommentText}>Add</button>\n </div>\n </form >\n\n <hr />\n\n <ul className=\"list-unstyled\">\n {\n this.state.comments.map(comment => {\n return (\n <li key={comment.id} className=\"media chitchat-item\">\n <img src={comment.user!.avatar} className=\"mr-3 li-avatar rounded\" />\n <div className=\"media-body\">\n <h6 className=\"mt-0 mb-1\"><span>{comment.user!.fullName}</span><span className=\"li-date\">{comment.dateCreated}</span></h6>\n\n <span className=\"chitchat-text \">{comment.title}</span>\n\n </div>\n </li>\n );\n })\n }\n </ul>\n </React.Fragment >\n );\n }\n}\n","/Users/alex/Code/progress/rpstrackerreact_kendo/src/modules/dashboard/components/active-issues/active-issues.tsx",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/helpers/index.ts",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/config.ts",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/helpers/user-avatar-helper.ts",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/constants/index.ts",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/state/app-state.ts",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/shared/models/forms/pt-item-details-edit-form.ts",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/helpers/string-helpers.ts",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/constants/pt-item-statuses.ts",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/constants/pt-item-types.ts",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/constants/pt-item-priorities.ts",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/models/domain/enums/index.ts",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/models/domain/enums/item-type-enum.ts",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/models/domain/enums/item-status.enum.ts",[],"/Users/alex/Code/progress/rpstrackerreact_kendo/src/core/models/domain/enums/item-priority.enum.ts",[],{"ruleId":"183","replacedBy":"184"},{"ruleId":"185","replacedBy":"186"},{"ruleId":"187","severity":1,"message":"188","line":8,"column":5,"nodeType":"189","messageId":"190","endLine":10,"endColumn":6},{"ruleId":"191","severity":1,"message":"192","line":15,"column":17,"nodeType":"193","endLine":15,"endColumn":68},{"ruleId":"194","severity":1,"message":"195","line":16,"column":21,"nodeType":"193","endLine":16,"endColumn":75},{"ruleId":"196","severity":1,"message":"197","line":5,"column":47,"nodeType":"198","messageId":"199","endLine":5,"endColumn":66},{"ruleId":"196","severity":1,"message":"200","line":5,"column":68,"nodeType":"198","messageId":"199","endLine":5,"endColumn":87},{"ruleId":"196","severity":1,"message":"201","line":6,"column":10,"nodeType":"198","messageId":"199","endLine":6,"endColumn":24},{"ruleId":"196","severity":1,"message":"202","line":6,"column":26,"nodeType":"198","messageId":"199","endLine":6,"endColumn":33},{"ruleId":"194","severity":1,"message":"195","line":207,"column":33,"nodeType":"193","endLine":207,"endColumn":110},{"ruleId":"194","severity":1,"message":"195","line":215,"column":37,"nodeType":"193","endLine":215,"endColumn":119},{"ruleId":"203","severity":1,"message":"204","line":116,"column":72,"nodeType":"205","messageId":"206","endLine":116,"endColumn":74},{"ruleId":"194","severity":1,"message":"195","line":116,"column":17,"nodeType":"193","endLine":116,"endColumn":92},{"ruleId":"196","severity":1,"message":"207","line":8,"column":10,"nodeType":"198","messageId":"199","endLine":8,"endColumn":20},{"ruleId":"196","severity":1,"message":"208","line":9,"column":10,"nodeType":"198","messageId":"199","endLine":9,"endColumn":13},{"ruleId":"196","severity":1,"message":"209","line":9,"column":15,"nodeType":"198","messageId":"199","endLine":9,"endColumn":18},{"ruleId":"203","severity":1,"message":"204","line":188,"column":69,"nodeType":"205","messageId":"206","endLine":188,"endColumn":71},{"ruleId":"187","severity":1,"message":"188","line":23,"column":5,"nodeType":"189","messageId":"190","endLine":23,"endColumn":22},{"ruleId":"196","severity":1,"message":"210","line":10,"column":5,"nodeType":"198","messageId":"199","endLine":10,"endColumn":16},{"ruleId":"196","severity":1,"message":"211","line":1,"column":17,"nodeType":"198","messageId":"199","endLine":1,"endColumn":26},{"ruleId":"187","severity":1,"message":"188","line":12,"column":5,"nodeType":"189","messageId":"190","endLine":14,"endColumn":6},{"ruleId":"196","severity":1,"message":"212","line":11,"column":10,"nodeType":"198","messageId":"199","endLine":11,"endColumn":22},{"ruleId":"194","severity":1,"message":"195","line":117,"column":17,"nodeType":"193","endLine":117,"endColumn":91},{"ruleId":"194","severity":1,"message":"195","line":194,"column":29,"nodeType":"193","endLine":194,"endColumn":102},{"ruleId":"194","severity":1,"message":"195","line":217,"column":49,"nodeType":"193","endLine":217,"endColumn":117},{"ruleId":"194","severity":1,"message":"195","line":65,"column":25,"nodeType":"193","endLine":65,"endColumn":103},{"ruleId":"194","severity":1,"message":"195","line":82,"column":37,"nodeType":"193","endLine":82,"endColumn":106},"no-native-reassign",["213"],"no-negated-in-lhs",["214"],"@typescript-eslint/no-useless-constructor","Useless constructor.","MethodDefinition","noUselessConstructor","jsx-a11y/anchor-is-valid","The href attribute is required for an anchor to be keyboard accessible. Provide a valid, navigable address as the href value. If you cannot provide an href, but still need the element to resemble a link, use a button and change it with appropriate styles. Learn more: https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-is-valid.md","JSXOpeningElement","jsx-a11y/alt-text","img elements must have an alt prop, either with meaningful text, or an empty string for decorative images.","@typescript-eslint/no-unused-vars","'GridPageChangeEvent' is defined but never used.","Identifier","unusedVar","'GridSortChangeEvent' is defined but never used.","'SortDescriptor' is defined but never used.","'orderBy' is defined but never used.","array-callback-return","Array.prototype.filter() expects a value to be returned at the end of arrow function.","ArrowFunctionExpression","expectedAtEnd","'Observable' is defined but never used.","'map' is defined but never used.","'tap' is defined but never used.","'ChartLegend' is defined but never used.","'ReactNode' is defined but never used.","'PriorityEnum' is defined but never used.","no-global-assign","no-unsafe-negation"]