Skip to content

Commit

Permalink
feat(workflows): create workflow page
Browse files Browse the repository at this point in the history
  • Loading branch information
Xaviju committed Sep 19, 2023
1 parent a621b89 commit c993ca4
Show file tree
Hide file tree
Showing 10 changed files with 213 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const KanbanActions = createActionGroup({
events: {
'Init Kanban': props<{ workflow: Workflow['slug'] }>(),
'Load Workflow kanban': props<{ workflow: Workflow['slug'] }>(),
'Create Workflow': props<{ name: Workflow['name'] }>(),
'Open Create Story form': props<{ status: Status['id'] }>(),
'Close Create Story form': emptyProps(),
'Create Story': props<{
Expand Down Expand Up @@ -127,6 +128,10 @@ export const KanbanApiActions = createActionGroup({
offset: number;
complete: boolean;
}>(),
'Create Workflow Success': props<{
workflow: Workflow;
}>(),
'create Workflow Error': emptyProps(),
'Create Story Success': props<{
story: Story;
tmpId: PartialStory['tmpId'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import { HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { TranslocoService } from '@ngneat/transloco';
import { Actions, concatLatestFrom, createEffect, ofType } from '@ngrx/effects';
import {
Expand Down Expand Up @@ -96,6 +97,42 @@ export class KanbanEffects {
);
});

public createWorkflow$ = createEffect(() => {
return this.actions$.pipe(
ofType(KanbanActions.createWorkflow),
concatLatestFrom(() => [
this.store.select(selectCurrentProject).pipe(filterNil()),
]),
pessimisticUpdate({
run: (workflow, project) => {
return this.projectApiService
.createWorkflow(workflow.name, project.id)
.pipe(
map((newWorkflow) => {
console.log({ newWorkflow });
void this.router.navigate([
'/project',
project.id,
project.slug,
newWorkflow.slug,
]);
return KanbanApiActions.createWorkflowSuccess({
workflow: newWorkflow,
});
})
);
},
onError: (action, httpResponse: HttpErrorResponse) => {
if (httpResponse.status !== 403) {
this.appService.errorManagement(httpResponse);
}

return KanbanApiActions.createWorkflowError();
},
})
);
});

public createStory$ = createEffect(() => {
return this.actions$.pipe(
ofType(KanbanActions.createStory),
Expand Down Expand Up @@ -480,6 +517,7 @@ export class KanbanEffects {
private actions$: Actions,
private store: Store,
private projectApiService: ProjectApiService,
private router: Router,
private kanbanScrollManagerService: KanbanScrollManagerService,
private translocoService: TranslocoService
) {}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
Copyright (c) 2023-present Kaleidos INC
*/
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,55 @@
Copyright (c) 2023-present Kaleidos INC
-->

<div>New workflow form</div>
<ng-container *transloco="let t">
<form
class="new-workflow-form-card"
#form="ngForm"
[showFormErrors]="submitted"
[formGroup]="newWorkflowForm"
(submit)="submitCreateWorkflow()">
<div class="content">
<tg-ui-input class="workflow-input">
<input
tgAutoFocus
[attr.aria-label]="t('kanban.create_workflow.workflow_name_aria')"
formControlName="name"
data-test="create-workflow-input"
[maxlength]="workflowNameMaxLength"
#statusInput
inputRef
[placeholder]="t('kanban.create_workflow.write_workflow_name')" />
<ng-container inputError>
<tg-ui-error error="required">
{{ t('kanban.create_workflow.workflow_empty') }}
</tg-ui-error>
</ng-container>
</tg-ui-input>
</div>
<div
*ngIf="
newWorkflowForm.get('name')!.value?.length! >= workflowNameMaxLength
"
class="max-length">
{{ t('form_errors.max_length') }}
</div>

<div class="actions">
<button
tuiButton
data-test="status-create"
appearance="primary"
type="submit">
{{ t('kanban.create_workflow.save') }}
</button>
<button
(click)="cancelEdit()"
data-test="cancel-edit-status"
tuiButton
type="button"
appearance="tertiary">
{{ t('commons.cancel') }}
</button>
</div>
</form>
</ng-container>
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,79 @@
* Copyright (c) 2023-present Kaleidos INC
*/

import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import {
ChangeDetectionStrategy,
Component,
EventEmitter,
OnInit,
Output,
} from '@angular/core';
import {
FormBuilder,
FormGroup,
ReactiveFormsModule,
Validators,
} from '@angular/forms';
import { TranslocoDirective } from '@ngneat/transloco';
import { TuiButtonModule } from '@taiga-ui/core';
import { Workflow } from '@taiga/data';
import { InputsModule } from '@taiga/ui/inputs';

@Component({
selector: 'tg-new-workflow-form',
templateUrl: './new-workflow-form.component.html',
styleUrls: ['./new-workflow-form.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [
CommonModule,
TranslocoDirective,
ReactiveFormsModule,
InputsModule,
TuiButtonModule,
],
})
export class NewWorkflowFormComponent implements OnInit {
@Output()
public createWorkflow = new EventEmitter<Workflow['name']>();

@Output()
public cancelCreateWorkflow = new EventEmitter();

public newWorkflowForm!: FormGroup;

public workflowNameMaxLength = 40;
public submitted = false;

constructor(private fb: FormBuilder) {}

public ngOnInit() {
console.log('new workflow form');
this.initForm();
}

public initForm() {
this.newWorkflowForm = this.fb.group({
name: [
'',
[
Validators.required,
Validators.maxLength(this.workflowNameMaxLength),
//avoid only white spaces
Validators.pattern(/^(\s+\S+\s*)*(?!\s).*$/),
],
],
});
}

public submitCreateWorkflow() {
this.submitted = true;
const workflowName = this.newWorkflowForm.get('name')
?.value as Workflow['name'];
this.createWorkflow.emit(workflowName);
}

public cancelEdit() {
this.cancelCreateWorkflow.emit();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@
-->

<div>New Kanban Works!</div>
<tg-new-workflow-form></tg-new-workflow-form>
<tg-new-workflow-form
(createWorkflow)="createWorkflow($event)"
(cancelCreateWorkflow)="cancelCreateWorkflow()"></tg-new-workflow-form>
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
* Copyright (c) 2023-present Kaleidos INC
*/

import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { Workflow } from '@taiga/data';
import { KanbanActions } from '../feature-kanban/data-access/+state/actions/kanban.actions';
import { NewWorkflowFormComponent } from './components/new-workflow-form/new-workflow-form.component';

@Component({
Expand All @@ -17,8 +20,19 @@ import { NewWorkflowFormComponent } from './components/new-workflow-form/new-wor
standalone: true,
imports: [NewWorkflowFormComponent],
})
export class ProjectFeatureNewWorkflowComponent implements OnInit {
public ngOnInit(): void {
console.log('ProjectFeatureNewWorkflowComponent works!');
export class ProjectFeatureNewWorkflowComponent {
constructor(private store: Store) {}

public createWorkflow(workflow: Workflow['name']) {
console.log({ workflow });
this.store.dispatch(
KanbanActions.createWorkflow({
name: workflow,
})
);
}

public cancelCreateWorkflow() {
console.log('routelink to main');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,18 @@

import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { TRANSLOCO_SCOPE } from '@ngneat/transloco';
import { ProjectFeatureNewWorkflowRoutingModule } from './project-feature-new-workflow-routing.module';

@NgModule({
imports: [CommonModule, ProjectFeatureNewWorkflowRoutingModule],
declarations: [],
providers: [],
providers: [
{
provide: TRANSLOCO_SCOPE,
useValue: 'kanban',
},
],
exports: [],
})
export class ProjectFeatureNewWorkflowModule {}
8 changes: 7 additions & 1 deletion javascript/apps/taiga/src/assets/i18n/kanban/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,11 @@
"delete_stories": "Delete the stories too",
"stories_placed_below": "The stories will be placed below the existing ones.",
"status": "Status"
},
"create_workflow": {
"save": "Create Workflow",
"workflow_name_aria": "Workflow name (Maximum 40 Characters only)",
"write_workflow_name": "Write a workflow name",
"workflow_empty": "Workflow name can’t be empty."
}
}
}
12 changes: 12 additions & 0 deletions javascript/libs/api/src/lib/project/project-api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,18 @@ export class ProjectApiService {
);
}

public createWorkflow(
workflow: Workflow['name'],
project: Project['id']
): Observable<Workflow> {
return this.http.post<Workflow>(
`${this.config.apiUrl}/projects/${project}/workflows`,
{
name: workflow,
}
);
}

public updateInvitationRole(
id: string,
userData: { id: string; roleSlug: string }
Expand Down

0 comments on commit c993ca4

Please sign in to comment.