Skip to content
This repository has been archived by the owner on Apr 16, 2024. It is now read-only.

Commit

Permalink
Merge branch 'develop' into feature/611-Profile-Image-Resizing
Browse files Browse the repository at this point in the history
  • Loading branch information
PatrickSkowronek authored Apr 23, 2018
2 parents 1c540e2 + 623face commit 0d38c4b
Show file tree
Hide file tree
Showing 28 changed files with 219 additions and 31 deletions.
2 changes: 1 addition & 1 deletion .travis/apidoc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ if [[ "$TRAVIS_BRANCH" == "master" ]] || [[ -n "$TRAVIS_TAG" ]]; then
git commit -m "Travis build: $TRAVIS_BUILD_NUMBER" &>/dev/null

if [[ -n "$TRAVIS_TAG" ]]; then
echo "+ git tag" ; git tag $TRAVIS_TAG
echo "+ git tag" ; git tag -a $TRAVIS_TAG -m "Release $TRAVIS_TAG"
else
echo -e "${YELLOW}+ skipping: git tag - not tagged build${NC}"
fi
Expand Down
Empty file added CHANGELOG.md
Empty file.
19 changes: 14 additions & 5 deletions api/src/controllers/UnitController.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import {
Body, Get, Put, Delete, Param, JsonController, UseBefore, NotFoundError, BadRequestError, Post,
Authorized
Authorized, CurrentUser
} from 'routing-controllers';
import passportJwtMiddleware from '../security/passportJwtMiddleware';

import {Lecture} from '../models/Lecture';
import {IUnitModel, Unit} from '../models/units/Unit';
import {ValidationError} from 'mongoose';
import {IUser} from '../../../shared/models/IUser';

