Skip to content

Commit

Permalink
Merge pull request #102 from theImmortalCoders/dev
Browse files Browse the repository at this point in the history
Release 1.4
  • Loading branch information
pablitoo1 authored Nov 7, 2024
2 parents a35f5c2 + b64faef commit ea5fbc3
Show file tree
Hide file tree
Showing 60 changed files with 1,358 additions and 416 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/angular.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ jobs:
- name: Install Cypress
run: npm install cypress --save-dev
- name: Run Karma unit tests
run: npm test -- --no-watch --no-progress --browsers=ChromeHeadless
run: npm test -- --no-watch --no-progress
- name: Run Cypress E2E tests
run: npx ng e2e --no-watch --headless
32 changes: 9 additions & 23 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,29 +1,15 @@
FROM --platform=$BUILDPLATFORM node:20.11.1-bullseye-slim as builder
FROM node:20.11-alpine AS build

RUN mkdir /project
WORKDIR /project
WORKDIR /dist/src/app

RUN npm install -g @angular/cli@18

COPY "package.json" "package-lock.json" ./
RUN npm ci
RUN npm cache clean --force

COPY . .
CMD ["ng", "serve", "--host", "0.0.0.0"]

FROM builder as dev-envs

RUN <<EOF
apt-get update
apt-get install -y --no-install-recommends git
EOF

RUN <<EOF
useradd -s /bin/bash -m vscode
groupadd docker
usermod -aG docker vscode
EOF
RUN npm install
RUN npm run build --prod

COPY "/" .
FROM nginx:latest AS ngi
COPY --from=build /dist/src/app/dist/rag-2-frontend/browser /usr/share/nginx/html
COPY /nginx.conf /etc/nginx/conf.d/default.conf

CMD ["ng", "serve", "--host", "0.0.0.0"]
EXPOSE 80
665 changes: 665 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# RAG-2 frontend

## License

This project is available under the AGPL License. See [LICENSE](./LICENSE) for more information.

The application was created as part of the work of the Human-Computer Interaction Scientific Club "GEST" at the Rzeszów University of Technology.

## Description

Application with web minigames prepared to collect game data and connect AI models to game agents via websocket.
Expand Down
16 changes: 14 additions & 2 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,24 @@
"maximumError": "4kB"
}
],
"outputHashing": "all"
"outputHashing": "all",
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
]
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
"sourceMap": true,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.ts"
}
]
}
},
"defaultConfiguration": "production"
Expand Down
20 changes: 20 additions & 0 deletions nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
server {
listen 80;
sendfile on;
default_type application/octet-stream;

gzip on;
gzip_http_version 1.1;
gzip_disable "MSIE [1-6]\.";
gzip_min_length 256;
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
gzip_comp_level 9;

root /usr/share/nginx/html;

location / {
try_files $uri $uri/ /index.html =404;
}
}
Binary file added public/images/home.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 8 additions & 2 deletions src/app/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@ import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';
import { provideHttpClient } from '@angular/common/http';
import {
HTTP_INTERCEPTORS,
provideHttpClient,
withInterceptorsFromDi,
} from '@angular/common/http';
import { JwtInterceptor } from '@utils/interceptors/jwt.interceptor';

export const appConfig: ApplicationConfig = {
providers: [
provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes),
provideHttpClient(),
provideHttpClient(withInterceptorsFromDi()),
{ provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true },
],
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,36 @@ import { TRole } from 'app/shared/models/role.enum';
import { CommonModule } from '@angular/common';
import { StatsEndpointsService } from '@endpoints/stats-endpoints.service';
import { SelectedUserInfoComponent } from './selected-user-info.component';
import { AllowedRolesDirective } from '@utils/directives/allowed-roles.directive';

