├── frontend ├── src │ ├── assets │ │ ├── .gitkeep │ │ ├── book.jpg │ │ ├── logo.png │ │ ├── favicon.png │ │ ├── background.jpg │ │ ├── GitHub-Mark.png │ │ ├── background_image.jpg │ │ └── twitter_header_photo_2.png │ ├── app │ │ ├── alert │ │ │ ├── alert.component.css │ │ │ ├── alert.component.html │ │ │ ├── alert.component.spec.ts │ │ │ └── alert.component.ts │ │ ├── external │ │ │ ├── external.component.css │ │ │ ├── external.component.html │ │ │ ├── external-create-pending │ │ │ │ ├── external-create-pending.component.css │ │ │ │ └── external-create-pending.component.spec.ts │ │ │ ├── external-thesis │ │ │ │ ├── external-thesis.component.css │ │ │ │ └── external-thesis.component.spec.ts │ │ │ ├── external-thesis-edit │ │ │ │ ├── external-thesis-edit.component.css │ │ │ │ └── external-thesis-edit.component.spec.ts │ │ │ ├── external.component.ts │ │ │ └── external.component.spec.ts │ │ ├── footer │ │ │ ├── footer.component.css │ │ │ ├── footer.component.ts │ │ │ ├── footer.component.html │ │ │ └── footer.component.spec.ts │ │ ├── student │ │ │ ├── student.component.css │ │ │ ├── student-thesis │ │ │ │ ├── student-thesis.component.css │ │ │ │ └── student-thesis.component.spec.ts │ │ │ ├── student.component.html │ │ │ ├── student-requests │ │ │ │ ├── student-requests.component.css │ │ │ │ └── student-requests.component.spec.ts │ │ │ ├── student-create-pending │ │ │ │ ├── student-create-pending.component.css │ │ │ │ ├── student-create-pending.component.spec.ts │ │ │ │ └── student-create-pending.component.ts │ │ │ ├── student-pending │ │ │ │ ├── student-pending.component.css │ │ │ │ └── student-pending.component.spec.ts │ │ │ ├── student.component.ts │ │ │ ├── student.component.spec.ts │ │ │ └── student-assigned │ │ │ │ ├── student-assigned.component.spec.ts │ │ │ │ └── student-assigned.component.css │ │ ├── professor │ │ │ ├── professor.component.css │ │ │ ├── professor-supervise │ │ │ │ ├── professor-supervise.component.css │ │ │ │ ├── professor-supervise.component.spec.ts │ │ │ │ ├── professor-supervise.component.ts │ │ │ │ └── professor-supervise.component.html │ │ │ ├── professor.component.html │ │ │ ├── professor-requests │ │ │ │ ├── professor-requests.component.css │ │ │ │ └── professor-requests.component.spec.ts │ │ │ ├── professor-supervisor-thesis │ │ │ │ ├── professor-supervisor-thesis.component.css │ │ │ │ ├── professor-supervisor-thesis.component.spec.ts │ │ │ │ └── professor-supervisor-thesis.component.html │ │ │ ├── professor-thesis-edit │ │ │ │ ├── professor-thesis-edit.component.css │ │ │ │ ├── professor-thesis-edit.component.spec.ts │ │ │ │ ├── professor-thesis-edit.component.html │ │ │ │ └── professor-thesis-edit.component.ts │ │ │ ├── professor.component.ts │ │ │ ├── professor-pending │ │ │ │ ├── professor-pending.component.css │ │ │ │ └── professor-pending.component.spec.ts │ │ │ ├── professor-thesis │ │ │ │ ├── professor-thesis.component.css │ │ │ │ ├── professor-thesis.component.spec.ts │ │ │ │ └── professor-thesis.component.ts │ │ │ ├── professor-assigned │ │ │ │ ├── professor-assigned.component.css │ │ │ │ └── professor-assigned.component.spec.ts │ │ │ └── professor.component.spec.ts │ │ ├── secretariat │ │ │ ├── secretariat.component.css │ │ │ ├── secretariat.component.html │ │ │ ├── secretariat-professors │ │ │ │ ├── secretariat-professors.component.css │ │ │ │ ├── secretariat-professors.component.spec.ts │ │ │ │ ├── secretariat-professors.component.ts │ │ │ │ └── secretariat-professors.component.html │ │ │ ├── secretariat.component.ts │ │ │ ├── secretariat-students │ │ │ │ ├── secretariat-students.component.css │ │ │ │ └── secretariat-students.component.spec.ts │ │ │ └── secretariat.component.spec.ts │ │ ├── home │ │ │ ├── search-results │ │ │ │ ├── search-results.component.css │ │ │ │ ├── search-results.component.spec.ts │ │ │ │ └── search-results.component.html │ │ │ ├── home.component.css │ │ │ ├── home.component.spec.ts │ │ │ └── home.component.html │ │ ├── admin │ │ │ ├── admin-user │ │ │ │ ├── create-user │ │ │ │ │ ├── create-user.component.css │ │ │ │ │ ├── create-user.component.html │ │ │ │ │ ├── create-user.component.ts │ │ │ │ │ └── create-user.component.spec.ts │ │ │ │ ├── admin-user.component.css │ │ │ │ ├── admin-user.component.spec.ts │ │ │ │ └── admin-user.component.html │ │ │ ├── admin.component.html │ │ │ ├── create-university │ │ │ │ ├── create-university.component.css │ │ │ │ ├── create-university.component.spec.ts │ │ │ │ ├── create-university.component.html │ │ │ │ └── create-university.component.ts │ │ │ ├── admin-activate-externals │ │ │ │ ├── admin-activate-externals.component.css │ │ │ │ ├── admin-activate-externals.component.spec.ts │ │ │ │ ├── admin-activate-externals.component.ts │ │ │ │ └── admin-activate-externals.component.html │ │ │ ├── admin-university │ │ │ │ ├── admin-university.component.css │ │ │ │ ├── admin-university.component.spec.ts │ │ │ │ ├── admin-university.component.html │ │ │ │ └── admin-university.component.ts │ │ │ ├── admin-external │ │ │ │ ├── admin-external.component.css │ │ │ │ └── admin-external.component.spec.ts │ │ │ ├── admin.component.css │ │ │ ├── admin.component.spec.ts │ │ │ └── admin.component.ts │ │ ├── thesis │ │ │ ├── thesis-professor │ │ │ │ ├── thesis-professor.component.css │ │ │ │ ├── thesis-professor.component.spec.ts │ │ │ │ ├── thesis-professor.component.ts │ │ │ │ └── thesis-professor.component.html │ │ │ ├── thesis-create │ │ │ │ ├── thesis-create.component.css │ │ │ │ ├── thesis-create.component.spec.ts │ │ │ │ └── thesis-create.component.ts │ │ │ └── thesis-details │ │ │ │ ├── thesis-details.component.css │ │ │ │ └── thesis-details.component.spec.ts │ │ ├── profile │ │ │ ├── profile.component.css │ │ │ ├── profile.component.spec.ts │ │ │ ├── profile.component.ts │ │ │ └── profile.component.html │ │ ├── login │ │ │ ├── login-ldap │ │ │ │ ├── login-ldap.component.css │ │ │ │ ├── login-ldap.component.spec.ts │ │ │ │ └── login-ldap.component.html │ │ │ ├── login-external │ │ │ │ ├── login-external.component.css │ │ │ │ ├── login-external.component.spec.ts │ │ │ │ ├── login-external.component.html │ │ │ │ └── login-external.component.ts │ │ │ ├── login.component.css │ │ │ ├── login.component.html │ │ │ ├── login.component.spec.ts │ │ │ └── login.component.ts │ │ ├── register-external │ │ │ ├── register-external.component.css │ │ │ ├── register-external.component.spec.ts │ │ │ └── register-external.component.ts │ │ ├── completed-thesis-repository │ │ │ ├── completed-thesis-repository.component.css │ │ │ └── completed-thesis-repository.component.spec.ts │ │ ├── shared │ │ │ ├── models │ │ │ │ ├── thesis.model.ts │ │ │ │ ├── request.model.ts │ │ │ │ ├── user.model.ts │ │ │ │ └── external.model.ts │ │ │ ├── guards │ │ │ │ ├── auth.guard.ts │ │ │ │ ├── login.guard.ts │ │ │ │ ├── secretariat.guard.ts │ │ │ │ ├── external.guard.ts │ │ │ │ ├── student.guard.ts │ │ │ │ ├── professor.guard.ts │ │ │ │ └── admin.guard.ts │ │ │ ├── interceptors │ │ │ │ ├── jwt.interceptor.ts │ │ │ │ └── http-error.interceptor.ts │ │ │ └── services │ │ │ │ ├── user.service.ts │ │ │ │ ├── alert.service.ts │ │ │ │ ├── external.service.ts │ │ │ │ ├── shared.service.ts │ │ │ │ ├── secretariat.service.ts │ │ │ │ └── admin.service.ts │ │ ├── app.component.html │ │ ├── header │ │ │ ├── header.component.css │ │ │ ├── header.component.spec.ts │ │ │ ├── header.component.ts │ │ │ └── header.component.html │ │ ├── app.component.css │ │ ├── sidenav │ │ │ ├── sidenav.component.css │ │ │ ├── sidenav.component.spec.ts │ │ │ └── sidenav.component.ts │ │ ├── app.component.ts │ │ └── app.component.spec.ts │ ├── typings.d.ts │ ├── favicon.ico │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── main.ts │ ├── styles.css │ ├── test.ts │ └── index.html ├── e2e │ ├── tsconfig.json │ ├── src │ │ ├── app.po.ts │ │ └── app.e2e-spec.ts │ └── protractor.conf.js ├── tsconfig.app.json ├── .editorconfig ├── tsconfig.spec.json ├── browserslist ├── Dockerfile ├── tsconfig.json ├── .gitignore ├── README.md ├── karma.conf.js ├── webpack.config.ts ├── package.json └── tslint.json ├── backend ├── android ├── .gitignore ├── server.js ├── models │ ├── university.js │ ├── draft.js │ ├── time_period.js │ ├── file_thesis.js │ ├── completed_thesis.js │ ├── pending.js │ ├── external.js │ ├── request.js │ ├── user.js │ ├── notification.js │ ├── supervision_requests.js │ ├── thesis.js │ └── assigned_thesis.js ├── Dockerfile ├── middleware │ ├── check-auth.js │ └── send-auth.js ├── cors.js ├── routes │ ├── university.js │ ├── secretariat.js │ ├── thesis.js │ ├── external.js │ ├── ldap_login.js │ └── admin.js ├── package.json ├── controllers │ └── university.js └── meta │ └── COMPANY_SP_metadata_localhost.xml ├── images ├── Screenshot_1.png ├── Screenshot_2.png ├── Screenshot_3.png ├── Screenshot_4.png └── Screenshot_5.png ├── .vscode └── launch.json ├── docker-compose.yml └── LICENSE /frontend/src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/android: -------------------------------------------------------------------------------- 1 | [object Object] -------------------------------------------------------------------------------- /frontend/src/app/alert/alert.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | -------------------------------------------------------------------------------- /frontend/src/app/external/external.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/app/footer/footer.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/app/student/student.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/app/professor/professor.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/app/secretariat/secretariat.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/typings.d.ts: -------------------------------------------------------------------------------- 1 | declare var config: any; 2 | -------------------------------------------------------------------------------- /frontend/src/app/home/search-results/search-results.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/app/student/student-thesis/student-thesis.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/app/admin/admin-user/create-user/create-user.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/app/thesis/thesis-professor/thesis-professor.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/app/admin/admin.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/app/external/external.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/app/professor/professor-supervise/professor-supervise.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/app/profile/profile.component.css: -------------------------------------------------------------------------------- 1 | dl { 2 | font-size:16px; 3 | } -------------------------------------------------------------------------------- /frontend/src/app/student/student.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /frontend/src/app/professor/professor.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /frontend/src/app/secretariat/secretariat.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eellak/gsoc2019-tms/HEAD/frontend/src/favicon.ico -------------------------------------------------------------------------------- /images/Screenshot_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eellak/gsoc2019-tms/HEAD/images/Screenshot_1.png -------------------------------------------------------------------------------- /images/Screenshot_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eellak/gsoc2019-tms/HEAD/images/Screenshot_2.png -------------------------------------------------------------------------------- /images/Screenshot_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eellak/gsoc2019-tms/HEAD/images/Screenshot_3.png -------------------------------------------------------------------------------- /images/Screenshot_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eellak/gsoc2019-tms/HEAD/images/Screenshot_4.png -------------------------------------------------------------------------------- /images/Screenshot_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eellak/gsoc2019-tms/HEAD/images/Screenshot_5.png -------------------------------------------------------------------------------- /frontend/src/app/professor/professor-requests/professor-requests.component.css: -------------------------------------------------------------------------------- 1 | p { font-size:16px} 2 | 3 | -------------------------------------------------------------------------------- /frontend/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /frontend/src/assets/book.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eellak/gsoc2019-tms/HEAD/frontend/src/assets/book.jpg -------------------------------------------------------------------------------- /frontend/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eellak/gsoc2019-tms/HEAD/frontend/src/assets/logo.png -------------------------------------------------------------------------------- /frontend/src/app/admin/admin-user/create-user/create-user.component.html: -------------------------------------------------------------------------------- 1 |

2 | create-user works! 3 |