@JsonController('/units')
@UseBefore(passportJwtMiddleware)
Expand All @@ -30,14 +31,19 @@ export class UnitController {
* "description": "...",
* "markdown": "# What is Lorem Ipsum?\n**Lorem Ipsum** is simply dummy text of the printing and typesetting industry.",
* "_course": "5a037e6b60f72236d8e7c83b",
* "unitCreator": "5a037e6b60f72236d8e7c834",
* "type": "free-text",
* "__v": 0
* }
*/
@Get('/:id')
getUnit(@Param('id') id: string) {
return Unit.findById(id)
.then((u) => u.toObject());
async getUnit(@Param('id') id: string) {
const unit = await Unit.findById(id);

if (unit) {
throw new NotFoundError();
}
return unit;
}

/**
Expand All @@ -62,6 +68,7 @@ export class UnitController {
* "markdown": "# What is Lorem Ipsum?\n**Lorem Ipsum** is simply dummy text of the printing and typesetting industry.",
* "_course": "5a037e6b60f72236d8e7c83b",
* "type": "free-text",
* "unitCreator": "5a037e6b60f72236d8e7c834",
* "__v": 0
* }
*
Expand All @@ -74,9 +81,11 @@ export class UnitController {
*/
@Authorized(['teacher', 'admin'])
@Post('/')
addUnit(@Body() data: any) {
addUnit(@Body() data: any, @CurrentUser() currentUser: IUser) {
// discard invalid requests
this.checkPostParam(data);
// Set current user as creator, old unit's dont have a creator
data.model.unitCreator = currentUser._id.toString();

return Unit.create(data.model)
.then((createdUnit) => {
Expand Down
2 changes: 1 addition & 1 deletion api/src/models/Course.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ courseSchema.methods.checkPrivileges = function (user: IUser) {
const userIsCourseTeacher: boolean = this.teachers.some((teacher: IUserModel) => user._id === extractId(teacher)._id);
const userIsCourseStudent: boolean = this.students.some((student: IUserModel) => user._id === extractId(student)._id);

const userCanEditCourse: boolean = roleCanEditCourse && (userIsCourseAdmin || userIsCourseTeacher);
const userCanEditCourse: boolean = roleCanEditCourse && (userIsAdmin || userIsCourseAdmin || userIsCourseTeacher);
const userIsParticipant: boolean = userIsCourseStudent || userCanEditCourse;
const userCanViewCourse: boolean = (this.active && userIsCourseStudent) || userCanEditCourse || userIsAdmin;

Expand Down
3 changes: 3 additions & 0 deletions api/src/models/units/Unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ const unitSchema = new mongoose.Schema({
},
type: {
type: String
},
unitCreator: {
type: String
}
},
{
Expand Down
1 change: 1 addition & 0 deletions api/test/integration/unit/codeKataUnit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ describe(`CodeKataUnit ${BASE_URL}`, () => {
res.status.should.be.equal(200);
res.body.name.should.equal(model.name);
res.body.description.should.equal(model.description);
res.body.unitCreator.should.equal(courseAdmin._id.toString());
});

it('should update a codeKata', async () => {
Expand Down
1 change: 1 addition & 0 deletions app/webFrontend/src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

<button mat-icon-button [matMenuTriggerFor]="langMenu">
<mat-icon>language</mat-icon>
<span>{{translate.currentLang | uppercase}}</span>
</button>
<mat-menu #langMenu="matMenu">
<button mat-menu-item (click)="changeLanguage('de')">
Expand Down
4 changes: 2 additions & 2 deletions app/webFrontend/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export class AppComponent implements OnInit {
private ravenErrorHandler: RavenErrorHandler,
private snackBar: MatSnackBar,
private themeService: ThemeService,
private translate: TranslateService) {
public translate: TranslateService) {
translate.setDefaultLang('en');

showProgress.toggleSidenav$.subscribe(
Expand All @@ -56,7 +56,7 @@ export class AppComponent implements OnInit {
});
}

changeLanguage(lang) {
changeLanguage(lang: string) {
localStorage.setItem('lang', lang);
this.translate.use(lang);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ export class DownloadCourseDialogComponent implements OnInit {
onChange() {
if (this.chkbox) {
this.childLectures.forEach(lecture => {
if (lecture.chkbox === false) {

lecture.chkbox = true;
lecture.onChange();
}

});
} else {
this.childLectures.forEach(lecture => lecture.chkbox = false);
Expand All @@ -54,15 +54,20 @@ export class DownloadCourseDialogComponent implements OnInit {
}

onChildEvent() {
let childChecked = false;
const childChecked: boolean[] = new Array();

this.childLectures.forEach(lec => {
if (lec.chkbox === true) {
childChecked = true;
this.chkbox = true;
if (lec.chkbox === true && !lec.childUnits.find(unit => unit.chkbox === false)) {
childChecked.push(true);
} else {
childChecked.push(false);
}
});
if (!childChecked) {

if (childChecked.find(bol => bol === false) !== undefined) {
this.chkbox = false;
} else {
this.chkbox = true;
}
}

Expand All @@ -87,6 +92,7 @@ export class DownloadCourseDialogComponent implements OnInit {
const obj = await this.buildObject();
if (obj.lectures.length === 0) {
this.snackBar.open('No units selected!', 'Dismiss', {duration: 3000});
this.disableDownloadButton = false;
return;
}
const downloadObj = <IDownload> obj;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,7 @@
<div class="opacity" *ngIf="isInSelectedMembers(user)"></div>

<div class="card-btn-wrapper" *ngIf="isInSelectedMembers(user)">
<button mat-raised-button routerLink="/profile/{{user._id}}" routerLinkActive="active"
[ngClass]="selectedMembers.length > 1 ? 'centered':''">
DETAILS
</button>
<button mat-raised-button (click)="openUserProfileDialog(user)" >DETAILS</button>
<button mat-raised-button (click)="openWriteMailDialog()" *ngIf="selectedMembers.length <= 1">SEND MAIL</button>
<button mat-raised-button color="warn" (click)="removeSelectedUsers()" *ngIf="selectedMembers.length <= 1">
REMOVE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {DialogService} from '../../../../shared/services/dialog.service';
import {MatSnackBar} from '@angular/material';
import {CourseService, NotificationService} from '../../../../shared/services/data.service';
import {ICourse} from '../../../../../../../../shared/models/ICourse';
import {User} from '../../../../models/User';

@Component({
selector: 'app-course-user-list-overview',
Expand Down Expand Up @@ -89,6 +90,12 @@ export class CourseUserListOverviewComponent implements OnInit {
}
}

async openUserProfileDialog(user: User) {
this.toggleBlocked = true;
await this.dialogService.userProfile(user).toPromise();
this.toggleBlocked = false;
}

toggleAllUsers() {
if (this.selectedAll) {
this.resetSelectedUsers();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,14 +183,14 @@ export class GeneralTabComponent implements OnInit {
if (!res) {
return;
}
await this.courseService.deleteItem(this.courseOb);
await this.router.navigate(['/']);
this.notificationService.createItem({
await this.notificationService.createItem({
changedCourse: this.courseOb,
changedLecture: null,
changedUnit: null,
text: 'Course ' + this.courseOb.name + ' has been deleted.'
});
await this.courseService.deleteItem(this.courseOb);
this.router.navigate(['/']);
});
}
}
1 change: 1 addition & 0 deletions app/webFrontend/src/app/models/units/CodeKataUnit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export class CodeKataUnit implements ICodeKataUnit {
code: string;
test: string;
deadline: string;
unitCreator: any;

constructor(_course: ICourse) {
this._course = _course;
Expand Down
1 change: 1 addition & 0 deletions app/webFrontend/src/app/models/units/FileUnit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export class FileUnit implements IFileUnit {
weight: number;
updatedAt: string;
createdAt: string;
unitCreator: any;

files: IFile[] = [];
fileUnitType: string;
Expand Down
1 change: 1 addition & 0 deletions app/webFrontend/src/app/models/units/FreeTextUnit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export class FreeTextUnit implements IFreeTextUnit {
__t: string;
progressable: boolean;
weight: number;
unitCreator: any;

markdown: string;

Expand Down
1 change: 1 addition & 0 deletions app/webFrontend/src/app/models/units/TaskUnit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export class TaskUnit implements ITaskUnit {
__t: string;
progressable: boolean;
weight: number;
unitCreator: any;

tasks: ITask[] = [];
deadline: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<div class="user-profile-dialog-wrapper">
<div class="profile" *ngIf="user">
<span class="user-icon" user-image [user-image]="user" [size]="50"></span>
<h2 class="name">
<span>{{user.profile.firstName}} {{user.profile.lastName}}</span>
</h2>
<div class="user-data">
<div><strong>E-Mail: </strong><a href="mailto:{{user.email}}">{{user.email}}</a></div>
<div *ngIf="canSeeUid()">
<strong>Matrikelnummer: </strong>{{user.uid}}
</div>
</div>
</div>
<button mat-raised-button color="primary" (click)="dialogRef.close(true)">CLOSE</button>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
.user-profile-dialog-wrapper{
text-align: center;
}

.profile {

.user-icon {
display: block;
width: 7rem;
height: 7rem;
background-size: cover;
margin: auto;
}

.name {
margin-top: 1rem;
margin-bottom: 1.5rem;
}

.user-data {
text-align: left;
margin-bottom: 1.5rem;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing';

import {UserProfileDialog} from './user-profile-dialog.component';

describe('UserProfileDialog', () => {
let component: UserProfileDialog;
let fixture: ComponentFixture<UserProfileDialog>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [UserProfileDialog]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(UserProfileDialog);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {Component, Input} from '@angular/core';
import {MatDialogRef} from '@angular/material';
import {User} from '../../../models/User';
import {UserService} from '../../services/user.service';

@Component({
selector: 'app-user-profile-dialog',
templateUrl: './user-profile-dialog.component.html',
styleUrls: ['./user-profile-dialog.component.scss']
})
export class UserProfileDialog {

@Input() user: User;

constructor(public dialogRef: MatDialogRef<UserProfileDialog>,
public userService: UserService) {
}

canSeeUid() {
return (this.userService.isAdmin() || this.userService.isTeacher()) && this.user.uid;
}
}
11 changes: 11 additions & 0 deletions app/webFrontend/src/app/shared/services/dialog.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {InfoDialog} from '../components/info-dialog/info-dialog.component';
import {FilepickerDialog} from '../components/filepicker-dialog/filepicker-dialog.component';
import {WriteMailDialog} from '../components/write-mail-dialog/write-mail-dialog.component';
import {ChangePasswordDialogComponent} from '../components/change-password-dialog/change-password-dialog.component';
import {UserProfileDialog} from '../components/user-profile-dialog/user-profile-dialog.component';
import {User} from '../../models/User';

@Injectable()
export class DialogService {
Expand All @@ -25,6 +27,15 @@ export class DialogService {
return dialogRef.afterClosed();
}

public userProfile(user: User): Observable<boolean> {
let dialogRef: MatDialogRef<UserProfileDialog>;

dialogRef = this.dialog.open(UserProfileDialog);
dialogRef.componentInstance.user = user;

return dialogRef.afterClosed();
}

public confirm(title: string, message: string, confirmText: string = 'Confirm'): Observable<boolean> {
let dialogRef: MatDialogRef<ConfirmDialog>;

Expand Down
4 changes: 4 additions & 0 deletions app/webFrontend/src/app/shared/shared.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {MarkdownEditorComponent} from './components/markdown-editor/markdown-edi
import {AceEditorModule} from 'ng2-ace-editor';
import {PickMediaDialog} from './components/pick-media-dialog/pick-media-dialog.component';
import {TranslateModule} from '@ngx-translate/core';
import {UserProfileDialog} from 'app/shared/components/user-profile-dialog/user-profile-dialog.component';

@NgModule({
imports: [
Expand Down Expand Up @@ -50,6 +51,7 @@ import {TranslateModule} from '@ngx-translate/core';
ChangePasswordDialogComponent,
MarkdownEditorComponent,
PickMediaDialog,
UserProfileDialog,
],
exports: [
GravatarDirective,
Expand All @@ -70,10 +72,12 @@ import {TranslateModule} from '@ngx-translate/core';
ChangePasswordDialogComponent,
PickMediaDialog,
TranslateModule,
UserProfileDialog,
],
entryComponents: [
UploadFormDialog,
PickMediaDialog,
UserProfileDialog,
],
})
export class SharedModule {
Expand Down
Loading

0 comments on commit 0d38c4b

Please sign in to comment.