From 53d28268883f75dab1e61faa503ec2a22bff4934 Mon Sep 17 00:00:00 2001 From: Isaac Mann Date: Tue, 22 Jan 2019 16:04:04 -0500 Subject: [PATCH 1/4] feat: Show all actions from project view --- .../src/integration/projects.spec.ts | 47 +++- .../lib/graphql/update-recent-actions.graphql | 16 ++ .../lib/graphql/workspace-schematics.graphql | 12 + .../src/lib/graphql/workspace.graphql | 4 + .../src/lib/projects/projects.component.html | 31 ++- .../src/lib/projects/projects.component.ts | 233 ++++++++++++++---- .../schema/src/lib/generated/graphql-types.ts | 64 +++++ libs/server/src/assets/schema.graphql | 12 + libs/server/src/lib/api/read-projects.ts | 14 +- .../server/src/lib/api/read-recent-actions.ts | 35 +++ libs/server/src/lib/api/read-settings.ts | 2 +- .../src/lib/resolvers/mutation.resolver.ts | 16 ++ .../src/lib/resolvers/query.resolver.ts | 2 +- 13 files changed, 428 insertions(+), 60 deletions(-) create mode 100644 libs/feature-workspaces/src/lib/graphql/update-recent-actions.graphql create mode 100644 libs/feature-workspaces/src/lib/graphql/workspace-schematics.graphql create mode 100644 libs/server/src/lib/api/read-recent-actions.ts diff --git a/apps/angular-console-e2e/src/integration/projects.spec.ts b/apps/angular-console-e2e/src/integration/projects.spec.ts index 43f529869b..95f8f12449 100644 --- a/apps/angular-console-e2e/src/integration/projects.spec.ts +++ b/apps/angular-console-e2e/src/integration/projects.spec.ts @@ -25,15 +25,18 @@ describe('Projects', () => { }); it('checks that hot actions work', () => { - elementContainsText('button', 'Generate Component').click(); - elementContainsText('div.context-title', '@schematics/angular - component'); + cy.contains('angular-console-projects button', 'Component').should( + 'not.exist' + ); + + cy.contains('mat-icon', 'more_horiz') + .first() + .click(); + cy.contains('.cdk-overlay-pane button', 'Component').click(); + cy.contains('div.context-title', '@schematics/angular - component'); cy.get('input[name="project"]').should(($p: any) => { expect($p[0].value).to.equal('proj'); }); - }); - - it('provides navigation to and from command runners', () => { - cy.contains('Generate Component').click(); cy.get('.exit-action').click(); projectNames($p => { @@ -41,5 +44,37 @@ describe('Projects', () => { expect(texts($p)[0]).to.contain('proj'); expect(texts($p)[1]).to.contain('proj-e2e'); }); + cy.contains('angular-console-projects button', 'Component'); + + cy.contains('angular-console-projects button', 'Build') + .first() + .click(); + cy.contains('div.context-title', 'ng build proj'); + cy.get('.exit-action').click(); + cy.contains('angular-console-projects button', 'Serve') + .first() + .click(); + cy.contains('div.context-title', 'ng serve proj'); + cy.get('.exit-action').click(); + cy.contains('angular-console-projects button', 'Extract-i18n') + .first() + .click(); + cy.contains('div.context-title', 'ng extract-i18n proj'); + cy.get('.exit-action').click(); + cy.contains('angular-console-projects button', 'Test') + .first() + .click(); + cy.contains('div.context-title', 'ng test proj'); + cy.get('.exit-action').click(); + cy.contains('mat-icon', 'more_horiz') + .first() + .click(); + cy.contains('.cdk-overlay-pane button', 'Lint').click(); + cy.contains('div.context-title', 'ng lint proj'); + cy.get('.exit-action').click(); + + cy.contains('angular-console-projects button', 'Component').should( + 'not.exist' + ); }); }); diff --git a/libs/feature-workspaces/src/lib/graphql/update-recent-actions.graphql b/libs/feature-workspaces/src/lib/graphql/update-recent-actions.graphql new file mode 100644 index 0000000000..6ca0b8b1ae --- /dev/null +++ b/libs/feature-workspaces/src/lib/graphql/update-recent-actions.graphql @@ -0,0 +1,16 @@ +mutation SaveRecentAction( + $workspacePath: String! + $projectName: String! + $actionName: String! + $schematicName: String +) { + saveRecentAction( + workspacePath: $workspacePath + projectName: $projectName + actionName: $actionName + schematicName: $schematicName + ) { + actionName + schematicName + } +} diff --git a/libs/feature-workspaces/src/lib/graphql/workspace-schematics.graphql b/libs/feature-workspaces/src/lib/graphql/workspace-schematics.graphql new file mode 100644 index 0000000000..6ceaf1b528 --- /dev/null +++ b/libs/feature-workspaces/src/lib/graphql/workspace-schematics.graphql @@ -0,0 +1,12 @@ +query WorkspaceSchematics($path: String!) { + workspace(path: $path) { + schematicCollections { + name + schematics { + name + description + collection + } + } + } +} diff --git a/libs/feature-workspaces/src/lib/graphql/workspace.graphql b/libs/feature-workspaces/src/lib/graphql/workspace.graphql index 37a6e9aa53..a0c784dd94 100644 --- a/libs/feature-workspaces/src/lib/graphql/workspace.graphql +++ b/libs/feature-workspaces/src/lib/graphql/workspace.graphql @@ -13,6 +13,10 @@ query Workspace($path: String!) { architect { name } + recentActions { + actionName + schematicName + } } } } diff --git a/libs/feature-workspaces/src/lib/projects/projects.component.html b/libs/feature-workspaces/src/lib/projects/projects.component.html index 7ecb887b88..38c19d2446 100644 --- a/libs/feature-workspaces/src/lib/projects/projects.component.html +++ b/libs/feature-workspaces/src/lib/projects/projects.component.html @@ -1,4 +1,4 @@ -
+
- + + + + + + + + {{ a.actionDescription }} + + + + + +
diff --git a/libs/feature-workspaces/src/lib/projects/projects.component.ts b/libs/feature-workspaces/src/lib/projects/projects.component.ts index 7012f4e7e7..78ee8b00fe 100644 --- a/libs/feature-workspaces/src/lib/projects/projects.component.ts +++ b/libs/feature-workspaces/src/lib/projects/projects.component.ts @@ -1,16 +1,39 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; -import { Project } from '@angular-console/schema'; import { combineLatest, Observable, of } from 'rxjs'; -import { map, startWith, switchMap, shareReplay } from 'rxjs/operators'; +import { + map, + startWith, + switchMap, + shareReplay, + filter, + catchError +} from 'rxjs/operators'; import { PROJECTS_POLLING, Settings, CommandRunner } from '@angular-console/utils'; -import { WorkspaceDocsGQL, WorkspaceGQL } from '../generated/graphql'; +import { + WorkspaceDocsGQL, + WorkspaceGQL, + SaveRecentActionGQL, + WorkspaceSchematicsGQL, + WorkspaceSchematics, + Workspace +} from '../generated/graphql'; import { FormControl } from '@angular/forms'; +export interface ProjectAction { + name: string; + actionDescription: string; + schematicName?: string; + link?: (string | { project: string })[]; +} +export interface ProjectActionMap { + [projectName: string]: ProjectAction[]; +} + @Component({ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'angular-console-projects', @@ -18,8 +41,9 @@ import { FormControl } from '@angular/forms'; styleUrls: ['./projects.component.scss'] }) export class ProjectsComponent implements OnInit { - projects$: Observable; - filteredProjects$: Observable; + workspacePath$: Observable; + projects$: Observable; + filteredProjects$: Observable; docs$ = this.settings.showDocs ? this.route.params.pipe( switchMap(p => this.workspaceDocsGQL.fetch({ path: p.path })), @@ -37,31 +61,64 @@ export class ProjectsComponent implements OnInit { shareReplay() ); + recentActions$: Observable; + constructor( private readonly route: ActivatedRoute, private readonly workspaceGQL: WorkspaceGQL, private readonly settings: Settings, private readonly workspaceDocsGQL: WorkspaceDocsGQL, - private readonly commandRunner: CommandRunner + private readonly saveRecentActionGQL: SaveRecentActionGQL, + private readonly commandRunner: CommandRunner, + private readonly workspaceSchematicsGQL: WorkspaceSchematicsGQL ) {} ngOnInit() { - this.projects$ = this.route.params.pipe( + const workspace$ = this.route.params.pipe( map(m => m.path), switchMap(path => { - return this.workspaceGQL.watch( - { - path - }, - { - pollInterval: PROJECTS_POLLING - } - ).valueChanges; + return combineLatest( + this.workspaceGQL.watch( + { + path + }, + { + pollInterval: PROJECTS_POLLING + } + ).valueChanges, + this.workspaceSchematicsGQL + .watch({ path }, { pollInterval: PROJECTS_POLLING }) + .valueChanges.pipe( + catchError(() => + of({ + data: { + workspace: { + schematicCollections: [] as WorkspaceSchematics.SchematicCollections[] + } + } + }) + ) + ) + ); }), - map((r: any) => { - const w = r.data.workspace; - const projects = w.projects.map((p: any) => { - return { ...p, actions: this.createActions(p) }; + filter(([r1, r2]) => Boolean(r1 && r2)), + map(([r1, r2]) => { + return { + workspace: r1.data.workspace, + schematicCollections: r2.data.workspace.schematicCollections + }; + }) + ); + this.workspacePath$ = workspace$.pipe( + map(({ workspace }) => workspace.path) + ); + this.projects$ = workspace$.pipe( + map(({ workspace, schematicCollections }) => { + const projects = workspace.projects.map((p: any) => { + return { + ...p, + actions: this.createActions(p, schematicCollections) + }; }); return projects; }) @@ -80,16 +137,70 @@ export class ProjectsComponent implements OnInit { ) ) ); + + const MAX_RECENT_ACTIONS = 5; + this.recentActions$ = this.projects$.pipe( + map(projects => { + return projects.reduce( + (projectActions, nextProject) => { + const recentActions = nextProject.recentActions + .map(recentAction => + (nextProject as any).actions.find( + (action: ProjectAction) => + action.name === recentAction.actionName && + action.schematicName === recentAction.schematicName + ) + ) + .filter(action => action !== undefined); + projectActions[nextProject.name] = [ + ...recentActions, + ...(nextProject as any).actions.filter( + (action: ProjectAction) => + action.link !== undefined && !recentActions.includes(action) + ) + ].slice(0, MAX_RECENT_ACTIONS); + return projectActions; + }, + {} + ); + }) + ); } - private createActions(p: any) { + onActionTriggered( + workspacePath: string, + project: Workspace.Projects, + action: ProjectAction + ) { + this.saveRecentActionGQL + .mutate({ + workspacePath: workspacePath, + projectName: project.name, + schematicName: action.schematicName, + actionName: action.name + }) + .subscribe(); + } + + private createActions( + p: Workspace.Projects, + schematicCollections: WorkspaceSchematics.SchematicCollections[] + ) { return [ - ...createLinkForTask(p, 'serve', 'Serve'), - ...createLinkForTask(p, 'test', 'Test'), - ...createLinkForTask(p, 'build', 'Build'), - ...createLinkForTask(p, 'e2e', 'E2E'), - ...createLinkForCoreSchematic(p, 'component', 'Generate Component') - ] as any[]; + { actionDescription: 'Tasks' }, + ...(p.architect || []) + .map(task => { + if (!task) { + return undefined; + } + return createLinkForTask(p, task.name, task.name); + }) + .filter(isDefinedProjectAction), + ...schematicCollections.reduce((links, collection) => { + links.push(...createLinksForCollection(p, collection)); + return links; + }, []) + ]; } trackByName(p: any) { @@ -98,39 +209,69 @@ export class ProjectsComponent implements OnInit { } function createLinkForTask( - project: Project, + project: Workspace.Projects, name: string, actionDescription: string ) { - if (project.architect.find(a => a.name === name)) { - return [{ actionDescription, link: ['../tasks', name, project.name] }]; + if ((project.architect || []).find(a => a !== null && a.name === name)) { + return { actionDescription, name, link: ['../tasks', name, project.name] }; } else { - return []; + return undefined; } } -function createLinkForCoreSchematic( - project: Project, +function createLinksForCollection( + project: Workspace.Projects, + collection: WorkspaceSchematics.SchematicCollections +): ProjectAction[] { + const newLinks = (collection.schematics || []) + .map(schematic => + createLinkForSchematic( + project, + '@schematics/angular', + schematic ? schematic.name : '', + schematic ? schematic.name : '' + ) + ) + .filter(isDefinedProjectAction); + if (newLinks.length > 0) { + newLinks.unshift({ + name: collection.name, + actionDescription: collection.name + }); + } + return newLinks; +} + +function createLinkForSchematic( + project: Workspace.Projects, + schematicName: string, name: string, actionDescription: string -) { +): ProjectAction | undefined { if ( (project.projectType === 'application' || project.projectType === 'library') && - !project.architect.find(a => a.name === 'e2e') + !(project.architect || []).find(a => a !== null && a.name === 'e2e') ) { - return [ - { - actionDescription, - link: [ - '../generate', - decodeURIComponent('@schematics/angular'), - name, - { project: project.name } - ] - } - ]; + return { + name, + schematicName, + actionDescription, + link: [ + '../generate', + decodeURIComponent(schematicName), + name, + { project: project.name } + ] + }; } else { - return []; + return undefined; } } + +function isDefinedProjectAction( + action: ProjectAction | undefined +): action is ProjectAction { + return action !== undefined; +} diff --git a/libs/schema/src/lib/generated/graphql-types.ts b/libs/schema/src/lib/generated/graphql-types.ts index 5c5e623107..ed9537e3fe 100644 --- a/libs/schema/src/lib/generated/graphql-types.ts +++ b/libs/schema/src/lib/generated/graphql-types.ts @@ -158,6 +158,8 @@ export interface Project { projectType: string; architect: Architect[]; + + recentActions: RecentAction[]; } export interface Architect { @@ -178,6 +180,12 @@ export interface ArchitectConfigurations { name: string; } +export interface RecentAction { + actionName: string; + + schematicName?: Maybe; +} + export interface Docs { workspaceDocs: Doc[]; @@ -285,6 +293,8 @@ export interface Mutation { updateSettings: Settings; + saveRecentAction: RecentAction[]; + installNodeJs?: Maybe; openInBrowser?: Maybe; @@ -445,6 +455,15 @@ export interface OpenInEditorMutationArgs { export interface UpdateSettingsMutationArgs { data: string; } +export interface SaveRecentActionMutationArgs { + workspacePath: string; + + projectName: string; + + actionName: string; + + schematicName?: Maybe; +} export interface OpenInBrowserMutationArgs { url: string; } @@ -1072,6 +1091,8 @@ export namespace ProjectResolvers { projectType?: ProjectTypeResolver; architect?: ArchitectResolver; + + recentActions?: RecentActionsResolver; } export type NameResolver = Resolver< @@ -1097,6 +1118,12 @@ export namespace ProjectResolvers { export interface ArchitectArgs { name?: Maybe; } + + export type RecentActionsResolver< + R = any[], + Parent = any, + Context = any + > = Resolver; } export namespace ArchitectResolvers { @@ -1158,6 +1185,25 @@ export namespace ArchitectConfigurationsResolvers { >; } +export namespace RecentActionResolvers { + export interface Resolvers { + actionName?: ActionNameResolver; + + schematicName?: SchematicNameResolver, TypeParent, Context>; + } + + export type ActionNameResolver< + R = string, + Parent = any, + Context = any + > = Resolver; + export type SchematicNameResolver< + R = Maybe, + Parent = any, + Context = any + > = Resolver; +} + export namespace DocsResolvers { export interface Resolvers { workspaceDocs?: WorkspaceDocsResolver; @@ -1486,6 +1532,8 @@ export namespace MutationResolvers { updateSettings?: UpdateSettingsResolver; + saveRecentAction?: SaveRecentActionResolver; + installNodeJs?: InstallNodeJsResolver, TypeParent, Context>; openInBrowser?: OpenInBrowserResolver, TypeParent, Context>; @@ -1631,6 +1679,21 @@ export namespace MutationResolvers { data: string; } + export type SaveRecentActionResolver< + R = any[], + Parent = {}, + Context = any + > = Resolver; + export interface SaveRecentActionArgs { + workspacePath: string; + + projectName: string; + + actionName: string; + + schematicName?: Maybe; + } + export type InstallNodeJsResolver< R = Maybe, Parent = {}, @@ -1834,6 +1897,7 @@ export interface IResolvers { Project?: ProjectResolvers.Resolvers; Architect?: ArchitectResolvers.Resolvers; ArchitectConfigurations?: ArchitectConfigurationsResolvers.Resolvers; + RecentAction?: RecentActionResolvers.Resolvers; Docs?: DocsResolvers.Resolvers; Doc?: DocResolvers.Resolvers; CompletionsTypes?: CompletionsTypesResolvers.Resolvers; diff --git a/libs/server/src/assets/schema.graphql b/libs/server/src/assets/schema.graphql index 8ddf252d04..fc2e244bff 100644 --- a/libs/server/src/assets/schema.graphql +++ b/libs/server/src/assets/schema.graphql @@ -142,6 +142,12 @@ type Mutation { restartCommand(id: String!): RemoveResult openInEditor(editor: String!, path: String!): OpenInEditor updateSettings(data: String!): Settings! + saveRecentAction( + workspacePath: String! + projectName: String! + actionName: String! + schematicName: String + ): [RecentAction!]! installNodeJs: InstallNodeJsStatus openInBrowser(url: String!): OpenInBrowserResult selectDirectory( @@ -173,6 +179,12 @@ type Project { root: String! projectType: String! architect(name: String): [Architect!]! + recentActions: [RecentAction!]! +} + +type RecentAction { + actionName: String! + schematicName: String } type Schematic { diff --git a/libs/server/src/lib/api/read-projects.ts b/libs/server/src/lib/api/read-projects.ts index 2a2bff744e..c8c4478ade 100644 --- a/libs/server/src/lib/api/read-projects.ts +++ b/libs/server/src/lib/api/read-projects.ts @@ -1,15 +1,25 @@ import { normalizeSchema, readJsonFile } from '../utils/utils'; import { Project, Architect } from '@angular-console/schema'; import * as path from 'path'; +import { Store } from '@nrwl/angular-console-enterprise-electron'; +import { readRecentActions } from './read-recent-actions'; -export function readProjects(json: any): Project[] { +export function readProjects( + json: any, + baseDir: string, + store: Store +): Project[] { return Object.entries(json) .map(([key, value]: [string, any]) => { return { name: key, root: value.root, projectType: value.projectType, - architect: readArchitect(key, value.architect) + architect: readArchitect(key, value.architect), + recentActions: readRecentActions( + store, + path.join(baseDir, value.root, key) + ) }; }) .sort(compareProjects); diff --git a/libs/server/src/lib/api/read-recent-actions.ts b/libs/server/src/lib/api/read-recent-actions.ts new file mode 100644 index 0000000000..9481c5921e --- /dev/null +++ b/libs/server/src/lib/api/read-recent-actions.ts @@ -0,0 +1,35 @@ +import { Store } from '@nrwl/angular-console-enterprise-electron'; +import { RecentAction } from '@angular-console/schema'; + +function getRecentActionsKey(projectPath: string): string { + return `recentActions:${projectPath}`; +} + +export function readRecentActions( + store: Store, + projectPath: string +): RecentAction[] { + const actions: any[] = store.get(getRecentActionsKey(projectPath)); + return (actions || []).filter(action => action && !!action.actionName); +} + +export function storeTriggeredAction( + store: Store, + projectPath: string, + actionName: string, + schematicName?: string +) { + const MAX_RECENT_ACTIONS = 5; + const existingActions = readRecentActions(store, projectPath); + store.set( + getRecentActionsKey(projectPath), + [ + { actionName, schematicName }, + ...existingActions.filter( + action => + action.actionName !== actionName || + action.schematicName !== schematicName + ) + ].slice(0, MAX_RECENT_ACTIONS) + ); +} diff --git a/libs/server/src/lib/api/read-settings.ts b/libs/server/src/lib/api/read-settings.ts index dcfe7add21..5abde02f60 100644 --- a/libs/server/src/lib/api/read-settings.ts +++ b/libs/server/src/lib/api/read-settings.ts @@ -2,9 +2,9 @@ import { Store } from '@nrwl/angular-console-enterprise-electron'; import { Settings } from '@angular-console/schema'; import { Subject } from 'rxjs'; -/* tslint:disable */ export function readSettings(store: Store): Settings { const settings: Settings = store.get('settings') || {}; + // tslint:disable-next-line if (settings.canCollectData === undefined) { settings.canCollectData = store.get('canCollectData', false); } diff --git a/libs/server/src/lib/resolvers/mutation.resolver.ts b/libs/server/src/lib/resolvers/mutation.resolver.ts index 1c7460c3cd..47b558d6da 100644 --- a/libs/server/src/lib/resolvers/mutation.resolver.ts +++ b/libs/server/src/lib/resolvers/mutation.resolver.ts @@ -11,6 +11,10 @@ import { commands, runCommand } from '../api/run-command'; import { SelectDirectory } from '../types'; import { findClosestNg, findExecutable, readJsonFile } from '../utils/utils'; import { platform } from 'os'; +import { + storeTriggeredAction, + readRecentActions +} from '../api/read-recent-actions'; function disableInteractivePrompts(p: string) { try { @@ -289,6 +293,18 @@ export class MutationResolver { return readSettings(this.store); } + @Mutation() + saveRecentAction( + @Args('workspacePath') workspacePath: string, + @Args('projectName') projectName: string, + @Args('actionName') actionName: string, + @Args('schematicName') schematicName: string + ) { + const key = `${workspacePath}/${projectName}`; + storeTriggeredAction(this.store, key, actionName, schematicName); + return readRecentActions(this.store, key); + } + @Mutation() async openDoc(@Args('id') id: string) { const result = await docs.openDoc(id).toPromise(); diff --git a/libs/server/src/lib/resolvers/query.resolver.ts b/libs/server/src/lib/resolvers/query.resolver.ts index 5ab1cc0fb1..c4ed6f9dd8 100644 --- a/libs/server/src/lib/resolvers/query.resolver.ts +++ b/libs/server/src/lib/resolvers/query.resolver.ts @@ -66,7 +66,7 @@ export class QueryResolver { path: p, dependencies: readDependencies(packageJson), extensions: readExtensions(packageJson), - projects: readProjects(angularJson.projects), + projects: readProjects(angularJson.projects, p, this.store), npmScripts: readNpmScripts(p, packageJson), docs: {} as any, schematicCollections: [] as any From 2baa60580818501d4a5909810053d6001023581f Mon Sep 17 00:00:00 2001 From: Isaac Mann Date: Wed, 20 Feb 2019 14:11:07 -0500 Subject: [PATCH 2/4] fix lint errors --- .../feature-workspaces/src/lib/projects/projects.component.ts | 4 ++-- libs/server/src/lib/api/read-settings.ts | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libs/feature-workspaces/src/lib/projects/projects.component.ts b/libs/feature-workspaces/src/lib/projects/projects.component.ts index 78ee8b00fe..942f818b29 100644 --- a/libs/feature-workspaces/src/lib/projects/projects.component.ts +++ b/libs/feature-workspaces/src/lib/projects/projects.component.ts @@ -213,7 +213,7 @@ function createLinkForTask( name: string, actionDescription: string ) { - if ((project.architect || []).find(a => a !== null && a.name === name)) { + if ((project.architect || []).find(a => a.name === name)) { return { actionDescription, name, link: ['../tasks', name, project.name] }; } else { return undefined; @@ -252,7 +252,7 @@ function createLinkForSchematic( if ( (project.projectType === 'application' || project.projectType === 'library') && - !(project.architect || []).find(a => a !== null && a.name === 'e2e') + !(project.architect || []).find(a => a.name === 'e2e') ) { return { name, diff --git a/libs/server/src/lib/api/read-settings.ts b/libs/server/src/lib/api/read-settings.ts index 5abde02f60..c660da21a1 100644 --- a/libs/server/src/lib/api/read-settings.ts +++ b/libs/server/src/lib/api/read-settings.ts @@ -8,6 +8,7 @@ export function readSettings(store: Store): Settings { if (settings.canCollectData === undefined) { settings.canCollectData = store.get('canCollectData', false); } + // tslint:disable-next-line if (settings.recent === undefined) { settings.recent = []; } From 740c503cc34ce8e4c963bf5f5859353738006536 Mon Sep 17 00:00:00 2001 From: Isaac Mann Date: Thu, 28 Feb 2019 09:32:51 -0500 Subject: [PATCH 3/4] chore: Fix lint error --- .../feature-workspaces/src/lib/projects/projects.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/feature-workspaces/src/lib/projects/projects.component.ts b/libs/feature-workspaces/src/lib/projects/projects.component.ts index 59bac9a201..74d08b7b6e 100644 --- a/libs/feature-workspaces/src/lib/projects/projects.component.ts +++ b/libs/feature-workspaces/src/lib/projects/projects.component.ts @@ -7,9 +7,9 @@ import { switchMap, shareReplay, filter, - catchError + catchError, + tap } from 'rxjs/operators'; -import { tap } from 'rxjs/operators'; import { PROJECTS_POLLING, Settings, From 997cef19e9c1fcd2bd1fa1cfb785515dcf7bd295 Mon Sep 17 00:00:00 2001 From: Isaac Mann Date: Tue, 5 Mar 2019 15:25:53 -0500 Subject: [PATCH 4/4] fix: e2e test --- apps/angular-console-e2e/src/integration/projects.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/angular-console-e2e/src/integration/projects.spec.ts b/apps/angular-console-e2e/src/integration/projects.spec.ts index b28ad56c46..de85744c45 100644 --- a/apps/angular-console-e2e/src/integration/projects.spec.ts +++ b/apps/angular-console-e2e/src/integration/projects.spec.ts @@ -59,7 +59,7 @@ describe('Projects', () => { cy.contains('angular-console-projects button', 'Extract-i18n') .first() .click(); - cy.contains('div.context-title', 'ng extract-i18n proj'); + cy.contains('div.context-title', 'ng run proj:extract-i18n'); cy.get('.exit-action').click(); cy.contains('angular-console-projects button', 'Test') .first()