4 | -------------------------------------------------------------------------------- /frontend/src/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eellak/gsoc2019-tms/HEAD/frontend/src/assets/favicon.png -------------------------------------------------------------------------------- /frontend/src/assets/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eellak/gsoc2019-tms/HEAD/frontend/src/assets/background.jpg -------------------------------------------------------------------------------- /frontend/src/assets/GitHub-Mark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eellak/gsoc2019-tms/HEAD/frontend/src/assets/GitHub-Mark.png -------------------------------------------------------------------------------- /frontend/src/app/professor/professor-supervisor-thesis/professor-supervisor-thesis.component.css: -------------------------------------------------------------------------------- 1 | p { 2 | font-size:16px; 3 | } -------------------------------------------------------------------------------- /frontend/src/assets/background_image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eellak/gsoc2019-tms/HEAD/frontend/src/assets/background_image.jpg -------------------------------------------------------------------------------- /frontend/src/app/login/login-ldap/login-ldap.component.css: -------------------------------------------------------------------------------- 1 | @media (min-width: 1340px){ 2 | form { 3 | margin-left: 12px; 4 | } 5 | } -------------------------------------------------------------------------------- /frontend/src/assets/twitter_header_photo_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eellak/gsoc2019-tms/HEAD/frontend/src/assets/twitter_header_photo_2.png -------------------------------------------------------------------------------- /frontend/src/app/login/login-external/login-external.component.css: -------------------------------------------------------------------------------- 1 | @media (min-width: 1340px){ 2 | form { 3 | margin-left: 12px; 4 | } 5 | } -------------------------------------------------------------------------------- /frontend/src/app/register-external/register-external.component.css: -------------------------------------------------------------------------------- 1 | @media (min-width: 1340px){ 2 | form { 3 | margin-left: 12px; 4 | } 5 | } -------------------------------------------------------------------------------- /frontend/src/app/thesis/thesis-create/thesis-create.component.css: -------------------------------------------------------------------------------- 1 | .btn-default { 2 | float:right 3 | } 4 | 5 | 6 | 7 | p { 8 | font-size:16px; 9 | } -------------------------------------------------------------------------------- /frontend/src/app/student/student-requests/student-requests.component.css: -------------------------------------------------------------------------------- 1 | .accepted { 2 | color:rgb(8, 105, 8) 3 | } 4 | 5 | .not_accepted { 6 | color:red 7 | } -------------------------------------------------------------------------------- /frontend/src/app/admin/create-university/create-university.component.css: -------------------------------------------------------------------------------- 1 | .btn-default { 2 | float:right 3 | } 4 | 5 | 6 | 7 | 8 | p { 9 | font-size:16px; 10 | } -------------------------------------------------------------------------------- /frontend/src/app/student/student-create-pending/student-create-pending.component.css: -------------------------------------------------------------------------------- 1 | .btn-default { 2 | float:right 3 | } 4 | 5 | 6 | 7 | 8 | p { 9 | font-size:16px; 10 | } -------------------------------------------------------------------------------- /backend/server.js: -------------------------------------------------------------------------------- 1 | const http = require('http'); 2 | const app = require('./app'); 3 | 4 | const port = process.env.PORT || 3000; 5 | 6 | const server = http.createServer(app); 7 | 8 | server.listen(port); -------------------------------------------------------------------------------- /frontend/src/app/admin/admin-activate-externals/admin-activate-externals.component.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | .active { 5 | color:rgb(8, 105, 8) 6 | } 7 | 8 | .not_active { 9 | color:red 10 | } -------------------------------------------------------------------------------- /frontend/src/app/admin/admin-university/admin-university.component.css: -------------------------------------------------------------------------------- 1 | .material-icons { 2 | font-size: 28px; 3 | text-align:center; 4 | } 5 | 6 | .table_data { 7 | font-size:16px; 8 | } 9 | -------------------------------------------------------------------------------- /frontend/src/app/login/login.component.css: -------------------------------------------------------------------------------- 1 | 2 | .confirm { 3 | 4 | background-color:rgb(69, 85, 228) !important; 5 | padding-right: 15px; 6 | } 7 | 8 | .mat-select-trigger { min-width: 50px; } -------------------------------------------------------------------------------- /frontend/src/app/alert/alert.component.html: -------------------------------------------------------------------------------- 1 |
{{message.text | json}}
2 | -------------------------------------------------------------------------------- /frontend/src/app/external/external-create-pending/external-create-pending.component.css: -------------------------------------------------------------------------------- 1 | p { 2 | font-size:16px; 3 | } 4 | 5 | .btn-default { 6 | float:right 7 | } 8 | 9 | .mat-select-trigger { min-width: 50px; } 10 | -------------------------------------------------------------------------------- /frontend/src/app/external/external-thesis/external-thesis.component.css: -------------------------------------------------------------------------------- 1 | .accepted { 2 | color:rgb(8, 105, 8) 3 | } 4 | 5 | .not_accepted { 6 | color:red 7 | } 8 | 9 | .edit { 10 | color:rgba(11, 142, 230, 0.842) 11 | } -------------------------------------------------------------------------------- /frontend/src/app/student/student-pending/student-pending.component.css: -------------------------------------------------------------------------------- 1 | .create .add { 2 | background-color:rgb(8, 105, 8) 3 | } 4 | 5 | .accepted { 6 | color:rgb(8, 105, 8) 7 | } 8 | 9 | .not_accepted { 10 | color:red 11 | } -------------------------------------------------------------------------------- /frontend/src/app/admin/admin-user/admin-user.component.css: -------------------------------------------------------------------------------- 1 | .material-icons { 2 | font-size: 28px; 3 | text-align:center; 4 | } 5 | 6 | .table_data { 7 | font-size:16px; 8 | } 9 | 10 | mat-form-field { 11 | width: 120px; 12 | } -------------------------------------------------------------------------------- /frontend/src/app/secretariat/secretariat-professors/secretariat-professors.component.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | .tabledata { 4 | font-size:16px; 5 | } 6 | 7 | .not_assigned { 8 | color:red; 9 | 10 | } 11 | 12 | 13 | .material-icons { 14 | font-size: 28px; 15 | text-align:center; 16 | } -------------------------------------------------------------------------------- /frontend/e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/e2e", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "types": [ 8 | "jasmine", 9 | "jasminewd2", 10 | "node" 11 | ] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /frontend/src/app/completed-thesis-repository/completed-thesis-repository.component.css: -------------------------------------------------------------------------------- 1 | .material-icons { 2 | font-size: 28px; 3 | text-align:center; 4 | } 5 | 6 | .glyphicon { 7 | font-size: 22px; 8 | text-align:center; 9 | } 10 | 11 | .itemlist { 12 | cursor:pointer; 13 | } -------------------------------------------------------------------------------- /frontend/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/app", 5 | "types": [] 6 | }, 7 | "include": [ 8 | "src/**/*.ts" 9 | ], 10 | "exclude": [ 11 | "src/test.ts", 12 | "src/**/*.spec.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /frontend/src/app/admin/admin-external/admin-external.component.css: -------------------------------------------------------------------------------- 1 | .material-icons { 2 | font-size: 28px; 3 | text-align:center; 4 | } 5 | 6 | .table_data { 7 | font-size:16px; 8 | } 9 | 10 | .active { 11 | color:rgb(8, 105, 8) 12 | } 13 | 14 | .not_active { 15 | color:red 16 | } -------------------------------------------------------------------------------- /backend/models/university.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | const universitySchema = mongoose.Schema({ 4 | _id: mongoose.Schema.Types.ObjectId, 5 | name: {type:String, required:true} 6 | }); 7 | 8 | 9 | module.exports = mongoose.model('University', universitySchema); 10 | -------------------------------------------------------------------------------- /frontend/src/app/professor/professor-thesis-edit/professor-thesis-edit.component.css: -------------------------------------------------------------------------------- 1 | .btn-default { 2 | float:right 3 | } 4 | 5 | .well , .col-md-8 { 6 | margin-right: 15%; 7 | } 8 | 9 | 10 | .text { 11 | width: 100%; 12 | padding: 3px; 13 | margin: 8px 0; 14 | box-sizing: border-box; 15 | } -------------------------------------------------------------------------------- /frontend/src/app/shared/models/thesis.model.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | export class Thesis { 4 | 5 | //_id: mongoose.Schema.Types.ObjectId, 6 | public title: String; 7 | public description: String; 8 | public prerequisites: String; 9 | public tags: [String]; 10 | public created_time: Date; 11 | 12 | } -------------------------------------------------------------------------------- /frontend/e2e/src/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class AppPage { 4 | navigateTo() { 5 | return browser.get(browser.baseUrl) as Promise; 6 | } 7 | 8 | getTitleText() { 9 | return element(by.css('app-root h1')).getText() as Promise; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /frontend/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /frontend/src/app/external/external-thesis-edit/external-thesis-edit.component.css: -------------------------------------------------------------------------------- 1 | .btn-default { 2 | float:right 3 | } 4 | 5 | 6 | 7 | .text { 8 | width: 100%; 9 | padding: 3px; 10 | margin: 8px 0; 11 | box-sizing: border-box; 12 | } 13 | 14 | .itemlist { 15 | text-align:'center'; 16 | cursor:pointer; 17 | } -------------------------------------------------------------------------------- /frontend/src/app/shared/models/request.model.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | export class Request { 5 | 6 | public student: String; 7 | public professor: String; 8 | public thesis: String; 9 | public text: String; 10 | public created_time: Date; 11 | public accepted_fromProfessor:Boolean; 12 | 13 | } 14 | 15 | -------------------------------------------------------------------------------- /frontend/src/app/footer/footer.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-footer', 5 | templateUrl: './footer.component.html', 6 | styleUrls: ['./footer.component.css'] 7 | }) 8 | export class FooterComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /frontend/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/spec", 5 | "types": [ 6 | "jasmine", 7 | "node" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts", 12 | "src/polyfills.ts" 13 | ], 14 | "include": [ 15 | "src/**/*.spec.ts", 16 | "src/**/*.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /frontend/src/app/student/student.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-student', 5 | templateUrl: './student.component.html', 6 | styleUrls: ['./student.component.css'] 7 | }) 8 | export class StudentComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /frontend/src/app/external/external.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-external', 5 | templateUrl: './external.component.html', 6 | styleUrls: ['./external.component.css'] 7 | }) 8 | export class ExternalComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /frontend/src/app/professor/professor.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-professor', 5 | templateUrl: './professor.component.html', 6 | styleUrls: ['./professor.component.css'] 7 | }) 8 | export class ProfessorComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /frontend/src/app/secretariat/secretariat.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-secretariat', 5 | templateUrl: './secretariat.component.html', 6 | styleUrls: ['./secretariat.component.css'] 7 | }) 8 | export class SecretariatComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /backend/models/draft.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | const draftSchema = mongoose.Schema({ 4 | _id: mongoose.Schema.Types.ObjectId, 5 | url: String, 6 | data: Buffer, 7 | name: String, 8 | created_time: Date, 9 | assigned_thesis: { type: mongoose.Schema.Types.ObjectId, ref:'Assigned_Thesis'}, 10 | }); 11 | 12 | module.exports = mongoose.model('Draft', draftSchema,'drafts'); -------------------------------------------------------------------------------- /backend/models/time_period.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | 4 | const time_periodSchema = mongoose.Schema({ 5 | _id: mongoose.Schema.Types.ObjectId, 6 | admin: { type: mongoose.Schema.Types.ObjectId, ref: 'External'}, 7 | application_period_start: Date, 8 | application_period_end: Date, 9 | 10 | }) 11 | 12 | module.exports = mongoose.model('Time_Period', time_periodSchema,'time_periods'); -------------------------------------------------------------------------------- /frontend/src/app/admin/admin-user/create-user/create-user.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-create-user', 5 | templateUrl: './create-user.component.html', 6 | styleUrls: ['./create-user.component.css'] 7 | }) 8 | export class CreateUserComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /frontend/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 | 7 | 8 |
9 |
10 |
11 | -------------------------------------------------------------------------------- /frontend/src/app/professor/professor-pending/professor-pending.component.css: -------------------------------------------------------------------------------- 1 | .create { 2 | color:rgb(8, 105, 8) 3 | } 4 | 5 | .assigned { 6 | color:rgb(8, 105, 8) 7 | } 8 | 9 | .not_assigned { 10 | color:red 11 | } 12 | 13 | .material-icons.add { 14 | font-size: 36px; 15 | text-align:center; 16 | } 17 | 18 | a.add { 19 | font-size: 33px; 20 | text-align: center; 21 | } 22 | 23 | p{ font-size:16px;} 24 | -------------------------------------------------------------------------------- /frontend/src/app/thesis/thesis-details/thesis-details.component.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | hr { 4 | display: block; 5 | margin-top: 0.5em; 6 | margin-bottom: 0.5em; 7 | margin-left: auto; 8 | margin-right: auto; 9 | border-style: inset; 10 | border-width: 1px; 11 | background-color: rgb(175, 243, 255); 12 | } 13 | 14 | .itemlist { 15 | cursor: pointer; 16 | } 17 | 18 | .item { 19 | font-size:16px; 20 | } -------------------------------------------------------------------------------- /frontend/src/app/home/home.component.css: -------------------------------------------------------------------------------- 1 | p { 2 | font-size:16px 3 | } 4 | 5 | 6 | .example-form { 7 | min-width: 150px; 8 | max-width: 500px; 9 | width: 100%; 10 | } 11 | 12 | .example-full-width { 13 | width: 100%; 14 | } 15 | 16 | 17 | button { 18 | text-align: right; 19 | } 20 | 21 | mat-card { 22 | margin-right: 10px; 23 | margin-bottom: 10px; 24 | } 25 | 26 | h3 { 27 | padding-left: 0px; 28 | } -------------------------------------------------------------------------------- /backend/models/file_thesis.js: -------------------------------------------------------------------------------- 1 | 2 | const mongoose = require('mongoose'); 3 | 4 | 5 | 6 | const fileSchema = mongoose.Schema({ 7 | _id: mongoose.Schema.Types.ObjectId, 8 | file_data: Buffer, // to store pdf file 9 | file_name: String, // pdf name file 10 | created_time : Date, 11 | thesis: {type: mongoose.Schema.Types.ObjectId, ref:'Thesis'}, 12 | 13 | }) 14 | 15 | module.exports = mongoose.model('FileThesis', fileSchema,'file_thesis'); -------------------------------------------------------------------------------- /frontend/src/app/shared/models/user.model.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | export class User { 4 | 5 | //_id: mongoose.Schema.Types.ObjectId, 6 | public email: string; 7 | public id: string; 8 | public name: string; 9 | public lastname: string; 10 | public role: 'Guest' | 'Admin' | 'Professor' | 'Student' | 'Secretariat'; 11 | public token : string; 12 | //public university: { type: mongoose.Schema.Types.ObjectId, ref: 'University'}, 13 | 14 | } -------------------------------------------------------------------------------- /backend/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:10 2 | 3 | # Create app directory 4 | WORKDIR /usr/src/app 5 | 6 | # Install app dependencies 7 | # A wildcard is used to ensure both package.json AND package-lock.json are copied 8 | COPY package*.json ./ 9 | 10 | RUN npm install 11 | # In production 12 | # RUN npm ci --only=production 13 | 14 | # Bundle app source 15 | COPY . . 16 | 17 | EXPOSE 3000 18 | CMD [ "node", "server.js" ] 19 | # Change in npm start if more starting script are in use -------------------------------------------------------------------------------- /backend/middleware/check-auth.js: -------------------------------------------------------------------------------- 1 | const jwt = require('jsonwebtoken'); 2 | 3 | module.exports = (req, res, next) => { 4 | 5 | try { 6 | 7 | const token = req.headers.authorization.split(" ")[1]; 8 | const decoded = jwt.verify(token, process.env.JWT_KEY); 9 | req.userData = decoded; 10 | next(); 11 | } catch (error) { 12 | return res.status(401).json({ 13 | message: 'Auth failed' 14 | }); 15 | } 16 | }; -------------------------------------------------------------------------------- /backend/cors.js: -------------------------------------------------------------------------------- 1 | const cors= (req, res, next) => { 2 | res.header("Access-Control-Allow-Origin", "*"); 3 | res.header( 4 | "Access-Control-Allow-Headers", 5 | "Origin, X-Requested-With, Content-Type, Accept, Authorization" 6 | ); 7 | if (req.method === "OPTIONS") { 8 | res.header("Access-Control-Allow-Methods", "PUT, POST, PATCH, DELETE, GET"); 9 | return res.status(200).json({}); 10 | } 11 | next(); 12 | }; 13 | 14 | module.exports= cors -------------------------------------------------------------------------------- /frontend/src/app/shared/models/external.model.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | export class External { 4 | 5 | //_id: mongoose.Schema.Types.ObjectId, 6 | public email: string; 7 | public name: string; 8 | public password: string; 9 | public lastname: string; 10 | public role: 'External' | 'External-Professor'; 11 | //public university: { type: mongoose.Schema.Types.ObjectId, ref: 'University'}, 12 | 13 | constructor(email) { this.email=email }; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /frontend/browserslist: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # You can see what browsers were selected by your queries by running: 6 | # npx browserslist 7 | 8 | > 0.5% 9 | last 2 versions 10 | Firefox ESR 11 | not dead 12 | not IE 9-11 # For IE 9-11 support, remove 'not'. -------------------------------------------------------------------------------- /frontend/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | import './polyfills'; 4 | import 'hammerjs'; 5 | 6 | 7 | import { AppModule } from './app/app.module'; 8 | import { environment } from './environments/environment'; 9 | 10 | if (environment.production) { 11 | enableProdMode(); 12 | } 13 | 14 | platformBrowserDynamic().bootstrapModule(AppModule) 15 | .catch(err => console.error(err)); 16 | -------------------------------------------------------------------------------- /backend/models/completed_thesis.js: -------------------------------------------------------------------------------- 1 | 2 | const mongoose = require('mongoose'); 3 | 4 | 5 | 6 | const completedThesisSchema = mongoose.Schema({ 7 | _id: mongoose.Schema.Types.ObjectId, 8 | file_data: Buffer, // to store pdf file 9 | file_name: String, // pdf name file 10 | created_time : Date, 11 | thesis: {type: mongoose.Schema.Types.ObjectId, ref:'Assigned_Thesis'}, 12 | 13 | }) 14 | 15 | module.exports = mongoose.model('CompletedThesis', completedThesisSchema,'completed_thesis'); -------------------------------------------------------------------------------- /frontend/src/app/secretariat/secretariat-students/secretariat-students.component.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | .tabledata { 4 | font-size:16px; 5 | } 6 | 7 | .not_assigned { 8 | color:red; 9 | 10 | } 11 | 12 | .material-icons { 13 | font-size: 28px; 14 | text-align:center; 15 | } 16 | 17 | .margin-left { 18 | margin-left: 1em; 19 | } 20 | 21 | mat-form-field { 22 | width: 16rem; 23 | margin-right: 12px; 24 | } 25 | 26 | .bold { 27 | font-weight: bold; 28 | margin-right: 10px; 29 | } -------------------------------------------------------------------------------- /backend/models/pending.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | const pendingSchema = mongoose.Schema({ 4 | _id: mongoose.Schema.Types.ObjectId, 5 | creator:{ type: mongoose.Schema.Types.ObjectId, ref:'External'}, // can be external or student 6 | thesis: { type: mongoose.Schema.Types.ObjectId, ref:'Thesis' }, 7 | professor: { type: mongoose.Schema.Types.ObjectId, ref:'User'}, 8 | created_time : Date 9 | }) 10 | 11 | module.exports = mongoose.model('Pending', pendingSchema,'pending'); -------------------------------------------------------------------------------- /frontend/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:10 2 | 3 | # Create app directory 4 | WORKDIR /usr/src/app 5 | 6 | # Install app dependencies 7 | # A wildcard is used to ensure both package.json AND package-lock.json are copied 8 | COPY package*.json ./ 9 | 10 | RUN npm install 11 | RUN npm install -g @angular/cli@8.0.0 12 | # In production 13 | # RUN npm ci --only=production 14 | 15 | # Bundle app source 16 | COPY . . 17 | 18 | EXPOSE 4200 19 | CMD ng serve --host 0.0.0.0 20 | # Change in npm start if more starting script are in use -------------------------------------------------------------------------------- /frontend/src/app/header/header.component.css: -------------------------------------------------------------------------------- 1 | .nav-item { 2 | cursor: pointer; 3 | font-size: 18px; 4 | } 5 | 6 | .navbar { 7 | background-color:rgb(88, 173, 226); 8 | } 9 | 10 | .logo { 11 | width:40px; 12 | height:40px; 13 | } 14 | .active2 15 | { 16 | background-color: rgb(64, 158, 216) ; 17 | } 18 | 19 | 20 | .nav-item { 21 | color: white !Important; 22 | } 23 | 24 | .logout { 25 | position:fixed; 26 | right:10px; 27 | top:5px; 28 | } 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /frontend/src/app/admin/admin.component.css: -------------------------------------------------------------------------------- 1 | .navbar-fixed-left { 2 | width: 140px; 3 | position: fixed; 4 | border-radius: 0; 5 | height: 100%; 6 | } 7 | 8 | .navbar-fixed-left .navbar-nav > li { 9 | float: none; /* Cancel default li float: left */ 10 | width: 139px; 11 | } 12 | 13 | .navbar-fixed-left + .container { 14 | } 15 | 16 | /* On using dropdown menu (To right shift popuped) */ 17 | .navbar-fixed-left .navbar-nav > li > .dropdown-menu { 18 | margin-top: -50px; 19 | } -------------------------------------------------------------------------------- /frontend/src/app/footer/footer.component.html: -------------------------------------------------------------------------------- 1 | 11 |
12 |
-------------------------------------------------------------------------------- /frontend/src/app/professor/professor-thesis/professor-thesis.component.css: -------------------------------------------------------------------------------- 1 | .create { 2 | color:rgb(8, 105, 8) 3 | } 4 | 5 | .assigned { 6 | color:rgb(8, 105, 8) 7 | } 8 | 9 | .not_assigned { 10 | color:red; 11 | 12 | } 13 | 14 | 15 | 16 | .material-icons.add { 17 | font-size: 36px; 18 | text-align:center; 19 | } 20 | 21 | 22 | 23 | .add { 24 | font-size: 33px; 25 | text-align: center; 26 | } 27 | 28 | .edit { 29 | color:rgba(11, 142, 230, 0.842) 30 | } 31 | 32 | p { 33 | font-size:16px; 34 | } -------------------------------------------------------------------------------- /frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/out-tsc", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "module": "esnext", 9 | "moduleResolution": "node", 10 | "emitDecoratorMetadata": true, 11 | "experimentalDecorators": true, 12 | "importHelpers": true, 13 | "target": "es2015", 14 | "typeRoots": [ 15 | "node_modules/@types" 16 | ], 17 | "lib": [ 18 | "es2018", 19 | "dom" 20 | ] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /frontend/src/app/login/login.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 |

Log In:

6 |
7 | 8 |
9 |
10 |
11 | 12 |
13 |
14 |
15 | -------------------------------------------------------------------------------- /backend/models/external.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | const externalSchema = mongoose.Schema({ 4 | _id: mongoose.Schema.Types.ObjectId, 5 | email: { 6 | type: String, 7 | required: true, 8 | unique: true 9 | }, 10 | password: { type: String, required: true }, 11 | name: String, 12 | lastname: String, 13 | role: {type: String, default: "External" }, 14 | active :{ type: Boolean, default: false } 15 | 16 | }); 17 | 18 | module.exports = mongoose.model('External', externalSchema); -------------------------------------------------------------------------------- /backend/models/request.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | //students requests for thesis selection 4 | const requestSchema = mongoose.Schema({ 5 | _id: mongoose.Schema.Types.ObjectId, 6 | student: { type: mongoose.Schema.Types.ObjectId, ref:'User'}, 7 | professor: { type: mongoose.Schema.Types.ObjectId, ref:'User'}, 8 | thesis: {type: mongoose.Schema.Types.ObjectId, ref:'Thesis'}, 9 | text: String, 10 | created_time: Date, 11 | accepted_fromProfessor:Boolean 12 | }); 13 | 14 | module.exports = mongoose.model('Request', requestSchema,'requests'); -------------------------------------------------------------------------------- /frontend/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | @import "../node_modules/@angular/material/prebuilt-themes/deeppurple-amber.css"; 3 | 4 | .pagination { 5 | font-weight:bold; 6 | font-size:20px; 7 | color: black; 8 | float: left; 9 | padding: 8px 16px; 10 | text-decoration: none; 11 | } 12 | 13 | .well { 14 | background: rgb(250, 247, 247) 15 | } 16 | 17 | .table_header { 18 | font-size: 16px; 19 | } 20 | 21 | td { 22 | font-size:16px 23 | } 24 | 25 | dt { 26 | font-size:16px; 27 | } -------------------------------------------------------------------------------- /backend/models/user.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | 4 | const userSchema = mongoose.Schema({ 5 | _id: mongoose.Schema.Types.ObjectId, 6 | email: { 7 | type: String, 8 | required: true, 9 | unique: true 10 | }, 11 | name: String, 12 | lastname: String, 13 | role: { 14 | type: String, 15 | enum: ['Guest','Admin','Professor','Student','Secretariat'] 16 | }, 17 | university: { type: mongoose.Schema.Types.ObjectId, ref: 'University'}, 18 | 19 | }); 20 | 21 | module.exports = mongoose.model('User', userSchema); -------------------------------------------------------------------------------- /backend/models/notification.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | const notificationSchema = mongoose.Schema({ 4 | _id: mongoose.Schema.Types.ObjectId, 5 | creator_external:{ type: mongoose.Schema.Types.ObjectId, ref:'External'}, // can be external or student 6 | creator_user: { type: mongoose.Schema.Types.ObjectId, ref:'User' }, 7 | receiver_external : { type: mongoose.Schema.Types.ObjectId, ref:'External'}, 8 | receiver_user : { type: mongoose.Schema.Types.ObjectId, ref:'User' }, 9 | text: String, 10 | ccreated_time: Date 11 | }); 12 | 13 | module.exports = mongoose.model('Notification', notificationSchema); -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Launch Program", 11 | "program": "${workspaceFolder}\\frontend\\src\\app\\student\\student-assigned\\student-assigned.component.ts", 12 | "outFiles": [ 13 | "${workspaceFolder}/**/*.js" 14 | ] 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /backend/routes/university.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const router = express.Router(); 3 | 4 | const universityController = require('../controllers/university'); 5 | const checkAuth = require('../middleware/check-auth'); 6 | 7 | 8 | //URL: /university 9 | 10 | router.get("/", universityController.get_all); //get all universities with pagination 11 | router.get("/noPages",universityController.get_all_noPages) //get all , no pagination 12 | router.get("/:universityId", universityController.get_byId) //get university by id 13 | 14 | //router.delete("/:userId", checkAuth, thesisController.user_delete); // 15 | //search thesis 16 | module.exports = router; 17 | -------------------------------------------------------------------------------- /frontend/src/app/app.component.css: -------------------------------------------------------------------------------- 1 | .footer { 2 | 3 | height:24px; 4 | width: 100%; 5 | background-image: none; 6 | background-repeat: repeat; 7 | background-attachment: scroll; 8 | background-position: 0% 0%; 9 | position: fixed; 10 | bottom: 0pt; 11 | left: 0pt; 12 | 13 | } 14 | 15 | .footer_contents { 16 | 17 | height:24px; 18 | width: 1000px; 19 | margin:auto; 20 | 21 | 22 | } 23 | 24 | .pull-right { 25 | float: right !important; 26 | } 27 | 28 | .row { 29 | margin: 0 auto; 30 | width: 80%; 31 | height: 60%; 32 | margin-right: 7%; 33 | } 34 | 35 | -------------------------------------------------------------------------------- /frontend/src/app/professor/professor-assigned/professor-assigned.component.css: -------------------------------------------------------------------------------- 1 | .create { 2 | color:rgb(8, 105, 8) 3 | } 4 | 5 | .assigned { 6 | color:rgb(8, 105, 8) 7 | } 8 | 9 | .not_assigned { 10 | color:red 11 | } 12 | 13 | .material-icons.add { 14 | font-size: 36px; 15 | text-align:center; 16 | } 17 | 18 | a.add { 19 | font-size: 33px; 20 | text-align: center; 21 | } 22 | 23 | .item { 24 | cursor:pointer; 25 | } 26 | .itemlist { 27 | font-size:16px; 28 | } 29 | 30 | #getDrafts { 31 | float:right; 32 | } 33 | 34 | dt { 35 | font-size:18px 36 | } 37 | 38 | dl { 39 | font-size:16px 40 | } 41 | 42 | #file { 43 | font-size:16px 44 | } 45 | -------------------------------------------------------------------------------- /frontend/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/zone-testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: any; 11 | 12 | // First, initialize the Angular testing environment. 13 | getTestBed().initTestEnvironment( 14 | BrowserDynamicTestingModule, 15 | platformBrowserDynamicTesting() 16 | ); 17 | // Then we find all the tests. 18 | const context = require.context('./', true, /\.spec\.ts$/); 19 | // And load the modules. 20 | context.keys().map(context); 21 | -------------------------------------------------------------------------------- /frontend/src/app/sidenav/sidenav.component.css: -------------------------------------------------------------------------------- 1 | .navbar-fixed-left { 2 | width: 12%; 3 | position: fixed; 4 | border-radius: 0; 5 | height: 100%; 6 | text-align: left; 7 | } 8 | 9 | .navbar-fixed-left .navbar-nav > li { 10 | float: none; /* Cancel default li float: left */ 11 | width: 100%; 12 | } 13 | 14 | .navbar-fixed-left + .container { 15 | padding-left: 160px; 16 | } 17 | 18 | /* On using dropdown menu (To right shift popuped) */ 19 | .navbar-fixed-left .navbar-nav > li > .dropdown-menu { 20 | margin-top: -50px; 21 | margin-left: 140px; 22 | } 23 | 24 | .navbar { 25 | background-color:rgb(255, 255, 255); 26 | 27 | } 28 | .nav-item { 29 | color: rgba(0, 0, 0, 0) !Important; 30 | } -------------------------------------------------------------------------------- /frontend/e2e/src/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { AppPage } from './app.po'; 2 | import { browser, logging } from 'protractor'; 3 | 4 | describe('workspace-project App', () => { 5 | let page: AppPage; 6 | 7 | beforeEach(() => { 8 | page = new AppPage(); 9 | }); 10 | 11 | it('should display welcome message', () => { 12 | page.navigateTo(); 13 | expect(page.getTitleText()).toEqual('Welcome to frontend!'); 14 | }); 15 | 16 | afterEach(async () => { 17 | // Assert that there are no errors emitted from the browser 18 | const logs = await browser.manage().logs().get(logging.Type.BROWSER); 19 | expect(logs).not.toContain(jasmine.objectContaining({ 20 | level: logging.Level.SEVERE, 21 | } as logging.Entry)); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /frontend/src/app/home/home.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { HomeComponent } from './home.component'; 4 | 5 | describe('HomeComponent', () => { 6 | let component: HomeComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ HomeComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(HomeComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/admin/admin.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { AdminComponent } from './admin.component'; 4 | 5 | describe('AdminComponent', () => { 6 | let component: AdminComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ AdminComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AdminComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/alert/alert.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { AlertComponent } from './alert.component'; 4 | 5 | describe('AlertComponent', () => { 6 | let component: AlertComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ AlertComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AlertComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/login/login.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { LoginComponent } from './login.component'; 4 | 5 | describe('LoginComponent', () => { 6 | let component: LoginComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ LoginComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(LoginComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/footer/footer.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { FooterComponent } from './footer.component'; 4 | 5 | describe('FooterComponent', () => { 6 | let component: FooterComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ FooterComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(FooterComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/header/header.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { HeaderComponent } from './header.component'; 4 | 5 | describe('HeaderComponent', () => { 6 | let component: HeaderComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ HeaderComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(HeaderComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/profile/profile.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ProfileComponent } from './profile.component'; 4 | 5 | describe('ProfileComponent', () => { 6 | let component: ProfileComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ProfileComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ProfileComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/sidenav/sidenav.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { SidenavComponent } from './sidenav.component'; 4 | 5 | describe('SidenavComponent', () => { 6 | let component: SidenavComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ SidenavComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(SidenavComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/student/student.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { StudentComponent } from './student.component'; 4 | 5 | describe('StudentComponent', () => { 6 | let component: StudentComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ StudentComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(StudentComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /backend/models/supervision_requests.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | //requests for supervision thesis 4 | 5 | const supervision_requestSchema = mongoose.Schema({ 6 | _id: mongoose.Schema.Types.ObjectId, 7 | student: { type: mongoose.Schema.Types.ObjectId, ref:'User'}, 8 | professor: { type: mongoose.Schema.Types.ObjectId, ref:'User'}, 9 | dst_professor: { type: mongoose.Schema.Types.ObjectId, refPath: 'supervisorModel'}, 10 | supervisorModel: { 11 | type: String, 12 | enum: ['User', 'External'] 13 | }, 14 | assigned_thesis: {type: mongoose.Schema.Types.ObjectId, ref:'Assigned_Thesis'}, 15 | text: String, 16 | created_time: Date, 17 | }); 18 | 19 | module.exports = mongoose.model('Supervision_Request', supervision_requestSchema); -------------------------------------------------------------------------------- /frontend/src/app/external/external.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ExternalComponent } from './external.component'; 4 | 5 | describe('ExternalComponent', () => { 6 | let component: ExternalComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ExternalComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ExternalComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false, 7 | apiUrl: "http://localhost:3000" 8 | }; 9 | 10 | /* 11 | * For easier debugging in development mode, you can import the following file 12 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 13 | * 14 | * This import should be commented out in production mode because it will have a negative impact 15 | * on performance if an error is thrown. 16 | */ 17 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI. 18 | -------------------------------------------------------------------------------- /frontend/src/app/professor/professor.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ProfessorComponent } from './professor.component'; 4 | 5 | describe('ProfessorComponent', () => { 6 | let component: ProfessorComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ProfessorComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ProfessorComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/admin/admin-user/admin-user.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { AdminUserComponent } from './admin-user.component'; 4 | 5 | describe('AdminUserComponent', () => { 6 | let component: AdminUserComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ AdminUserComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AdminUserComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/login/login-ldap/login-ldap.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { LoginLdapComponent } from './login-ldap.component'; 4 | 5 | describe('LoginLdapComponent', () => { 6 | let component: LoginLdapComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ LoginLdapComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(LoginLdapComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/alert/alert.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, OnDestroy } from '@angular/core'; 2 | import { Subscription } from 'rxjs'; 3 | import { AlertService } from '../shared/services/alert.service'; 4 | 5 | 6 | @Component({ 7 | selector: 'app-alert', 8 | templateUrl: './alert.component.html', 9 | styleUrls: ['./alert.component.css'] 10 | }) 11 | export class AlertComponent implements OnInit,OnDestroy { 12 | private subscription: Subscription; 13 | message: any; 14 | 15 | constructor(private alertService: AlertService) { } 16 | 17 | ngOnInit() { 18 | this.subscription = this.alertService.getMessage() 19 | .subscribe(message => { 20 | this.message = message; 21 | }); 22 | } 23 | 24 | ngOnDestroy() { 25 | this.subscription.unsubscribe(); 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /frontend/src/app/secretariat/secretariat.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { SecretariatComponent } from './secretariat.component'; 4 | 5 | describe('SecretariatComponent', () => { 6 | let component: SecretariatComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ SecretariatComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(SecretariatComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.5' 2 | 3 | services: 4 | node-app: 5 | build: backend 6 | ports: 7 | - 3000:3000 8 | depends_on: 9 | - mongo 10 | 11 | mongo: 12 | image: mongo # pulls official mongo image 13 | restart: always 14 | ports: 15 | - 27017:27017 16 | # Uncomment the following 2 lines if you want the container to preserve the mongodb data 17 | # volumes: 18 | # - /var/log/mongodb/mongodb.log:/data/db 19 | environment: 20 | ME_CONFIG_MONGODB_ADMINUSERNAME: 21 | ME_CONFIG_MONGODB_ADMINPASSWORD: 22 | 23 | angular-app: 24 | build: frontend 25 | ports: 26 | - 4200:4200 27 | depends_on: 28 | - node-app -------------------------------------------------------------------------------- /frontend/src/app/admin/admin-user/create-user/create-user.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { CreateUserComponent } from './create-user.component'; 4 | 5 | describe('CreateUserComponent', () => { 6 | let component: CreateUserComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ CreateUserComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(CreateUserComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/thesis/thesis-create/thesis-create.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ThesisCreateComponent } from './thesis-create.component'; 4 | 5 | describe('ThesisCreateComponent', () => { 6 | let component: ThesisCreateComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ThesisCreateComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ThesisCreateComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/admin/admin.component.ts: -------------------------------------------------------------------------------- 1 | import { Router } from '@angular/router'; 2 | import { Component, OnInit } from '@angular/core'; 3 | import { first } from 'rxjs/operators'; 4 | import {MatSidenavModule} from '@angular/material/sidenav'; 5 | 6 | 7 | import { AuthenticationService } from '../shared/services/authentication.service'; 8 | import { UserService } from '../shared/services/user.service'; 9 | import { AlertService } from '../shared/services/alert.service'; 10 | import { AdminService } from './../shared/services/admin.service'; 11 | 12 | @Component({ 13 | selector: 'app-admin', 14 | templateUrl: './admin.component.html', 15 | styleUrls: ['./admin.component.css'] 16 | }) 17 | export class AdminComponent implements OnInit { 18 | 19 | constructor( ) {} 20 | 21 | ngOnInit() { 22 | 23 | } 24 | 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /frontend/src/app/home/search-results/search-results.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { SearchResultsComponent } from './search-results.component'; 4 | 5 | describe('SearchResultsComponent', () => { 6 | let component: SearchResultsComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ SearchResultsComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(SearchResultsComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/admin/admin-external/admin-external.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { AdminExternalComponent } from './admin-external.component'; 4 | 5 | describe('AdminExternalComponent', () => { 6 | let component: AdminExternalComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ AdminExternalComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AdminExternalComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/login/login-external/login-external.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { LoginExternalComponent } from './login-external.component'; 4 | 5 | describe('LoginExternalComponent', () => { 6 | let component: LoginExternalComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ LoginExternalComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(LoginExternalComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/student/student-thesis/student-thesis.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { StudentThesisComponent } from './student-thesis.component'; 4 | 5 | describe('StudentThesisComponent', () => { 6 | let component: StudentThesisComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ StudentThesisComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(StudentThesisComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/thesis/thesis-details/thesis-details.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ThesisDetailsComponent } from './thesis-details.component'; 4 | 5 | describe('ThesisDetailsComponent', () => { 6 | let component: ThesisDetailsComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ThesisDetailsComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ThesisDetailsComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | # Only exists if Bazel was run 8 | /bazel-out 9 | 10 | # dependencies 11 | /node_modules 12 | 13 | # profiling files 14 | chrome-profiler-events.json 15 | speed-measure-plugin.json 16 | 17 | # IDEs and editors 18 | /.idea 19 | .project 20 | .classpath 21 | .c9/ 22 | *.launch 23 | .settings/ 24 | *.sublime-workspace 25 | 26 | # IDE - VSCode 27 | .vscode/* 28 | !.vscode/settings.json 29 | !.vscode/tasks.json 30 | !.vscode/launch.json 31 | !.vscode/extensions.json 32 | .history/* 33 | 34 | # misc 35 | /.sass-cache 36 | /connect.lock 37 | /coverage 38 | /libpeerconnection.log 39 | npm-debug.log 40 | yarn-error.log 41 | testem.log 42 | /typings 43 | 44 | # System Files 45 | .DS_Store 46 | Thumbs.db 47 | -------------------------------------------------------------------------------- /frontend/src/app/external/external-thesis/external-thesis.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ExternalThesisComponent } from './external-thesis.component'; 4 | 5 | describe('ExternalThesisComponent', () => { 6 | let component: ExternalThesisComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ExternalThesisComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ExternalThesisComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/student/student-pending/student-pending.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { StudentPendingComponent } from './student-pending.component'; 4 | 5 | describe('StudentPendingComponent', () => { 6 | let component: StudentPendingComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ StudentPendingComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(StudentPendingComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/admin/admin-university/admin-university.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { AdminUniversityComponent } from './admin-university.component'; 4 | 5 | describe('AdminUniversityComponent', () => { 6 | let component: AdminUniversityComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ AdminUniversityComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AdminUniversityComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/thesis/thesis-professor/thesis-professor.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ThesisProfessorComponent } from './thesis-professor.component'; 4 | 5 | describe('ThesisProfessorComponent', () => { 6 | let component: ThesisProfessorComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ThesisProfessorComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ThesisProfessorComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/professor/professor-thesis/professor-thesis.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ProfessorThesisComponent } from './professor-thesis.component'; 4 | 5 | describe('ProfessorThesisComponent', () => { 6 | let component: ProfessorThesisComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ProfessorThesisComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ProfessorThesisComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/register-external/register-external.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { RegisterExternalComponent } from './register-external.component'; 4 | 5 | describe('RegisterExternalComponent', () => { 6 | let component: RegisterExternalComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ RegisterExternalComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(RegisterExternalComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/student/student-assigned/student-assigned.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { StudentAssignedComponent } from './student-assigned.component'; 4 | 5 | describe('StudentAssignedComponent', () => { 6 | let component: StudentAssignedComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ StudentAssignedComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(StudentAssignedComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/student/student-requests/student-requests.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { StudentRequestsComponent } from './student-requests.component'; 4 | 5 | describe('StudentRequestsComponent', () => { 6 | let component: StudentRequestsComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ StudentRequestsComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(StudentRequestsComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/admin/create-university/create-university.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { CreateUniversityComponent } from './create-university.component'; 4 | 5 | describe('CreateUniversityComponent', () => { 6 | let component: CreateUniversityComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ CreateUniversityComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(CreateUniversityComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/professor/professor-pending/professor-pending.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ProfessorPendingComponent } from './professor-pending.component'; 4 | 5 | describe('ProfessorPendingComponent', () => { 6 | let component: ProfessorPendingComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ProfessorPendingComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ProfessorPendingComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/professor/professor-assigned/professor-assigned.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ProfessorAssignedComponent } from './professor-assigned.component'; 4 | 5 | describe('ProfessorAssignedComponent', () => { 6 | let component: ProfessorAssignedComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ProfessorAssignedComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ProfessorAssignedComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/professor/professor-requests/professor-requests.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ProfessorRequestsComponent } from './professor-requests.component'; 4 | 5 | describe('ProfessorRequestsComponent', () => { 6 | let component: ProfessorRequestsComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ProfessorRequestsComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ProfessorRequestsComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/professor/professor-supervise/professor-supervise.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ProfessorSuperviseComponent } from './professor-supervise.component'; 4 | 5 | describe('ProfessorSuperviseComponent', () => { 6 | let component: ProfessorSuperviseComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ProfessorSuperviseComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ProfessorSuperviseComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/external/external-thesis-edit/external-thesis-edit.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ExternalThesisEditComponent } from './external-thesis-edit.component'; 4 | 5 | describe('ExternalThesisEditComponent', () => { 6 | let component: ExternalThesisEditComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ExternalThesisEditComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ExternalThesisEditComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/professor/professor-thesis-edit/professor-thesis-edit.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ProfessorThesisEditComponent } from './professor-thesis-edit.component'; 4 | 5 | describe('ProfessorThesisEditComponent', () => { 6 | let component: ProfessorThesisEditComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ProfessorThesisEditComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ProfessorThesisEditComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/secretariat/secretariat-students/secretariat-students.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { SecretariatStudentsComponent } from './secretariat-students.component'; 4 | 5 | describe('SecretariatStudentsComponent', () => { 6 | let component: SecretariatStudentsComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ SecretariatStudentsComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(SecretariatStudentsComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/student/student-create-pending/student-create-pending.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { StudentCreatePendingComponent } from './student-create-pending.component'; 4 | 5 | describe('StudentCreatePendingComponent', () => { 6 | let component: StudentCreatePendingComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ StudentCreatePendingComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(StudentCreatePendingComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/external/external-create-pending/external-create-pending.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ExternalCreatePendingComponent } from './external-create-pending.component'; 4 | 5 | describe('ExternalCreatePendingComponent', () => { 6 | let component: ExternalCreatePendingComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ExternalCreatePendingComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ExternalCreatePendingComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/secretariat/secretariat-professors/secretariat-professors.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { SecretariatProfessorsComponent } from './secretariat-professors.component'; 4 | 5 | describe('SecretariatProfessorsComponent', () => { 6 | let component: SecretariatProfessorsComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ SecretariatProfessorsComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(SecretariatProfessorsComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/admin/admin-activate-externals/admin-activate-externals.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { AdminActivateExternalsComponent } from './admin-activate-externals.component'; 4 | 5 | describe('AdminActivateExternalsComponent', () => { 6 | let component: AdminActivateExternalsComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ AdminActivateExternalsComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AdminActivateExternalsComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/shared/guards/auth.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; 3 | 4 | import { AuthenticationService } from '../services/authentication.service'; 5 | 6 | @Injectable({ providedIn: 'root' }) 7 | export class AuthGuard implements CanActivate { 8 | constructor( 9 | private router: Router, 10 | private authenticationService: AuthenticationService 11 | ) {} 12 | 13 | canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) : boolean { 14 | if (this.authenticationService.isLoggedIn()) { 15 | // authorised so let access 16 | return true; 17 | } 18 | else { 19 | // not logged in so redirect to login 20 | this.router.navigate(['/login']) 21 | return false; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /frontend/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component , OnInit} from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | import { Title } from '@angular/platform-browser'; 4 | 5 | import {User} from './shared/models/user.model'; 6 | import { AuthenticationService } from './shared/services/authentication.service'; 7 | 8 | @Component({ 9 | selector: 'app-root', 10 | templateUrl: './app.component.html', 11 | styleUrls: ['./app.component.css'] 12 | }) 13 | export class AppComponent implements OnInit { 14 | currentUser: User; 15 | constructor( 16 | private router: Router, 17 | private authenticationService: AuthenticationService, 18 | private titleService: Title 19 | ) {} 20 | 21 | ngOnInit() { 22 | this.titleService.setTitle( "Thesis Management System"); 23 | } 24 | 25 | logout() { 26 | this.authenticationService.logout(); 27 | this.router.navigate(['/login']); 28 | } 29 | 30 | } 31 | 32 | -------------------------------------------------------------------------------- /frontend/src/app/shared/guards/login.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; 3 | 4 | import { AuthenticationService } from '../services/authentication.service'; 5 | 6 | @Injectable({ providedIn: 'root' }) 7 | export class LoginGuard implements CanActivate { 8 | constructor( 9 | private router: Router, 10 | private authenticationService: AuthenticationService 11 | ) {} 12 | 13 | canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) : boolean { 14 | if (this.authenticationService.isLoggedIn()) { 15 | // authorised so navigate to home page 16 | this.router.navigate(['/']) 17 | return false; 18 | } 19 | else { 20 | // not logged in so let access to /login 21 | return true; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /frontend/src/app/shared/guards/secretariat.guard.ts: -------------------------------------------------------------------------------- 1 | 2 | import { Observable } from 'rxjs'; 3 | import { map, tap, take, catchError } from 'rxjs/operators'; 4 | import { Injectable } from '@angular/core'; 5 | import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; 6 | 7 | 8 | 9 | @Injectable({ providedIn: 'root' }) 10 | export class SecretariatGuard implements CanActivate { 11 | constructor( 12 | private router: Router, 13 | ) {} 14 | 15 | canActivate(route: ActivatedRouteSnapshot , 16 | router: RouterStateSnapshot) 17 | :Observable|boolean { 18 | if(localStorage.getItem('Role')==="Secretariat") 19 | return true; 20 | else { 21 | console.log("not auth"); 22 | this.router.navigate(['/']) 23 | return false; 24 | } 25 | 26 | // not logged in so redirect to login page with the return url 27 | } 28 | } -------------------------------------------------------------------------------- /frontend/src/app/completed-thesis-repository/completed-thesis-repository.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { CompletedThesisRepositoryComponent } from './completed-thesis-repository.component'; 4 | 5 | describe('CompletedThesisRepositoryComponent', () => { 6 | let component: CompletedThesisRepositoryComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ CompletedThesisRepositoryComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(CompletedThesisRepositoryComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/src/app/professor/professor-supervisor-thesis/professor-supervisor-thesis.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ProfessorSupervisorThesisComponent } from './professor-supervisor-thesis.component'; 4 | 5 | describe('ProfessorSupervisorThesisComponent', () => { 6 | let component: ProfessorSupervisorThesisComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ProfessorSupervisorThesisComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ProfessorSupervisorThesisComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/e2e/protractor.conf.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | // Protractor configuration file, see link for more information 3 | // https://github.com/angular/protractor/blob/master/lib/config.ts 4 | 5 | const { SpecReporter } = require('jasmine-spec-reporter'); 6 | 7 | /** 8 | * @type { import("protractor").Config } 9 | */ 10 | exports.config = { 11 | allScriptsTimeout: 11000, 12 | specs: [ 13 | './src/**/*.e2e-spec.ts' 14 | ], 15 | capabilities: { 16 | 'browserName': 'chrome' 17 | }, 18 | directConnect: true, 19 | baseUrl: 'http://localhost:4200/', 20 | framework: 'jasmine', 21 | jasmineNodeOpts: { 22 | showColors: true, 23 | defaultTimeoutInterval: 30000, 24 | print: function() {} 25 | }, 26 | onPrepare() { 27 | require('ts-node').register({ 28 | project: require('path').join(__dirname, './tsconfig.json') 29 | }); 30 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 31 | } 32 | }; -------------------------------------------------------------------------------- /backend/models/thesis.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | const thesisSchema = mongoose.Schema({ 4 | _id: mongoose.Schema.Types.ObjectId, 5 | title: { 6 | type: String, 7 | required: true, 8 | }, 9 | description: String, 10 | prerequisites: String, 11 | tags: [String], 12 | created_time: Date, 13 | file: [{type: mongoose.Schema.Types.ObjectId, ref:'FileThesis'}], 14 | assigned: Boolean, // true if it is assigned to some student 15 | university: { type: mongoose.Schema.Types.ObjectId, ref: 'University'}, 16 | professor: { type: mongoose.Schema.Types.ObjectId, ref:'User'}, 17 | pending: Boolean, // external,student wait for approval from professor. 18 | creator_student: { type: mongoose.Schema.Types.ObjectId, ref:'User' }, 19 | creator_external:{ type: mongoose.Schema.Types.ObjectId, ref:'External'}, 20 | }); 21 | 22 | 23 | module.exports = mongoose.model('Thesis', thesisSchema,'thesis'); -------------------------------------------------------------------------------- /frontend/src/app/shared/interceptors/jwt.interceptor.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http'; 3 | import { Observable } from 'rxjs'; 4 | 5 | import { AuthenticationService } from '../services/authentication.service'; 6 | 7 | @Injectable() 8 | export class JwtInterceptor implements HttpInterceptor { 9 | constructor(private authenticationService: AuthenticationService) {} 10 | 11 | intercept(request: HttpRequest, next: HttpHandler): Observable> { 12 | // add authorization header with jwt token if available 13 | let token = this.authenticationService.getToken(); 14 | if (token) { 15 | request = request.clone({ 16 | setHeaders: { 17 | Authorization: `Bearer ${token}` 18 | } 19 | }); 20 | } 21 | 22 | return next.handle(request); 23 | } 24 | } -------------------------------------------------------------------------------- /backend/routes/secretariat.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const router = express.Router(); 3 | const secretariatController=require('../controllers/secretariat') 4 | const professorController = require('../controllers/professor'); 5 | const checkAuth = require('../middleware/check-auth'); 6 | 7 | 8 | //url secretariat 9 | 10 | router.all("/*",checkAuth,secretariatController.is_secretariat) 11 | 12 | 13 | router.get("/get_students",secretariatController.get_students_pages); //get all students 14 | router.get("/get_students_not_assigned",secretariatController.get_students) //get students seperated in assigned and not assigned to thesis 15 | 16 | router.get("/get_professors",secretariatController.get_professors) // get all professors 17 | 18 | router.post("/notify_student/:studentId",secretariatController.notify_student); //notify students that dont have assigned a thesis 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | module.exports = router; 33 | -------------------------------------------------------------------------------- /frontend/src/app/login/login.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { HttpClient } from '@angular/common/http'; 3 | import {Router, ActivatedRoute } from '@angular/router' ; 4 | import {ViewEncapsulation} from '@angular/core'; 5 | 6 | @Component({ 7 | selector: 'app-login', 8 | templateUrl: './login.component.html', 9 | styleUrls: ['./login.component.css'], 10 | encapsulation: ViewEncapsulation.None, 11 | 12 | }) 13 | export class LoginComponent implements OnInit { 14 | 15 | value: string; 16 | viewValue: string; 17 | 18 | constructor(private router: Router, 19 | private http: HttpClient 20 | ) { } 21 | 22 | ngOnInit() { 23 | } 24 | 25 | login_ldap(){ 26 | this.router.navigate(['/login-ldap']); 27 | } 28 | 29 | login_external() { 30 | this.router.navigate(['/login-external']); 31 | } 32 | 33 | // Geting the value of selected university and // NOT IMPLEMENTED ---- redirect to the specified Identity Provider ! 34 | 35 | } 36 | -------------------------------------------------------------------------------- /frontend/src/app/shared/services/user.service.ts: -------------------------------------------------------------------------------- 1 | import { environment } from './../../../environments/environment'; 2 | import { Injectable } from '@angular/core'; 3 | import { HttpClient } from '@angular/common/http'; 4 | import { User } from '../models/user.model'; 5 | 6 | @Injectable({ providedIn: 'root' }) 7 | export class UserService { 8 | constructor(private http: HttpClient) { } 9 | 10 | /* getAll() { 11 | return this.http.get(`${config.apiUrl}/users`); 12 | } 13 | 14 | getById(id: number) { 15 | return this.http.get(`${config.apiUrl}/users/${id}`); 16 | } 17 | */ 18 | register(user: User) { 19 | return this.http.post(environment.apiUrl+'/external/signup', user); 20 | } 21 | 22 | getUser() { 23 | return this.http.get(environment.apiUrl+'/user'); 24 | } 25 | 26 | /* update(user: User) { 27 | return this.http.put(`${config.apiUrl}/users/${user.id}`, user); 28 | } 29 | 30 | delete(id: number) { 31 | return this.http.delete(`${config.apiUrl}/users/${id}`); 32 | } */ 33 | } -------------------------------------------------------------------------------- /frontend/src/app/student/student-assigned/student-assigned.component.css: -------------------------------------------------------------------------------- 1 | .header { 2 | text-align: center; 3 | } 4 | 5 | .header h1 { 6 | font-family: serif; 7 | font-size: 38px; 8 | font-family: 'Times New Roman'; 9 | } 10 | 11 | .content { 12 | margin: 100px; 13 | } 14 | 15 | .margin25 { 16 | margin: 25px; 17 | } 18 | 19 | .upload { 20 | cursor: pointer; 21 | } 22 | 23 | .message { 24 | position: relative; 25 | } 26 | 27 | div.centered { width: 900px; } 28 | div.columns div { width: 300px; height: 100px; float: left; } 29 | 30 | .item { 31 | cursor:pointer; 32 | } 33 | .itemlist { 34 | font-size:16px; 35 | } 36 | 37 | #getDrafts { 38 | float:right; 39 | } 40 | 41 | dt { 42 | font-size:18px 43 | } 44 | 45 | dl { 46 | font-size:16px 47 | } 48 | 49 | P { 50 | font-size:16px; 51 | } 52 | 53 | #file { 54 | font-size:16px 55 | } 56 | 57 | .completed { 58 | color:rgb(8, 105, 8); 59 | cursor:pointer; 60 | } 61 | 62 | .not_completed { 63 | color:red 64 | } 65 | 66 | .material-icons { 67 | font-size:30px; 68 | } 69 | -------------------------------------------------------------------------------- /frontend/src/app/shared/guards/external.guard.ts: -------------------------------------------------------------------------------- 1 | 2 | import { Observable } from 'rxjs'; 3 | import { map, tap, take, catchError } from 'rxjs/operators'; 4 | import { Injectable } from '@angular/core'; 5 | import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; 6 | 7 | import { AuthenticationService } from '../services/authentication.service'; 8 | 9 | @Injectable({ providedIn: 'root' }) 10 | export class ExternalGuard implements CanActivate { 11 | constructor( 12 | private router: Router, 13 | private authenticationService: AuthenticationService 14 | ) {} 15 | 16 | canActivate(route: ActivatedRouteSnapshot , 17 | router: RouterStateSnapshot) 18 | :Observable|boolean { 19 | if(localStorage.getItem('Role')==="External" || localStorage.getItem('Role')==="External-Professor") 20 | return true; 21 | else { 22 | console.log("not auth"); 23 | this.router.navigate(['/']) 24 | return false; 25 | } 26 | 27 | // not logged in so redirect to login page with the return url 28 | } 29 | } -------------------------------------------------------------------------------- /frontend/README.md: -------------------------------------------------------------------------------- 1 | # Frontend 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.0.0. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). 28 | -------------------------------------------------------------------------------- /frontend/src/app/shared/guards/student.guard.ts: -------------------------------------------------------------------------------- 1 | 2 | import { Observable } from 'rxjs'; 3 | import { map, tap, take, catchError } from 'rxjs/operators'; 4 | import { Injectable } from '@angular/core'; 5 | import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; 6 | 7 | import { AuthenticationService } from '../services/authentication.service'; 8 | 9 | @Injectable({ providedIn: 'root' }) 10 | export class StudentGuard implements CanActivate { 11 | constructor( 12 | private router: Router, 13 | private authenticationService: AuthenticationService 14 | ) {} 15 | 16 | canActivate(route: ActivatedRouteSnapshot , 17 | router: RouterStateSnapshot) 18 | :Observable|boolean { 19 | if(localStorage.getItem('Role')==="Student") 20 | return true; 21 | else { 22 | console.log("not auth"); 23 | this.router.navigate(['/']) 24 | return false; 25 | } 26 | 27 | // not logged in so redirect to login page with the return url 28 | } 29 | } -------------------------------------------------------------------------------- /frontend/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, './coverage/frontend'), 20 | reports: ['html', 'lcovonly', 'text-summary'], 21 | fixWebpackSourcePaths: true 22 | }, 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: false, 30 | restartOnFileChange: true 31 | }); 32 | }; 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 GFOSS - Open Technologies Alliance (Οργανισμός Ανοιχτών Τεχνολογιών - EEΛΛΑΚ) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /frontend/src/app/shared/guards/professor.guard.ts: -------------------------------------------------------------------------------- 1 | 2 | import { Observable } from 'rxjs'; 3 | import { map, tap, take, catchError } from 'rxjs/operators'; 4 | import { Injectable } from '@angular/core'; 5 | import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; 6 | 7 | import { AuthenticationService } from '../services/authentication.service'; 8 | 9 | @Injectable({ providedIn: 'root' }) 10 | export class ProfessorGuard implements CanActivate { 11 | constructor( 12 | private router: Router, 13 | private authenticationService: AuthenticationService 14 | ) {} 15 | 16 | canActivate(route: ActivatedRouteSnapshot , 17 | router: RouterStateSnapshot) 18 | :Observable|boolean { 19 | if(localStorage.getItem('Role')==="Professor" || localStorage.getItem('Role')==="External-Professor") 20 | return true; 21 | else { 22 | console.log("not auth"); 23 | this.router.navigate(['/']) 24 | return false; 25 | } 26 | 27 | // not logged in so redirect to login page with the return url 28 | } 29 | } -------------------------------------------------------------------------------- /frontend/src/app/admin/create-university/create-university.component.html: -------------------------------------------------------------------------------- 1 | 2 |

Create a new Thesis

3 | 4 |

5 | Please complete the list below in order to create a new thesis. 6 |

7 |
8 |

9 |
10 |
11 | 12 | 13 |
14 |
Name is required
15 |
16 |
17 |
18 | 19 |
20 |
21 |
22 |
23 |

24 | University created successfully! 25 |

26 |
27 |
-------------------------------------------------------------------------------- /backend/routes/thesis.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const router = express.Router(); 3 | 4 | const thesisController = require('../controllers/thesis'); 5 | const checkAuth = require('../middleware/check-auth'); 6 | 7 | 8 | //URL: /thesis 9 | 10 | router.get("/", thesisController.thesis_get_all); //get all thesis //queries url: page,university,professor 11 | 12 | router.get("/professors",thesisController.getProfessors) //get all professors 13 | 14 | router.get("/files/:thesisId",thesisController.get_files) //get files of specified thesis 15 | router.get("/file/:fileId",thesisController.get_file_byId) // get specified file 16 | router.get("/completed", thesisController.thesis_completed_get_all); //get all completed thesis-digital repository 17 | router.get("/completed/file/:assigned_thesisId",thesisController.thesis_completed_file); // get completed thesis(not data) file; 18 | router.get("/completed/data/:fileId",thesisController.thesis_completed_data_file); //get completed thesis data file; 19 | 20 | 21 | router.get("/:thesisId",thesisController.get_byId) //get thesis by id 22 | 23 | 24 | 25 | //router.delete("/:userId", checkAuth, thesisController.user_delete); // 26 | //search thesis 27 | module.exports = router; 28 | -------------------------------------------------------------------------------- /frontend/src/app/sidenav/sidenav.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, DoCheck } from '@angular/core'; 2 | import { Router, ActivatedRoute } from '@angular/router'; 3 | 4 | import { AuthenticationService } from './../shared/services/authentication.service'; 5 | import { SharedService } from './../shared/services/shared.service'; 6 | import { AlertService } from './../shared/services/alert.service'; 7 | 8 | 9 | @Component({ 10 | selector: 'app-sidenav', 11 | templateUrl: './sidenav.component.html', 12 | styleUrls: ['./sidenav.component.css'] 13 | }) 14 | export class SidenavComponent implements OnInit , DoCheck { 15 | 16 | 17 | role; 18 | 19 | constructor( private router : Router 20 | ,private authenticationService: AuthenticationService, 21 | private route: ActivatedRoute, 22 | private sharedService:SharedService, 23 | private alertService:AlertService ) {} 24 | 25 | 26 | 27 | ngOnInit() { 28 | this.role=localStorage.getItem('Role'); 29 | console.log(this.role) 30 | this.router.events.subscribe((val) => { 31 | this.role=localStorage.getItem('Role'); 32 | }) 33 | 34 | } 35 | 36 | 37 | ngDoCheck() { 38 | this.role=localStorage.getItem('Role'); 39 | } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /frontend/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, async } from '@angular/core/testing'; 2 | import { RouterTestingModule } from '@angular/router/testing'; 3 | import { AppComponent } from './app.component'; 4 | 5 | describe('AppComponent', () => { 6 | beforeEach(async(() => { 7 | TestBed.configureTestingModule({ 8 | imports: [ 9 | RouterTestingModule 10 | ], 11 | declarations: [ 12 | AppComponent 13 | ], 14 | }).compileComponents(); 15 | })); 16 | 17 | it('should create the app', () => { 18 | const fixture = TestBed.createComponent(AppComponent); 19 | const app = fixture.debugElement.componentInstance; 20 | expect(app).toBeTruthy(); 21 | }); 22 | 23 | it(`should have as title 'frontend'`, () => { 24 | const fixture = TestBed.createComponent(AppComponent); 25 | const app = fixture.debugElement.componentInstance; 26 | expect(app.title).toEqual('frontend'); 27 | }); 28 | 29 | it('should render title in a h1 tag', () => { 30 | const fixture = TestBed.createComponent(AppComponent); 31 | fixture.detectChanges(); 32 | const compiled = fixture.debugElement.nativeElement; 33 | expect(compiled.querySelector('h1').textContent).toContain('Welcome to frontend!'); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /frontend/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Frontend 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /backend/models/assigned_thesis.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const Draft = require('./draft'); 3 | 4 | const assigned_thesisSchema = mongoose.Schema({ 5 | _id: mongoose.Schema.Types.ObjectId, 6 | thesis:{ type:mongoose.Schema.Types.ObjectId, ref:'Thesis'}, 7 | student: { type: mongoose.Schema.Types.ObjectId, ref:'User'}, 8 | professor: {type: mongoose.Schema.Types.ObjectId, ref:'User'}, 9 | university: {type: mongoose.Schema.Types.ObjectId, ref:'University'}, 10 | file: {type: mongoose.Schema.Types.ObjectId, ref:'FileThesis'}, 11 | created_time: Date, 12 | published: Date, //only if it is completed 13 | completed: Boolean, // completed thesis for digital repository 14 | supervisors: [{ type : mongoose.Schema.Types.ObjectId, ref: 'User' }], // array of supervisors 15 | external_supervisors: [{ type : mongoose.Schema.Types.ObjectId, ref: 'External' }], 16 | // supervisorModel: { 17 | // type: String, 18 | // enum: ['User', 'External'] 19 | // }, 20 | examiners: [{ type : mongoose.Schema.Types.ObjectId, ref: 'User' }], // array of examiners 21 | draft: [{ type:mongoose.Schema.Types.ObjectId, ref:'Draft' }] 22 | 23 | }); 24 | 25 | module.exports = mongoose.model('Assigned_Thesis', assigned_thesisSchema,'assigned_thesis'); -------------------------------------------------------------------------------- /frontend/src/app/shared/interceptors/http-error.interceptor.ts: -------------------------------------------------------------------------------- 1 | import { 2 | HttpEvent, 3 | HttpInterceptor, 4 | HttpHandler, 5 | HttpRequest, 6 | HttpResponse, 7 | HttpErrorResponse 8 | } from '@angular/common/http'; 9 | import { Observable, throwError } from 'rxjs'; 10 | import { retry, catchError } from 'rxjs/operators'; 11 | import { Injectable } from '@angular/core'; 12 | 13 | @Injectable() 14 | export class HttpErrorInterceptor implements HttpInterceptor { 15 | 16 | constructor() {} 17 | intercept(request: HttpRequest, next: HttpHandler): Observable> { 18 | return next.handle(request) 19 | .pipe( 20 | retry(1), 21 | catchError((error: HttpErrorResponse) => { 22 | let errorMessage = ''; 23 | if (error.error instanceof ErrorEvent) { 24 | // client-side error 25 | errorMessage = `Error: ${error.error.message}`; 26 | } else { 27 | // server-side error 28 | errorMessage = `Error Code: ${error.status}\nMessage: ${error.error.message}`; 29 | } 30 | window.alert(errorMessage); 31 | return throwError(errorMessage); 32 | }) 33 | ) 34 | } 35 | } -------------------------------------------------------------------------------- /frontend/webpack.config.ts: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | const path = require('path'); 4 | 5 | module.exports = { 6 | entry: './src/main.ts', 7 | module: { 8 | rules: [ 9 | { 10 | test: /\.ts$/, 11 | use: ['ts-loader', 'angular2-template-loader'], 12 | exclude: /node_modules/ 13 | }, 14 | { 15 | test: /\.(html|css)$/, 16 | loader: 'raw-loader' 17 | }, 18 | ] 19 | }, 20 | resolve: { 21 | extensions: ['.ts', '.js'], 22 | alias: { 23 | '@': path.resolve(__dirname, 'src/app/'), 24 | } 25 | }, 26 | plugins: [ 27 | new HtmlWebpackPlugin({ 28 | template: './src/index.html', 29 | filename: 'index.html', 30 | inject: 'body' 31 | }), 32 | new webpack.DefinePlugin({ 33 | // global app config object 34 | config: JSON.stringify({ 35 | apiUrl: 'http://localhost:3000' 36 | }) 37 | }) 38 | ], 39 | optimization: { 40 | splitChunks: { 41 | chunks: 'all', 42 | }, 43 | runtimeChunk: true 44 | }, 45 | devServer: { 46 | historyApiFallback: true 47 | } 48 | }; -------------------------------------------------------------------------------- /backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backend", 3 | "version": "1.0.0", 4 | "description": "The backend side for the Thesis Management System ", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "nodemon ./server.js" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/eellak/gsoc2019-tms.git" 13 | }, 14 | "keywords": [ 15 | "node", 16 | "api" 17 | ], 18 | "author": "Michail Chatzianastasis", 19 | "license": "MIT", 20 | "bugs": { 21 | "url": "https://github.com/eellak/gsoc2019-tms/issues" 22 | }, 23 | "homepage": "https://github.com/eellak/gsoc2019-tms#readme", 24 | "dependencies": { 25 | "bcrypt": "^3.0.6", 26 | "body-parser": "^1.19.0", 27 | "dotenv": "^8.0.0", 28 | "express": "^4.16.4", 29 | "express-fileupload": "^1.1.5", 30 | "express-rate-limit": "^5.0.0", 31 | "form-data": "^2.5.0", 32 | "formidable": "^1.2.1", 33 | "jsonwebtoken": "^8.5.1", 34 | "lodash": "^4.17.14", 35 | "mongodb": "^3.2.4", 36 | "mongoose": "^5.5.7", 37 | "mongoose-paginate-v2": "^1.3.0", 38 | "morgan": "^1.9.1", 39 | "multer": "^1.4.1", 40 | "nodemon": "^1.19.1", 41 | "passport": "^0.4.0", 42 | "passport-ldapauth": "^2.1.4", 43 | "passport-saml": "^1.1.0", 44 | "querystringify": "^2.1.1" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /backend/middleware/send-auth.js: -------------------------------------------------------------------------------- 1 | const jwt = require('jsonwebtoken'); 2 | const University=require('../models/university'); 3 | const mongoose = require("mongoose"); 4 | 5 | module.exports = (req, res, next) => { 6 | 7 | try { 8 | 9 | let university; 10 | console.log(req.headers) 11 | const token = req.headers.authorization.split(" ")[1]; 12 | const decoded = jwt.verify(token, process.env.JWT_KEY); 13 | req.userData = decoded; 14 | if(decoded.university!=null) { 15 | console.log("re") 16 | University.findById(decoded.university) 17 | .select('name') 18 | .exec() 19 | .then(university => { 20 | if(university!=null) { 21 | decoded.university=university.name; 22 | console.log(decoded); 23 | res.status(200).json({ 24 | userData:decoded 25 | }) 26 | } 27 | }) 28 | .catch(error=> { 29 | res.status(500).json({error:error}) 30 | }) 31 | } 32 | else { console.log("something") 33 | res.status(200).json({ 34 | userData:decoded 35 | }) 36 | } 37 | } catch (error) { 38 | return res.status(401).json({ 39 | message: 'Auth failed' 40 | }); 41 | } 42 | }; -------------------------------------------------------------------------------- /frontend/src/app/shared/guards/admin.guard.ts: -------------------------------------------------------------------------------- 1 | 2 | import { Observable } from 'rxjs'; 3 | import { map, tap, take, catchError } from 'rxjs/operators'; 4 | import { Injectable } from '@angular/core'; 5 | import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; 6 | 7 | import { AuthenticationService } from '../services/authentication.service'; 8 | 9 | @Injectable({ providedIn: 'root' }) 10 | export class AdminGuard implements CanActivate { 11 | constructor( 12 | private router: Router, 13 | private authenticationService: AuthenticationService 14 | ) {} 15 | 16 | canActivate(route: ActivatedRouteSnapshot , 17 | router: RouterStateSnapshot) 18 | :Observable|boolean { 19 | return this.authenticationService.isAdmin() 20 | .pipe(map( (data:any) => { 21 | console.log(data); 22 | console.log(data.message); 23 | if(data.message==="Authenticated") { 24 | return true; 25 | } 26 | else { 27 | console.log("not auth"); 28 | this.router.navigate(['/']) 29 | return false; 30 | } 31 | }) 32 | 33 | ) 34 | // not logged in so redirect to login page with the return url 35 | } 36 | } -------------------------------------------------------------------------------- /frontend/src/app/profile/profile.component.ts: -------------------------------------------------------------------------------- 1 | import { Router } from '@angular/router'; 2 | import { Component, OnInit } from '@angular/core'; 3 | import { first } from 'rxjs/operators'; 4 | 5 | 6 | import { AuthenticationService } from '../shared/services/authentication.service'; 7 | import { UserService } from '../shared/services/user.service'; 8 | import { AlertService } from '../shared/services/alert.service'; 9 | 10 | @Component({ 11 | selector: 'app-profile', 12 | templateUrl: './profile.component.html', 13 | styleUrls: ['./profile.component.css'] 14 | }) 15 | export class ProfileComponent implements OnInit { 16 | 17 | user:any={}; 18 | loading=false; 19 | isLoaded; 20 | 21 | constructor( private router: Router, 22 | private authenticationService: AuthenticationService, 23 | private userService: UserService, 24 | private alertService: AlertService) { } 25 | 26 | ngOnInit() { 27 | this.loading=true; 28 | this.userService.getUser() 29 | .subscribe( 30 | (data:any) => { 31 | //this.alertService.success('Get user information successful', true); 32 | this.user=data.userData; 33 | console.log(this.user); 34 | this.loading=false; 35 | this.isLoaded=true; 36 | }, 37 | error => { 38 | this.alertService.error(error); 39 | this.loading = false; 40 | }); 41 | 42 | } 43 | } 44 | 45 | 46 | -------------------------------------------------------------------------------- /frontend/src/app/profile/profile.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |

User Information

7 |
8 |
User Id:
person {{user.userId}}
9 |
10 |
Email:
email {{user.email}}
11 |
12 |
Name:
person_pin{{user.name}}
13 |
14 |
Lastname:
person_pin{{user.lastname}}
15 |
16 |
Role:
{{user.role}}
17 |
18 |
University:
school {{user.university}}
19 |
20 |
21 |
22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /frontend/src/app/shared/services/alert.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Router, NavigationStart } from '@angular/router'; 3 | import { Observable, Subject } from 'rxjs'; 4 | 5 | @Injectable({ providedIn: 'root' }) 6 | export class AlertService { 7 | private subject = new Subject(); 8 | private keepAfterNavigationChange = false; 9 | 10 | constructor(private router: Router) { 11 | // clear alert message on route change 12 | router.events.subscribe(event => { 13 | if (event instanceof NavigationStart) { 14 | if (this.keepAfterNavigationChange) { 15 | // only keep for a single location change 16 | this.keepAfterNavigationChange = false; 17 | } else { 18 | // clear alert 19 | this.subject.next(); 20 | } 21 | } 22 | }); 23 | } 24 | 25 | success(message: string, keepAfterNavigationChange = false) { 26 | this.keepAfterNavigationChange = keepAfterNavigationChange; 27 | this.subject.next({ type: 'success', text: message }); 28 | } 29 | 30 | error(message: string, keepAfterNavigationChange = false) { 31 | this.keepAfterNavigationChange = keepAfterNavigationChange; 32 | this.subject.next({ type: 'error', text: message }); 33 | } 34 | 35 | getMessage(): Observable { 36 | return this.subject.asObservable(); 37 | } 38 | } -------------------------------------------------------------------------------- /backend/routes/external.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const router = express.Router(); 3 | 4 | const ExternalController = require('../controllers/external'); 5 | const checkAuth = require('../middleware/check-auth'); 6 | 7 | 8 | //url: /external 9 | 10 | router.post("/signup", ExternalController.user_signup); 11 | 12 | router.post("/login", ExternalController.user_login); 13 | 14 | router.all("/*",checkAuth); 15 | 16 | router.get("/pending/accepted",ExternalController.get_accepted) // get all accepted pending thesis of userId (From different professors) returns from pending collection 17 | router.get("/pending/:pendingId",ExternalController.get_pending_byId); //get pending thesis by id 18 | router.get("/pending/:pendingId/accepted",ExternalController.get_accepted_byId) //get accepted pending thesis by Id 19 | router.post("/pending/:pendingId/accepted",ExternalController.confirm_pending,ExternalController.delete_all_pendings) // thesis is now confirmed for a specific professor 20 | 21 | router.get("/pending",ExternalController.get_pending); //get pending thesis of userId, returns from thesis collection 22 | router.post("/pending",ExternalController.create_pending); //create pending thesis 23 | 24 | router.post("/thesis/file/:thesisId",ExternalController.post_pdf) //post pdf of specified pending thesis 25 | router.put("/thesis/:thesisId",ExternalController.update_thesis) //update specified thesis 26 | router.delete("/file/:thesisId/:fileId",ExternalController.delete_file) //delete specified file 27 | module.exports = router; 28 | -------------------------------------------------------------------------------- /frontend/src/app/header/header.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, OnDestroy, HostListener } from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | import { AuthenticationService } from '../shared/services/authentication.service'; 4 | import { User } from '../shared/models/user.model'; 5 | 6 | 7 | 8 | @Component({ 9 | selector: 'app-header', 10 | templateUrl: './header.component.html', 11 | styleUrls: ['./header.component.css'] 12 | }) 13 | export class HeaderComponent implements OnInit { 14 | currentUser: User; 15 | message:any; 16 | 17 | constructor( 18 | private router: Router, 19 | private authenticationService: AuthenticationService 20 | ) { 21 | } 22 | 23 | 24 | 25 | ngOnInit() { 26 | } 27 | 28 | logout() { 29 | //this.authenticationService.logout(); 30 | //this.router.navigate(['/login']); 31 | const role=this.authenticationService.getRole() 32 | if(role==="External" || role==="Admin") { 33 | this.authenticationService.logout(); 34 | } 35 | else { 36 | this.authenticationService.sso_logout(); 37 | } 38 | } 39 | 40 | isLoggedIn() { 41 | return this.authenticationService.isLoggedIn(); 42 | } 43 | 44 | isAdmin() { 45 | if(localStorage.getItem('Role')==="Admin") 46 | return true; 47 | else 48 | return false; 49 | } 50 | 51 | isStudent() { 52 | if(localStorage.getItem('Role')==="Student") 53 | return true; 54 | else 55 | return false; 56 | } 57 | 58 | isProfessor() { 59 | if(localStorage.getItem('Role')==="Professor") 60 | return true; 61 | else 62 | return false; 63 | } 64 | 65 | 66 | 67 | } 68 | -------------------------------------------------------------------------------- /backend/routes/ldap_login.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const router = express.Router(); 3 | const passport= require("passport"); 4 | const mongoose = require("mongoose"); 5 | const app=express(); 6 | const auth=require("../controllers/ldapauth"); 7 | const bodyParser=require("body-parser"); 8 | const jwt=require("jsonwebtoken"); 9 | 10 | //url : /ldap 11 | app.use(passport.initialize()); 12 | app.use(passport.session()); 13 | 14 | router.get('/login', auth.setUniversity, 15 | passport.authenticate('ldapauth', { failureRedirect: '/', failureFlash: true }), 16 | function(req, res) { 17 | res.redirect('/'); 18 | } 19 | ); 20 | 21 | router.post("/login", 22 | bodyParser.urlencoded({ extended: false }), 23 | (req, res, next) => { 24 | passport.authenticate("ldapauth", { session: false , passReqToCallback: true }, (err, user) => { 25 | if(err) { 26 | console.log("Error"+err) 27 | } 28 | console.log('User to give sign in token is: ' + user) 29 | if(user){ 30 | const token = jwt.sign( 31 | { 32 | email: user.email, 33 | userId: user._id, 34 | role: user.role, 35 | university: user.university, 36 | name: user.name, 37 | lastname: user.lastname 38 | }, 39 | process.env.JWT_KEY, 40 | { expiresIn: '5h' } 41 | ); 42 | req.user = user; 43 | req.token=token; 44 | return res.status(200).json({ 45 | message: "Auth successful", 46 | token: token, 47 | role: user.role, 48 | university: user.university 49 | }); 50 | } 51 | next(); 52 | })(req, res, next); 53 | }); 54 | 55 | module.exports = router; -------------------------------------------------------------------------------- /backend/controllers/university.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const University= require('../models/university'); 3 | 4 | 5 | exports.get_all=(req,res,next) => { 6 | var perPage = 6 7 | var page = req.query.page || 1 8 | var query= {pending:false} 9 | if(req.query.university!=null) 10 | query['university']=req.query.university 11 | var count; 12 | console.log(query) 13 | query={} 14 | University.countDocuments(query) 15 | .then(result=> { 16 | count=result 17 | University.find(query) 18 | .skip((perPage * page) - perPage) 19 | .limit(perPage) 20 | .exec() 21 | .then(docs => { 22 | const response = { 23 | docs:docs, 24 | count:count, 25 | pages: Math.ceil(count / perPage), 26 | } 27 | res.status(200).json(response); 28 | }) 29 | }) 30 | .catch(err => { 31 | console.log(err+"wjat"); 32 | res.status(500).json({ 33 | error: err 34 | }); 35 | }) 36 | } 37 | 38 | exports.get_all_noPages=(req,res,next) => { 39 | University.find() 40 | .exec() 41 | .then(docs => { 42 | res.status(200).json(docs); 43 | }) 44 | .catch(err => { 45 | console.log(err+"wjat"); 46 | res.status(500).json({ 47 | error: err 48 | }); 49 | }) 50 | } 51 | 52 | exports.get_byId= (req,res,next) => { 53 | University.findById({_id:req.params.universityId}) 54 | .exec() 55 | .then(doc => { 56 | if(doc!=null) 57 | res.status(200).json(doc); 58 | else 59 | res.status(404).json({message : 'University not found'}) 60 | }) 61 | .catch(err => { 62 | console.log(err+"wjat"); 63 | res.status(500).json({ 64 | error: err 65 | }); 66 | }) 67 | } 68 | -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "webpack --mode production", 8 | "test": "ng test", 9 | "lint": "ng lint", 10 | "e2e": "ng e2e" 11 | }, 12 | "private": true, 13 | "dependencies": { 14 | "@angular/animations": "^8.0.3", 15 | "@angular/cdk": "^8.2.3", 16 | "@angular/common": "^8.0.3", 17 | "@angular/compiler": "^8.0.3", 18 | "@angular/core": "^8.0.3", 19 | "@angular/forms": "^8.0.3", 20 | "@angular/material": "^8.2.3", 21 | "@angular/platform-browser": "^8.0.3", 22 | "@angular/platform-browser-dynamic": "^8.0.3", 23 | "@angular/router": "^8.0.3", 24 | "@auth0/angular-jwt": "^2.1.2", 25 | "@ng-bootstrap/ng-bootstrap": "^5.1.5", 26 | "auth0-sso-login": "^4.0.159", 27 | "bootstrap": "^3.4.1", 28 | "crypto": "^1.0.1", 29 | "hammerjs": "^2.0.8", 30 | "jquery": "^3.4.1", 31 | "lodash": "^4.17.15", 32 | "ngx-autosize": "^1.7.2", 33 | "querystringify": "^2.1.1", 34 | "rxjs": "~6.4.0", 35 | "tslib": "^1.10.0", 36 | "zone.js": "~0.9.1" 37 | }, 38 | "devDependencies": { 39 | "@angular-devkit/build-angular": "^0.800.6", 40 | "@angular/cli": "^8.0.6", 41 | "@angular/compiler-cli": "^8.0.3", 42 | "@angular/language-service": "^8.0.3", 43 | "@types/jasmine": "^3.3.16", 44 | "@types/jasminewd2": "^2.0.8", 45 | "@types/node": "~8.9.4", 46 | "codelyzer": "^5.2.1", 47 | "jasmine-core": "~3.4.0", 48 | "jasmine-spec-reporter": "~4.2.1", 49 | "karma": "~4.1.0", 50 | "karma-chrome-launcher": "~2.2.0", 51 | "karma-coverage-istanbul-reporter": "^2.0.6", 52 | "karma-jasmine": "~2.0.1", 53 | "karma-jasmine-html-reporter": "^1.5.1", 54 | "protractor": "~5.4.0", 55 | "ts-node": "~7.0.0", 56 | "tslint": "~5.15.0", 57 | "typescript": "~3.4.3" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /frontend/src/app/header/header.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/routes/admin.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const router = express.Router(); 3 | 4 | const adminController = require('../controllers/admin'); 5 | const checkAuth = require('../middleware/check-auth'); 6 | const externalController= require('../controllers/external') 7 | 8 | //URL: /admin 9 | 10 | router.get("/",checkAuth,adminController.is_admin2); //check if user is admin 11 | 12 | router.all("/*",checkAuth,adminController.is_admin); // check if user is admin. For all routes 13 | 14 | router.post("/create_external",externalController.user_signup); //create external 15 | router.get("/get_externals",adminController.get_externals); //get all externals 16 | router.get("/get_external/:userId",adminController.get_external_byId); //get external by id 17 | router.delete("/delete_external/:userId",adminController.delete_external); //delete external 18 | router.get("/get_not_active_externals",adminController.get_not_active_externals); //get all not active externals; 19 | router.get("/activate_external/:userId",adminController.activate_external); //activate external with the specified id; 20 | router.put("/update_external/:userId",adminController.update_external); //update external 21 | 22 | router.get("/get_users",adminController.get_users); //get all users 23 | router.get("/get_user/:userId",adminController.get_user_byId); //get user by id 24 | router.delete("/delete_user/:userId",adminController.delete_user); //delete user 25 | router.put("/update_user/:userId",adminController.update_user); //update user 26 | 27 | router.post("/application_period",adminController.application_period); // specify application period 28 | 29 | router.post("/create_university",adminController.create_university) // create university 30 | router.delete("/delete_university/:universityId",adminController.delete_university) //delete university 31 | 32 | //router.get("/completed", adminController.thesis_completed_get_all); // 33 | 34 | 35 | 36 | module.exports = router; 37 | -------------------------------------------------------------------------------- /frontend/src/app/thesis/thesis-professor/thesis-professor.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { UrlSegment, Router, ActivatedRoute } from '@angular/router'; 3 | import { Subscription } from 'rxjs'; 4 | 5 | import { AuthenticationService } from '../../shared/services/authentication.service'; 6 | import { SharedService } from '../../shared/services/shared.service'; 7 | import { AlertService } from '../../shared/services/alert.service'; 8 | 9 | @Component({ 10 | selector: 'app-thesis-professor', 11 | templateUrl: './thesis-professor.component.html', 12 | styleUrls: ['./thesis-professor.component.css'] 13 | }) 14 | export class ThesisProfessorComponent implements OnInit { 15 | 16 | theses:any=[]; 17 | loading=false; 18 | pager:any={} 19 | id; 20 | isLoaded:boolean; 21 | private routeSub: Subscription; 22 | 23 | 24 | constructor( private router : Router 25 | ,private authenticationService: AuthenticationService, 26 | private route: ActivatedRoute, 27 | private sharedService:SharedService, 28 | private alertService:AlertService ) {} 29 | 30 | ngOnInit() { 31 | this.routeSub = this.route.params.subscribe(params => { 32 | this.id=params['id']; 33 | this.loading=true; 34 | this.getThesis(1,this.id); 35 | }) 36 | } 37 | 38 | getThesis(page,professor_id) { 39 | this.sharedService.getThesisOfProfessor(page,professor_id) 40 | .subscribe( 41 | (data:any) => { 42 | //this.alertService.success('Get user information successful', true); 43 | this.theses=data.docs; 44 | console.log(this.theses) 45 | this.pager.count=data.count; 46 | this.pager.pages= data.pages; 47 | this.pager.currentPage=page; 48 | this.loading=false; 49 | }, 50 | error => { 51 | this.alertService.error(error); 52 | this.loading = false; 53 | }); 54 | } 55 | } 56 | 57 | -------------------------------------------------------------------------------- /frontend/src/app/secretariat/secretariat-professors/secretariat-professors.component.ts: -------------------------------------------------------------------------------- 1 | import { AlertService } from './../../shared/services/alert.service'; 2 | import { SecretariatService } from './../../shared/services/secretariat.service'; 3 | import { Component, OnInit } from '@angular/core'; 4 | import {Sort} from '@angular/material/sort'; 5 | 6 | @Component({ 7 | selector: 'app-secretariat-professors', 8 | templateUrl: './secretariat-professors.component.html', 9 | styleUrls: ['./secretariat-professors.component.css'] 10 | }) 11 | export class SecretariatProfessorsComponent implements OnInit { 12 | 13 | loading=false; 14 | count=0; 15 | pager:any={} 16 | sortedData:any=[]; 17 | assigned; 18 | not_assigned; 19 | 20 | constructor( private secretariatService:SecretariatService, 21 | private alertService:AlertService 22 | ) { } 23 | 24 | ngOnInit() { 25 | this.loading=true; 26 | this.getProfessors(1); 27 | 28 | } 29 | 30 | compare(a: number | string | boolean, b: number | string | boolean, isAsc: boolean) { 31 | return (a < b ? -1 : 1) * (isAsc ? 1 : -1); 32 | } 33 | 34 | 35 | sortData(sort: Sort) { 36 | const data = this.sortedData.slice(); 37 | this.sortedData = data.sort((a, b) => { 38 | const isAsc = sort.direction === 'asc'; 39 | switch (sort.active) { 40 | case 'name': return this.compare(a.name, b.name, isAsc); 41 | case 'lastname': return this.compare(a.lastname, b.lastname, isAsc); 42 | case 'email': return this.compare(a.email, b.email, isAsc); 43 | default: return 0; 44 | } 45 | }); 46 | 47 | } 48 | 49 | getProfessors(page) { 50 | this.secretariatService.getProfessors(page) 51 | .subscribe( 52 | (data:any) => { 53 | console.log(data); 54 | this.count=data.count; 55 | this.pager.count=data.count; 56 | this.pager.pages= data.pages; 57 | this.pager.currentPage=page; 58 | this.sortedData=data.docs; 59 | this.loading=false; 60 | }, 61 | error => { 62 | this.alertService.error(error); 63 | this.loading = false; 64 | }); 65 | } 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /frontend/src/app/shared/services/external.service.ts: -------------------------------------------------------------------------------- 1 | import { environment } from './../../../environments/environment'; 2 | import { Injectable } from '@angular/core'; 3 | import { HttpClient, HttpHandler, HttpErrorResponse } from '@angular/common/http'; 4 | import { map } from 'rxjs/operators'; 5 | import {Observable} from 'rxjs'; 6 | 7 | 8 | 9 | @Injectable({ providedIn: 'root' }) 10 | export class ExternalService { 11 | 12 | constructor(private http: HttpClient) {} 13 | 14 | 15 | getPendings(page) { 16 | return this.http.get(environment.apiUrl+`/external/pending?page=${page}`) 17 | } 18 | 19 | getPendingById(pendingId) { 20 | return this.http.get(environment.apiUrl+`/external/pending/${pendingId}`) 21 | } 22 | 23 | createPending(thesis) { 24 | return this.http.post(environment.apiUrl+`/external/pending`,{thesis:thesis}) 25 | } 26 | 27 | deletePending(thesis) { 28 | return this.http.delete(environment.apiUrl+`/external/pending/${thesis._id}`) 29 | } 30 | 31 | //get accepted pending 32 | 33 | getAcceptedPendings() { 34 | return this.http.get(environment.apiUrl+`/external/pending/accepted`); 35 | } 36 | 37 | getAcceptedPendingById(id) { 38 | return this.http.get(environment.apiUrl+`/external/pending/${id}/accepted`); 39 | } 40 | 41 | postAcceptedPending(id) { 42 | return this.http.post(environment.apiUrl+`/external/pending/${id}/accepted`,{}); 43 | } 44 | 45 | postPdfThesis(fileToUpload: File, ThesisId): Observable { 46 | const endpoint = environment.apiUrl+`/external/thesis/file/${ThesisId}`; 47 | const formData: FormData = new FormData(); 48 | formData.append('pdf', fileToUpload, fileToUpload.name); 49 | return this.http 50 | .post(endpoint, formData,{responseType:'arraybuffer' as 'json'}) 51 | .pipe(map(() => { return true; })) 52 | } 53 | 54 | //update thesis 55 | putThesis(id,thesis) { 56 | return this.http.put(environment.apiUrl+`/external/thesis/${id}`,{thesis:thesis}); 57 | } 58 | 59 | deleteFile(thesisId,fileId) { 60 | return this.http.delete(environment.apiUrl+`/external/file/${thesisId}/${fileId}`) 61 | } 62 | 63 | 64 | 65 | } -------------------------------------------------------------------------------- /frontend/src/app/admin/create-university/create-university.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { FormBuilder, FormGroup, Validators } from '@angular/forms'; 3 | import { Router, ActivatedRoute } from '@angular/router'; 4 | import { first } from 'rxjs/operators'; 5 | import { AlertService } from '../../shared/services/alert.service'; 6 | import {AuthenticationService} from '../../shared/services/authentication.service'; 7 | import { AdminService } from './../../shared/services/admin.service'; 8 | 9 | @Component({ 10 | selector: 'app-create-university', 11 | templateUrl: './create-university.component.html', 12 | styleUrls: ['./create-university.component.css'] 13 | }) 14 | export class CreateUniversityComponent implements OnInit { 15 | CreateUniversityForm: FormGroup; 16 | loading = false; 17 | submitted = false; 18 | returnUrl: string; 19 | message 20 | 21 | constructor(private formBuilder: FormBuilder, 22 | private route: ActivatedRoute, 23 | private router: Router, 24 | private alertService: AlertService, 25 | private adminService: AdminService 26 | ) { } 27 | 28 | ngOnInit() { 29 | this.CreateUniversityForm = this.formBuilder.group({ 30 | name: ['', Validators.required] 31 | }); 32 | 33 | // get return url from route parameters or default to '/' 34 | this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/'; 35 | 36 | } 37 | 38 | get f() { return this.CreateUniversityForm.controls; } 39 | 40 | 41 | onSubmit() { 42 | this.submitted = true; 43 | 44 | // stop here if form is invalid 45 | if (this.CreateUniversityForm.invalid) { 46 | return; 47 | } 48 | this.loading = true; 49 | this.adminService.createUniversity(this.f.name.value) 50 | .subscribe( 51 | (data:any) => { 52 | this.message=data; 53 | setTimeout(() => { 54 | this.router.navigate(['../university'], { relativeTo: this.route}) 55 | } 56 | ,1500); 57 | }, 58 | error => { 59 | console.log(error) 60 | this.alertService.error(error); 61 | this.loading = false; 62 | }); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /frontend/src/app/admin/admin-university/admin-university.component.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 21 |
3 |

Externals Results

4 |
University IdschoolNameDelete
{{university._id}}{{university.name}} 18 |
22 | 23 | 24 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /frontend/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tslint:recommended", 3 | "rules": { 4 | "array-type": false, 5 | "arrow-parens": false, 6 | "deprecation": { 7 | "severity": "warn" 8 | }, 9 | "component-class-suffix": true, 10 | "contextual-lifecycle": true, 11 | "directive-class-suffix": true, 12 | "directive-selector": [ 13 | true, 14 | "attribute", 15 | "app", 16 | "camelCase" 17 | ], 18 | "component-selector": [ 19 | true, 20 | "element", 21 | "app", 22 | "kebab-case" 23 | ], 24 | "import-blacklist": [ 25 | true, 26 | "rxjs/Rx" 27 | ], 28 | "interface-name": false, 29 | "max-classes-per-file": false, 30 | "max-line-length": [ 31 | true, 32 | 140 33 | ], 34 | "member-access": false, 35 | "member-ordering": [ 36 | true, 37 | { 38 | "order": [ 39 | "static-field", 40 | "instance-field", 41 | "static-method", 42 | "instance-method" 43 | ] 44 | } 45 | ], 46 | "no-consecutive-blank-lines": false, 47 | "no-console": [ 48 | true, 49 | "debug", 50 | "info", 51 | "time", 52 | "timeEnd", 53 | "trace" 54 | ], 55 | "no-empty": false, 56 | "no-inferrable-types": [ 57 | true, 58 | "ignore-params" 59 | ], 60 | "no-non-null-assertion": true, 61 | "no-redundant-jsdoc": true, 62 | "no-switch-case-fall-through": true, 63 | "no-use-before-declare": true, 64 | "no-var-requires": false, 65 | "object-literal-key-quotes": [ 66 | true, 67 | "as-needed" 68 | ], 69 | "object-literal-sort-keys": false, 70 | "ordered-imports": false, 71 | "quotemark": [ 72 | true, 73 | "single" 74 | ], 75 | "trailing-comma": false, 76 | "no-conflicting-lifecycle": true, 77 | "no-host-metadata-property": true, 78 | "no-input-rename": true, 79 | "no-inputs-metadata-property": true, 80 | "no-output-native": true, 81 | "no-output-on-prefix": true, 82 | "no-output-rename": true, 83 | "no-outputs-metadata-property": true, 84 | "template-banana-in-box": true, 85 | "template-no-negated-async": true, 86 | "use-lifecycle-interface": true, 87 | "use-pipe-transform-interface": true 88 | }, 89 | "rulesDirectory": [ 90 | "codelyzer" 91 | ] 92 | } -------------------------------------------------------------------------------- /frontend/src/app/professor/professor-thesis-edit/professor-thesis-edit.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |

Thesis Edit

7 |
8 |

9 |

Created Time:
{{thesis.created_time | date}}
10 |
11 |
Title:
12 |
Description:
13 |
14 | 19 |
20 |
21 |
22 |
Prerequisites:
23 |
24 |
University:
{{thesis.university?.name}}
25 | 26 | 27 | 28 | 29 |
30 |
31 |

32 | Thesis updated successfully! 33 |

34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | -------------------------------------------------------------------------------- /frontend/src/app/professor/professor-thesis-edit/professor-thesis-edit.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit} from '@angular/core'; 2 | import { Router, ActivatedRoute } from '@angular/router'; 3 | import { Subscription } from 'rxjs'; 4 | import { AlertService } from '../../shared/services/alert.service'; 5 | import { ProfessorService } from './../../shared/services/professor.service'; 6 | 7 | 8 | @Component({ 9 | selector: 'app-professor-thesis-edit', 10 | templateUrl: './professor-thesis-edit.component.html', 11 | styleUrls: ['./professor-thesis-edit.component.css'] 12 | }) 13 | export class ProfessorThesisEditComponent implements OnInit { 14 | fontsize="16px" 15 | private routeSub: Subscription; 16 | thesis={}; 17 | professor={}; 18 | creator_student; 19 | creator_external; 20 | loading=false; 21 | pager:any={} 22 | id; 23 | isLoaded:boolean; 24 | message 25 | constructor( 26 | private router : Router, 27 | private route: ActivatedRoute, 28 | private professorService:ProfessorService, 29 | private alertService:AlertService ) {} 30 | 31 | 32 | 33 | 34 | 35 | ngOnInit() { 36 | this.routeSub = this.route.params.subscribe(params => { 37 | this.id=params['id']; 38 | this.professorService.getThesisById(this.id) 39 | .subscribe( 40 | (data:any) => { 41 | //this.alertService.success('Get user information successful', true); 42 | this.thesis=data; 43 | this.professor=data.professor; 44 | this.creator_external=data.creator_external; 45 | this.creator_student=data.creator_student; 46 | console.log(this.thesis) 47 | this.isLoaded=true; 48 | }, 49 | error => { 50 | this.alertService.error(error); 51 | this.loading = false; 52 | }); 53 | }); 54 | } 55 | 56 | 57 | 58 | onSave() { 59 | this.professorService.putThesis(this.id,this.thesis) 60 | .subscribe( 61 | (data:any) => { 62 | console.log(data) 63 | this.message=data; 64 | setTimeout(() => { 65 | this.router.navigate(['../../thesis'], { relativeTo: this.route}) 66 | } 67 | ,1500); 68 | 69 | }, 70 | error => { 71 | this.alertService.error(error); 72 | } 73 | ) 74 | } 75 | 76 | onCancel() { 77 | this.ngOnInit(); 78 | } 79 | 80 | ngOnDestroy() { 81 | this.routeSub.unsubscribe(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /frontend/src/app/login/login-external/login-external.component.html: -------------------------------------------------------------------------------- 1 | 2 |

External Login

3 |
4 |
5 |
6 | 7 | Email 8 | 9 | 10 | Email is required 11 | Not a valid email 12 | 13 | 14 |
15 |
16 | 17 | Password 18 | 19 | 20 | Password is required 21 | 22 | 23 |
24 |
25 | 26 | 27 | Register 28 |
29 |
30 |
-------------------------------------------------------------------------------- /frontend/src/app/secretariat/secretariat-professors/secretariat-professors.component.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
3 | 4 |

Professors of university:

personNamepersonLastnameemailEmailbookTheses of professor
{{professor.name}}{{professor.lastname}}{{professor.email}} Click here to see theses
25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /frontend/src/app/login/login-external/login-external.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { FormBuilder, FormGroup, Validators } from '@angular/forms'; 3 | import { Router, ActivatedRoute } from '@angular/router'; 4 | import { first } from 'rxjs/operators'; 5 | import { AlertService } from '../../shared/services/alert.service'; 6 | import {AuthenticationService} from '../../shared/services/authentication.service'; 7 | 8 | @Component({ 9 | selector: 'app-login-external', 10 | templateUrl: './login-external.component.html', 11 | styleUrls: ['./login-external.component.css'] 12 | }) 13 | export class LoginExternalComponent implements OnInit { 14 | loginForm: FormGroup; 15 | loading = false; 16 | submitted = false; 17 | returnUrl: string; 18 | 19 | 20 | constructor( 21 | private formBuilder: FormBuilder, 22 | private route: ActivatedRoute, 23 | private router: Router, 24 | private authenticationService: AuthenticationService, 25 | private alertService: AlertService 26 | ) 27 | { 28 | // redirect to home if already logged in 29 | if (this.authenticationService.isLoggedIn()) { 30 | this.router.navigate(['/']); 31 | } 32 | } 33 | 34 | ngOnInit() { 35 | this.loginForm = this.formBuilder.group({ 36 | email: ['', Validators.compose([Validators.required, Validators.pattern('^[^\\s@]+@[^\\s@]+\\.[^\\s@]{2,}$')])], 37 | password: ['', Validators.required] 38 | }); 39 | 40 | // get return url from route parameters or default to '/' 41 | this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/'; 42 | 43 | } 44 | 45 | // convenience getter for easy access to form fields 46 | get f() { return this.loginForm.controls; } 47 | 48 | onSubmit() { 49 | this.submitted = true; 50 | 51 | // stop here if form is invalid 52 | if (this.loginForm.invalid) { 53 | return; 54 | } 55 | 56 | this.loading = true; 57 | this.authenticationService.login(this.f.email.value, this.f.password.value) 58 | .pipe(first()) 59 | .subscribe( 60 | data => { 61 | this.router.navigate([this.returnUrl]); 62 | }, 63 | error => { 64 | console.log(error) 65 | this.alertService.error(error); 66 | this.loading = false; 67 | }); 68 | } 69 | } 70 | 71 | -------------------------------------------------------------------------------- /frontend/src/app/register-external/register-external.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | import { FormBuilder, FormGroup, Validators, EmailValidator } from '@angular/forms'; 4 | import { first } from 'rxjs/operators'; 5 | import { FormsModule, ReactiveFormsModule } from '@angular/forms'; 6 | 7 | 8 | import { AuthenticationService } from '../shared/services/authentication.service'; 9 | import { AlertService } from '../shared/services/alert.service'; 10 | import {UserService} from '../shared/services/user.service'; 11 | 12 | @Component({ 13 | selector: 'app-register-external', 14 | templateUrl: './register-external.component.html', 15 | styleUrls: ['./register-external.component.css'] 16 | }) 17 | export class RegisterExternalComponent implements OnInit { 18 | 19 | registerForm: FormGroup; 20 | loading = false; 21 | submitted = false; 22 | message; 23 | 24 | constructor( 25 | private formBuilder: FormBuilder, 26 | private router: Router, 27 | private authenticationService: AuthenticationService, 28 | private userService: UserService, 29 | private alertService: AlertService 30 | ) { 31 | // redirect to home if already logged in 32 | if (this.authenticationService.isLoggedIn()) { 33 | this.router.navigate(['/']); 34 | } 35 | } 36 | 37 | ngOnInit() { 38 | this.registerForm = this.formBuilder.group({ 39 | email: ['', Validators.compose([Validators.required, Validators.pattern('^[^\\s@]+@[^\\s@]+\\.[^\\s@]{2,}$')])], 40 | name: ['', Validators.required], 41 | lastname: ['', Validators.required], 42 | password: ['', [Validators.required, Validators.required]] 43 | }); 44 | } 45 | 46 | // convenience getter for easy access to form fields 47 | get f() { return this.registerForm.controls; } 48 | 49 | onSubmit() { 50 | this.submitted = true; 51 | 52 | // stop here if form is invalid 53 | if (this.registerForm.invalid) { 54 | return; 55 | } 56 | 57 | this.loading = true; 58 | this.userService.register(this.registerForm.value) 59 | .pipe(first()) 60 | .subscribe( 61 | data => { 62 | this.message="success"; 63 | setTimeout(() => { 64 | this.router.navigate(['/login-external']); 65 | } 66 | ,3000); 67 | }, 68 | error => { 69 | this.loading = false; 70 | }); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /frontend/src/app/professor/professor-thesis/professor-thesis.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit,ViewChild } from '@angular/core'; 2 | import { AlertService } from './../../shared/services/alert.service'; 3 | import { ProfessorService } from './../../shared/services/professor.service'; 4 | import {Sort} from '@angular/material/sort'; 5 | 6 | @Component({ 7 | selector: 'app-professor-thesis', 8 | templateUrl: './professor-thesis.component.html', 9 | styleUrls: ['./professor-thesis.component.css'] 10 | }) 11 | export class ProfessorThesisComponent implements OnInit { 12 | loading=false; 13 | count=0; 14 | pager:any={} 15 | sortedData:any=[]; 16 | 17 | 18 | 19 | constructor(private professorService:ProfessorService, private alertService:AlertService) { 20 | } 21 | 22 | ngOnInit() { 23 | this.loading=true; 24 | this.getThesis(1) 25 | } 26 | 27 | compare(a: number | string | boolean, b: number | string | boolean, isAsc: boolean) { 28 | return (a < b ? -1 : 1) * (isAsc ? 1 : -1); 29 | } 30 | 31 | 32 | sortData(sort: Sort) { 33 | const data = this.sortedData.slice(); 34 | this.sortedData = data.sort((a, b) => { 35 | const isAsc = sort.direction === 'asc'; 36 | console.log(a.title) 37 | switch (sort.active) { 38 | case 'created_time': return this.compare(a.created_time, b.created_time, isAsc); 39 | case 'title': return this.compare(a.title, b.title, isAsc); 40 | case 'assigned': return this.compare(a.assigned, b.assigned, isAsc); 41 | default: return 0; 42 | } 43 | }); 44 | } 45 | 46 | getThesis(page) { 47 | this.professorService.getThesis(page) 48 | .subscribe( 49 | (data:any) => { 50 | //this.alertService.success('Get user information successful', true); 51 | this.count=data.count; 52 | this.pager.count=data.count; 53 | this.pager.pages= data.pages; 54 | this.pager.currentPage=page; 55 | this.sortedData=data.theses; 56 | this.loading=false; 57 | }, 58 | error => { 59 | this.alertService.error(error); 60 | this.loading = false; 61 | }); 62 | } 63 | 64 | deleteThesis(thesis) { 65 | if(confirm("Are you sure to delete thesis: "+thesis.title)) { 66 | this.professorService.deleteThesis(thesis) 67 | .subscribe( 68 | (data:any) => { 69 | console.log(data) 70 | this.getThesis(this.pager.currentPage) 71 | }, 72 | error => { 73 | this.alertService.error(error) 74 | this.loading=false 75 | } 76 | 77 | ) 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /frontend/src/app/home/home.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |

Welcome to TMS

4 |

You can get started by browsing available theses:

5 |
6 | 7 |
8 | 9 |
10 |

Search theses by university

11 |
12 | 13 | 15 | 16 | 17 | {{university.name}} 18 | 19 | 20 | 21 |
22 | 23 |
24 |
25 |
26 |
27 | 28 | 29 |
30 |

Search theses by professor

31 | 32 |
34 | 35 | 37 | 38 | 39 | {{professor.name}} {{professor.lastname}} 40 | 41 | 42 | 43 |
44 | 45 |
46 |
47 | 48 |
49 |
50 | 51 |
52 |
53 |

Or you can propose you own!

54 |
-------------------------------------------------------------------------------- /frontend/src/app/student/student-create-pending/student-create-pending.component.ts: -------------------------------------------------------------------------------- 1 | import { StudentService } from './../../shared/services/student.service'; 2 | import { ProfessorService } from './../../shared/services/professor.service'; 3 | import { Component, OnInit } from '@angular/core'; 4 | import { FormBuilder, FormGroup, Validators } from '@angular/forms'; 5 | import { Router, ActivatedRoute } from '@angular/router'; 6 | import { first } from 'rxjs/operators'; 7 | import { AlertService } from '../../shared/services/alert.service'; 8 | import {AuthenticationService} from '../../shared/services/authentication.service'; 9 | 10 | 11 | @Component({ 12 | selector: 'app-student-create-pending', 13 | templateUrl: './student-create-pending.component.html', 14 | styleUrls: ['./student-create-pending.component.css'] 15 | }) 16 | export class StudentCreatePendingComponent implements OnInit { 17 | createThesisForm: FormGroup; 18 | description; 19 | thesis={}; 20 | message; 21 | 22 | constructor( 23 | private formBuilder: FormBuilder, 24 | private route: ActivatedRoute, 25 | private router: Router, 26 | private authenticationService: AuthenticationService, 27 | private alertService: AlertService, 28 | private studentService:StudentService 29 | ) { } 30 | 31 | ngOnInit() { 32 | this.createThesisForm = this.formBuilder.group({ 33 | title: ['', Validators.required], 34 | prerequisites: ['', Validators.required], 35 | tags: ['', Validators.required], 36 | description: ['', Validators.required] 37 | 38 | 39 | }); 40 | } 41 | 42 | get f() { return this.createThesisForm.controls; } 43 | 44 | onSubmit() { 45 | if (this.createThesisForm.invalid) { 46 | console.log("invalid form") 47 | return; 48 | } 49 | this.thesis['title']=this.f.title.value; 50 | this.thesis['description']=this.f.description.value; 51 | this.thesis['tags']=this.f.tags.value; 52 | this.thesis['prerequisites']=this.f.prerequisites.value; 53 | this.thesis['created_time']=new Date(); 54 | this.thesis['assigned']=false; 55 | this.thesis['university']=localStorage.getItem('University'); 56 | this.studentService.createPending(this.thesis) 57 | .subscribe( 58 | (data:any) => { 59 | console.log(data) 60 | this.message=data.message 61 | setTimeout(() => { 62 | this.router.navigate(['/student/pending']) 63 | } 64 | ,1500); 65 | }, 66 | error => { 67 | console.log(error) 68 | this.alertService.error(error); 69 | }); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /frontend/src/app/shared/services/shared.service.ts: -------------------------------------------------------------------------------- 1 | import { environment } from './../../../environments/environment'; 2 | import { Injectable } from '@angular/core'; 3 | import { HttpClient, HttpHandler, HttpErrorResponse } from '@angular/common/http'; 4 | import { map, tap, take, catchError } from 'rxjs/operators'; 5 | 6 | 7 | import { BehaviorSubject, Observable, throwError } from 'rxjs'; 8 | import { 9 | CanActivate, 10 | ActivatedRouteSnapshot, 11 | RouterStateSnapshot, 12 | Router, 13 | UrlTree 14 | } from '@angular/router'; 15 | 16 | 17 | @Injectable({ providedIn: 'root' }) 18 | export class SharedService { 19 | 20 | private searchQuery = new BehaviorSubject(''); 21 | currentQuery = this.searchQuery.asObservable(); 22 | 23 | 24 | constructor(private http: HttpClient) { } 25 | 26 | changeQuery(searchQuery: string) { 27 | this.searchQuery.next(searchQuery) 28 | } 29 | 30 | getUniversities(page) { 31 | return this.http.get(environment.apiUrl + `/university?page=${page}`); 32 | } 33 | 34 | getUniversitiesNoPages() { 35 | return this.http.get(environment.apiUrl + `/university/noPages`); 36 | } 37 | 38 | getThesis(page?,university?,professor?) { 39 | return this.http.get(environment.apiUrl + `/thesis?page=${page}&university=${university}&professor=${professor}`); 40 | } 41 | 42 | getCompletedThesis(page) { 43 | return this.http.get(environment.apiUrl + `/thesis/completed?page=${page}`); 44 | } 45 | 46 | getCompletedFileThesis(thesisId) { 47 | return this.http.get(environment.apiUrl + `/thesis/completed/file/${thesisId}`) 48 | } 49 | 50 | getCompletedFileThesisData(fileId) { 51 | return this.http.get(environment.apiUrl + `/thesis/completed/data/${fileId}`); 52 | } 53 | 54 | getThesisOfProfessor(page, id) { 55 | return this.http.get(environment.apiUrl + `/thesis?page=${page}&professor=${id}`); 56 | } 57 | 58 | getThesisById(id) { 59 | return this.http.get(environment.apiUrl + `/thesis/${id}`); 60 | } 61 | getCompleted(page) { 62 | return this.http.get(environment.apiUrl + `/thesis/completed?page=${page}`); //digital repository 63 | } 64 | 65 | getFilesThesis(ThesisId) { 66 | return this.http.get(environment.apiUrl + `/thesis/files/${ThesisId}`); 67 | } 68 | 69 | getFile(FileId) { 70 | return this.http.get(environment.apiUrl + `/thesis/file/${FileId}`); 71 | } 72 | 73 | getProfessors() { 74 | return this.http.get(environment.apiUrl + `/thesis/professors`); 75 | } 76 | 77 | 78 | 79 | 80 | } -------------------------------------------------------------------------------- /frontend/src/app/shared/services/secretariat.service.ts: -------------------------------------------------------------------------------- 1 | import { environment } from './../../../environments/environment'; 2 | import { Injectable } from '@angular/core'; 3 | import { HttpClient} from '@angular/common/http'; 4 | import { map} from 'rxjs/operators'; 5 | import {Observable} from 'rxjs'; 6 | 7 | 8 | 9 | @Injectable({ providedIn: 'root' }) 10 | export class SecretariatService { 11 | 12 | constructor(private http: HttpClient) {} 13 | 14 | getStudents(page) { 15 | return this.http.get(environment.apiUrl+`/secretariat/get_students?page=${page}`); 16 | } 17 | 18 | getStudents_not_assigned() { 19 | return this.http.get(environment.apiUrl+`/secretariat/get_students_not_assigned`); 20 | } 21 | 22 | getProfessors(page) { 23 | return this.http.get(environment.apiUrl+`/secretariat/get_professors?page=${page}`); 24 | } 25 | 26 | downloadFile(data, filename='data') { 27 | let csvData = this.ConvertToCSV(data, ['ΟΝΟΜΑΤΕΠΩΝΥΜΟ', 'ΑΜ', 'ΤΙΤΛΟΣ', 'ΗΜΕΡΟΜΗΝΙΑ', 'ΕΠΙΒΛΕΠΩΝ', 'ΜΕΛΟΣ1', 'ΜΕΛΟΣ2']); 28 | console.log(csvData) 29 | let blob = new Blob(['\ufeff' + csvData], { type: 'text/csv;charset=utf-8;' }); 30 | let dwldLink = document.createElement("a"); 31 | let url = URL.createObjectURL(blob); 32 | let isSafariBrowser = navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1; 33 | if (isSafariBrowser) { //if Safari open in new window to save file with random filename. 34 | dwldLink.setAttribute("target", "_blank"); 35 | } 36 | dwldLink.setAttribute("href", url); 37 | dwldLink.setAttribute("download", filename + ".csv"); 38 | dwldLink.style.visibility = "hidden"; 39 | document.body.appendChild(dwldLink); 40 | dwldLink.click(); 41 | document.body.removeChild(dwldLink); 42 | } 43 | 44 | ConvertToCSV(objArray, headerList) { 45 | let array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray; 46 | let str = ''; 47 | let row = 'Α/Α,'; 48 | 49 | for (let index in headerList) { 50 | row += headerList[index] + ','; 51 | } 52 | row = row.slice(0, -1); 53 | str += row + '\r\n'; 54 | for (let i = 0; i < array.length; i++) { 55 | let line = (i+1)+''; 56 | for (let index in headerList) { 57 | let head = headerList[index]; 58 | 59 | line += ',' + array[i][head]; 60 | } 61 | str += line + '\r\n'; 62 | } 63 | return str; 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /frontend/src/app/admin/admin-activate-externals/admin-activate-externals.component.ts: -------------------------------------------------------------------------------- 1 | import { Router, Route, ActivatedRoute } from '@angular/router'; 2 | import { Component, OnInit } from '@angular/core'; 3 | 4 | import { AuthenticationService } from '../../shared/services/authentication.service'; 5 | import { UserService } from '../../shared/services/user.service'; 6 | import { AlertService } from '../../shared/services/alert.service'; 7 | import { AdminService } from '.././../shared/services/admin.service'; 8 | 9 | @Component({ 10 | selector: 'app-admin-activate-externals', 11 | templateUrl: './admin-activate-externals.component.html', 12 | styleUrls: ['./admin-activate-externals.component.css'] 13 | }) 14 | export class AdminActivateExternalsComponent implements OnInit { 15 | 16 | users:any=[]; 17 | loading=false; 18 | pager:any={} 19 | message; 20 | length=-1; 21 | 22 | constructor( private router: Router, 23 | private authenticationService: AuthenticationService, 24 | private userService: UserService, 25 | private alertService: AlertService, 26 | private adminService: AdminService, 27 | private route: ActivatedRoute) {} 28 | 29 | 30 | ngOnInit() { 31 | this.getNotActiveExternals(1); 32 | } 33 | 34 | 35 | getNotActiveExternals(page) { 36 | this.adminService.getNotActiveExternals(page) 37 | .subscribe( 38 | (data:any) => { 39 | //this.alertService.success('Get user information successful', true); 40 | this.users=data.docs; 41 | console.log(this.users) 42 | this.pager.count=data.count; 43 | this.pager.pages= data.pages; 44 | this.pager.currentPage=page; 45 | }, 46 | error => { 47 | this.alertService.error(error); 48 | this.loading = false; 49 | }); 50 | } 51 | 52 | onActivate(id) { 53 | this.adminService.activateExternal(id) 54 | .subscribe( 55 | (data:any) =>{ 56 | console.log(data) 57 | this.message="success" 58 | setTimeout(() => { 59 | this.router.navigate(['../external'], { relativeTo: this.route}) 60 | } 61 | ,2000); 62 | }, 63 | error => { 64 | console.log(error) 65 | }); 66 | } 67 | 68 | 69 | 70 | deleteExternal(user) { 71 | this.adminService.deleteExternal(user) 72 | .subscribe( 73 | (data:any) => { 74 | //this.alertService.success('Get user information successful', true); 75 | console.log(data.message) 76 | }, 77 | error => { 78 | this.alertService.error(error); 79 | this.loading = false; 80 | }); 81 | } 82 | 83 | 84 | 85 | 86 | 87 | } 88 | 89 | -------------------------------------------------------------------------------- /frontend/src/app/professor/professor-supervisor-thesis/professor-supervisor-thesis.component.html: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 12 | 13 | 15 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 27 | 28 | 29 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
3 | 4 |

Supervise Theses Results

5 |

You are supervisor in these theses:

6 |
7 |
date_range Assigned 11 | TimetitleTitlepersonProfessor personStudent AssignedPrerequisitesbookDrafts
{{thesis.thesis.created_time | date}} {{thesis.thesis.title}} {{thesis.professor.name}} 26 | {{thesis.professor.lastname}} {{thesis.student.name}} {{thesis.student.lastname}}{{thesis.thesis.prerequisites}} 30 |
31 | 32 |
33 | {{draft.name}} on {{draft.created_time | date}}

34 |
42 | 43 | 44 | 45 | 46 |
47 |
48 |

49 | You have propose the supervisor for the thesis sucessfully! 50 |

51 |
52 |
53 | 54 |
55 | 56 |

You do not supervise any theses !

57 |
58 | 59 | -------------------------------------------------------------------------------- /frontend/src/app/thesis/thesis-professor/thesis-professor.component.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 23 | 24 | 25 | 26 |
3 | 4 |

Theses of Professor {{theses[0]?.professor.name}} {{theses[0]?.professor.lastname}}:

5 |
6 |
date_rangeCreated TimetitleTitleschoolUniversitypersonProfessorPrerequisites
{{thesis.created_time | date}} {{thesis.title}} {{thesis.university.name}}{{thesis.professor.name}} 22 | {{thesis.professor.lastname}} {{thesis.prerequisites}}
27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /frontend/src/app/professor/professor-supervise/professor-supervise.component.ts: -------------------------------------------------------------------------------- 1 | import { Router, ActivatedRoute } from '@angular/router'; 2 | import { Component, OnInit } from '@angular/core'; 3 | import { AlertService } from './../../shared/services/alert.service'; 4 | import { ProfessorService } from './../../shared/services/professor.service'; 5 | import { Sort } from '@angular/material/sort'; 6 | 7 | 8 | 9 | @Component({ 10 | selector: 'app-professor-supervise', 11 | templateUrl: './professor-supervise.component.html', 12 | styleUrls: ['./professor-supervise.component.css'] 13 | }) 14 | export class ProfessorSuperviseComponent implements OnInit { 15 | sortedData: any = []; 16 | messageReject; 17 | message; 18 | loading; 19 | count; 20 | 21 | constructor(private professorService: ProfessorService) { } 22 | 23 | ngOnInit() { 24 | this.loading = true; 25 | this.getSupervisePending() 26 | } 27 | 28 | 29 | compare(a: number | string | boolean, b: number | string | boolean, isAsc: boolean) { 30 | return (a < b ? -1 : 1) * (isAsc ? 1 : -1); 31 | } 32 | 33 | sortData(sort: Sort) { 34 | const data = this.sortedData.slice(); 35 | this.sortedData = data.sort((a, b) => { 36 | const isAsc = sort.direction === 'asc'; 37 | switch (sort.active) { 38 | case 'created_time': return this.compare(a.created_time, b.created_time, isAsc); 39 | case 'title': return this.compare(a.thesis.title, b.thesis.title, isAsc); 40 | case 'student': return this.compare(a.student.lastname, b.student.lastname, isAsc); 41 | case 'apply': return this.compare(a.applied, b.applied, isAsc); 42 | default: return 0; 43 | } 44 | }); 45 | } 46 | 47 | 48 | getSupervisePending() { 49 | this.professorService.getSupervisePending() 50 | .subscribe((result: any) => { 51 | this.sortedData = result; 52 | this.count = result.length 53 | this.loading = false; 54 | console.log(result) 55 | }) 56 | } 57 | 58 | acceptRequest(request) { 59 | this.professorService.acceptSuperviceRequest(request._id) 60 | .subscribe((result: any) => { 61 | console.log(result) 62 | this.message = "success" 63 | setTimeout(() => { 64 | this.message="" 65 | this.getSupervisePending() 66 | } 67 | ,2000); 68 | }) 69 | } 70 | 71 | rejectRequest(request) { 72 | this.professorService.deleteSuperviceRequest(request._id) 73 | .subscribe((result: any) => { 74 | console.log(result) 75 | this.messageReject = "success" 76 | setTimeout(() => { 77 | this.messageReject="" 78 | this.getSupervisePending() 79 | } 80 | ,2000); 81 | }) 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /frontend/src/app/admin/admin-activate-externals/admin-activate-externals.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 25 | 26 | 27 |

Activate Externals Users

User IdEmailNameLastnameRoleActiveDelete
{{user._id}}{{user.email}}{{user.name}}{{user.lastname}}{{user.role}}doneclear 24 |
28 | 29 | 30 |
31 |
32 |
33 |

All Externals have been activated!

34 |
35 |
36 |
37 | 38 |
39 |
40 |

41 | External has been activated! 42 |

43 |
44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /frontend/src/app/home/search-results/search-results.component.html: -------------------------------------------------------------------------------- 1 | 3 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 | 28 | 29 |
4 | 5 |

Search Theses Results of {{selected}}

6 |
7 |
date_range Created 12 | Timetitle Titleschool Universityperson ProfessorPrerequisites
{{thesis.created_time | date}} {{thesis.title}} {{thesis.university.name}}{{thesis.professor.name}} 25 | {{thesis.professor.lastname}} {{thesis.prerequisites}}
30 | 31 | 32 | 33 | 34 | 35 |

No theses found !

36 |
37 |

To return to search page click here

38 |
39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /frontend/src/app/thesis/thesis-create/thesis-create.component.ts: -------------------------------------------------------------------------------- 1 | import { ProfessorService } from './../../shared/services/professor.service'; 2 | import { Component, OnInit } from '@angular/core'; 3 | import { FormBuilder, FormGroup, Validators } from '@angular/forms'; 4 | import { Router, ActivatedRoute } from '@angular/router'; 5 | import { AlertService } from '../../shared/services/alert.service'; 6 | 7 | @Component({ 8 | selector: 'app-thesis-create', 9 | templateUrl: './thesis-create.component.html', 10 | styleUrls: ['./thesis-create.component.css'] 11 | }) 12 | export class ThesisCreateComponent implements OnInit { 13 | createThesisForm: FormGroup; 14 | description; 15 | thesis={}; 16 | message=" "; 17 | fileToUpload: File = null; 18 | 19 | 20 | constructor( 21 | private formBuilder: FormBuilder, 22 | private route: ActivatedRoute, 23 | private router: Router, 24 | private alertService: AlertService, 25 | private professorService:ProfessorService 26 | ) { } 27 | 28 | ngOnInit() { 29 | this.createThesisForm = this.formBuilder.group({ 30 | title: ['', Validators.required], 31 | prerequisites: ['', Validators.required], 32 | tags: ['', Validators.required], 33 | description: ['', Validators.required] 34 | 35 | 36 | }); 37 | } 38 | 39 | get f() { return this.createThesisForm.controls; } 40 | 41 | handleFileInput(files: FileList) { 42 | this.fileToUpload = files.item(0); 43 | } 44 | 45 | 46 | onSubmit() { 47 | if (this.createThesisForm.invalid) { 48 | console.log("invalid form") 49 | return; 50 | } 51 | this.thesis['title']=this.f.title.value; 52 | this.thesis['description']=this.f.description.value; 53 | this.thesis['tags']=this.f.tags.value; 54 | this.thesis['prerequisites']=this.f.prerequisites.value; 55 | this.thesis['created_time']=new Date(); 56 | this.thesis['assigned']=false; 57 | this.professorService.postThesis(this.thesis) 58 | .subscribe( 59 | (data:any) => { 60 | this.message="loading" 61 | console.log(data) 62 | console.log(data) 63 | if(this.fileToUpload !== null){ 64 | this.professorService.postPdfThesis(this.fileToUpload,data.thesis._id) 65 | .subscribe( 66 | (result:any) => { 67 | console.log(result); 68 | this.message="success"; 69 | this.router.navigate(['../professor/thesis'], { relativeTo: this.route}) 70 | } 71 | ) 72 | }else{ 73 | this.message="success"; 74 | this.router.navigate(['../professor/thesis'], { relativeTo: this.route}) 75 | } 76 | }, 77 | error => { 78 | console.log(error) 79 | this.alertService.error(error); 80 | }); 81 | } 82 | 83 | 84 | 85 | } 86 | -------------------------------------------------------------------------------- /frontend/src/app/professor/professor-supervise/professor-supervise.component.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 11 | 13 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 29 | 31 | 32 | 33 | 35 | 37 | 38 | 39 |
3 | 4 |

Requests for Supervisor Results

5 |
6 |
date_rangeCreated TimetitleTitle 12 | personProfessor personStudentMessage from professorAcceptReject
{{request.created_time | date}} 28 | {{request.assigned_thesis.thesis.title}} {{request.professor.name}} 30 | {{request.professor.lastname}} {{request.student.name}} {{request.student.lastname}}{{request.text}}
40 | 41 | 42 | 43 | 44 |

You have not any supervise requests !

45 |
46 | 47 |
48 |
49 |

50 | You have accept the request for the thesis sucessfully! 51 |

52 |
53 |
54 | 55 |
56 |
57 |

58 | You have rejected the request for the thesis sucessfully! 59 |

60 |
61 |
62 | 63 |
-------------------------------------------------------------------------------- /frontend/src/app/admin/admin-university/admin-university.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | import {Sort} from '@angular/material/sort'; 4 | 5 | import { AuthenticationService } from '../../shared/services/authentication.service'; 6 | import { UserService } from '../../shared/services/user.service'; 7 | import { AlertService } from '../../shared/services/alert.service'; 8 | import { AdminService } from '.././../shared/services/admin.service'; 9 | import { SharedService } from './../../shared/services/shared.service'; 10 | 11 | @Component({ 12 | selector: 'app-admin-university', 13 | templateUrl: './admin-university.component.html', 14 | styleUrls: ['./admin-university.component.css'] 15 | }) 16 | export class AdminUniversityComponent implements OnInit { 17 | 18 | sortedData:any=[]; 19 | universities:any=[]; 20 | loading=false; 21 | pager:any={} 22 | 23 | constructor(private router: Router, 24 | private authenticationService: AuthenticationService, 25 | private userService: UserService, 26 | private alertService: AlertService, 27 | private adminService: AdminService, 28 | private sharedService:SharedService 29 | ) {} 30 | 31 | ngOnInit() { 32 | this.getUniversities(1); 33 | 34 | } 35 | 36 | compare(a: number | string | boolean, b: number | string | boolean, isAsc: boolean) { 37 | return (a < b ? -1 : 1) * (isAsc ? 1 : -1); 38 | } 39 | 40 | sortData(sort: Sort) { 41 | const data = this.sortedData.slice(); 42 | this.sortedData = data.sort((a, b) => { 43 | const isAsc = sort.direction === 'asc'; 44 | switch (sort.active) { 45 | case 'name': return this.compare(a.name, b.name, isAsc); 46 | default: return 0; 47 | } 48 | }); 49 | } 50 | 51 | getUniversities(page) { 52 | this.sharedService.getUniversities(page) 53 | .subscribe( 54 | (data:any) => { 55 | //this.alertService.success('Get user information successful', true); 56 | this.universities=data.docs; 57 | this.sortedData=this.universities.slice() 58 | console.log(this.universities) 59 | this.pager.count=data.count; 60 | this.pager.pages= data.pages; 61 | this.pager.currentPage=page; 62 | }, 63 | error => { 64 | this.alertService.error(error); 65 | this.loading = false; 66 | }); 67 | } 68 | 69 | deleteUniversity(university) { 70 | this.adminService.deleteUniversity(university) 71 | .subscribe( 72 | (data:any) => { 73 | //this.alertService.success('Get user information successful', true); 74 | console.log(data.message) 75 | this.getUniversities(this.pager.currentPage) 76 | }, 77 | error => { 78 | this.alertService.error(error); 79 | this.loading = false; 80 | }); 81 | } 82 | 83 | 84 | 85 | 86 | } 87 | -------------------------------------------------------------------------------- /frontend/src/app/shared/services/admin.service.ts: -------------------------------------------------------------------------------- 1 | import { environment } from './../../../environments/environment'; 2 | import { Injectable } from '@angular/core'; 3 | import { HttpClient, HttpHandler, HttpErrorResponse } from '@angular/common/http'; 4 | import { map, tap, take, catchError } from 'rxjs/operators'; 5 | 6 | 7 | import { BehaviorSubject, Observable, throwError } from 'rxjs'; 8 | import { 9 | CanActivate, 10 | ActivatedRouteSnapshot, 11 | RouterStateSnapshot, 12 | Router, 13 | UrlTree 14 | } from '@angular/router'; 15 | 16 | import { User } from '../models/user.model'; 17 | 18 | @Injectable({ providedIn: 'root' }) 19 | export class AdminService { 20 | 21 | constructor(private http: HttpClient) {} 22 | 23 | 24 | /* 25 | getAll() { 26 | return this.http.get(`${config.apiUrl}/users`); 27 | } 28 | 29 | getById(id: number) { 30 | return this.http.get(`${config.apiUrl}/users/${id}`); 31 | } 32 | */ 33 | 34 | getExternals(page) { 35 | return this.http.get(environment.apiUrl+`/admin/get_externals?page=${page}`); 36 | } 37 | 38 | getNotActiveExternals(page) { 39 | return this.http.get(environment.apiUrl+`/admin/get_not_active_externals?page=${page}`); 40 | } 41 | 42 | activateExternal(id) { 43 | return this.http.get(environment.apiUrl+`/admin/activate_external/${id}`); 44 | 45 | } 46 | getUsers(page) { 47 | return this.http.get(environment.apiUrl+`/admin/get_users?page=${page}`); 48 | } 49 | 50 | 51 | getExternalById(id: number) { 52 | return this.http.get(environment.apiUrl+`/admin/get_external/${id}`); 53 | } 54 | 55 | deleteExternal(user) { 56 | if(confirm("Are you sure to delete user with email "+user.email)) { 57 | return this.http.delete(environment.apiUrl+`/admin/delete_external/${user._id}`); 58 | 59 | } 60 | } 61 | 62 | deleteUser(user) { 63 | if(confirm("Are you sure to delete user with email "+user.email)) { 64 | return this.http.delete(environment.apiUrl+`/admin/delete_user/${user._id}`); 65 | 66 | } 67 | } 68 | 69 | putUser(id, role) { 70 | return this.http.put(environment.apiUrl+`/admin/update_user/${id}`, {role:role}); 71 | } 72 | 73 | putExternal(id, role) { 74 | return this.http.put(environment.apiUrl+`/admin/update_external/${id}`, {role:role}); 75 | } 76 | 77 | createUniversity(name) { 78 | return this.http.post(environment.apiUrl+`/admin/create_university`,{name:name}); 79 | } 80 | 81 | deleteUniversity(university) { 82 | if(confirm("Are you sure to delete university: "+university.name)) { 83 | return this.http.delete(environment.apiUrl+`/admin/delete_university/${university._id}`) 84 | } 85 | } 86 | 87 | /* update(user: User) { 88 | return this.http.put(`${config.apiUrl}/users/${user.id}`, user); 89 | } 90 | */ 91 | } 92 | 93 | -------------------------------------------------------------------------------- /backend/meta/COMPANY_SP_metadata_localhost.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | MIICajCCAdOgAwIBAgIBADANBgkqhkiG9w0BAQ0FADBSMQswCQYDVQQGEwJncjEPMA0GA1UECAwGQXRoZW5zMRIwEAYDVQQKDAlnZm9zcy10bXMxHjAcBgNVBAMMFWh0dHA6Ly9sb2NhbGhvc3Q6MzAwMDAeFw0xOTA1MjEyMzI0NDRaFw0yMDA1MjAyMzI0NDRaMFIxCzAJBgNVBAYTAmdyMQ8wDQYDVQQIDAZBdGhlbnMxEjAQBgNVBAoMCWdmb3NzLXRtczEeMBwGA1UEAwwVaHR0cDovL2xvY2FsaG9zdDozMDAwMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA1G4i1Uc6T3uECw1SD+rvzHCf/qupEwSHiVo2N1jYtWCce16nBycJScX4GKYa+17hma3odTLVfVFIRAoGxAXU5CAa63ttHO6fHTbyqC4NbGIjxzhCv4Qd1T3jow5p1K4aWIOJT379A30cNeiGDJl5PvAYZyLZjuuT01J+VTdOGwIDAQABo1AwTjAdBgNVHQ4EFgQU7Yhl/+Fn8xwwAScrKvO9rhAmqi4wHwYDVR0jBBgwFoAU7Yhl/+Fn8xwwAScrKvO9rhAmqi4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQ0FAAOBgQAHU8oM2RPTwJTXvhh42WqsSrgYEqhp37/25h+5Ryy/mEUUqAn/Sx+IctboqVzBWI3ESz6bwyXC5wpbuKrVJToQbGGAhqr5Gqi+Sa0aKGN0bUfjyqAGhgTlxT0LQXX+E03BNB97OeXDBVBGEeK7b4Wy9FCGjM7u+l6yXSxtEW5SlQ== 8 | 9 | 10 | 11 | 12 | 13 | 14 | MIICajCCAdOgAwIBAgIBADANBgkqhkiG9w0BAQ0FADBSMQswCQYDVQQGEwJncjEPMA0GA1UECAwGQXRoZW5zMRIwEAYDVQQKDAlnZm9zcy10bXMxHjAcBgNVBAMMFWh0dHA6Ly9sb2NhbGhvc3Q6MzAwMDAeFw0xOTA1MjEyMzI0NDRaFw0yMDA1MjAyMzI0NDRaMFIxCzAJBgNVBAYTAmdyMQ8wDQYDVQQIDAZBdGhlbnMxEjAQBgNVBAoMCWdmb3NzLXRtczEeMBwGA1UEAwwVaHR0cDovL2xvY2FsaG9zdDozMDAwMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA1G4i1Uc6T3uECw1SD+rvzHCf/qupEwSHiVo2N1jYtWCce16nBycJScX4GKYa+17hma3odTLVfVFIRAoGxAXU5CAa63ttHO6fHTbyqC4NbGIjxzhCv4Qd1T3jow5p1K4aWIOJT379A30cNeiGDJl5PvAYZyLZjuuT01J+VTdOGwIDAQABo1AwTjAdBgNVHQ4EFgQU7Yhl/+Fn8xwwAScrKvO9rhAmqi4wHwYDVR0jBBgwFoAU7Yhl/+Fn8xwwAScrKvO9rhAmqi4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQ0FAAOBgQAHU8oM2RPTwJTXvhh42WqsSrgYEqhp37/25h+5Ryy/mEUUqAn/Sx+IctboqVzBWI3ESz6bwyXC5wpbuKrVJToQbGGAhqr5Gqi+Sa0aKGN0bUfjyqAGhgTlxT0LQXX+E03BNB97OeXDBVBGEeK7b4Wy9FCGjM7u+l6yXSxtEW5SlQ== 15 | 16 | 17 | 18 | 19 | urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified 20 | 21 | 22 | -------------------------------------------------------------------------------- /frontend/src/app/admin/admin-user/admin-user.component.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 35 | 36 | 38 | 39 | 40 |
3 | 4 |

Users Results

5 |
6 |
User IdemailEmailpersonNamepersonLastnameRoleschoolUniversityDelete
{{user._id}}{{user.email}}{{user.name}}{{user.lastname}} 25 | 26 | {{user.role}} 27 | 28 | 29 | {{role}} 30 | 31 | 32 | 33 | 34 | {{user.university.name}}
41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /frontend/src/app/login/login-ldap/login-ldap.component.html: -------------------------------------------------------------------------------- 1 | 2 |

University Login

3 |
4 |
5 |
6 | 7 | Email 8 | 9 | 10 | Email is required 11 | Not a valid email 12 | 13 | 14 |
15 |
16 | 17 | Password 18 | 19 | 20 | Password is required 21 | 22 | 23 |
24 |
25 | 26 | University 27 | 28 | {{university.name}} 29 | 30 | 31 |
32 |
33 | 34 | 35 | Register 36 |
37 |
38 |
--------------------------------------------------------------------------------