Compare commits
185 Commits
aai_roles_
...
master
Author | SHA1 | Date |
---|---|---|
Lampros Smyrnaios | 17d0ac6c33 | |
Lampros Smyrnaios | e4009b7903 | |
Lampros Smyrnaios | 4f1e3a14d4 | |
Lampros Smyrnaios | cb458553f0 | |
Lampros Smyrnaios | c836de5761 | |
Lampros Smyrnaios | 6dfe11484e | |
Lampros Smyrnaios | 0deeb00ee5 | |
Lampros Smyrnaios | b047caee26 | |
Lampros Smyrnaios | 958e6b304e | |
Antonis Lempesis | 44610c172d | |
Lampros Smyrnaios | 547b3107a3 | |
Antonis Lempesis | 4e7ba9d5cb | |
Antonis Lempesis | 62aa87bd86 | |
Lampros Smyrnaios | 7853494a5b | |
Lampros Smyrnaios | d1c336f4e7 | |
Lampros Smyrnaios | 1c9ff0669a | |
Antonis Lempesis | cb8c68e8f9 | |
Antonis Lempesis | 6f964e3d16 | |
Antonis Lempesis | a673450f9c | |
Lampros Smyrnaios | 224d058d89 | |
Lampros Smyrnaios | 91e0b66b28 | |
Lampros Smyrnaios | c838f71227 | |
Lampros Smyrnaios | 0b8e4c4729 | |
Lampros Smyrnaios | a72c5b2fb8 | |
Konstantinos Spyrou | bd315848e0 | |
Konstantinos Spyrou | 4b5132358a | |
Konstantinos Spyrou | 39596cfcc1 | |
Konstantinos Spyrou | 5138605163 | |
Lampros Smyrnaios | 75e97ece26 | |
TheQuaker | 9da5fa5c1e | |
Lampros Smyrnaios | 842468a175 | |
Lampros Smyrnaios | 64fdff095d | |
Lampros Smyrnaios | 11460764a2 | |
Lampros Smyrnaios | 4e1f9cb965 | |
Lampros Smyrnaios | 3cb8e7a5f6 | |
Lampros Smyrnaios | eb42185991 | |
Lampros Smyrnaios | a2a387be90 | |
Lampros Smyrnaios | dc469df9d6 | |
Lampros Smyrnaios | 8f6426eaf6 | |
Konstantinos Spyrou | 6024e0c5b5 | |
Konstantinos Spyrou | ab854a6624 | |
Lampros Smyrnaios | 311442854a | |
Lampros Smyrnaios | dfc4a4690e | |
Lampros Smyrnaios | 0ce67b6355 | |
Lampros Smyrnaios | 54ebb35161 | |
Lampros Smyrnaios | 97e85c2a75 | |
Lampros Smyrnaios | 7cab17c133 | |
Lampros Smyrnaios | d2973871a8 | |
Lampros Smyrnaios | a0fd5f67a7 | |
Lampros Smyrnaios | 59fc344730 | |
Antonis Lempesis | 85f3d1c9dc | |
Lampros Smyrnaios | fe1a398773 | |
Lampros Smyrnaios | 3684f09970 | |
Lampros Smyrnaios | 19fcda5ae1 | |
Konstantinos Spyrou | e9fedc90d4 | |
Konstantinos Spyrou | 0ad86025b3 | |
Konstantinos Spyrou | bae9a132cb | |
Konstantinos Spyrou | b67e98976d | |
Lampros Smyrnaios | c006c7baa0 | |
Lampros Smyrnaios | 8f5aed3aab | |
Lampros Smyrnaios | 0f0163dc2d | |
Antonis Lempesis | 6041bb8f1f | |
Konstantinos Spyrou | 401de371b2 | |
Konstantinos Spyrou | ccf826ee42 | |
Konstantinos Spyrou | 9ad28a2640 | |
Lampros Smyrnaios | 06cea537bf | |
Lampros Smyrnaios | c1abaad3e1 | |
Lampros Smyrnaios | 3845a5103b | |
Lampros Smyrnaios | 8bf0f76ad6 | |
Lampros Smyrnaios | a239164f97 | |
Konstantinos Spyrou | c2e5af87e8 | |
Konstantinos Spyrou | 19923c19fc | |
Konstantinos Spyrou | 1a3399f7d7 | |
Konstantinos Spyrou | fdd597cf02 | |
Konstantinos Spyrou | 60f8c8cb82 | |
Konstantinos Spyrou | 699b45d62f | |
Konstantinos Spyrou | 287f476bd2 | |
Konstantinos Spyrou | d3bcea79c0 | |
Lampros Smyrnaios | de2ac5631f | |
Lampros Smyrnaios | 97d81ce478 | |
Lampros Smyrnaios | b9cde0f1a9 | |
Lampros Smyrnaios | 40aae5d750 | |
Konstantinos Spyrou | 8c07950459 | |
Konstantinos Spyrou | 9e4817f2bd | |
Konstantinos Spyrou | 4231480cbc | |
Konstantinos Spyrou | 33694d17c1 | |
Konstantinos Spyrou | 0aa604a192 | |
Konstantinos Spyrou | caa1f1244a | |
Konstantinos Spyrou | 63b99ea68e | |
Konstantinos Spyrou | ab03a5164d | |
Konstantinos Spyrou | 607c417e3f | |
Konstantinos Spyrou | aeca9ce38b | |
Antonis Lempesis | 242014f2da | |
Konstantinos Spyrou | 7b7c6b0842 | |
Konstantinos Spyrou | 125b64ec3b | |
Konstantinos Spyrou | 415bb1e197 | |
Konstantinos Spyrou | 95335461a2 | |
Konstantinos Spyrou | f88d9b8381 | |
Konstantinos Spyrou | cda2cd5557 | |
Konstantinos Spyrou | 0674a3c031 | |
Konstantinos Spyrou | 0ea91e909d | |
Konstantinos Spyrou | d5327aedea | |
Konstantinos Spyrou | 7c5020c205 | |
Lampros Smyrnaios | df14f5eaab | |
Konstantinos Spyrou | e4d52c2323 | |
Konstantinos Spyrou | 139fb420d4 | |
Konstantinos Spyrou | 60ff3dce6e | |
Konstantinos Spyrou | 40b20b1122 | |
Konstantinos Spyrou | 49cc3d74e8 | |
Konstantinos Spyrou | e551a7a783 | |
Konstantinos Spyrou | 788dac69ad | |
Konstantinos Spyrou | b1e1185765 | |
Konstantinos Spyrou | 817446df41 | |
Konstantinos Spyrou | 87f610b06b | |
Konstantinos Spyrou | e947fe3fec | |
Lampros Smyrnaios | 96003f9f88 | |
Lampros Smyrnaios | d4e4624a3f | |
Lampros Smyrnaios | eaa4083b04 | |
Lampros Smyrnaios | f136488b0e | |
Konstantinos Spyrou | 720ee5a9a4 | |
Konstantinos Spyrou | 4dd0320255 | |
Konstantinos Spyrou | af0482a9fb | |
Konstantinos Spyrou | 830df7cb52 | |
Konstantinos Spyrou | d8eac0ac10 | |
Lampros Smyrnaios | ceb53248ce | |
Konstantinos Spyrou | 4850581c53 | |
Konstantinos Spyrou | a5a4924c08 | |
Konstantinos Spyrou | 6c2780927d | |
Lampros Smyrnaios | 63c9caaf96 | |
Lampros Smyrnaios | a40c1b3e44 | |
Lampros Smyrnaios | 1a4df2b852 | |
Lampros Smyrnaios | deae3b8b54 | |
Lampros Smyrnaios | f720446bdf | |
Lampros Smyrnaios | db88b2eecb | |
Lampros Smyrnaios | 4a32d0278b | |
Konstantinos Spyrou | b3758da868 | |
Konstantinos Spyrou | a792fd34c1 | |
Lampros Smyrnaios | 36b17e4ef1 | |
Konstantinos Spyrou | 01ba340f47 | |
Konstantinos Spyrou | b533355c4f | |
Konstantinos Spyrou | 33d28cefc1 | |
Konstantinos Spyrou | c09cbbbcc0 | |
Konstantinos Spyrou | 6a5c637f51 | |
Lampros Smyrnaios | 96d8ba8dde | |
Lampros Smyrnaios | dbe13a7ed1 | |
Lampros Smyrnaios | 83c77670ab | |
Konstantinos Spyrou | f41a5c8985 | |
Lampros Smyrnaios | 83f9ce36ce | |
Konstantinos Spyrou | e99f334708 | |
Konstantinos Spyrou | cff16a2d7c | |
Konstantinos Spyrou | ee01491995 | |
Konstantinos Spyrou | 1491d8e280 | |
Konstantinos Spyrou | 82cf64a3e3 | |
Konstantinos Spyrou | 0b322c87d6 | |
Konstantinos Spyrou | 0f73e95209 | |
Antonis Lempesis | 9ca8aed160 | |
Konstantinos Spyrou | 9633710cec | |
Konstantinos Spyrou | a46e64f5b5 | |
Konstantinos Spyrou | 3c41f3206a | |
Konstantinos Spyrou | 0590efba9a | |
Konstantinos Spyrou | 2afd3ef412 | |
Konstantinos Spyrou | c7b7d37ae3 | |
Konstantinos Spyrou | 2a8294a958 | |
Antonis Lempesis | d3f13fc8c2 | |
Antonis Lempesis | d57782444d | |
Antonis Lempesis | a61b259ca3 | |
Konstantinos Spyrou | 94a8b1abf9 | |
Konstantinos Spyrou | 03dad9cb1e | |
Konstantinos Spyrou | bd31f55685 | |
Konstantinos Spyrou | 982d299b2d | |
Antonis Lempesis | 2a57236c9a | |
Antonis Lempesis | 9d38d86c03 | |
Antonis Lempesis | b5f1c113c6 | |
Konstantinos Spyrou | 746f3bbfbe | |
Konstantinos Spyrou | 03e0b8f472 | |
Konstantinos Spyrou | 1b6ca905da | |
Konstantinos Spyrou | 4d7f3d7a64 | |
Konstantinos Spyrou | 500c379b8c | |
Konstantinos Spyrou | 84df31c87a | |
Antonis Lempesis | 9e967cab33 | |
Antonis Lempesis | e603487103 | |
Antonis Lempesis | 25ff488405 | |
Antonis Lempesis | a8143fe775 | |
Antonis Lempesis | fca5ada4c0 | |
Antonis Lempesis | b19f53bf80 |
|
@ -0,0 +1,4 @@
|
|||
# Ignore directories
|
||||
.idea
|
||||
target
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
FROM tomcat:7.0.90-jre8
|
||||
#FROM tomcat:7.0.90-jre8
|
||||
FROM tomcat:8.5.71-jre8-openjdk-bullseye
|
||||
MAINTAINER "pkanakakis@di.uoa.gr"
|
||||
RUN ["rm", "-fr", "/usr/local/tomcat/webapps/ROOT"]
|
||||
COPY ./target/uoa-repository-manager-service.war /usr/local/tomcat/webapps/uoa-repository-manager-service.war
|
||||
#COPY src/main/resources/dnet-override-new.properties /usr/local/tomcat/lib/dnet-override.properties
|
||||
COPY src/main/resources/application.properties /usr/local/tomcat/lib/dnet-override.properties
|
||||
COPY validator.env /usr/local/tomcat/lib/dnet-override.properties
|
||||
#COPY src/main/resources/application.properties /usr/local/tomcat/lib/application.properties
|
||||
#COPY src/main/resources/email-texts.properties /usr/local/tomcat/lib/email-texts.properties
|
||||
VOLUME /var/log/uoa-repository-manager-service:/var/log/uoa-repository-manager-service/
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
|
@ -0,0 +1,218 @@
|
|||
# OpenAIRE Provide - backend service
|
||||
|
||||
## Introduction
|
||||
OpenAIRE PROVIDE is the content gateway service of OpenAIRE, where data providers are invited to connect scholarly content with OpenAIRE.<br>
|
||||
OpenAIRE PROVIDE allows repositories, data archives, journals, aggregators, CRIS systems, to enter the OpenAIRE and European Open Science (EOSC) ecosystem and be accessible by millions of researchers, research institutes and networks, research funders, policy makers and citizens.<br>
|
||||
OpenAIRE PROVIDE lowers any technological barriers, by supporting a series of integrations, therefore, enabling its users to visually access OpenAIRE's services that are responsible for the data harvesting process.
|
||||
<br><br>
|
||||
There are four distinctive steps from the initial express of interest for OpenAIRE PROVIDE to the actual content availability on OpenAIRE and EOSC.
|
||||
<br>
|
||||
The steps indicate the important subservices of OpenAIRE that perform the following functionalities:
|
||||
- Validation of data sources with the OpenAIRE guidelines (via the OpenAIRE Validator)
|
||||
- Registration of data sources to OpenAIRE and global interlinked networks provides links to content for text and data mining, view history of validations, status of harvesting Enrichment of metadata information that describes the data sources to be available through OpenAIRE.
|
||||
- Subscribe and view/receive notifications to enrich the metadata or the content of the data source (via the OpenAIRE Broker)
|
||||
- View usage statistics of Open research impact by subscribing to the OpenAIRE UsageCounts service; view aggregated, cleaned usage stats for repository access and broaden your mechanisms for impact assessment.
|
||||
|
||||
<br>
|
||||
|
||||
## Architecture
|
||||
[...]
|
||||
|
||||
<br>
|
||||
|
||||
## Building
|
||||
The backend is a [Maven](https://maven.apache.org/index.html) project. It has been tested using Java 8.
|
||||
<br>
|
||||
|
||||
#### Manual Build Instructions
|
||||
|
||||
###### Requirements:
|
||||
- Java 8
|
||||
- Apache Maven 3+
|
||||
|
||||
###### Build Instructions:
|
||||
1. Clone the repository and move inside the directory
|
||||
<br> `git clone https://code-repo.d4science.org/MaDgIK/uoa-repository-manager-service.git && cd uoa-repository-manager-service`
|
||||
2. Provide all not-set or redacted configurations, inside the **src/main/resources/application.yml** file.
|
||||
3. Build Maven project
|
||||
<br> `mvn clean package`
|
||||
<br> Produces the file "./target/**uoa-repository-manager-service.jar**" which can be run with: - Run the app with: `java -jar ./target/uoa-repository-manager-service.jar`
|
||||
|
||||
#### Build using Docker
|
||||
The repository contains a **Dockerfile** which can be used to build an image containing the compiled project.
|
||||
|
||||
###### Requirements:
|
||||
- Docker
|
||||
|
||||
###### Build Instructions:
|
||||
1. Clone the repository and move inside the directory
|
||||
<br> `git clone https://code-repo.d4science.org/MaDgIK/uoa-repository-manager-service.git && cd uoa-repository-manager-service`
|
||||
2. Provide all not-set or redacted configurations, inside the **src/main/resources/application.yml** file.
|
||||
3. Build Docker image
|
||||
<br> `docker build . -t <docker-image-name>`
|
||||
|
||||
<br>
|
||||
|
||||
## Configuration
|
||||
The configuration can be set inside the **src/main/resources/application.yml** file.
|
||||
|
||||
### Server-related configuration.
|
||||
```
|
||||
server:
|
||||
port: 8480
|
||||
servlet:
|
||||
context-path: /uoa-repository-manager-service
|
||||
```
|
||||
|
||||
### Swagger UI - related configuration
|
||||
```
|
||||
springdoc:
|
||||
swagger-ui:
|
||||
disable-swagger-default-url: true
|
||||
path: /swagger-ui.html
|
||||
displayRequestDuration: true
|
||||
api-docs:
|
||||
path: /api-docs
|
||||
```
|
||||
|
||||
### Datasource -related configuration
|
||||
```
|
||||
spring:
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: update
|
||||
datasource:
|
||||
url: ${services.provide.db.url}
|
||||
username: ${services.provide.db.username}
|
||||
password: ${services.provide.db.password}
|
||||
driverClassName: ${services.provide.db.driverClassName}
|
||||
```
|
||||
|
||||
### Configurations about the provide service.
|
||||
```
|
||||
services:
|
||||
openaireServicesBaseUrl: https://beta.services.openaire.eu
|
||||
provide:
|
||||
dev-machine: 88.197.53.71 # VM-71
|
||||
```
|
||||
|
||||
### Configuration about Authentication and authorization infrastructure (AAI).
|
||||
```
|
||||
aai:
|
||||
baseURL: https://aai.openaire.eu
|
||||
oidc:
|
||||
domain: .openaire.eu # use empty value for local, otherwise: ".openaire.eu"
|
||||
id: XX
|
||||
issuer: ${services.provide.aai.baseURL}/oidc/
|
||||
redirectURL: http://localhost:${server.port}${server.servlet.context-path}/openid_connect_login
|
||||
secret: XX
|
||||
webURL: http://localhost:4200/join
|
||||
registry:
|
||||
coid: XX
|
||||
username: XX
|
||||
password: XX
|
||||
production: false
|
||||
url: ${services.provide.aai.baseURL}/registry/
|
||||
```
|
||||
|
||||
### Broker's configuration
|
||||
```
|
||||
broker:
|
||||
api: api/
|
||||
openaire: openaireBroker
|
||||
port: 443
|
||||
url: https://beta.broker.openaire.eu
|
||||
```
|
||||
|
||||
### Client's configuration
|
||||
```
|
||||
clients:
|
||||
dsm: ${services.provide.baseUrl}
|
||||
search: ${services.openaireServicesBaseUrl}/search/v2/api
|
||||
usageEvents: http://beta.lbs.openaire.eu:8080/ajax/summary
|
||||
usagestats: ${services.openaireServicesBaseUrl}/usagestats
|
||||
```
|
||||
|
||||
### Database configuration for Provide.
|
||||
```
|
||||
db:
|
||||
driverClassName: org.postgresql.Driver
|
||||
password: dnetPwd
|
||||
url: jdbc:postgresql://${services.provide.dev-machine}:5432/repomanager
|
||||
username: dnet
|
||||
```
|
||||
|
||||
### Configuration for the IS LookUp service.
|
||||
```
|
||||
iSLookUpService:
|
||||
url: https://dev-openaire.d4science.org:443/is/services/isLookUp
|
||||
```
|
||||
|
||||
### Mail-server configuration.
|
||||
```
|
||||
mail:
|
||||
authenticate: true
|
||||
debug: false
|
||||
from: XX
|
||||
host: smtp.gmail.com
|
||||
mode: ssl
|
||||
password: XX
|
||||
port: 465
|
||||
replyTo: XX
|
||||
username: XX
|
||||
```
|
||||
|
||||
### Redis's configuration
|
||||
```
|
||||
redis:
|
||||
host: vereniki.athenarc.gr
|
||||
password: XX
|
||||
port: 6379
|
||||
```
|
||||
|
||||
### Usage statistics
|
||||
```
|
||||
usageStatisticsDiagramsBaseURL: https://beta.openaire.eu/stats3/
|
||||
usageStatisticsNumbersBaseURL: ${services.openaireServicesBaseUrl}/usagestats/datasources/
|
||||
usagestats:
|
||||
adminEmail: XX
|
||||
sushiliteEndpoint: ${services.openaireServicesBaseUrl}/usagestats/sushilite/
|
||||
sushiliteR5Endpoint: ${services.openaireServicesBaseUrl}/usagestats_r5/sushilite/r5/
|
||||
```
|
||||
|
||||
### Validator - related configuration.
|
||||
```
|
||||
validator:
|
||||
results:
|
||||
url: https://beta.provide.openaire.eu/compatibility/browseHistory/
|
||||
validatorService:
|
||||
url: http://${services.provide.dev-machine}:8080/uoa-validator-service/services/validatorWebService
|
||||
```
|
||||
|
||||
### Miscellaneous
|
||||
```
|
||||
topic_types:
|
||||
url: ${services.openaireServicesBaseUrl}/provision/mvc/vocabularies/dnet:topic_types.json
|
||||
adminEmail: XX
|
||||
analyticsURL: https://analytics.openaire.eu/addsite.php?
|
||||
baseUrl: ${services.openaireServicesBaseUrl}/openaire
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Deployment
|
||||
|
||||
|
||||
### Prerequisites
|
||||
* install [PostgreSQL 9.5+](https://www.postgresql.org/)
|
||||
* Run the app with: `java -jar ./target/uoa-repository-manager-service.jar --spring.config.location=application.yml`
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
## misc
|
||||
|
||||
### Notes for Swagger-UI:
|
||||
- Access it through this url: http://localhost:8480/uoa-repository-manager-service/swagger-ui/index.html
|
||||
- In order to request data from most endpoints, you have to be a "REGISTERED_USER", otherwise you will get a 403 error code.
|
||||
- In order to be a registered user, you have to run the [UI-service](https://code-repo.d4science.org/MaDgIK/uoa-repository-manager-ui) , in the same machine, at the same time and login through a browser, using the following url: http://localhost:8480/uoa-repository-manager-service/openid_connect_login
|
35
_fonts.scss
35
_fonts.scss
|
@ -1,35 +0,0 @@
|
|||
/* You can add fonts */
|
||||
|
||||
@font-face {
|
||||
font-family: "CharterITCW05";
|
||||
src: url("assets/fonts/CharterITCW05-Regular.woff") format("woff");
|
||||
}
|
||||
|
||||
/*@font-face {
|
||||
font-family: "HelveticaNeue";
|
||||
src: url("assets/fonts/HelveticaNeue-Regular.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "PragmaticaMedium";
|
||||
src: url("assets/fonts/PragmaticaMedium.otf") format("opentype");
|
||||
}*/
|
||||
|
||||
|
||||
:host ::ng-deep {
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "CharterITCW05";
|
||||
}
|
||||
|
||||
/*label, .p-button, th {
|
||||
font-family: "PragmaticaMedium";
|
||||
font-weight: 100;
|
||||
}*/
|
||||
|
||||
/** {
|
||||
:not(h1, h2, h3, h4, h5, h6, label, .p-button, th, .pi) {
|
||||
font-family: "HelveticaNeue";
|
||||
font-weight: 600;
|
||||
}
|
||||
}*/
|
||||
}
|
1263
_general.scss
1263
_general.scss
File diff suppressed because it is too large
Load Diff
32
_media.scss
32
_media.scss
|
@ -1,32 +0,0 @@
|
|||
/* You can add media styles */
|
||||
|
||||
@media (max-width: 991px) {
|
||||
|
||||
//header
|
||||
.header {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
//main-content
|
||||
.main-content {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media (max-width: 961px) {
|
||||
|
||||
.hidden-left-panel {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media (min-width: 961px) {
|
||||
|
||||
.hidden-horizontal-menu {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
/* You can add reusable colors */
|
||||
|
||||
// Primary
|
||||
$dark-orange-1: #933401;
|
||||
$dark-orange-2: #571F01;
|
||||
$orange: #D04A02;
|
||||
$light-orange-1: #FD6412;
|
||||
$light-orange-2: #FEB791;
|
||||
|
||||
$dark-tangerine-1: #AE6800;
|
||||
$dark-tangerine-2: #714300;
|
||||
$tangerine: #EB8C00;
|
||||
$light-tangerine-1: #FFA929;
|
||||
$light-tangerine-2: #FFDCA9;
|
||||
|
||||
$dark-yellow-1: #C28A00;
|
||||
$dark-yellow-2: #855F00;
|
||||
$yellow: #FFB600;
|
||||
$light-yellow-1: #FFC83D;
|
||||
$light-yellow-2: #FFECBD;
|
||||
|
||||
$dark-rose-1: #A43E50;
|
||||
$dark-rose-2: #6E2A35;
|
||||
$rose: #DB536A;
|
||||
$light-rose-1: #E27588;
|
||||
$light-rose-2: #F1BAC3;
|
||||
|
||||
$dark-red-1: #AA2417;
|
||||
$dark-red-2: #741910;
|
||||
$red: #E0301E;
|
||||
$light-red-1: #E86153;
|
||||
$Light-red-2: #F7C8C4;
|
||||
|
||||
$white: white;
|
||||
$black: black;
|
||||
$dark-grey: #2D2D2D;
|
||||
$medium-grey: #464646;
|
||||
$grey: #7D7D7D;
|
||||
$light-grey: #DEDEDE;
|
||||
|
||||
// Secondary
|
||||
$dark-purple-1: #6A1CE2;
|
||||
$dark-purple-2: #4B06B2;
|
||||
$purple: #9013FE;
|
||||
$light-purple-1: #B15AFE;
|
||||
$light-purple-2: #DEB8FF;
|
||||
|
||||
$dark-blue-1: #0060D7;
|
||||
$dark-blue-2: #003DAB;
|
||||
$blue: #0089EB;
|
||||
$light-blue-1: #4DACF1;
|
||||
$light-blue-2: #B3DCF9;
|
||||
|
||||
$dark-green-1: #2C8646;
|
||||
$dark-green-2: #175C2C;
|
||||
$green: #4EB523;
|
||||
$light-green-1: #86DB4F;
|
||||
$light-green-2: #C4FC9F;
|
||||
$rose-for-white-type: #D93954;
|
||||
|
||||
// Status Colors
|
||||
$status-red: #E0301E;
|
||||
$status-yellow: #FFB600;
|
||||
$status-green: #175C2C;
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
const routes: Routes = [];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AppRoutingModule { }
|
|
@ -1,9 +0,0 @@
|
|||
<p-toast preventOpenDuplicates="true"></p-toast>
|
||||
<div class="container">
|
||||
<div class="p-grid p-nogutter">
|
||||
<div class="p-col-12">
|
||||
<app-header></app-header>
|
||||
<app-main-page></app-main-page>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1 +0,0 @@
|
|||
@import 'src/styles';
|
|
@ -1,35 +0,0 @@
|
|||
import { TestBed } from '@angular/core/testing';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [
|
||||
RouterTestingModule
|
||||
],
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
it('should create the app', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
});
|
||||
|
||||
it(`should have as title 'RTA-Admin-UI'`, () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app.title).toEqual('RTA-Admin-UI');
|
||||
});
|
||||
|
||||
it('should render title', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement;
|
||||
expect(compiled.querySelector('.content span').textContent).toContain('RTA-Admin-UI app is running!');
|
||||
});
|
||||
});
|
|
@ -1,19 +0,0 @@
|
|||
import { AuthService } from './shared/services/auth.service';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { PrimeNGConfig } from 'primeng/api';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.scss']
|
||||
})
|
||||
export class AppComponent implements OnInit {
|
||||
|
||||
constructor(private primengConfig: PrimeNGConfig, private authService: AuthService) { }
|
||||
|
||||
|
||||
ngOnInit(): void {
|
||||
this.primengConfig.ripple = true;
|
||||
this.authService.initializeOAuth2Login();
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
import { ToastModule } from 'primeng/toast';
|
||||
import { OAuthModule, OAuthStorage } from 'angular-oauth2-oidc';
|
||||
import { environment } from './../environments/environment';
|
||||
import { HttpClientModule, HttpClient } from '@angular/common/http';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { AppComponent } from './app.component';
|
||||
import { CoreModule } from './core/core.module';
|
||||
import { FeaturesModule } from './features/features.module';
|
||||
import { SharedModule } from './shared/shared.module';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
||||
import { ConfirmationService, MessageService } from 'primeng/api';
|
||||
import { SearchListStateService } from './shared/back-button/search-list-state.service';
|
||||
|
||||
export function HttpLoaderFactory(http: HttpClient): TranslateHttpLoader {
|
||||
return new TranslateHttpLoader(http);
|
||||
}
|
||||
|
||||
// Settings localStorage as OAuth2 storage.
|
||||
// We need a factory, since localStorage is not available during AOT build time.
|
||||
export function storageFactory(): OAuthStorage {
|
||||
return localStorage;
|
||||
}
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
BrowserAnimationsModule,
|
||||
AppRoutingModule,
|
||||
CoreModule,
|
||||
FeaturesModule,
|
||||
SharedModule,
|
||||
HttpClientModule,
|
||||
ToastModule,
|
||||
OAuthModule.forRoot({
|
||||
resourceServer: {
|
||||
allowedUrls: [environment.baseApiUrl],
|
||||
sendAccessToken: true
|
||||
}
|
||||
}),
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useFactory: HttpLoaderFactory,
|
||||
deps: [HttpClient]
|
||||
},
|
||||
defaultLanguage: environment.defaultLanguage,
|
||||
}),
|
||||
],
|
||||
providers: [ConfirmationService, { provide: OAuthStorage, useFactory: storageFactory }, MessageService, SearchListStateService],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule { }
|
|
@ -1,25 +0,0 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { SharedModule } from 'primeng/api';
|
||||
import { PrimengSharedModule } from './../shared/primeng-shared/primeng-shared.module';
|
||||
import { ErrorHandlingModule } from './error-handling/error-handling.module';
|
||||
|
||||
import { HeaderComponent } from './header/header.component';
|
||||
import { MainPageComponent } from './main-page/main-page.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [HeaderComponent, MainPageComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
PrimengSharedModule,
|
||||
SharedModule,
|
||||
ErrorHandlingModule
|
||||
],
|
||||
exports: [
|
||||
HeaderComponent,
|
||||
MainPageComponent
|
||||
]
|
||||
})
|
||||
export class CoreModule { }
|
|
@ -1,15 +0,0 @@
|
|||
import { HttpErrorInterceptor } from './http-error.interceptor';
|
||||
import { GlobalErrorHandler } from './global-error-handler';
|
||||
import { NgModule, ErrorHandler } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
imports: [CommonModule],
|
||||
providers: [
|
||||
{ provide: ErrorHandler, useClass: GlobalErrorHandler },
|
||||
{ provide: HTTP_INTERCEPTORS, useClass: HttpErrorInterceptor, multi: true }
|
||||
]
|
||||
})
|
||||
export class ErrorHandlingModule { }
|
|
@ -1,21 +0,0 @@
|
|||
import { environment } from 'src/environments/environment';
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { ErrorHandlingService } from './../../shared/services/error-handling/error-handling.service';
|
||||
import { ErrorHandler, Injectable, NgZone } from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class GlobalErrorHandler implements ErrorHandler {
|
||||
constructor(private errorHandlingService: ErrorHandlingService, private zone: NgZone) {}
|
||||
|
||||
handleError(error: Error): void {
|
||||
|
||||
this.zone.run(() => {
|
||||
if (!(error instanceof HttpErrorResponse) && environment.enableGlobalErrorToast){
|
||||
this.errorHandlingService.showErrorMessage(error.message);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
console.error('Error from global error handler', error);
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
import { ErrorHandlingService } from './../../shared/services/error-handling/error-handling.service';
|
||||
import {
|
||||
HttpHandler,
|
||||
HttpRequest,
|
||||
HttpEvent,
|
||||
HttpErrorResponse,
|
||||
HttpInterceptor
|
||||
} from '@angular/common/http';
|
||||
import { Observable, throwError } from 'rxjs';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class HttpErrorInterceptor implements HttpInterceptor {
|
||||
constructor(
|
||||
private injector: Injector,
|
||||
) {}
|
||||
|
||||
intercept(
|
||||
request: HttpRequest<any>,
|
||||
next: HttpHandler
|
||||
): Observable<HttpEvent<any>> {
|
||||
return next.handle(request).pipe(
|
||||
catchError((error: HttpErrorResponse) => {
|
||||
// We don't inject an HttpClient dependent service directly to an http interceptor's constructor,
|
||||
// or we'll get cyclic dependency errors
|
||||
const errorHandlingService = this.injector.get(ErrorHandlingService);
|
||||
|
||||
errorHandlingService.showHttpResponseError(error);
|
||||
return throwError(error);
|
||||
})
|
||||
) as Observable<HttpEvent<any>>;
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
<div class="p-grid p-nogutter p-ai-center vertical-container header">
|
||||
<div class="p-col-4">
|
||||
<div class="p-grid p-nogutter p-jc-start">
|
||||
<a routerLink=''>
|
||||
<img src="assets/images/pwc-logo.svg" height="50">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-col-8">
|
||||
<div class="p-grid p-nogutter p-jc-end">
|
||||
<p-selectButton class="p-ml-auto" [options]="languages" [(ngModel)]="selectedLang" (ngModelChange)="changeLanguage($event)" optionLabel="name" optionValue="code"></p-selectButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1 +0,0 @@
|
|||
@import 'src/styles';
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { HeaderComponent } from './header.component';
|
||||
|
||||
describe('HeaderComponent', () => {
|
||||
let component: HeaderComponent;
|
||||
let fixture: ComponentFixture<HeaderComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ HeaderComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(HeaderComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,28 +0,0 @@
|
|||
import { Language } from './../../shared/models/language.interface';
|
||||
import { environment } from './../../../environments/environment';
|
||||
import { AuthService } from './../../shared/services/auth.service';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { MenuItem } from 'primeng/api';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import {Router} from "@angular/router";
|
||||
|
||||
@Component({
|
||||
selector: 'app-header',
|
||||
templateUrl: './header.component.html',
|
||||
styleUrls: ['./header.component.scss']
|
||||
})
|
||||
export class HeaderComponent implements OnInit {
|
||||
|
||||
languages: Language[] = environment.languages;
|
||||
selectedLang = environment.defaultLanguage;
|
||||
|
||||
constructor(private auth: AuthService, private translateService: TranslateService, private router: Router) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
changeLanguage($event): void {
|
||||
this.translateService.use($event);
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
<router-outlet></router-outlet>
|
|
@ -1 +0,0 @@
|
|||
@import 'src/styles';
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MainPageComponent } from './main-page.component';
|
||||
|
||||
describe('MainPageComponent', () => {
|
||||
let component: MainPageComponent;
|
||||
let fixture: ComponentFixture<MainPageComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ MainPageComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(MainPageComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,22 +0,0 @@
|
|||
import { Router } from '@angular/router';
|
||||
import { AuthService } from 'src/app/shared/services/auth.service';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-main-page',
|
||||
templateUrl: './main-page.component.html',
|
||||
styleUrls: ['./main-page.component.scss']
|
||||
})
|
||||
export class MainPageComponent implements OnInit {
|
||||
|
||||
constructor(private auth: AuthService, private router: Router) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.auth.authStatusChanged.subscribe((isAuthenticated) => {
|
||||
if (!isAuthenticated) {
|
||||
this.router.navigateByUrl('login');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
<div class="p-grid p-nogutter">
|
||||
|
||||
<app-left-panel class="hidden-left-panel"></app-left-panel>
|
||||
|
||||
<div class="p-col main-content">
|
||||
<h1>{{'ADMINISTRATION' | translate}}</h1>
|
||||
|
||||
<div class="p-mb-5 hidden-horizontal-menu">
|
||||
<app-horizontal-menu></app-horizontal-menu>
|
||||
</div>
|
||||
|
||||
<ng-template ngFor let-section [ngForOf]="adminSections">
|
||||
<h3 class="sub-title" id="{{section.title}}">{{section.title}}</h3>
|
||||
<div class="sub-content">
|
||||
<div class="p-grid">
|
||||
<ng-template ngFor let-subSection [ngForOf]="section.subSections">
|
||||
<div class="p-col-12 p-sm-6 p-xl-3">
|
||||
<app-card [data]="subSection"></app-card>
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
</div>
|
|
@ -1 +0,0 @@
|
|||
@import 'src/styles';
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { AdministrationComponent } from './administration.component';
|
||||
|
||||
describe('WelcomeComponent', () => {
|
||||
let component: AdministrationComponent;
|
||||
let fixture: ComponentFixture<AdministrationComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [AdministrationComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AdministrationComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,103 +0,0 @@
|
|||
import { AuthService } from './../../shared/services/auth.service';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { CardItem } from './../../shared/models/card-item.interface';
|
||||
import { AdministrationSection } from './../../shared/models/administration-section.interface';
|
||||
|
||||
@Component({
|
||||
selector: 'app-administration',
|
||||
templateUrl: './administration.component.html',
|
||||
styleUrls: ['./administration.component.scss']
|
||||
})
|
||||
export class AdministrationComponent implements OnInit {
|
||||
|
||||
data: CardItem;
|
||||
adminSections: AdministrationSection[];
|
||||
|
||||
constructor(public authService: AuthService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.initializeData();
|
||||
}
|
||||
|
||||
initializeData() {
|
||||
this.adminSections = [
|
||||
{
|
||||
title: 'Monitoring',
|
||||
subSections: [
|
||||
{
|
||||
title: 'Downloads Monitoring',
|
||||
subtitle: 'View File\'s Downloading Process and Manage...',
|
||||
headerImage: 'pi-image',
|
||||
footerImage: 'pi-desktop',
|
||||
path: '/pages/administration/downloads-monitoring'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Configurations',
|
||||
subSections: [
|
||||
{
|
||||
title: 'Categories Managenent',
|
||||
subtitle: 'View File\'s Downloading Process and Manage...',
|
||||
headerImage: 'pi-image',
|
||||
footerImage: 'pi-cog',
|
||||
path: '/pages/administration/categories-management'
|
||||
},
|
||||
{
|
||||
title: 'Templates Managenent',
|
||||
subtitle: 'View File\'s Downloading Process and Manage...',
|
||||
headerImage: 'pi-image',
|
||||
footerImage: 'pi-cog',
|
||||
path: '/pages/administration/templates-management'
|
||||
},
|
||||
{
|
||||
title: 'Verification Managenent',
|
||||
subtitle: 'View File\'s Downloading Process and Manage...',
|
||||
headerImage: 'pi-image',
|
||||
footerImage: 'pi-cog',
|
||||
path: '/pages/administration/verification-management'
|
||||
},
|
||||
{
|
||||
title: 'Configurator',
|
||||
subtitle: 'View File\'s Downloading Process and Manage...',
|
||||
headerImage: 'pi-image',
|
||||
footerImage: 'pi-cog',
|
||||
path: '/pages/administration/configurator'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Access',
|
||||
subSections: [
|
||||
{
|
||||
title: 'Users Managenent',
|
||||
subtitle: 'View File\'s Downloading Process and Manage...',
|
||||
headerImage: 'pi-image',
|
||||
footerImage: 'pi-key',
|
||||
path: '/pages/administration/users-management'
|
||||
},
|
||||
{
|
||||
title: 'Roles Managenent',
|
||||
subtitle: 'View File\'s Downloading Process and Manage...',
|
||||
headerImage: 'pi-image',
|
||||
footerImage: 'pi-key',
|
||||
path: '/pages/administration/roles-management'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Exception Handling',
|
||||
subSections: [
|
||||
{
|
||||
title: 'Application Level Exceptions',
|
||||
subtitle: 'View Application Level exceptions thrown by the Platform',
|
||||
headerImage: 'pi-image',
|
||||
footerImage: 'pi-exclamation-triangle',
|
||||
path: '/pages/administration/application-level-exceptions'
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
<p-dialog [header]="header"
|
||||
[(visible)]="displayDialog "
|
||||
[closable]="false"
|
||||
[draggable]="false"
|
||||
[modal]="true"
|
||||
appendTo="body">
|
||||
<ng-template pTemplate="content">
|
||||
<pre>
|
||||
{{this.trace}}
|
||||
</pre>
|
||||
</ng-template>
|
||||
<ng-template pTemplate="footer">
|
||||
<p-button (onClick)="cancel()"
|
||||
label="Close"
|
||||
styleClass="p-mt-3 p-button-warning">
|
||||
</p-button>
|
||||
</ng-template>
|
||||
</p-dialog>
|
|
@ -1,13 +0,0 @@
|
|||
@import 'src/styles';
|
||||
|
||||
pre {
|
||||
width: 900px !important;
|
||||
}
|
||||
|
||||
@media (max-width: 991px) {
|
||||
|
||||
pre {
|
||||
width: 420px !important;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ApplicationLevelDialogComponent } from './application-level-dialog.component';
|
||||
|
||||
describe('ApplicationLevelDialogComponent', () => {
|
||||
let component: ApplicationLevelDialogComponent;
|
||||
let fixture: ComponentFixture<ApplicationLevelDialogComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ ApplicationLevelDialogComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ApplicationLevelDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,24 +0,0 @@
|
|||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { ApplicationLevelExceptionService } from 'src/app/shared/services/administration/application-level-exception.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-application-level-dialog',
|
||||
templateUrl: './application-level-dialog.component.html',
|
||||
styleUrls: ['./application-level-dialog.component.scss']
|
||||
})
|
||||
export class ApplicationLevelDialogComponent implements OnInit {
|
||||
@Input() displayDialog: boolean;
|
||||
@Input() header: string;
|
||||
@Input() trace: string;
|
||||
@Output() cancelled = new EventEmitter<boolean>();
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.cancelled.emit(true);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
<div class="p-grid p-nogutter">
|
||||
<div class="p-col main-content">
|
||||
|
||||
<h1>{{'APPLICATION-LEVEL-EXCEPTIONS' | translate}}</h1>
|
||||
|
||||
<app-horizontal-menu></app-horizontal-menu>
|
||||
|
||||
<app-breadcrumb></app-breadcrumb>
|
||||
|
||||
<div class="p-grid p-nogutter p-pt-5 p-pb-5">
|
||||
|
||||
<div class="p-col p-nogutter p-col-12 p-mt-5">
|
||||
<app-application-level-search-form [paginationEventRequest]="paginationEventRequest"
|
||||
(searchResults)="searchMade($event)"
|
||||
(loading)="passloading($event)">
|
||||
</app-application-level-search-form>
|
||||
</div>
|
||||
|
||||
<div class="p-col p-nogutter p-col-12 p-mt-5">
|
||||
<app-application-level-table [searchResultsPage]="searchResults"
|
||||
(paginationEvent)="paginationEvent($event)"
|
||||
[loading]="loading">
|
||||
</app-application-level-table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
|
@ -1 +0,0 @@
|
|||
@import 'src/styles';
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ApplicationLevelExceptionsComponent } from './application-level-exceptions.component';
|
||||
|
||||
describe('ApplicationLevelExceptionsComponent', () => {
|
||||
let component: ApplicationLevelExceptionsComponent;
|
||||
let fixture: ComponentFixture<ApplicationLevelExceptionsComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ ApplicationLevelExceptionsComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ApplicationLevelExceptionsComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,33 +0,0 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { Page } from 'src/app/shared/models/paging/page.interface';
|
||||
import { SystemException } from 'src/app/shared/models/system-exception.interface';
|
||||
|
||||
@Component({
|
||||
selector: 'app-application-level-exceptions',
|
||||
templateUrl: './application-level-exceptions.component.html',
|
||||
styleUrls: ['./application-level-exceptions.component.scss']
|
||||
})
|
||||
export class ApplicationLevelExceptionsComponent implements OnInit {
|
||||
|
||||
searchResults: Page<SystemException> = null;
|
||||
paginationEventRequest: { page: number, offset: number } ;
|
||||
loading: boolean;
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
searchMade(results) {
|
||||
this.searchResults = results;
|
||||
}
|
||||
|
||||
passloading(loading) {
|
||||
this.loading = loading;
|
||||
}
|
||||
|
||||
paginationEvent(paginationEvent) {
|
||||
this.paginationEventRequest = paginationEvent;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
<p-fieldset legend="Search Filters"
|
||||
[toggleable]="true">
|
||||
<app-application-level-form></app-application-level-form>
|
||||
<div class="p-formgroup-inline p-jc-center p-mt-3">
|
||||
<p-button (onClick)="clear()" label="Clear" styleClass="p-mr-2 p-button-warning"
|
||||
[disabled]="!canPreviewLevelExceptions()">
|
||||
</p-button>
|
||||
<p-button (onClick)="search()"
|
||||
label="Search"
|
||||
styleClass="p-button-primary"
|
||||
[disabled]="!canPreviewLevelExceptions()">
|
||||
</p-button>
|
||||
</div>
|
||||
</p-fieldset>
|
|
@ -1 +0,0 @@
|
|||
@import 'src/styles';
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ApplicationLevelSearchFormComponent } from './application-level-search-form.component';
|
||||
|
||||
describe('ApplicationLevelSearchFormComponent', () => {
|
||||
let component: ApplicationLevelSearchFormComponent;
|
||||
let fixture: ComponentFixture<ApplicationLevelSearchFormComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ ApplicationLevelSearchFormComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ApplicationLevelSearchFormComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,59 +0,0 @@
|
|||
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
|
||||
import { USER_RIGHTS } from 'src/app/shared/enums/USER_RIGHTS.enum';
|
||||
import { Page } from 'src/app/shared/models/paging/page.interface';
|
||||
import { SystemException } from 'src/app/shared/models/system-exception.interface';
|
||||
import { AuthService } from 'src/app/shared/services/auth.service';
|
||||
import { ApplicationLevelExceptionService } from 'src/app/shared/services/administration/application-level-exception.service';
|
||||
import { ErrorHandlingService } from 'src/app/shared/services/error-handling/error-handling.service';
|
||||
import { environment } from 'src/environments/environment';
|
||||
import { ApplicationLevelFormComponent } from '../../forms/application-level-form/application-level-form.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-application-level-search-form',
|
||||
templateUrl: './application-level-search-form.component.html',
|
||||
styleUrls: ['./application-level-search-form.component.scss']
|
||||
})
|
||||
export class ApplicationLevelSearchFormComponent implements OnInit {
|
||||
|
||||
@Input() set paginationEventRequest(value: { page: number, offset: number }) {
|
||||
|
||||
// This setter may be called on page setup without arguments.
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
// this._value = Object.assign(value);
|
||||
this.search(value.page, value.offset);
|
||||
}
|
||||
|
||||
@Output() searchResults = new EventEmitter<Page<SystemException>>();
|
||||
@Output() loading = new EventEmitter<boolean>();
|
||||
@ViewChild(ApplicationLevelFormComponent)
|
||||
private searchCriteriaForm: ApplicationLevelFormComponent;
|
||||
_value : {page: number , offset: number};
|
||||
|
||||
constructor(private applicationLevelService: ApplicationLevelExceptionService,private errorHandlingService: ErrorHandlingService, private auth: AuthService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
search(pageNumber = 0, pageSize = 10) {
|
||||
this.loading.emit(true);
|
||||
this.applicationLevelService.searchByCriteriaPaged(pageNumber, pageSize, this.searchCriteriaForm?.formValue(), 'search').subscribe((results: Page<SystemException>) => {
|
||||
this.searchResults.emit(results);
|
||||
this.loading.emit(false);
|
||||
},
|
||||
err => {
|
||||
this.errorHandlingService.showHttpResponseError(err)
|
||||
this.loading.emit(false);
|
||||
});
|
||||
}
|
||||
|
||||
canPreviewLevelExceptions(): boolean {
|
||||
return this.auth.userHasRightForClient(USER_RIGHTS.K01, environment.globalRightsClientID);
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.searchCriteriaForm.resetForm();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
<p-fieldset legend="List of Exceptions"
|
||||
[toggleable]="_searchResultsPage?.data !== null"
|
||||
[collapsed]="_searchResultsPage?.data === null">
|
||||
<p-table [value]="_searchResultsPage?.data"
|
||||
[lazy]="true"
|
||||
(onLazyLoad)="onLazyLoad($event)"
|
||||
[paginator]="true"
|
||||
[rows]="rows"
|
||||
[totalRecords]="totalRecords"
|
||||
styleClass="p-datatable-gridlines"
|
||||
[rowHover]="true"
|
||||
[loading]="loading"
|
||||
[autoLayout]="true"
|
||||
[lazyLoadOnInit]="false">
|
||||
<ng-template pTemplate="header">
|
||||
<tr>
|
||||
<th>Date-Time</th>
|
||||
<th>Process Id</th>
|
||||
<th>Job Name</th>
|
||||
<th>File Code</th>
|
||||
<th>iPower Client Code</th>
|
||||
<th>Message</th>
|
||||
<th>Cause</th>
|
||||
<th class="one-button">Trace</th>
|
||||
</tr>
|
||||
</ng-template>
|
||||
<ng-template pTemplate="body" let-systemException>
|
||||
<tr>
|
||||
<td>{{systemException.creationDatetime|date: "dd/MM/yyyy HH:mm"}}</td>
|
||||
<td>{{systemException.processId}}</td>
|
||||
<td>{{systemException.jobName}}</td>
|
||||
<td>{{systemException.dmsFileCode}}</td>
|
||||
<td>{{systemException.clientId}}</td>
|
||||
<td>{{systemException.message}}</td>
|
||||
<td>{{systemException.cause}}</td>
|
||||
<!-- Edit & Delete icons -->
|
||||
<td>
|
||||
<button pButton
|
||||
(click)="edit(systemException.id)"
|
||||
icon="pi pi-align-justify"
|
||||
pTooltip="{{'TRACE' | translate}}"
|
||||
class="p-button-secondary p-button-rounded p-button-outlined">
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
</p-table>
|
||||
</p-fieldset>
|
||||
|
||||
<app-application-level-dialog [displayDialog]="displayTraceDialog"
|
||||
[header]="header"
|
||||
(cancelled)="cancelEditLevelException()"
|
||||
[trace]="trace">
|
||||
</app-application-level-dialog>
|
|
@ -1 +0,0 @@
|
|||
@import 'src/styles';
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ApplicationLevelTableComponent } from './application-level-table.component';
|
||||
|
||||
describe('ApplicationLevelTableComponent', () => {
|
||||
let component: ApplicationLevelTableComponent;
|
||||
let fixture: ComponentFixture<ApplicationLevelTableComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ ApplicationLevelTableComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ApplicationLevelTableComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,64 +0,0 @@
|
|||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { LazyLoadEvent } from 'primeng/api';
|
||||
import { Page } from 'src/app/shared/models/paging/page.interface';
|
||||
import { SystemException } from 'src/app/shared/models/system-exception.interface';
|
||||
import { ApplicationLevelExceptionService } from 'src/app/shared/services/administration/application-level-exception.service';
|
||||
import { ErrorHandlingService } from 'src/app/shared/services/error-handling/error-handling.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-application-level-table',
|
||||
templateUrl: './application-level-table.component.html',
|
||||
styleUrls: ['./application-level-table.component.scss']
|
||||
})
|
||||
export class ApplicationLevelTableComponent implements OnInit {
|
||||
|
||||
@Output() paginationEvent = new EventEmitter<{ page: number, offset: number }>(); // TODO: Use interface.
|
||||
@Input() loading: boolean;
|
||||
@Input() set searchResultsPage(results: Page<SystemException>) {
|
||||
|
||||
// This setter may be called on page setup without arguments.
|
||||
if (!results) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._searchResultsPage = results;
|
||||
this.totalRecords = results.totalElements;
|
||||
// this.loading = false;
|
||||
}
|
||||
_searchResultsPage: Page<SystemException>;
|
||||
totalRecords: number;
|
||||
rows: number = 10;
|
||||
header: string;
|
||||
trace: string;
|
||||
displayTraceDialog: boolean;
|
||||
|
||||
constructor(private errorHandlingService: ErrorHandlingService, private applicationLevelService: ApplicationLevelExceptionService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
onLazyLoad(event: LazyLoadEvent) {
|
||||
let pageToRequest = Math.floor(event.first / event.rows);
|
||||
let pageSize = event.rows;
|
||||
this.paginationEvent.emit({ page: pageToRequest, offset: pageSize });
|
||||
}
|
||||
|
||||
edit(id: number) {
|
||||
this.header = "Trace";
|
||||
if(id){
|
||||
this.applicationLevelService.getById(id).subscribe(result => {
|
||||
this.trace = result.trace;
|
||||
this.displayTraceDialog = true;
|
||||
},
|
||||
err => {
|
||||
this.errorHandlingService.showHttpResponseError(err)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
cancelEditLevelException() {
|
||||
this.displayTraceDialog = false;
|
||||
this.trace = null;
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
<div class="p-grid p-nogutter">
|
||||
<div class="p-col main-content">
|
||||
|
||||
<h1>{{'CATEGORIES-MANAGEMENT' | translate}}</h1>
|
||||
|
||||
<app-horizontal-menu></app-horizontal-menu>
|
||||
|
||||
<app-breadcrumb></app-breadcrumb>
|
||||
|
||||
<div class="p-grid p-nogutter p-pt-5 p-pb-5">
|
||||
|
||||
<div class="p-col p-nogutter p-col-12">
|
||||
<div class="p-grid p-nogutter p-jc-end">
|
||||
<button pButton
|
||||
pRipple
|
||||
type="button"
|
||||
label="{{'ADD-NEW-CATEGORY' | translate}}"
|
||||
icon="pi pi-plus-circle"
|
||||
class="p-button-primary"
|
||||
[disabled]="!canAddNewCategory()"
|
||||
(click)="addCategory()">
|
||||
</button>
|
||||
<app-create-category-dialog [displayDialog]="displayCategoryCreationDialog"
|
||||
[header]="header"
|
||||
(cancelled)="displayCategoryCreationDialog = false"
|
||||
(valueChange)="passEvent($event)">
|
||||
</app-create-category-dialog>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-col p-nogutter p-col-12 p-mt-5">
|
||||
<app-categories-search [paginationEventRequest]="paginationEventRequest"
|
||||
(searchResults)="searchMade($event)"
|
||||
(loading)="passLoadingForTable($event)"
|
||||
[passChange]="passChange"
|
||||
(loading)="passloading($event)"
|
||||
[valueTableChange]="valueOfTableChanged">
|
||||
</app-categories-search>
|
||||
</div>
|
||||
|
||||
<div class="p-col p-nogutter p-col-12 p-mt-5">
|
||||
<app-categories-search-results [searchResultsPage]="searchResults"
|
||||
[loading]="loading"
|
||||
(paginationEvent)="paginationEvent($event)"
|
||||
(valueChange)="passEvent($event)"
|
||||
[loading]="loading">
|
||||
</app-categories-search-results>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
|
@ -1 +0,0 @@
|
|||
@import 'src/styles';
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CategoriesManagementComponent } from './categories-management.component';
|
||||
|
||||
describe('CategoriesManagementComponent', () => {
|
||||
let component: CategoriesManagementComponent;
|
||||
let fixture: ComponentFixture<CategoriesManagementComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ CategoriesManagementComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CategoriesManagementComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,59 +0,0 @@
|
|||
import { environment } from './../../../../environments/environment.prod';
|
||||
import { USER_RIGHTS } from 'src/app/shared/enums/USER_RIGHTS.enum';
|
||||
import { AuthService } from './../../../shared/services/auth.service';
|
||||
import { Category } from 'src/app/shared/models/category.interface';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Page } from '../../../shared/models/paging/page.interface';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-categories-management',
|
||||
templateUrl: './categories-management.component.html',
|
||||
styleUrls: ['./categories-management.component.scss']
|
||||
})
|
||||
export class CategoriesManagementComponent implements OnInit {
|
||||
|
||||
displayCategoryCreationDialog: boolean = false;
|
||||
searchResults: Page<Category> = null;
|
||||
paginationEventRequest: { page: number, offset: number } = { page: 10, offset: 0 };
|
||||
header: string;
|
||||
passChange: boolean;
|
||||
valueOfTableChanged: any;
|
||||
loading: boolean;
|
||||
|
||||
constructor(private authService: AuthService, private translate: TranslateService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
searchMade(results) {
|
||||
this.searchResults = results;
|
||||
}
|
||||
|
||||
passLoadingForTable(loading) {
|
||||
this.loading = loading;
|
||||
}
|
||||
|
||||
paginationEvent(paginationEvent) {
|
||||
this.paginationEventRequest = paginationEvent;
|
||||
}
|
||||
|
||||
canAddNewCategory(): boolean {
|
||||
return this.authService.userHasRightForClient(USER_RIGHTS.H02, environment.globalRightsClientID);
|
||||
}
|
||||
|
||||
addCategory(): void {
|
||||
this.header = this.translate.instant('ADD-NEW-CATEGORY');
|
||||
this.displayCategoryCreationDialog = true;
|
||||
}
|
||||
|
||||
passEvent(passEvent: any) {
|
||||
if (passEvent) {
|
||||
this.valueOfTableChanged = passEvent;
|
||||
}
|
||||
}
|
||||
|
||||
passloading(loading) {
|
||||
this.loading = loading;
|
||||
}
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
<p-fieldset legend="Results"
|
||||
[toggleable]="_searchResultsPage?.data !== null"
|
||||
[collapsed]="_searchResultsPage?.data === null">
|
||||
<p-confirmDialog message="{{'DELETE-MESSAGE-CATEGORY' | translate}}"
|
||||
header="{{'DELETE-CONFIRMATION' | translate}}"
|
||||
acceptLabel="{{'ACCEPT_LABEL' | translate}}"
|
||||
rejectLabel="{{'REJECT_LABEL' | translate}}"
|
||||
acceptButtonStyleClass="p-button-primary"
|
||||
rejectButtonStyleClass="p-button-warning"
|
||||
acceptIcon="null"
|
||||
rejectIcon="null">
|
||||
</p-confirmDialog>
|
||||
<p-table [value]="_searchResultsPage?.data"
|
||||
[lazy]="true"
|
||||
(onLazyLoad)="onLazyLoad($event)"
|
||||
[paginator]="true"
|
||||
[rows]="rows"
|
||||
[totalRecords]="totalRecords"
|
||||
styleClass="p-datatable-gridlines"
|
||||
[rowHover]="true"
|
||||
[loading]="loading"
|
||||
[autoLayout]="true">
|
||||
<ng-template pTemplate="header">
|
||||
<tr>
|
||||
<th>Document Classification</th>
|
||||
<th>Category Name</th>
|
||||
<th>Category Code</th>
|
||||
<!-- TODO: Fix hacky way of locking the icon-columns in place -->
|
||||
<th class="two-buttons">Actions</th>
|
||||
</tr>
|
||||
</ng-template>
|
||||
<ng-template pTemplate="body" let-category>
|
||||
<tr>
|
||||
<td>{{category.documentClassification.classificationName}}</td>
|
||||
<td>{{category.categoryName}}</td>
|
||||
<td>{{category.categoryCode}}</td>
|
||||
<!-- Edit & Delete icons -->
|
||||
<td>
|
||||
<button pButton
|
||||
[disabled]="!canEditCategories()"
|
||||
(click)="edit(category)"
|
||||
icon="pi pi-pencil"
|
||||
pTooltip="{{'EDIT-CATEGORY' | translate}}"
|
||||
class="p-button-secondary p-button-rounded p-button-outlined">
|
||||
</button>
|
||||
<button pButton
|
||||
[disabled]="!canDeleteCategories()"
|
||||
(click)="delete(category)"
|
||||
icon="pi pi pi-trash"
|
||||
pTooltip="{{'DELETE-CATEGORY' | translate}}"
|
||||
class="p-button-danger p-button-rounded p-button-outlined p-ml-2">
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
</p-table>
|
||||
</p-fieldset>
|
||||
|
||||
<app-create-category-dialog [displayDialog]="displayEditCategoryDialog"
|
||||
[header]="header"
|
||||
(cancelled)="cancelEditCategory()"
|
||||
[categoryToEdit]="categoryToEdit"
|
||||
(valueChange)="passEvent($event)">
|
||||
</app-create-category-dialog>
|
|
@ -1 +0,0 @@
|
|||
@import 'src/styles';
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CategoriesSearchResultsComponent } from './categories-search-results.component';
|
||||
|
||||
describe('CategoriesSearchResultsComponent', () => {
|
||||
let component: CategoriesSearchResultsComponent;
|
||||
let fixture: ComponentFixture<CategoriesSearchResultsComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ CategoriesSearchResultsComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CategoriesSearchResultsComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,103 +0,0 @@
|
|||
import { AuthService } from './../../../../shared/services/auth.service';
|
||||
import { environment } from './../../../../../environments/environment.prod';
|
||||
import { ErrorHandlingService } from './../../../../shared/services/error-handling/error-handling.service';
|
||||
import { CategoriesService } from 'src/app/shared/services/administration/categories.service';
|
||||
import { Category } from './../../../../shared/models/category.interface';
|
||||
import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core';
|
||||
import { ConfirmationService, LazyLoadEvent } from 'primeng/api';
|
||||
import { Page } from '../../../../shared/models/paging/page.interface';
|
||||
import { USER_RIGHTS } from 'src/app/shared/enums/USER_RIGHTS.enum';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { NotificationsHandlingService } from 'src/app/shared/services/notifications-handling/notifications-handling.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-categories-search-results',
|
||||
templateUrl: './categories-search-results.component.html',
|
||||
styleUrls: ['./categories-search-results.component.scss']
|
||||
})
|
||||
export class CategoriesSearchResultsComponent implements OnInit {
|
||||
|
||||
@Output() paginationEvent = new EventEmitter<{ page: number, offset: number }>(); // TODO: Use interface.
|
||||
@Output() valueChange = new EventEmitter<any>();
|
||||
@Input() loading: boolean;
|
||||
@Input() set searchResultsPage(results: Page<Category>) {
|
||||
|
||||
// This setter may be called on page setup without arguments.
|
||||
if (!results) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._searchResultsPage = results;
|
||||
this.totalRecords = results.totalElements;
|
||||
}
|
||||
|
||||
_searchResultsPage: Page<Category>;
|
||||
totalRecords: number;
|
||||
rows: number = 10;
|
||||
header: string;
|
||||
|
||||
displayEditCategoryDialog: boolean;
|
||||
categoryToEdit: Category;
|
||||
|
||||
constructor(
|
||||
private categoriesService: CategoriesService,
|
||||
private errorHandlingService: ErrorHandlingService,
|
||||
private authService: AuthService,
|
||||
private translate: TranslateService,
|
||||
private confirmationService: ConfirmationService,
|
||||
private notifications: NotificationsHandlingService
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
onLazyLoad(event: LazyLoadEvent) {
|
||||
let pageToRequest = Math.floor(event.first / event.rows);
|
||||
let pageSize = event.rows;
|
||||
this.paginationEvent.emit({ page: pageToRequest, offset: pageSize });
|
||||
}
|
||||
|
||||
edit(category: Category) {
|
||||
this.header = this.translate.instant('EDIT-CATEGORY');
|
||||
this.categoryToEdit = category;
|
||||
this.displayEditCategoryDialog = true;
|
||||
}
|
||||
|
||||
cancelEditCategory() {
|
||||
this.displayEditCategoryDialog = false;
|
||||
this.categoryToEdit = null;
|
||||
}
|
||||
|
||||
delete(category: Category): void {
|
||||
this.confirmationService.confirm({
|
||||
accept: () => {
|
||||
this.categoriesService.delete(category.id).subscribe((success) => {
|
||||
this.valueChange.emit(success);
|
||||
this.notifications.showDeleteCategorySuccess();
|
||||
},
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
// Actual logic to perform a confirmation
|
||||
}, reject: () => {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* UserRights-check Methods
|
||||
*/
|
||||
canEditCategories(): boolean {
|
||||
return this.authService.userHasRightForClient(USER_RIGHTS.H03, environment.globalRightsClientID);
|
||||
}
|
||||
|
||||
canDeleteCategories(): boolean {
|
||||
return this.authService.userHasRightForClient(USER_RIGHTS.H04, environment.globalRightsClientID);
|
||||
}
|
||||
|
||||
passEvent(passEvent : any) {
|
||||
if(passEvent){
|
||||
this.valueChange.emit(passEvent);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
<p-fieldset legend="Search Filters"
|
||||
[toggleable]="true">
|
||||
<app-category-form [autosuggestInputs]="true"></app-category-form>
|
||||
<div class="p-formgroup-inline p-jc-center p-mt-3">
|
||||
<p-button (onClick)="clear()"
|
||||
label="Clear"
|
||||
styleClass="p-mr-2 p-button-warning">
|
||||
</p-button>
|
||||
<p-button (onClick)="searchButtonClicked()"
|
||||
label="Search"
|
||||
styleClass="p-ml-2 p-button-primary"
|
||||
[disabled]="!canPreviewAllCategories()">
|
||||
</p-button>
|
||||
</div>
|
||||
</p-fieldset>
|
|
@ -1 +0,0 @@
|
|||
@import 'src/styles';
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CategoriesSearchComponent } from './categories-search.component';
|
||||
|
||||
describe('CategoriesSearchComponent', () => {
|
||||
let component: CategoriesSearchComponent;
|
||||
let fixture: ComponentFixture<CategoriesSearchComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ CategoriesSearchComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CategoriesSearchComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,101 +0,0 @@
|
|||
import { environment } from './../../../../../environments/environment.prod';
|
||||
import { ErrorHandlingService } from './../../../../shared/services/error-handling/error-handling.service';
|
||||
import { AuthService } from 'src/app/shared/services/auth.service';
|
||||
import { CategoryFormComponent } from './../../forms/category-form/category-form.component';
|
||||
import { Category } from './../../../../shared/models/category.interface';
|
||||
import { DocumentClassificationsService } from './../../../../shared/services/administration/document-classifications.service';
|
||||
import { Component, OnInit, Output, EventEmitter, Input, ViewChild } from '@angular/core';
|
||||
import { FormBuilder } from '@angular/forms';
|
||||
import { CategoriesService } from 'src/app/shared/services/administration/categories.service';
|
||||
import { DocumentClassification } from 'src/app/shared/models/document-classification.interface';
|
||||
import { Page } from '../../../../shared/models/paging/page.interface';
|
||||
import { USER_RIGHTS } from 'src/app/shared/enums/USER_RIGHTS.enum';
|
||||
|
||||
@Component({
|
||||
selector: 'app-categories-search',
|
||||
templateUrl: './categories-search.component.html',
|
||||
styleUrls: ['./categories-search.component.scss']
|
||||
})
|
||||
export class CategoriesSearchComponent implements OnInit {
|
||||
|
||||
@Input() set paginationEventRequest(value: { page: number, offset: number }) {
|
||||
|
||||
// This setter may be called on page setup without arguments.
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
this._value = Object.assign(value);
|
||||
this.search(value.page, value.offset);
|
||||
}
|
||||
|
||||
@Input() set valueTableChange(results: any) {
|
||||
if (results) {
|
||||
this.search(this._value.page, this._value.offset);
|
||||
}
|
||||
}
|
||||
|
||||
@Output() searchResults = new EventEmitter<Page<Category>>();
|
||||
@Output() loading = new EventEmitter<boolean>();
|
||||
@Output() searchInitiated = new EventEmitter<boolean>();
|
||||
@Input() passChange: any;
|
||||
|
||||
@ViewChild(CategoryFormComponent)
|
||||
private categoryForm: CategoryFormComponent;
|
||||
_value: { page: number, offset: number };
|
||||
lastSearchCriteria: { docClassificationId: number | string, categoryName: string, categoryCode: string };
|
||||
|
||||
constructor(
|
||||
private categoriesService: CategoriesService,
|
||||
private authService: AuthService,
|
||||
private errorHandlingService: ErrorHandlingService
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.categoryForm.resetForm();
|
||||
}
|
||||
|
||||
searchButtonClicked() {
|
||||
|
||||
// Inform anyone interested there is a new search underway.
|
||||
this.searchInitiated.emit(true);
|
||||
|
||||
// Remember the search for future pagination/whatever requests.
|
||||
let categoryFormValue = this.categoryForm.formValue();
|
||||
let docClassId = categoryFormValue.documentClassification ? categoryFormValue.documentClassification.classificationId : null;
|
||||
let catName = categoryFormValue.categoryName;
|
||||
let catCode = categoryFormValue.categoryCode;
|
||||
|
||||
this.lastSearchCriteria = {
|
||||
docClassificationId: docClassId ? docClassId : '',
|
||||
categoryName: catName ? catName : '',
|
||||
categoryCode: catCode ? catCode : ''
|
||||
};
|
||||
|
||||
// Then actually search.
|
||||
this.search();
|
||||
}
|
||||
|
||||
search(pageNumber = 0, pageSize = 10) {
|
||||
this.loading.emit(true);
|
||||
|
||||
// A search may be issued by the paginationEventRequest setter upon setting up the page.
|
||||
if (!this.lastSearchCriteria) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.categoriesService.searchByCriteriaPaged(pageNumber, pageSize, this.lastSearchCriteria, 'search').subscribe((results: Page<Category>) => {
|
||||
this.searchResults.emit(results);
|
||||
this.loading.emit(false);
|
||||
},err => {
|
||||
this.loading.emit(false);
|
||||
this.errorHandlingService.showHttpResponseError(err);
|
||||
});
|
||||
}
|
||||
|
||||
canPreviewAllCategories(): boolean {
|
||||
return this.authService.userHasRightForClient(USER_RIGHTS.H01, environment.globalRightsClientID);
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
<p-dialog [header]="header"
|
||||
[(visible)]="displayDialog"
|
||||
[closable]="false"
|
||||
[draggable]="false"
|
||||
[modal]="true"
|
||||
(onHide)="reset()"
|
||||
(onShow)="onShow()"
|
||||
appendTo="body">
|
||||
<div class="p-grid p-nogutter">
|
||||
<app-category-form [dialogLayout]="true"
|
||||
[requiredFields]="true"
|
||||
[displayValidationMessagesEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-category-form>
|
||||
</div>
|
||||
<div class="p-grid p-nogutter p-jc-center">
|
||||
<div class="p-formgroup-inline p-mt-3">
|
||||
<p-button (onClick)="cancel()"
|
||||
label="Cancel"
|
||||
styleClass="p-mr-2 p-button-warning">
|
||||
</p-button>
|
||||
<p-button *ngIf="!categoryToEdit"
|
||||
(onClick)="addCategory()"
|
||||
label="Add"
|
||||
styleClass="p-ml-2 p-mr-2 p-button-primary">
|
||||
</p-button>
|
||||
<p-button *ngIf="categoryToEdit && categoryToEdit.id"
|
||||
(onClick)="editCategory()"
|
||||
label="Update"
|
||||
styleClass="p-ml-2 p-button-primary">
|
||||
</p-button>
|
||||
</div>
|
||||
</div>
|
||||
</p-dialog>
|
|
@ -1 +0,0 @@
|
|||
@import 'src/styles';
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CreateCategoryDialogComponent } from './create-category-dialog.component';
|
||||
|
||||
describe('CreateCategoryComponent', () => {
|
||||
let component: CreateCategoryDialogComponent;
|
||||
let fixture: ComponentFixture<CreateCategoryDialogComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ CreateCategoryDialogComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CreateCategoryDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,86 +0,0 @@
|
|||
import { CategoryFormComponent } from './../../forms/category-form/category-form.component';
|
||||
import { Category } from './../../../../shared/models/category.interface';
|
||||
import { CategoriesService } from '../../../../shared/services/administration/categories.service';
|
||||
import { Component, Input, OnInit, Output, EventEmitter, ViewChild } from '@angular/core';
|
||||
import { NotificationsHandlingService } from 'src/app/shared/services/notifications-handling/notifications-handling.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-create-category-dialog',
|
||||
templateUrl: './create-category-dialog.component.html',
|
||||
styleUrls: ['./create-category-dialog.component.scss']
|
||||
})
|
||||
export class CreateCategoryDialogComponent implements OnInit {
|
||||
|
||||
@ViewChild(CategoryFormComponent) private categoryForm: CategoryFormComponent;
|
||||
@Input() displayDialog: boolean;
|
||||
@Input() header: string;
|
||||
@Input() categoryToEdit: Category;
|
||||
@Output() cancelled = new EventEmitter<boolean>();
|
||||
@Output() valueChange = new EventEmitter<any>();
|
||||
|
||||
displayValidationMessagesEvenIfPristine: boolean;
|
||||
|
||||
constructor(private categoriesService: CategoriesService,
|
||||
private notificationHandling: NotificationsHandlingService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.reset(); // Make sure everything is cleanly initialised.
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.displayValidationMessagesEvenIfPristine = false;
|
||||
this.categoryForm?.resetForm();
|
||||
}
|
||||
|
||||
onShow() {
|
||||
// If a categoryToEdit was provided.
|
||||
if (this.categoryToEdit) {
|
||||
this.categoryForm.setValue(this.categoryToEdit);
|
||||
}
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.cancelled.emit(true);
|
||||
}
|
||||
|
||||
addCategory() {
|
||||
// If the form is not valid, make sure validator messages are displayed and then return without doing anything.
|
||||
if (!this.categoryForm.isValid()) {
|
||||
this.displayValidationMessagesEvenIfPristine = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: What is returned from backend on create()??
|
||||
this.categoriesService.createNewCategory(this.categoryForm.formValue()).subscribe(result => {
|
||||
this.valueChange.emit(result);
|
||||
this.notificationHandling.showCreateCategorySuccess();
|
||||
this.cancel();
|
||||
this.notificationHandling.showCreateNewCategorySuccess();
|
||||
|
||||
},
|
||||
error => {
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
editCategory() {
|
||||
// If the form is not valid, make sure validator messages are displayed and then return without doing anything.
|
||||
if (!this.categoryForm.isValid()) {
|
||||
this.displayValidationMessagesEvenIfPristine = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: What is returned from backend on create()??
|
||||
// TODO: It's to ugly having to provide the categoryId separately.
|
||||
this.categoriesService.updateCategory(this.categoryForm.formValue()).subscribe(result => {
|
||||
this.valueChange.emit(result);
|
||||
this.cancel();
|
||||
this.notificationHandling.showUpdateCategorySuccess();
|
||||
|
||||
},
|
||||
error => {
|
||||
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
<p-fieldset legend="Edit Value" [toggleable]="true">
|
||||
<app-configurator-form [editableParameter]="editParameterRequestInput" (valueChange)="passValueChange($event)"></app-configurator-form>
|
||||
</p-fieldset>
|
|
@ -1 +0,0 @@
|
|||
@import 'src/styles';
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ConfiguratorEditValueComponent } from './configurator-edit-value.component';
|
||||
|
||||
describe('ConfiguratorEditValueComponent', () => {
|
||||
let component: ConfiguratorEditValueComponent;
|
||||
let fixture: ComponentFixture<ConfiguratorEditValueComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ ConfiguratorEditValueComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ConfiguratorEditValueComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,28 +0,0 @@
|
|||
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||
import {ConfiguratorParameter} from "../../../../shared/models/configurator-parameter.interface";
|
||||
|
||||
@Component({
|
||||
selector: 'app-configurator-edit-value',
|
||||
templateUrl: './configurator-edit-value.component.html',
|
||||
styleUrls: ['./configurator-edit-value.component.scss']
|
||||
})
|
||||
export class ConfiguratorEditValueComponent implements OnInit {
|
||||
|
||||
@Input() editParameterRequestInput: ConfiguratorParameter;
|
||||
@Output() newConfiguratorParameter = new EventEmitter<ConfiguratorParameter>();
|
||||
|
||||
selectedParameter: ConfiguratorParameter = null;
|
||||
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
console.log('editParameterRequestInput in edit: ' + JSON.stringify(this.editParameterRequestInput));
|
||||
}
|
||||
|
||||
passValueChange(newConfigurator: ConfiguratorParameter) {
|
||||
this.newConfiguratorParameter.emit(newConfigurator);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
<p-fieldset legend="List of Parameters" [toggleable]="true">
|
||||
|
||||
<p-table [value]="parametersListInput"
|
||||
[lazy]="true"
|
||||
[loading]="loadingInput"
|
||||
[autoLayout]="true"
|
||||
[rowHover]="true"
|
||||
styleClass="p-datatable-gridlines"
|
||||
[(selection)]="selectedParameterRequest"
|
||||
(click)="passSelectedConfigurator(selectedParameterRequest)">
|
||||
<ng-template pTemplate="header">
|
||||
<tr>
|
||||
<th style="width: 3rem"></th>
|
||||
<th>Parameter Name</th>
|
||||
<th>Parameter Type</th>
|
||||
<th>Parameter Value </th>
|
||||
</tr>
|
||||
</ng-template>
|
||||
<ng-template pTemplate="body"
|
||||
let-parameter>
|
||||
<tr>
|
||||
<td>
|
||||
<p-tableRadioButton *ngIf="parameter.configurationVariable != 'CRON_EXPRESSION'" [value]="parameter"></p-tableRadioButton>
|
||||
</td>
|
||||
<td>{{parameter.configurationVariable}}</td>
|
||||
<td>{{parameter.variableType}}</td>
|
||||
<td>
|
||||
<span *ngIf="parameter.variableType === 'Integer'" >{{parameter.integerValue}}<br></span>
|
||||
<span *ngIf="parameter.variableType === 'String'" >{{parameter.stringValue}}<br></span>
|
||||
</td>
|
||||
<!-- <td *ngIf="parameter.variableType === 'Integer'">{{parameter.integerValue}}</td>
|
||||
<td *ngIf="parameter.variableType === 'String'">{{parameter.stringValue}}</td> -->
|
||||
<!-- Edit & Delete icons -->
|
||||
</tr>
|
||||
</ng-template>
|
||||
</p-table>
|
||||
|
||||
</p-fieldset>
|
|
@ -1 +0,0 @@
|
|||
@import 'src/styles';
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ConfiguratorListOfParametersComponent } from './configurator-list-of-parameters.component';
|
||||
|
||||
describe('ConfiguratorListOfParametersComponent', () => {
|
||||
let component: ConfiguratorListOfParametersComponent;
|
||||
let fixture: ComponentFixture<ConfiguratorListOfParametersComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ ConfiguratorListOfParametersComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ConfiguratorListOfParametersComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,40 +0,0 @@
|
|||
import {AfterViewChecked, AfterViewInit, Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||
import {ConfiguratorParameter} from '../../../../shared/models/configurator-parameter.interface';
|
||||
import {Page} from '../../../../shared/models/paging/page.interface';
|
||||
import {LazyLoadEvent} from 'primeng/api';
|
||||
|
||||
@Component({
|
||||
selector: 'app-configurator-list-of-parameters',
|
||||
templateUrl: './configurator-list-of-parameters.component.html',
|
||||
styleUrls: ['./configurator-list-of-parameters.component.scss']
|
||||
})
|
||||
export class ConfiguratorListOfParametersComponent implements OnInit {
|
||||
|
||||
@Input() parametersListInput: ConfiguratorParameter[];
|
||||
@Input() loadingInput: boolean;
|
||||
@Output() editEventRequest = new EventEmitter<ConfiguratorParameter>();
|
||||
|
||||
editParameterRequest: ConfiguratorParameter;
|
||||
parametersList: ConfiguratorParameter[];
|
||||
selectedParameterRequest: ConfiguratorParameter;
|
||||
totalRecords: number;
|
||||
rows = 10;
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
const initParameter: ConfiguratorParameter = {
|
||||
configurationId: null,
|
||||
configurationVariable: null,
|
||||
variableType: null,
|
||||
integerValue: null,
|
||||
stringValue: null
|
||||
};
|
||||
this.editEventRequest.emit(initParameter);
|
||||
}
|
||||
|
||||
passSelectedConfigurator(parameter: ConfiguratorParameter) {
|
||||
this.editEventRequest.emit(parameter);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
<div class="p-grid p-nogutter">
|
||||
<div class="p-col main-content">
|
||||
|
||||
<h1>{{'CONFIGURATOR' | translate}}</h1>
|
||||
|
||||
<app-horizontal-menu></app-horizontal-menu>
|
||||
|
||||
<app-breadcrumb></app-breadcrumb>
|
||||
|
||||
<div class="p-grid p-nogutter p-pt-5 p-pb-5">
|
||||
|
||||
<div class="p-col p-nogutter p-col-12">
|
||||
<app-configurator-list-of-parameters [parametersListInput]="parametersList"
|
||||
[loadingInput] = "loading"
|
||||
(editEventRequest)="editEvent($event)">
|
||||
</app-configurator-list-of-parameters>
|
||||
</div>
|
||||
|
||||
<div class="p-col p-nogutter p-col-12 p-mt-5">
|
||||
<app-configurator-edit-value [editParameterRequestInput]="editEventRequest" (newConfiguratorParameter)="passNewConfigurator($event)">
|
||||
</app-configurator-edit-value>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
|
@ -1 +0,0 @@
|
|||
@import 'src/styles';
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ConfiguratorComponent } from './configurator.component';
|
||||
|
||||
describe('ConfiguratorComponent', () => {
|
||||
let component: ConfiguratorComponent;
|
||||
let fixture: ComponentFixture<ConfiguratorComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ ConfiguratorComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ConfiguratorComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,51 +0,0 @@
|
|||
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||
import { ErrorHandlingService } from 'src/app/shared/services/error-handling/error-handling.service';
|
||||
import {ConfiguratorParameter} from '../../../shared/models/configurator-parameter.interface';
|
||||
import {ConfiguratorService} from "../../../shared/services/administration/configurator.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-configurator',
|
||||
templateUrl: './configurator.component.html',
|
||||
styleUrls: ['./configurator.component.scss']
|
||||
})
|
||||
export class ConfiguratorComponent implements OnInit {
|
||||
|
||||
// @Input() parametersListInput: [ConfiguratorParameter];
|
||||
// @Input() editParameterRequestInput: ConfiguratorParameter;
|
||||
// @Output() editEventRequest = new EventEmitter<ConfiguratorParameter>();
|
||||
|
||||
parametersList: ConfiguratorParameter[];
|
||||
editEventRequest: ConfiguratorParameter;
|
||||
loading = true;
|
||||
|
||||
constructor(private configuratorService: ConfiguratorService, private errorHandlingService: ErrorHandlingService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
|
||||
this.initData();
|
||||
console.log('this.parametersList: ' + JSON.stringify(this.parametersList));
|
||||
}
|
||||
|
||||
initData() {
|
||||
this.loading = true;
|
||||
this.configuratorService.getConfiguratorParameters().subscribe(values => {
|
||||
this.parametersList = values;
|
||||
this.loading = false;
|
||||
console.log('IN this.parametersList: ' + JSON.stringify(this.parametersList));
|
||||
},
|
||||
err => {
|
||||
this.errorHandlingService.showHttpResponseError(err);
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
editEvent(request) {
|
||||
this.editEventRequest = request;
|
||||
}
|
||||
|
||||
passNewConfigurator(newConfigurator: ConfiguratorParameter){
|
||||
this.initData();
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
<div [formGroup]="searchCriteriaForm">
|
||||
<div class="p-fluid p-grid">
|
||||
|
||||
<div class="p-col-12">
|
||||
<div class="p-grid p-formgrid">
|
||||
<div class="p-field p-col-12 p-sm-6 p-lg-3">
|
||||
<label for="dateFrom">
|
||||
Date From
|
||||
</label>
|
||||
<p-calendar id="dateFrom"
|
||||
formControlName="dateFrom"
|
||||
[maxDate]="searchCriteriaForm.get('dateFrom').value"
|
||||
[readonlyInput]="false"
|
||||
showButtonBar="true"
|
||||
todayButtonStyleClass="p-button-set-today"
|
||||
clearButtonStyleClass="p-button-clear-date"
|
||||
[showIcon]="true"
|
||||
dateFormat="dd/mm/yy">
|
||||
</p-calendar>
|
||||
</div>
|
||||
|
||||
<div class="p-field p-col-12 p-sm-6 p-lg-3">
|
||||
<label for="dateTo">
|
||||
Date To
|
||||
</label>
|
||||
<p-calendar id="dateTo"
|
||||
formControlName="dateTo"
|
||||
showButtonBar="true"
|
||||
[minDate]="searchCriteriaForm.get('dateTo').value"
|
||||
[readonlyInput]="false"
|
||||
todayButtonStyleClass="p-button-set-today"
|
||||
clearButtonStyleClass="p-button-clear-date"
|
||||
[showIcon]="true"
|
||||
dateFormat="dd/mm/yy">
|
||||
</p-calendar>
|
||||
</div>
|
||||
|
||||
<div class="p-field p-col-12 p-sm-6 p-lg-3">
|
||||
<label for="clientName">
|
||||
iPower Client Name
|
||||
</label>
|
||||
<p-autoComplete id="clientName"
|
||||
formControlName="clientName"
|
||||
[suggestions]="iPowerClientNameSuggestions"
|
||||
[forceSelection]="true"
|
||||
(completeMethod)="autosuggestIPowerClientName($event)"
|
||||
(onSelect)="iPowerClientNameSelected($event)">
|
||||
</p-autoComplete>
|
||||
</div>
|
||||
|
||||
<div class="p-field p-col-12 p-sm-6 p-lg-3">
|
||||
<label for="clientId">
|
||||
iPower Client Code
|
||||
</label>
|
||||
<p-autoComplete id="clientId"
|
||||
formControlName="clientId"
|
||||
[suggestions]="iPowerClientCodeSuggestions"
|
||||
[forceSelection]="true"
|
||||
(completeMethod)="autosuggestIPowerClientCode($event)"
|
||||
(onSelect)="iPowerClientCodeSelected($event)">
|
||||
</p-autoComplete>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-col-12">
|
||||
<div class="p-grid p-formgrid">
|
||||
<div class="p-field p-col-12 p-sm-6 p-lg-3">
|
||||
<label for="processId">
|
||||
Process Id
|
||||
</label>
|
||||
<input id="processId"
|
||||
type="text"
|
||||
pInputText
|
||||
formControlName="processId">
|
||||
</div>
|
||||
|
||||
<div class="p-field p-col-12 p-sm-6 p-lg-3">
|
||||
<label for="jobName">
|
||||
Job Name
|
||||
</label>
|
||||
<input id="jobName"
|
||||
type="text"
|
||||
pInputText
|
||||
formControlName="jobName">
|
||||
</div>
|
||||
|
||||
<div class="p-field p-col-12 p-sm-6 p-lg-3">
|
||||
<label for="dmsFileCode">
|
||||
File Code
|
||||
</label>
|
||||
<input id="dmsFileCode"
|
||||
type="text"
|
||||
pInputText
|
||||
formControlName="dmsFileCode">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
|
@ -1 +0,0 @@
|
|||
@import 'src/styles';
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ApplicationLevelFormComponent } from './application-level-form.component';
|
||||
|
||||
describe('ApplicationLevelFormComponent', () => {
|
||||
let component: ApplicationLevelFormComponent;
|
||||
let fixture: ComponentFixture<ApplicationLevelFormComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ ApplicationLevelFormComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ApplicationLevelFormComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,111 +0,0 @@
|
|||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { FormBuilder } from '@angular/forms';
|
||||
import { IPowerClient } from 'src/app/shared/models/ipower-client.interface';
|
||||
import { SearchSystemException} from 'src/app/shared/models/request/search-system-exceptions.interface';
|
||||
import { IpowerClientsService } from 'src/app/shared/services/administration/ipower-clients.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-application-level-form',
|
||||
templateUrl: './application-level-form.component.html',
|
||||
styleUrls: ['./application-level-form.component.scss']
|
||||
})
|
||||
export class ApplicationLevelFormComponent implements OnInit {
|
||||
|
||||
iPowerClientNameSuggestions: any;
|
||||
iPowerClientCodeSuggestions: any;
|
||||
private iPowerClientSuggestions: IPowerClient[];
|
||||
private selectedIPowerClient: IPowerClient;
|
||||
|
||||
searchCriteriaForm = this.fb.group({
|
||||
processId: [null],
|
||||
clientId: [null],
|
||||
clientName: [null],
|
||||
jobName: [null],
|
||||
dmsFileCode: [null],
|
||||
dateFrom: [null],
|
||||
dateTo: [null],
|
||||
});
|
||||
|
||||
constructor(private fb: FormBuilder, private iPowerClientsService: IpowerClientsService) { }
|
||||
|
||||
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
public formValue(): SearchSystemException {
|
||||
let formValue: SearchSystemException = {
|
||||
processId: this.searchCriteriaForm.get('processId').value,
|
||||
clientId: this.searchCriteriaForm.get('clientId').value,
|
||||
jobName: this.searchCriteriaForm.get('jobName').value,
|
||||
dmsFileCode: this.searchCriteriaForm.get('dmsFileCode').value,
|
||||
dateFrom: this.searchCriteriaForm.get('dateFrom').value,
|
||||
dateTo: this.searchCriteriaForm.get('dateTo').value
|
||||
};
|
||||
|
||||
formValue.dateFrom = new Date(Date.UTC(formValue.dateFrom?.getFullYear(), formValue.dateFrom?.getMonth(), formValue.dateFrom?.getDate()));
|
||||
formValue.dateTo = new Date(Date.UTC(formValue.dateTo?.getFullYear(), formValue.dateTo?.getMonth(),formValue.dateTo?.getDate() + 1));
|
||||
formValue.dateTo?.setMilliseconds(formValue.dateTo?.getMilliseconds() -1);
|
||||
|
||||
|
||||
return formValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Auto-suggest & Auto-complete IPower Client
|
||||
*/
|
||||
autosuggestIPowerClientName(event): void {
|
||||
|
||||
if (!event.query || event.query.length < 3) {
|
||||
this.iPowerClientNameSuggestions = [];
|
||||
return;
|
||||
}
|
||||
|
||||
this.iPowerClientsService.getClientsByNameOnly(event.query).subscribe(
|
||||
(values: IPowerClient[]) => {
|
||||
this.iPowerClientSuggestions = values;
|
||||
|
||||
const temp: string[] = [];
|
||||
values.map(val => temp.push(val.name));
|
||||
this.iPowerClientNameSuggestions = temp;
|
||||
},
|
||||
err => console.error(err) // TODO: Handle this via a Messaging Service
|
||||
);
|
||||
}
|
||||
|
||||
autosuggestIPowerClientCode(event): void {
|
||||
|
||||
if (event.query.length < 3) {
|
||||
this.iPowerClientCodeSuggestions = [];
|
||||
return;
|
||||
}
|
||||
|
||||
this.iPowerClientsService.getClientsByCodeOnly(event.query).subscribe(
|
||||
(values: IPowerClient[]) => {
|
||||
this.iPowerClientSuggestions = values;
|
||||
|
||||
const temp: string[] = [];
|
||||
values.map(val => temp.push(val.clientCode));
|
||||
this.iPowerClientCodeSuggestions = temp;
|
||||
},
|
||||
err => console.error(err)
|
||||
);
|
||||
}
|
||||
|
||||
iPowerClientNameSelected(name: string): void {
|
||||
this.selectedIPowerClient = this.iPowerClientSuggestions.find(client => client.name === name);
|
||||
this.searchCriteriaForm.get('clientId').patchValue(this.selectedIPowerClient ? this.selectedIPowerClient.clientCode : '');
|
||||
this.searchCriteriaForm.updateValueAndValidity();
|
||||
}
|
||||
|
||||
iPowerClientCodeSelected(code: string): void {
|
||||
this.selectedIPowerClient = this.iPowerClientSuggestions.find(client => client.clientCode === code);
|
||||
this.searchCriteriaForm.get('clientName').patchValue(this.selectedIPowerClient ? this.selectedIPowerClient.name : '');
|
||||
this.searchCriteriaForm.updateValueAndValidity();
|
||||
}
|
||||
|
||||
resetForm() {
|
||||
this.searchCriteriaForm.reset();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
<div [formGroup]="categoryForm">
|
||||
<div class="p-fluid p-formgrid"
|
||||
[ngClass]="{'p-grid': !dialogLayout}">
|
||||
|
||||
<div class="p-field"
|
||||
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
|
||||
<label for="document-classification">
|
||||
Document Classification
|
||||
</label>
|
||||
<p-dropdown inputId="document-classification"
|
||||
[options]="documentClassificationsList"
|
||||
optionLabel="classificationName"
|
||||
placeholder="Select"
|
||||
formControlName="documentClassification"
|
||||
[showClear]="true">
|
||||
</p-dropdown>
|
||||
<app-validation-message [control]="categoryForm.get('documentClassification')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
|
||||
<div class="p-field"
|
||||
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
|
||||
<label for="categoryName">
|
||||
Category Name
|
||||
</label>
|
||||
<p-autoComplete id="categoryName"
|
||||
formControlName="categoryName"
|
||||
*ngIf="autosuggestInputs"
|
||||
[suggestions]="categoryNameSuggestions"
|
||||
(completeMethod)="autosuggestCategoryName($event)"
|
||||
(onSelect)="categoryNameSelected($event)"
|
||||
[forceSelection]="true">
|
||||
</p-autoComplete>
|
||||
<input id="categoryName"
|
||||
type="text"
|
||||
pInputText
|
||||
formControlName="categoryName"
|
||||
*ngIf="!autosuggestInputs">
|
||||
<app-validation-message [control]="categoryForm.get('categoryName')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
|
||||
<div class="p-field"
|
||||
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
|
||||
<label for="categoryCode">
|
||||
Category Code
|
||||
</label>
|
||||
<p-autoComplete id="categoryCode"
|
||||
formControlName="categoryCode"
|
||||
*ngIf="autosuggestInputs"
|
||||
[suggestions]="categoryCodeSuggestions"
|
||||
(completeMethod)="autosuggestCategoryCode($event)"
|
||||
(onSelect)="categoryCodeSelected($event)"
|
||||
[forceSelection]="true">
|
||||
</p-autoComplete>
|
||||
<input id="categoryCode"
|
||||
type="text"
|
||||
pInputText
|
||||
formControlName="categoryCode"
|
||||
*ngIf="!autosuggestInputs">
|
||||
<app-validation-message [control]="categoryForm.get('categoryCode')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
|
@ -1 +0,0 @@
|
|||
@import 'src/styles';
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CategoryFormComponent } from './category-form.component';
|
||||
|
||||
describe('CategoryFormComponent', () => {
|
||||
let component: CategoryFormComponent;
|
||||
let fixture: ComponentFixture<CategoryFormComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ CategoryFormComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CategoryFormComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,183 +0,0 @@
|
|||
import { Category } from './../../../../shared/models/category.interface';
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { FormBuilder, Validators, FormGroup } from '@angular/forms';
|
||||
import { DocumentClassification } from 'src/app/shared/models/document-classification.interface';
|
||||
import { CategoriesService } from 'src/app/shared/services/administration/categories.service';
|
||||
import { DocumentClassificationsService } from 'src/app/shared/services/administration/document-classifications.service';
|
||||
import { ErrorHandlingService } from 'src/app/shared/services/error-handling/error-handling.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-category-form',
|
||||
templateUrl: './category-form.component.html',
|
||||
styleUrls: ['./category-form.component.scss']
|
||||
})
|
||||
export class CategoryFormComponent implements OnInit {
|
||||
|
||||
/*
|
||||
* Inputs
|
||||
*/
|
||||
@Input() dialogLayout: boolean = false; // Controls .scss classes to allow for better dispay in a dialog.
|
||||
@Input() requiredFields: string[] | boolean = false; // True/False indicates that all/none are required. String[] specifies the form controls required.
|
||||
@Input() displayValidationMessagesEvenIfPristine: boolean = false; // Serves for manually treating the controls as dirty.
|
||||
@Input() autosuggestInputs: boolean = false;
|
||||
|
||||
/*
|
||||
* Reactive Form
|
||||
*/
|
||||
categoryForm = this.fb.group({
|
||||
documentClassification: [null],
|
||||
categoryName: [null],
|
||||
categoryCode: [null]
|
||||
});
|
||||
|
||||
setFormValue: Category = null;
|
||||
selectedCategory: Category;
|
||||
|
||||
/*
|
||||
* Other Variables
|
||||
*/
|
||||
documentClassificationsList: DocumentClassification[];
|
||||
|
||||
categoryNameSuggestions: string[];
|
||||
categoryCodeSuggestions: string[];
|
||||
categorySuggestions: Category[];
|
||||
|
||||
/*
|
||||
* Constructor & Initialisers
|
||||
*/
|
||||
constructor(
|
||||
private fb: FormBuilder,
|
||||
private categoriesService: CategoriesService,
|
||||
private documentClassificationsService: DocumentClassificationsService,
|
||||
private errorHandlingService: ErrorHandlingService
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.initData();
|
||||
this.initValidators()
|
||||
}
|
||||
|
||||
initData() {
|
||||
this.documentClassificationsService.getAll().subscribe(
|
||||
value => this.documentClassificationsList = value,
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: Have this mechanism offer the use of custom validators too.
|
||||
initValidators() {
|
||||
|
||||
if (!this.requiredFields) { return; }
|
||||
|
||||
// In a true/false case.
|
||||
if (typeof this.requiredFields == 'boolean') {
|
||||
// If true, enable the required validator for all controls and sub-controls.
|
||||
if (this.requiredFields) {
|
||||
this.setRequiredValidatorRecursively(this.categoryForm);
|
||||
}
|
||||
|
||||
// If false, do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
// If it was a string array, enable the validators for all provided field-names. TODO: This ONLY supports 1st level controls and not nested ones.
|
||||
(<string[]>this.requiredFields).forEach(field => this.categoryForm.controls[field].setValidators(Validators.required))
|
||||
}
|
||||
|
||||
setRequiredValidatorRecursively(group: FormGroup) {
|
||||
Object.keys(group.controls).forEach(key => {
|
||||
group.controls[key].setValidators(Validators.required);
|
||||
|
||||
if (group.controls[key]['controls']) {
|
||||
this.setRequiredValidatorRecursively(<FormGroup>group.controls[key])
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Auto-suggest & Auto-complete Category
|
||||
*/
|
||||
autosuggestCategoryName(event) {
|
||||
|
||||
if (!event.query || event.query.length < 3) {
|
||||
this.categoryNameSuggestions = [];
|
||||
return;
|
||||
}
|
||||
|
||||
let classId = this.categoryForm.get('documentClassification').value ? this.categoryForm.get('documentClassification').value.classificationId : null;
|
||||
this.categoriesService.autosuggestCategoryName(event.query, classId).subscribe(
|
||||
(values: Category[]) => {
|
||||
let temp: string[] = [];
|
||||
this.categorySuggestions = values;
|
||||
values.map(val => temp.push(val.categoryName));
|
||||
this.categoryNameSuggestions = temp
|
||||
},
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
}
|
||||
|
||||
autosuggestCategoryCode(event) {
|
||||
|
||||
if (event.query.length < 3) {
|
||||
this.categoryCodeSuggestions = [];
|
||||
return;
|
||||
}
|
||||
|
||||
let classId = this.categoryForm.get('documentClassification').value ? this.categoryForm.get('documentClassification').value.classificationId : null;
|
||||
this.categoriesService.autosuggestCategoryCode(event.query, classId).subscribe(
|
||||
(values: Category[]) => {
|
||||
let temp: string[] = [];
|
||||
this.categorySuggestions = values;
|
||||
values.map(val => temp.push(val.categoryCode));
|
||||
this.categoryCodeSuggestions = temp
|
||||
},
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
}
|
||||
|
||||
categoryNameSelected(name: string) {
|
||||
this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryName == name);
|
||||
this.categoryForm.get('categoryCode').patchValue(this.selectedCategory.categoryCode);
|
||||
this.categoryForm.updateValueAndValidity();
|
||||
}
|
||||
|
||||
categoryCodeSelected(code: string) {
|
||||
this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryCode == code);
|
||||
this.categoryForm.get('categoryName').patchValue(this.selectedCategory.categoryName);
|
||||
this.categoryForm.updateValueAndValidity();
|
||||
}
|
||||
|
||||
/*
|
||||
* API methods
|
||||
*/
|
||||
public resetForm(): void {
|
||||
this.categoryForm.reset();
|
||||
}
|
||||
|
||||
public formValue(): Category {
|
||||
let formValue: Category = {
|
||||
id: this.setFormValue ? this.setFormValue.id : null,
|
||||
documentClassification: this.categoryForm.get('documentClassification').value,
|
||||
categoryName: this.categoryForm.get('categoryName').value,
|
||||
categoryCode: this.categoryForm.get('categoryCode').value
|
||||
};
|
||||
|
||||
return formValue;
|
||||
}
|
||||
|
||||
public setValue(value: Category): void {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setFormValue = value;
|
||||
this.categoryForm.get('documentClassification').setValue(value.documentClassification);
|
||||
this.categoryForm.get('categoryName').setValue(value.categoryName);
|
||||
this.categoryForm.get('categoryCode').setValue(value.categoryCode);
|
||||
this.categoryForm.updateValueAndValidity();
|
||||
}
|
||||
|
||||
public isValid(): boolean {
|
||||
return this.categoryForm.valid;
|
||||
}
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
<div [formGroup]="configuratorForm">
|
||||
<div class="p-fluid p-formgrid"
|
||||
[ngClass]="{'p-grid': !dialogLayout}">
|
||||
|
||||
<!-- Configurator Form - Start -->
|
||||
<div class="p-field p-col-12"
|
||||
[ngClass]="{'p-lg-4': !dialogLayout}">
|
||||
<label for="parameterName">Parameter Name</label>
|
||||
<input id="parameterName"
|
||||
type="text"
|
||||
pInputText
|
||||
disabled
|
||||
formControlName="parameterName"
|
||||
value="{{editableParameter?.configurationVariable}}">
|
||||
<app-validation-message [control]="configuratorForm.get('parameterName')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
|
||||
<div class="p-field p-col-12 "
|
||||
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
|
||||
<label for="parameterType">Parameter Type</label>
|
||||
<input id="parameterType"
|
||||
type="text"
|
||||
pInputText
|
||||
disabled
|
||||
formControlName="parameterType"
|
||||
value="{{editableParameter?.variableType}}">
|
||||
<app-validation-message [control]="configuratorForm.get('parameterType')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
|
||||
<div class="p-field p-col-12 "
|
||||
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
|
||||
<label for="parameterValue">Parameter Value</label>
|
||||
<input id="parameterValue"
|
||||
type="text"
|
||||
pInputText
|
||||
formControlName="parameterValue"
|
||||
value="{{editableParameter?.variableType == 'Integer' ? editableParameter?.integerValue : editableParameter?.stringValue}}">
|
||||
<app-validation-message [control]="configuratorForm.get('parameterValue')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="p-formgroup-inline p-jc-center p-mt-3">
|
||||
<p-button (onClick)="updateButtonClicked()"
|
||||
label="Update"
|
||||
styleClass="p-button-primary"
|
||||
[disabled]="!canEditParameterValue()">
|
||||
</p-button>
|
||||
</div>
|
||||
|
||||
</div>
|
|
@ -1 +0,0 @@
|
|||
@import 'src/styles';
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ConfiguratorFormComponent } from './configurator-form.component';
|
||||
|
||||
describe('ConfiguratorFormComponent', () => {
|
||||
let component: ConfiguratorFormComponent;
|
||||
let fixture: ComponentFixture<ConfiguratorFormComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ ConfiguratorFormComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ConfiguratorFormComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,69 +0,0 @@
|
|||
import { AfterViewChecked, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { FormBuilder } from '@angular/forms';
|
||||
import { ConfiguratorParameter } from '../../../../shared/models/configurator-parameter.interface';
|
||||
import { ConfiguratorService } from "../../../../shared/services/administration/configurator.service";
|
||||
import { Category } from "../../../../shared/models/category.interface";
|
||||
import { Router } from "@angular/router";
|
||||
import { NotificationsHandlingService } from 'src/app/shared/services/notifications-handling/notifications-handling.service';
|
||||
import { AuthService } from 'src/app/shared/services/auth.service';
|
||||
import { USER_RIGHTS } from 'src/app/shared/enums/USER_RIGHTS.enum';
|
||||
import { environment } from 'src/environments/environment';
|
||||
|
||||
@Component({
|
||||
selector: 'app-configurator-form',
|
||||
templateUrl: './configurator-form.component.html',
|
||||
styleUrls: ['./configurator-form.component.scss']
|
||||
})
|
||||
export class ConfiguratorFormComponent implements OnInit {
|
||||
|
||||
@Input() dialogLayout: boolean = false; // Controls .scss classes to allow for better dispay in a dialog.
|
||||
@Input() displayValidationMessagesEvenIfPristine: boolean = false; // Serves for manually treating the controls as dirty.
|
||||
@Input() editableParameter: ConfiguratorParameter;
|
||||
@Output() valueChange = new EventEmitter<ConfiguratorParameter>();
|
||||
|
||||
/*
|
||||
* Reactive Form
|
||||
*/
|
||||
configuratorForm = this.fb.group({
|
||||
parameterName: null,
|
||||
parameterType: null,
|
||||
parameterValue: null
|
||||
});
|
||||
|
||||
constructor(private fb: FormBuilder, private configuratorService: ConfiguratorService, private router: Router, private notificationService: NotificationsHandlingService,
|
||||
private authService: AuthService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
ngOnChanges(): void {
|
||||
}
|
||||
|
||||
public formValue(): ConfiguratorParameter {
|
||||
let formValue: ConfiguratorParameter = {
|
||||
configurationId: this.editableParameter.configurationId,
|
||||
configurationVariable: this.editableParameter.configurationVariable,
|
||||
variableType: this.editableParameter.variableType,
|
||||
integerValue: this.editableParameter.variableType === 'Integer' ? Number(this.configuratorForm.get('parameterValue').value) : null,
|
||||
stringValue: this.editableParameter.variableType === 'String' ? String(this.configuratorForm.get('parameterValue').value) : null
|
||||
};
|
||||
|
||||
return formValue;
|
||||
}
|
||||
|
||||
updateButtonClicked(): void {
|
||||
if (this.editableParameter.configurationId !== null) {
|
||||
this.configuratorService.updateConfiguratorParameter(this.formValue()).subscribe(result => {
|
||||
this.valueChange.emit(this.formValue());
|
||||
this.notificationService.showUpdateConfiguratorParameterSuccess();
|
||||
},
|
||||
error => {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
canEditParameterValue(): boolean {
|
||||
return this.authService.userHasRightForClient(USER_RIGHTS.J01, environment.globalRightsClientID) && this.editableParameter.configurationVariable != null;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,138 +0,0 @@
|
|||
<div [formGroup]="templateForm">
|
||||
<div class="p-fluid p-formgrid"
|
||||
[ngClass]="{'p-grid': !dialogLayout}">
|
||||
|
||||
<div class="p-field"
|
||||
*ngIf="!excludedFormControls?.includes('documentClassification')"
|
||||
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
|
||||
<label for="documentClassification">
|
||||
Document Classification
|
||||
</label>
|
||||
<p-dropdown inputId="documentClassification"
|
||||
[options]="documentClassificationsList"
|
||||
optionLabel="classificationName"
|
||||
placeholder="Select"
|
||||
formControlName="documentClassification"
|
||||
(onChange)="documentClassificationSelected($event.value)"
|
||||
[showClear]="true">
|
||||
</p-dropdown>
|
||||
<app-validation-message [control]="templateForm.get('documentClassification')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
|
||||
<div class="p-field"
|
||||
*ngIf="!excludedFormControls?.includes('categoryName')"
|
||||
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
|
||||
<label for="categoryName">
|
||||
Category Name
|
||||
</label>
|
||||
<p-autoComplete id="categoryName"
|
||||
formControlName="categoryName"
|
||||
[suggestions]="categoryNameSuggestions"
|
||||
[forceSelection]="true"
|
||||
(completeMethod)="autosuggestCategoryName($event)"
|
||||
(onSelect)="categoryNameSelected($event)">
|
||||
</p-autoComplete>
|
||||
<app-validation-message [control]="templateForm.get('categoryName')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
|
||||
<div class="p-field"
|
||||
*ngIf="!excludedFormControls?.includes('categoryName')"
|
||||
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
|
||||
<label for="categoryCode">
|
||||
Category Code
|
||||
</label>
|
||||
<p-autoComplete id="categoryCode"
|
||||
formControlName="categoryCode"
|
||||
[suggestions]="categoryCodeSuggestions"
|
||||
[forceSelection]="true"
|
||||
(completeMethod)="autosuggestCategoryCode($event)"
|
||||
(onSelect)="categoryCodeSelected($event)">
|
||||
</p-autoComplete>
|
||||
<app-validation-message [control]="templateForm.get('categoryCode')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
|
||||
<div class="p-field"
|
||||
*ngIf="!excludedFormControls?.includes('iPowerClient')"
|
||||
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
|
||||
<label for="iPowerClientName">
|
||||
iPower Client Name
|
||||
</label>
|
||||
<p-autoComplete id="iPowerClientName"
|
||||
formControlName="iPowerClientName"
|
||||
[suggestions]="iPowerClientNameSuggestions"
|
||||
[forceSelection]="true"
|
||||
(completeMethod)="autosuggestIPowerClientName($event)"
|
||||
(onSelect)="iPowerClientNameSelected($event)">
|
||||
</p-autoComplete>
|
||||
<app-validation-message [control]="templateForm.get('iPowerClientName')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
|
||||
<div class="p-field"
|
||||
*ngIf="!excludedFormControls?.includes('iPowerClient')"
|
||||
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
|
||||
<label for="iPowerClientCode">
|
||||
iPower Client Code
|
||||
</label>
|
||||
<p-autoComplete id="iPowerClientCode"
|
||||
formControlName="iPowerClientCode"
|
||||
[suggestions]="iPowerClientCodeSuggestions"
|
||||
[forceSelection]="true"
|
||||
(completeMethod)="autosuggestIPowerClientCode($event)"
|
||||
(onSelect)="iPowerClientCodeSelected($event)">
|
||||
</p-autoComplete>
|
||||
<app-validation-message [control]="templateForm.get('iPowerClientCode')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
|
||||
<div class="p-field"
|
||||
*ngIf="!excludedFormControls?.includes('documentSubclassification')"
|
||||
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
|
||||
<label for="documentSubclassification">
|
||||
Sub-Category Name
|
||||
</label>
|
||||
<p-dropdown inputId="documentSubclassification"
|
||||
[options]="availableDocumentSubclassifications"
|
||||
[disabled]="subCategoryCodeDisabled"
|
||||
optionLabel="subclassificationName"
|
||||
placeholder="Select a Document Classification first"
|
||||
formControlName="documentSubclassification">
|
||||
</p-dropdown>
|
||||
<app-validation-message [control]="templateForm.get('documentSubclassification')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
|
||||
<div class="p-field"
|
||||
*ngIf="!excludedFormControls?.includes('abbyyTemplateCode')"
|
||||
[ngClass]="{'p-col-12 p-lg-4': !dialogLayout}">
|
||||
<label for="abbyyTemplateCode"
|
||||
>
|
||||
ABBYY Template Code
|
||||
</label>
|
||||
<input id="abbyyTemplateCode"
|
||||
type="text"
|
||||
pInputText
|
||||
formControlName="abbyyTemplateCode">
|
||||
<app-validation-message [control]="templateForm.get('abbyyTemplateCode')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
|
@ -1 +0,0 @@
|
|||
@import 'src/styles';
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { TemplateFormComponent } from './template-form.component';
|
||||
|
||||
describe('TemplateFormComponent', () => {
|
||||
let component: TemplateFormComponent;
|
||||
let fixture: ComponentFixture<TemplateFormComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ TemplateFormComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(TemplateFormComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,369 +0,0 @@
|
|||
import { DocumentClassification } from './../../../../shared/models/document-classification.interface';
|
||||
import { Category } from './../../../../shared/models/category.interface';
|
||||
import { DocumentSubclassificationsService } from './../../../../shared/services/administration/document-subclassifications.service';
|
||||
import { DocumentSubclassification } from './../../../../shared/models/document-subclassification.interface';
|
||||
import { IPowerClient } from './../../../../shared/models/ipower-client.interface';
|
||||
import { Template } from './../../../../shared/models/template.interface';
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { FormBuilder, Validators } from '@angular/forms';
|
||||
import { CategoriesService } from 'src/app/shared/services/administration/categories.service';
|
||||
import { DocumentClassificationsService } from 'src/app/shared/services/administration/document-classifications.service';
|
||||
import { IpowerClientsService } from 'src/app/shared/services/administration/ipower-clients.service';
|
||||
import { ErrorHandlingService } from 'src/app/shared/services/error-handling/error-handling.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-template-form',
|
||||
templateUrl: './template-form.component.html',
|
||||
styleUrls: ['./template-form.component.scss']
|
||||
})
|
||||
export class TemplateFormComponent implements OnInit {
|
||||
|
||||
/*
|
||||
* Inputs
|
||||
*/
|
||||
@Input() dialogLayout: boolean = false; // Controls .scss classes to allow for better dispay in a dialog.
|
||||
@Input() requiredFields: string[] | boolean = false; // True/False indicates that all/none are required. String[] specifies the form controls required.
|
||||
@Input() displayValidationMessagesEvenIfPristine: boolean = false; // Serves for manually treating the controls as dirty.
|
||||
@Input() excludedFormControls: string[]; // Specifies the form controls to be removed and NOT displayed.
|
||||
|
||||
/*
|
||||
* Reactive Form
|
||||
*/
|
||||
templateForm = this.fb.group({
|
||||
documentClassification: [null],
|
||||
categoryName: [null],
|
||||
categoryCode: [null],
|
||||
iPowerClientName: [null],
|
||||
iPowerClientCode: [null],
|
||||
documentSubclassification: [null],
|
||||
abbyyTemplateCode: [null]
|
||||
});
|
||||
initiallySetFormValue: Template;
|
||||
|
||||
/*
|
||||
* Other Variables
|
||||
*/
|
||||
documentClassificationsList: DocumentClassification[];
|
||||
|
||||
categoryNameSuggestions: string[];
|
||||
categoryCodeSuggestions: string[];
|
||||
categorySuggestions: Category[];
|
||||
selectedCategory: Category;
|
||||
|
||||
iPowerClientNameSuggestions: string[];
|
||||
iPowerClientCodeSuggestions: string[];
|
||||
iPowerClientSuggestions: IPowerClient[];
|
||||
selectedIPowerClient: IPowerClient;
|
||||
|
||||
documentSubclassificationsList: DocumentSubclassification[];
|
||||
availableDocumentSubclassifications: DocumentSubclassification[];
|
||||
subCategoryCodeDisabled: boolean = true;
|
||||
|
||||
/*
|
||||
* Constructor & Initialisers
|
||||
*/
|
||||
constructor(
|
||||
private fb: FormBuilder,
|
||||
private documentClassificationsService: DocumentClassificationsService,
|
||||
private categoriesService: CategoriesService,
|
||||
private iPowerClientsService: IpowerClientsService,
|
||||
private documentSubclassificationsService: DocumentSubclassificationsService,
|
||||
private errorHandlingService: ErrorHandlingService
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.initData();
|
||||
this.initValidators()
|
||||
this.excludeFields();
|
||||
}
|
||||
|
||||
initData() {
|
||||
this.documentClassificationsService.getAll().subscribe(
|
||||
value => this.documentClassificationsList = value,
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
|
||||
// This is NOT the list of Subclassifications used for the dropdown.
|
||||
this.documentSubclassificationsService.getAll().subscribe(
|
||||
value => this.documentSubclassificationsList = value,
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: Have this mechanism offer the use of custom validators too.
|
||||
initValidators() {
|
||||
|
||||
if (!this.requiredFields) { return; }
|
||||
|
||||
// In a true/false case.
|
||||
if (typeof this.requiredFields == 'boolean') {
|
||||
// If true, enable the required validator for all controls.
|
||||
if (this.requiredFields) {
|
||||
Object.keys(this.templateForm.controls).forEach(key => this.templateForm.controls[key].setValidators(Validators.required));
|
||||
}
|
||||
|
||||
// If false, do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
// If it was a string array, enable the validators for all provided field-names.
|
||||
(<string[]>this.requiredFields).forEach(field => this.templateForm.controls[field].setValidators(Validators.required))
|
||||
}
|
||||
|
||||
excludeFields() {
|
||||
if (!this.excludedFormControls) { return; }
|
||||
this.excludedFormControls.forEach(field => this.templateForm.removeControl(field));
|
||||
}
|
||||
|
||||
/*
|
||||
* Auto-suggest & Auto-complete Category
|
||||
*/
|
||||
autosuggestCategoryName(event) {
|
||||
|
||||
if (!event.query || event.query.length < 3) {
|
||||
this.categoryNameSuggestions = [];
|
||||
return;
|
||||
}
|
||||
|
||||
let classId = this.templateForm.get('documentClassification').value ? this.templateForm.get('documentClassification').value.classificationId : null;
|
||||
this.categoriesService.autosuggestCategoryName(event.query, classId).subscribe(
|
||||
(values: Category[]) => {
|
||||
let temp: string[] = [];
|
||||
this.categorySuggestions = values;
|
||||
values.map(val => temp.push(val.categoryName));
|
||||
this.categoryNameSuggestions = temp
|
||||
},
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
}
|
||||
|
||||
autosuggestCategoryCode(event) {
|
||||
|
||||
if (event.query.length < 3) {
|
||||
this.categoryCodeSuggestions = [];
|
||||
return;
|
||||
}
|
||||
|
||||
let classId = this.templateForm.get('documentClassification').value ? this.templateForm.get('documentClassification').value.classificationId : null;
|
||||
this.categoriesService.autosuggestCategoryCode(event.query, classId).subscribe(
|
||||
(values: Category[]) => {
|
||||
let temp: string[] = [];
|
||||
this.categorySuggestions = values;
|
||||
values.map(val => temp.push(val.categoryCode));
|
||||
this.categoryCodeSuggestions = temp
|
||||
},
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
}
|
||||
|
||||
categoryNameSelected(name: string) {
|
||||
this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryName == name);
|
||||
this.templateForm.get('categoryCode')?.patchValue(this.selectedCategory.categoryCode);
|
||||
this.templateForm.updateValueAndValidity();
|
||||
}
|
||||
|
||||
categoryCodeSelected(code: string) {
|
||||
this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryCode == code);
|
||||
this.templateForm.get('categoryName')?.patchValue(this.selectedCategory?.categoryName);
|
||||
this.templateForm.updateValueAndValidity();
|
||||
}
|
||||
|
||||
/*
|
||||
* Auto-suggest & Auto-complete IPower Client
|
||||
*/
|
||||
autosuggestIPowerClientName(event): void {
|
||||
|
||||
if (!event.query || event.query.length < 3) {
|
||||
this.iPowerClientNameSuggestions = [];
|
||||
return;
|
||||
}
|
||||
|
||||
this.iPowerClientsService.getClientsByNameOnly(event.query).subscribe(
|
||||
(values: IPowerClient[]) => {
|
||||
this.iPowerClientSuggestions = values;
|
||||
|
||||
const temp: string[] = [];
|
||||
values.map(val => temp.push(val.name));
|
||||
this.iPowerClientNameSuggestions = temp;
|
||||
},
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
}
|
||||
|
||||
autosuggestIPowerClientCode(event): void {
|
||||
|
||||
if (event.query.length < 3) {
|
||||
this.iPowerClientCodeSuggestions = [];
|
||||
return;
|
||||
}
|
||||
|
||||
this.iPowerClientsService.getClientsByCodeOnly(event.query).subscribe(
|
||||
(values: IPowerClient[]) => {
|
||||
this.iPowerClientSuggestions = values;
|
||||
|
||||
const temp: string[] = [];
|
||||
values.map(val => temp.push(val.clientCode));
|
||||
this.iPowerClientCodeSuggestions = temp;
|
||||
},
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
}
|
||||
|
||||
iPowerClientNameSelected(name: string) {
|
||||
this.selectedIPowerClient = this.iPowerClientSuggestions.find(client => client.name == name);
|
||||
this.templateForm.get('iPowerClientCode')?.patchValue(this.selectedIPowerClient ? this.selectedIPowerClient.clientCode : '');
|
||||
this.templateForm.updateValueAndValidity();
|
||||
}
|
||||
|
||||
iPowerClientCodeSelected(code: string) {
|
||||
this.selectedIPowerClient = this.iPowerClientSuggestions.find(client => client.clientCode == code);
|
||||
this.templateForm.get('iPowerClientName')?.patchValue(this.selectedIPowerClient ? this.selectedIPowerClient.name : '');
|
||||
this.templateForm.updateValueAndValidity();
|
||||
}
|
||||
|
||||
/*
|
||||
* Other Methods
|
||||
*/
|
||||
documentClassificationSelected(selection: DocumentClassification) {
|
||||
this.availableDocumentSubclassifications = this.documentSubclassificationsList.filter(element => element.documentClassification.classificationId == selection.classificationId);
|
||||
this.templateForm.get('documentSubclassification')?.setValue(this.availableDocumentSubclassifications[0]); //TODO CHECK
|
||||
this.subCategoryCodeDisabled = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility Methods
|
||||
*/
|
||||
// Auto-suggest inputs - We have to ensure our reactive form holds values that represent the selectedCategory, otherwise truncate it.
|
||||
syncSelectedCategory() {
|
||||
|
||||
// Ιf our form has no value, truncate the selectedCategory either way.
|
||||
if (!this.templateForm.get('categoryName')?.value && !this.templateForm.get('categoryCode').value) {
|
||||
this.selectedCategory = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// If both or either of our form's values match the selectedCategory's and the other one doesn't have a value, all is good.
|
||||
// Just sync the values in case one is missing. Otherwise truncate the selectedCategory.
|
||||
if (
|
||||
this.templateForm.get('categoryName')?.value == this.selectedCategory.categoryName
|
||||
|| this.templateForm.get('categoryCode')?.value == this.selectedCategory.categoryCode
|
||||
) {
|
||||
this.selectedCategory.categoryName = this.templateForm.get('categoryName')?.value;
|
||||
this.selectedCategory.categoryCode = this.templateForm.get('categoryCode')?.value;
|
||||
}
|
||||
|
||||
// If both our values were different from the selectedCategory's, truncate it. This is an extremely abnormal scenario.
|
||||
else {
|
||||
console.error('WARNING - syncSelectedCategory()', 'Both of our form\'s values were different from the selectedCategory\'s.');
|
||||
this.selectedCategory = null;
|
||||
this.templateForm.get('categoryName')?.setValue('');
|
||||
this.templateForm.get('categoryCode')?.setValue('');
|
||||
this.templateForm.updateValueAndValidity();
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-suggest inputs - We have to ensure our reactive form holds values that represent the selectedIPowerClient, otherwise truncate it.
|
||||
syncSelectedIPowerClient() {
|
||||
|
||||
// Ιf our form has no value, truncate the selectedIPowerClient either way.
|
||||
if (!this.templateForm.get('iPowerClientName')?.value && !this.templateForm.get('iPowerClientCode')?.value) {
|
||||
this.selectedIPowerClient = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// If both or either of our form's values match the selectedIPowerClient's and the other one doesn't have a value, all is good.
|
||||
// Just sync the values in case one is missing. Otherwise truncate the selectedIPowerClient.
|
||||
if (
|
||||
this.templateForm.get('iPowerClientName')?.value == this.selectedIPowerClient.name
|
||||
|| this.templateForm.get('iPowerClientCode')?.value == this.selectedIPowerClient.clientCode
|
||||
) {
|
||||
this.selectedIPowerClient.name = this.templateForm.get('iPowerClientName')?.value;
|
||||
this.selectedIPowerClient.clientCode = this.templateForm.get('iPowerClientCode')?.value;
|
||||
}
|
||||
|
||||
// If both our values were different from the selectedIPowerClient's, truncate it. This is an extremely abnormal scenario.
|
||||
else {
|
||||
console.error('WARNING - syncSelectedIPowerClient()', 'Both of our form\'s values were different from the selectedIPowerClient\'s.');
|
||||
this.selectedIPowerClient = null;
|
||||
this.templateForm.get('iPowerClientName')?.setValue('');
|
||||
this.templateForm.get('iPowerClientCode')?.setValue('');
|
||||
this.templateForm.updateValueAndValidity();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* API methods
|
||||
*/
|
||||
public resetForm(): void {
|
||||
this.templateForm.reset();
|
||||
this.selectedCategory = null;
|
||||
this.selectedIPowerClient = null;
|
||||
}
|
||||
|
||||
public formValue(): Template {
|
||||
|
||||
// A field ('documentSubclassification') may be excluded, so we have to check for that too.
|
||||
let subCatCode = this.templateForm.get('documentSubclassification') ? this.templateForm.get('documentSubclassification').value : null;
|
||||
let abbyy = this.templateForm.get('abbyyTemplateCode') ? this.templateForm.get('abbyyTemplateCode').value : null;
|
||||
let docClass = this.templateForm.get('documentClassification') ? this.templateForm.get('documentClassification').value : null;
|
||||
|
||||
// We keep track of those two using object-variables separate from our ReactiveForm.
|
||||
// Thus, we now have to make sure the ReactiveForm really has values that match those objects, before we forward them.
|
||||
// Also, keep in mind that our auto-suggest inputs limit the user in choosing one of their values.
|
||||
this.syncSelectedCategory();
|
||||
this.syncSelectedIPowerClient();
|
||||
|
||||
let formValue: Template = {
|
||||
id: this.initiallySetFormValue ? this.initiallySetFormValue.id : null,
|
||||
category: this.selectedCategory,
|
||||
subCategoryCode: subCatCode ? subCatCode.subclassificationName : '',
|
||||
abbyyTemplate: abbyy,
|
||||
client: this.selectedIPowerClient,
|
||||
documentClassification: docClass
|
||||
};
|
||||
|
||||
return formValue;
|
||||
}
|
||||
|
||||
public setValue(value: Template): void {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.initiallySetFormValue = value;
|
||||
|
||||
// If a documentClassification is already selected, enable the subclassification dropdown.
|
||||
this.subCategoryCodeDisabled = !value.documentClassification;
|
||||
|
||||
this.templateForm.get('documentClassification')?.setValue(value.documentClassification);
|
||||
// Having set the documentClassification -and provided there was one- we must also set the availableDocumentSubclassifications.
|
||||
this.availableDocumentSubclassifications = this.documentSubclassificationsList.filter(element =>
|
||||
element.documentClassification.classificationId == value.documentClassification.classificationId
|
||||
);
|
||||
|
||||
this.selectedCategory = value.category;
|
||||
this.templateForm.get('categoryName')?.setValue(value.category.categoryName);
|
||||
this.templateForm.get('categoryCode')?.setValue(value.category.categoryCode);
|
||||
|
||||
this.selectedIPowerClient = value.client;
|
||||
this.templateForm.get('iPowerClientName')?.setValue(value.client.name);
|
||||
this.templateForm.get('iPowerClientCode')?.setValue(value.client.clientCode);
|
||||
|
||||
this.templateForm.get('abbyyTemplateCode')?.setValue(value.abbyyTemplate);
|
||||
|
||||
// To set the subcategory/subclassification we also have to make sure the documentClassification is the same.
|
||||
// WARNING: Since we have enabled the [forceSelection] option of the <p-autoComplete>,
|
||||
// if the availableDocumentSubclassifications are not set, documentSubclassification won't be displayed.
|
||||
this.templateForm.get('documentSubclassification').setValue(
|
||||
this.documentSubclassificationsList.find(subClass => (
|
||||
subClass.subclassificationName == value.subCategoryCode && subClass.documentClassification.classificationId == value.documentClassification.classificationId
|
||||
))
|
||||
);
|
||||
|
||||
this.templateForm.updateValueAndValidity();
|
||||
}
|
||||
|
||||
public isValid(): boolean {
|
||||
return this.templateForm.valid;
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
import { JournalVerification } from './../../../../shared/models/journal-verification.interface';
|
||||
import { CapturingVerification } from './../../../../shared/models/capturing-verification.interface';
|
||||
import { Template } from 'src/app/shared/models/template.interface';
|
||||
|
||||
export interface CreateVerificationRuleFormValue {
|
||||
id: number;
|
||||
confidenceLevelMinThreshold: number;
|
||||
clientId: string
|
||||
categoryId: number;
|
||||
subCategoryCode: string;
|
||||
verificationRuleStatus: string;
|
||||
capturingVerification: CapturingVerification;
|
||||
journalVerification: JournalVerification;
|
||||
alteryxRoutineId: string;
|
||||
template: Template;
|
||||
}
|
|
@ -1,200 +0,0 @@
|
|||
<div [formGroup]="verificationRuleForm">
|
||||
|
||||
<div class="p-fluid"
|
||||
[ngClass]="{'p-formgrid': !dialogLayout}">
|
||||
|
||||
<div class="p-grid">
|
||||
<div class="p-field p-col-12 p-lg-6">
|
||||
<label for="document-classification">
|
||||
Document Classification
|
||||
</label>
|
||||
<p-dropdown inputId="document-classification"
|
||||
[options]="documentClassificationsList"
|
||||
optionLabel="classificationName"
|
||||
placeholder="Select"
|
||||
formControlName="documentClassification"
|
||||
[disabled]="editMode"
|
||||
(onChange)="documentClassificationSelected($event)">
|
||||
</p-dropdown>
|
||||
<app-validation-message [control]="verificationRuleForm.get('documentClassification')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-grid">
|
||||
<div class="p-field p-col-12 p-lg-6">
|
||||
<label for="ipower-name">
|
||||
iPower Client Name
|
||||
</label>
|
||||
<p-autoComplete id="ipower-name"
|
||||
formControlName="ipowerName"
|
||||
[suggestions]="iPowerClientNameSuggestions"
|
||||
[forceSelection]="true"
|
||||
(completeMethod)="autosuggestIPowerClientName($event)"
|
||||
[disabled]="editMode"
|
||||
(onSelect)="iPowerClientNameSelected($event)">
|
||||
</p-autoComplete>
|
||||
<app-validation-message [control]="verificationRuleForm.get('ipowerName')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
|
||||
<div class="p-field p-col-12 p-lg-6">
|
||||
<label for="ipower-code">
|
||||
iPower Client Code
|
||||
</label>
|
||||
<p-autoComplete id="ipower-code"
|
||||
formControlName="ipowerCode"
|
||||
[suggestions]="iPowerClientCodeSuggestions"
|
||||
[forceSelection]="true"
|
||||
(completeMethod)="autosuggestIPowerClientCode($event)"
|
||||
[disabled]="editMode"
|
||||
(onSelect)="iPowerClientCodeSelected($event)">
|
||||
</p-autoComplete>
|
||||
<app-validation-message [control]="verificationRuleForm.get('ipowerCode')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-grid">
|
||||
<div class="p-field p-col-12 p-lg-6">
|
||||
<label for="category-name">
|
||||
Category Name
|
||||
</label>
|
||||
<p-autoComplete id="category-name"
|
||||
formControlName="categoryName"
|
||||
[suggestions]="categoryNameSuggestions"
|
||||
[forceSelection]="true"
|
||||
(completeMethod)="autosuggestCategoryName($event)"
|
||||
[disabled]="editMode"
|
||||
(onSelect)="categoryNameSelected($event)">
|
||||
</p-autoComplete>
|
||||
<app-validation-message [control]="verificationRuleForm.get('categoryName')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
|
||||
<div class="p-field p-col-12 p-lg-6">
|
||||
<label for="category-code">
|
||||
Category Code
|
||||
</label>
|
||||
<p-autoComplete id="category-code"
|
||||
formControlName="categoryCode"
|
||||
[suggestions]="categoryCodeSuggestions"
|
||||
[forceSelection]="true"
|
||||
(completeMethod)="autosuggestCategoryCode($event)"
|
||||
[disabled]="editMode"
|
||||
(onSelect)="categoryCodeSelected($event)">
|
||||
</p-autoComplete>
|
||||
<app-validation-message [control]="verificationRuleForm.get('categoryCode')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-grid">
|
||||
<div class="p-field p-col-12 p-lg-6">
|
||||
<label for="document-subclassification">
|
||||
Sub-Category Name
|
||||
</label>
|
||||
<p-dropdown inputId="document-subclassification"
|
||||
[options]="availableDocumentSubclassifications"
|
||||
[disabled]="subCategoryCodeDisabled || editMode"
|
||||
optionLabel="subclassificationName"
|
||||
placeholder="Select a Document Classification first"
|
||||
formControlName="subCategoryCode">
|
||||
</p-dropdown>
|
||||
<app-validation-message [control]="verificationRuleForm.get('subCategoryCode')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-grid"
|
||||
[ngClass]="{'p-pt-4': (initiallySetFormValue && initiallySetFormValue.id)}">
|
||||
<div class="p-field p-col-12 p-lg-6">
|
||||
<label for="capturing-verification">
|
||||
Capturing Verification
|
||||
</label>
|
||||
<p-dropdown inputId="capturing-verification"
|
||||
formControlName="capturingVerification"
|
||||
[options]="capturingVerificationsList"
|
||||
optionLabel="capturingVerificationName"
|
||||
placeholder="Select">
|
||||
</p-dropdown>
|
||||
<app-validation-message [control]="verificationRuleForm.get('capturingVerification')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
|
||||
<div class="p-field p-col-12 p-lg-6">
|
||||
<label for="journal-verification">
|
||||
Journal Verification
|
||||
</label>
|
||||
<p-dropdown inputId="journal-verification"
|
||||
formControlName="journalVerification"
|
||||
[options]="journalVerificationsList"
|
||||
optionLabel="journalVerificationName"
|
||||
placeholder="Select">
|
||||
</p-dropdown>
|
||||
<app-validation-message [control]="verificationRuleForm.get('journalVerification')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-grid">
|
||||
<div class="p-field p-col-12 p-lg-6">
|
||||
<label for="confidence-level">
|
||||
Confidence Level
|
||||
</label>
|
||||
<input id="confidence-level"
|
||||
type="number"
|
||||
pInputText
|
||||
formControlName="confidenceLevelMinThreshold">
|
||||
<app-validation-message [control]="verificationRuleForm.get('confidenceLevelMinThreshold')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
|
||||
<div class="p-field p-col-12 p-lg-6">
|
||||
<label for="alteryx-routine-id">
|
||||
Alteryx Routine Name
|
||||
</label>
|
||||
<input id="alteryx-routine-id"
|
||||
type="text"
|
||||
pInputText
|
||||
formControlName="alteryxRoutineId">
|
||||
<app-validation-message [control]="verificationRuleForm.get('alteryxRoutineId')"
|
||||
[validationMessage]="'This field is required.'"
|
||||
[displayEvenIfPristine]="displayValidationMessagesEvenIfPristine">
|
||||
</app-validation-message>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-grid p-jc-center" *ngIf="editMode">
|
||||
<div class="p-field p-col-5 p-m-2">
|
||||
</div>
|
||||
|
||||
<div class="p-field p-col-5 p-m-2">
|
||||
<p-checkbox id="verification-rule-status" name="verification-rule-status"
|
||||
[formControl]="verificationRuleForm.get('verificationRuleStatus')" binary="true" label="Rule Status"
|
||||
[disabled]="!canEditRuleStatus()">
|
||||
</p-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
|
@ -1 +0,0 @@
|
|||
@import 'src/styles';
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { VerificationRuleFormComponent } from './verification-rule-form.component';
|
||||
|
||||
describe('VerificationRuleFormComponent', () => {
|
||||
let component: VerificationRuleFormComponent;
|
||||
let fixture: ComponentFixture<VerificationRuleFormComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ VerificationRuleFormComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(VerificationRuleFormComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,527 +0,0 @@
|
|||
import { Right } from './../../../../shared/models/right.interface';
|
||||
import { environment } from './../../../../../environments/environment';
|
||||
import { USER_RIGHTS } from './../../../../shared/enums/USER_RIGHTS.enum';
|
||||
import { AuthService } from 'src/app/shared/services/auth.service';
|
||||
import { CreateVerificationRuleFormValue } from './create-verification-rule-form-value.interface';
|
||||
import { JournalVerificationsService } from './../../../../shared/services/administration/journal-verifications.service';
|
||||
import { CapturingVerificationsService } from './../../../../shared/services/administration/capturing-verifications.service';
|
||||
import { DocumentSubclassificationsService } from 'src/app/shared/services/administration/document-subclassifications.service';
|
||||
import { IpowerClientsService } from 'src/app/shared/services/administration/ipower-clients.service';
|
||||
import { CategoriesService } from 'src/app/shared/services/administration/categories.service';
|
||||
import { DocumentClassificationsService } from 'src/app/shared/services/administration/document-classifications.service';
|
||||
import { FormBuilder, Validators } from '@angular/forms';
|
||||
import { DocumentSubclassification } from 'src/app/shared/models/document-subclassification.interface';
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { CapturingVerification } from '../../../../shared/models/capturing-verification.interface';
|
||||
import { Category } from '../../../../shared/models/category.interface';
|
||||
import { IPowerClient } from '../../../../shared/models/ipower-client.interface';
|
||||
import { JournalVerification } from '../../../../shared/models/journal-verification.interface';
|
||||
import { VerificationRule } from './../../../../shared/models/verification-rule.interface';
|
||||
import { DocumentClassification } from '../../../../shared/models/document-classification.interface';
|
||||
import { ErrorHandlingService } from 'src/app/shared/services/error-handling/error-handling.service';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'app-verification-rule-form',
|
||||
templateUrl: './verification-rule-form.component.html',
|
||||
styleUrls: ['./verification-rule-form.component.scss']
|
||||
})
|
||||
export class VerificationRuleFormComponent implements OnInit {
|
||||
|
||||
/*
|
||||
* Inputs
|
||||
*/
|
||||
@Input() dialogLayout: boolean = false; // Controls .scss classes to allow for better dispay in a dialog.
|
||||
@Input() requiredFields: string[] | boolean = false; // True/False indicates that all/none are required. String[] specifies the form controls required.
|
||||
@Input() displayValidationMessagesEvenIfPristine: boolean = false; // Serves for manually treating the controls as dirty.
|
||||
@Input() excludedFormControls: string[]; // Specifies the form controls to be removed and NOT displayed.
|
||||
|
||||
/*
|
||||
* Reactive Form
|
||||
*/
|
||||
verificationRuleForm = this.fb.group({
|
||||
documentClassification: [null],
|
||||
ipowerName: [null],
|
||||
ipowerCode: [null],
|
||||
categoryName: [null],
|
||||
categoryCode: [null],
|
||||
subCategoryCode: [null], // This actually represents the complete DocumentSubclassification object.
|
||||
confidenceLevelMinThreshold: [null],
|
||||
capturingVerification: [null],
|
||||
journalVerification: [null],
|
||||
alteryxRoutineId: [null],
|
||||
verificationRuleStatus: [true],
|
||||
template: [null]
|
||||
});
|
||||
initiallySetFormValue: VerificationRule;
|
||||
editMode: boolean = false;
|
||||
|
||||
/*
|
||||
* Other Variables
|
||||
*/
|
||||
documentClassificationsList: DocumentClassification[];
|
||||
|
||||
categoryNameSuggestions: string[];
|
||||
categoryCodeSuggestions: string[];
|
||||
categorySuggestions: Category[];
|
||||
selectedCategory: Category;
|
||||
|
||||
iPowerClientNameSuggestions: string[];
|
||||
iPowerClientCodeSuggestions: string[];
|
||||
iPowerClientSuggestions: IPowerClient[];
|
||||
selectedIPowerClient: IPowerClient;
|
||||
|
||||
capturingVerificationsList: CapturingVerification[];
|
||||
journalVerificationsList: JournalVerification[];
|
||||
|
||||
documentSubclassificationsList: DocumentSubclassification[];
|
||||
availableDocumentSubclassifications: DocumentSubclassification[];
|
||||
subCategoryCodeDisabled: boolean = true;
|
||||
|
||||
/*
|
||||
* Constructor & Initialisers
|
||||
*/
|
||||
constructor(
|
||||
private fb: FormBuilder,
|
||||
private documentClassificationsService: DocumentClassificationsService,
|
||||
private categoriesService: CategoriesService,
|
||||
private iPowerClientsService: IpowerClientsService,
|
||||
private documentSubclassificationsService: DocumentSubclassificationsService,
|
||||
private capturingVerificationsService: CapturingVerificationsService,
|
||||
private journalVerificationsService: JournalVerificationsService,
|
||||
private authService: AuthService,
|
||||
private errorHandlingService: ErrorHandlingService
|
||||
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.initData();
|
||||
this.initValidators()
|
||||
this.excludeFields();
|
||||
}
|
||||
|
||||
initData() {
|
||||
this.documentClassificationsService.getAll().subscribe(
|
||||
value => this.documentClassificationsList = value,
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
|
||||
// This is NOT the list of Subclassifications used for the dropdown.
|
||||
this.documentSubclassificationsService.getAll().subscribe(
|
||||
value => this.documentSubclassificationsList = value,
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
|
||||
this.journalVerificationsService.getJournalVerifications().subscribe(
|
||||
values => this.journalVerificationsList = values,
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
|
||||
this.capturingVerificationsService.getCapturingVerifications().subscribe(
|
||||
values => this.capturingVerificationsList = values,
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: Have this mechanism offer the use of custom validators too.
|
||||
initValidators() {
|
||||
|
||||
if (!this.requiredFields) { return; }
|
||||
|
||||
// In a true/false case.
|
||||
if (typeof this.requiredFields == 'boolean') {
|
||||
// If true, enable the required validator for all controls.
|
||||
if (this.requiredFields) {
|
||||
Object.keys(this.verificationRuleForm.controls).forEach(key => this.verificationRuleForm.controls[key].setValidators(Validators.required));
|
||||
}
|
||||
|
||||
// If false, do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
// If it was a string array, enable the validators for all provided field-names.
|
||||
(<string[]>this.requiredFields).forEach(field => this.verificationRuleForm.controls[field].setValidators(Validators.required))
|
||||
}
|
||||
|
||||
excludeFields() {
|
||||
if (!this.excludedFormControls) { return; }
|
||||
this.excludedFormControls.forEach(field => this.verificationRuleForm.removeControl(field));
|
||||
}
|
||||
|
||||
/*
|
||||
* Auto-suggest & Auto-complete Category
|
||||
*/
|
||||
autosuggestCategoryName(event) {
|
||||
|
||||
if (!event.query || event.query.length < 3) {
|
||||
this.categoryNameSuggestions = [];
|
||||
return;
|
||||
}
|
||||
|
||||
let classId = this.verificationRuleForm.get('documentClassification').value ? this.verificationRuleForm.get('documentClassification').value.classificationId : null;
|
||||
this.categoriesService.autosuggestCategoryName(event.query, classId).subscribe(
|
||||
(values: Category[]) => {
|
||||
let temp: string[] = [];
|
||||
this.categorySuggestions = values;
|
||||
values.map(val => temp.push(val.categoryName));
|
||||
this.categoryNameSuggestions = temp
|
||||
},
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
}
|
||||
|
||||
autosuggestCategoryCode(event) {
|
||||
|
||||
if (event.query.length < 3) {
|
||||
this.categoryCodeSuggestions = [];
|
||||
return;
|
||||
}
|
||||
|
||||
let classId = this.verificationRuleForm.get('documentClassification').value ? this.verificationRuleForm.get('documentClassification').value.classificationId : null;
|
||||
this.categoriesService.autosuggestCategoryCode(event.query, classId).subscribe(
|
||||
(values: Category[]) => {
|
||||
let temp: string[] = [];
|
||||
this.categorySuggestions = values;
|
||||
values.map(val => temp.push(val.categoryCode));
|
||||
this.categoryCodeSuggestions = temp
|
||||
},
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
}
|
||||
|
||||
categoryNameSelected(name: string) {
|
||||
this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryName == name);
|
||||
this.verificationRuleForm.get('categoryCode').patchValue(this.selectedCategory.categoryCode);
|
||||
this.verificationRuleForm.updateValueAndValidity();
|
||||
}
|
||||
|
||||
categoryCodeSelected(code: string) {
|
||||
this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryCode == code);
|
||||
this.verificationRuleForm.get('categoryName').patchValue(this.selectedCategory.categoryName);
|
||||
this.verificationRuleForm.updateValueAndValidity();
|
||||
}
|
||||
|
||||
// /*
|
||||
// * Auto-suggest & Auto-complete IPower Client
|
||||
// */
|
||||
// /*
|
||||
// * Rights-check Warning:
|
||||
// * If we are NOT in editMode (and are thus on "addMode"), we should only suggest clients for which we actually CAN add a new rule.
|
||||
// * Note:
|
||||
// * I know that if on editMode the client-input is disabled and thus this check is redundant,
|
||||
// * but I think it is better to work with as an abstract perspective as possible, not entailing business logic that may either be unrelated or prone to changes.
|
||||
// */
|
||||
// autosuggestIPowerClientName(event) {
|
||||
|
||||
// if (!event.query || event.query.length < 3) {
|
||||
// this.iPowerClientNameSuggestions = [];
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // If the user has the right to preview all rules (B01), we use the endpoint that returns all iPowerClients,
|
||||
// // otherwise, the one that checks for the user's User_Access too. Whether the user can see ANY rule has already been handled by the 'search' button.
|
||||
// let endpointToSubscribeTo: Observable<IPowerClient[]> = USER_RIGHTS.B01.isGrantedToUser(
|
||||
// this.authService.userRights.find(rbc => rbc.client.id == environment.globalRightsClientID)?.rights
|
||||
// )
|
||||
// ? this.iPowerClientsService.getClientsByNameOnly(event.query)
|
||||
// : this.iPowerClientsService.getClientsByNameDistinct(event.query);
|
||||
|
||||
// endpointToSubscribeTo.subscribe(
|
||||
// (values: IPowerClient[]) => {
|
||||
|
||||
// // ***See comment at method level***
|
||||
// if (!this.editMode) {
|
||||
// values = values.filter(client => USER_RIGHTS.B03.isGrantedToUser(
|
||||
// this.authService.userRights.find(rdc => rdc.client.id == client.id)?.rights
|
||||
// ));
|
||||
// }
|
||||
|
||||
// let temp: string[] = [];
|
||||
// this.iPowerClientSuggestions = values;
|
||||
// values.map(val => temp.push(val.name));
|
||||
// this.iPowerClientNameSuggestions = temp
|
||||
// },
|
||||
// err => this.errorHandlingService.showHttpResponseError(err)
|
||||
// );
|
||||
// }
|
||||
|
||||
// /*
|
||||
// * Rights-check Warning:
|
||||
// * If we are NOT in editMode (and are thus on "addMode"), we should only suggest clients for which we actually CAN add a new rule.
|
||||
// * Note:
|
||||
// * I know that if on editMode the client-input is disabled and thus this check is redundant,
|
||||
// * but I think it is better to work with as an abstract perspective as possible, not entailing business logic that may either be unrelated or prone to changes.
|
||||
// */
|
||||
// autosuggestIPowerClientCode(event) {
|
||||
|
||||
// if (event.query.length < 3) {
|
||||
// this.iPowerClientCodeSuggestions = [];
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // If the user has the right to preview all rules (B01), we use the endpoint that returns all iPowerClients,
|
||||
// // otherwise, the one that checks for the user's User_Access too. Whether the user can see ANY rule has already been handled by the 'search' button.
|
||||
// let endpointToSubscribeTo: Observable<IPowerClient[]> = USER_RIGHTS.B01.isGrantedToUser(
|
||||
// this.authService.userRights.find(rbc => rbc.client.id == environment.globalRightsClientID)?.rights
|
||||
// )
|
||||
// ? this.iPowerClientsService.getClientsByCodeOnly(event.query): null;
|
||||
|
||||
// endpointToSubscribeTo.subscribe(
|
||||
// (values: IPowerClient[]) => {
|
||||
|
||||
// // ***See comment at method level***
|
||||
// if (!this.editMode) {
|
||||
// values = values;
|
||||
// }
|
||||
|
||||
// let temp: string[] = [];
|
||||
// this.iPowerClientSuggestions = values;
|
||||
// values.map(val => temp.push(val.clientCode));
|
||||
// this.iPowerClientCodeSuggestions = temp
|
||||
// },
|
||||
// err => this.errorHandlingService.showHttpResponseError(err)
|
||||
// );
|
||||
// }
|
||||
|
||||
|
||||
/*
|
||||
* Auto-suggest & Auto-complete IPower Client
|
||||
*/
|
||||
autosuggestIPowerClientName(event): void {
|
||||
|
||||
if (!event.query || event.query.length < 3) {
|
||||
this.iPowerClientNameSuggestions = [];
|
||||
return;
|
||||
}
|
||||
|
||||
this.iPowerClientsService.getClientsByNameOnly(event.query).subscribe(
|
||||
(values: IPowerClient[]) => {
|
||||
this.iPowerClientSuggestions = values;
|
||||
|
||||
const temp: string[] = [];
|
||||
values.map(val => temp.push(val.name));
|
||||
this.iPowerClientNameSuggestions = temp;
|
||||
},
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
}
|
||||
|
||||
autosuggestIPowerClientCode(event): void {
|
||||
|
||||
if (event.query.length < 3) {
|
||||
this.iPowerClientCodeSuggestions = [];
|
||||
return;
|
||||
}
|
||||
|
||||
this.iPowerClientsService.getClientsByCodeOnly(event.query).subscribe(
|
||||
(values: IPowerClient[]) => {
|
||||
this.iPowerClientSuggestions = values;
|
||||
|
||||
const temp: string[] = [];
|
||||
values.map(val => temp.push(val.clientCode));
|
||||
this.iPowerClientCodeSuggestions = temp;
|
||||
},
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
}
|
||||
|
||||
iPowerClientNameSelected(name: string) {
|
||||
this.selectedIPowerClient = this.iPowerClientSuggestions.find(client => client.name == name);
|
||||
this.verificationRuleForm.get('ipowerCode').patchValue(this.selectedIPowerClient.clientCode);
|
||||
this.verificationRuleForm.updateValueAndValidity();
|
||||
}
|
||||
|
||||
iPowerClientCodeSelected(code: string) {
|
||||
this.selectedIPowerClient = this.iPowerClientSuggestions.find(client => client.clientCode == code);
|
||||
this.verificationRuleForm.get('ipowerName').patchValue(this.selectedIPowerClient.name);
|
||||
this.verificationRuleForm.updateValueAndValidity();
|
||||
}
|
||||
|
||||
/*
|
||||
* Other Methods
|
||||
*/
|
||||
documentClassificationSelected(selection) {
|
||||
this.availableDocumentSubclassifications = this.documentSubclassificationsList.filter(element => element.documentClassification.classificationId == selection.value.classificationId);
|
||||
this.verificationRuleForm.get('subCategoryCode').setValue(this.availableDocumentSubclassifications[0]);
|
||||
this.subCategoryCodeDisabled = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility Methods
|
||||
*/
|
||||
initiateEditMode() {
|
||||
// let controlsToDisableInEditMode = ['documentClassification', 'ipowerName', 'ipowerCode', 'categoryName', 'categoryCode', 'subCategoryCode']
|
||||
// controlsToDisableInEditMode.forEach(ctrl => this.verificationRuleForm.get(ctrl).disable());
|
||||
}
|
||||
|
||||
|
||||
// Auto-suggest inputs - We have to ensure our reactive form holds values that represent the selectedCategory, otherwise truncate it.
|
||||
syncSelectedCategory() {
|
||||
|
||||
// Ιf our form has no value, truncate the selectedCategory either way.
|
||||
if (!this.verificationRuleForm.get('categoryName').value && !this.verificationRuleForm.get('categoryCode').value) {
|
||||
this.selectedCategory = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// If both or either of our form's values match the selectedCategory's and the other one doesn't have a value, all is good.
|
||||
// Just sync the values in case one is missing. Otherwise truncate the selectedCategory.
|
||||
if (
|
||||
this.verificationRuleForm.get('categoryName').value == this.selectedCategory.categoryName
|
||||
|| this.verificationRuleForm.get('categoryCode').value == this.selectedCategory.categoryCode
|
||||
) {
|
||||
this.selectedCategory.categoryName = this.verificationRuleForm.get('categoryName').value;
|
||||
this.selectedCategory.categoryCode = this.verificationRuleForm.get('categoryCode').value;
|
||||
}
|
||||
|
||||
// If both our values were different from the selectedCategory's, truncate it. This is an extremely abnormal scenario.
|
||||
else {
|
||||
console.error('WARNING - syncSelectedCategory()', 'Both of our form\'s values were different from the selectedCategory\'s.');
|
||||
this.selectedCategory = null;
|
||||
this.verificationRuleForm.get('categoryName').setValue('');
|
||||
this.verificationRuleForm.get('categoryCode').setValue('');
|
||||
this.verificationRuleForm.updateValueAndValidity();
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-suggest inputs - We have to ensure our reactive form holds values that represent the selectedIPowerClient, otherwise truncate it.
|
||||
syncSelectedIPowerClient() {
|
||||
|
||||
// Ιf our form has no value, truncate the selectedIPowerClient either way.
|
||||
if (!this.verificationRuleForm.get('ipowerName').value && !this.verificationRuleForm.get('ipowerCode').value) {
|
||||
this.selectedIPowerClient = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// If both or either of our form's values match the selectedIPowerClient's and the other one doesn't have a value, all is good.
|
||||
// Just sync the values in case one is missing. Otherwise truncate the selectedIPowerClient.
|
||||
if (
|
||||
this.verificationRuleForm.get('ipowerName').value == this.selectedIPowerClient.name
|
||||
|| this.verificationRuleForm.get('ipowerCode').value == this.selectedIPowerClient.clientCode
|
||||
) {
|
||||
this.selectedIPowerClient.name = this.verificationRuleForm.get('ipowerName').value;
|
||||
this.selectedIPowerClient.clientCode = this.verificationRuleForm.get('ipowerCode').value;
|
||||
}
|
||||
|
||||
// If both our values were different from the selectedIPowerClient's, truncate it. This is an extremely abnormal scenario.
|
||||
else {
|
||||
console.error('WARNING - syncSelectedIPowerClient()', 'Both of our form\'s values were different from the selectedIPowerClient\'s.');
|
||||
this.selectedIPowerClient = null;
|
||||
this.verificationRuleForm.get('ipowerName').setValue('');
|
||||
this.verificationRuleForm.get('ipowerCode').setValue('');
|
||||
this.verificationRuleForm.updateValueAndValidity();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Rights-check Methods
|
||||
*/
|
||||
canEditRuleStatus(): boolean {
|
||||
if (this.initiallySetFormValue) {
|
||||
return this.authService.userHasRightForClient(USER_RIGHTS.B06, environment.globalRightsClientID);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// canEditConfidenceLevel(): boolean {
|
||||
// if (this.initiallySetFormValue) {
|
||||
// return this.authService.userHasRightForClient(USER_RIGHTS.B07, this.initiallySetFormValue.client.id);
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
|
||||
/*
|
||||
* API methods
|
||||
*/
|
||||
public resetForm(): void {
|
||||
this.verificationRuleForm.reset();
|
||||
this.selectedCategory = null;
|
||||
this.selectedIPowerClient = null;
|
||||
this.editMode = null;
|
||||
}
|
||||
|
||||
public formValue(): CreateVerificationRuleFormValue {
|
||||
|
||||
// We keep track of those two using object-variables separate from our ReactiveForm.
|
||||
// Thus, we now have to make sure the ReactiveForm really has values that match those objects, before we forward them.
|
||||
// Also, keep in mind that our auto-suggest inputs limit the user in choosing one of their values.
|
||||
this.syncSelectedCategory();
|
||||
this.syncSelectedIPowerClient();
|
||||
|
||||
let formValue: CreateVerificationRuleFormValue = {
|
||||
id: this.initiallySetFormValue ? this.initiallySetFormValue.id : null,
|
||||
confidenceLevelMinThreshold: this.verificationRuleForm.get('confidenceLevelMinThreshold').value,
|
||||
clientId: this.selectedIPowerClient ? this.selectedIPowerClient.id : null,
|
||||
categoryId: this.selectedCategory ? this.selectedCategory.id : null,
|
||||
// The backend only requires the subcategory's name, and not the whole object. Don't ask me.
|
||||
subCategoryCode: this.verificationRuleForm.get('subCategoryCode').value ? this.verificationRuleForm.get('subCategoryCode').value['subclassificationName'] : '',
|
||||
capturingVerification: this.verificationRuleForm.get('capturingVerification').value,
|
||||
journalVerification: this.verificationRuleForm.get('journalVerification').value,
|
||||
alteryxRoutineId: this.verificationRuleForm.get('alteryxRoutineId').value,
|
||||
template: this.verificationRuleForm.get('template').value,
|
||||
|
||||
// Convert 'verificationRuleStatus' from boolean to string.
|
||||
verificationRuleStatus: this.verificationRuleForm.get('verificationRuleStatus').value ? 'Enabled' : 'Disabled'
|
||||
};
|
||||
|
||||
return formValue;
|
||||
}
|
||||
|
||||
public setValue(value: VerificationRule): void {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.editMode = true;
|
||||
this.initiateEditMode();
|
||||
|
||||
this.initiallySetFormValue = value
|
||||
|
||||
// If a documentClassification is already selected, enable the subclassification dropdown.
|
||||
this.subCategoryCodeDisabled = !value.docClassificationCategory;
|
||||
|
||||
this.verificationRuleForm.get('documentClassification').setValue(value.docClassificationCategory);
|
||||
// Having set the documentClassification -and provided there was one- we must also set the availableDocumentSubclassifications.
|
||||
this.availableDocumentSubclassifications = this.documentSubclassificationsList.filter(element =>
|
||||
element.documentClassification.classificationId == value.docClassificationCategory.classificationId
|
||||
);
|
||||
|
||||
this.verificationRuleForm.get('ipowerName').setValue(value.client.name);
|
||||
this.verificationRuleForm.get('ipowerCode').setValue(value.client.clientCode);
|
||||
this.selectedIPowerClient = value.client;
|
||||
|
||||
this.verificationRuleForm.get('categoryName').setValue(value.template.category.categoryName);
|
||||
this.verificationRuleForm.get('categoryCode').setValue(value.template.category.categoryCode);
|
||||
this.selectedCategory = value.template.category;
|
||||
|
||||
this.verificationRuleForm.get('confidenceLevelMinThreshold').setValue(value.confidenceLevelMinThreshold);
|
||||
this.verificationRuleForm.get('capturingVerification').setValue(value.capturingVerification);
|
||||
this.verificationRuleForm.get('journalVerification').setValue(value.journalVerification);
|
||||
this.verificationRuleForm.get('alteryxRoutineId').setValue(value.alteryxRoutineId);
|
||||
this.verificationRuleForm.get('template').setValue(value.template);
|
||||
|
||||
// Convert 'verificationRuleStatus' from string to boolean.
|
||||
this.verificationRuleForm.get('verificationRuleStatus').setValue(value.verificationRuleStatus.trim().toLowerCase() == 'enabled');
|
||||
|
||||
// To set the subcategory/subclassification we also have to make sure the documentClassification is the same.
|
||||
// WARNING: Since we have enabled the [forceSelection] option of the <p-autoComplete>,
|
||||
// if the availableDocumentSubclassifications are not set, documentSubclassification won't be displayed.
|
||||
this.verificationRuleForm.get('subCategoryCode').setValue(
|
||||
this.documentSubclassificationsList.find(subClass =>
|
||||
subClass.subclassificationName == value.template.subCategoryCode && subClass.documentClassification.classificationId == value.docClassificationCategory.classificationId
|
||||
)
|
||||
);
|
||||
|
||||
this.verificationRuleForm.updateValueAndValidity();
|
||||
}
|
||||
|
||||
public isValid(): boolean {
|
||||
return this.verificationRuleForm.valid;
|
||||
}
|
||||
|
||||
public initForCreation() {
|
||||
this.editMode = false;
|
||||
this.verificationRuleForm.get('verificationRuleStatus').setValue(true); // The default value in creation mode.
|
||||
this.verificationRuleForm.get('template').setValidators(null); // 'template' is not required during the creation.
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
export interface VerificationRuleSearchFormValue {
|
||||
clientId: string;
|
||||
categoryId: number;
|
||||
docClassificationId: number;
|
||||
docSubcategory: string;
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
<div [formGroup]="verificationRuleForm">
|
||||
<div class="p-fluid p-grid">
|
||||
|
||||
<div class="p-col-12 p-lg-8">
|
||||
<div class="p-grid p-formgrid">
|
||||
<div class="p-field p-col-12 p-lg-6">
|
||||
<label for="ipower-name">
|
||||
iPower Client Name
|
||||
</label>
|
||||
<p-autoComplete id="ipower-name"
|
||||
formControlName="ipowerName"
|
||||
[suggestions]="ipowerClientNameSuggestions"
|
||||
(completeMethod)="autosuggestIPowerClientName($event)"
|
||||
(onSelect)="ipowerClientNameSelected($event)"
|
||||
[forceSelection]="true">
|
||||
</p-autoComplete>
|
||||
</div>
|
||||
|
||||
<div class="p-field p-col-12 p-lg-6">
|
||||
<label for="ipower-code">
|
||||
iPower Client Code
|
||||
</label>
|
||||
<p-autoComplete id="ipower-code"
|
||||
formControlName="ipowerCode"
|
||||
[suggestions]="ipowerClientCodeSuggestions"
|
||||
(completeMethod)="autosuggestIPowerClientCode($event)"
|
||||
(onSelect)="ipowerClientCodeSelected($event)"
|
||||
[forceSelection]="true">
|
||||
</p-autoComplete>
|
||||
</div>
|
||||
|
||||
<div class="p-field p-col-12 p-lg-6">
|
||||
<label for="category-name">
|
||||
Category Name
|
||||
</label>
|
||||
<p-autoComplete id="category-name"
|
||||
formControlName="categoryName"
|
||||
[suggestions]="categoryNameSuggestions"
|
||||
(completeMethod)="autosuggestCategoryName($event)"
|
||||
(onSelect)="categoryNameSelected($event)"
|
||||
[forceSelection]="true">
|
||||
</p-autoComplete>
|
||||
</div>
|
||||
|
||||
<div class="p-field p-col-12 p-lg-6">
|
||||
<label for="category-code">
|
||||
Category Code
|
||||
</label>
|
||||
<p-autoComplete id="category-code"
|
||||
formControlName="categoryCode"
|
||||
[suggestions]="categoryCodeSuggestions"
|
||||
(completeMethod)="autosuggestCategoryCode($event)"
|
||||
(onSelect)="categoryCodeSelected($event)"
|
||||
[forceSelection]="true">
|
||||
</p-autoComplete>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-col-12 p-lg-4">
|
||||
<div class="p-grid p-formgrid">
|
||||
<div class="p-field p-col-12">
|
||||
<label for="document-classification">
|
||||
Document Classification
|
||||
</label>
|
||||
<p-dropdown inputId="document-classification"
|
||||
[options]="documentClassificationsList"
|
||||
optionLabel="classificationName"
|
||||
placeholder="Select"
|
||||
formControlName="documentClassification"
|
||||
(onChange)="documentClassificationSelected($event.value)"
|
||||
[showClear]="true">
|
||||
</p-dropdown>
|
||||
</div>
|
||||
|
||||
<div class="p-field p-col-12">
|
||||
<label for="subCategoryCode">
|
||||
Document Subclassification
|
||||
</label>
|
||||
<p-dropdown inputId="subCategoryCode"
|
||||
[options]="availableDocumentSubclassifications"
|
||||
optionLabel="subclassificationName"
|
||||
placeholder="Select"
|
||||
formControlName="subCategoryCode"
|
||||
(onChange)="documentSubclassificationSelected($event.value)"
|
||||
[showClear]="true">
|
||||
</p-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
|
@ -1 +0,0 @@
|
|||
@import 'src/styles';
|
|
@ -1,25 +0,0 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { VerificationRuleSearchFormComponent } from './verification-rule-search-form.component';
|
||||
|
||||
describe('VerificationRuleSearchFormComponent', () => {
|
||||
let component: VerificationRuleSearchFormComponent;
|
||||
let fixture: ComponentFixture<VerificationRuleSearchFormComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ VerificationRuleSearchFormComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(VerificationRuleSearchFormComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,358 +0,0 @@
|
|||
import { VerificationRulesService } from './../../../../shared/services/administration/verification-rules.service';
|
||||
import { VerificationRule } from './../../../../shared/models/verification-rule.interface';
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { AbstractControl, FormBuilder } from '@angular/forms';
|
||||
import { Category } from 'src/app/shared/models/category.interface';
|
||||
import { DocumentClassification } from 'src/app/shared/models/document-classification.interface';
|
||||
import { DocumentSubclassification } from 'src/app/shared/models/document-subclassification.interface';
|
||||
import { IPowerClient } from 'src/app/shared/models/ipower-client.interface';
|
||||
import { CategoriesService } from 'src/app/shared/services/administration/categories.service';
|
||||
import { DocumentClassificationsService } from 'src/app/shared/services/administration/document-classifications.service';
|
||||
import { DocumentSubclassificationsService } from 'src/app/shared/services/administration/document-subclassifications.service';
|
||||
import { IpowerClientsService } from 'src/app/shared/services/administration/ipower-clients.service';
|
||||
import { VerificationRuleSearchFormValue } from './verification-rule-search-form-value.interface';
|
||||
import { ErrorHandlingService } from 'src/app/shared/services/error-handling/error-handling.service';
|
||||
import { USER_RIGHTS } from 'src/app/shared/enums/USER_RIGHTS.enum';
|
||||
import { AuthService } from 'src/app/shared/services/auth.service';
|
||||
import { Observable } from 'rxjs';
|
||||
import { environment } from 'src/environments/environment';
|
||||
|
||||
@Component({
|
||||
selector: 'app-verification-rule-search-form',
|
||||
templateUrl: './verification-rule-search-form.component.html',
|
||||
styleUrls: ['./verification-rule-search-form.component.scss']
|
||||
})
|
||||
export class VerificationRuleSearchFormComponent implements OnInit {
|
||||
|
||||
@Input() disabled: boolean = false;
|
||||
|
||||
documentClassificationsList: DocumentClassification[];
|
||||
documentSubclassificationsList: DocumentSubclassification[];
|
||||
availableDocumentSubclassifications: DocumentSubclassification[];
|
||||
previouslySelectedClassificationId: number;
|
||||
|
||||
categoryNameSuggestions: string[];
|
||||
categoryCodeSuggestions: string[];
|
||||
categorySuggestions: Category[];
|
||||
selectedCategory: Category = null;
|
||||
|
||||
ipowerClientNameSuggestions: string[];
|
||||
ipowerClientCodeSuggestions: string[];
|
||||
ipowerClientSuggestions: IPowerClient[];
|
||||
selectedIPowerClient: IPowerClient = null;
|
||||
|
||||
displayValidationMessagesEvenIfPristine: boolean;
|
||||
|
||||
verificationRuleForm = this.fb.group({
|
||||
ipowerName: [null],
|
||||
ipowerCode: [null],
|
||||
categoryName: [null],
|
||||
categoryCode: [null],
|
||||
documentClassification: [null],
|
||||
subCategoryCode: [null] // This actually represents the complete DocumentSubclassification object.
|
||||
});
|
||||
|
||||
constructor(
|
||||
private fb: FormBuilder,
|
||||
private documentClassificationsService: DocumentClassificationsService,
|
||||
private documentSubclassificationsService: DocumentSubclassificationsService,
|
||||
private verificationRulesService: VerificationRulesService,
|
||||
private categoriesService: CategoriesService,
|
||||
private ipowerClientsService: IpowerClientsService,
|
||||
private errorHandlingService: ErrorHandlingService,
|
||||
private authService: AuthService
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
|
||||
if (this.disabled) {
|
||||
Object.keys(this.verificationRuleForm.controls).forEach(ctrl => this.verificationRuleForm.get(ctrl).disable());
|
||||
return; // Don't even bother initialising or requesting anything.
|
||||
}
|
||||
|
||||
this.initData();
|
||||
}
|
||||
|
||||
initData() {
|
||||
this.documentClassificationsService.getAll().subscribe(
|
||||
value => this.documentClassificationsList = value,
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
|
||||
// This is NOT the list of Subclassifications used for the dropdown.
|
||||
this.documentSubclassificationsService.getAll().subscribe(
|
||||
value => {
|
||||
this.documentSubclassificationsList = value;
|
||||
this.availableDocumentSubclassifications = value;
|
||||
},
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.verificationRuleForm.reset();
|
||||
|
||||
this.selectedCategory = null;
|
||||
this.selectedIPowerClient = null;
|
||||
}
|
||||
|
||||
documentClassificationSelected(selection: DocumentClassification) {
|
||||
|
||||
// If a different Classification has been selected, reset the Subclassification's value.
|
||||
if (this.previouslySelectedClassificationId && selection.classificationId != this.previouslySelectedClassificationId) {
|
||||
this.verificationRuleForm.get('subCategoryCode').reset();
|
||||
}
|
||||
this.previouslySelectedClassificationId = this.verificationRuleForm.get('documentClassification').value.classificationId;
|
||||
|
||||
this.availableDocumentSubclassifications = this.documentSubclassificationsList.filter(element => element.documentClassification.classificationId == selection.classificationId);
|
||||
}
|
||||
|
||||
documentSubclassificationSelected(selection: DocumentSubclassification) {
|
||||
this.verificationRuleForm.get('documentClassification').setValue(selection.documentClassification);
|
||||
}
|
||||
|
||||
/*
|
||||
* Auto-suggest/complete Categories
|
||||
*/
|
||||
autosuggestCategoryName(event) {
|
||||
|
||||
if (!event.query || event.query.length < 3) {
|
||||
this.categoryNameSuggestions = [];
|
||||
return;
|
||||
}
|
||||
|
||||
let classId = this.verificationRuleForm.get('documentClassification').value ? this.verificationRuleForm.get('documentClassification').value.classificationId : null;
|
||||
this.categoriesService.autosuggestCategoryName(event.query, classId).subscribe(
|
||||
(values: Category[]) => {
|
||||
let temp: string[] = [];
|
||||
this.categorySuggestions = values;
|
||||
values.map(val => temp.push(val.categoryName));
|
||||
this.categoryNameSuggestions = temp
|
||||
},
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
}
|
||||
|
||||
autosuggestCategoryCode(event) {
|
||||
|
||||
if (event.query.length < 3) {
|
||||
this.categoryCodeSuggestions = [];
|
||||
return;
|
||||
}
|
||||
|
||||
let classId = this.verificationRuleForm.get('documentClassification').value ? this.verificationRuleForm.get('documentClassification').value.classificationId : null;
|
||||
this.categoriesService.autosuggestCategoryCode(event.query, classId).subscribe(
|
||||
(values: Category[]) => {
|
||||
let temp: string[] = [];
|
||||
this.categorySuggestions = values;
|
||||
values.map(val => temp.push(val.categoryCode));
|
||||
this.categoryCodeSuggestions = temp
|
||||
},
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
}
|
||||
|
||||
categoryNameSelected(name: string) {
|
||||
this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryName == name);
|
||||
this.verificationRuleForm.get('categoryCode').patchValue(this.selectedCategory.categoryCode);
|
||||
this.verificationRuleForm.updateValueAndValidity();
|
||||
}
|
||||
|
||||
categoryCodeSelected(code: string) {
|
||||
this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryCode == code);
|
||||
this.verificationRuleForm.get('categoryName').patchValue(this.selectedCategory.categoryName);
|
||||
this.verificationRuleForm.updateValueAndValidity();
|
||||
}
|
||||
|
||||
// /*
|
||||
// * Auto-suggest/complete iPower Clients
|
||||
// */
|
||||
// autosuggestIPowerClientName(event) {
|
||||
|
||||
// if (!event.query || event.query.length < 3) {
|
||||
// this.ipowerClientNameSuggestions = [];
|
||||
// return;
|
||||
// }
|
||||
|
||||
// this.ipowerClientsService.getClientsByNameDistinct(event.query).subscribe(
|
||||
// (values: IPowerClient[]) => {
|
||||
// let temp: string[] = [];
|
||||
// this.ipowerClientSuggestions = values;
|
||||
// values.map(val => temp.push(val.name));
|
||||
// this.ipowerClientNameSuggestions = temp
|
||||
// },
|
||||
// err => this.errorHandlingService.showHttpResponseError(err)
|
||||
// );
|
||||
// }
|
||||
|
||||
// autosuggestIPowerClientCode(event) {
|
||||
|
||||
// if (!event.query || event.query.length < 3) {
|
||||
// this.ipowerClientCodeSuggestions = [];
|
||||
// return;
|
||||
// }
|
||||
|
||||
// this.ipowerClientsService.getClientsByCodeDistinct(event.query).subscribe(
|
||||
// (values: IPowerClient[]) => {
|
||||
// let temp: string[] = [];
|
||||
// this.ipowerClientSuggestions = values;
|
||||
// values.map(val => temp.push(val.clientCode));
|
||||
// this.ipowerClientCodeSuggestions = temp
|
||||
// },
|
||||
// err => this.errorHandlingService.showHttpResponseError(err)
|
||||
// );
|
||||
// }
|
||||
|
||||
autosuggestIPowerClientCode(event) {
|
||||
|
||||
if (event.query.length < 3) {
|
||||
this.ipowerClientCodeSuggestions = [];
|
||||
return;
|
||||
}
|
||||
|
||||
// If the user has the right to Preview of Scheduling Procedure (A02), we use the endpoint that returns all iPowerClients,
|
||||
// otherwise, the one that checks for the user's User_Access too. Whether the user can see ANY rule has already been handled by the 'search' button.
|
||||
let endpointToSubscribeTo: Observable<IPowerClient[]> = this.authService.userHasRightForClient(USER_RIGHTS.B01, environment.globalRightsClientID)
|
||||
? this.ipowerClientsService.getClientsByCodeOnly(event.query)
|
||||
: this.authService.userRights.find(rdc => USER_RIGHTS.B02.isGrantedToUser(rdc.rights)) != null ? this.ipowerClientsService.getClientsByCodeDistinct(event.query) : null;
|
||||
|
||||
endpointToSubscribeTo.subscribe(
|
||||
(values: IPowerClient[]) => {
|
||||
let temp: string[] = [];
|
||||
this.ipowerClientSuggestions = values;
|
||||
values.map(val => temp.push(val.clientCode));
|
||||
this.ipowerClientCodeSuggestions = temp
|
||||
},
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Auto-suggest & Auto-complete IPower Client
|
||||
*/
|
||||
autosuggestIPowerClientName(event): void {
|
||||
|
||||
if (!event.query || event.query.length < 3) {
|
||||
this.ipowerClientNameSuggestions = [];
|
||||
return;
|
||||
}
|
||||
|
||||
// If the user has the right to Preview of Scheduling Procedure (A02), we use the endpoint that returns all iPowerClients,
|
||||
// otherwise, the one that checks for the user's User_Access too. Whether the user can see ANY rule has already been handled by the 'search' button.
|
||||
let endpointToSubscribeTo: Observable<IPowerClient[]> = this.authService.userHasRightForClient(USER_RIGHTS.B01, environment.globalRightsClientID)
|
||||
? this.ipowerClientsService.getClientsByNameOnly(event.query)
|
||||
: this.authService.userRights.find(rdc => USER_RIGHTS.B02.isGrantedToUser(rdc.rights)) != null ? this.ipowerClientsService.getClientsByNameDistinct(event.query) : null;
|
||||
|
||||
endpointToSubscribeTo.subscribe(
|
||||
(values: IPowerClient[]) => {
|
||||
this.ipowerClientSuggestions = values;
|
||||
|
||||
const temp: string[] = [];
|
||||
values.map(val => temp.push(val.name));
|
||||
this.ipowerClientNameSuggestions = temp;
|
||||
},
|
||||
err => this.errorHandlingService.showHttpResponseError(err)
|
||||
);
|
||||
}
|
||||
|
||||
ipowerClientNameSelected(name: string) {
|
||||
this.selectedIPowerClient = this.ipowerClientSuggestions.find(client => client.name == name);
|
||||
this.verificationRuleForm.get('ipowerCode').patchValue(this.selectedIPowerClient.clientCode);
|
||||
this.verificationRuleForm.updateValueAndValidity();
|
||||
}
|
||||
|
||||
ipowerClientCodeSelected(code: string) {
|
||||
this.selectedIPowerClient = this.ipowerClientSuggestions.find(client => client.clientCode == code);
|
||||
this.verificationRuleForm.get('ipowerName').patchValue(this.selectedIPowerClient.name);
|
||||
this.verificationRuleForm.updateValueAndValidity();
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility Methods
|
||||
*/
|
||||
// Auto-suggest inputs - We have to ensure our reactive form holds values that represent the selectedCategory, otherwise truncate it.
|
||||
syncSelectedCategory() {
|
||||
|
||||
// Ιf our form has no value, truncate the selectedCategory either way.
|
||||
if (!this.verificationRuleForm.get('categoryName').value && !this.verificationRuleForm.get('categoryCode').value) {
|
||||
this.selectedCategory = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// If both or either of our form's values match the selectedCategory's and the other one doesn't have a value, all is good.
|
||||
// Just sync the values in case one is missing. Otherwise truncate the selectedCategory.
|
||||
if (
|
||||
this.verificationRuleForm.get('categoryName').value == this.selectedCategory.categoryName
|
||||
|| this.verificationRuleForm.get('categoryCode').value == this.selectedCategory.categoryCode
|
||||
) {
|
||||
this.selectedCategory.categoryName = this.verificationRuleForm.get('categoryName').value;
|
||||
this.selectedCategory.categoryCode = this.verificationRuleForm.get('categoryCode').value;
|
||||
}
|
||||
|
||||
// If both our values were different from the selectedCategory's, truncate it. This is an extremely abnormal scenario.
|
||||
else {
|
||||
console.error('WARNING - syncSelectedCategory()', 'Both of our form\'s values were different from the selectedCategory\'s.');
|
||||
this.selectedCategory = null;
|
||||
this.verificationRuleForm.get('categoryName').setValue('');
|
||||
this.verificationRuleForm.get('categoryCode').setValue('');
|
||||
this.verificationRuleForm.updateValueAndValidity();
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-suggest inputs - We have to ensure our reactive form holds values that represent the selectedIPowerClient, otherwise truncate it.
|
||||
syncSelectedIPowerClient() {
|
||||
|
||||
// Ιf our form has no value, truncate the selectedIPowerClient either way.
|
||||
if (!this.verificationRuleForm.get('ipowerName').value && !this.verificationRuleForm.get('ipowerCode').value) {
|
||||
this.selectedIPowerClient = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// If both or either of our form's values match the selectedIPowerClient's and the other one doesn't have a value, all is good.
|
||||
// Just sync the values in case one is missing. Otherwise truncate the selectedIPowerClient.
|
||||
if (
|
||||
this.verificationRuleForm.get('ipowerName').value == this.selectedIPowerClient.name
|
||||
|| this.verificationRuleForm.get('ipowerCode').value == this.selectedIPowerClient.clientCode
|
||||
) {
|
||||
this.selectedIPowerClient.name = this.verificationRuleForm.get('ipowerName').value;
|
||||
this.selectedIPowerClient.clientCode = this.verificationRuleForm.get('ipowerCode').value;
|
||||
}
|
||||
|
||||
// If both our values were different from the selectedIPowerClient's, truncate it. This is an extremely abnormal scenario.
|
||||
else {
|
||||
console.error('WARNING - syncSelectedIPowerClient()', 'Both of our form\'s values were different from the selectedIPowerClient\'s.');
|
||||
this.selectedIPowerClient = null;
|
||||
this.verificationRuleForm.get('ipowerName').setValue('');
|
||||
this.verificationRuleForm.get('ipowerCode').setValue('');
|
||||
this.verificationRuleForm.updateValueAndValidity();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* API methods
|
||||
*/
|
||||
public resetForm(): void {
|
||||
this.verificationRuleForm.reset();
|
||||
}
|
||||
|
||||
// TODO: Set type
|
||||
public formValue(): VerificationRuleSearchFormValue {
|
||||
|
||||
this.syncSelectedCategory();
|
||||
this.syncSelectedIPowerClient();
|
||||
|
||||
let formValue: VerificationRuleSearchFormValue = {
|
||||
clientId: this.selectedIPowerClient ? this.selectedIPowerClient.id : '',
|
||||
categoryId: this.selectedCategory ? this.selectedCategory.id : null,
|
||||
docClassificationId: this.verificationRuleForm.get('documentClassification').value ? this.verificationRuleForm.get('documentClassification').value.classificationId : '',
|
||||
// The backend only requires the subcategory's name, and not the whole object. Don't ask me.
|
||||
docSubcategory: this.verificationRuleForm.get('subCategoryCode').value ? this.verificationRuleForm.get('subCategoryCode').value['subclassificationName'] : ''
|
||||
}
|
||||
|
||||
return formValue;
|
||||
}
|
||||
|
||||
public isValid(): boolean {
|
||||
return this.verificationRuleForm.valid;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue