PUNKT-11 Front-end aplikacji StudyCave
This commit is contained in:
parent
6a5655cca9
commit
5fefcef27f
68
.angular-cli.json
Normal file
68
.angular-cli.json
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
{
|
||||||
|
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||||
|
"project": {
|
||||||
|
"name": "study-cave"
|
||||||
|
},
|
||||||
|
"apps": [
|
||||||
|
{
|
||||||
|
"root": "src",
|
||||||
|
"outDir": "dist",
|
||||||
|
"assets": [
|
||||||
|
"assets",
|
||||||
|
"./favicon.ico"
|
||||||
|
],
|
||||||
|
"index": "index.html",
|
||||||
|
"main": "main.ts",
|
||||||
|
"polyfills": "polyfills.ts",
|
||||||
|
"test": "test.ts",
|
||||||
|
"tsconfig": "tsconfig.app.json",
|
||||||
|
"testTsconfig": "tsconfig.spec.json",
|
||||||
|
"prefix": "app",
|
||||||
|
"styles": [
|
||||||
|
"../node_modules/bootstrap/dist/css/bootstrap.min.css",
|
||||||
|
"../node_modules/primeicons/primeicons.css",
|
||||||
|
"../node_modules/primeng/resources/primeng.min.css",
|
||||||
|
"../node_modules/primeng/resources/themes/luna-amber/theme.css",
|
||||||
|
"../node_modules/primeng/resources/components/dialog/dialog.css",
|
||||||
|
"styles.css"
|
||||||
|
],
|
||||||
|
"scripts": [
|
||||||
|
"../node_modules/jquery/dist/jquery.min.js",
|
||||||
|
"../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"
|
||||||
|
],
|
||||||
|
"environmentSource": "environments/environment.ts",
|
||||||
|
"environments": {
|
||||||
|
"dev": "environments/environment.ts",
|
||||||
|
"prod": "environments/environment.prod.ts"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"e2e": {
|
||||||
|
"protractor": {
|
||||||
|
"config": "./protractor.conf.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint": [
|
||||||
|
{
|
||||||
|
"project": "src/tsconfig.app.json",
|
||||||
|
"exclude": "**/node_modules/**"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"project": "src/tsconfig.spec.json",
|
||||||
|
"exclude": "**/node_modules/**"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"project": "e2e/tsconfig.e2e.json",
|
||||||
|
"exclude": "**/node_modules/**"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"test": {
|
||||||
|
"karma": {
|
||||||
|
"config": "./karma.conf.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaults": {
|
||||||
|
"styleExt": "css",
|
||||||
|
"component": {}
|
||||||
|
}
|
||||||
|
}
|
13
.editorconfig
Normal file
13
.editorconfig
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Editor configuration, see http://editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
max_line_length = off
|
||||||
|
trim_trailing_whitespace = false
|
43
.gitignore
vendored
Normal file
43
.gitignore
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# compiled output
|
||||||
|
/dist
|
||||||
|
/tmp
|
||||||
|
/out-tsc
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
package-lock.json
|
||||||
|
|
||||||
|
# IDEs and editors
|
||||||
|
/.idea
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.c9/
|
||||||
|
*.launch
|
||||||
|
.settings/
|
||||||
|
*.sublime-workspace
|
||||||
|
|
||||||
|
# IDE - VSCode
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
|
||||||
|
# misc
|
||||||
|
/.sass-cache
|
||||||
|
/connect.lock
|
||||||
|
/coverage
|
||||||
|
/libpeerconnection.log
|
||||||
|
npm-debug.log
|
||||||
|
testem.log
|
||||||
|
/typings
|
||||||
|
|
||||||
|
# e2e
|
||||||
|
/e2e/*.js
|
||||||
|
/e2e/*.map
|
||||||
|
|
||||||
|
# System Files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
7
.htaccess
Normal file
7
.htaccess
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Options +FollowSymLinks
|
||||||
|
|
||||||
|
RewriteEngine On
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-d
|
||||||
|
RewriteCond %{REQUEST_URI} !index
|
||||||
|
RewriteRule (.*) index.html [L]
|
18
.vscode/launch.json
vendored
Normal file
18
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "node",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Launch Program",
|
||||||
|
"program": "${workspaceFolder}\\serve",
|
||||||
|
"preLaunchTask": "tsc: build - tsconfig.json",
|
||||||
|
"outFiles": [
|
||||||
|
"${workspaceFolder}/dist/out-tsc/**/*.js"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
14
e2e/app.e2e-spec.ts
Normal file
14
e2e/app.e2e-spec.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { AppPage } from './app.po';
|
||||||
|
|
||||||
|
describe('study-cave App', () => {
|
||||||
|
let page: AppPage;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
page = new AppPage();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display welcome message', () => {
|
||||||
|
page.navigateTo();
|
||||||
|
expect(page.getParagraphText()).toEqual('Welcome to app!');
|
||||||
|
});
|
||||||
|
});
|
11
e2e/app.po.ts
Normal file
11
e2e/app.po.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { browser, by, element } from 'protractor';
|
||||||
|
|
||||||
|
export class AppPage {
|
||||||
|
navigateTo() {
|
||||||
|
return browser.get('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
getParagraphText() {
|
||||||
|
return element(by.css('app-root h1')).getText();
|
||||||
|
}
|
||||||
|
}
|
14
e2e/tsconfig.e2e.json
Normal file
14
e2e/tsconfig.e2e.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"extends": "../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../out-tsc/e2e",
|
||||||
|
"baseUrl": "./",
|
||||||
|
"module": "commonjs",
|
||||||
|
"target": "es5",
|
||||||
|
"types": [
|
||||||
|
"jasmine",
|
||||||
|
"jasminewd2",
|
||||||
|
"node"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
33
karma.conf.js
Normal file
33
karma.conf.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Karma configuration file, see link for more information
|
||||||
|
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||||
|
|
||||||
|
module.exports = function (config) {
|
||||||
|
config.set({
|
||||||
|
basePath: '',
|
||||||
|
frameworks: ['jasmine', '@angular/cli'],
|
||||||
|
plugins: [
|
||||||
|
require('karma-jasmine'),
|
||||||
|
require('karma-chrome-launcher'),
|
||||||
|
require('karma-jasmine-html-reporter'),
|
||||||
|
require('karma-coverage-istanbul-reporter'),
|
||||||
|
require('@angular/cli/plugins/karma')
|
||||||
|
],
|
||||||
|
client:{
|
||||||
|
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||||
|
},
|
||||||
|
coverageIstanbulReporter: {
|
||||||
|
reports: [ 'html', 'lcovonly' ],
|
||||||
|
fixWebpackSourcePaths: true
|
||||||
|
},
|
||||||
|
angularCli: {
|
||||||
|
environment: 'dev'
|
||||||
|
},
|
||||||
|
reporters: ['progress', 'kjhtml'],
|
||||||
|
port: 9876,
|
||||||
|
colors: true,
|
||||||
|
logLevel: config.LOG_INFO,
|
||||||
|
autoWatch: true,
|
||||||
|
browsers: ['Chrome'],
|
||||||
|
singleRun: false
|
||||||
|
});
|
||||||
|
};
|
68
package.json
Normal file
68
package.json
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
{
|
||||||
|
"name": "study-cave",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"ng": "ng",
|
||||||
|
"start": "ng serve",
|
||||||
|
"build": "ng build",
|
||||||
|
"test": "ng test",
|
||||||
|
"lint": "ng lint",
|
||||||
|
"e2e": "ng e2e"
|
||||||
|
},
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@angular/animations": "^5.0.0",
|
||||||
|
"@angular/cdk": "^5.2.5",
|
||||||
|
"@angular/common": "^5.0.0",
|
||||||
|
"@angular/compiler": "^5.0.0",
|
||||||
|
"@angular/core": "^5.0.0",
|
||||||
|
"@angular/forms": "^5.0.0",
|
||||||
|
"@angular/http": "^5.0.0",
|
||||||
|
"@angular/material": "^5.2.5",
|
||||||
|
"@angular/platform-browser": "^5.0.0",
|
||||||
|
"@angular/platform-browser-dynamic": "^5.0.0",
|
||||||
|
"@angular/router": "^5.0.0",
|
||||||
|
"@auth0/angular-jwt": "^2.0.0",
|
||||||
|
"@fortawesome/fontawesome-svg-core": "^1.2.10",
|
||||||
|
"@fortawesome/free-solid-svg-icons": "^5.6.1",
|
||||||
|
"ag-grid-angular": "^19.1.2",
|
||||||
|
"ag-grid-community": "^19.1.4",
|
||||||
|
"ajv": "^6.0.0",
|
||||||
|
"angular-font-awesome": "^3.1.2",
|
||||||
|
"angular2-jwt": "^0.2.3",
|
||||||
|
"bootstrap": "^4.1.2",
|
||||||
|
"core-js": "^2.4.1",
|
||||||
|
"font-awesome": "^4.7.0",
|
||||||
|
"jquery": "^3.3.1",
|
||||||
|
"jquery-ui": "^1.12.1",
|
||||||
|
"picasso.js": "^0.18.2",
|
||||||
|
"popper.js": "^1.12.9",
|
||||||
|
"primeicons": "^1.0.0",
|
||||||
|
"primeng": "^6.1.7",
|
||||||
|
"rxjs": "^5.5.2",
|
||||||
|
"zone.js": "^0.8.14"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@angular-devkit/core": "^7.1.2",
|
||||||
|
"@angular/cli": "^1.7.4",
|
||||||
|
"@angular/compiler-cli": "^5.0.0",
|
||||||
|
"@angular/language-service": "^5.0.0",
|
||||||
|
"@types/jasmine": "~2.5.53",
|
||||||
|
"@types/jasminewd2": "~2.0.2",
|
||||||
|
"@types/node": "~6.0.60",
|
||||||
|
"codelyzer": "^4.0.1",
|
||||||
|
"jasmine-core": "~2.5.2",
|
||||||
|
"jasmine-spec-reporter": "~4.1.0",
|
||||||
|
"karma": "~1.7.0",
|
||||||
|
"karma-chrome-launcher": "~2.1.1",
|
||||||
|
"karma-cli": "~1.0.1",
|
||||||
|
"karma-coverage-istanbul-reporter": "^1.2.1",
|
||||||
|
"karma-jasmine": "~1.1.0",
|
||||||
|
"karma-jasmine-html-reporter": "^0.2.2",
|
||||||
|
"protractor": "~5.1.2",
|
||||||
|
"ts-node": "~3.2.0",
|
||||||
|
"tslint": "~5.7.0",
|
||||||
|
"typescript": "~2.4.2"
|
||||||
|
}
|
||||||
|
}
|
28
protractor.conf.js
Normal file
28
protractor.conf.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// Protractor configuration file, see link for more information
|
||||||
|
// https://github.com/angular/protractor/blob/master/lib/config.ts
|
||||||
|
|
||||||
|
const { SpecReporter } = require('jasmine-spec-reporter');
|
||||||
|
|
||||||
|
exports.config = {
|
||||||
|
allScriptsTimeout: 11000,
|
||||||
|
specs: [
|
||||||
|
'./e2e/**/*.e2e-spec.ts'
|
||||||
|
],
|
||||||
|
capabilities: {
|
||||||
|
'browserName': 'chrome'
|
||||||
|
},
|
||||||
|
directConnect: true,
|
||||||
|
baseUrl: 'http://localhost:4200/',
|
||||||
|
framework: 'jasmine',
|
||||||
|
jasmineNodeOpts: {
|
||||||
|
showColors: true,
|
||||||
|
defaultTimeoutInterval: 30000,
|
||||||
|
print: function() {}
|
||||||
|
},
|
||||||
|
onPrepare() {
|
||||||
|
require('ts-node').register({
|
||||||
|
project: 'e2e/tsconfig.e2e.json'
|
||||||
|
});
|
||||||
|
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
|
||||||
|
}
|
||||||
|
};
|
108
src/app/app-routing.module.ts
Normal file
108
src/app/app-routing.module.ts
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
|
||||||
|
import { FlashcardsModule } from './flashcards/flashcards.module';
|
||||||
|
import { TestsModule } from './tests/tests.module';
|
||||||
|
import { UserModule } from './user/user.module';
|
||||||
|
import { GroupsModule } from './groups/groups.module';
|
||||||
|
|
||||||
|
import { AuthGuard } from './auth-guard.service';
|
||||||
|
|
||||||
|
import { FlashcardsComponent } from './flashcards/flashcards/flashcards.component';
|
||||||
|
import { FlashcardsSetsListComponent } from './flashcards/flashcards-sets-list/flashcards-sets-list.component';
|
||||||
|
import { FlashcardsAddComponent } from './flashcards/flashcards-add/flashcards-add.component';
|
||||||
|
import { FlashcardsAddCsvComponent } from './flashcards/flashcards-add-csv/flashcards-add-csv.component';
|
||||||
|
import { FlashcardsAddTableComponent } from './flashcards/flashcards-add-table/flashcards-add-table.component';
|
||||||
|
import { FlashcardsSetDetailComponent } from './flashcards/flashcards-set-detail/flashcards-set-detail.component';
|
||||||
|
import { FlashcardsPairsTestComponent } from './flashcards/flashcards-pairs-test/flashcards-pairs-test.component';
|
||||||
|
import { FlashcardsMemoryTestComponent } from './flashcards/flashcards-memory-test/flashcards-memory-test.component';
|
||||||
|
import { FlashcardsEditTableComponent } from './flashcards/flashcards-edit-table/flashcards-edit-table.component';
|
||||||
|
import { FlashcardsFillingInTestComponent } from './flashcards/flashcards-filling-in-test/flashcards-filling-in-test.component';
|
||||||
|
import { FlashcardsTyperaceTestComponent } from './flashcards/flashcards-typerace-test/flashcards-typerace-test.component';
|
||||||
|
import { HomePageComponent } from './home-page/home-page.component';
|
||||||
|
import { LoginComponent } from './login/login.component';
|
||||||
|
import { TestMakerComponent } from './tests/test-maker/test-maker.component';
|
||||||
|
import { TestEditComponent } from './tests/test-edit/test-edit.component';
|
||||||
|
import { RegisterComponent } from './user/register/register.component';
|
||||||
|
import { UserComponent } from './user/user/user.component';
|
||||||
|
import { EditUserComponent } from './user/edit-user/edit-user.component';
|
||||||
|
import { MaterialsMenuComponent } from './materials/materials-menu/materials-menu.component';
|
||||||
|
import { MaterialsListComponent } from './materials/materials-list/materials-list.component';
|
||||||
|
import { MaterialsAddComponent } from './materials/materials-add/materials-add.component';
|
||||||
|
import { TestsListComponent } from './tests/tests-list/tests-list.component';
|
||||||
|
import { WorkInProgressComponent } from './work-in-progress/work-in-progress.component';
|
||||||
|
import { TestDetailsComponent } from './tests/test-details/test-details.component';
|
||||||
|
import { MaterialsDetailsComponent } from './materials/materials-details/materials-details.component';
|
||||||
|
import { MyGroupsComponent } from './groups/my-groups/my-groups.component';
|
||||||
|
import { GroupCreatorComponent } from './groups/group-creator/group-creator.component';
|
||||||
|
import { JoinToGroupComponent } from './groups/join-to-group/join-to-group.component';
|
||||||
|
import { GroupDetailsComponent } from './groups/group-details/group-details.component';
|
||||||
|
import { ManageGroupComponent } from './groups/manage-group/manage-group.component';
|
||||||
|
import { SharingResourcesInGroupsComponent } from './groups/sharing-resources-in-groups/sharing-resources-in-groups.component';
|
||||||
|
import { CommentsComponent } from './shared/comments/comments.component';
|
||||||
|
import { SharedModule } from './shared/shared.module';
|
||||||
|
import { WaitingResourcesComponent } from './groups/waiting-resources/waiting-resources.component';
|
||||||
|
import { BagdesComponent } from './user/bagdes/bagdes.component';
|
||||||
|
import { RankingComponent } from './groups/ranking/ranking.component';
|
||||||
|
import { HistoryOfActivityInGroupComponent } from './groups/history-of-activity-in-group/history-of-activity-in-group.component';
|
||||||
|
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{ path: 'login', component: LoginComponent },
|
||||||
|
{ path: '', component: HomePageComponent },
|
||||||
|
{ path: 'home', component: HomePageComponent },
|
||||||
|
{ path: 'flashcards', component: FlashcardsComponent },
|
||||||
|
{ path: 'flashcards/sets', component: FlashcardsSetsListComponent },
|
||||||
|
{ path: 'flashcards/add', component: FlashcardsAddComponent, canActivate: [AuthGuard] },
|
||||||
|
{ path: 'flashcards/add/table', component: FlashcardsAddTableComponent , canActivate: [AuthGuard]},
|
||||||
|
{ path: 'flashcards/add/csv', component: FlashcardsAddCsvComponent, canActivate: [AuthGuard] },
|
||||||
|
{ path: 'flashcards/sets/:id', component: FlashcardsSetDetailComponent },
|
||||||
|
{ path: 'flashcards/test-gen/flashcards-pairs/:id', component: FlashcardsPairsTestComponent },
|
||||||
|
{ path: 'flashcards/test-gen/flashcards-memory/:id', component: FlashcardsMemoryTestComponent },
|
||||||
|
{ path: 'flashcards/test-gen/flashcards-typerace/:id', component: FlashcardsTyperaceTestComponent },
|
||||||
|
{ path: 'flashcards/test-gen/flashcards-filling-in/:id', component: FlashcardsFillingInTestComponent },
|
||||||
|
{ path: 'flashcards/sets/edit/:id', component: FlashcardsEditTableComponent, canActivate: [AuthGuard] },
|
||||||
|
{ path: 'tests', component: TestsListComponent},
|
||||||
|
{ path: 'tests/:id', component: TestDetailsComponent},
|
||||||
|
{ path: 'tests/edit/:id', component: TestEditComponent, canActivate: [AuthGuard]},
|
||||||
|
{ path: 'test-maker', component: TestMakerComponent, canActivate: [AuthGuard] },
|
||||||
|
{ path: 'sign-up', component: RegisterComponent },
|
||||||
|
{ path: 'profile/:id', component: UserComponent, canActivate: [AuthGuard] },
|
||||||
|
{ path: 'edit-profile', component: EditUserComponent, canActivate: [AuthGuard] },
|
||||||
|
{ path: 'materials', component: MaterialsMenuComponent },
|
||||||
|
{ path: 'materials/list', component: MaterialsListComponent },
|
||||||
|
{ path: 'materials/add-materials', component: MaterialsAddComponent, canActivate: [AuthGuard] },
|
||||||
|
{ path: 'work-in-progress', component: WorkInProgressComponent },
|
||||||
|
{ path: 'materials/:id', component: MaterialsDetailsComponent},
|
||||||
|
{ path: 'my-groups', component: MyGroupsComponent, canActivate: [AuthGuard] },
|
||||||
|
{ path: 'create-group', component: GroupCreatorComponent, canActivate: [AuthGuard] },
|
||||||
|
{ path: 'join-to-group', component: JoinToGroupComponent, canActivate: [AuthGuard] },
|
||||||
|
{ path: 'groups/:id', component: GroupDetailsComponent, canActivate: [AuthGuard] },
|
||||||
|
{ path: 'groups/manage/:id', component: ManageGroupComponent, canActivate: [AuthGuard] },
|
||||||
|
{ path: 'groups/add-resources/:id', component: SharingResourcesInGroupsComponent , canActivate: [AuthGuard] },
|
||||||
|
{ path: 'groups/waiting-resources/:id', component: WaitingResourcesComponent, canActivate: [AuthGuard] },
|
||||||
|
{ path: 'badges', component: BagdesComponent, canActivate: [AuthGuard] },
|
||||||
|
{ path: 'groups/ranking/:id', component: RankingComponent , canActivate: [AuthGuard] },
|
||||||
|
{ path: 'groups/waiting-resources/:id', component: WaitingResourcesComponent, canActivate: [AuthGuard] },
|
||||||
|
{ path: 'groups/waiting-resources/:id', component: WaitingResourcesComponent, canActivate: [AuthGuard] },
|
||||||
|
{ path: 'groups/history/:id', component: HistoryOfActivityInGroupComponent, canActivate: [AuthGuard] }
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
RouterModule.forRoot(routes, {onSameUrlNavigation: 'reload', useHash: false}),
|
||||||
|
FlashcardsModule,
|
||||||
|
TestsModule,
|
||||||
|
UserModule,
|
||||||
|
GroupsModule,
|
||||||
|
SharedModule
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
RouterModule,
|
||||||
|
FlashcardsModule,
|
||||||
|
TestsModule,
|
||||||
|
UserModule,
|
||||||
|
SharedModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class AppRoutingModule { }
|
30
src/app/app.component.css
Normal file
30
src/app/app.component.css
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
.content{
|
||||||
|
width: 100%;
|
||||||
|
position: fixed;
|
||||||
|
margin-top: 100px;
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
height: calc(100vh - 154px);
|
||||||
|
min-height: calc(100vh - 154px);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper{
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 800px) {
|
||||||
|
.content{
|
||||||
|
margin-top: 170px;
|
||||||
|
height: calc(100vh - 200px);
|
||||||
|
min-height: calc(100vh - 200px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 352px) {
|
||||||
|
.content{
|
||||||
|
margin-top: 170px;
|
||||||
|
height: calc(100vh - 250px);
|
||||||
|
min-height: calc(100vh - 250px);
|
||||||
|
}
|
||||||
|
}
|
8
src/app/app.component.html
Normal file
8
src/app/app.component.html
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<div class="wrapper">
|
||||||
|
<app-main-navigation></app-main-navigation>
|
||||||
|
<div class="content">
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
<br /><br /><br /><br />
|
||||||
|
</div>
|
||||||
|
<app-footer></app-footer>
|
||||||
|
</div>
|
31
src/app/app.component.spec.ts
Normal file
31
src/app/app.component.spec.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { RoutingStateService } from './routing-state.service';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
|
||||||
|
describe('AppComponent', () => {
|
||||||
|
let component: AppComponent;
|
||||||
|
let fixture: ComponentFixture<AppComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [
|
||||||
|
AppComponent
|
||||||
|
],
|
||||||
|
providers: [RoutingStateService],
|
||||||
|
imports: [RouterTestingModule],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(AppComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create the app', async(() => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
}));
|
||||||
|
});
|
17
src/app/app.component.ts
Normal file
17
src/app/app.component.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { Component, OnInit, Input } from '@angular/core';
|
||||||
|
import { RoutingStateService } from './routing-state.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
templateUrl: './app.component.html',
|
||||||
|
styleUrls: ['./app.component.css']
|
||||||
|
})
|
||||||
|
export class AppComponent implements OnInit {
|
||||||
|
title = 'app';
|
||||||
|
|
||||||
|
constructor(routingState: RoutingStateService) {
|
||||||
|
routingState.loadRouting();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {}
|
||||||
|
}
|
60
src/app/app.module.ts
Normal file
60
src/app/app.module.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { HttpModule } from '@angular/http';
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
|
||||||
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
|
import { MaterialsModule } from './materials/materials.module';
|
||||||
|
import { FlashcardsModule } from './flashcards/flashcards.module';
|
||||||
|
import { TestsModule } from './tests/tests.module';
|
||||||
|
import { GroupsModule } from './groups/groups.module';
|
||||||
|
import { UserModule } from './user/user.module';
|
||||||
|
|
||||||
|
import { httpInterceptorProviders } from './http-interceptors/index';
|
||||||
|
import { LocationStrategy, HashLocationStrategy, PathLocationStrategy } from '@angular/common';
|
||||||
|
|
||||||
|
import { LoginComponent } from './login/login.component';
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
import { MainNavigationComponent } from './main-navigation/main-navigation.component';
|
||||||
|
import { FooterComponent } from './footer/footer.component';
|
||||||
|
import { HomePageComponent } from './home-page/home-page.component';
|
||||||
|
import { WorkInProgressComponent } from './work-in-progress/work-in-progress.component';
|
||||||
|
|
||||||
|
import { AuthGuard } from './auth-guard.service';
|
||||||
|
import { AuthenticationService } from './authentication.service';
|
||||||
|
import { SharedModule } from './shared/shared.module';
|
||||||
|
import { RoutingStateService } from './routing-state.service';
|
||||||
|
|
||||||
|
import { AutofocusDirective } from './autofocus.directive';
|
||||||
|
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
LoginComponent,
|
||||||
|
AppComponent,
|
||||||
|
MainNavigationComponent,
|
||||||
|
FooterComponent,
|
||||||
|
HomePageComponent,
|
||||||
|
WorkInProgressComponent,
|
||||||
|
AutofocusDirective
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
BrowserModule,
|
||||||
|
FormsModule,
|
||||||
|
HttpModule,
|
||||||
|
HttpClientModule,
|
||||||
|
AppRoutingModule,
|
||||||
|
FlashcardsModule,
|
||||||
|
MaterialsModule,
|
||||||
|
TestsModule,
|
||||||
|
GroupsModule,
|
||||||
|
UserModule,
|
||||||
|
SharedModule
|
||||||
|
],
|
||||||
|
providers: [AuthGuard, httpInterceptorProviders, AuthenticationService, RoutingStateService, {
|
||||||
|
provide: LocationStrategy, useClass: PathLocationStrategy
|
||||||
|
}],
|
||||||
|
bootstrap: [AppComponent]
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
16
src/app/auth-guard.service.spec.ts
Normal file
16
src/app/auth-guard.service.spec.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { AuthGuard } from './auth-guard.service';
|
||||||
|
|
||||||
|
describe('AuthGuardService', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [AuthGuard],
|
||||||
|
imports: [RouterTestingModule]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([AuthGuard], (service: AuthGuard) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
|
});
|
19
src/app/auth-guard.service.ts
Normal file
19
src/app/auth-guard.service.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
import {Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot} from '@angular/router';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AuthGuard implements CanActivate {
|
||||||
|
constructor(private router: Router) {
|
||||||
|
}
|
||||||
|
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
|
||||||
|
if (localStorage.getItem('currentUser')) {
|
||||||
|
// logged in so return true
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// tslint:disable-next-line:one-line
|
||||||
|
else {
|
||||||
|
this.router.navigate(['/login']);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
src/app/authentication.service.spec.ts
Normal file
19
src/app/authentication.service.spec.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
import { AuthenticationService } from './authentication.service';
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
|
|
||||||
|
describe('AuthenticationService', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [AuthenticationService],
|
||||||
|
imports: [HttpClientModule, MatSnackBarModule],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([AuthenticationService], (service: AuthenticationService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
|
});
|
71
src/app/authentication.service.ts
Normal file
71
src/app/authentication.service.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import { Injectable, Output, EventEmitter } from '@angular/core';
|
||||||
|
import { HttpClient, HttpHeaders, HttpRequest, HttpEvent } from '@angular/common/http';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import 'rxjs/add/operator/map';
|
||||||
|
import 'rxjs/add/operator/catch';
|
||||||
|
import 'rxjs/add/observable/throw';
|
||||||
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
|
import { Subject } from 'rxjs/Subject';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AuthenticationService {
|
||||||
|
@Output() getLoggedInName: EventEmitter<any> = new EventEmitter();
|
||||||
|
private headers = new HttpHeaders({ 'Content-Type': 'application/json' });
|
||||||
|
private storageSub = new Subject<boolean>();
|
||||||
|
public token: string;
|
||||||
|
constructor(private http: HttpClient, public snackBar: MatSnackBar) {
|
||||||
|
}
|
||||||
|
|
||||||
|
watchStorage(): Observable<any> {
|
||||||
|
return this.storageSub.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
watchStorageChanges(): void {
|
||||||
|
this.storageSub.next(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
login(username: string, password: string): Observable<boolean> {
|
||||||
|
return this.http.post('login', { password: password, username: username }, { headers: this.headers, observe: 'response' })
|
||||||
|
.map((response) => {
|
||||||
|
// czy login ok jeśli w response jest token
|
||||||
|
// const token = response.json() && response.json().token;
|
||||||
|
const token = response.headers.get('authorization');
|
||||||
|
if (token) {
|
||||||
|
// store username and jwt token w local storage aby nie wylogowało przy zmianie stron
|
||||||
|
localStorage.setItem('currentUser', JSON.stringify({ username: username, authorization: token }));
|
||||||
|
this.getLoggedInName.emit('logged');
|
||||||
|
this.storageSub.next(true);
|
||||||
|
this.snackBar.open('Zalogowano pomyślnie!', null,
|
||||||
|
{ duration: 3000, verticalPosition: 'top', panelClass: ['snackbar-success'] });
|
||||||
|
// return true jeśli ok
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// return false jeśli nie
|
||||||
|
this.getLoggedInName.emit('notLogged');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}).catch((error: any) => Observable.throw(error.json().error || 'Server error'));
|
||||||
|
}
|
||||||
|
|
||||||
|
getToken(): String {
|
||||||
|
const currentUser = JSON.parse(localStorage.getItem('currentUser'));
|
||||||
|
if (currentUser.authorization == null) {
|
||||||
|
return ' ';
|
||||||
|
} else {
|
||||||
|
return currentUser.authorization;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoggedIn(): boolean {
|
||||||
|
const token: String = this.getToken();
|
||||||
|
return token && token.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
logout(): void {
|
||||||
|
// clear token remove user from local storage to log user out
|
||||||
|
this.snackBar.open('Wylogowano pomyślnie!', null,
|
||||||
|
{ duration: 3000, verticalPosition: 'top', panelClass: ['snackbar-success'] });
|
||||||
|
localStorage.removeItem('currentUser');
|
||||||
|
}
|
||||||
|
}
|
7
src/app/autofocus.directive.spec.ts
Normal file
7
src/app/autofocus.directive.spec.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { AutofocusDirective } from './autofocus.directive';
|
||||||
|
|
||||||
|
describe('AutofocusDirective', () => {
|
||||||
|
it('should create an instance', () => {
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
15
src/app/autofocus.directive.ts
Normal file
15
src/app/autofocus.directive.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { Directive, AfterViewInit, ElementRef } from '@angular/core';
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
selector: '[appAutofocus]'
|
||||||
|
})
|
||||||
|
export class AutofocusDirective implements AfterViewInit {
|
||||||
|
|
||||||
|
constructor(private el: ElementRef) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit() {
|
||||||
|
this.el.nativeElement.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
8
src/app/filter-user.pipe.spec.ts
Normal file
8
src/app/filter-user.pipe.spec.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { FilterUserPipe } from './filter-user.pipe';
|
||||||
|
|
||||||
|
describe('FilterUserPipe', () => {
|
||||||
|
it('create an instance', () => {
|
||||||
|
const pipe = new FilterUserPipe();
|
||||||
|
expect(pipe).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
20
src/app/filter-user.pipe.ts
Normal file
20
src/app/filter-user.pipe.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { Pipe, PipeTransform } from '@angular/core';
|
||||||
|
|
||||||
|
@Pipe({
|
||||||
|
name: 'filterUser'
|
||||||
|
})
|
||||||
|
export class FilterUserPipe implements PipeTransform {
|
||||||
|
|
||||||
|
transform(sets: any, searchOwner: any ): any {
|
||||||
|
if (searchOwner === undefined || sets === undefined) {
|
||||||
|
return sets;
|
||||||
|
} else {
|
||||||
|
return sets.filter(function(set){
|
||||||
|
return set.owner.toString() === (searchOwner.toString());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
8
src/app/filter.pipe.spec.ts
Normal file
8
src/app/filter.pipe.spec.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { FilterPipe } from './filter.pipe';
|
||||||
|
|
||||||
|
describe('FilterPipe', () => {
|
||||||
|
it('create an instance', () => {
|
||||||
|
const pipe = new FilterPipe();
|
||||||
|
expect(pipe).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
20
src/app/filter.pipe.ts
Normal file
20
src/app/filter.pipe.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { Pipe, PipeTransform } from '@angular/core';
|
||||||
|
|
||||||
|
@Pipe({
|
||||||
|
name: 'filter'
|
||||||
|
})
|
||||||
|
export class FilterPipe implements PipeTransform {
|
||||||
|
|
||||||
|
transform(sets: any, search: any ): any {
|
||||||
|
if (search === undefined || sets === undefined) {
|
||||||
|
return sets;
|
||||||
|
} else {
|
||||||
|
return sets.filter(function(set){
|
||||||
|
return set.permission === (search);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
|||||||
|
.description {
|
||||||
|
background-color: #22272a;
|
||||||
|
padding: 1rem;
|
||||||
|
margin-top: 1rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
background-color: #181616;
|
||||||
|
padding: 30px;
|
||||||
|
margin-top: 2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper-description {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper-add {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-content: center;
|
||||||
|
margin-bottom: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper{
|
||||||
|
width: 100%;
|
||||||
|
padding: 30px;
|
||||||
|
min-height: 100%;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content{
|
||||||
|
background-color: #181616;
|
||||||
|
padding: 30px;
|
||||||
|
margin-top: 2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
ag-grid-angular{
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons-container > div{
|
||||||
|
margin: 10px;
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
<div class="wrapper">
|
||||||
|
<div class="content">
|
||||||
|
<div class="buttons-container">
|
||||||
|
<button class="btn btn-study-cave" routerLink="/flashcards/sets"><i class="fas fa-arrow-left"></i> WRÓĆ DO LISTY</button>
|
||||||
|
<button class="btn btn-study-cave" routerLink="/flashcards/add/table"><i class="fas fa-table"></i> DODAJ ZA POMOCĄ TABELI</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="wrapper-add">
|
||||||
|
<div class="container">
|
||||||
|
<h1>Importowanie zestawu z pliku CSV</h1>
|
||||||
|
<br />
|
||||||
|
<h3>Twój plik CSV powinien mieć poniższy format:</h3>
|
||||||
|
<div class="wrapper-description">
|
||||||
|
<div class="description row">
|
||||||
|
<h4 class="col-8 ml-4">
|
||||||
|
nazwa zestawu;kategoria <br />
|
||||||
|
lewa strona fiszki;prawa strona fiszki <br />
|
||||||
|
lewa strona fiszki;prawa strona fiszki <br />
|
||||||
|
lewa strona fiszki;prawa strona fiszki <br />
|
||||||
|
.....
|
||||||
|
</h4>
|
||||||
|
<p class="col-3 ml-4">
|
||||||
|
<u>Przykład:</u> <br />
|
||||||
|
zwierzęta;angielski <br />
|
||||||
|
pies;dog <br />
|
||||||
|
kot;cat <br />
|
||||||
|
królik;rabbit <br />
|
||||||
|
ryba;fish <br />
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div *ngIf="currentFileUpload" class="progress">
|
||||||
|
<div class="progress-bar progress-bar-info progress-bar-striped"
|
||||||
|
role="progressbar" attr.aria-valuenow="{{progress.percentage}}"
|
||||||
|
aria-valuemin="0" aria-valuemax="100"
|
||||||
|
[ngStyle]="{width:progress.percentage+'%'}">
|
||||||
|
{{progress.percentage}}%</div>
|
||||||
|
</div>
|
||||||
|
<label>
|
||||||
|
<p>Wybierz plik:</p>
|
||||||
|
<input type="file" accept=".csv" (change)="selectFile($event)">
|
||||||
|
</label>
|
||||||
|
<div>
|
||||||
|
<br />
|
||||||
|
<input type="checkbox" name="{{ permission }}" class="form-control" [checked]="permission" (change)="changePermission()"/><b>Udostępnij publicznie</b>
|
||||||
|
</div><br />
|
||||||
|
<button class="btn btn-study-cave" [disabled]="!selectedFiles" (click)="upload()"><i class="fas fa-check-circle"></i> Dodaj fiszki!</button>
|
||||||
|
<br /><br />
|
||||||
|
<button class="btn btn-study-cave" routerLink="/flashcards/sets/"><i class="fas fa-arrow-left"></i> Powrót</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,34 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FlashcardsAddCsvComponent } from './flashcards-add-csv.component';
|
||||||
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { AuthenticationService } from '../../authentication.service';
|
||||||
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
|
|
||||||
|
describe('FlashcardsAddCsvComponent', () => {
|
||||||
|
let component: FlashcardsAddCsvComponent;
|
||||||
|
let fixture: ComponentFixture<FlashcardsAddCsvComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ FlashcardsAddCsvComponent ],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA],
|
||||||
|
providers: [FlashcardsService, AuthenticationService],
|
||||||
|
imports: [HttpClientModule, RouterTestingModule, MatSnackBarModule]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(FlashcardsAddCsvComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,75 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { HttpClient, HttpResponse, HttpEventType } from '@angular/common/http';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-flashcards-add-csv',
|
||||||
|
templateUrl: './flashcards-add-csv.component.html',
|
||||||
|
styleUrls: ['./flashcards-add-csv.component.css']
|
||||||
|
})
|
||||||
|
export class FlashcardsAddCsvComponent implements OnInit {
|
||||||
|
|
||||||
|
selectedFiles: FileList;
|
||||||
|
currentFileUpload: File;
|
||||||
|
progress: { percentage: number } = { percentage: 0 };
|
||||||
|
currentUser = JSON.parse(localStorage.getItem('currentUser'));
|
||||||
|
user: string;
|
||||||
|
permission: Boolean = true;
|
||||||
|
constructor(private uploadService: FlashcardsService, private router: Router, public snackBar: MatSnackBar) { }
|
||||||
|
|
||||||
|
ngOnInit() { this.isLoggedIn(); }
|
||||||
|
|
||||||
|
isLoggedIn() {
|
||||||
|
if (localStorage.getItem('currentUser') === null) {
|
||||||
|
this.user = 'Anonim';
|
||||||
|
} else {
|
||||||
|
this.user = this.currentUser.username;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
changePermission(): void {
|
||||||
|
this.permission = !this.permission;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectFile(event) {
|
||||||
|
this.selectedFiles = event.target.files;
|
||||||
|
}
|
||||||
|
|
||||||
|
upload() {
|
||||||
|
this.progress.percentage = 0;
|
||||||
|
const url = 'file/upload';
|
||||||
|
let p = 'Private';
|
||||||
|
if (this.permission) {
|
||||||
|
p = 'Public';
|
||||||
|
}
|
||||||
|
this.currentFileUpload = this.selectedFiles.item(0);
|
||||||
|
if (this.currentFileUpload.type === 'application/vnd.ms-excel') {
|
||||||
|
this.uploadService.pushFileToStorage(this.currentFileUpload, this.user, p, url).subscribe(
|
||||||
|
event => {
|
||||||
|
if (event.type === HttpEventType.UploadProgress) {
|
||||||
|
this.progress.percentage = Math.round(100 * event.loaded / event.total);
|
||||||
|
} else if (event instanceof HttpResponse) {
|
||||||
|
this.currentFileUpload = undefined;
|
||||||
|
this.snackBar.open(`Plik został zaimportowany.
|
||||||
|
Swoje fiszki możesz podejrzeć na liście zestawów fiszek
|
||||||
|
i tam je edytować jeśli zajdzie taka potrzeba :)`, null,
|
||||||
|
{ duration: 3000, verticalPosition: 'top', panelClass: ['snackbar-success'] });
|
||||||
|
this.router.navigate(['flashcards/sets']);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
this.snackBar.open('Coś poszło nie tak. Spróbuj ponownie później.', null,
|
||||||
|
{ duration: 3000, verticalPosition: 'top', panelClass: ['snackbar-error'] });
|
||||||
|
this.currentFileUpload = undefined;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.currentFileUpload = undefined;
|
||||||
|
this.snackBar.open('Wybierz plik CSV!', null,
|
||||||
|
{ duration: 3000, verticalPosition: 'top', panelClass: ['snackbar-error'] });
|
||||||
|
}
|
||||||
|
this.selectedFiles = undefined;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
table, th, td, tr {
|
||||||
|
border-width: 0;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
background-color: #181616;
|
||||||
|
padding: 30px;
|
||||||
|
margin-top: 2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper-add {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-content: center;
|
||||||
|
margin-bottom: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper{
|
||||||
|
width: 100%;
|
||||||
|
padding: 30px;
|
||||||
|
min-height: 100%;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content{
|
||||||
|
background-color: #181616;
|
||||||
|
padding: 30px;
|
||||||
|
margin-top: 2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
ag-grid-angular{
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons-container > div{
|
||||||
|
margin: 10px;
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
<div class="wrapper">
|
||||||
|
<div class="content">
|
||||||
|
<div class="buttons-container">
|
||||||
|
<button class="btn btn-study-cave" routerLink="/flashcards/sets"><i class="fas fa-arrow-left"></i> WRÓĆ DO LISTY</button>
|
||||||
|
<button class="btn btn-study-cave" routerLink="/flashcards/add/csv"><i class="fas fa-file-csv"></i> DODAJ ZA POMOCĄ CSV</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="wrapper-add">
|
||||||
|
<div class="container">
|
||||||
|
<h1>Tworzenie zestawu</h1>
|
||||||
|
<br />
|
||||||
|
<form ngNativeValidate action="/" method="post" #user="ngForm" (ngSubmit)="addTable(user.value)">
|
||||||
|
<label>
|
||||||
|
Wprowadź nazwę dla zestawu:
|
||||||
|
<input type="text" name="title" class="form-control" ngModel required />
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Wprowadź kategorię zestawu:
|
||||||
|
<input type="text" name="category" class="form-control" ngModel required />
|
||||||
|
</label>
|
||||||
|
<br />
|
||||||
|
<label>
|
||||||
|
Wypełnij tabelę fiszkami:
|
||||||
|
<table class="table table-striped table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Lewa strona</th>
|
||||||
|
<th>Prawa strona</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr *ngFor="let field of fieldArray; let i = index">
|
||||||
|
<td>
|
||||||
|
<input [(ngModel)]="field.left_side" class="form-control" type="text" name="{{field.left_side}}" />
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input [(ngModel)]="field.right_side" class="form-control" type="text" name="{{field.right_side}}" />
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-study-cave" type="button" (click)="deleteFieldValue(i)"><i class="fas fa-trash-alt"></i> Usuń fiszkę</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input class="form-control" type="text" id="newAttributeLeft" [(ngModel)]="newAttribute.left_side" name="newAttributeLeft" />
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input class="form-control" type="text" id="newAttributeRight" [(ngModel)]="newAttribute.right_side" name="newAttributeRight" />
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-study-cave" type="button" (click)="addFieldValue()"><i class="fas fa-plus"></i> Dodaj fiszkę</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</label>
|
||||||
|
<div>
|
||||||
|
<br />
|
||||||
|
<input type="checkbox" name="{{ permission }}" class="form-control" [checked]="permission" (change)="changePermission()"/>
|
||||||
|
<b>Udostępnij publicznie</b>
|
||||||
|
</div>
|
||||||
|
<br /><br />
|
||||||
|
<button class="btn btn-study-cave" type="submit"><i class="fas fa-check-circle"></i> Dodaj fiszki!</button>
|
||||||
|
<button class="btn btn-study-cave" routerLink="/flashcards/sets/"><i class="fas fa-arrow-left"></i> Powrót</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,44 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FlashcardsAddTableComponent } from './flashcards-add-table.component';
|
||||||
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { AuthenticationService } from '../../authentication.service';
|
||||||
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
|
describe('FlashcardsAddTableComponent', () => {
|
||||||
|
let component: FlashcardsAddTableComponent;
|
||||||
|
let fixture: ComponentFixture<FlashcardsAddTableComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ FlashcardsAddTableComponent ],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA],
|
||||||
|
providers: [FlashcardsService, AuthenticationService],
|
||||||
|
imports: [HttpClientModule, RouterTestingModule, MatSnackBarModule, FormsModule]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(FlashcardsAddTableComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Testowanie funkcji w klasie
|
||||||
|
it('should change permissions', () => {
|
||||||
|
expect(component.permission).toBe(true);
|
||||||
|
component.changePermission();
|
||||||
|
expect(component.permission).toBe(false);
|
||||||
|
component.changePermission();
|
||||||
|
expect(component.permission).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,84 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-flashcards-add-table',
|
||||||
|
templateUrl: './flashcards-add-table.component.html',
|
||||||
|
styleUrls: ['./flashcards-add-table.component.css']
|
||||||
|
})
|
||||||
|
export class FlashcardsAddTableComponent implements OnInit {
|
||||||
|
|
||||||
|
table: Boolean = false;
|
||||||
|
tableToSend: any = {};
|
||||||
|
public fieldArray: Array<any> = [];
|
||||||
|
newAttribute: any = {};
|
||||||
|
currentUser;
|
||||||
|
permission: Boolean = true;
|
||||||
|
|
||||||
|
constructor(private flashcardsService: FlashcardsService, public snackBar: MatSnackBar) { }
|
||||||
|
|
||||||
|
ngOnInit() { this.isLoggedIn(); }
|
||||||
|
|
||||||
|
changePermission(): void {
|
||||||
|
this.permission = !this.permission;
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoggedIn() {
|
||||||
|
if (localStorage.getItem('currentUser') === null) {
|
||||||
|
this.currentUser = 'Anonim';
|
||||||
|
} else {
|
||||||
|
this.currentUser = JSON.parse(localStorage.getItem('currentUser'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addFieldValue() {
|
||||||
|
const undefinedAttr = ((this.newAttribute['left_side'] === undefined) || (this.newAttribute['right_side'] === undefined));
|
||||||
|
if (undefinedAttr) {
|
||||||
|
this.snackBar.open('Nie można dodać fiszki z pustym polem!', null,
|
||||||
|
{ duration: 3000, verticalPosition: 'top', panelClass: ['snackbar-error'] });
|
||||||
|
} else {
|
||||||
|
const length = ((this.newAttribute['left_side'].trim().length === 0) || (this.newAttribute['right_side'].trim().length === 0));
|
||||||
|
if (length) {
|
||||||
|
this.snackBar.open('Nie można dodać fiszki z pustym polem!', null,
|
||||||
|
{ duration: 3000, verticalPosition: 'top', panelClass: ['snackbar-error'] });
|
||||||
|
} else {
|
||||||
|
this.fieldArray.push(this.newAttribute);
|
||||||
|
this.newAttribute = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteFieldValue(index) {
|
||||||
|
this.fieldArray.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
setOwner(): string {
|
||||||
|
if (localStorage.getItem('currentUser')) {
|
||||||
|
return JSON.parse(localStorage.getItem('currentUser')).username;
|
||||||
|
} else {
|
||||||
|
return 'anonim';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addTable(value: any) {
|
||||||
|
// obsługa formularza dodawania fiszek do tabeli
|
||||||
|
if (this.fieldArray.length === 0) {
|
||||||
|
this.snackBar.open('Zestaw fiszek nie może być pusty!', null,
|
||||||
|
{ duration: 3000, verticalPosition: 'top', panelClass: ['snackbar-error'] });
|
||||||
|
} else {
|
||||||
|
let p = 'Private';
|
||||||
|
if (this.permission) {
|
||||||
|
p = 'Public';
|
||||||
|
}
|
||||||
|
this.tableToSend = {
|
||||||
|
name: value.title,
|
||||||
|
category: value.category,
|
||||||
|
owner: this.setOwner(),
|
||||||
|
flashcards: this.fieldArray,
|
||||||
|
permission: p
|
||||||
|
};
|
||||||
|
this.flashcardsService.add(this.tableToSend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
|
||||||
|
.wrapper{
|
||||||
|
width: 100%;
|
||||||
|
padding: 30px;
|
||||||
|
min-height: 100%;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 800px) {
|
||||||
|
.mobile{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty{
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content{
|
||||||
|
background-color: #181616;
|
||||||
|
padding: 30px;
|
||||||
|
margin-top: 2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
ag-grid-angular{
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons-container > div{
|
||||||
|
margin: 10px;
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
<div class="wrapper">
|
||||||
|
<div class="content">
|
||||||
|
<div class="buttons-container">
|
||||||
|
<button class="btn btn-study-cave" routerLink="/flashcards/sets"><i class="fas fa-arrow-left"></i> WRÓĆ DO LISTY</button>
|
||||||
|
<button class="btn btn-study-cave" routerLink="/flashcards/add/table"><i class="fas fa-table"></i> DODAJ ZA POMOCĄ TABELI</button>
|
||||||
|
<button class="btn btn-study-cave" routerLink="/flashcards/add/csv"><i class="fas fa-file-csv"></i> DODAJ ZA POMOCĄ CSV</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FlashcardsAddComponent } from './flashcards-add.component';
|
||||||
|
|
||||||
|
describe('FlashcardsAddComponent', () => {
|
||||||
|
let component: FlashcardsAddComponent;
|
||||||
|
let fixture: ComponentFixture<FlashcardsAddComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ FlashcardsAddComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(FlashcardsAddComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,15 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-flashcards-add',
|
||||||
|
templateUrl: './flashcards-add.component.html',
|
||||||
|
styleUrls: ['./flashcards-add.component.css']
|
||||||
|
})
|
||||||
|
export class FlashcardsAddComponent implements OnInit {
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
table, th, td, tr {
|
||||||
|
border-width: 0;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
background-color: #181616;
|
||||||
|
padding: 30px;
|
||||||
|
margin-top: 2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper-add {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-content: center;
|
||||||
|
margin-bottom: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper{
|
||||||
|
width: 100%;
|
||||||
|
padding: 30px;
|
||||||
|
min-height: 100%;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content{
|
||||||
|
background-color: #181616;
|
||||||
|
padding: 30px;
|
||||||
|
margin-top: 2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
ag-grid-angular{
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons-container > div{
|
||||||
|
margin: 10px;
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
<div class="wrapper">
|
||||||
|
<div class="content">
|
||||||
|
<div class="buttons-container">
|
||||||
|
<button class="btn btn-study-cave" (click)="returnToSet()"><i class="fas fa-arrow-left"></i> WRÓĆ DO ZESTAWU</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="wrapper-add">
|
||||||
|
<div class="container">
|
||||||
|
<h1>Edycja zestawu</h1>
|
||||||
|
<br />
|
||||||
|
<form ngNativeValidate action="/" method="post" #user="ngForm" (ngSubmit)="addTable(user.value)">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-10">
|
||||||
|
<label>
|
||||||
|
Wprowadź nazwę dla zestawu:
|
||||||
|
<input type="text" name="title" class="form-control" [(ngModel)]="set['name']" required />
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Wprowadź kategorię zestawu:
|
||||||
|
<input type="text" name="category" class="form-control" [(ngModel)]="set['category']" required />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<label class="col-md-2">
|
||||||
|
<br />
|
||||||
|
<input type="checkbox" name="{{ permission }}" class="form-control" [checked]="permission" (change)="changePermission()"/>
|
||||||
|
<b>Udostępnij publicznie</b>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<label>
|
||||||
|
Wypełnij tabelę fiszkami:
|
||||||
|
<table class="table table-striped table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Lewa strona</th>
|
||||||
|
<th>Prawa strona</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr *ngFor="let field of fieldArray; let i = index">
|
||||||
|
<td>
|
||||||
|
<input [(ngModel)]="field.left_side" class="form-control" type="text" name="{{field.left_side}}" />
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input [(ngModel)]="field.right_side" class="form-control" type="text" name="{{field.right_side}}" />
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-study-cave" type="button" (click)="deleteFieldValue(i)"><i class="fas fa-trash-alt"></i> Usuń fiszkę</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input class="form-control" type="text" id="newAttributeLeft" [(ngModel)]="newAttribute['left_side']" name="newAttributeLeft" />
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input class="form-control" type="text" id="newAttributeRight" [(ngModel)]="newAttribute['right_side']" name="newAttributeRight" />
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-study-cave" type="button" (click)="addFieldValue()"><i class="fas fa-file-csv"></i> Dodaj fiszkę</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</label>
|
||||||
|
<br />
|
||||||
|
<div>
|
||||||
|
<button class="btn btn-study-cave" type="submit"><i class="fas fa-check-circle"></i> Edytuj fiszki!</button>
|
||||||
|
<button class="btn btn-study-cave" [routerLink]="['/flashcards/sets', ident]"><i class="fas fa-arrow-left"></i> Powrót</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,35 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FlashcardsEditTableComponent } from './flashcards-edit-table.component';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
import { AuthenticationService } from '../../authentication.service';
|
||||||
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
|
|
||||||
|
describe('FlashcardsEditTableComponent', () => {
|
||||||
|
let component: FlashcardsEditTableComponent;
|
||||||
|
let fixture: ComponentFixture<FlashcardsEditTableComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ FlashcardsEditTableComponent ],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA],
|
||||||
|
providers: [FlashcardsService, AuthenticationService],
|
||||||
|
imports: [ RouterTestingModule, FormsModule, HttpClientModule, MatSnackBarModule]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(FlashcardsEditTableComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,106 @@
|
|||||||
|
import { Component, OnInit, OnDestroy, Input } from '@angular/core';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { Subscription } from 'rxjs/Subscription';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-flashcards-edit-table',
|
||||||
|
templateUrl: './flashcards-edit-table.component.html',
|
||||||
|
styleUrls: ['./flashcards-edit-table.component.css']
|
||||||
|
})
|
||||||
|
export class FlashcardsEditTableComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
ident: number;
|
||||||
|
permission: Boolean = false;
|
||||||
|
table: Boolean = false;
|
||||||
|
tableToSend: any = {};
|
||||||
|
fieldArray: Array<any> = [];
|
||||||
|
newAttribute: any = {};
|
||||||
|
set: Object = {};
|
||||||
|
flashcardSubscribtion: Subscription;
|
||||||
|
|
||||||
|
constructor(private flashcardsService: FlashcardsService, private route: ActivatedRoute, private router: Router,
|
||||||
|
public snackBar: MatSnackBar) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.ident = this.route.snapshot.params.id;
|
||||||
|
this.flashcardSubscribtion = this.flashcardsService.getSet(this.ident).subscribe(data => {
|
||||||
|
this.set = data;
|
||||||
|
if (data['permission'] === 'Private') {
|
||||||
|
this.permission = false;
|
||||||
|
} else {
|
||||||
|
this.permission = true;
|
||||||
|
}
|
||||||
|
const flashcards = data['flashcards'];
|
||||||
|
for (let i = 0; i < flashcards.length; i++) {
|
||||||
|
const id = flashcards[i]['id'];
|
||||||
|
this.fieldArray.push({
|
||||||
|
id: id,
|
||||||
|
left_side: flashcards[i]['left_side'],
|
||||||
|
right_side: flashcards[i]['right_side']
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
returnToSet() {
|
||||||
|
this.router.navigate(['/flashcards/sets/', this.ident]);
|
||||||
|
}
|
||||||
|
addFieldValue() {
|
||||||
|
const undefinedAttr = ((this.newAttribute['left_side'] === undefined) || (this.newAttribute['right_side'] === undefined));
|
||||||
|
if (undefinedAttr) {
|
||||||
|
this.snackBar.open('Nie można dodać fiszki z pustym polem!', null,
|
||||||
|
{ duration: 3000, verticalPosition: 'top', panelClass: ['snackbar-error'] });
|
||||||
|
} else {
|
||||||
|
const length = ((this.newAttribute['left_side'].trim().length === 0) || (this.newAttribute['right_side'].trim().length === 0));
|
||||||
|
if (length) {
|
||||||
|
this.snackBar.open('Nie można dodać fiszki z pustym polem!', null,
|
||||||
|
{ duration: 3000, verticalPosition: 'top', panelClass: ['snackbar-error'] });
|
||||||
|
} else {
|
||||||
|
const insert = {
|
||||||
|
id: null,
|
||||||
|
left_side: this.newAttribute['left_side'],
|
||||||
|
right_side: this.newAttribute['right_side'],
|
||||||
|
};
|
||||||
|
this.fieldArray.push(insert);
|
||||||
|
this.newAttribute = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteFieldValue(index) {
|
||||||
|
this.fieldArray.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
addTable(value: any) {
|
||||||
|
const currentUser = JSON.parse(localStorage.getItem('currentUser'));
|
||||||
|
if (this.fieldArray.length === 0) {
|
||||||
|
this.snackBar.open('Zestaw fiszek nie może być pusty!', null,
|
||||||
|
{ duration: 3000, verticalPosition: 'top', panelClass: ['snackbar-error'] });
|
||||||
|
} else {
|
||||||
|
let perm = 'Private';
|
||||||
|
if (this.permission) {
|
||||||
|
perm = 'Public';
|
||||||
|
}
|
||||||
|
this.tableToSend = {
|
||||||
|
id: this.ident,
|
||||||
|
name: value.title,
|
||||||
|
permission: perm,
|
||||||
|
category: value.category,
|
||||||
|
owner: currentUser.username,
|
||||||
|
flashcards: this.fieldArray
|
||||||
|
};
|
||||||
|
this.flashcardsService.edit(this.tableToSend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
changePermission(): void {
|
||||||
|
this.permission = !this.permission;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.flashcardSubscribtion.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
#container-small {
|
||||||
|
background-color: #181616;
|
||||||
|
padding: 30px;
|
||||||
|
width: 32%;
|
||||||
|
height: 400px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-content: center;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container-large {
|
||||||
|
background-color: #181616;
|
||||||
|
padding: 30px;
|
||||||
|
width: 62%;
|
||||||
|
min-height: 400px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
margin-bottom: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 800px) {
|
||||||
|
.content {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container-small {
|
||||||
|
height: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container-small, #container-large {
|
||||||
|
width: 90%;
|
||||||
|
margin-bottom: 2.5rem;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
<div class="content">
|
||||||
|
<div id="container-small">
|
||||||
|
<h4>Uzupełnianie fiszek</h4>
|
||||||
|
<br />
|
||||||
|
<div>
|
||||||
|
<b>Nazwa zestawu: </b>
|
||||||
|
<i>{{ name }}</i>
|
||||||
|
<br />
|
||||||
|
<b>Kategoria: </b>
|
||||||
|
<i>{{ category }}</i>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="started">
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<b>Uzupełniono: </b>
|
||||||
|
<span> {{ filled }} z {{ length_test }} fiszek</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<b>Poprawnych odpowiedzi: </b>
|
||||||
|
<span> {{ good }} na {{ length_test }}</span><br />
|
||||||
|
<b>Złych odpowiedzi: </b>
|
||||||
|
<span> {{ bad }} na {{ length_test }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="container-large">
|
||||||
|
<div *ngIf="started">
|
||||||
|
<div *ngIf="this.filled >= 1 && !finish">
|
||||||
|
|
||||||
|
Poprzednia odpowiedź:<br />
|
||||||
|
{{flashcards[index-1].content}} {{allAnswers[index-1].answer}}
|
||||||
|
</div>
|
||||||
|
<div *ngIf="this.filled < this.length_test && !finish ">
|
||||||
|
Podaj odpowiedź:<br />
|
||||||
|
{{flashcards[index].content}}
|
||||||
|
<input appAutofocus [(ngModel)]="answer" class="mr-2" placeholder="odpowiedź" (keyup.enter)="verifyAnswer()" >
|
||||||
|
<button class="btn btn-study-cave" (click)="verifyAnswer()"><i class="fas fa-check-circle"></i> Sprawdź</button>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="this.is_correct === true && !finish">ODPOWIEDŹ POPRAWNA</div>
|
||||||
|
<div *ngIf="this.is_correct === false && !finish">ODPOWIEDŹ NIEPOPRAWNA</div>
|
||||||
|
<div *ngIf="this.filled < this.length_test-1 && !finish">
|
||||||
|
Następne pytanie:<br />
|
||||||
|
{{flashcards[index+1].content}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div *ngIf="finish">
|
||||||
|
<app-test-results [result]="good" [maxPts]="length_test"></app-test-results>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="!finish">
|
||||||
|
<button class="btn btn-study-cave" *ngIf="!started" (click)="start()"><i class="far fa-play-circle"></i> Rozpocznij test</button>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-study-cave" *ngIf="finish" routerLink="/flashcards/sets/{{ id }}"><i class="far fa-stop-circle"></i> Zakończ test</button>
|
||||||
|
<button class="btn btn-study-cave" *ngIf="started && !finish && !not_last"(click)="finished()"><i class="fas fa-arrow-left"></i> Przejdź do wyniku</button>
|
||||||
|
<br />
|
||||||
|
<button class="btn btn-study-cave" routerLink="/flashcards/sets/{{ id }}"><i class="fas fa-arrow-left"></i> Wróć do zestawu</button>
|
||||||
|
</div>
|
@ -0,0 +1,34 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FlashcardsFillingInTestComponent } from './flashcards-filling-in-test.component';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
import { AuthenticationService } from '../../authentication.service';
|
||||||
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
|
|
||||||
|
describe('FlashcardsFillingInTestComponent', () => {
|
||||||
|
let component: FlashcardsFillingInTestComponent;
|
||||||
|
let fixture: ComponentFixture<FlashcardsFillingInTestComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ FlashcardsFillingInTestComponent ],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA],
|
||||||
|
providers: [FlashcardsService, AuthenticationService],
|
||||||
|
imports: [ RouterTestingModule, FormsModule, HttpClientModule, MatSnackBarModule]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(FlashcardsFillingInTestComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,96 @@
|
|||||||
|
import { Component, OnInit, Input, OnDestroy } from '@angular/core';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { Subscription } from 'rxjs/Subscription';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-flashcards-filling-in-test',
|
||||||
|
templateUrl: './flashcards-filling-in-test.component.html',
|
||||||
|
styleUrls: ['./flashcards-filling-in-test.component.css']
|
||||||
|
})
|
||||||
|
export class FlashcardsFillingInTestComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
id: number;
|
||||||
|
flashcardSubscribtionMeta: Subscription;
|
||||||
|
flashcardSubscribtion: Subscription;
|
||||||
|
flashcardSubscribtionCheck: Subscription;
|
||||||
|
name: String;
|
||||||
|
category: String;
|
||||||
|
length_test: number;
|
||||||
|
goodNow: number;
|
||||||
|
started: Boolean = false;
|
||||||
|
finish: Boolean = false;
|
||||||
|
flashcards: Array<Object> = [];
|
||||||
|
filled = 0;
|
||||||
|
good = 0;
|
||||||
|
bad = 0;
|
||||||
|
answer: String;
|
||||||
|
index = 0;
|
||||||
|
not_last: Boolean = true;
|
||||||
|
is_correct: Boolean;
|
||||||
|
allAnswers = [];
|
||||||
|
|
||||||
|
|
||||||
|
constructor(private flashcardsService: FlashcardsService, private route: ActivatedRoute) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.id = this.route.snapshot.params.id;
|
||||||
|
this.flashcardSubscribtionMeta = this.flashcardsService.getSet(this.id).subscribe(data => {
|
||||||
|
this.name = data['name'];
|
||||||
|
this.category = data['category'];
|
||||||
|
});
|
||||||
|
this.flashcardSubscribtion = this.flashcardsService.getTestFilling(this.id).subscribe(data => {
|
||||||
|
this.length_test = data.length;
|
||||||
|
this.flashcards = data;
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
this.started = true;
|
||||||
|
}
|
||||||
|
finished() {
|
||||||
|
this.finish = true;
|
||||||
|
}
|
||||||
|
verifyAnswer() {
|
||||||
|
const body = [];
|
||||||
|
const n = this.length_test;
|
||||||
|
if (this.answer === '') {
|
||||||
|
this.answer = ' ';
|
||||||
|
}
|
||||||
|
this.allAnswers.push({
|
||||||
|
id: this.index,
|
||||||
|
answer: this.answer,
|
||||||
|
});
|
||||||
|
body.push({
|
||||||
|
id: this.flashcards[this.index]['id'],
|
||||||
|
content: this.answer,
|
||||||
|
side: this.flashcards[this.index]['side'],
|
||||||
|
});
|
||||||
|
this.flashcardSubscribtionCheck = this.flashcardsService.testCheck(this.id, body[0])
|
||||||
|
.subscribe(data => {
|
||||||
|
this.is_correct = data.result;
|
||||||
|
if (this.is_correct === true) {
|
||||||
|
this.good = this.good + 1;
|
||||||
|
} else {
|
||||||
|
this.bad = this.bad + 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (this.index < this.length_test) {
|
||||||
|
this.index = this.index + 1;
|
||||||
|
this.filled = this.filled + 1;
|
||||||
|
this.answer = '';
|
||||||
|
}
|
||||||
|
if (this.index === this.length_test) {
|
||||||
|
this.not_last = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.flashcardSubscribtionMeta.unsubscribe();
|
||||||
|
this.flashcardSubscribtion.unsubscribe();
|
||||||
|
if (this.flashcardSubscribtionCheck) {
|
||||||
|
this.flashcardSubscribtionCheck.unsubscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
h2 {
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 900;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
color: white;
|
||||||
|
background-color: gray;
|
||||||
|
text-align: center;
|
||||||
|
min-height: 4rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
transition: color 1000ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-invisible {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-visible {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
<div class="container">
|
||||||
|
<div>
|
||||||
|
<h2 *ngIf="!isOK && !isBad"> </h2>
|
||||||
|
<h2 *ngIf="isOK">Dobrze :)</h2>
|
||||||
|
<h2 *ngIf="isBad">Źle :(</h2>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<div class="row">
|
||||||
|
<div *ngFor="let card of set; let i = index" class="col-md-6">
|
||||||
|
<p *ngIf="!visible[i]" id="{{ i }}" class="card card-invisible clickable" (click)="check($event)">???</p>
|
||||||
|
<p *ngIf="visible[i]" id="{{ i }}" class='card card-visible unclickable' onclick='return false;'><b>{{ card }}</b></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,34 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FlashcardsMemoryTestSetComponent } from './flashcards-memory-test-set.component';
|
||||||
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { AuthenticationService } from '../../authentication.service';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
|
|
||||||
|
describe('FlashcardsMemoryTestSetComponent', () => {
|
||||||
|
let component: FlashcardsMemoryTestSetComponent;
|
||||||
|
let fixture: ComponentFixture<FlashcardsMemoryTestSetComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ FlashcardsMemoryTestSetComponent ],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA],
|
||||||
|
providers: [FlashcardsService, AuthenticationService],
|
||||||
|
imports: [ RouterTestingModule, FormsModule, HttpClientModule, MatSnackBarModule]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(FlashcardsMemoryTestSetComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,121 @@
|
|||||||
|
import { Component, OnInit, OnChanges, SimpleChanges, Input, Output, EventEmitter, OnDestroy } from '@angular/core';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { Subscription } from 'rxjs/Subscription';
|
||||||
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-flashcards-memory-test-set',
|
||||||
|
templateUrl: './flashcards-memory-test-set.component.html',
|
||||||
|
styleUrls: ['./flashcards-memory-test-set.component.css']
|
||||||
|
})
|
||||||
|
export class FlashcardsMemoryTestSetComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
|
|
||||||
|
@Input() package: Array<any>;
|
||||||
|
@Input() id: number;
|
||||||
|
@Input() package_id: number;
|
||||||
|
|
||||||
|
@Output() goodEvent = new EventEmitter();
|
||||||
|
@Output() isChecked = new EventEmitter();
|
||||||
|
|
||||||
|
flashcardSubscribtion: Array<Subscription> = [];
|
||||||
|
answer: Array<Object> = [];
|
||||||
|
set: Array<Object> = [];
|
||||||
|
visible: Array<Boolean> = [];
|
||||||
|
toCheck: Array<number> = [];
|
||||||
|
isBad: Boolean = false;
|
||||||
|
isOK: Boolean = false;
|
||||||
|
good = 0;
|
||||||
|
clicks = 0;
|
||||||
|
|
||||||
|
constructor(private uploadService: FlashcardsService, public snackBar: MatSnackBar) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.isChecked.emit(false);
|
||||||
|
this.flashcardSubscribtion = [];
|
||||||
|
this.visible = [];
|
||||||
|
this.set = this.package[this.package_id]['set'];
|
||||||
|
for (let i = 0; i < this.set.length; i++) {
|
||||||
|
this.visible.push(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
|
this.ngOnDestroy();
|
||||||
|
const package_idChanges = changes['package_id'];
|
||||||
|
if (package_idChanges) {
|
||||||
|
this.ngOnInit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
check(event) {
|
||||||
|
if (this.clicks <= 2) {
|
||||||
|
this.clicks += 1;
|
||||||
|
this.toCheck.push(event.target.id);
|
||||||
|
this.visible[this.toCheck[0]] = true;
|
||||||
|
if (this.clicks === 2) {
|
||||||
|
this.visible[this.toCheck[1]] = true;
|
||||||
|
const toSend = {
|
||||||
|
x: this.set[this.toCheck[0]],
|
||||||
|
y: this.set[this.toCheck[1]],
|
||||||
|
};
|
||||||
|
setTimeout(() => {
|
||||||
|
this.flashcardSubscribtion[this.flashcardSubscribtion.length] =
|
||||||
|
this.uploadService.testMemory(this.id, toSend).subscribe(data => {
|
||||||
|
this.showWrong(data);
|
||||||
|
this.clicks = 0;
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
this.snackBar.open('Coś poszło nie tak :( Spróbuj ponownie później.', null,
|
||||||
|
{ duration: 3000, verticalPosition: 'top', panelClass: ['snackbar-error'] });
|
||||||
|
this.clicks = 0;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showWrong(answer: Boolean) {
|
||||||
|
this.isGood(answer);
|
||||||
|
this.goodEvent.emit(this.good);
|
||||||
|
}
|
||||||
|
|
||||||
|
isGood(answer: Boolean) {
|
||||||
|
if (!answer) {
|
||||||
|
this.isBad = true;
|
||||||
|
this.visible[this.toCheck[0]] = false;
|
||||||
|
this.visible[this.toCheck[1]] = false;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.isBad = false;
|
||||||
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
this.isOK = true;
|
||||||
|
this.visible[this.toCheck[0]] = true;
|
||||||
|
this.visible[this.toCheck[1]] = true;
|
||||||
|
document.getElementById(this.toCheck[0].toString()).style.color = 'rgb(94, 249, 37)';
|
||||||
|
document.getElementById(this.toCheck[1].toString()).style.color = 'rgb(94, 249, 37)';
|
||||||
|
setTimeout(() => {
|
||||||
|
this.isOK = false;
|
||||||
|
}, 1000);
|
||||||
|
this.good += 1;
|
||||||
|
let i = 0;
|
||||||
|
while (this.visible[i]) {
|
||||||
|
if (i === (this.visible.length - 1)) {
|
||||||
|
this.isChecked.emit(true);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
if (i === this.visible.length) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.toCheck = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
for (let i = 0; i < this.flashcardSubscribtion.length; i++) {
|
||||||
|
this.flashcardSubscribtion[i].unsubscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
#container-small {
|
||||||
|
background-color: #181616;
|
||||||
|
padding: 30px;
|
||||||
|
width: 32%;
|
||||||
|
height: 400px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-content: center;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container-large {
|
||||||
|
background-color: #181616;
|
||||||
|
padding: 30px;
|
||||||
|
width: 62%;
|
||||||
|
min-height: 400px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
margin-bottom: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 800px) {
|
||||||
|
.content {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container-small {
|
||||||
|
height: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container-small, #container-large {
|
||||||
|
width: 90%;
|
||||||
|
margin-bottom: 2.5rem;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
<div class="container">
|
||||||
|
<div class="content">
|
||||||
|
<div id="container-small">
|
||||||
|
<h4>Memory</h4>
|
||||||
|
<br />
|
||||||
|
<div>
|
||||||
|
<b>Nazwa zestawu: </b>
|
||||||
|
<i>{{ name }}</i>
|
||||||
|
<br />
|
||||||
|
<b>Kategoria: </b>
|
||||||
|
<i>{{ category }}</i>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="started">
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<b>Uzupełniono: </b>
|
||||||
|
<span> {{ filled }} z {{ flashcards }} fiszek</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<b>Poprawnych odpowiedzi: </b>
|
||||||
|
<span> {{ good }} na {{ flashcards }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="container-large">
|
||||||
|
<div class="test" *ngIf="started">
|
||||||
|
<app-flashcards-memory-test-set (goodEvent)="goodEvent($event)" (isChecked)=isChecked($event)
|
||||||
|
[package]="packages" package_id="{{ package_id }}" [id]="id"></app-flashcards-memory-test-set>
|
||||||
|
<br />
|
||||||
|
<div>
|
||||||
|
<b>Ekran: </b>
|
||||||
|
<span> {{ package_id + 1 }} z {{ length_packages }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="finish">
|
||||||
|
<app-test-results [result]="good" [maxPts]="flashcards"></app-test-results>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<div *ngIf="!finish">
|
||||||
|
<button class="btn btn-study-cave" *ngIf="!started" (click)="start()"><i class="far fa-play-circle"></i> Rozpocznij test</button>
|
||||||
|
<button class="btn btn-study-cave" *ngIf="checked && not_last" (click)="increment()"><i class="fas fa-arrow-right"></i>Przejdź dalej</button>
|
||||||
|
<button class="btn btn-study-cave" *ngIf="checked && !not_last" (click)="increment()"><i class="far fa-stop-circle"></i> Zakończ test</button>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<button class="btn btn-study-cave" routerLink="/flashcards/sets/{{ id }}"><i class="fas fa-arrow-left"></i> Wróć do zestawu</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,34 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FlashcardsMemoryTestComponent } from './flashcards-memory-test.component';
|
||||||
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { AuthenticationService } from '../../authentication.service';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
|
|
||||||
|
describe('FlashcardsMemoryTestComponent', () => {
|
||||||
|
let component: FlashcardsMemoryTestComponent;
|
||||||
|
let fixture: ComponentFixture<FlashcardsMemoryTestComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ FlashcardsMemoryTestComponent ],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA],
|
||||||
|
providers: [FlashcardsService, AuthenticationService],
|
||||||
|
imports: [ RouterTestingModule, FormsModule, HttpClientModule, MatSnackBarModule]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(FlashcardsMemoryTestComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,102 @@
|
|||||||
|
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { Subscription } from 'rxjs/Subscription';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-flashcards-memory-test',
|
||||||
|
templateUrl: './flashcards-memory-test.component.html',
|
||||||
|
styleUrls: ['./flashcards-memory-test.component.css']
|
||||||
|
})
|
||||||
|
export class FlashcardsMemoryTestComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
id: number;
|
||||||
|
flashcardSubscribtionMeta: Subscription;
|
||||||
|
flashcardSubscribtion: Subscription;
|
||||||
|
name: String;
|
||||||
|
category: String;
|
||||||
|
length_test: number;
|
||||||
|
flashcards: number;
|
||||||
|
length_packages: number;
|
||||||
|
goodNow: number;
|
||||||
|
started: Boolean = false;
|
||||||
|
finish: Boolean = false;
|
||||||
|
checked: Boolean = false;
|
||||||
|
not_last: Boolean = true;
|
||||||
|
packages: Array<Object> = [];
|
||||||
|
filled = 0;
|
||||||
|
good = 0;
|
||||||
|
package_id = 0;
|
||||||
|
|
||||||
|
constructor(private flashcardsService: FlashcardsService, private route: ActivatedRoute) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.id = this.route.snapshot.params.id;
|
||||||
|
this.flashcardSubscribtionMeta = this.flashcardsService.getSet(this.id).subscribe(data => {
|
||||||
|
this.name = data['name'];
|
||||||
|
this.category = data['category'];
|
||||||
|
});
|
||||||
|
this.flashcardSubscribtion = this.flashcardsService.getTestMemory(this.id).subscribe(data => {
|
||||||
|
this.length_test = data.length;
|
||||||
|
this.flashcards = data.length / 2;
|
||||||
|
this.createPackages(data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
createPackages(data) {
|
||||||
|
let attribute = '0';
|
||||||
|
let set = [];
|
||||||
|
const n = this.length_test;
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
if (i % 10 === 0) {
|
||||||
|
this.packages[attribute] = {
|
||||||
|
set: set,
|
||||||
|
};
|
||||||
|
attribute = (i / 10).toString();
|
||||||
|
set = [];
|
||||||
|
}
|
||||||
|
set.push(data[i]);
|
||||||
|
if (i === (n - 1)) {
|
||||||
|
this.packages[attribute] = {
|
||||||
|
set: set,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.length_packages = this.packages.length;
|
||||||
|
if (this.packages.length < 2) {
|
||||||
|
this.not_last = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
this.started = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
increment() {
|
||||||
|
if (this.package_id === (this.length_packages - 2)) {
|
||||||
|
this.not_last = false;
|
||||||
|
}
|
||||||
|
if (this.package_id === (this.length_packages - 1)) {
|
||||||
|
this.started = false;
|
||||||
|
this.finish = true;
|
||||||
|
} else {
|
||||||
|
this.package_id += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
goodEvent(goods) {
|
||||||
|
this.goodNow = goods;
|
||||||
|
this.filled = this.goodNow;
|
||||||
|
this.good = this.goodNow;
|
||||||
|
}
|
||||||
|
|
||||||
|
isChecked(check) {
|
||||||
|
this.checked = check;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.flashcardSubscribtionMeta.unsubscribe();
|
||||||
|
this.flashcardSubscribtion.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,94 @@
|
|||||||
|
#container-small {
|
||||||
|
background-color: #181616;
|
||||||
|
padding: 30px;
|
||||||
|
width: 25%;
|
||||||
|
height: 400px;
|
||||||
|
margin: 25px;
|
||||||
|
float:left;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.content{
|
||||||
|
position:fixed;
|
||||||
|
width:100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
#container-large {
|
||||||
|
background-color: #181616;
|
||||||
|
padding: 30px;
|
||||||
|
width: 65%;
|
||||||
|
height: 400px;
|
||||||
|
margin: 25px;
|
||||||
|
float: right;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title{
|
||||||
|
font-size: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-content{
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.puzzle{
|
||||||
|
display: flex;
|
||||||
|
min-height: 50px;
|
||||||
|
min-width: 100px;
|
||||||
|
background-color: rgb(206, 168, 86);
|
||||||
|
color: black;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 5px 0 5px 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.puzzle-right{
|
||||||
|
display: flex;
|
||||||
|
color: black;
|
||||||
|
min-height: 50px;
|
||||||
|
min-width: 100px;
|
||||||
|
background-color: rgb(202, 144, 17);
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 5px 5px 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.both-sides{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.puzzle:hover{
|
||||||
|
border: 3px solid gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.active{
|
||||||
|
border: 3px solid white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.puzzles-container{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty{
|
||||||
|
background-color: gray;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.good{
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrong{
|
||||||
|
background-color: red;
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
<div>
|
||||||
|
<h3>Dostępne lewe strony:</h3>
|
||||||
|
<div class="puzzles-container">
|
||||||
|
<div class='puzzle' *ngFor="let item of leftSides; let i = index" (click)="leftSideClick(item,i)" [ngClass]="{'active': (selectedLeftSide.leftSideText === item && selectedLeftSide.indexOfLeftSide === i && selectedLeftSide.from === 'leftSides'), 'empty': (item === undefined || item === '')}">
|
||||||
|
<span>{{item.left_side}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h3>Twoja odpowiedź:</h3>
|
||||||
|
<div class="puzzles-container">
|
||||||
|
<div *ngFor="let item of leftSidesToSend; let i = index" class="both-sides">
|
||||||
|
<div class="puzzle good" *ngIf="result[i] && verify">
|
||||||
|
<span>{{item.left_side}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="puzzle wrong" *ngIf="!result[i] && verify">
|
||||||
|
<span>{{item.left_side}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="!verify" class='puzzle' (click)="leftSideToSendClick(item,i)" [ngClass]="{'active': (selectedLeftSide.leftSideText === item && selectedLeftSide.indexOfLeftSide === i && selectedLeftSide.from === 'leftSidesToSend')}">
|
||||||
|
<span>{{item.left_side}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class='puzzle-right'>
|
||||||
|
<span>{{rightSides[i].right_side}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<button *ngIf="!verify" class="btn btn-study-cave" (click)="nextQuestion()"><i class="fas fa-check-circle"></i> Sprawdź</button>
|
||||||
|
</div>
|
@ -0,0 +1,34 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FlashcardsPairsTestSetComponent } from './flashcards-pairs-test-set.component';
|
||||||
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { AuthenticationService } from '../../authentication.service';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
|
|
||||||
|
describe('FlashcardsPairsTestSetComponent', () => {
|
||||||
|
let component: FlashcardsPairsTestSetComponent;
|
||||||
|
let fixture: ComponentFixture<FlashcardsPairsTestSetComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ FlashcardsPairsTestSetComponent ],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA],
|
||||||
|
providers: [FlashcardsService, AuthenticationService],
|
||||||
|
imports: [ RouterTestingModule, FormsModule, HttpClientModule, MatSnackBarModule]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(FlashcardsPairsTestSetComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,121 @@
|
|||||||
|
import { Component, OnInit, OnChanges, SimpleChanges, Input, Output, EventEmitter, OnDestroy } from '@angular/core';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { Subscription } from 'rxjs/Subscription';
|
||||||
|
import * as $ from 'jquery';
|
||||||
|
import { ISubscription } from 'rxjs/Subscription';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-flashcards-pairs-test-set',
|
||||||
|
templateUrl: './flashcards-pairs-test-set.component.html',
|
||||||
|
styleUrls: ['./flashcards-pairs-test-set.component.css']
|
||||||
|
})
|
||||||
|
export class FlashcardsPairsTestSetComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
|
|
||||||
|
@Input() package: Array<any>;
|
||||||
|
@Input() id: number;
|
||||||
|
@Input() package_id: number;
|
||||||
|
|
||||||
|
@Output() goodEvent = new EventEmitter();
|
||||||
|
@Output() isChecked = new EventEmitter();
|
||||||
|
|
||||||
|
private verifyAnswerSubscription: ISubscription;
|
||||||
|
leftSides = [];
|
||||||
|
rightSides = [];
|
||||||
|
leftSidesToSend = [];
|
||||||
|
result = [];
|
||||||
|
verify = false;
|
||||||
|
good = 0;
|
||||||
|
selectedLeftSide = { indexOfLeftSide: Number, left_side: String, from: '', id: Number };
|
||||||
|
|
||||||
|
constructor(private flashcardsService: FlashcardsService) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.isChecked.emit(false);
|
||||||
|
this.prepareLists();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
|
this.prepareLists();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
if (this.verifyAnswerSubscription) {
|
||||||
|
this.verifyAnswerSubscription.unsubscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nextQuestion(f) {
|
||||||
|
let canSend = true;
|
||||||
|
this.good = 0;
|
||||||
|
this.result = [];
|
||||||
|
this.leftSides.forEach(element => {
|
||||||
|
if (element !== '') {
|
||||||
|
canSend = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (canSend) {
|
||||||
|
this.verify = true;
|
||||||
|
this.leftSidesToSend.forEach((element, index) => {
|
||||||
|
const body = {
|
||||||
|
content: this.rightSides[index].right_side,
|
||||||
|
id: element.id,
|
||||||
|
side: 'left'
|
||||||
|
};
|
||||||
|
this.verifyAnswerSubscription = this.flashcardsService.testCheck(this.id, body).subscribe(d => {
|
||||||
|
this.result[index] = d.result;
|
||||||
|
if (d.result) {
|
||||||
|
this.good += 1;
|
||||||
|
}
|
||||||
|
if (this.result.length === this.leftSidesToSend.length) {
|
||||||
|
this.send();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
send() {
|
||||||
|
this.isChecked.emit(true);
|
||||||
|
this.goodEvent.emit(this.good);
|
||||||
|
}
|
||||||
|
|
||||||
|
leftSideClick(item, i) {
|
||||||
|
if (item !== '' && item !== undefined) {
|
||||||
|
if (this.selectedLeftSide.from === 'leftSides') {
|
||||||
|
this.selectedLeftSide = { indexOfLeftSide: undefined, left_side: undefined, from: undefined, id: undefined };
|
||||||
|
} else {
|
||||||
|
this.selectedLeftSide = { indexOfLeftSide: i, left_side: item.left_side, from: 'leftSides', id: item.id };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
leftSideToSendClick(item, i) {
|
||||||
|
if (this.selectedLeftSide.from === 'leftSides') {
|
||||||
|
const helper = this.leftSidesToSend[i];
|
||||||
|
this.leftSidesToSend[i] = this.selectedLeftSide;
|
||||||
|
this.leftSides[Number(this.selectedLeftSide.indexOfLeftSide)] = helper;
|
||||||
|
this.selectedLeftSide = { indexOfLeftSide: undefined, left_side: undefined, from: undefined, id: undefined };
|
||||||
|
} else if (this.selectedLeftSide.from === 'leftSidesToSend') {
|
||||||
|
const helper = this.leftSidesToSend[i];
|
||||||
|
this.leftSidesToSend[i] = this.selectedLeftSide;
|
||||||
|
this.leftSidesToSend[Number(this.selectedLeftSide.indexOfLeftSide)] = helper;
|
||||||
|
this.selectedLeftSide = { indexOfLeftSide: undefined, left_side: undefined, from: undefined, id: undefined };
|
||||||
|
} else if (item !== '' && item !== undefined) {
|
||||||
|
this.selectedLeftSide = { indexOfLeftSide: i, left_side: item.left_side, from: 'leftSidesToSend', id: item.id };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareLists() {
|
||||||
|
this.selectedLeftSide = { indexOfLeftSide: undefined, left_side: undefined, from: undefined, id: undefined };
|
||||||
|
this.leftSides = [];
|
||||||
|
this.rightSides = [];
|
||||||
|
this.leftSidesToSend = [];
|
||||||
|
this.verify = false;
|
||||||
|
this.leftSides = JSON.parse(JSON.stringify(this.package[0].setLeft));
|
||||||
|
this.rightSides = JSON.parse(JSON.stringify(this.package[0].setRight));
|
||||||
|
this.leftSides.forEach(element => {
|
||||||
|
this.leftSidesToSend.push('');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
#container-small {
|
||||||
|
background-color: #181616;
|
||||||
|
padding: 30px;
|
||||||
|
width: 32%;
|
||||||
|
height: 400px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-content: center;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container-large {
|
||||||
|
background-color: #181616;
|
||||||
|
padding: 30px;
|
||||||
|
width: 62%;
|
||||||
|
min-height: 400px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
margin-bottom: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 800px) {
|
||||||
|
.content {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container-small {
|
||||||
|
height: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container-small, #container-large {
|
||||||
|
width: 90%;
|
||||||
|
margin-bottom: 2.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 350px) {
|
||||||
|
|
||||||
|
#container-small {
|
||||||
|
height: 350px;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
<div class="content">
|
||||||
|
<div id="container-small">
|
||||||
|
<h4>Łączenie fiszek w pary</h4>
|
||||||
|
<br />
|
||||||
|
<div>
|
||||||
|
<b>Nazwa zestawu: </b>
|
||||||
|
<i>{{ name }}</i>
|
||||||
|
<br />
|
||||||
|
<b>Kategoria: </b>
|
||||||
|
<i>{{ category }}</i>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="started">
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<b>Uzupełniono: </b>
|
||||||
|
<span> {{ filled }} z {{ length_test }} fiszek</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<b>Poprawnych odpowiedzi: </b>
|
||||||
|
<span> {{ good }} na {{ length_test }}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<b>Złych odpowiedzi: </b>
|
||||||
|
<span> {{ bad }} na {{ length_test }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="container-large">
|
||||||
|
<div class="test" *ngIf="started">
|
||||||
|
<app-flashcards-pairs-test-set (goodEvent)="goodEvent($event)" (isChecked)=isChecked($event)
|
||||||
|
[package]="packages" package_id="{{ package_id }}" [id]="id"></app-flashcards-pairs-test-set>
|
||||||
|
<br />
|
||||||
|
<div>
|
||||||
|
<b>Ekran: </b>
|
||||||
|
<span> {{ package_id + 1}} z {{ length_packages }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div *ngIf="finish">
|
||||||
|
<app-test-results [result]="good" [maxPts]="length_test"></app-test-results>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<div *ngIf="!finish">
|
||||||
|
<button class="btn btn-study-cave" *ngIf="!started" (click)="start()"><i class="far fa-play-circle"></i> Rozpocznij test</button>
|
||||||
|
<button class="btn btn-study-cave" *ngIf="checked && not_last" (click)="increment()"><i class="far fa-play-circle"></i> Przejdź dalej</button>
|
||||||
|
<button class="btn btn-study-cave" *ngIf="checked && !not_last" (click)="increment()"><i class="far fa-stop-circle"></i> Zakończ test</button>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<button class="btn btn-study-cave" routerLink="/flashcards/sets/{{ id }}"><i class="fas fa-arrow-left"></i> Wróć do zestawu</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,34 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FlashcardsPairsTestComponent } from './flashcards-pairs-test.component';
|
||||||
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { AuthenticationService } from '../../authentication.service';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
|
|
||||||
|
describe('FlashcardsPairsTestComponent', () => {
|
||||||
|
let component: FlashcardsPairsTestComponent;
|
||||||
|
let fixture: ComponentFixture<FlashcardsPairsTestComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ FlashcardsPairsTestComponent ],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA],
|
||||||
|
providers: [FlashcardsService, AuthenticationService],
|
||||||
|
imports: [ RouterTestingModule, FormsModule, HttpClientModule, MatSnackBarModule]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(FlashcardsPairsTestComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,110 @@
|
|||||||
|
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { Subscription } from 'rxjs/Subscription';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-flashcards-pairs-test',
|
||||||
|
templateUrl: './flashcards-pairs-test.component.html',
|
||||||
|
styleUrls: ['./flashcards-pairs-test.component.css']
|
||||||
|
})
|
||||||
|
export class FlashcardsPairsTestComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
id: number;
|
||||||
|
flashcardSubscribtionMeta: Subscription;
|
||||||
|
flashcardSubscribtion: Subscription;
|
||||||
|
name: String;
|
||||||
|
category: String;
|
||||||
|
length_test: number;
|
||||||
|
length_packages: number;
|
||||||
|
goodNow: number;
|
||||||
|
started: Boolean = false;
|
||||||
|
finish: Boolean = false;
|
||||||
|
left: Boolean = true;
|
||||||
|
right: Boolean = false;
|
||||||
|
checked: Boolean = false;
|
||||||
|
not_last: Boolean = true;
|
||||||
|
packages: Array<Object> = [];
|
||||||
|
filled = 0;
|
||||||
|
good = 0;
|
||||||
|
bad = 0;
|
||||||
|
package_id = 0;
|
||||||
|
|
||||||
|
constructor(private flashcardsService: FlashcardsService, private route: ActivatedRoute) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.id = this.route.snapshot.params.id;
|
||||||
|
this.flashcardSubscribtionMeta = this.flashcardsService.getSet(this.id).subscribe(data => {
|
||||||
|
this.name = data['name'];
|
||||||
|
this.category = data['category'];
|
||||||
|
});
|
||||||
|
this.flashcardSubscribtion = this.flashcardsService.getTestPairing(this.id).subscribe(data => {
|
||||||
|
this.length_test = data['left'].length;
|
||||||
|
this.createPackages(data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
createPackages(data) {
|
||||||
|
let attribute = '0';
|
||||||
|
let setLeft = [];
|
||||||
|
let setRight = [];
|
||||||
|
const n = this.length_test;
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
if (i % 5 === 0) {
|
||||||
|
this.packages[attribute] = {
|
||||||
|
setLeft: setLeft,
|
||||||
|
setRight: setRight
|
||||||
|
};
|
||||||
|
attribute = (i / 5).toString();
|
||||||
|
setLeft = [];
|
||||||
|
setRight = [];
|
||||||
|
}
|
||||||
|
setLeft.push(data['left'][i]);
|
||||||
|
setRight.push(data['right'][i]);
|
||||||
|
if (i === (n - 1)) {
|
||||||
|
this.packages[attribute] = {
|
||||||
|
setLeft: setLeft,
|
||||||
|
setRight: setRight
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.length_packages = this.packages.length;
|
||||||
|
if (this.packages.length < 2) {
|
||||||
|
this.not_last = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
this.started = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
increment() {
|
||||||
|
if (this.package_id === (this.length_packages - 2)) {
|
||||||
|
this.not_last = false;
|
||||||
|
}
|
||||||
|
if (this.package_id === (this.length_packages - 1)) {
|
||||||
|
this.started = false;
|
||||||
|
this.finish = true;
|
||||||
|
} else {
|
||||||
|
this.package_id += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
goodEvent(goods) {
|
||||||
|
this.goodNow = goods;
|
||||||
|
const filledNow = this.packages[this.package_id]['setLeft'].length;
|
||||||
|
this.filled = filledNow;
|
||||||
|
this.good = this.goodNow;
|
||||||
|
this.bad = this.filled - this.good;
|
||||||
|
}
|
||||||
|
|
||||||
|
isChecked(check) {
|
||||||
|
this.checked = check;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.flashcardSubscribtionMeta.unsubscribe();
|
||||||
|
this.flashcardSubscribtion.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
.listItem:hover {
|
||||||
|
background-color: rgb(206, 168, 86);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper{
|
||||||
|
width: 100%;
|
||||||
|
padding: 30px;
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn{
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content{
|
||||||
|
background-color: #181616;
|
||||||
|
padding: 30px;
|
||||||
|
margin-top: 2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons-container > div{
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.puzzle{
|
||||||
|
min-height: 50px;
|
||||||
|
min-width: 100px;
|
||||||
|
background-color: rgb(206, 168, 86);
|
||||||
|
align-items: center;
|
||||||
|
color: black;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 5px 5px 5px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.puzzle-right{
|
||||||
|
min-height: 50px;
|
||||||
|
min-width: 100px;
|
||||||
|
color: black;
|
||||||
|
background-color: rgb(202, 144, 17);;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 5px 5px 5px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.both-sides{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.puzzles-container{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty{
|
||||||
|
background-color: gray;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
|||||||
|
<div class="wrapper">
|
||||||
|
<div class="content">
|
||||||
|
<div class="button-container">
|
||||||
|
<button class="btn btn-study-cave" (click)="goBack()"><i class="fas fa-arrow-left"></i> POWRÓT</button>
|
||||||
|
<button class="btn btn-study-cave" (click)="showTestTypeMenu()"><i class="fas fa-pencil-ruler"></i> GENERUJ TESTY</button>
|
||||||
|
<button *ngIf="owned && set && set.permission !== 'GROUP'" class="btn btn-study-cave" (click)="navigateToEditMode()"><i class="fas fa-edit"></i> EDYTUJ FISZKI</button>
|
||||||
|
<button *ngIf="owned && set && set.permission !== 'GROUP'" class="btn btn-study-cave" (click)="showPopup()"><i class="fas fa-trash-alt"></i> USUŃ FISZKI</button>
|
||||||
|
<div *ngIf="user && owned && set && set.permission !== 'GROUP'">
|
||||||
|
<button class="btn btn-study-cave" (click)="changePermission()"><i class="fas fa-unlock"></i> ZMIEŃ UPRAWNIENIA</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<app-flashcards-test-type-menu [id]="id" (cancel)="handleCancelFlashcardsTestyTypeMenu($event)" *ngIf="testTypeMenu"></app-flashcards-test-type-menu>
|
||||||
|
<br />
|
||||||
|
<div *ngIf="set">
|
||||||
|
<h2>{{set.name}}</h2>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<th>
|
||||||
|
Lewa strona
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Prawa strona
|
||||||
|
</th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr *ngFor="let flashcard of set.flashcards; let i = index">
|
||||||
|
<td class="puzzle">{{flashcard.left_side}}</td>
|
||||||
|
<td class="puzzle-right">{{flashcard.right_side}}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<app-comments [what]="'flashcardsets'"></app-comments>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p-dialog header="Potwierdź" [(visible)]="display">
|
||||||
|
Czy chcesz usunąć fiszkę?
|
||||||
|
<p-footer>
|
||||||
|
<button type="button" pButton icon="pi pi-check" (click)="deleteSet()" label="TAK"></button>
|
||||||
|
<button type="button" pButton icon="pi pi-close" (click)="display=false" label="NIE" class="ui-button-secondary"></button>
|
||||||
|
</p-footer>
|
||||||
|
</p-dialog>
|
||||||
|
</div>
|
@ -0,0 +1,65 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FlashcardsSetDetailComponent } from './flashcards-set-detail.component';
|
||||||
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { AuthenticationService } from '../../authentication.service';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { RoutingStateService } from '../../routing-state.service';
|
||||||
|
|
||||||
|
describe('FlashcardsSetDetailComponent', () => {
|
||||||
|
let component: FlashcardsSetDetailComponent;
|
||||||
|
let fixture: ComponentFixture<FlashcardsSetDetailComponent>;
|
||||||
|
let mockSet: any;
|
||||||
|
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ FlashcardsSetDetailComponent ],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA],
|
||||||
|
providers: [FlashcardsService, AuthenticationService, RoutingStateService],
|
||||||
|
imports: [ RouterTestingModule, FormsModule, HttpClientModule, MatSnackBarModule]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(FlashcardsSetDetailComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
mockSet = {
|
||||||
|
name: 'testName',
|
||||||
|
flashcards: [
|
||||||
|
{
|
||||||
|
left_side: 'testLeftSide',
|
||||||
|
right_side: 'testRightSide'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
// testowanie DOM
|
||||||
|
it('should render set name', () => {
|
||||||
|
component.set = mockSet;
|
||||||
|
fixture.detectChanges();
|
||||||
|
const setName = document.querySelector('h2').innerHTML;
|
||||||
|
expect(setName).toEqual(mockSet.name);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render flashcards sides', () => {
|
||||||
|
component.set = mockSet;
|
||||||
|
fixture.detectChanges();
|
||||||
|
const leftSide = document.querySelector('.puzzle').innerHTML;
|
||||||
|
expect(leftSide).toEqual('testLeftSide');
|
||||||
|
const rightSide = document.querySelector('.puzzle-right').innerHTML;
|
||||||
|
expect(rightSide).toEqual('testRightSide');
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,102 @@
|
|||||||
|
import { Component, OnInit, OnDestroy, Input } from '@angular/core';
|
||||||
|
import { Set } from '../set';
|
||||||
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { Subscription } from 'rxjs/Subscription';
|
||||||
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
|
import { RoutingStateService } from '../../routing-state.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-flashcards-set-detail',
|
||||||
|
templateUrl: './flashcards-set-detail.component.html',
|
||||||
|
styleUrls: ['./flashcards-set-detail.component.css']
|
||||||
|
})
|
||||||
|
export class FlashcardsSetDetailComponent implements OnInit, OnDestroy {
|
||||||
|
id: number;
|
||||||
|
set: any;
|
||||||
|
flashcardSubscribtion: Subscription;
|
||||||
|
testTypeMenu = false;
|
||||||
|
user: Boolean = false;
|
||||||
|
ShowStatus: Boolean = false;
|
||||||
|
permission: string;
|
||||||
|
owner;
|
||||||
|
owned: Boolean = false;
|
||||||
|
display = false;
|
||||||
|
|
||||||
|
constructor(private route: ActivatedRoute, private flashcardsService: FlashcardsService, private router: Router,
|
||||||
|
private routingState: RoutingStateService, public snackBar: MatSnackBar) { }
|
||||||
|
ngOnInit() {
|
||||||
|
const previousUrl = this.routingState.getPreviousUrl();
|
||||||
|
if (previousUrl.indexOf('test-gen') === -1) {
|
||||||
|
sessionStorage.setItem('previousUrl', previousUrl);
|
||||||
|
}
|
||||||
|
this.id = this.route.snapshot.params.id;
|
||||||
|
this.flashcardSubscribtion = this.flashcardsService.getSet(this.id).subscribe(data => { this.set = data; });
|
||||||
|
this.IsLogin();
|
||||||
|
this.owner = this.flashcardsService.getOwner();
|
||||||
|
this.isOwner();
|
||||||
|
}
|
||||||
|
|
||||||
|
isOwner() {
|
||||||
|
const currentUser = JSON.parse(localStorage.getItem('currentUser'));
|
||||||
|
if (localStorage.getItem('currentUser')) {
|
||||||
|
if (currentUser.username === this.owner) {
|
||||||
|
this.owned = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.owned = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showTestTypeMenu() {
|
||||||
|
this.testTypeMenu = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
IsLogin() {
|
||||||
|
if (localStorage.getItem('currentUser')) {
|
||||||
|
this.user = true;
|
||||||
|
} else {
|
||||||
|
this.user = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showPopup() {
|
||||||
|
this.display = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
changePermission(): void {
|
||||||
|
if (this.set.permission === 'Public') {
|
||||||
|
this.permission = 'Private';
|
||||||
|
} else {
|
||||||
|
this.permission = 'Public';
|
||||||
|
}
|
||||||
|
this.flashcardsService.changeSetPermission(this.id, this.permission);
|
||||||
|
this.snackBar.open('Zmieniono pozwolenie na: ' + this.permission, null,
|
||||||
|
{ duration: 3000, verticalPosition: 'top', panelClass: ['snackbar-success'] });
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCancelFlashcardsTestyTypeMenu(e) {
|
||||||
|
this.testTypeMenu = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
navigateToEditMode() {
|
||||||
|
this.router.navigate(['flashcards/sets/edit', this.id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.flashcardSubscribtion.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteSet() {
|
||||||
|
const data = this.id;
|
||||||
|
this.flashcardSubscribtion = this.flashcardsService.deleteSet(data);
|
||||||
|
this.display = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
goBack() {
|
||||||
|
const previousUrl = sessionStorage.getItem('previousUrl');
|
||||||
|
sessionStorage.removeItem('previousUrl');
|
||||||
|
this.router.navigate([previousUrl]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
.listItem:hover {
|
||||||
|
background-color: rgb(206, 168, 86);
|
||||||
|
}
|
||||||
|
|
||||||
|
.listItem:active{
|
||||||
|
background-color: #4BC7FA;
|
||||||
|
}
|
||||||
|
|
||||||
|
.listItem{
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper{
|
||||||
|
width: 100%;
|
||||||
|
padding: 30px;
|
||||||
|
min-height: 100%;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 800px) {
|
||||||
|
.mobile{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty{
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content{
|
||||||
|
background-color: #181616;
|
||||||
|
padding: 30px;
|
||||||
|
margin-top: 2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
ag-grid-angular{
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons-container > div{
|
||||||
|
margin: 10px;
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
<div class="wrapper">
|
||||||
|
<div class="content">
|
||||||
|
<app-flashcards></app-flashcards>
|
||||||
|
<br />
|
||||||
|
<h1>FISZKI</h1>
|
||||||
|
<br />
|
||||||
|
<div class="buttons-container">
|
||||||
|
<div *ngIf="logged">
|
||||||
|
<button class="btn btn-study-cave" (click)="toFlashcardsMaker()"><i class="fas fa-plus"></i> Dodaj fiszki</button>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="logged" class="btn-group btn-group-toggle" data-toggle="buttons">
|
||||||
|
<label class="btn btn-study-cave active" (click)="ShowPublic()">
|
||||||
|
<input type="radio" name="options" id="option1" autocomplete="off" checked><i class="fas fa-globe"></i> Publiczne
|
||||||
|
</label>
|
||||||
|
<label class="btn btn-study-cave" (click)="ShowPrivate()">
|
||||||
|
<input type="radio" name="options" id="option2" autocomplete="off"><i class="fas fa-user-secret"></i> Prywatne
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<ag-grid-angular style="width: 100%; height: 475px;" class="ag-theme-dark" [rowData]="sets" [columnDefs]="columnDefs" [enableSorting]="true"
|
||||||
|
[enableFilter]="true" (gridReady)="onGridReady($event)" (gridSizeChanged)="onGridSizeChanged($event)" [gridOptions]="gridOptions"
|
||||||
|
[pagination]="true" [paginationAutoPageSize]="true" (rowClicked)="onRowClicked($event)" [localeText]="localeText"
|
||||||
|
(gridColumnsChanged)="onGidColumnsChanged($event)">
|
||||||
|
</ag-grid-angular>
|
||||||
|
<p-dialog header="Potwierdź" [(visible)]="display">
|
||||||
|
Czy chcesz usunąć fiszkę?
|
||||||
|
<p-footer>
|
||||||
|
<button type="button" pButton icon="pi pi-check" (click)="deleteSet()" label="TAK"></button>
|
||||||
|
<button type="button" pButton icon="pi pi-close" (click)="display=false" label="NIE" class="ui-button-secondary"></button>
|
||||||
|
</p-footer>
|
||||||
|
</p-dialog>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,35 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FlashcardsSetsListComponent } from './flashcards-sets-list.component';
|
||||||
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { AuthenticationService } from '../../authentication.service';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
|
|
||||||
|
describe('FlashcardsSetsListComponent', () => {
|
||||||
|
let component: FlashcardsSetsListComponent;
|
||||||
|
let fixture: ComponentFixture<FlashcardsSetsListComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ FlashcardsSetsListComponent ],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA],
|
||||||
|
providers: [FlashcardsService, AuthenticationService],
|
||||||
|
imports: [ RouterTestingModule, FormsModule, HttpClientModule, MatSnackBarModule]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(FlashcardsSetsListComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,271 @@
|
|||||||
|
import { Component, OnInit, Output, EventEmitter, OnDestroy } from '@angular/core';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { Set } from '../set';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { Subscription } from 'rxjs/Subscription';
|
||||||
|
import { FilterPipe } from '../../filter.pipe';
|
||||||
|
import { GridOptions, RowDoubleClickedEvent } from 'ag-grid-community/main';
|
||||||
|
import localeText from './localeText';
|
||||||
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-flashcards-sets-list',
|
||||||
|
templateUrl: './flashcards-sets-list.component.html',
|
||||||
|
styleUrls: ['./flashcards-sets-list.component.css']
|
||||||
|
})
|
||||||
|
export class FlashcardsSetsListComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
sets = [];
|
||||||
|
privatesets = [];
|
||||||
|
setsEmpty = true;
|
||||||
|
selectedSet: Set;
|
||||||
|
flashcardSubscription: Subscription;
|
||||||
|
flashcardSubscriptionOwners: Subscription;
|
||||||
|
user: Boolean;
|
||||||
|
ShowStatus: Boolean = false;
|
||||||
|
owner;
|
||||||
|
searchPublic = 'Public';
|
||||||
|
searchOwner;
|
||||||
|
gridApi;
|
||||||
|
gridColumnApi;
|
||||||
|
public gridOptions: GridOptions;
|
||||||
|
localeText = localeText;
|
||||||
|
logged = false;
|
||||||
|
publicMode = true;
|
||||||
|
permission;
|
||||||
|
display = false;
|
||||||
|
isGroup = false;
|
||||||
|
|
||||||
|
columnDefs = [
|
||||||
|
{ headerName: 'Nazwa', field: 'name', headerTooltip: 'Nazwa' },
|
||||||
|
{ headerName: 'Data dodania', field: 'add_date', headerTooltip: 'Data dodania', hide: false },
|
||||||
|
{ headerName: 'Data modyfikacji', field: 'edit_date', headerTooltip: 'Data modyfikacji', hide: false },
|
||||||
|
{ headerName: 'Właściciel', field: 'owner', headerTooltip: 'Właściciel', hide: false },
|
||||||
|
{ headerName: 'Grupa', field: 'group', headerTooltip: 'Grupa', hide: !this.isGroup },
|
||||||
|
{
|
||||||
|
headerName: '',
|
||||||
|
suppressMenu: true,
|
||||||
|
suppressSorting: true,
|
||||||
|
cellRenderer: this.customCellRendererFunc,
|
||||||
|
hide: !this.isGroup
|
||||||
|
}
|
||||||
|
];
|
||||||
|
setToDelete: any;
|
||||||
|
constructor(private flashcardsService: FlashcardsService, private router: Router, public snackBar: MatSnackBar) { }
|
||||||
|
|
||||||
|
customCellRendererFunc(params) {
|
||||||
|
const currentUser = JSON.parse(localStorage.getItem('currentUser'));
|
||||||
|
if (!currentUser) {
|
||||||
|
return '';
|
||||||
|
} else if (params.data['owner'] === currentUser.username) {
|
||||||
|
return `
|
||||||
|
<button type="button" data-action-type="remove" class="btn btn-study-cave btn-sm" title="Usuń">
|
||||||
|
<i class="fas fa-trash-alt" data-action-type="remove"></i></button>
|
||||||
|
<button type="button" data-action-type="changePermission" class="btn btn-study-cave btn-sm" title="Uprawnienia">
|
||||||
|
<i class="fas fa-unlock" data-action-type="changePermission"></i></button>
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onSelect(set: Set): void {
|
||||||
|
this.selectedSet = set;
|
||||||
|
this.router.navigate(['flashcards/sets', this.selectedSet.id]);
|
||||||
|
this.flashcardsService.setOwner(this.selectedSet.owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
toFlashcardsMaker() {
|
||||||
|
this.router.navigate(['flashcards/add']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public onRowClicked(e) {
|
||||||
|
if (e.event.target !== undefined) {
|
||||||
|
const data = e.data;
|
||||||
|
const actionType = e.event.target.getAttribute('data-action-type');
|
||||||
|
|
||||||
|
switch (actionType) {
|
||||||
|
case 'remove':
|
||||||
|
return this.onActionRemoveClick(e);
|
||||||
|
case 'changePermission':
|
||||||
|
return this.changePermission(e);
|
||||||
|
default:
|
||||||
|
return this.goToSets(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public onActionRemoveClick(e) {
|
||||||
|
this.display = true;
|
||||||
|
this.setToDelete = e.data.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteSet() {
|
||||||
|
const data = this.setToDelete;
|
||||||
|
this.flashcardSubscription = this.flashcardsService.deleteSet(data);
|
||||||
|
this.display = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
changePermission(e): void {
|
||||||
|
if (e.data.permission === 'Public') {
|
||||||
|
this.permission = 'Private';
|
||||||
|
} else {
|
||||||
|
this.permission = 'Public';
|
||||||
|
}
|
||||||
|
this.flashcardsService.changeSetPermission(e.data.id, this.permission);
|
||||||
|
this.snackBar.open('Zmieniono pozwolenie na: ' + this.permission, null,
|
||||||
|
{ duration: 3000, verticalPosition: 'top', panelClass: ['snackbar-success'] });
|
||||||
|
}
|
||||||
|
|
||||||
|
goToSets(e) {
|
||||||
|
this.router.navigate(['flashcards/sets', e.data.id]);
|
||||||
|
this.flashcardsService.setOwner(e.data.owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
IsLogin() {
|
||||||
|
const own = JSON.parse(localStorage.getItem('currentUser'));
|
||||||
|
if (localStorage.getItem('currentUser')) {
|
||||||
|
this.user = true;
|
||||||
|
this.searchOwner = own.username;
|
||||||
|
} else {
|
||||||
|
this.user = false;
|
||||||
|
this.searchOwner = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowPublic() {
|
||||||
|
this.sets = [];
|
||||||
|
this.ShowStatus = false;
|
||||||
|
this.getSets();
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowPrivate() {
|
||||||
|
this.privatesets = [];
|
||||||
|
this.ShowStatus = true;
|
||||||
|
this.getSetsOwners();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
if (localStorage.getItem('currentUser')) {
|
||||||
|
this.logged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.gridOptions = {
|
||||||
|
rowHeight: 50,
|
||||||
|
headerHeight: 25,
|
||||||
|
getRowStyle: function (params) {
|
||||||
|
return {
|
||||||
|
cursor: 'pointer'
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
this.getSets();
|
||||||
|
this.IsLogin();
|
||||||
|
this.refreshColumns();
|
||||||
|
}
|
||||||
|
|
||||||
|
getSets(): void {
|
||||||
|
this.isGroup = false;
|
||||||
|
this.flashcardSubscription = this.flashcardsService.getSets()
|
||||||
|
.subscribe(data => {
|
||||||
|
this.sets = data;
|
||||||
|
if (this.sets.length > 0) {
|
||||||
|
this.setsEmpty = false;
|
||||||
|
} else {
|
||||||
|
this.setsEmpty = true;
|
||||||
|
}
|
||||||
|
this.refreshColumns();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getSetsOwners(): void {
|
||||||
|
this.isGroup = true;
|
||||||
|
this.flashcardSubscriptionOwners = this.flashcardsService.getSetsOwners()
|
||||||
|
.subscribe(data => {
|
||||||
|
data.forEach((x, i) => {
|
||||||
|
if (!x['group']) {
|
||||||
|
x['group'] = 'Brak';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.sets = data;
|
||||||
|
if (this.sets.length > 0) {
|
||||||
|
this.setsEmpty = false;
|
||||||
|
} else {
|
||||||
|
this.setsEmpty = true;
|
||||||
|
}
|
||||||
|
this.refreshColumns();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onGridReady(params) {
|
||||||
|
this.gridApi = params.api;
|
||||||
|
this.gridColumnApi = params.columnApi;
|
||||||
|
this.gridApi.sizeColumnsToFit();
|
||||||
|
}
|
||||||
|
|
||||||
|
onGridSizeChanged(params) {
|
||||||
|
if (params.clientWidth < 800) {
|
||||||
|
this.columnDefs = [
|
||||||
|
{ headerName: 'Nazwa', field: 'name', headerTooltip: 'Nazwa' },
|
||||||
|
{ headerName: 'Data dodania', field: 'add_date', headerTooltip: 'Data dodania', hide: true },
|
||||||
|
{ headerName: 'Data modyfikacji', field: 'edit_date', headerTooltip: 'Data modyfikacji', hide: true },
|
||||||
|
{ headerName: 'Właściciel', field: 'owner', headerTooltip: 'Właściciel', hide: true },
|
||||||
|
{ headerName: 'Grupa', field: 'group', headerTooltip: 'Grupa', hide: !this.isGroup },
|
||||||
|
{
|
||||||
|
headerName: '',
|
||||||
|
suppressMenu: true,
|
||||||
|
suppressSorting: true,
|
||||||
|
cellRenderer: this.customCellRendererFunc,
|
||||||
|
hide: !this.isGroup
|
||||||
|
}
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
this.columnDefs = [
|
||||||
|
{ headerName: 'Nazwa', field: 'name', headerTooltip: 'Nazwa' },
|
||||||
|
{ headerName: 'Data dodania', field: 'add_date', headerTooltip: 'Data dodania', hide: false },
|
||||||
|
{ headerName: 'Data modyfikacji', field: 'edit_date', headerTooltip: 'Data modyfikacji', hide: false },
|
||||||
|
{ headerName: 'Właściciel', field: 'owner', headerTooltip: 'Właściciel', hide: false },
|
||||||
|
{ headerName: 'Grupa', field: 'group', headerTooltip: 'Grupa', hide: !this.isGroup },
|
||||||
|
{
|
||||||
|
headerName: '',
|
||||||
|
suppressMenu: true,
|
||||||
|
suppressSorting: true,
|
||||||
|
cellRenderer: this.customCellRendererFunc,
|
||||||
|
hide: !this.isGroup
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
params.api.sizeColumnsToFit();
|
||||||
|
}
|
||||||
|
|
||||||
|
onGidColumnsChanged(params) {
|
||||||
|
params.api.sizeColumnsToFit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
if (this.flashcardSubscription) {
|
||||||
|
this.flashcardSubscription.unsubscribe();
|
||||||
|
}
|
||||||
|
if (this.flashcardSubscriptionOwners) {
|
||||||
|
this.flashcardSubscriptionOwners.unsubscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshColumns() {
|
||||||
|
this.columnDefs = [
|
||||||
|
{ headerName: 'Nazwa', field: 'name', headerTooltip: 'Nazwa' },
|
||||||
|
{ headerName: 'Data dodania', field: 'add_date', headerTooltip: 'Data dodania', hide: false },
|
||||||
|
{ headerName: 'Data modyfikacji', field: 'edit_date', headerTooltip: 'Data modyfikacji', hide: false },
|
||||||
|
{ headerName: 'Właściciel', field: 'owner', headerTooltip: 'Właściciel', hide: false },
|
||||||
|
{ headerName: 'Grupa', field: 'group', headerTooltip: 'Grupa', hide: !this.isGroup },
|
||||||
|
{
|
||||||
|
headerName: '',
|
||||||
|
suppressMenu: true,
|
||||||
|
suppressSorting: true,
|
||||||
|
cellRenderer: this.customCellRendererFunc,
|
||||||
|
hide: !this.isGroup
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
90
src/app/flashcards/flashcards-sets-list/localeText.ts
Normal file
90
src/app/flashcards/flashcards-sets-list/localeText.ts
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
const localeText = {
|
||||||
|
|
||||||
|
// for filter panel
|
||||||
|
page: 'Strona',
|
||||||
|
more: 'Więcej',
|
||||||
|
to: 'do',
|
||||||
|
of: 'z',
|
||||||
|
next: '>',
|
||||||
|
last: '>>',
|
||||||
|
first: '<<',
|
||||||
|
previous: '<',
|
||||||
|
loadingOoo: 'Ładowanie...',
|
||||||
|
|
||||||
|
// for set filter
|
||||||
|
selectAll: 'Wybierz wszystkie',
|
||||||
|
searchOoo: 'Szukaj',
|
||||||
|
blanks: 'Luki',
|
||||||
|
|
||||||
|
// for number filter and text filter
|
||||||
|
filterOoo: 'Filtruj...',
|
||||||
|
applyFilter: 'Zastosuj filtr',
|
||||||
|
|
||||||
|
// for number filter
|
||||||
|
equals: 'Równy',
|
||||||
|
notEqual: 'Nie równy',
|
||||||
|
lessThan: 'Mniejszy niż',
|
||||||
|
greaterThan: 'Większy niż',
|
||||||
|
|
||||||
|
// for text filter
|
||||||
|
contains: 'Zawiera',
|
||||||
|
notContains: 'Nie zawiera',
|
||||||
|
startsWith: 'Zaczyna się od',
|
||||||
|
endsWith: 'Kończy się na',
|
||||||
|
|
||||||
|
// the header of the default group column
|
||||||
|
group: 'Grupa',
|
||||||
|
|
||||||
|
// tool panel
|
||||||
|
columns: 'Kolumny',
|
||||||
|
rowGroupColumns: 'Grupa wiersza kolumn',
|
||||||
|
rowGroupColumnsEmptyMessage: 'Przeciągnij kolumny do grupy',
|
||||||
|
valueColumns: 'Wartości kolumn',
|
||||||
|
pivotMode: 'Pivot-Mode',
|
||||||
|
groups: 'Grupy',
|
||||||
|
values: 'Wartości',
|
||||||
|
pivots: 'Pivots',
|
||||||
|
valueColumnsEmptyMessage: 'Przeciągnij kolumny do agregacji',
|
||||||
|
pivotColumnsEmptyMessage: 'Przeciągnij kolumny na oś',
|
||||||
|
toolPanelButton: 'Narzędzia',
|
||||||
|
|
||||||
|
// other
|
||||||
|
noRowsToShow: 'Brak fiszek do wyświetlenia',
|
||||||
|
|
||||||
|
// enterprise menu
|
||||||
|
pinColumn: 'Przypiąta kolumna',
|
||||||
|
valueAggregation: 'Sumuj',
|
||||||
|
autosizeThiscolumn: 'Autosize this column',
|
||||||
|
autosizeAllColumns: 'Autosize All Columns',
|
||||||
|
groupBy: 'Grupuj po',
|
||||||
|
ungroupBy: 'Nie grupuj po',
|
||||||
|
resetColumns: 'Resetuj kolumny',
|
||||||
|
expandAll: 'Rozszerz wszystko',
|
||||||
|
collapseAll: 'Zwiń wszystko',
|
||||||
|
toolPanel: 'Narzędzia',
|
||||||
|
export: 'Export',
|
||||||
|
csvExport: 'CSV Export',
|
||||||
|
excelExport: 'Excel Export',
|
||||||
|
|
||||||
|
// enterprise menu pinning
|
||||||
|
pinLeft: 'Przypnij <<',
|
||||||
|
pinRight: 'Przypnij >>',
|
||||||
|
noPin: 'Nie przypinaj <>',
|
||||||
|
|
||||||
|
// enterprise menu aggregation and status panel
|
||||||
|
sum: 'Suma',
|
||||||
|
min: 'Minimum',
|
||||||
|
max: 'Maksimum',
|
||||||
|
none: 'Nic',
|
||||||
|
count: 'Ilość',
|
||||||
|
average: 'Średnia',
|
||||||
|
|
||||||
|
// standard menu
|
||||||
|
copy: 'Kopiuj',
|
||||||
|
copyWithHeaders: 'Kopiuj z nagłówkami',
|
||||||
|
ctrlC: 'ctrl + C',
|
||||||
|
paste: 'wklej',
|
||||||
|
ctrlV: 'ctrl + C'
|
||||||
|
};
|
||||||
|
|
||||||
|
export default localeText;
|
@ -0,0 +1,4 @@
|
|||||||
|
div{
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
<div>
|
||||||
|
<button class="btn btn-study-cave" (click)="goToTestGenFill()">Uzupełnij</button>
|
||||||
|
<button class="btn btn-study-cave" (click)="goToTestGen()">Pary</button>
|
||||||
|
<button class="btn btn-study-cave" (click)="goToTestGenTyperace()">Na czas</button>
|
||||||
|
<button class="btn btn-study-cave" (click)="goToTestGenMemory()">Memory</button>
|
||||||
|
<button class="btn btn-study-cave" (click)="cancelMenu()"><i class="fas fa-times"></i> Anuluj</button>
|
||||||
|
</div>
|
@ -0,0 +1,34 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FlashcardsTestTypeMenuComponent } from './flashcards-test-type-menu.component';
|
||||||
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { AuthenticationService } from '../../authentication.service';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
|
|
||||||
|
describe('FlashcardsTestTypeMenuComponent', () => {
|
||||||
|
let component: FlashcardsTestTypeMenuComponent;
|
||||||
|
let fixture: ComponentFixture<FlashcardsTestTypeMenuComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ FlashcardsTestTypeMenuComponent ],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA],
|
||||||
|
providers: [FlashcardsService, AuthenticationService],
|
||||||
|
imports: [ RouterTestingModule, FormsModule, HttpClientModule, MatSnackBarModule]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(FlashcardsTestTypeMenuComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,37 @@
|
|||||||
|
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-flashcards-test-type-menu',
|
||||||
|
templateUrl: './flashcards-test-type-menu.component.html',
|
||||||
|
styleUrls: ['./flashcards-test-type-menu.component.css']
|
||||||
|
})
|
||||||
|
export class FlashcardsTestTypeMenuComponent implements OnInit {
|
||||||
|
@Input() id: Number;
|
||||||
|
@Output() cancel = new EventEmitter;
|
||||||
|
|
||||||
|
cancelMenu() {
|
||||||
|
this.cancel.emit(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
goToTestGen() {
|
||||||
|
this.router.navigate(['flashcards/test-gen/flashcards-pairs', this.id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
goToTestGenFill() {
|
||||||
|
this.router.navigate(['flashcards/test-gen/flashcards-filling-in', this.id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
goToTestGenMemory() {
|
||||||
|
this.router.navigate(['flashcards/test-gen/flashcards-memory', this.id]);
|
||||||
|
}
|
||||||
|
goToTestGenTyperace() {
|
||||||
|
this.router.navigate(['flashcards/test-gen/flashcards-typerace', this.id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(private router: Router) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
#container-small {
|
||||||
|
background-color: #181616;
|
||||||
|
padding: 30px;
|
||||||
|
width: 32%;
|
||||||
|
min-height: 400px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-content: center;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container-large {
|
||||||
|
background-color: #181616;
|
||||||
|
padding: 30px;
|
||||||
|
width: 62%;
|
||||||
|
min-height: 400px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
margin-bottom: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 800px) {
|
||||||
|
.content {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container-small {
|
||||||
|
height: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container-small, #container-large {
|
||||||
|
width: 90%;
|
||||||
|
margin-bottom: 2.5rem;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
<div class="content">
|
||||||
|
<div id="container-small">
|
||||||
|
<h4>Przepisywanie fiszek na czas</h4>
|
||||||
|
<br />
|
||||||
|
<div>
|
||||||
|
<b>Nazwa zestawu: </b>
|
||||||
|
<i>{{ name }}</i>
|
||||||
|
<br />
|
||||||
|
<b>Kategoria: </b>
|
||||||
|
<i>{{ category }}</i>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="started">
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<b>Uzupełniono: </b>
|
||||||
|
<span> {{ filled }} z {{ length_test }} fiszek</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<b>Poprawnych odpowiedzi: </b>
|
||||||
|
<span> {{ good }} na {{ length_test }}</span><br />
|
||||||
|
<b>Złych odpowiedzi: </b>
|
||||||
|
<span> {{ bad }} na {{ length_test }}</span><br />
|
||||||
|
<div *ngIf="this.filled < this.length_test && !finish">
|
||||||
|
<b>Twój czas: </b>
|
||||||
|
<span> {{minute}} m {{second}} s {{millisecond}} ms</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="container-large">
|
||||||
|
<div *ngIf="started">
|
||||||
|
<div *ngIf="this.filled >= 1 && !finish">
|
||||||
|
Poprzednia odpowiedź:<br />
|
||||||
|
{{flashcards[index-1].content}} {{stoptimes[index-1].m}} m {{stoptimes[index-1].s}} s {{stoptimes[index-1].ms}} ms
|
||||||
|
</div>
|
||||||
|
<div *ngIf="this.filled < this.length_test && !finish">
|
||||||
|
Podaj odpowiedź:<br />
|
||||||
|
{{flashcards[index].content}}
|
||||||
|
<input appAutofocus [(ngModel)]="answer" class="mr-2" placeholder="odpowiedź" (keyup.enter)="verifyAnswer()" >
|
||||||
|
<button class="btn btn-study-cave" (click)="verifyAnswer()" ><i class="fas fa-check-circle"></i> Sprawdź</button>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="this.is_correct === true && !finish">ODPOWIEDŹ POPRAWNA</div>
|
||||||
|
<div *ngIf="this.is_correct === false && !finish">ODPOWIEDŹ NIEPOPRAWNA</div>
|
||||||
|
<div *ngIf="this.filled < this.length_test-1 && !finish">
|
||||||
|
Następne pytanie:<br />
|
||||||
|
{{flashcards[index+1].content}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="finish">
|
||||||
|
<app-test-results [result]="good" [maxPts]="length_test" [minutes]="finalminute" [seconds]="finalsecond" [milliseconds]="finalmillisecond" [timer]="true"></app-test-results>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="!finish">
|
||||||
|
<button class="btn btn-study-cave" *ngIf="!started" (click)="start()"><i class="far fa-play-circle"></i> Rozpocznij test</button>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-study-cave" *ngIf="finish" routerLink="/flashcards/sets/{{ id }}"><i class="far fa-stop-circle"></i> Zakończ test</button>
|
||||||
|
<button class="btn btn-study-cave" *ngIf="started && !finish && !not_last"(click)="finished()"><i class="far fa-stop-circle"></i> Przejdź do wyniku</button>
|
||||||
|
<br />
|
||||||
|
<button class="btn btn-study-cave" routerLink="/flashcards/sets/{{ id }}"><i class="fas fa-arrow-left"></i> Wróć do zestawu</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,34 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FlashcardsTyperaceTestComponent } from './flashcards-typerace-test.component';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { AuthenticationService } from '../../authentication.service';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
|
|
||||||
|
describe('FlashcardsTyperaceTestComponent', () => {
|
||||||
|
let component: FlashcardsTyperaceTestComponent;
|
||||||
|
let fixture: ComponentFixture<FlashcardsTyperaceTestComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ FlashcardsTyperaceTestComponent ],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA],
|
||||||
|
providers: [FlashcardsService, AuthenticationService],
|
||||||
|
imports: [ RouterTestingModule, FormsModule, HttpClientModule, MatSnackBarModule]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(FlashcardsTyperaceTestComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,167 @@
|
|||||||
|
import { Component, OnInit, Input, OnDestroy } from '@angular/core';
|
||||||
|
import { FlashcardsService } from '../flashcards.service';
|
||||||
|
import { Subscription } from 'rxjs/Subscription';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-flashcards-typerace-test',
|
||||||
|
templateUrl: './flashcards-typerace-test.component.html',
|
||||||
|
styleUrls: ['./flashcards-typerace-test.component.css']
|
||||||
|
})
|
||||||
|
export class FlashcardsTyperaceTestComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
id: number;
|
||||||
|
private flashcardSubscribtionMeta: Subscription;
|
||||||
|
private flashcardSubscribtion: Subscription;
|
||||||
|
private flashcardSubscribtionCheck: Subscription;
|
||||||
|
|
||||||
|
name: String;
|
||||||
|
category: String;
|
||||||
|
length_test: number;
|
||||||
|
goodNow: number;
|
||||||
|
started: Boolean = false;
|
||||||
|
finish: Boolean = false;
|
||||||
|
flashcards: Array<Object> = [];
|
||||||
|
filled = 0;
|
||||||
|
good = 0;
|
||||||
|
bad = 0;
|
||||||
|
answer: String;
|
||||||
|
index = 0;
|
||||||
|
not_last: Boolean = true;
|
||||||
|
is_correct: Boolean;
|
||||||
|
allAnswers = [];
|
||||||
|
stoptimes = [];
|
||||||
|
|
||||||
|
hour= 0;
|
||||||
|
minute= 0;
|
||||||
|
second= 0;
|
||||||
|
millisecond= 0;
|
||||||
|
starttime= false;
|
||||||
|
pause= false;
|
||||||
|
x= 10;
|
||||||
|
intervalId;
|
||||||
|
|
||||||
|
finalhour= 0;
|
||||||
|
finalminute= 0;
|
||||||
|
finalsecond= 0;
|
||||||
|
finalmillisecond= 0;
|
||||||
|
|
||||||
|
constructor(private flashcardsService: FlashcardsService, private route: ActivatedRoute) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.id = this.route.snapshot.params.id;
|
||||||
|
this.flashcardSubscribtionMeta = this.flashcardsService.getSet(this.id).subscribe(data => {
|
||||||
|
this.name = data['name'];
|
||||||
|
this.category = data['category'];
|
||||||
|
});
|
||||||
|
this.flashcardSubscribtion = this.flashcardsService.getTestFilling(this.id).subscribe(data => {
|
||||||
|
this.length_test = data.length;
|
||||||
|
this.flashcards = data;
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
this.started = true;
|
||||||
|
this.onStart();
|
||||||
|
}
|
||||||
|
finished() {
|
||||||
|
this.finish = true;
|
||||||
|
this.onPause();
|
||||||
|
}
|
||||||
|
verifyAnswer() {
|
||||||
|
this.reset();
|
||||||
|
const body = [];
|
||||||
|
const n = this.length_test;
|
||||||
|
if (this.answer === '') {
|
||||||
|
this.answer = ' ';
|
||||||
|
}
|
||||||
|
this.allAnswers.push({
|
||||||
|
id: this.index,
|
||||||
|
answer: this.answer,
|
||||||
|
});
|
||||||
|
body.push({
|
||||||
|
id: this.flashcards[this.index]['id'],
|
||||||
|
content: this.answer,
|
||||||
|
side: this.flashcards[this.index]['side'],
|
||||||
|
});
|
||||||
|
this.flashcardSubscribtionCheck = this.flashcardsService.testCheck(this.id, body[0])
|
||||||
|
.subscribe(data => {
|
||||||
|
this.is_correct = data.result;
|
||||||
|
if (this.is_correct === true) {
|
||||||
|
this.good = this.good + 1;
|
||||||
|
} else {
|
||||||
|
this.bad = this.bad + 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (this.index < this.length_test) {
|
||||||
|
this.index = this.index + 1;
|
||||||
|
this.filled = this.filled + 1;
|
||||||
|
this.answer = '';
|
||||||
|
}
|
||||||
|
if (this.index === this.length_test) {
|
||||||
|
this.not_last = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.finalhour = this.finalhour + this.hour;
|
||||||
|
this.finalminute = this.finalminute + this.minute;
|
||||||
|
this.finalsecond = this.finalsecond + this.second;
|
||||||
|
this.finalmillisecond = this.finalmillisecond + this.millisecond;
|
||||||
|
this.stoptimes.push({
|
||||||
|
id: this.index,
|
||||||
|
m: this.minute,
|
||||||
|
s: this.second,
|
||||||
|
ms: this.millisecond,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.x = 0;
|
||||||
|
this.hour = this.minute = this.second = this.millisecond = 0;
|
||||||
|
this.starttime = false;
|
||||||
|
this.pause = false;
|
||||||
|
clearInterval(this.intervalId);
|
||||||
|
this.onStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
onStart() {
|
||||||
|
this.x = 10;
|
||||||
|
this.starttime = true;
|
||||||
|
this.intervalId = setInterval(() => {
|
||||||
|
this.updateTime();
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
onPause() {
|
||||||
|
this.pause = true;
|
||||||
|
clearInterval(this.intervalId);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTime() {
|
||||||
|
this.millisecond += this.x;
|
||||||
|
|
||||||
|
if (this.millisecond > 90) {
|
||||||
|
this.millisecond = 0;
|
||||||
|
this.second++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.second > 59) {
|
||||||
|
this.second = 0;
|
||||||
|
this.minute++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.minute > 59) {
|
||||||
|
this.minute = 0;
|
||||||
|
this.hour++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.flashcardSubscribtionMeta.unsubscribe();
|
||||||
|
this.flashcardSubscribtion.unsubscribe();
|
||||||
|
if (this.flashcardSubscribtionCheck) {
|
||||||
|
this.flashcardSubscribtionCheck.unsubscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
66
src/app/flashcards/flashcards.module.ts
Normal file
66
src/app/flashcards/flashcards.module.ts
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import * as $ from 'jquery';
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { HttpModule } from '@angular/http';
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
|
||||||
|
import { FlashcardsComponent } from './flashcards/flashcards.component';
|
||||||
|
import { FlashcardsSetsListComponent } from './flashcards-sets-list/flashcards-sets-list.component';
|
||||||
|
import { FlashcardsService } from './flashcards.service';
|
||||||
|
import { FlashcardsAddComponent } from './flashcards-add/flashcards-add.component';
|
||||||
|
import { FlashcardsAddTableComponent } from './flashcards-add-table/flashcards-add-table.component';
|
||||||
|
import { FlashcardsAddCsvComponent } from './flashcards-add-csv/flashcards-add-csv.component';
|
||||||
|
import { FlashcardsSetDetailComponent } from './flashcards-set-detail/flashcards-set-detail.component';
|
||||||
|
import { FlashcardsEditTableComponent } from './flashcards-edit-table/flashcards-edit-table.component';
|
||||||
|
import { FlashcardsPairsTestComponent } from './flashcards-pairs-test/flashcards-pairs-test.component';
|
||||||
|
import { FlashcardsPairsTestSetComponent } from './flashcards-pairs-test-set/flashcards-pairs-test-set.component';
|
||||||
|
import { FlashcardsTestTypeMenuComponent } from './flashcards-test-type-menu/flashcards-test-type-menu.component';
|
||||||
|
import { FlashcardsFillingInTestComponent } from './flashcards-filling-in-test/flashcards-filling-in-test.component';
|
||||||
|
import { FlashcardsMemoryTestComponent } from './flashcards-memory-test/flashcards-memory-test.component';
|
||||||
|
import { FlashcardsMemoryTestSetComponent } from './flashcards-memory-test-set/flashcards-memory-test-set.component';
|
||||||
|
import { FlashcardsTyperaceTestComponent } from './flashcards-typerace-test/flashcards-typerace-test.component';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { TestResultsComponent } from './test-results/test-results.component';
|
||||||
|
import { FilterUserPipe } from '../filter-user.pipe';
|
||||||
|
import { FilterPipe } from '../filter.pipe';
|
||||||
|
import { AgGridModule } from 'ag-grid-angular';
|
||||||
|
import { DialogModule } from 'primeng/dialog';
|
||||||
|
import { ConfirmDialogModule } from 'primeng/confirmdialog';
|
||||||
|
import { SharedModule } from '../shared/shared.module';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
RouterModule,
|
||||||
|
BrowserModule,
|
||||||
|
FormsModule,
|
||||||
|
HttpModule,
|
||||||
|
HttpClientModule,
|
||||||
|
AgGridModule.withComponents([]),
|
||||||
|
DialogModule,
|
||||||
|
ConfirmDialogModule,
|
||||||
|
SharedModule
|
||||||
|
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
TestResultsComponent,
|
||||||
|
FlashcardsComponent,
|
||||||
|
FlashcardsSetsListComponent,
|
||||||
|
FlashcardsAddComponent,
|
||||||
|
FlashcardsAddTableComponent,
|
||||||
|
FlashcardsAddCsvComponent,
|
||||||
|
FlashcardsSetDetailComponent,
|
||||||
|
FlashcardsEditTableComponent,
|
||||||
|
FlashcardsPairsTestComponent,
|
||||||
|
FlashcardsPairsTestSetComponent,
|
||||||
|
FlashcardsTestTypeMenuComponent,
|
||||||
|
FlashcardsFillingInTestComponent,
|
||||||
|
FlashcardsMemoryTestComponent,
|
||||||
|
FlashcardsMemoryTestSetComponent,
|
||||||
|
FlashcardsTyperaceTestComponent,
|
||||||
|
FilterUserPipe,
|
||||||
|
FilterPipe
|
||||||
|
],
|
||||||
|
providers: [FlashcardsService, FilterPipe, FilterUserPipe],
|
||||||
|
})
|
||||||
|
export class FlashcardsModule { }
|
23
src/app/flashcards/flashcards.service.spec.ts
Normal file
23
src/app/flashcards/flashcards.service.spec.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FlashcardsService } from './flashcards.service';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
|
import { AuthenticationService } from '../authentication.service';
|
||||||
|
|
||||||
|
describe('FlashcardsService', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [FlashcardsService, AuthenticationService],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA],
|
||||||
|
imports: [ RouterTestingModule, FormsModule, HttpClientModule, MatSnackBarModule]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([FlashcardsService], (service: FlashcardsService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
|
});
|
160
src/app/flashcards/flashcards.service.ts
Normal file
160
src/app/flashcards/flashcards.service.ts
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { HttpClient, HttpHeaders, HttpRequest, HttpEvent } from '@angular/common/http';
|
||||||
|
import { Http, Response, Headers, RequestOptions } from '@angular/http';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { of } from 'rxjs/observable/of';
|
||||||
|
import { Set } from './set';
|
||||||
|
import 'rxjs/add/operator/map';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { AuthenticationService } from '../authentication.service';
|
||||||
|
import { THIS_EXPR } from '@angular/compiler/src/output/output_ast';
|
||||||
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class FlashcardsService {
|
||||||
|
|
||||||
|
// tslint:disable-next-line:max-line-length
|
||||||
|
constructor(private httpClient: HttpClient, private router: Router, private authenticationService: AuthenticationService,
|
||||||
|
public snackBar: MatSnackBar) { this.setHeaders(); }
|
||||||
|
private headers;
|
||||||
|
owner;
|
||||||
|
|
||||||
|
setHeaders() {
|
||||||
|
if (localStorage.getItem('currentUser')) {
|
||||||
|
this.headers = new HttpHeaders({
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': '' + this.authenticationService.getToken()
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.headers = new HttpHeaders({
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
changeSetPermission(id, permission) {
|
||||||
|
this.setHeaders();
|
||||||
|
this.httpClient.put('sets/' + id + '/permission', permission, { headers: this.headers })
|
||||||
|
.subscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
add(body) {
|
||||||
|
const url = 'sets/';
|
||||||
|
this.sendData(url, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
edit(body) {
|
||||||
|
const url = 'sets/';
|
||||||
|
this.putData(url, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
getSets(): Observable<any> {
|
||||||
|
this.setHeaders();
|
||||||
|
return this.httpClient.get('sets', { headers: this.headers, params: { permission: 'Public' } });
|
||||||
|
}
|
||||||
|
getSetsOwners(): Observable<any> {
|
||||||
|
this.setHeaders();
|
||||||
|
const owner = JSON.parse(localStorage.getItem('currentUser'));
|
||||||
|
return this.httpClient.get('sets', { headers: this.headers, params: { owner: owner.username } });
|
||||||
|
}
|
||||||
|
|
||||||
|
setOwner(owner) {
|
||||||
|
if (owner === null) {
|
||||||
|
this.owner = ' ';
|
||||||
|
} else {
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getOwner() {
|
||||||
|
return this.owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendData(url, body) {
|
||||||
|
this.setHeaders();
|
||||||
|
this.httpClient.post(url, body, { headers: this.headers, observe: 'response' })
|
||||||
|
.subscribe(data => { this.sendResponse(data); },
|
||||||
|
error => {
|
||||||
|
this.snackBar.open('Coś poszło nie tak. Spróbuj ponownie później.', null,
|
||||||
|
{ duration: 3000, verticalPosition: 'top', panelClass: ['snackbar-error'] });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
putData(url, body) {
|
||||||
|
this.setHeaders();
|
||||||
|
this.httpClient.put(url, body, { headers: this.headers, observe: 'response' })
|
||||||
|
.subscribe(data => { this.sendResponse(data); },
|
||||||
|
error => {
|
||||||
|
this.snackBar.open('Coś poszło nie tak. Spróbuj ponownie później.', null,
|
||||||
|
{ duration: 3000, verticalPosition: 'top', panelClass: ['snackbar-error'] });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendResponse(data) {
|
||||||
|
if (data.status === 200) {
|
||||||
|
this.snackBar.open('Operacja przebiegła pomyślnie!', null,
|
||||||
|
{ duration: 3000, verticalPosition: 'top', panelClass: ['snackbar-success'] });
|
||||||
|
this.router.navigate(['flashcards/sets']);
|
||||||
|
} else {
|
||||||
|
this.snackBar.open('Coś poszło nie tak. Spróbuj ponownie później.', null,
|
||||||
|
{ duration: 3000, verticalPosition: 'top', panelClass: ['snackbar-error'] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sending file - import flashcards from CSV
|
||||||
|
pushFileToStorage(file: File, user: string, permission: string, url: string): Observable<HttpEvent<{}>> {
|
||||||
|
const formdata: FormData = new FormData();
|
||||||
|
formdata.append('file', file);
|
||||||
|
formdata.append('owner', user);
|
||||||
|
formdata.append('permission', permission);
|
||||||
|
const req = new HttpRequest('POST', url, formdata, {
|
||||||
|
reportProgress: true,
|
||||||
|
responseType: 'text'
|
||||||
|
});
|
||||||
|
return this.httpClient.request(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
getSet(id) {
|
||||||
|
return this.httpClient.get('sets/' + id + '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
getTestPairing(id) {
|
||||||
|
return this.httpClient.get('sets/' + id + '/test/pairing/');
|
||||||
|
}
|
||||||
|
|
||||||
|
getTestFilling(id) {
|
||||||
|
return this.httpClient.get('sets/' + id + '/test/filling-in/').map((data: Array<Object>) => data);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTestMemory(id) {
|
||||||
|
return this.httpClient.get('sets/' + id + '/test/memory/').map((data: Array<Object>) => data);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteSet(id) {
|
||||||
|
this.setHeaders();
|
||||||
|
return this.httpClient.delete('sets/' + id, { headers: this.headers, observe: 'response' })
|
||||||
|
.subscribe(data => { this.sendResponse(data); },
|
||||||
|
error => {
|
||||||
|
this.snackBar.open('Coś poszło nie tak. Spróbuj ponownie później.', null,
|
||||||
|
{ duration: 3000, verticalPosition: 'top', panelClass: ['snackbar-error'] });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sprawdzanie testu - zapytanie dla jednej fiszki
|
||||||
|
testCheck(id, body) {
|
||||||
|
// id - id zestawu fiszek
|
||||||
|
// ciało body = {id - idFiszki, content - wpisana odpowiedź, side - strona fiszki, którą widział użytkownik}
|
||||||
|
this.setHeaders();
|
||||||
|
return this.httpClient.get(`sets/${id}/${body['id']}/${body['content']}/${body['side']}/test/check/`, { headers: this.headers })
|
||||||
|
.map((data: any) => data);
|
||||||
|
}
|
||||||
|
|
||||||
|
testMemory(id, body) {
|
||||||
|
this.setHeaders();
|
||||||
|
return this.httpClient.get(`sets/${id}/test/memory/check?x=${body['x']}&y=${body['y']}`, { headers: this.headers })
|
||||||
|
.map((data: any) => data);
|
||||||
|
}
|
||||||
|
}
|
3
src/app/flashcards/flashcards/flashcards.component.css
Normal file
3
src/app/flashcards/flashcards/flashcards.component.css
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.btn{
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
4
src/app/flashcards/flashcards/flashcards.component.html
Normal file
4
src/app/flashcards/flashcards/flashcards.component.html
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<div>
|
||||||
|
<button class="btn btn-study-cave" routerLink="/flashcards/sets"><i class="fas fa-scroll"></i> FISZKI</button>
|
||||||
|
<button class="btn btn-study-cave" routerLink="/materials/list"><i class="fas fa-book-open"></i> MATERIAŁY</button>
|
||||||
|
</div>
|
25
src/app/flashcards/flashcards/flashcards.component.spec.ts
Normal file
25
src/app/flashcards/flashcards/flashcards.component.spec.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FlashcardsComponent } from './flashcards.component';
|
||||||
|
|
||||||
|
describe('FlashcardsComponent', () => {
|
||||||
|
let component: FlashcardsComponent;
|
||||||
|
let fixture: ComponentFixture<FlashcardsComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ FlashcardsComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(FlashcardsComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
15
src/app/flashcards/flashcards/flashcards.component.ts
Normal file
15
src/app/flashcards/flashcards/flashcards.component.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-flashcards',
|
||||||
|
templateUrl: './flashcards.component.html',
|
||||||
|
styleUrls: ['./flashcards.component.css']
|
||||||
|
})
|
||||||
|
export class FlashcardsComponent implements OnInit {
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
10
src/app/flashcards/set.ts
Normal file
10
src/app/flashcards/set.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
export interface Set {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
category: string;
|
||||||
|
owner: string;
|
||||||
|
add_date: string;
|
||||||
|
edit_date: string;
|
||||||
|
grade: number;
|
||||||
|
permission: string;
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
<h2>Twój wynik to {{(result/maxPts*100) | number : '1.0-2' }}%!</h2>
|
||||||
|
<h3>Poprawne odpowiedzi: {{result}}</h3>
|
||||||
|
<h3>Niepoprawne odpowiedzi: {{maxPts-result}}</h3>
|
||||||
|
<div *ngIf="timer">
|
||||||
|
<h3>Twój czas: {{minutes}} m {{seconds}} s {{milliseconds}} ms</h3>
|
||||||
|
</div>
|
@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { TestResultsComponent } from './test-results.component';
|
||||||
|
|
||||||
|
describe('TestResultsComponent', () => {
|
||||||
|
let component: TestResultsComponent;
|
||||||
|
let fixture: ComponentFixture<TestResultsComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ TestResultsComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(TestResultsComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
20
src/app/flashcards/test-results/test-results.component.ts
Normal file
20
src/app/flashcards/test-results/test-results.component.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { Component, OnInit, Input } from '@angular/core';
|
||||||
|
@Component({
|
||||||
|
selector: 'app-test-results',
|
||||||
|
templateUrl: './test-results.component.html',
|
||||||
|
styleUrls: ['./test-results.component.css']
|
||||||
|
})
|
||||||
|
export class TestResultsComponent implements OnInit {
|
||||||
|
@Input() result: number;
|
||||||
|
@Input() maxPts: number;
|
||||||
|
@Input() minutes: number;
|
||||||
|
@Input() seconds: number;
|
||||||
|
@Input() milliseconds: number;
|
||||||
|
@Input() timer: Boolean;
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
10
src/app/footer/footer.component.css
Normal file
10
src/app/footer/footer.component.css
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
.footer{
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
background-color: rgb(24, 22, 22);
|
||||||
|
padding: 1rem 0;
|
||||||
|
}
|
3
src/app/footer/footer.component.html
Normal file
3
src/app/footer/footer.component.html
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<div class="footer">
|
||||||
|
Regulamin | Polityka Cookies | © 2018 StudyCave
|
||||||
|
</div>
|
25
src/app/footer/footer.component.spec.ts
Normal file
25
src/app/footer/footer.component.spec.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FooterComponent } from './footer.component';
|
||||||
|
|
||||||
|
describe('FooterComponent', () => {
|
||||||
|
let component: FooterComponent;
|
||||||
|
let fixture: ComponentFixture<FooterComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ FooterComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(FooterComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
15
src/app/footer/footer.component.ts
Normal file
15
src/app/footer/footer.component.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-footer',
|
||||||
|
templateUrl: './footer.component.html',
|
||||||
|
styleUrls: ['./footer.component.css']
|
||||||
|
})
|
||||||
|
export class FooterComponent implements OnInit {
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
40
src/app/groups/group-creator/group-creator.component.css
Normal file
40
src/app/groups/group-creator/group-creator.component.css
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
background-color: #181616;
|
||||||
|
padding: 30px;
|
||||||
|
margin-top: 2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper-add {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-content: center;
|
||||||
|
margin-bottom: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
width: 100%;
|
||||||
|
padding: 30px;
|
||||||
|
min-height: 100%;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
background-color: #181616;
|
||||||
|
padding: 30px;
|
||||||
|
margin-top: 2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons-container > div {
|
||||||
|
margin: 10px;
|
||||||
|
}
|
35
src/app/groups/group-creator/group-creator.component.html
Normal file
35
src/app/groups/group-creator/group-creator.component.html
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<div class="wrapper">
|
||||||
|
<div class="wrapper-add">
|
||||||
|
<div class="container">
|
||||||
|
<h1>Tworzenie grupy</h1>
|
||||||
|
<br />
|
||||||
|
<form ngNativeValidate action="/" method="post" #user="ngForm" (ngSubmit)="add(user.value)">
|
||||||
|
<label>
|
||||||
|
Wprowadź nazwę dla grupy:
|
||||||
|
<input type="text" name="name" maxlength="150" class="form-control" ngModel required />
|
||||||
|
</label>
|
||||||
|
<br />
|
||||||
|
<label>
|
||||||
|
Wprowadź opis grupy:
|
||||||
|
<textarea name="description" class="form-control" ngModel required></textarea>
|
||||||
|
</label>
|
||||||
|
<br /><br />
|
||||||
|
<button #btn class="btn btn-study-cave" type="submit"><i class="fas fa-check-circle"></i> Dodaj grupę!</button>
|
||||||
|
<button class="btn btn-study-cave" routerLink="/my-groups"><i class="fas fa-arrow-left"></i> Powrót</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p-dialog header="Informacja" [(visible)]="showInfoDialog" [responsive]="true"
|
||||||
|
[minWidth]="300" [minY]="70" [draggable]="false" [closable]="false">
|
||||||
|
<p>Twoja grupa została utworzona prawidłowo.</p>
|
||||||
|
<p>Poniżej znajduje się kod dostępu poprzez który możesz dodawać członków:</p>
|
||||||
|
<!--<p><b>{{ createdGroup.key }}</b></p>-->
|
||||||
|
<p><b>{{ createdGroup.groupKey }}</b></p>
|
||||||
|
<br />
|
||||||
|
<p>Kod ten będzie dostępny także w sekcji "Zarządzaj grupą."</p>
|
||||||
|
<br />
|
||||||
|
<!-- To check later -->
|
||||||
|
<button class="btn btn-study-cave" (click)="showInfoDialog = false" [routerLink]="['/groups/manage', createdGroup.id]">Rozumiem</button>
|
||||||
|
</p-dialog>
|
49
src/app/groups/group-creator/group-creator.component.spec.ts
Normal file
49
src/app/groups/group-creator/group-creator.component.spec.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { GroupCreatorComponent } from './group-creator.component';
|
||||||
|
import { GroupsService } from '../groups.service';
|
||||||
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { BrowserAnimationsModule, NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
|
import { AuthenticationService } from '../../authentication.service';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
|
|
||||||
|
describe('GroupCreatorComponent', () => {
|
||||||
|
let component: GroupCreatorComponent;
|
||||||
|
let fixture: ComponentFixture<GroupCreatorComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [GroupCreatorComponent],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA],
|
||||||
|
providers: [GroupsService, AuthenticationService],
|
||||||
|
imports: [RouterTestingModule, FormsModule, HttpClientModule, MatSnackBarModule, NoopAnimationsModule]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(GroupCreatorComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create group', async(() => {
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.autoDetectChanges();
|
||||||
|
spyOn(component, 'add').and.callThrough();
|
||||||
|
fixture.debugElement.nativeElement.querySelectorAll('.form-control')[0].value = 'group-name';
|
||||||
|
fixture.debugElement.nativeElement.querySelectorAll('.form-control')[1].value = 'group-descripion';
|
||||||
|
fixture.debugElement.nativeElement.querySelectorAll('.btn-study-cave')[0].click();
|
||||||
|
expect(component.add).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
});
|
63
src/app/groups/group-creator/group-creator.component.ts
Normal file
63
src/app/groups/group-creator/group-creator.component.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import { Component, OnInit, OnDestroy, ElementRef, ViewChild } from '@angular/core';
|
||||||
|
import { ISubscription } from 'rxjs/Subscription';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
|
|
||||||
|
import { GroupsService } from '../groups.service';
|
||||||
|
import { Group } from '../group';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-group-creator',
|
||||||
|
templateUrl: './group-creator.component.html',
|
||||||
|
styleUrls: ['./group-creator.component.css']
|
||||||
|
})
|
||||||
|
export class GroupCreatorComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
public currentUser: string;
|
||||||
|
public postGroupsSubscription: ISubscription;
|
||||||
|
public createdGroup: Group = {};
|
||||||
|
public showInfoDialog: boolean;
|
||||||
|
|
||||||
|
@ViewChild('btn') btn: ElementRef;
|
||||||
|
|
||||||
|
constructor(private groupsService: GroupsService, private router: Router,
|
||||||
|
private snackBar: MatSnackBar) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.showInfoDialog = false;
|
||||||
|
if (localStorage.getItem('currentUser') !== null) {
|
||||||
|
this.currentUser = JSON.parse(localStorage.getItem('currentUser')).username;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
add(value: any) {
|
||||||
|
this.btn.nativeElement.disabled = true;
|
||||||
|
const toSend = {
|
||||||
|
name: value.name,
|
||||||
|
description: value.description,
|
||||||
|
owner: this.currentUser
|
||||||
|
};
|
||||||
|
this.postGroupsSubscription = this.groupsService.postGroup(toSend).subscribe(
|
||||||
|
success => {
|
||||||
|
this.createdGroup = success;
|
||||||
|
this.showInfoDialog = true;
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
this.btn.nativeElement.disabled = false;
|
||||||
|
this.snackBar.open('Wystąpił błąd serwera. Spróbuj ponownie później.', null,
|
||||||
|
{ duration: 3000, verticalPosition: 'top', panelClass: ['snackbar-error'] });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
goToManageGroup() {
|
||||||
|
this.router.navigate(['groups/manage', this.createdGroup.id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
if (this.postGroupsSubscription) {
|
||||||
|
this.postGroupsSubscription.unsubscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user