Add disucssion export into tsv, minor fixes

This commit is contained in:
Michał Romaszkin 2021-01-17 13:54:53 +01:00
parent 8af2a4d192
commit 250ecc8eb7
39 changed files with 538 additions and 773 deletions

View File

@ -42,3 +42,9 @@ export const removeCategoryFromDimension = createAction(
'[Dimension] Remove Category From Dimension',
props<{ id: any }>()
);
export const removeSelectedDimension = createAction(
'[Dimension] Remove Selected Dimension'
);
export const removeSelectedDimensionSuccess = createAction(
'[Dimension] Remove Selected Dimension Success'
);

View File

@ -8,6 +8,9 @@ export const discussionLoadSuccess = createAction(
'[DiscussionChooser] Load Discussions Success',
props<{ discussions: any }>()
);
export const loadDimensions = createAction(
'[DiscussionChooser] Load Available Dimensions'
);
export const availableDimensionsLoadSuccess = createAction(
'[DiscussionChooser] Load Available Dimensions Success',
props<{ dimensions: Array<Dimension> }>()

View File

@ -43,3 +43,13 @@ export const updateCategory = createAction(
export const updateCategorySuccess = createAction(
'[DiscussionViewer] Update Paragraph Category Success'
);
export const exportFile = createAction('[DiscussionViewer] Export File');
export const exportFileSuccess = createAction(
'[DiscussionViewer] Export File Success'
);
export const exportFileFailure = createAction(
'[DiscussionViewer] Export File Failure'
);

View File

@ -8,12 +8,6 @@ const routes: Routes = [
path: '',
component: FrontPageComponent,
},
{
path: 'view',
canActivate: [AuthGuard],
loadChildren: () =>
import('./main-view/main-view.module').then((m) => m.MainViewModule),
},
{
path: 'auth',
loadChildren: () => import('./auth/auth.module').then((m) => m.AuthModule),

View File

@ -18,6 +18,8 @@ import {
updateSelectedDimension,
updateSelectedDimensionSuccess,
removeCategoryFromDimension,
removeSelectedDimension,
removeSelectedDimensionSuccess,
} from '../actions/dimension.actions';
import { addDimensionToFile } from '../actions/discussion-chooser.actions';
import { DimensionsService } from '../services/dimensions.service';
@ -28,13 +30,15 @@ import {
selectCurrentDimension,
selectDimension,
} from '../selectors/dimension.selectors';
import { NbToastrService } from '@nebular/theme';
@Injectable()
export class DimmensionEffects {
constructor(
private actions$: Actions,
private dimensionService: DimensionsService,
private store$: Store<State>
private store$: Store<State>,
private toastService: NbToastrService
) {}
getDimmensions$ = createEffect(() =>
@ -130,4 +134,22 @@ export class DimmensionEffects {
),
{ dispatch: false }
);
removeSelectedDimension = createEffect(() =>
this.actions$.pipe(
ofType(removeSelectedDimension),
withLatestFrom(this.store$.select(selectDimension)),
flatMap(([_, id]) => {
this.store$.dispatch(removeDimension({ id: id! }));
return this.dimensionService.removeDimension(id!).pipe(
map(() => {
this.toastService.info('', 'Pomyślnie usnięto wymiar', {
icon: 'checkmark-outline',
});
return removeSelectedDimensionSuccess();
})
);
})
)
);
}

View File

@ -8,6 +8,7 @@ import {
bindClassifier,
bindClassifierSuccess,
setBindClassifierLoading,
loadDimensions,
} from '../actions/discussion-chooser.actions';
import {
catchError,
@ -17,7 +18,7 @@ import {
tap,
withLatestFrom,
} from 'rxjs/operators';
import { EMPTY, forkJoin, of } from 'rxjs';
import { EMPTY, forkJoin, of, throwError } from 'rxjs';
import { map } from 'rxjs/operators';
import { selectRouteParam, State as AppState } from '../reducers';
import { GetDiscussionService } from '../services/get-discussion.service';
@ -55,34 +56,50 @@ export class DiscussionChooserEffects {
)
);
$loadDimensions = createEffect(() =>
this.actions$.pipe(
ofType(loadDimensions),
withLatestFrom(this.store$.select(selectRouteParam('id'))),
flatMap(([_, id]) =>
this.discussionService.getDiscussionDimensions(parseInt(id!)).pipe(
map((res) =>
availableDimensionsLoadSuccess({ dimensions: res.data })
),
catchError((error) => throwError(error))
)
)
)
);
$bind = createEffect(() =>
this.actions$.pipe(
ofType(bindClassifier),
withLatestFrom(
this.store$.select((state) => state.dataState.data?.discussions)
),
flatMap(([action, data]) =>
flatMap(([_, data]) =>
forkJoin(
data?.map((el) => this.discussionService.bindClassfier(el.id))
).pipe(
map(() => bindClassifierSuccess()),
catchError((err) => EMPTY)
catchError(() => EMPTY)
)
)
)
);
$bindSuccess = createEffect(
() =>
this.actions$.pipe(
ofType(bindClassifierSuccess),
tap(() => {
this.toastService.success('', 'Pomyślnie dodano klasyfikator', {
icon: 'checkmark-circle',
});
this.store$.dispatch(setBindClassifierLoading({ status: false }));
})
),
{ dispatch: false }
$bindSuccess = createEffect(() =>
this.actions$.pipe(
ofType(bindClassifierSuccess),
tap(() => {
this.toastService.success('', 'Pomyślnie dodano klasyfikator', {
icon: 'checkmark-circle',
});
return this.store$.dispatch(
setBindClassifierLoading({ status: false })
);
}),
map(() => loadDimensions())
)
);
}

View File

@ -3,6 +3,9 @@ import { Actions, createEffect, ofType } from '@ngrx/effects';
import { Injectable } from '@angular/core';
import {
discussionSuccess,
exportFile,
exportFileFailure,
exportFileSuccess,
getDimensionCategories,
getDimensionCategoriesSuccess,
getDiscussion,
@ -18,11 +21,12 @@ import {
catchError,
flatMap,
} from 'rxjs/operators';
import { EMPTY, of } from 'rxjs';
import { EMPTY, of, throwError } from 'rxjs';
import { GetDiscussionService } from '../services/get-discussion.service';
import { Router } from '@angular/router';
import {
selectCurrentDimension,
selectCurrentDiscussion,
selectSelectedParams,
} from 'src/app/selectors/discussion.selectors';
import { DimensionsService } from '../services/dimensions.service';
@ -38,28 +42,6 @@ export class DiscussionEffects {
private paragraphService: ParagraphService,
private router: Router
) {}
// get$ = createEffect(() =>
// this.actions$.pipe(
// ofType(getDiscussion),
// concatMap((action) =>
// of(action).pipe(
// withLatestFrom(this.store$.select(selectRouteParam('id')))
// )
// ),
// flatMap(([_, id]) =>
// this.getDiscussionService.getDiscussion(id!).pipe(
// map((discussions) => {
// console.log('Dupa!');
// return discussionSuccess({ payload: discussions.posts });
// }),
// catchError(() => {
// console.log('Dupa?');
// return EMPTY;
// })
// )
// )
// )
// );
get$ = createEffect(() =>
this.actions$.pipe(
ofType(getDiscussion),
@ -106,16 +88,31 @@ export class DiscussionEffects {
)
);
// load$ = createEffect(
// () =>
// this.actions$.pipe(
// ofType(ROUTER_NAVIGATED),
// tap(() => {
// if (this.router.url.includes('/topic/')) {
// this.store$.dispatch(getDiscussion());
// }
// })
// ),
// { dispatch: false }
// );
exportFile$ = createEffect(() =>
this.actions$.pipe(
ofType(exportFile),
withLatestFrom(
this.store$.select(selectCurrentDimension),
this.store$.select(selectCurrentDiscussion)
),
flatMap(([_, dimension, discussion]) =>
this.getDiscussionService.exportFile(discussion, dimension).pipe(
map((res) => {
let blob = new Blob([res], { type: 'application/tsv' });
let url = window.URL.createObjectURL(blob);
let a = document.createElement('a');
a.href = url;
a.download = 'export.tsv';
a.click();
a.remove();
return exportFileSuccess();
}),
catchError(() => {
this.store$.dispatch(exportFileFailure());
return EMPTY;
})
)
)
)
);
}

View File

@ -109,6 +109,16 @@
pliki <b>forum.xml</b> w każdym z podfolderów
</p>
<button nbButton nbStepperPrevious>Poprzedni krok</button>
<button nbButton nbStepperNext>Następny krok</button>
</nb-step>
<nb-step label="Krok 5">
<h5>Krok #5</h5>
<p class="paragraph">
Jeżeli nie masz dostępu do kopii zapasowej forum, to przykładowe
forum możesz pobrać klikając
<a download="forum.xml" href="assets/forum1.xml">tutaj</a>
</p>
<button nbButton nbStepperPrevious>Poprzedni krok</button>
<button nbButton nbStepperNext disabled>Następny krok</button>
</nb-step>
</nb-stepper>
@ -116,6 +126,6 @@
</section>
</nb-layout-column>
<nb-layout-footer>
Karolina Boczoń, Michał Romaszkin, Marcin Armacki 2020
Karolina Boczoń, Michał Romaszkin, Marcin Armacki 2021
</nb-layout-footer>
</nb-layout>

View File

@ -1,13 +0,0 @@
<div class="picker-container" *ngIf="data$ | async">
<h1>
Wybierz dyskusję z <i>{{ (data$ | async)?.name }}:</i>
</h1>
<nb-card
*ngFor="let item of (data$ | async)?.discussions"
class="picker-container__discussion"
[accent]="getRandomColor()"
(click)="onDiscussionClick(item.id)"
>
<h3 class="picker-container__disc-title">{{ item.title }}</h3>
</nb-card>
</div>

View File

@ -1,8 +0,0 @@
.picker-container {
&__discussion {
cursor: pointer;
}
&__disc-title {
margin: 1rem;
}
}

View File

@ -1,43 +0,0 @@
import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
import { SharedDataService } from '../../services/shared-data.service';
import { Colors } from '../../_types/color';
import { CustomForumData } from '../../_interfaces/customforumdata';
import { Observable, Subscription } from 'rxjs';
import { NbMenuItem } from '@nebular/theme';
import { Router } from '@angular/router';
import { MapIdService } from 'src/app/services/map-id.service';
import { Store } from '@ngrx/store';
import { State } from 'src/app/reducers';
// import { selectData } from '../../selectors/discussion-chooser.selectors';
// import { setDiscussion } from '../../actions/data.actions';
@Component({
selector: 'app-discussion-chooser',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './discussion-chooser.component.html',
styleUrls: ['./discussion-chooser.component.scss'],
})
export class DiscussionChooserComponent implements OnInit {
public data: CustomForumData;
colors: Colors[] = ['primary', 'danger', 'info', 'success', 'warning'];
data$: Observable<CustomForumData>;
constructor(
private sharedDataService: SharedDataService,
private router: Router,
private mapIdService: MapIdService,
private store: Store<State>
) {}
ngOnInit(): void {
// this.data$ = this.store.select(selectData);
}
getRandomColor(): Colors {
return this.colors[Math.floor(Math.random() * this.colors.length)];
}
onDiscussionClick(id: number) {
this.router.navigate([`/view/forum/${id}`]);
}
}

View File

@ -1,62 +0,0 @@
<!-- <div class="discussion-viewer">
<div
subheader
class="discussion-viewer__buttons-container"
[ngClass]="{ scrolled: scrollPosition.y > 40 }"
>
<button
nbButton
hero
status="primary"
class="discussion-viewer__save-button"
(click)="onSaveChangesButtonClick(id)"
>
Zapisz zmiany
</button>
<button
nbButton
hero
status="success"
class="discussion-viewer__back-button"
(click)="onBackButtonClick()"
>
Wróć do wyboru dyskusji
</button>
<button
nbButton
hero
status="info"
class="discussion-viewer__map-id-button"
(click)="onMapIdClick()"
>
Zmapuj ID na dane z pliku
</button>
<button
nbButton
hero
status="danger"
*ngIf="displayNamesMode"
(click)="resetDataMapping()"
>
Usuń zmapowane dane
</button>
<input id="input-for-id" type="file" (change)="fetchFile($event)" />
</div>
<div class="discussion-viewer__posts-container">
<nb-card *ngFor="let item of discussion$ | async">
<nb-card-header>
{{ item.author | idToName: displayNamesMode:parsedNames }}
</nb-card-header>
<nb-card-body>
<app-styled-paragraph
*ngFor="let paragraph of item.message; let i = index"
[message]="paragraph"
[loadedLabel]="item.label[i]"
[paragraphId]="item.para_id[i]"
[discussionId]="id"
[userEdited]="item.user_updated[i]"
></app-styled-paragraph>
</nb-card-body>
</nb-card>
</div>
</div> -->

View File

@ -1,27 +0,0 @@
.discussion-viewer {
display: flex;
flex-flow: column nowrap;
nb-card:first-of-type {
margin-top: 3rem;
}
&__buttons-container {
position: fixed;
margin: 0 -2.25rem;
width: 100%;
top: 4.75rem;
display: flex;
flex-flow: row nowrap;
background-color: white;
box-shadow: 0px 10px 17px -15px rgba(0, 0, 0, 0.88);
z-index: 10;
button {
margin: 1rem 0rem 1rem 1rem;
}
}
}
input[type="file"] {
display: none;
}

View File

@ -1,116 +0,0 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { GetDiscussionService } from '../../services/get-discussion.service';
import { PredictedPost } from '../../_interfaces/predictedposts';
import { Observable, Subject, Subscription } from 'rxjs';
import { concatMap, defaultIfEmpty, map } from 'rxjs/operators';
import { ParagraphService } from 'src/app/services/paragraph.service';
import {
NbToastrService,
NbLayoutScrollService,
NbScrollPosition,
} from '@nebular/theme';
import { parse } from 'papaparse';
import { selectRouteParam, State } from 'src/app/reducers';
import { Store } from '@ngrx/store';
@Component({
selector: 'app-discussion-viewer',
templateUrl: './discussion-viewer.component.html',
styleUrls: ['./discussion-viewer.component.scss'],
})
export class DiscussionViewerComponent {
// data: PredictedPost[];
// id: number;
// subscriptionData: Subscription;
// subscriptionId: Subscription;
// displayNamesMode: boolean;
// parsedNames: { id: number; name: string }[];
// scrollPosition: NbScrollPosition;
// constructor(
// private getDiscussionService: GetDiscussionService,
// private paragraphService: ParagraphService,
// private router: Router,
// private toastService: NbToastrService,
// private scrollService: NbLayoutScrollService,
// private store: Store<State>
// ) {
// this.scrollPosition = { x: 0, y: 0 };
// }
// discussion$: Observable<PredictedPost[]> = this.store.select((state) => {
// return state.currentDiscussion;
// });
// ngOnInit(): void {
// this.store.dispatch({
// type: '[DiscussionViewer Component] Load Discussion',
// });
// this.store.select(selectRouteParam('id')).subscribe((id) => {
// this.id = parseInt(id!);
// });
// this.scrollService
// .onScroll()
// .pipe(concatMap(() => this.scrollService.getPosition()))
// .subscribe((result) => {
// this.scrollPosition = result;
// });
// }
// onBackButtonClick() {
// this.router.navigate(['/view/discussions/']);
// }
// onSaveChangesButtonClick(id: number) {
// this.paragraphService
// .patchParagraphs(id)
// ?.pipe(defaultIfEmpty())
// .subscribe((result: any) => {
// if (result === null) {
// this.toastService.danger('', 'Brak zmian!', {
// preventDuplicates: true,
// icon: 'alert-circle',
// });
// } else {
// this.data = result.posts;
// this.toastService.success('', 'Zmiany zostały zapisane!', {
// icon: 'checkmark-circle-2-outline',
// });
// }
// });
// }
// onMapIdClick() {
// const el: HTMLElement = document.getElementById(
// 'input-for-id'
// ) as HTMLElement;
// el.click();
// }
// async fetchFile(event: Event) {
// let parsedNamesFromArray: Array<{ id: number; name: string }>;
// const target = event.target as HTMLInputElement;
// const file = target.files![0];
// try {
// parsedNamesFromArray = await this.parseFile(file);
// this.parsedNames = parsedNamesFromArray;
// this.displayNamesMode = true;
// } catch (e) {
// this.toastService.danger('', e, {
// icon: 'alert-circle',
// });
// }
// }
// parseFile(file: File): Promise<{ id: number; name: string }[]> {
// return new Promise((resolve, reject) => {
// parse(file, {
// header: true,
// skipEmptyLines: true,
// dynamicTyping: true,
// complete: (result) => {
// if (result.errors.length > 0) {
// reject('Błąd przy parsowaniu pliku');
// }
// resolve(result.data as { id: number; name: string }[]);
// },
// });
// });
// }
// resetDataMapping() {
// this.displayNamesMode = false;
// }
}

View File

@ -1,40 +0,0 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { MainViewComponent } from './main-view.component';
import { DiscussionChooserComponent } from './discussion-chooser/discussion-chooser.component';
import { DiscussionViewerComponent } from './discussion-viewer/discussion-viewer.component';
const routes: Routes = [
{
path: '',
component: MainViewComponent,
children: [
{
path: 'discussions',
component: DiscussionChooserComponent,
},
{
path: 'forum/:id',
component: DiscussionViewerComponent,
},
{
path: 'visualize/:id',
loadChildren: () =>
import('./visualize-forum/visualize-forum.module').then(
(m) => m.VisualizeForumModule
),
},
{
path: '',
redirectTo: 'discussions',
pathMatch: 'full',
},
],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class MainViewRoutingModule {}

View File

@ -1,28 +0,0 @@
<nb-layout>
<nb-layout-header fixed>
<div class="actions-container">
<nb-actions>
<nb-action
icon="menu"
(click)="toggleSidebar()"
nbTooltip="Schowaj/Pokaż panel menu"
></nb-action>
<nb-action>nkadf</nb-action>
</nb-actions>
<nb-actions>
<nb-action
icon="power"
(click)="logout()"
nbTooltip="Wróć do strony początkowej"
>Wyloguj</nb-action
>
</nb-actions>
</div>
</nb-layout-header>
<nb-sidebar tag="main" responsive>
<nb-menu [items]="items"></nb-menu>
</nb-sidebar>
<nb-layout-column>
<router-outlet></router-outlet>
</nb-layout-column>
</nb-layout>

View File

@ -1,6 +0,0 @@
.actions-container {
width: 100%;
display: flex;
flex-flow: row;
justify-content: space-between;
}

View File

@ -1,66 +0,0 @@
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { NbSidebarService, NbMenuItem } from '@nebular/theme';
import { Observable, Subscription } from 'rxjs';
import { Store } from '@ngrx/store';
import { State } from '../reducers';
// import { selectDiscussions } from '../selectors/discussion-chooser.selectors';
@Component({
selector: 'app-main-view',
templateUrl: './main-view.component.html',
styleUrls: ['./main-view.component.scss'],
})
export class MainViewComponent implements OnInit {
items: NbMenuItem[];
menuItemsSub: Subscription;
discussions$: Observable<{ id: number; title: string }[]>;
constructor(
private sidebarService: NbSidebarService,
private router: Router,
private store: Store<State>
) {}
toggleSidebar() {
this.sidebarService.toggle(true, 'main');
}
logout() {
this.router.navigate(['/']);
}
ngOnInit(): void {
// this.store.select(selectDiscussions).subscribe((discussions) => {
// const availableDiscussions = discussions.map(
// (discussion): NbMenuItem => ({
// title: discussion.title,
// link: `/view/forum/${discussion.id}`,
// })
// );
// const availableVisualizations = discussions.map(
// (discussion): NbMenuItem => ({
// title: discussion.title,
// link: `/view/visualize/${discussion.id}`,
// })
// );
// this.items = [
// {
// title: 'Dyskusje',
// link: '/view/discussions',
// icon: {
// icon: 'message-square',
// },
// children: availableDiscussions,
// },
// {
// title: 'Wizualizacje',
// icon: {
// icon: 'trending-up',
// },
// children: availableVisualizations,
// },
// ];
// });
}
}

View File

@ -1,52 +0,0 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MainViewComponent } from './main-view.component';
import { DiscussionChooserComponent } from './discussion-chooser/discussion-chooser.component';
import { MainViewRoutingModule } from './main-view-routing.module';
import { DiscussionViewerComponent } from './discussion-viewer/discussion-viewer.component';
import { GetDiscussionService } from '../services/get-discussion.service';
import { ParagraphService } from '../services/paragraph.service';
import { MapIdService } from '../services/map-id.service';
// import { StyledParagraphComponent } from './styled-paragraph/styled-paragraph.component';
import { IdToNamePipe } from '../_pipes/id-to-name.pipe';
import { DiscussionEffects } from '../effects/discussion.effect';
import {
NbLayoutModule,
NbActionsModule,
NbSidebarModule,
NbTooltipModule,
NbCardModule,
NbMenuModule,
NbButtonModule,
NbSelectModule,
NbIconModule,
} from '@nebular/theme';
import { EffectsModule } from '@ngrx/effects';
import { GetVisualizationDataService } from '../services/get-visualization-data.service';
@NgModule({
declarations: [
MainViewComponent,
DiscussionChooserComponent,
DiscussionViewerComponent,
],
imports: [
CommonModule,
MainViewRoutingModule,
NbLayoutModule,
NbActionsModule,
NbSidebarModule,
NbTooltipModule,
NbCardModule,
NbMenuModule,
NbButtonModule,
NbSelectModule,
NbIconModule,
EffectsModule.forFeature([DiscussionEffects]),
],
providers: [GetDiscussionService, ParagraphService, MapIdService],
})
export class MainViewModule {}

View File

@ -1,16 +0,0 @@
import { Routes, RouterModule } from '@angular/router';
import { VisualizeForumComponent } from './visualize-forum.component';
import { NgModule } from '@angular/core';
const routes: Routes = [
{
path: '',
component: VisualizeForumComponent,
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class VisualizeForumRoutingModule {}

View File

@ -1 +0,0 @@
<div id="tree" #tree></div>

View File

@ -1,18 +0,0 @@
::ng-deep .link {
fill: none;
stroke: #000;
stroke-width: 2px;
}
::ng-deep .tooltip {
width: 25rem;
background-color: #ffffff;
border: 0.0625rem solid #e4e9f2;
border-radius: 0.25rem;
padding: 1rem;
max-height: 20rem;
overflow: hidden;
h6 {
margin: 0;
}
}

View File

@ -1,153 +0,0 @@
import {
Component,
OnDestroy,
ViewChild,
ElementRef,
AfterViewInit,
} from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { GetVisualizationDataService } from '../../services/get-visualization-data.service';
import { Subscription } from 'rxjs';
import { concatMap } from 'rxjs/operators';
import { Post } from 'src/app/_interfaces/post';
import * as d3 from 'd3';
import maked3hierarchy from '../../_functions/maked3hierarchy';
@Component({
selector: 'visualize-forum',
templateUrl: './visualize-forum.component.html',
styleUrls: ['./visualize-forum.component.scss'],
})
export class VisualizeForumComponent implements AfterViewInit, OnDestroy {
private subscription: Subscription;
private data: Post[];
private hierarchizedData: Post[];
@ViewChild('tree', { read: ElementRef })
private treeContainer: ElementRef;
constructor(
private route: ActivatedRoute,
private getDataService: GetVisualizationDataService
) {}
ngAfterViewInit(): void {
this.subscription = this.route.params
.pipe(concatMap((params) => this.getDataService.getDiscussion(params.id)))
.subscribe((result) => {
this.initializeData(result.posts);
this.generateGraph();
});
}
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
private initializeData(data: Post[]): void {
this.data = data;
this.hierarchizedData = maked3hierarchy(data);
}
private generateGraph(): void {
/* ToDo: Add option to change sizes */
const margin = { top: 50, right: 90, bottom: 30, left: 90 };
const width = 860 - margin.left - margin.right;
const height = 500 - margin.top - margin.bottom;
const hierarchizedNodes = d3.hierarchy<Post>(this.hierarchizedData[0]);
d3.tree().size([width, height])(hierarchizedNodes);
const element = this.treeContainer.nativeElement;
/* Clear previous graph */
d3.selectAll(`#tree > *`).remove();
/* Create SVG */
const svg = d3
.select(element)
.append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom);
const group = svg
.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`);
const gLink = group.append('g').attr('class', 'links');
const gNode = group.append('g').attr('class', 'nodes');
/* Custom tooltip */
const tooltip = d3
.select(element)
.append('div')
.attr('class', 'tooltip')
.style('position', 'absolute')
.style('opacity', 0);
/* Select all nodes and pass data into them */
const node = gNode
.selectAll('g.nodes')
.data(hierarchizedNodes.descendants());
/* Select all links and pass data into them */
const link = gLink.selectAll('g.links').data(hierarchizedNodes.links());
/* 'Enter' into node, style it properly and create tooltip on hover */
const nodeEnter = node.enter().append('g').classed('node', true);
nodeEnter
.append('circle')
.attr('cx', (d: any) => d.x)
.attr('cy', (d: any) => d.y)
.attr('r', 25)
.style('fill', '#fff')
.style('stroke', '#ccc');
nodeEnter
.append('text')
.attr('x', (d: any) => d.x)
.attr('y', (d: any) => d.y + 5)
.attr('text-anchor', 'middle')
.attr('class', 'h6')
.text((d: any) => d.data.id);
nodeEnter
.on('mouseover', (d) => {
tooltip.transition().duration(400).style('opacity', 1);
tooltip
.html(
/* HTML */
`
<h6>Wiadomość:</h6>
<p>${d.data.message}</p>
`
)
// .style('width', '15rem')
// .style('max-height', '10rem')
// .style('overflow', 'hidden')
// .style('text-overflow', 'ellipsis')
// .style('background-color', '#fff')
// .style('border', '1px solid black')
.style('left', `${d3.event.pageX}px`)
.style('top', `${d3.event.pageY}px`);
})
.on('mouseout', function (d) {
tooltip
.transition()
.duration(400)
.style('opacity', 0)
.style('top', '0')
.style('left', '0');
})
.on('mousemove', function (d) {
return tooltip
.style('top', `${d3.event.pageY - 55}px`)
.style('left', `${d3.event.pageX + 30}px`);
});
/* 'Enter' into links and style them properly */
const linkEnter = link.enter().append('line').classed('link', true);
linkEnter
.attr('x1', (d: any) => d.source.x)
.attr('y1', (d: any) => d.source.y)
.attr('x2', (d: any) => d.target.x)
.attr('y2', (d: any) => d.target.y);
}
}

View File

@ -1,12 +0,0 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { VisualizeForumComponent } from './visualize-forum.component';
import { VisualizeForumRoutingModule } from './visualize-forum-routing.module';
import { GetVisualizationDataService } from '../../services/get-visualization-data.service';
@NgModule({
declarations: [VisualizeForumComponent],
imports: [CommonModule, VisualizeForumRoutingModule],
providers: [GetVisualizationDataService],
})
export class VisualizeForumModule {}

View File

@ -1,6 +1,9 @@
.picker-container {
&__discussion {
cursor: pointer;
&:hover {
background-color: #f5f5f5;
}
}
&__disc-title {
margin: 1rem;

View File

@ -5,13 +5,10 @@
}
::ng-deep .tooltip {
width: 25rem;
background-color: #ffffff;
border: 0.0625rem solid #e4e9f2;
border-radius: 0.25rem;
padding: 1rem;
max-height: 20rem;
overflow: hidden;
h6 {
margin: 0;
}

View File

@ -113,7 +113,12 @@ export class GraphComponent implements AfterViewInit, OnDestroy {
nodeEnter
.on('mouseover', (d) => {
tooltip.transition().duration(400).style('opacity', 1);
tooltip
.transition()
.duration(400)
.style('height', 'auto')
.style('opacity', 1)
.style('overflow', 'auto');
tooltip
.html(
/* HTML */
@ -122,12 +127,6 @@ export class GraphComponent implements AfterViewInit, OnDestroy {
<p>${d.data.message}</p>
`
)
// .style('width', '15rem')
// .style('max-height', '10rem')
// .style('overflow', 'hidden')
// .style('text-overflow', 'ellipsis')
// .style('background-color', '#fff')
// .style('border', '1px solid black')
.style('left', `${d3.event.pageX}px`)
.style('top', `${d3.event.pageY}px`);
})
@ -136,12 +135,14 @@ export class GraphComponent implements AfterViewInit, OnDestroy {
.transition()
.duration(400)
.style('opacity', 0)
.style('height', '0')
.style('top', '0')
.style('left', '0');
.style('left', '0')
.style('overflow', 'hidden');
})
.on('mousemove', function (d) {
return tooltip
.style('top', `${d3.event.pageY - 55}px`)
.style('top', `90px`)
.style('left', `${d3.event.pageX + 30}px`);
});

View File

@ -6,8 +6,9 @@
<nb-list-item
*ngFor="let item of dimensions$ | async; let i = index"
(click)="dimension(item.id)"
class="list-item"
>
{{ item.name }}
<span class="subtitle">{{ item.name }}</span>
</nb-list-item>
</nb-list>
<nb-card-footer>

View File

@ -0,0 +1,6 @@
.list-item {
cursor: pointer;
&:hover {
background-color: #f5f5f5;
}
}

View File

@ -1,38 +1,53 @@
<nb-layout class="discussion-viewer">
<nb-layout-header
subheader
class="discussion-viewer__buttons-container"
withScroll
>
<button
nbButton
hero
status="success"
class="discussion-viewer__back-button"
routerLink="../"
>
Wróć do wyboru dyskusji
</button>
<button nbButton hero status="info" (click)="mapId()">
Zmapuj dane z pliku users.xml
</button>
<button nbButton hero status="danger" (click)="resetDataMapping()">
Usuń zmapowane dane
</button>
<input
id="input-for-id"
type="file"
(change)="fetchFile($event)"
accept=".xml"
/>
<nb-select
[selected]="currentDimension$ | async"
(selectedChange)="changeCurrentDimension($event)"
>
<nb-option *ngFor="let item of dimensions$ | async" [value]="item.id">{{
item.name
}}</nb-option>
</nb-select>
<nb-layout-header subheader class="discussion-viewer__header" withScroll>
<div class="discussion-viewer__button-container">
<div>
<button nbButton hero status="info" (click)="mapId()">
Zmapuj dane z pliku users.xml
</button>
<button
nbButton
hero
status="danger"
(click)="resetDataMapping()"
*ngIf="displayNamesMode"
>
Usuń zmapowane dane
</button>
<input
id="input-for-id"
type="file"
(change)="fetchFile($event)"
accept=".xml"
/>
<nb-select
[selected]="currentDimension$ | async"
(selectedChange)="changeCurrentDimension($event)"
class="discussion-viewer__dimension-select"
>
<nb-option [value]="0"> Brak wymiaru </nb-option>
<nb-option
*ngFor="let item of dimensions$ | async"
[value]="item.id"
>{{ item.name }}</nb-option
>
</nb-select>
<button nbButton outline status="primary" (click)="exportTSV()">
Eksportuj dyskusję do pliku tsv
</button>
</div>
<div>
<button
nbButton
hero
status="success"
class="discussion-viewer__back-button"
routerLink="../"
>
Wróć do wyboru dyskusji
</button>
</div>
</div>
</nb-layout-header>
<nb-sidebar containerFixed>
@ -41,6 +56,7 @@
<nb-list-item
*ngFor="let item of (items$ | async)!.discussions"
(click)="goToDiscussion(item.id)"
class="subtitle discussion-item"
>
{{ item.title }}
</nb-list-item>
@ -48,6 +64,7 @@
<nb-list-item
*ngFor="let item of (items$ | async)!.discussions"
(click)="goToVisualization(item.id)"
class="subtitle discussion-item"
>
{{ item.title }}
</nb-list-item>

View File

@ -9,17 +9,38 @@
}
}
&__buttons-container {
&__header {
position: fixed;
width: 100%;
width: calc(100% - 250px);
top: 4.75rem;
background-color: white;
box-shadow: 0px 10px 17px -15px rgba(0, 0, 0, 0.88);
z-index: 10;
button {
margin: 1rem 1rem 1rem 0rem;
}
&__button-container {
display: flex;
flex-flow: row wrap;
width: 100%;
justify-content: space-between;
> div {
display: flex;
button {
margin-right: 1rem;
}
}
}
.discussion-item {
cursor: pointer;
&:hover {
background-color: #f5f5f5;
}
}
&__dimension-select {
margin-right: 1rem;
}
}
input[type="file"] {

View File

@ -2,9 +2,9 @@ import { Component } from '@angular/core';
import { concatMap } from 'rxjs/operators';
import {
exportFile,
getDimensionCategories,
setCurrentDimensionId,
setCurrentDiscussion,
setCurrentDiscussionId,
} from 'src/app/actions/discussion.actions';
import { NbToastrService, NbLayoutScrollService } from '@nebular/theme';
@ -72,7 +72,7 @@ export class ViewComponent {
goToDiscussion(id: any) {
this.store.dispatch(setCurrentDiscussionId({ id }));
window.location.reload();
this.store.dispatch(getDiscussion());
}
goToVisualization(id: any) {
@ -94,6 +94,9 @@ export class ViewComponent {
}));
this.parsedNames = users;
this.displayNamesMode = true;
this.toastService.success('', 'Pomyślnie zmapowano dane!', {
icon: 'checkmark-circle-2-outline',
});
});
};
}
@ -102,6 +105,10 @@ export class ViewComponent {
this.displayNamesMode = false;
}
exportTSV() {
this.store.dispatch(exportFile());
}
changeCurrentDimension(event: number) {
this.store.dispatch(setCurrentDimensionId({ id: event }));
this.store.dispatch(loadDiscussions());

View File

@ -5,6 +5,7 @@
<nb-layout>
<nb-layout-column class="editDimension__leftColumn">
<h3>Edytuj wymiar</h3>
<label class="label editDimension__name-label">Nazwa wymiaru</label>
<input
fullWidth
nbInput
@ -12,11 +13,13 @@
formControlName="name"
class="editDimension__name"
/>
<label class="label editDimension__description-label">Opis wymiaru</label>
<textarea
nbInput
fullWidth
placeholder="Opis wymiaru"
formControlName="description"
class="editDimension__description"
></textarea>
</nb-layout-column>
<nb-layout-column>
@ -35,6 +38,7 @@
outline
status="danger"
class="editDimension__button"
(click)="deleteDimension()"
>
Usuń wymiar
</button>

View File

@ -10,4 +10,11 @@
display: flex;
justify-content: flex-end;
}
&__name-label,
&__description-label {
margin-bottom: 0.5rem;
}
&__description-label {
margin-top: 1rem;
}
}

