Spaces:
Sleeping
Sleeping
Hammaad
commited on
Commit
•
b7b370e
1
Parent(s):
238a3ee
added initial files
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .browserslistrc +17 -0
- .editorconfig +16 -0
- .gitignore +46 -0
- README copy.md +47 -0
- angular.json +135 -0
- dockerfile +33 -0
- e2e/protractor.conf.js +37 -0
- e2e/src/app.e2e-spec.ts +23 -0
- e2e/src/app.po.ts +11 -0
- e2e/tsconfig.json +13 -0
- karma.conf.js +44 -0
- package-lock.json +0 -0
- package.json +51 -0
- requirements.txt +124 -0
- src/app/app-routing.module.ts +16 -0
- src/app/app.component.html +1 -0
- src/app/app.component.scss +0 -0
- src/app/app.component.spec.ts +35 -0
- src/app/app.component.ts +17 -0
- src/app/app.module.ts +54 -0
- src/app/core/core-routing.module.ts +11 -0
- src/app/core/core.component.html +1 -0
- src/app/core/core.component.scss +0 -0
- src/app/core/core.component.spec.ts +25 -0
- src/app/core/core.component.ts +15 -0
- src/app/core/core.module.ts +17 -0
- src/app/core/guards/auth.gaurd.ts +33 -0
- src/app/core/interceptors/auth.interceptor.ts +47 -0
- src/app/core/models/ai-model.model.ts +6 -0
- src/app/core/models/answer.model.ts +6 -0
- src/app/core/models/chat-model.ts +10 -0
- src/app/core/models/key-value.model.ts +4 -0
- src/app/core/models/query.model.ts +9 -0
- src/app/core/models/question.model.ts +7 -0
- src/app/core/models/source-document.model.ts +7 -0
- src/app/core/models/user.model.ts +7 -0
- src/app/core/services/authentication.service.ts +33 -0
- src/app/core/services/chat.service.spec.ts +16 -0
- src/app/core/services/chat.service.ts +26 -0
- src/app/core/services/history.service.ts +29 -0
- src/app/core/services/request-manager-error-handler.service.ts +26 -0
- src/app/core/services/request-manager.service.ts +36 -0
- src/app/features/home/chat/chat.component.html +33 -0
- src/app/features/home/chat/chat.component.scss +118 -0
- src/app/features/home/chat/chat.component.spec.ts +25 -0
- src/app/features/home/chat/chat.component.ts +70 -0
- src/app/features/home/documents/documents.component.html +16 -0
- src/app/features/home/documents/documents.component.scss +9 -0
- src/app/features/home/documents/documents.component.spec.ts +25 -0
- src/app/features/home/documents/documents.component.ts +16 -0
.browserslistrc
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
# For the full list of supported browsers by the Angular framework, please see:
|
6 |
+
# https://angular.io/guide/browser-support
|
7 |
+
|
8 |
+
# You can see what browsers were selected by your queries by running:
|
9 |
+
# npx browserslist
|
10 |
+
|
11 |
+
last 1 Chrome version
|
12 |
+
last 1 Firefox version
|
13 |
+
last 2 Edge major versions
|
14 |
+
last 2 Safari major versions
|
15 |
+
last 2 iOS major versions
|
16 |
+
Firefox ESR
|
17 |
+
not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line.
|
.editorconfig
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
[*.ts]
|
12 |
+
quote_type = single
|
13 |
+
|
14 |
+
[*.md]
|
15 |
+
max_line_length = off
|
16 |
+
trim_trailing_whitespace = false
|
.gitignore
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
README copy.md
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# AiQAWeb
|
2 |
+
|
3 |
+
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 11.2.19.
|
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 Overview and Command Reference](https://angular.io/cli) page.
|
28 |
+
# ATrad_Final
|
29 |
+
|
30 |
+
|
31 |
+
# ATrad GPT
|
32 |
+
|
33 |
+
## Server Up
|
34 |
+
change directry `cd app1 - Endpoint`
|
35 |
+
|
36 |
+
run `python -m main` to activate the server Local
|
37 |
+
|
38 |
+
run `uvicorn main:app --host 192.168.10.77 --port 8000` to activate the server on the network
|
39 |
+
|
40 |
+
## Web App Up
|
41 |
+
go to new terminal
|
42 |
+
|
43 |
+
start web app run `ng serve` Localy up in `http://localhost:4200/`
|
44 |
+
|
45 |
+
start web app run `ng serve --host 192.168.10.77` to activate the server on the network
|
46 |
+
|
47 |
+
|
angular.json
ADDED
@@ -0,0 +1,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
3 |
+
"version": 1,
|
4 |
+
"newProjectRoot": "projects",
|
5 |
+
"projects": {
|
6 |
+
"AiQA-Web": {
|
7 |
+
"projectType": "application",
|
8 |
+
"schematics": {
|
9 |
+
"@schematics/angular:component": {
|
10 |
+
"style": "scss"
|
11 |
+
}
|
12 |
+
},
|
13 |
+
"root": "",
|
14 |
+
"sourceRoot": "src",
|
15 |
+
"prefix": "app",
|
16 |
+
"architect": {
|
17 |
+
"build": {
|
18 |
+
"builder": "@angular-devkit/build-angular:browser",
|
19 |
+
"options": {
|
20 |
+
"outputPath": "dist/AiQA-Web",
|
21 |
+
"index": "src/index.html",
|
22 |
+
"main": "src/main.ts",
|
23 |
+
"polyfills": "src/polyfills.ts",
|
24 |
+
"tsConfig": "tsconfig.app.json",
|
25 |
+
"aot": true,
|
26 |
+
"assets": [
|
27 |
+
"src/favicon.ico",
|
28 |
+
"src/assets"
|
29 |
+
],
|
30 |
+
"styles": [
|
31 |
+
"src/styles.scss",
|
32 |
+
"node_modules/ngx-toastr/toastr.css",
|
33 |
+
"node_modules/@fortawesome/fontawesome-free/css/all.min.css"
|
34 |
+
],
|
35 |
+
"scripts": []
|
36 |
+
},
|
37 |
+
"configurations": {
|
38 |
+
"production": {
|
39 |
+
"fileReplacements": [
|
40 |
+
{
|
41 |
+
"replace": "src/environments/environment.ts",
|
42 |
+
"with": "src/environments/environment.prod.ts"
|
43 |
+
}
|
44 |
+
],
|
45 |
+
"optimization": true,
|
46 |
+
"outputHashing": "all",
|
47 |
+
"sourceMap": false,
|
48 |
+
"namedChunks": false,
|
49 |
+
"extractLicenses": true,
|
50 |
+
"vendorChunk": false,
|
51 |
+
"buildOptimizer": true,
|
52 |
+
"budgets": [
|
53 |
+
{
|
54 |
+
"type": "initial",
|
55 |
+
"maximumWarning": "2mb",
|
56 |
+
"maximumError": "5mb"
|
57 |
+
},
|
58 |
+
{
|
59 |
+
"type": "anyComponentStyle",
|
60 |
+
"maximumWarning": "6kb",
|
61 |
+
"maximumError": "10kb"
|
62 |
+
}
|
63 |
+
]
|
64 |
+
}
|
65 |
+
}
|
66 |
+
},
|
67 |
+
"serve": {
|
68 |
+
"builder": "@angular-devkit/build-angular:dev-server",
|
69 |
+
"options": {
|
70 |
+
"browserTarget": "AiQA-Web:build",
|
71 |
+
"disableHostCheck": true,
|
72 |
+
"host": "0.0.0.0",
|
73 |
+
"port": 4200
|
74 |
+
},
|
75 |
+
"configurations": {
|
76 |
+
"production": {
|
77 |
+
"browserTarget": "AiQA-Web:build:production"
|
78 |
+
}
|
79 |
+
}
|
80 |
+
},
|
81 |
+
"extract-i18n": {
|
82 |
+
"builder": "@angular-devkit/build-angular:extract-i18n",
|
83 |
+
"options": {
|
84 |
+
"browserTarget": "AiQA-Web:build"
|
85 |
+
}
|
86 |
+
},
|
87 |
+
"test": {
|
88 |
+
"builder": "@angular-devkit/build-angular:karma",
|
89 |
+
"options": {
|
90 |
+
"main": "src/test.ts",
|
91 |
+
"polyfills": "src/polyfills.ts",
|
92 |
+
"tsConfig": "tsconfig.spec.json",
|
93 |
+
"karmaConfig": "karma.conf.js",
|
94 |
+
"assets": [
|
95 |
+
"src/favicon.ico",
|
96 |
+
"src/assets"
|
97 |
+
],
|
98 |
+
"styles": [
|
99 |
+
"src/styles.scss",
|
100 |
+
"node_modules/ngx-toastr/toastr.css",
|
101 |
+
"node_modules/@fortawesome/fontawesome-free/css/all.min.css"
|
102 |
+
],
|
103 |
+
"scripts": []
|
104 |
+
}
|
105 |
+
},
|
106 |
+
"lint": {
|
107 |
+
"builder": "@angular-devkit/build-angular:tslint",
|
108 |
+
"options": {
|
109 |
+
"tsConfig": [
|
110 |
+
"tsconfig.app.json",
|
111 |
+
"tsconfig.spec.json",
|
112 |
+
"e2e/tsconfig.json"
|
113 |
+
],
|
114 |
+
"exclude": [
|
115 |
+
"**/node_modules/**"
|
116 |
+
]
|
117 |
+
}
|
118 |
+
},
|
119 |
+
"e2e": {
|
120 |
+
"builder": "@angular-devkit/build-angular:protractor",
|
121 |
+
"options": {
|
122 |
+
"protractorConfig": "e2e/protractor.conf.js",
|
123 |
+
"devServerTarget": "AiQA-Web:serve"
|
124 |
+
},
|
125 |
+
"configurations": {
|
126 |
+
"production": {
|
127 |
+
"devServerTarget": "AiQA-Web:serve:production"
|
128 |
+
}
|
129 |
+
}
|
130 |
+
}
|
131 |
+
}
|
132 |
+
}
|
133 |
+
},
|
134 |
+
"defaultProject": "AiQA-Web"
|
135 |
+
}
|
dockerfile
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Step 1: Build the Angular app
|
2 |
+
# Use a Node.js image to build the Angular project
|
3 |
+
FROM node:18 AS build
|
4 |
+
|
5 |
+
# Set the working directory inside the container
|
6 |
+
WORKDIR /app
|
7 |
+
|
8 |
+
# Copy package.json and package-lock.json to the working directory
|
9 |
+
COPY package*.json ./
|
10 |
+
|
11 |
+
# Install dependencies
|
12 |
+
RUN npm install
|
13 |
+
|
14 |
+
# Copy the rest of the application code
|
15 |
+
COPY . .
|
16 |
+
|
17 |
+
# Fix for OpenSSL issue
|
18 |
+
ENV NODE_OPTIONS=--openssl-legacy-provider
|
19 |
+
|
20 |
+
# Build the Angular project (no --prod flag)
|
21 |
+
RUN npm run build -- --output-path=dist/AiQA-Web --configuration production
|
22 |
+
|
23 |
+
# Step 2: Serve the Angular app with NGINX
|
24 |
+
FROM nginx:alpine
|
25 |
+
|
26 |
+
# Copy the build output to NGINX's default location
|
27 |
+
COPY --from=build /app/dist/AiQA-Web /usr/share/nginx/html
|
28 |
+
|
29 |
+
# Expose port 80
|
30 |
+
EXPOSE 80
|
31 |
+
|
32 |
+
# Start NGINX
|
33 |
+
CMD ["nginx", "-g", "daemon off;"]
|
e2e/protractor.conf.js
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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, StacktraceOption } = 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 |
+
SELENIUM_PROMISE_MANAGER: false,
|
20 |
+
baseUrl: 'http://localhost:4200/',
|
21 |
+
framework: 'jasmine',
|
22 |
+
jasmineNodeOpts: {
|
23 |
+
showColors: true,
|
24 |
+
defaultTimeoutInterval: 30000,
|
25 |
+
print: function() {}
|
26 |
+
},
|
27 |
+
onPrepare() {
|
28 |
+
require('ts-node').register({
|
29 |
+
project: require('path').join(__dirname, './tsconfig.json')
|
30 |
+
});
|
31 |
+
jasmine.getEnv().addReporter(new SpecReporter({
|
32 |
+
spec: {
|
33 |
+
displayStacktrace: StacktraceOption.PRETTY
|
34 |
+
}
|
35 |
+
}));
|
36 |
+
}
|
37 |
+
};
|
e2e/src/app.e2e-spec.ts
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { browser, logging } from 'protractor';
|
2 |
+
import { AppPage } from './app.po';
|
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', async () => {
|
12 |
+
await page.navigateTo();
|
13 |
+
expect(await page.getTitleText()).toEqual('AiQA-Web app is running!');
|
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 |
+
});
|
e2e/src/app.po.ts
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { browser, by, element } from 'protractor';
|
2 |
+
|
3 |
+
export class AppPage {
|
4 |
+
async navigateTo(): Promise<unknown> {
|
5 |
+
return browser.get(browser.baseUrl);
|
6 |
+
}
|
7 |
+
|
8 |
+
async getTitleText(): Promise<string> {
|
9 |
+
return element(by.css('app-root .content span')).getText();
|
10 |
+
}
|
11 |
+
}
|
e2e/tsconfig.json
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
2 |
+
{
|
3 |
+
"extends": "../tsconfig.json",
|
4 |
+
"compilerOptions": {
|
5 |
+
"outDir": "../out-tsc/e2e",
|
6 |
+
"module": "commonjs",
|
7 |
+
"target": "es2018",
|
8 |
+
"types": [
|
9 |
+
"jasmine",
|
10 |
+
"node"
|
11 |
+
]
|
12 |
+
}
|
13 |
+
}
|
karma.conf.js
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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'),
|
13 |
+
require('@angular-devkit/build-angular/plugins/karma')
|
14 |
+
],
|
15 |
+
client: {
|
16 |
+
jasmine: {
|
17 |
+
// you can add configuration options for Jasmine here
|
18 |
+
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
|
19 |
+
// for example, you can disable the random execution with `random: false`
|
20 |
+
// or set a specific seed with `seed: 4321`
|
21 |
+
},
|
22 |
+
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
23 |
+
},
|
24 |
+
jasmineHtmlReporter: {
|
25 |
+
suppressAll: true // removes the duplicated traces
|
26 |
+
},
|
27 |
+
coverageReporter: {
|
28 |
+
dir: require('path').join(__dirname, './coverage/AiQA-Web'),
|
29 |
+
subdir: '.',
|
30 |
+
reporters: [
|
31 |
+
{ type: 'html' },
|
32 |
+
{ type: 'text-summary' }
|
33 |
+
]
|
34 |
+
},
|
35 |
+
reporters: ['progress', 'kjhtml'],
|
36 |
+
port: 9876,
|
37 |
+
colors: true,
|
38 |
+
logLevel: config.LOG_INFO,
|
39 |
+
autoWatch: true,
|
40 |
+
browsers: ['Chrome'],
|
41 |
+
singleRun: false,
|
42 |
+
restartOnFileChange: true
|
43 |
+
});
|
44 |
+
};
|
package-lock.json
ADDED
The diff for this file is too large to render.
See raw diff
|
|
package.json
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "ai-qa-web",
|
3 |
+
"version": "0.0.0",
|
4 |
+
"scripts": {
|
5 |
+
"ng": "ng",
|
6 |
+
"start": "ng serve",
|
7 |
+
"build": "ng build",
|
8 |
+
"test": "ng test",
|
9 |
+
"lint": "ng lint",
|
10 |
+
"e2e": "ng e2e"
|
11 |
+
},
|
12 |
+
"private": true,
|
13 |
+
"dependencies": {
|
14 |
+
"@angular/animations": "~11.2.14",
|
15 |
+
"@angular/common": "~11.2.14",
|
16 |
+
"@angular/compiler": "~11.2.14",
|
17 |
+
"@angular/core": "~11.2.14",
|
18 |
+
"@angular/forms": "~11.2.14",
|
19 |
+
"@angular/platform-browser": "~11.2.14",
|
20 |
+
"@angular/platform-browser-dynamic": "~11.2.14",
|
21 |
+
"@angular/router": "~11.2.14",
|
22 |
+
"@fortawesome/fontawesome-free": "^6.5.1",
|
23 |
+
"bootstrap": "^5.3.2",
|
24 |
+
"csv-writer": "^1.6.0",
|
25 |
+
"jwt-decode": "^4.0.0",
|
26 |
+
"ngx-toastr": "^11.3.3",
|
27 |
+
"primeicons": "^6.0.1",
|
28 |
+
"rxjs": "~6.6.0",
|
29 |
+
"tslib": "^2.0.0",
|
30 |
+
"zone.js": "~0.11.3"
|
31 |
+
},
|
32 |
+
"devDependencies": {
|
33 |
+
"@angular-devkit/build-angular": "~0.1102.18",
|
34 |
+
"@angular/cli": "~11.2.0",
|
35 |
+
"@angular/compiler-cli": "~11.2.14",
|
36 |
+
"@types/jasmine": "~3.6.0",
|
37 |
+
"@types/node": "^12.11.1",
|
38 |
+
"codelyzer": "^6.0.0",
|
39 |
+
"jasmine-core": "~3.6.0",
|
40 |
+
"jasmine-spec-reporter": "~5.0.0",
|
41 |
+
"karma": "~6.1.0",
|
42 |
+
"karma-chrome-launcher": "~3.1.0",
|
43 |
+
"karma-coverage": "~2.0.3",
|
44 |
+
"karma-jasmine": "~4.0.0",
|
45 |
+
"karma-jasmine-html-reporter": "~1.5.0",
|
46 |
+
"protractor": "~7.0.0",
|
47 |
+
"ts-node": "~8.3.0",
|
48 |
+
"tslint": "~6.1.0",
|
49 |
+
"typescript": "~4.1.5"
|
50 |
+
}
|
51 |
+
}
|
requirements.txt
ADDED
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
aiohttp==3.9.3
|
2 |
+
aiosignal==1.3.1
|
3 |
+
altair==5.2.0
|
4 |
+
annotated-types==0.6.0
|
5 |
+
anyio==4.2.0
|
6 |
+
|
7 |
+
async-timeout==4.0.3
|
8 |
+
attrs==23.2.0
|
9 |
+
blinker==1.7.0
|
10 |
+
cachetools==5.3.2
|
11 |
+
certifi==2024.2.2
|
12 |
+
charset-normalizer==3.3.2
|
13 |
+
click==8.1.7
|
14 |
+
|
15 |
+
dataclasses-json==0.6.4
|
16 |
+
|
17 |
+
distro==1.9.0
|
18 |
+
et-xmlfile==1.1.0
|
19 |
+
|
20 |
+
faiss-cpu==1.7.4
|
21 |
+
fastapi==0.109.2
|
22 |
+
filelock==3.13.1
|
23 |
+
frozenlist==1.4.1
|
24 |
+
fsspec==2024.2.0
|
25 |
+
gitdb==4.0.11
|
26 |
+
GitPython==3.1.42
|
27 |
+
greenlet==3.0.3
|
28 |
+
h11==0.14.0
|
29 |
+
httpcore==1.0.3
|
30 |
+
httptools==0.6.1
|
31 |
+
httpx==0.26.0
|
32 |
+
huggingface-hub==0.20.3
|
33 |
+
idna==3.6
|
34 |
+
|
35 |
+
Jinja2==3.1.3
|
36 |
+
joblib==1.3.2
|
37 |
+
jsonpatch==1.33
|
38 |
+
jsonpointer==2.4
|
39 |
+
jsonschema==4.21.1
|
40 |
+
jsonschema-specifications==2023.12.1
|
41 |
+
|
42 |
+
langchain==0.1.7
|
43 |
+
langchain-community==0.0.25
|
44 |
+
langchain-core==0.1.28
|
45 |
+
langchain-openai==0.0.6
|
46 |
+
langsmith==0.1.14
|
47 |
+
markdown-it-py==3.0.0
|
48 |
+
MarkupSafe==2.1.5
|
49 |
+
marshmallow==3.20.2
|
50 |
+
|
51 |
+
mdurl==0.1.2
|
52 |
+
mpmath==1.3.0
|
53 |
+
multidict==6.0.5
|
54 |
+
mypy-extensions==1.0.0
|
55 |
+
|
56 |
+
networkx==3.2.1
|
57 |
+
nltk==3.8.1
|
58 |
+
numpy==1.26.4
|
59 |
+
openai==1.12.0
|
60 |
+
openpyxl==3.1.2
|
61 |
+
orjson==3.9.15
|
62 |
+
|
63 |
+
pandas==2.2.0
|
64 |
+
|
65 |
+
pillow==10.2.0
|
66 |
+
|
67 |
+
protobuf==4.25.3
|
68 |
+
|
69 |
+
pyarrow==15.0.0
|
70 |
+
pydantic==2.6.1
|
71 |
+
pydantic_core==2.16.2
|
72 |
+
pydeck==0.8.1b0
|
73 |
+
|
74 |
+
pypdf==4.1.0
|
75 |
+
|
76 |
+
python-dotenv==1.0.1
|
77 |
+
pytz==2024.1
|
78 |
+
pywin32==305.1
|
79 |
+
PyYAML==6.0.1
|
80 |
+
|
81 |
+
referencing==0.33.0
|
82 |
+
regex==2023.12.25
|
83 |
+
requests==2.31.0
|
84 |
+
rich==13.7.0
|
85 |
+
rpds-py==0.18.0
|
86 |
+
safetensors==0.4.2
|
87 |
+
scikit-learn==1.4.1.post1
|
88 |
+
scipy==1.12.0
|
89 |
+
sentence-transformers==2.3.1
|
90 |
+
sentencepiece==0.1.99
|
91 |
+
|
92 |
+
smmap==5.0.1
|
93 |
+
sniffio==1.3.0
|
94 |
+
SQLAlchemy==2.0.27
|
95 |
+
|
96 |
+
starlette==0.36.3
|
97 |
+
streamlit==1.31.1
|
98 |
+
sympy==1.12
|
99 |
+
tenacity==8.2.3
|
100 |
+
threadpoolctl==3.3.0
|
101 |
+
tiktoken==0.6.0
|
102 |
+
tokenizers==0.15.2
|
103 |
+
toml==0.10.2
|
104 |
+
toolz==0.12.1
|
105 |
+
torch==2.2.0+cu121
|
106 |
+
torchaudio==2.2.0+cu121
|
107 |
+
torchvision==0.17.0+cu121
|
108 |
+
|
109 |
+
tqdm==4.66.2
|
110 |
+
|
111 |
+
transformers==4.37.2
|
112 |
+
typing-inspect==0.9.0
|
113 |
+
|
114 |
+
tzdata==2024.1
|
115 |
+
tzlocal==5.2
|
116 |
+
urllib3==2.2.1
|
117 |
+
uvicorn==0.27.1
|
118 |
+
validators==0.22.0
|
119 |
+
watchdog==4.0.0
|
120 |
+
watchfiles==0.21.0
|
121 |
+
|
122 |
+
websockets==12.0
|
123 |
+
yarl==1.9.4
|
124 |
+
|
src/app/app-routing.module.ts
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { NgModule } from '@angular/core';
|
2 |
+
import { RouterModule, Routes } from '@angular/router';
|
3 |
+
import { LogonComponent } from './features/logon/logon.component';
|
4 |
+
import { HomeComponent } from './features/home/home.component';
|
5 |
+
import { AuthGuard } from './core/guards/auth.gaurd';
|
6 |
+
|
7 |
+
const routes: Routes = [
|
8 |
+
{ path: '', component: LogonComponent, data: { title: 'Login Page' }},
|
9 |
+
{ path: 'chat', component: HomeComponent, data: { title: 'chat Page' }}
|
10 |
+
];
|
11 |
+
|
12 |
+
@NgModule({
|
13 |
+
imports: [RouterModule.forRoot(routes)],
|
14 |
+
exports: [RouterModule]
|
15 |
+
})
|
16 |
+
export class AppRoutingModule { }
|
src/app/app.component.html
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
<router-outlet></router-outlet>
|
src/app/app.component.scss
ADDED
File without changes
|
src/app/app.component.spec.ts
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { TestBed } 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 |
+
await 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.componentInstance;
|
20 |
+
expect(app).toBeTruthy();
|
21 |
+
});
|
22 |
+
|
23 |
+
it(`should have as title 'AiQA-Web'`, () => {
|
24 |
+
const fixture = TestBed.createComponent(AppComponent);
|
25 |
+
const app = fixture.componentInstance;
|
26 |
+
expect(app.title).toEqual('AiQA-Web');
|
27 |
+
});
|
28 |
+
|
29 |
+
it('should render title', () => {
|
30 |
+
const fixture = TestBed.createComponent(AppComponent);
|
31 |
+
fixture.detectChanges();
|
32 |
+
const compiled = fixture.nativeElement;
|
33 |
+
expect(compiled.querySelector('.content span').textContent).toContain('AiQA-Web app is running!');
|
34 |
+
});
|
35 |
+
});
|
src/app/app.component.ts
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Component, OnInit } from '@angular/core';
|
2 |
+
import { isLoggedIn } from './shared/helpers/auth';
|
3 |
+
import { Router } from '@angular/router';
|
4 |
+
|
5 |
+
@Component({
|
6 |
+
selector: 'app-root',
|
7 |
+
templateUrl: './app.component.html',
|
8 |
+
styleUrls: ['./app.component.scss']
|
9 |
+
})
|
10 |
+
export class AppComponent implements OnInit {
|
11 |
+
title = 'AiQA-Web';
|
12 |
+
|
13 |
+
constructor(private router: Router) {}
|
14 |
+
|
15 |
+
ngOnInit(): void {
|
16 |
+
}
|
17 |
+
}
|
src/app/app.module.ts
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { NgModule } from '@angular/core';
|
2 |
+
import { BrowserModule } from '@angular/platform-browser';
|
3 |
+
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
4 |
+
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
|
5 |
+
import { CommonModule } from '@angular/common';
|
6 |
+
import { DatePipe } from '@angular/common';
|
7 |
+
|
8 |
+
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
9 |
+
import { ToastrModule } from 'ngx-toastr';
|
10 |
+
|
11 |
+
import { AppRoutingModule } from './app-routing.module';
|
12 |
+
import { AppComponent } from './app.component';
|
13 |
+
import { CoreModule } from './core/core.module';
|
14 |
+
import { HistoryService } from './core/services/history.service';
|
15 |
+
import { AuthInterceptor } from './core/interceptors/auth.interceptor';
|
16 |
+
import { LogonComponent } from './features/logon/logon.component';
|
17 |
+
import { HomeComponent } from './features/home/home.component';
|
18 |
+
import { SidebarComponent } from './features/home/sidebar/sidebar.component';
|
19 |
+
import { NavbarComponent } from './features/home/navbar/navbar.component';
|
20 |
+
import { DocumentsComponent } from './features/home/documents/documents.component';
|
21 |
+
import { ChatComponent } from './features/home/chat/chat.component';
|
22 |
+
|
23 |
+
|
24 |
+
@NgModule({
|
25 |
+
declarations: [
|
26 |
+
AppComponent,
|
27 |
+
LogonComponent,
|
28 |
+
HomeComponent,
|
29 |
+
SidebarComponent,
|
30 |
+
NavbarComponent,
|
31 |
+
DocumentsComponent,
|
32 |
+
ChatComponent,
|
33 |
+
],
|
34 |
+
imports: [
|
35 |
+
AppRoutingModule,
|
36 |
+
BrowserAnimationsModule,
|
37 |
+
BrowserModule,
|
38 |
+
CommonModule,
|
39 |
+
CoreModule,
|
40 |
+
FormsModule,
|
41 |
+
HttpClientModule,
|
42 |
+
ReactiveFormsModule,
|
43 |
+
ToastrModule.forRoot(),
|
44 |
+
],
|
45 |
+
providers: [HistoryService, DatePipe,
|
46 |
+
{
|
47 |
+
provide: HTTP_INTERCEPTORS,
|
48 |
+
useClass: AuthInterceptor,
|
49 |
+
multi: true,
|
50 |
+
}
|
51 |
+
],
|
52 |
+
bootstrap: [AppComponent]
|
53 |
+
})
|
54 |
+
export class AppModule { }
|
src/app/core/core-routing.module.ts
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { NgModule } from '@angular/core';
|
2 |
+
import { RouterModule, Routes } from '@angular/router';
|
3 |
+
import { CoreComponent } from './core.component';
|
4 |
+
|
5 |
+
const routes: Routes = [{ path: '', component: CoreComponent }];
|
6 |
+
|
7 |
+
@NgModule({
|
8 |
+
imports: [RouterModule.forChild(routes)],
|
9 |
+
exports: [RouterModule]
|
10 |
+
})
|
11 |
+
export class CoreRoutingModule { }
|
src/app/core/core.component.html
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
<p>core works!</p>
|
src/app/core/core.component.scss
ADDED
File without changes
|
src/app/core/core.component.spec.ts
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
2 |
+
|
3 |
+
import { CoreComponent } from './core.component';
|
4 |
+
|
5 |
+
describe('CoreComponent', () => {
|
6 |
+
let component: CoreComponent;
|
7 |
+
let fixture: ComponentFixture<CoreComponent>;
|
8 |
+
|
9 |
+
beforeEach(async () => {
|
10 |
+
await TestBed.configureTestingModule({
|
11 |
+
declarations: [ CoreComponent ]
|
12 |
+
})
|
13 |
+
.compileComponents();
|
14 |
+
});
|
15 |
+
|
16 |
+
beforeEach(() => {
|
17 |
+
fixture = TestBed.createComponent(CoreComponent);
|
18 |
+
component = fixture.componentInstance;
|
19 |
+
fixture.detectChanges();
|
20 |
+
});
|
21 |
+
|
22 |
+
it('should create', () => {
|
23 |
+
expect(component).toBeTruthy();
|
24 |
+
});
|
25 |
+
});
|
src/app/core/core.component.ts
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Component, OnInit } from '@angular/core';
|
2 |
+
|
3 |
+
@Component({
|
4 |
+
selector: 'app-core',
|
5 |
+
templateUrl: './core.component.html',
|
6 |
+
styleUrls: ['./core.component.scss']
|
7 |
+
})
|
8 |
+
export class CoreComponent implements OnInit {
|
9 |
+
|
10 |
+
constructor() { }
|
11 |
+
|
12 |
+
ngOnInit(): void {
|
13 |
+
}
|
14 |
+
|
15 |
+
}
|
src/app/core/core.module.ts
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { NgModule } from '@angular/core';
|
2 |
+
import { CommonModule } from '@angular/common';
|
3 |
+
|
4 |
+
import { CoreRoutingModule } from './core-routing.module';
|
5 |
+
import { CoreComponent } from './core.component';
|
6 |
+
|
7 |
+
|
8 |
+
@NgModule({
|
9 |
+
declarations: [
|
10 |
+
CoreComponent
|
11 |
+
],
|
12 |
+
imports: [
|
13 |
+
CommonModule,
|
14 |
+
CoreRoutingModule
|
15 |
+
]
|
16 |
+
})
|
17 |
+
export class CoreModule { }
|
src/app/core/guards/auth.gaurd.ts
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Injectable } from '@angular/core';
|
2 |
+
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
|
3 |
+
import { isLoggedIn, getLoggedInUser, clearUser } from 'src/app/shared/helpers/auth';
|
4 |
+
import { AuthenticationService } from '../services/authentication.service';
|
5 |
+
|
6 |
+
@Injectable({
|
7 |
+
providedIn: 'root'
|
8 |
+
})
|
9 |
+
export class AuthGuard implements CanActivate {
|
10 |
+
constructor(private router: Router,
|
11 |
+
private authService: AuthenticationService) {}
|
12 |
+
|
13 |
+
canActivate(
|
14 |
+
next: ActivatedRouteSnapshot,
|
15 |
+
state: RouterStateSnapshot
|
16 |
+
): boolean {
|
17 |
+
if (isLoggedIn()){
|
18 |
+
if (this.authService.isTokenExpired()){
|
19 |
+
const user = getLoggedInUser();
|
20 |
+
this.authService.logOut(user.userName).subscribe((response) => {
|
21 |
+
clearUser();
|
22 |
+
this.router.navigate(['/login']);
|
23 |
+
});
|
24 |
+
return false;
|
25 |
+
}else{
|
26 |
+
return true;
|
27 |
+
}
|
28 |
+
} else {
|
29 |
+
this.router.navigate(['/login']);
|
30 |
+
return false;
|
31 |
+
}
|
32 |
+
}
|
33 |
+
}
|
src/app/core/interceptors/auth.interceptor.ts
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Injectable } from '@angular/core';
|
2 |
+
import { Router } from '@angular/router';
|
3 |
+
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpErrorResponse } from '@angular/common/http';
|
4 |
+
import { Observable } from 'rxjs';
|
5 |
+
import { tap } from 'rxjs/operators';
|
6 |
+
import { getLoggedInUser, clearUser } from 'src/app/shared/helpers/auth';
|
7 |
+
import { AuthenticationService } from '../services/authentication.service';
|
8 |
+
import { ToastrService } from 'ngx-toastr';
|
9 |
+
|
10 |
+
@Injectable()
|
11 |
+
export class AuthInterceptor implements HttpInterceptor {
|
12 |
+
constructor(private router: Router,
|
13 |
+
private authService: AuthenticationService,
|
14 |
+
private toastr: ToastrService) {}
|
15 |
+
|
16 |
+
intercept(
|
17 |
+
request: HttpRequest<any>,
|
18 |
+
next: HttpHandler
|
19 |
+
): Observable<HttpEvent<any>> {
|
20 |
+
const authToken = getLoggedInUser()?.token;
|
21 |
+
|
22 |
+
if (authToken) {
|
23 |
+
const authRequest = request.clone({
|
24 |
+
setHeaders: {
|
25 |
+
Authorization: `Bearer ${authToken}`,
|
26 |
+
},
|
27 |
+
});
|
28 |
+
return next.handle(authRequest).pipe(tap(() => {},
|
29 |
+
(err: any) => {
|
30 |
+
if (err instanceof HttpErrorResponse) {
|
31 |
+
if (err.status !== 401){
|
32 |
+
return this.toastr.error("Something went wrong. Please try again later.");
|
33 |
+
}
|
34 |
+
const user = getLoggedInUser();
|
35 |
+
this.authService.logOut(user.userName).subscribe((response) => {
|
36 |
+
clearUser();
|
37 |
+
this.router.navigate(['/login']);
|
38 |
+
return this.toastr.error("Your session has expired.");
|
39 |
+
});
|
40 |
+
return false;
|
41 |
+
}
|
42 |
+
}
|
43 |
+
))
|
44 |
+
}
|
45 |
+
return next.handle(request);
|
46 |
+
}
|
47 |
+
}
|
src/app/core/models/ai-model.model.ts
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { AiModel } from "src/app/shared/enums/ai-model.enum"
|
2 |
+
|
3 |
+
export class AiModelModel {
|
4 |
+
name: string;
|
5 |
+
type: AiModel;
|
6 |
+
}
|
src/app/core/models/answer.model.ts
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { SourceDocumentModel } from "./source-document.model";
|
2 |
+
|
3 |
+
export class AnswerModel {
|
4 |
+
content: string;
|
5 |
+
sourceDocuments: Array<SourceDocumentModel>;
|
6 |
+
}
|
src/app/core/models/chat-model.ts
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { AnswerModel } from "./answer.model";
|
2 |
+
import { QuestionModel } from "./question.model";
|
3 |
+
|
4 |
+
export class ChatModel {
|
5 |
+
questionModel: QuestionModel;
|
6 |
+
answerModel: AnswerModel;
|
7 |
+
feedback: string; // Add the feedback property
|
8 |
+
feedbackSubmitted: boolean = false; // Track whether feedback has been submitted
|
9 |
+
userTypedMessage: string; // Add the userTypedMessage property
|
10 |
+
}
|
src/app/core/models/key-value.model.ts
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export class KeyValueModel {
|
2 |
+
public key: string;
|
3 |
+
public value: string;
|
4 |
+
}
|
src/app/core/models/query.model.ts
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export class QueryModel {
|
2 |
+
historyId: number;
|
3 |
+
question: string;
|
4 |
+
answer: string;
|
5 |
+
aiModel: number;
|
6 |
+
createdOn: string;
|
7 |
+
createdBy: number;
|
8 |
+
sourceDocuments: []
|
9 |
+
}
|
src/app/core/models/question.model.ts
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { AiModel } from "src/app/shared/enums/ai-model.enum";
|
2 |
+
|
3 |
+
export class QuestionModel {
|
4 |
+
user_question: string;
|
5 |
+
// userId: number;
|
6 |
+
// aiModel: AiModel;
|
7 |
+
}
|
src/app/core/models/source-document.model.ts
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export class SourceDocumentModel {
|
2 |
+
// sourceDocumentId: number;
|
3 |
+
pageContent: string;
|
4 |
+
source: string;
|
5 |
+
// page: number;
|
6 |
+
// year: number;
|
7 |
+
}
|
src/app/core/models/user.model.ts
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export class UserModel {
|
2 |
+
userId: number;
|
3 |
+
firstName: string;
|
4 |
+
lastName: string;
|
5 |
+
userName: string;
|
6 |
+
token: string;
|
7 |
+
}
|
src/app/core/services/authentication.service.ts
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Injectable } from '@angular/core';
|
2 |
+
import { Router } from '@angular/router';
|
3 |
+
import { clearUser, getLoggedInUser } from 'src/app/shared/helpers/auth';
|
4 |
+
import { UrlConfigs } from 'src/app/shared/url-configs/url-configs';
|
5 |
+
import { RequestManagerService } from './request-manager.service';
|
6 |
+
import { jwtDecode } from 'jwt-decode';
|
7 |
+
|
8 |
+
@Injectable({
|
9 |
+
providedIn: 'root'
|
10 |
+
})
|
11 |
+
export class AuthenticationService {
|
12 |
+
constructor(private router: Router, private restApiService:RequestManagerService,
|
13 |
+
private urlConfig: UrlConfigs) {}
|
14 |
+
|
15 |
+
logOn(username: string, password: string) {
|
16 |
+
let url = `${this.urlConfig.getValueByKey('Login')}`;
|
17 |
+
return this.restApiService.post(url, {username, password});
|
18 |
+
}
|
19 |
+
|
20 |
+
logOut(username: string) {
|
21 |
+
let url = `${this.urlConfig.getValueByKey('Logout')}`;
|
22 |
+
return this.restApiService.post(url, {username});
|
23 |
+
}
|
24 |
+
|
25 |
+
isTokenExpired(): boolean {
|
26 |
+
const token = getLoggedInUser()?.token;
|
27 |
+
if (!token) {
|
28 |
+
return true;
|
29 |
+
}
|
30 |
+
const decodedToken: any = jwtDecode(token);
|
31 |
+
return Date.now() >= decodedToken.exp * 1000;
|
32 |
+
}
|
33 |
+
}
|
src/app/core/services/chat.service.spec.ts
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { TestBed } from '@angular/core/testing';
|
2 |
+
|
3 |
+
import { ChatService } from './chat.service';
|
4 |
+
|
5 |
+
describe('ChatService', () => {
|
6 |
+
let service: ChatService;
|
7 |
+
|
8 |
+
beforeEach(() => {
|
9 |
+
TestBed.configureTestingModule({});
|
10 |
+
service = TestBed.inject(ChatService);
|
11 |
+
});
|
12 |
+
|
13 |
+
it('should be created', () => {
|
14 |
+
expect(service).toBeTruthy();
|
15 |
+
});
|
16 |
+
});
|
src/app/core/services/chat.service.ts
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Injectable } from '@angular/core';
|
2 |
+
import { RequestManagerService } from "./request-manager.service";
|
3 |
+
import { UrlConfigs } from "src/app/shared/url-configs/url-configs";
|
4 |
+
import { Observable } from "rxjs";
|
5 |
+
import { QuestionModel } from '../models/question.model';
|
6 |
+
|
7 |
+
@Injectable({
|
8 |
+
providedIn: 'root'
|
9 |
+
})
|
10 |
+
export class ChatService {
|
11 |
+
|
12 |
+
constructor(private restApiService:RequestManagerService,
|
13 |
+
private urlConfig: UrlConfigs) { }
|
14 |
+
|
15 |
+
getModels(): Observable<any> {
|
16 |
+
let url = `${this.urlConfig.getValueByKey('AiModels')}`;
|
17 |
+
return this.restApiService.get(url);
|
18 |
+
}
|
19 |
+
|
20 |
+
generateAnswer(questionModel): Observable<any> {
|
21 |
+
let url = `${this.urlConfig.getValueByKey('GenerateAnswer')}`;
|
22 |
+
console.log('questionModel'+questionModel)
|
23 |
+
console.log('url'+url)
|
24 |
+
return this.restApiService.post(url, questionModel);
|
25 |
+
}
|
26 |
+
}
|
src/app/core/services/history.service.ts
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Injectable } from "@angular/core";
|
2 |
+
import { RequestManagerService } from "./request-manager.service";
|
3 |
+
import { UrlConfigs } from "src/app/shared/url-configs/url-configs";
|
4 |
+
import { Observable } from "rxjs";
|
5 |
+
|
6 |
+
@Injectable({
|
7 |
+
providedIn: 'root'
|
8 |
+
})
|
9 |
+
export class HistoryService {
|
10 |
+
|
11 |
+
constructor(private restApiService:RequestManagerService,
|
12 |
+
private urlConfig: UrlConfigs
|
13 |
+
) { }
|
14 |
+
|
15 |
+
public getChatHistoryByUser(id: number): Observable<any> {
|
16 |
+
let url = `${this.urlConfig.getValueByKey('ChatHistoryByUser')}`;
|
17 |
+
url = url.replace('${id}', String(id));
|
18 |
+
return this.restApiService.get(url);
|
19 |
+
}
|
20 |
+
|
21 |
+
public getChatHistoryByDate(id: number, createdOn: string){
|
22 |
+
let url = `${this.urlConfig.getValueByKey('ChatHistoryByDate')}`;
|
23 |
+
url = url.replace('${id}', String(id));
|
24 |
+
url = url.replace('${date}', encodeURIComponent(createdOn));
|
25 |
+
return this.restApiService.get(url);
|
26 |
+
}
|
27 |
+
|
28 |
+
}
|
29 |
+
|
src/app/core/services/request-manager-error-handler.service.ts
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Injectable } from '@angular/core';
|
2 |
+
import { HttpErrorResponse } from '@angular/common/http';
|
3 |
+
import { Observable, throwError } from 'rxjs';
|
4 |
+
|
5 |
+
@Injectable({
|
6 |
+
providedIn: 'root'
|
7 |
+
})
|
8 |
+
export class RequestManagerErrorHandlerService {
|
9 |
+
|
10 |
+
constructor() { }
|
11 |
+
|
12 |
+
handleError(error: HttpErrorResponse): Observable<never> {
|
13 |
+
let errorMessage = 'An error occurred';
|
14 |
+
if (error.error instanceof ErrorEvent) {
|
15 |
+
// Client-side error
|
16 |
+
errorMessage = `Error: ${error.error.message}`;
|
17 |
+
} else {
|
18 |
+
// Server-side error
|
19 |
+
errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
|
20 |
+
}
|
21 |
+
console.error(errorMessage);
|
22 |
+
return throwError(errorMessage);
|
23 |
+
}
|
24 |
+
}
|
25 |
+
|
26 |
+
|
src/app/core/services/request-manager.service.ts
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Injectable } from "@angular/core";
|
2 |
+
import { HttpClient } from '@angular/common/http';
|
3 |
+
import { Observable } from "rxjs";
|
4 |
+
import { environment } from "src/environments/environment";
|
5 |
+
@Injectable({
|
6 |
+
providedIn: 'root'
|
7 |
+
})
|
8 |
+
export class RequestManagerService{
|
9 |
+
private apiUrl = environment.identityServerURL;
|
10 |
+
|
11 |
+
constructor(private http: HttpClient) { }
|
12 |
+
|
13 |
+
public get(endpoint: string): Observable<any> {
|
14 |
+
const url = `${this.apiUrl}/${endpoint}`;
|
15 |
+
return this.http.get(url);
|
16 |
+
}
|
17 |
+
|
18 |
+
public post(endpoint: string, data: any): Observable<any> {
|
19 |
+
const url = `${this.apiUrl}/${endpoint}`;
|
20 |
+
console.log('questionModel :'+data)
|
21 |
+
console.log('url :'+url)
|
22 |
+
return this.http.post(url, data);
|
23 |
+
}
|
24 |
+
|
25 |
+
public put(endpoint: string, data: any): Observable<any> {
|
26 |
+
const url = `${this.apiUrl}/${endpoint}`;
|
27 |
+
return this.http.put(url, data);
|
28 |
+
}
|
29 |
+
|
30 |
+
public delete(endpoint: string): Observable<any> {
|
31 |
+
const url = `${this.apiUrl}/${endpoint}`;
|
32 |
+
return this.http.delete(url);
|
33 |
+
}
|
34 |
+
|
35 |
+
|
36 |
+
}
|
src/app/features/home/chat/chat.component.html
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div id="frame">
|
2 |
+
<div class="content">
|
3 |
+
<div class="messages">
|
4 |
+
<ul>
|
5 |
+
<ng-container *ngFor="let chat of chats; let i = index">
|
6 |
+
<li class="sent">
|
7 |
+
<div class="d-flex">
|
8 |
+
<div><img src="../assets/images/man.png" alt="" /></div>
|
9 |
+
<div class="flex-grow-1">
|
10 |
+
<h6>You</h6>
|
11 |
+
<p>{{ chat.questionModel.user_question }}</p>
|
12 |
+
</div>
|
13 |
+
</div>
|
14 |
+
</li>
|
15 |
+
<li class="replies" [ngClass]="{'typing': i === selectedChatIndex}">
|
16 |
+
<div class="d-flex">
|
17 |
+
<div><img src="../assets/images/robot.png" alt="" /></div>
|
18 |
+
<div class="flex-grow-1">
|
19 |
+
<h6>ATrad AI</h6>
|
20 |
+
<p [class.active]="i === selectedChatIndex" [innerHTML]="formatResponse(chat.answerModel.content)">
|
21 |
+
</p>
|
22 |
+
<input type="text" class="form-control" [(ngModel)]="chat.userTypedMessage"
|
23 |
+
placeholder="Type your feedback here, and then press 👍/👎 to submit." aria-label="Write your message" *ngIf="!chat.feedbackSubmitted">
|
24 |
+
<button *ngIf="!chat.feedbackSubmitted" (click)="thumbsUp(i)">👍</button>
|
25 |
+
<button *ngIf="!chat.feedbackSubmitted" (click)="thumbsDown(i)">👎</button>
|
26 |
+
</div>
|
27 |
+
</div>
|
28 |
+
</li>
|
29 |
+
</ng-container>
|
30 |
+
</ul>
|
31 |
+
</div>
|
32 |
+
</div>
|
33 |
+
</div>
|
src/app/features/home/chat/chat.component.scss
ADDED
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.active {
|
2 |
+
border: 1px solid #10734A !important;
|
3 |
+
}
|
4 |
+
|
5 |
+
#frame .content .messages::-webkit-scrollbar-thumb {
|
6 |
+
background-color: rgba(0, 0, 0, 0.3);
|
7 |
+
}
|
8 |
+
|
9 |
+
#frame .content .messages ul li {
|
10 |
+
display: inline-block;
|
11 |
+
clear: both;
|
12 |
+
margin: 0;
|
13 |
+
width: 100%;
|
14 |
+
font-size: 0.9em;
|
15 |
+
}
|
16 |
+
|
17 |
+
#frame .content .messages ul li.sent img {
|
18 |
+
margin: 0 10px 0 0;
|
19 |
+
}
|
20 |
+
|
21 |
+
#frame .content .messages ul li.sent p {
|
22 |
+
color: #32465a;
|
23 |
+
background-color: #fff;
|
24 |
+
border: 1px solid #D7DAED;
|
25 |
+
margin: 0 0 30px 0;
|
26 |
+
font-size: 13px;
|
27 |
+
line-height: 1.8;
|
28 |
+
width: 100%;
|
29 |
+
padding: 10px 20px;
|
30 |
+
}
|
31 |
+
|
32 |
+
#frame .content .messages ul li.replies img {
|
33 |
+
margin: 0 10px 0 0;
|
34 |
+
}
|
35 |
+
|
36 |
+
#frame .content .messages ul li.replies p {
|
37 |
+
color: #32465a;
|
38 |
+
background: #fff;
|
39 |
+
border: 1px solid #D7DAED;
|
40 |
+
margin: 0 0 30px 0;
|
41 |
+
font-size: 13px;
|
42 |
+
line-height: 1.8;
|
43 |
+
padding: 20px;
|
44 |
+
}
|
45 |
+
|
46 |
+
#frame .content .messages ul li img {
|
47 |
+
width: 35px;
|
48 |
+
height: 35px;
|
49 |
+
border-radius: 50%;
|
50 |
+
}
|
51 |
+
|
52 |
+
#frame .content .messages ul li p {
|
53 |
+
display: inline-block;
|
54 |
+
padding: 0 5x;
|
55 |
+
border-radius: 10px;
|
56 |
+
font-size: 13px;
|
57 |
+
|
58 |
+
}
|
59 |
+
|
60 |
+
#frame .content .message-input .wrap input {
|
61 |
+
border-radius: 10px;
|
62 |
+
border: 1px solid #E9EBF8;
|
63 |
+
padding: 15px 20px;
|
64 |
+
color: #32465a;
|
65 |
+
}
|
66 |
+
|
67 |
+
/* Add this CSS to your component's stylesheet or global styles */
|
68 |
+
button {
|
69 |
+
border: none; /* Remove border */
|
70 |
+
background-color: transparent; /* Make background transparent */
|
71 |
+
cursor: pointer; /* Show pointer cursor on hover */
|
72 |
+
}
|
73 |
+
|
74 |
+
button:focus {
|
75 |
+
outline: none; /* Remove focus outline */
|
76 |
+
}
|
77 |
+
|
78 |
+
/* Optionally, you can add more styles for better visual appearance */
|
79 |
+
button {
|
80 |
+
font-size: 16px; /* Adjust font size */
|
81 |
+
padding: 5px; /* Adjust padding */
|
82 |
+
margin: 2px; /* Adjust margin */
|
83 |
+
}
|
84 |
+
|
85 |
+
.feedback-prompt {
|
86 |
+
font-size: 12px; /* Adjust the font size as needed */
|
87 |
+
color: rgba(0, 0, 0, 0.5); /* Adjust the transparency as needed */
|
88 |
+
}
|
89 |
+
.replies {
|
90 |
+
animation: comeDown 0.5s ease forwards; /* Come down animation */
|
91 |
+
}
|
92 |
+
|
93 |
+
.submit-button {
|
94 |
+
border: none;
|
95 |
+
background: none;
|
96 |
+
cursor: pointer;
|
97 |
+
}
|
98 |
+
|
99 |
+
.feedback-input {
|
100 |
+
border: none;
|
101 |
+
background: none;
|
102 |
+
outline: none; /* Remove outline when focused */
|
103 |
+
}
|
104 |
+
|
105 |
+
.full-width {
|
106 |
+
width: 100%;
|
107 |
+
}
|
108 |
+
|
109 |
+
@keyframes comeDown {
|
110 |
+
from {
|
111 |
+
opacity: 0;
|
112 |
+
transform: translateY(-20px);
|
113 |
+
}
|
114 |
+
to {
|
115 |
+
opacity: 1;
|
116 |
+
transform: translateY(0);
|
117 |
+
}
|
118 |
+
}
|
src/app/features/home/chat/chat.component.spec.ts
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
2 |
+
|
3 |
+
import { ChatComponent } from './chat.component';
|
4 |
+
|
5 |
+
describe('ChatComponent', () => {
|
6 |
+
let component: ChatComponent;
|
7 |
+
let fixture: ComponentFixture<ChatComponent>;
|
8 |
+
|
9 |
+
beforeEach(async () => {
|
10 |
+
await TestBed.configureTestingModule({
|
11 |
+
declarations: [ ChatComponent ]
|
12 |
+
})
|
13 |
+
.compileComponents();
|
14 |
+
});
|
15 |
+
|
16 |
+
beforeEach(() => {
|
17 |
+
fixture = TestBed.createComponent(ChatComponent);
|
18 |
+
component = fixture.componentInstance;
|
19 |
+
fixture.detectChanges();
|
20 |
+
});
|
21 |
+
|
22 |
+
it('should create', () => {
|
23 |
+
expect(component).toBeTruthy();
|
24 |
+
});
|
25 |
+
});
|
src/app/features/home/chat/chat.component.ts
ADDED
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
2 |
+
import { HttpClient } from '@angular/common/http';
|
3 |
+
import { environment } from "src/environments/environment"; // Import environment configuration
|
4 |
+
import { ChatModel } from 'src/app/core/models/chat-model';
|
5 |
+
import { ToastrService } from 'ngx-toastr';
|
6 |
+
|
7 |
+
@Component({
|
8 |
+
selector: 'app-chat',
|
9 |
+
templateUrl: './chat.component.html',
|
10 |
+
styleUrls: ['./chat.component.scss']
|
11 |
+
})
|
12 |
+
export class ChatComponent {
|
13 |
+
@Input() chats: Array<ChatModel>;
|
14 |
+
@Input() selectedChatIndex: number;
|
15 |
+
@Output() onQuestionSelect: EventEmitter<number> = new EventEmitter();
|
16 |
+
|
17 |
+
constructor(private http: HttpClient,private toastr: ToastrService) { }
|
18 |
+
|
19 |
+
onSelect(index: number): void {
|
20 |
+
this.onQuestionSelect.emit(index);
|
21 |
+
}
|
22 |
+
|
23 |
+
formatResponse(response: string): string {
|
24 |
+
return response.replace(/\n/g, '<br>');
|
25 |
+
}
|
26 |
+
thumbsUp(index: number) {
|
27 |
+
const question = this.chats[index].questionModel.user_question;
|
28 |
+
const botResponse = this.chats[index].answerModel.content;
|
29 |
+
const userFeedback = this.chats[index].userTypedMessage ? this.chats[index].userTypedMessage : ''; // Get user's typed message
|
30 |
+
const feedback = 'Good'; // Set feedback to 'Good'
|
31 |
+
this.sendFeedbackToBackend(question, botResponse, userFeedback, feedback);
|
32 |
+
this.chats[index].feedbackSubmitted = true; // Mark feedback as submitted
|
33 |
+
this.chats[index].userTypedMessage = ''; // Clear user's typed message
|
34 |
+
this.toastr.success('Thank you for your feedback!', 'Feedback Submitted');
|
35 |
+
}
|
36 |
+
|
37 |
+
thumbsDown(index: number) {
|
38 |
+
const question = this.chats[index].questionModel.user_question;
|
39 |
+
const botResponse = this.chats[index].answerModel.content;
|
40 |
+
const userFeedback = this.chats[index].userTypedMessage ? this.chats[index].userTypedMessage : ''; // Get user's typed message
|
41 |
+
const feedback = 'Bad'; // Set feedback to 'Bad
|
42 |
+
this.sendFeedbackToBackend(question, botResponse, userFeedback, feedback);
|
43 |
+
this.chats[index].feedbackSubmitted = true; // Mark feedback as submitted
|
44 |
+
this.chats[index].userTypedMessage = ''; // Clear user's typed message
|
45 |
+
this.toastr.success('Thank you for your feedback!', 'Feedback Submitted');
|
46 |
+
}
|
47 |
+
|
48 |
+
sendFeedbackToBackend(question: string, botResponse: string, userFeedback: string, feedback: string) {
|
49 |
+
const feedbackData = {
|
50 |
+
question: question,
|
51 |
+
botResponse: botResponse,
|
52 |
+
userFeedback: userFeedback,
|
53 |
+
feedback: feedback
|
54 |
+
};
|
55 |
+
|
56 |
+
// Use the backend API URL from environment configuration
|
57 |
+
const apiUrl = `${environment.identityServerURL}/feedback`;
|
58 |
+
|
59 |
+
this.http.post(apiUrl, feedbackData).subscribe(
|
60 |
+
(response) => {
|
61 |
+
console.log('Feedback sent successfully:', response);
|
62 |
+
},
|
63 |
+
(error) => {
|
64 |
+
console.error('Error sending feedback:', error);
|
65 |
+
}
|
66 |
+
);
|
67 |
+
}
|
68 |
+
|
69 |
+
|
70 |
+
}
|
src/app/features/home/documents/documents.component.html
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="accordion" id="accordionPanelsStayOpenExample">
|
2 |
+
<div class="accordion-item" *ngFor="let sourceDocument of sourceDocuments; let i = index">
|
3 |
+
<h1 class="accordion-header">
|
4 |
+
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
|
5 |
+
[attr.data-bs-target]="'#panelsStayOpen-collapseOne-' + i" aria-expanded="false"
|
6 |
+
aria-controls="panelsStayOpen-collapseOne">
|
7 |
+
{{ sourceDocument.source }}
|
8 |
+
</button>
|
9 |
+
</h1>
|
10 |
+
<div [id]="'panelsStayOpen-collapseOne-' + i" class="accordion-collapse collapse">
|
11 |
+
<div class="accordion-body">
|
12 |
+
{{ sourceDocument.pageContent }}
|
13 |
+
</div>
|
14 |
+
</div>
|
15 |
+
</div>
|
16 |
+
</div>
|
src/app/features/home/documents/documents.component.scss
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.accordion-button {
|
2 |
+
font-size: 14px !important;
|
3 |
+
font-weight: 600 !important;
|
4 |
+
padding: 10px 20px;
|
5 |
+
}
|
6 |
+
|
7 |
+
.accordion {
|
8 |
+
font-size: 12px;
|
9 |
+
}
|
src/app/features/home/documents/documents.component.spec.ts
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
2 |
+
|
3 |
+
import { DocumentsComponent } from './documents.component';
|
4 |
+
|
5 |
+
describe('DocumentsComponent', () => {
|
6 |
+
let component: DocumentsComponent;
|
7 |
+
let fixture: ComponentFixture<DocumentsComponent>;
|
8 |
+
|
9 |
+
beforeEach(async () => {
|
10 |
+
await TestBed.configureTestingModule({
|
11 |
+
declarations: [ DocumentsComponent ]
|
12 |
+
})
|
13 |
+
.compileComponents();
|
14 |
+
});
|
15 |
+
|
16 |
+
beforeEach(() => {
|
17 |
+
fixture = TestBed.createComponent(DocumentsComponent);
|
18 |
+
component = fixture.componentInstance;
|
19 |
+
fixture.detectChanges();
|
20 |
+
});
|
21 |
+
|
22 |
+
it('should create', () => {
|
23 |
+
expect(component).toBeTruthy();
|
24 |
+
});
|
25 |
+
});
|
src/app/features/home/documents/documents.component.ts
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Component, Input, OnInit } from '@angular/core';
|
2 |
+
import { SourceDocumentModel } from 'src/app/core/models/source-document.model';
|
3 |
+
|
4 |
+
@Component({
|
5 |
+
selector: 'app-documents',
|
6 |
+
templateUrl: './documents.component.html',
|
7 |
+
styleUrls: ['./documents.component.scss']
|
8 |
+
})
|
9 |
+
export class DocumentsComponent implements OnInit{
|
10 |
+
@Input() sourceDocuments: Array<SourceDocumentModel> = [];
|
11 |
+
|
12 |
+
constructor() { }
|
13 |
+
|
14 |
+
ngOnInit(): void {
|
15 |
+
}
|
16 |
+
}
|