diff --git a/scilog/src/app/app.module.ts b/scilog/src/app/app.module.ts index 012b1d51..1f854d15 100644 --- a/scilog/src/app/app.module.ts +++ b/scilog/src/app/app.module.ts @@ -4,32 +4,32 @@ import { APP_INITIALIZER, NgModule } from "@angular/core"; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { SnippetComponent } from '@shared/snippet/snippet.component'; -import {MatButtonModule} from '@angular/material/button'; -import {MatCardModule} from '@angular/material/card'; -import {MatDialogModule} from '@angular/material/dialog'; -import {MatExpansionModule} from '@angular/material/expansion'; -import {MatIconModule} from '@angular/material/icon'; -import {MatProgressSpinnerModule} from '@angular/material/progress-spinner'; -import {MatSidenavModule} from '@angular/material/sidenav'; -import {BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import {ScrollingModule as ExperimentalScrollingModule} from '@angular/cdk-experimental/scrolling'; -import {DragDropModule} from '@angular/cdk/drag-drop'; -import {ScrollingModule} from '@angular/cdk/scrolling'; -import {HttpClientModule} from '@angular/common/http'; -import {CKEditorModule} from '@ckeditor/ckeditor5-angular'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCardModule } from '@angular/material/card'; +import { MatDialogModule } from '@angular/material/dialog'; +import { MatExpansionModule } from '@angular/material/expansion'; +import { MatIconModule } from '@angular/material/icon'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { MatSidenavModule } from '@angular/material/sidenav'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { ScrollingModule as ExperimentalScrollingModule } from '@angular/cdk-experimental/scrolling'; +import { DragDropModule } from '@angular/cdk/drag-drop'; +import { ScrollingModule } from '@angular/cdk/scrolling'; +import { HttpClientModule } from '@angular/common/http'; +import { CKEditorModule } from '@ckeditor/ckeditor5-angular'; import { AddContentComponent } from '@shared/add-content/add-content.component'; -import {MatMenuModule} from '@angular/material/menu'; -import {MatChipsModule} from '@angular/material/chips'; -import {MatFormFieldModule} from '@angular/material/form-field'; -import {MatToolbarModule} from '@angular/material/toolbar'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatChipsModule } from '@angular/material/chips'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatToolbarModule } from '@angular/material/toolbar'; import { SnippetTableComponent } from '@shared/snippet/snippet-table/snippet-table.component' -import {MatTableModule} from '@angular/material/table'; -import {MatButtonToggleModule} from '@angular/material/button-toggle'; -import {GridsterModule} from 'angular-gridster2'; +import { MatTableModule } from '@angular/material/table'; +import { MatButtonToggleModule } from '@angular/material/button-toggle'; +import { GridsterModule } from 'angular-gridster2'; import { DashboardItemComponent } from './logbook/dashboard/dashboard-item/dashboard-item.component'; import { LogbookItemComponent } from './logbook/widgets/logbook-item/logbook-item.component'; -import {MatDividerModule} from '@angular/material/divider'; -import {MatBadgeModule} from '@angular/material/badge'; +import { MatDividerModule } from '@angular/material/divider'; +import { MatBadgeModule } from '@angular/material/badge'; import { DashboardComponent } from './logbook/dashboard/dashboard.component'; import { ChatComponent } from './logbook/widgets/chat/chat.component'; import { TodosComponent } from './logbook/widgets/todos/todos.component'; @@ -39,53 +39,54 @@ import { OverviewComponent } from './overview/overview.component'; import { LogbookComponent } from './logbook/logbook.component'; import { LogbookWidgetComponent } from './overview/logbook-cover/logbook-cover.component'; import { ViewWidgetComponent } from './overview/view-widget/view-widget.component'; -import {FormsModule, ReactiveFormsModule} from '@angular/forms'; -import {MatInputModule} from '@angular/material/input'; -import {AuthInterceptor} from '@shared/auth-services/auth.interceptor'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { MatInputModule } from '@angular/material/input'; +import { AuthInterceptor } from '@shared/auth-services/auth.interceptor'; import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { ToolbarComponent } from '@shared/toolbar/toolbar.component'; import { ChartsModule } from 'ng2-charts'; -import {MatTooltipModule} from '@angular/material/tooltip'; -import { WidgetPreferencesComponent } from './logbook/widgets/widget-preferences/widget-preferences.component'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { WidgetPreferencesComponent } from './logbook/widgets/widget-preferences/widget-preferences.component'; import { MatSelectModule } from '@angular/material/select'; -import {MatRadioModule} from '@angular/material/radio'; -import {MatCheckboxModule} from '@angular/material/checkbox'; +import { MatRadioModule } from '@angular/material/radio'; +import { MatCheckboxModule } from '@angular/material/checkbox'; import { SettingsComponent } from '@shared/settings/settings.component'; -import { CollectionWidgetComponent } from './overview/collection-widget/collection-widget.component'; +import { CollectionWidgetComponent } from './overview/collection-widget/collection-widget.component'; import { AuthService } from '@shared/auth-services/auth.service'; import { Router } from '@angular/router'; import { AddLogbookComponent } from './overview/add-logbook/add-logbook.component'; import { AddCollectionComponent } from './overview/add-collection/add-collection.component'; -import {MatSlideToggleModule} from '@angular/material/slide-toggle'; -import {MatAutocompleteModule} from '@angular/material/autocomplete'; +import { MatSlideToggleModule } from '@angular/material/slide-toggle'; +import { MatAutocompleteModule } from '@angular/material/autocomplete'; import { LogbookSearchPipe } from './overview/logbook-search.pipe'; -import { NavigationButtonComponent } from './logbook/navigation-button/navigation-button.component'; +import { NavigationButtonComponent } from './logbook/navigation-button/navigation-button.component'; import { AngularResizeEventModule } from 'angular-resize-event'; import { SnippetContentComponent } from '@shared/snippet/snippet-content/snippet-content.component'; -import {CookieService} from 'ngx-cookie-service'; +import { CookieService } from 'ngx-cookie-service'; import { NgxJdenticonModule, JDENTICON_CONFIG } from 'ngx-jdenticon'; import { SnippetViewerComponent } from './logbook/widgets/snippet-viewer/snippet-viewer.component'; import { SnippetDashboardNameComponent } from '@shared/snippet/snippet-dashboard-name/snippet-dashboard-name.component'; import { ViewSettingsComponent } from '@shared/settings/view-settings/view-settings.component'; import { ProfileSettingsComponent } from '@shared/settings/profile-settings/profile-settings.component'; import { ViewEditComponent } from '@shared/settings/view-settings/view-edit/view-edit.component'; -import {MatTabsModule} from '@angular/material/tabs'; +import { MatTabsModule } from '@angular/material/tabs'; import { TagEditorComponent } from '@shared/tag-editor/tag-editor.component'; import { SnippetInfoComponent } from '@shared/snippet/snippet-info/snippet-info.component'; -import { SnippetInfoSectionComponent } from '@shared/snippet/snippet-info/snippet-info-section/snippet-info-section.component'; +import { SnippetInfoSectionComponent } from '@shared/snippet/snippet-info/snippet-info-section/snippet-info-section.component'; import { UiScrollModule } from 'ngx-ui-scroll'; import { HotkeysComponent } from '@shared/hotkeys/hotkeys.component'; import { ExportDialogComponent } from './logbook/dashboard/dashboard-item/export-dialog/export-dialog.component'; -import {MatProgressBarModule} from '@angular/material/progress-bar'; -import {MatSnackBarModule} from '@angular/material/snack-bar'; +import { MatProgressBarModule } from '@angular/material/progress-bar'; +import { MatSnackBarModule } from '@angular/material/snack-bar'; import { DownloadComponent } from '@shared/download/download.component'; import { SearchComponent } from '@shared/search/search.component'; import { SearchWindowComponent } from '@shared/search-window/search-window.component'; import { AppConfigService } from "./app-config.service"; import { NavigationGuardService } from './logbook/core/navigation-guard-service'; +import { TaskComponent } from './logbook/core/task/task.component'; const appConfigInitializerFn = (appConfig: AppConfigService) => { - return () => appConfig.loadAppConfig(); + return () => appConfig.loadAppConfig(); }; @NgModule({ @@ -127,6 +128,7 @@ const appConfigInitializerFn = (appConfig: AppConfigService) => { DownloadComponent, SearchComponent, SearchWindowComponent, + TaskComponent ], imports: [ BrowserModule, diff --git a/scilog/src/app/logbook/core/task/task.component.html b/scilog/src/app/logbook/core/task/task.component.html new file mode 100644 index 00000000..5177f27b --- /dev/null +++ b/scilog/src/app/logbook/core/task/task.component.html @@ -0,0 +1,24 @@ +
+ + + +
+ +
+
+ + {{ task.content }} + + + + + +
+
+
diff --git a/scilog/src/app/logbook/core/task/task.component.scss b/scilog/src/app/logbook/core/task/task.component.scss new file mode 100644 index 00000000..f2e351b2 --- /dev/null +++ b/scilog/src/app/logbook/core/task/task.component.scss @@ -0,0 +1,33 @@ + +.task-mat-card{ + margin-bottom: 1px; + margin-left: 20px; + margin-right: 20px; + margin-top: 1px; + min-height: 100%; + text-align: left; + border-radius: 5px; + padding: 4px 0px; + box-shadow: 0 1px 4px 0 rgba(0, 0, 0, .2), 0 2px 8px 0 rgba(0, 0, 0, .14), 0 4px 8px -1px rgba(0, 0, 0, .12); + // background-color: var(--sidenav-color); + color: var(--default-text-color); + +} + + +.task-content{ + display: flex; + align-items: center; + max-width: 100%; + padding-left: 15px; + padding-right: 5px; +} + +.task-text { + padding-left: 20px; + padding-right: 10px; +} + +.flexExpand { + flex: 1 1 auto; +} diff --git a/scilog/src/app/logbook/core/task/task.component.spec.ts b/scilog/src/app/logbook/core/task/task.component.spec.ts new file mode 100644 index 00000000..a83fc37a --- /dev/null +++ b/scilog/src/app/logbook/core/task/task.component.spec.ts @@ -0,0 +1,68 @@ +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; +import { TaskComponent } from "./task.component"; +import { HttpClientTestingModule } from "@angular/common/http/testing"; +import { AppConfigService } from "src/app/app-config.service"; +import { Tasks } from "src/app/core/model/tasks"; + +const getConfig = () => ({}); + +describe('TaskComponent', () => { + let component: TaskComponent; + let fixture: ComponentFixture; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + providers: [ + { provide: AppConfigService, useValue: { getConfig } }, + ], + declarations: [TaskComponent] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TaskComponent); + component = fixture.componentInstance; + component.task = {isDone: false, id: '123'} as Tasks; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should addTask', () => { + const addTaskSpy = spyOn(component['tasksService'], 'addTask'); + const task = {isDone: false} as Tasks; + component.addTask(task); + expect(addTaskSpy).toHaveBeenCalledOnceWith(task); + }); + + it('should toggleTaskIsDone', () => { + const updateTaskSpy = spyOn(component['tasksService'], 'updateTask'); + component.toggleTaskIsDone(); + expect(updateTaskSpy).toHaveBeenCalledOnceWith({isDone: true}, '123'); + }); + + it('should deleteTask', () => { + const deleteTaskSpy = spyOn(component['tasksService'], 'deleteTask'); + component.deleteTask(); + expect(deleteTaskSpy).toHaveBeenCalledOnceWith('123'); + }); + + it('should deleteTask', () => { + const deleteTaskSpy = spyOn(component['tasksService'], 'deleteTask'); + component.deleteTask(); + expect(deleteTaskSpy).toHaveBeenCalledOnceWith('123'); + }); + + it('should isAllowed', () => { + const canUpdateSpy = spyOn(component['isActionAllowed'], 'canUpdate'); + const canDeleteSpy = spyOn(component['isActionAllowed'], 'canDelete'); + component.isAllowed(); + expect(canUpdateSpy).toHaveBeenCalledTimes(1); + expect(canDeleteSpy).toHaveBeenCalledTimes(1); + }); + + }); diff --git a/scilog/src/app/logbook/core/task/task.component.ts b/scilog/src/app/logbook/core/task/task.component.ts new file mode 100644 index 00000000..56d17540 --- /dev/null +++ b/scilog/src/app/logbook/core/task/task.component.ts @@ -0,0 +1,49 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { Tasks } from '@model/tasks'; +import { TasksService } from '@shared/tasks.service'; +import { IsAllowedService } from 'src/app/overview/is-allowed.service'; + +@Component({ + selector: 'task', + templateUrl: './task.component.html', + styleUrls: ['./task.component.scss'], + providers: [IsAllowedService], +}) +export class TaskComponent implements OnInit { + + @Input() + task: Tasks; + + constructor( + private tasksService: TasksService, + protected isActionAllowed: IsAllowedService) { + console.log("constructor called") + } + + ngOnInit(): void { + this.isActionAllowed.snippet = this.task; + this.isAllowed(); + } + + addTask(task: Tasks) { + this.tasksService.addTask(task); + } + + toggleTaskIsDone() { + let payload = { + isDone: !this.task.isDone + } + this.tasksService.updateTask(payload, this.task.id); + } + + deleteTask() { + console.log("deleting task"); + this.tasksService.deleteTask(this.task.id); + } + + isAllowed() { + this.isActionAllowed.canDelete(); + this.isActionAllowed.canUpdate(); + } + +} diff --git a/scilog/src/app/logbook/widgets/todos/todos.component.html b/scilog/src/app/logbook/widgets/todos/todos.component.html index 69e0afbc..402cf6a9 100644 --- a/scilog/src/app/logbook/widgets/todos/todos.component.html +++ b/scilog/src/app/logbook/widgets/todos/todos.component.html @@ -3,53 +3,11 @@ {{numTasks}} {{tasks.length == 1 ? 'item' : 'items'}} left - +
-
- - - -
- -
-
- - {{ task.content }} - - - - - - - -
-
-
+
+ +
- - - - \ No newline at end of file diff --git a/scilog/src/app/logbook/widgets/todos/todos.component.scss b/scilog/src/app/logbook/widgets/todos/todos.component.scss index 47fc8913..9b2b9852 100644 --- a/scilog/src/app/logbook/widgets/todos/todos.component.scss +++ b/scilog/src/app/logbook/widgets/todos/todos.component.scss @@ -2,10 +2,6 @@ text-align: right; } -/* .new-task{ - padding: 1px; -} */ - .add-task{ padding-left: 20px; } @@ -28,27 +24,3 @@ ::ng-deep .mat-checkbox-checked.mat-accent .mat-checkbox-background { background-color: var(--button-accent); } - - -.task-content{ - display: flex; - align-items: center; - max-width: 100%; - padding-left: 15px; - padding-right: 5px; -} - -.task-text { - padding-left: 20px; - padding-right: 10px; -} - -.task-container { - overflow-y: scroll; - height: calc(100% - 150px); -} - -.flexExpand { - flex: 1 1 auto; - } - \ No newline at end of file diff --git a/scilog/src/app/logbook/widgets/todos/todos.component.ts b/scilog/src/app/logbook/widgets/todos/todos.component.ts index 691b5952..ab20971b 100644 --- a/scilog/src/app/logbook/widgets/todos/todos.component.ts +++ b/scilog/src/app/logbook/widgets/todos/todos.component.ts @@ -1,11 +1,11 @@ -import { Component, Input, OnInit } from '@angular/core'; -import { UntypedFormControl } from '@angular/forms'; +import { Component, Input, OnInit, ViewChild } from '@angular/core'; import { Tasks } from '@model/tasks'; import { TasksService } from '@shared/tasks.service'; import { LogbookInfoService } from '@shared/logbook-info.service'; import { ChangeStreamService } from '@shared/change-stream.service'; import { Subscription } from 'rxjs'; import { ViewsService } from '@shared/views.service'; +import { TaskComponent } from '../../core/task/task.component'; @Component({ selector: 'todos', @@ -16,9 +16,10 @@ export class TodosComponent implements OnInit { @Input() configIndex: number; + @ViewChild(TaskComponent) taskComponent: TaskComponent; tasks: Tasks[] = []; - newTask = new UntypedFormControl(''); + newTask = ''; numTasks: number = 0; subscriptions: Subscription[] = []; @@ -56,8 +57,6 @@ export class TodosComponent implements OnInit { } - - addTasks() { let newTask: Tasks = { ownerGroup: this.logbookInfo.logbookInfo.ownerGroup, @@ -65,26 +64,12 @@ export class TodosComponent implements OnInit { isPrivate: this.logbookInfo.logbookInfo.isPrivate, parentId: this.logbookInfo.logbookInfo.id, snippetType: "task", - content: this.newTask.value, + content: this.newTask, isDone: false }; console.log("adding new task") - - this.tasksService.addTask(newTask); - this.newTask.setValue(''); - - } - - toggleTaskIsDone(id: number) { - let payload = { - isDone: !this.tasks[id].isDone - } - this.tasksService.updateTask(payload, this.tasks[id].id); - } - - deleteTask(id: number) { - console.log("deleting task", id); - this.tasksService.deleteTask(this.tasks[id].id); + this.taskComponent.addTask(newTask); + this.newTask = ''; } ngOnDestroy(): void {