View File

@ -11,6 +11,7 @@ import {
clearSelectedDimension,
getSelectedDimension,
removeCategoryFromDimension,
removeSelectedDimension,
updateSelectedDimension,
} from 'src/app/actions/dimension.actions';
import {
@ -20,6 +21,8 @@ import {
} from 'src/app/selectors/dimension.selectors';
import { ActivatedRoute, Router } from '@angular/router';
import { Category } from 'src/app/reducers/dimension.reducers';
import { NbDialogService } from '@nebular/theme';
import { DeleteDialogComponent } from '../delete-dialog/delete-dialog.component';
@Component({
selector: 'edit-dimension',
@ -39,7 +42,8 @@ export class EditDimensionComponent implements OnInit, OnDestroy {
private fb: FormBuilder,
private store: Store<State>,
private router: Router,
private route: ActivatedRoute
private route: ActivatedRoute,
private dialogService: NbDialogService
) {}
ngOnInit(): void {
@ -107,4 +111,15 @@ export class EditDimensionComponent implements OnInit, OnDestroy {
this.store.dispatch(clearSelectedDimension());
this.editDimensionForm.reset();
}
deleteDimension() {
this.dialogService
.open(DeleteDialogComponent, { context: { type: 'wymiar' } })
.onClose.subscribe((res: boolean) => {
if (res) {
this.store.dispatch(removeSelectedDimension());
this.router.navigate(['../'], { relativeTo: this.route });
}
});
}
}

View File

@ -1,3 +1,4 @@
import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { NbAuthService, NbTokenService } from '@nebular/auth';
@ -18,6 +19,7 @@ export class MyProfileComponent implements OnInit {
logout() {
this.tokenService.clear();
this.authService.logout('email');
this.router.navigate(['/']);
}
}

View File

@ -18,6 +18,10 @@ export const selectCurrentDimension = createSelector(
selectFeature,
(state) => state.selectedDimension
);
export const selectCurrentDiscussion = createSelector(
selectFeature,
(state) => state.selectedDiscussion
);
export const selectCurrentCategories = createSelector(
selectFeature,
(state) => state.currentCategories

View File

@ -2,6 +2,7 @@ import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import url from './url';
import { map } from 'rxjs/operators';
@Injectable()
export class GetDiscussionService {
@ -24,4 +25,17 @@ export class GetDiscussionService {
bindClassfier(id: number) {
return this.http.get<any>(`${url}/classifier/${id}`);
}
exportFile(discussionId: number, dimensionId: number) {
return this.http.post<any>(
`${url}/export/`,
{
discussion: discussionId,
dimension: dimensionId,
},
{
responseType: 'arraybuffer' as 'json',
}
);
}
}

View File

@ -0,0 +1,268 @@
<?xml version="1.0" encoding="UTF-8"?>
<activity id="6" moduleid="6" modulename="forum" contextid="76">
<forum id="6">
<type>general</type>
<name>Najnowsze technologie</name>
<intro></intro>
<introformat>1</introformat>
<assessed>0</assessed>
<assesstimestart>0</assesstimestart>
<assesstimefinish>0</assesstimefinish>
<scale>100</scale>
<maxbytes>512000</maxbytes>
<maxattachments>9</maxattachments>
<forcesubscribe>0</forcesubscribe>
<trackingtype>1</trackingtype>
<rsstype>0</rsstype>
<rssarticles>0</rssarticles>
<timemodified>1593091872</timemodified>
<warnafter>0</warnafter>
<blockafter>0</blockafter>
<blockperiod>0</blockperiod>
<completiondiscussions>0</completiondiscussions>
<completionreplies>0</completionreplies>
<completionposts>0</completionposts>
<displaywordcount>0</displaywordcount>
<lockdiscussionafter>0</lockdiscussionafter>
<discussions>
<discussion id="9">
<name>Najnowsze technologie - dyskusja</name>
<firstpost>30</firstpost>
<userid>2</userid>
<groupid>-1</groupid>
<assessed>0</assessed>
<timemodified>1593093116</timemodified>
<usermodified>2</usermodified>
<timestart>0</timestart>
<timeend>0</timeend>
<pinned>0</pinned>
<posts>
<post id="30">
<parent>0</parent>
<userid>2</userid>
<created>1593092060</created>
<modified>1593092060</modified>
<mailed>1</mailed>
<subject>Najnowsze technologie - dyskusja</subject>
<message>&lt;p&gt;Czy tworząc nowy system powinniśmy korzystać z najnowszych technologii dostępnych w branży?&lt;/p&gt;&lt;p&gt;Odpowiedź uzasadnij.&lt;br /&gt;&lt;/p&gt;</message>
<messageformat>1</messageformat>
<messagetrust>0</messagetrust>
<attachment></attachment>
<totalscore>0</totalscore>
<mailnow>0</mailnow>
<ratings>
</ratings>
</post>
<post id="31">
<parent>30</parent>
<userid>7</userid>
<created>1593092371</created>
<modified>1593092371</modified>
<mailed>1</mailed>
<subject>Re: Najnowsze technologie - dyskusja</subject>
<message>&lt;p&gt;Uważam, że jak najbardziej. Należy zawsze inwestować w nowoczesne rozwiązania. Trzeba za wszelką cenę wyprzedzić konkurencję i promować nowatorskie podejście.&lt;br /&gt;&lt;/p&gt;</message>
<messageformat>1</messageformat>
<messagetrust>0</messagetrust>
<attachment></attachment>
<totalscore>0</totalscore>
<mailnow>0</mailnow>
<ratings>
</ratings>
</post>
<post id="32">
<parent>30</parent>
<userid>8</userid>
<created>1593092625</created>
<modified>1593092625</modified>
<mailed>1</mailed>
<subject>Re: Najnowsze technologie - dyskusja</subject>
<message>&lt;p&gt;Nie mogę się z tym zgodzić. Uważam, że znacznie rozsądniej jest postawić na sprawdzone rozwiązania. Celem nadrzędnym jest tworzenie stabilnych systemów o niskiej awaryjności, a nie wyścig zbrojeń w tworzeniu nowatorskich rozwiązań. Rozumiem, że w grę wchodzą też umowy i zobowiązania wobec klienta. W ogólnym rozrachunku jednak zdecydowanie nie popieram.&lt;br /&gt;</message>
<messageformat>1</messageformat>
<messagetrust>0</messagetrust>
<attachment></attachment>
<totalscore>0</totalscore>
<mailnow>0</mailnow>
<ratings>
</ratings>
</post>
<post id="33">
<parent>32</parent>
<userid>9</userid>
<created>1593092682</created>
<modified>1593092682</modified>
<mailed>1</mailed>
<subject>Re: Najnowsze technologie - dyskusja</subject>
<message>&lt;p&gt;A co jeśli to klient chce postawić na nowoczesną technologię?&lt;br /&gt;&lt;/p&gt;</message>
<messageformat>1</messageformat>
<messagetrust>0</messagetrust>
<attachment></attachment>
<totalscore>0</totalscore>
<mailnow>0</mailnow>
<ratings>
</ratings>
</post>
<post id="34">
<parent>33</parent>
<userid>8</userid>
<created>1593092794</created>
<modified>1593092794</modified>
<mailed>1</mailed>
<subject>Re: Najnowsze technologie - dyskusja</subject>
<message>&lt;p&gt;Spotkałem się kiedyś w pracy w z takim przypadkiem. Klient zazwyczaj nie przykłada wagi do tego jakie rozwiązania są stosowane. Ważnym jest, by system działał poprawnie i spełniał oczekiwania.&lt;br /&gt;&lt;/p&gt;</message>
<messageformat>1</messageformat>
<messagetrust>0</messagetrust>
<attachment></attachment>
<totalscore>0</totalscore>
<mailnow>0</mailnow>
<ratings>
</ratings>
</post>
<post id="35">
<parent>30</parent>
<userid>2</userid>
<created>1593093116</created>
<modified>1593093116</modified>
<mailed>1</mailed>
<subject>Re: Najnowsze technologie - dyskusja</subject>
<message>&lt;p&gt;Sam zgadzam się z tym, że należy postawić na nowe rozwiązania i nowoczesną technologię, która w wielu przypadkach jest równoznaczna z ułatwieniem życia programisty i zapewnieniu wielu komfortowych rozwiązań, które odciążają twórcę oprogramowania i pozwalają skupić się na innych aspektach tworzonego sytemu, lecz nie jestem do końca przekonany. Głównie dlatego, że nowoczesna technologia musi się odpowiednio wdrożyć i osiągnąć pewien poziom stabilności. W ostatecznym rozrachunku uważam, że należy dobierać narzędzia adekwatnie do problemu, który chcemy rozwiązać.&lt;br /&gt;</message>
<messageformat>1</messageformat>
<messagetrust>0</messagetrust>
<attachment></attachment>
<totalscore>0</totalscore>
<mailnow>0</mailnow>
<ratings>
</ratings>
</post>
</posts>
<discussion_subs>
<discussion_sub id="21">
<userid>2</userid>
<preference>1593092060</preference>
</discussion_sub>
<discussion_sub id="22">
<userid>7</userid>
<preference>1593092371</preference>
</discussion_sub>
<discussion_sub id="23">
<userid>8</userid>
<preference>1593092625</preference>
</discussion_sub>
<discussion_sub id="24">
<userid>9</userid>
<preference>1593092682</preference>
</discussion_sub>
</discussion_subs>
</discussion>
<discussion id="10">
<name>Czy komputer w lodówce to już współczesność?</name>
<firstpost>36</firstpost>
<userid>2</userid>
<groupid>-1</groupid>
<assessed>0</assessed>
<timemodified>1593096052</timemodified>
<usermodified>9</usermodified>
<timestart>0</timestart>
<timeend>0</timeend>
<pinned>0</pinned>
<posts>
<post id="36">
<parent>0</parent>
<userid>2</userid>
<created>1593095765</created>
<modified>1593095765</modified>
<mailed>1</mailed>
<subject>Czy komputer w lodówce to już współczesność?</subject>
<message>&lt;p&gt;Kiedyś żartobliwie mówiono, że niedługo komputer będzie już w każdej
lodówce. Czy to "niedługo" jest już "dzisiaj"? Jakie zastosowania
informatyki wdarły się do życia codziennego w taki sposób, że tego nie
zauważamy?&lt;br /&gt;&lt;/p&gt;</message>
<messageformat>1</messageformat>
<messagetrust>0</messagetrust>
<attachment></attachment>
<totalscore>0</totalscore>
<mailnow>0</mailnow>
<ratings>
</ratings>
</post>
<post id="37">
<parent>36</parent>
<userid>7</userid>
<created>1593095882</created>
<modified>1593095882</modified>
<mailed>1</mailed>
<subject>Re: Czy komputer w lodówce to już współczesność?</subject>
<message>&lt;p&gt;Komputery w życiu codziennym to już norma. Mamy z nimi do czynienia w kuchni, łazience oraz salonie. Firmy technologiczne dążą do stworzenia inteligentych domów, w zasadzie już takie domy istnieją, ale zwykły śmiertelnik może o nich tylko pomarzyć. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Zacznę więc może od wspomnianej lodówki. Na targach CES w 2011 roku firma LG zaprezentowała inteligentną lodówkę, która sama przeszukiwała internet w poszukiwaniu ciekawych przepisów, bazując przy tym na produktach, które znajdowały się w jej wnętrzu. Sprawdzanie terminów ważności produktów równeż nie było problemem. Wszystkie niezbędne informacje, dotyczące lodówki i produktów z jej wnętrza, użytkownik mógł odebrać przy pomocy komputera, bądź urządzenia mobilnego, podłączonego do internetu. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Samsung w tym roku zaprezentowały lodówki z wyświetlaczem dotykowym oraz możliwością dokonywania zakupów z poziomu lodówki.[url]http://www.youtube.com/watch?v=yu3keu48hzY[/url] &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Samsung i LG nie poprzestają tylko na konstruowaniu inteligentych urządzeń AGD, chcą również zapewnić swobodną komunikację pomiędzy urządzeniami bez naszej ingerencji. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Dwa tygodnie temu miałem okazję obejrzeć film dokumentalny o inteligentych domach. Prezentowane technologie mieściły się w centrum badawczym firmy Samsung, których oglądanie jest dostępne dla zwiedzających. Tak więc system rozpoznający domowników wybiera dla konkretnej osoby poziom oświetlenia w pomieszczeniu, załącza odpowiednią muzykę, itp. Nie będę już wspominał o automatycznym nalewaniu wody do wanny o określonej godzinie, kabinach prysznicowych z telewizorem, łącznością telefoniczną i internetową czy podgrzewanych deskach sedesowych. Część tych rozwiązań jest już dostępna na rynku, a część będzie wdrażana w tym roku. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Zapewne część z Was słyszała o posiadłości Billa Gatesa, która jest w całości naszpikowana elektroniką. Jeśli nie to polecam poniższy artykuł:[url]http://nt.interia.pl/gadzety/news-jak-mieszka-bill-gates,nId,690078[/url]&lt;br /&gt;&lt;/p&gt;</message>
<messageformat>1</messageformat>
<messagetrust>0</messagetrust>
<attachment></attachment>
<totalscore>0</totalscore>
<mailnow>0</mailnow>
<ratings>
</ratings>
</post>
<post id="38">
<parent>36</parent>
<userid>8</userid>
<created>1593095987</created>
<modified>1593157009</modified>
<mailed>1</mailed>
<subject>Re: Czy komputer w lodówce to już współczesność?</subject>
<message>&lt;p&gt;Niestety taka komputeryzacja postępuje. Dlaczego niestety? &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Bo boje się iż ludzie przez nią staną się coraz bardziej leniwi i przepraszam za określenie 'zidioceni' &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Dlaczego? Mamy juz inteligentne lodówki, samo czyszczące odkurzacze, samo jeżdzące samochody. To co człowiek ma robić? Jak żyć, skoro nie ma nawet najprostrzych codziennych udręk i wyzwań? Co gorsza w ten sposób ludzie oduczaja się dbać o inne rzeczy. Bo po co skoro komputer zrobi to za nas? &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Wyobraźcie sobie sytuację za powiedzmy 20 lat. Gdzie nie ma już gazet, tylko same e-papiery i tablety. A tu w piwnicy znajdzie stary album ze zdjęciami i próbując go otworzyć nieświadomie go zniszczy. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Jest to problem teoretycznie wielokrotnie wyśmiewany w naszej kulturze np w filmie animowanym [url=http://www.youtube.com/watch?v=h1BQPV-iCkU][b]WALL-E LINK 1[/b][/url] [url=http://www.youtube.com/watch?v=xoa25BjRP-I][b]WALL-E LINK 2[/b][/url] gdzie mamy wiele scen pokazujących wręcz ludzka degenerację w pełni zautomatyzowanym świecie. Jednak moim zdaniem problem istnieje i sądzę że komputery nie powinny być wpychane gdzie popadnie.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span class="edited"&gt;(Edited by &lt;a href="https://fep.gnomio.com/user/view.php?id=2&amp;amp;course=2"&gt;Admin User&lt;/a&gt; - original submission Thursday, 25 June 2020, 2:39 PM)&lt;/span&gt;&lt;/p&gt;</message>
<messageformat>1</messageformat>
<messagetrust>0</messagetrust>
<attachment></attachment>
<totalscore>0</totalscore>
<mailnow>0</mailnow>
<ratings>
</ratings>
</post>
<post id="39">
<parent>36</parent>
<userid>9</userid>
<created>1593096052</created>
<modified>1593096052</modified>
<mailed>1</mailed>
<subject>Re: Czy komputer w lodówce to już współczesność?</subject>
<message>&lt;p&gt;Odwołując się do wypowiedzi X 2 i 3 akapit. Co prawda powstaje coraz lepszy sprzęt ale kto z niego korzysta? Nie znam nikogo kto by miał samoczyszczący odkurzacz, czy inteligentną lodówkę. Zwykły szary obywatel woli te pieniądze przeznaczyć na coś innego, a ci co kupują taki sprzęt i tak by sami nie sprzątali. Wydaje mi się, że jeszcze sporo czasu pomęczymy się z odkurzaczem.Jednak postem komputeryzacji w naszym życiu możemy zaobserwować np. siedząc na wykładzie. Kiedyś na nudnych zajęciach uczniowie/studyci grali w kółko i krzyżyk, statki itp., a notowali w zeszycie. Teraz co druga osoba siedzi z laptopem lub innym sprzętem elektronicznym, nieraz też słyszałam w telewizji rozmowy polityków by dzieci zamiast książek i zeszytów chodziły do szkoły z laptopami. Również ściąga pisana na kartce została totalnie wyparta przez elektronikę.
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</message>
<messageformat>1</messageformat>
<messagetrust>0</messagetrust>
<attachment></attachment>
<totalscore>0</totalscore>
<mailnow>0</mailnow>
<ratings>
</ratings>
</post>
</posts>
<discussion_subs>
<discussion_sub id="25">
<userid>2</userid>
<preference>1593095765</preference>
</discussion_sub>
<discussion_sub id="26">
<userid>7</userid>
<preference>1593095882</preference>
</discussion_sub>
<discussion_sub id="27">
<userid>8</userid>
<preference>1593095987</preference>
</discussion_sub>
<discussion_sub id="28">
<userid>9</userid>
<preference>1593096052</preference>
</discussion_sub>
</discussion_subs>
</discussion>
</discussions>
<subscriptions>
</subscriptions>
<digests>
</digests>
<readposts>
</readposts>
<trackedprefs>
</trackedprefs>
<poststags>
</poststags>
</forum>
</activity>