@Component({
selector: 'app-admin-settings',
standalone: true,
imports: [ModalComponent, CommonModule, SelectedUserInfoComponent],
imports: [
ModalComponent,
CommonModule,
SelectedUserInfoComponent,
AllowedRolesDirective,
],
template: `
<h1
class="text-xl xs:text-2xl sm:text-4xl font-bold text-mainOrange text-center 2xs:text-start">
Administration settings
</h1>
<hr class="w-full border-[1px] sm:border-2 border-mainOrange mb-4" />
<div
class="flex flex-col xs:flex-row justify-around gap-y-2 xs:gap-y-0 space-x-0 xs:space-x-4 sm:space-x-8 w-full">
class="flex flex-col xs:flex-row justify-between gap-y-2 xs:gap-y-0 space-x-0 xs:space-x-4 sm:space-x-8 w-full">
<button
type="button"
*appAllowedRoles="allowedRolesAdmin"
(click)="banUnbanUserModal()"
class="dashboard-button group">
<span>Ban/unban some user</span>
<i data-feather="slash" class="dashboard-icon"></i>
</button>
<button
type="button"
*appAllowedRoles="allowedRolesAdmin"
(click)="changeUserRoleModal()"
class="dashboard-button group">
<span>Change role of some user</span>
Expand Down Expand Up @@ -113,7 +121,6 @@ import { SelectedUserInfoComponent } from './selected-user-info.component';
<option value="Student">Student</option>
<option value="Teacher">Teacher</option>
<option value="Admin">Admin</option>
<option value="Special">Special</option>
</select>
</div>
} @else if (
Expand Down Expand Up @@ -153,17 +160,18 @@ export class AdminSettingsComponent implements OnDestroy {
private _statsEndpointsService = inject(StatsEndpointsService);
private _notificationService = inject(NotificationService);

private _getUsersSubscription: Subscription | null = null;
private _getUserStatsSubscription: Subscription | null = null;
private _changeBanStatusSubscription: Subscription | null = null;
private _changeRoleSubscription: Subscription | null = null;
private _getUsersSubscription = new Subscription();
private _getUserStatsSubscription = new Subscription();
private _changeBanStatusSubscription = new Subscription();
private _changeRoleSubscription = new Subscription();

public usersList: IUserResponse[] | null = null;
public selectedUserData: IUserResponse | null = null;
public selectedUserStats: IUserStatsResponse | null = null;
public isBanned = false;
public newUserRole: TRole = TRole.Student;
public errorMessage: string | null = null;
public allowedRolesAdmin: TRole[] = [TRole.Admin];

public modalVisibility:
| 'banUnbanUser'
Expand Down Expand Up @@ -311,17 +319,9 @@ export class AdminSettingsComponent implements OnDestroy {
}

public ngOnDestroy(): void {
if (this._getUsersSubscription) {
this._getUsersSubscription.unsubscribe();
}
if (this._changeBanStatusSubscription) {
this._changeBanStatusSubscription.unsubscribe();
}
if (this._changeRoleSubscription) {
this._changeRoleSubscription.unsubscribe();
}
if (this._getUserStatsSubscription) {
this._getUserStatsSubscription.unsubscribe();
}
this._getUsersSubscription.unsubscribe();
this._changeBanStatusSubscription.unsubscribe();
this._changeRoleSubscription.unsubscribe();
this._getUserStatsSubscription.unsubscribe();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { GameHandlingOptionsComponent } from './game-handling-options.component'
import { GameEndpointsService } from '@endpoints/game-endpoints.service';
import { NotificationService } from 'app/shared/services/notification.service';
import { ReactiveFormsModule } from '@angular/forms';
import { of, throwError } from 'rxjs';
import { of } from 'rxjs';
import { IGameResponse } from 'app/shared/models/game.models';
import { HttpClientTestingModule } from '@angular/common/http/testing';

Expand Down Expand Up @@ -94,17 +94,6 @@ describe('GameHandlingOptionsComponent', () => {
expect(component.errorMessage).toBeNull();
}));

it('should handle error when adding a new game', fakeAsync(() => {
component.modalVisibility = 'addNewGame';
component.gameHandlingForm.controls.newGameName.setValue('New Game');

mockGameEndpointsService.addGame.and.returnValue(
throwError(() => new Error('Error adding game'))
);
component.addNewGameFunction();
tick();
}));

it('should edit an existing game and show notification', fakeAsync(() => {
component.modalVisibility = 'editGame';
component.selectedGameId = 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,10 @@ export class GameHandlingOptionsComponent implements OnDestroy {
private _notificationService = inject(NotificationService);
private _formBuilder = inject(NonNullableFormBuilder);

private _getGamesSubscription: Subscription | null = null;
private _addGameSubscription: Subscription | null = null;
private _editGameSubscription: Subscription | null = null;
private _removeGameSubscription: Subscription | null = null;
private _getGamesSubscription = new Subscription();
private _addGameSubscription = new Subscription();
private _editGameSubscription = new Subscription();
private _removeGameSubscription = new Subscription();

public selectedGameId = 0;

Expand Down Expand Up @@ -266,17 +266,9 @@ export class GameHandlingOptionsComponent implements OnDestroy {
}

public ngOnDestroy(): void {
if (this._getGamesSubscription) {
this._getGamesSubscription.unsubscribe();
}
if (this._addGameSubscription) {
this._addGameSubscription.unsubscribe();
}
if (this._editGameSubscription) {
this._editGameSubscription.unsubscribe();
}
if (this._removeGameSubscription) {
this._removeGameSubscription.unsubscribe();
}
this._getGamesSubscription.unsubscribe();
this._addGameSubscription.unsubscribe();
this._editGameSubscription.unsubscribe();
this._removeGameSubscription.unsubscribe();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { RecordedGamesComponent } from './recorded-games.component';
import { GameEndpointsService } from '@endpoints/game-endpoints.service';
import { GameRecordEndpointsService } from '@endpoints/game-record-endpoints.service';
import { NotificationService } from 'app/shared/services/notification.service';
import { of, throwError } from 'rxjs';
import { of } from 'rxjs';
import { IGameResponse } from 'app/shared/models/game.models';
import { IRecordedGameResponse } from 'app/shared/models/recorded-game.models';
import { HttpClientTestingModule } from '@angular/common/http/testing';
Expand Down Expand Up @@ -52,16 +52,6 @@ describe('RecordedGamesComponent', () => {
component = fixture.componentInstance;
});

it('should handle error when fetching available games', fakeAsync(() => {
const errorMsg = 'Failed to fetch games';
mockGameEndpointsService.getGames.and.returnValue(
throwError(() => new Error(errorMsg))
);

component.ngOnInit();
tick();
}));

it('should get recorded games when available games are fetched', fakeAsync(() => {
const mockGames: IGameResponse[] = [{ id: 1, name: 'Game 1' }];
const mockRecordedGames: IRecordedGameResponse[] = [
Expand All @@ -87,18 +77,6 @@ describe('RecordedGamesComponent', () => {
expect(component.errorMessage).toBeNull();
}));

it('should handle error when getting recorded games', fakeAsync(() => {
const mockGames: IGameResponse[] = [{ id: 1, name: 'Game 1' }];
const errorMsg = 'Failed to fetch recorded games';
mockGameEndpointsService.getGames.and.returnValue(of(mockGames));
mockGameRecordEndpointsService.getAllRecordedGames.and.returnValue(
throwError(() => new Error(errorMsg))
);

component.ngOnInit();
tick();
}));

it('should download game record and notify on success', fakeAsync(() => {
// eslint-disable-next-line @typescript-eslint/no-empty-function
mockNotificationService.addNotification.and.callFake(() => {});
Expand All @@ -112,16 +90,6 @@ describe('RecordedGamesComponent', () => {
expect(component.errorMessage).toBeNull();
}));

it('should handle error when downloading game record', fakeAsync(() => {
const errorMsg = 'Failed to download game record';
mockGameRecordEndpointsService.downloadSpecificRecordedGame.and.returnValue(
throwError(() => new Error(errorMsg))
);

component.downloadGameRecord(1);
tick();
}));

it('should delete game record and notify on success', fakeAsync(() => {
// eslint-disable-next-line @typescript-eslint/no-empty-function
mockNotificationService.addNotification.and.callFake(() => {});
Expand All @@ -133,16 +101,6 @@ describe('RecordedGamesComponent', () => {
expect(component.errorMessage).toBeNull();
}));

it('should handle error when deleting game record', fakeAsync(() => {
const errorMsg = 'Failed to delete game record';
mockGameRecordEndpointsService.deleteGameRecording.and.returnValue(
throwError(() => new Error(errorMsg))
);

component.deleteGameRecord(1);
tick();
}));

afterEach(() => {
fixture.destroy();
});
Expand Down
Loading

0 comments on commit ea5fbc3

Please sign in to comment.