mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Compare commits
344 Commits
feature/47
...
feature/50
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9e9e39998 | ||
|
|
896478b2fb | ||
|
|
d84bc276d5 | ||
|
|
ca3433a4e1 | ||
|
|
d2b3d1bf18 | ||
|
|
08f8686791 | ||
|
|
4131255a1b | ||
|
|
874453f74f | ||
|
|
8077fe949f | ||
|
|
39bdcd4da6 | ||
|
|
55b95e571c | ||
|
|
4adf947b90 | ||
|
|
efdfa126e7 | ||
|
|
efd28bcc06 | ||
|
|
05986ab9f4 | ||
|
|
6fc65c4158 | ||
|
|
e3395c8772 | ||
|
|
ec67724b66 | ||
|
|
911187bc08 | ||
|
|
9a55cd8642 | ||
|
|
4815963565 | ||
|
|
0d4e5c6bf9 | ||
|
|
e60f4db18a | ||
|
|
b0de88301f | ||
|
|
6868c6df75 | ||
|
|
f2ca829b36 | ||
|
|
190d0786e0 | ||
|
|
0ec1457ffc | ||
|
|
a978f94519 | ||
|
|
71ee7ea842 | ||
|
|
a8c5e8feb5 | ||
|
|
1b9e70141b | ||
|
|
bdc711926c | ||
|
|
74531a7ddc | ||
|
|
202ceb0b22 | ||
|
|
693d1af51b | ||
|
|
78880fb2f4 | ||
|
|
d887c4e8fe | ||
|
|
0fe71fe9d8 | ||
|
|
b4bb5ab979 | ||
|
|
bd19ec8489 | ||
|
|
2bbf3d3739 | ||
|
|
e49d084439 | ||
|
|
5f31842afa | ||
|
|
81bb8ba72d | ||
|
|
68ea22f3d2 | ||
|
|
7edbe11c65 | ||
|
|
82d991fcbc | ||
|
|
0d1a65ed4a | ||
|
|
c98cbd73b1 | ||
|
|
4c79f2d127 | ||
|
|
61d0030342 | ||
|
|
86ed379b38 | ||
|
|
eba9cec16e | ||
|
|
651c65edc7 | ||
|
|
809a6e38b3 | ||
|
|
e1ce520711 | ||
|
|
81995e8863 | ||
|
|
ae89f1e2f8 | ||
|
|
75c6170be4 | ||
|
|
5db3521a0e | ||
|
|
a48ff29051 | ||
|
|
337ef46acb | ||
|
|
c0e8e69f9f | ||
|
|
2046212581 | ||
|
|
57968bd061 | ||
|
|
22c0a7d5d9 | ||
|
|
fa5ad7a561 | ||
|
|
39d101d456 | ||
|
|
c9b5af7282 | ||
|
|
2efc5c3b0d | ||
|
|
e0edd7887e | ||
|
|
d615efd806 | ||
|
|
a608d77ab5 | ||
|
|
fdfff237f2 | ||
|
|
def52fde63 | ||
|
|
0957617b93 | ||
|
|
a67305369e | ||
|
|
9c74dc15d2 | ||
|
|
e65085439e | ||
|
|
621a8a5dc7 | ||
|
|
beeba1004e | ||
|
|
4885a523ab | ||
|
|
f7a8cbf31d | ||
|
|
29d5c24e59 | ||
|
|
afff1ea8fd | ||
|
|
3c43d50f0f | ||
|
|
e04d88f2ce | ||
|
|
a50f02cb5b | ||
|
|
aff6d18888 | ||
|
|
8144253a18 | ||
|
|
718918e3dc | ||
|
|
93665cf35d | ||
|
|
a766534b97 | ||
|
|
82c1861fdc | ||
|
|
82e04917b7 | ||
|
|
cdcd41a884 | ||
|
|
3e14426d2e | ||
|
|
a93251f082 | ||
|
|
de47c493bf | ||
|
|
23876e3266 | ||
|
|
4ac84df25c | ||
|
|
c027791e27 | ||
|
|
3d18e45f59 | ||
|
|
03b132fc94 | ||
|
|
206586035d | ||
|
|
67d8902423 | ||
|
|
1c2d0421c4 | ||
|
|
b4caf3a177 | ||
|
|
ae3662dfd1 | ||
|
|
291386e4fd | ||
|
|
6a7d509aa4 | ||
|
|
620ffae55c | ||
|
|
59ad7710d9 | ||
|
|
8ca7977f7c | ||
|
|
62d0783e88 | ||
|
|
bd1e4f36e1 | ||
|
|
79356fa130 | ||
|
|
c1a40ae82f | ||
|
|
492dae14f7 | ||
|
|
9950c76482 | ||
|
|
7e7a5ebab9 | ||
|
|
41fc8e0fb1 | ||
|
|
41067a7e54 | ||
|
|
e1a50b0ce0 | ||
|
|
227af192e6 | ||
|
|
bd21b674bf | ||
|
|
b21395ed61 | ||
|
|
da27745ebe | ||
|
|
8a94da6868 | ||
|
|
81a7154470 | ||
|
|
0dee30062f | ||
|
|
eb0a0d3dc3 | ||
|
|
67dcb49a1d | ||
|
|
f3e2e9fee3 | ||
|
|
a4b092a021 | ||
|
|
aeacd0077f | ||
|
|
78a0e828b8 | ||
|
|
b508abefaf | ||
|
|
df49e3a79b | ||
|
|
34512f3b9a | ||
|
|
093bb3b484 | ||
|
|
921edf8066 | ||
|
|
858242c6dd | ||
|
|
119bcd9df9 | ||
|
|
b43d0fcea6 | ||
|
|
ddad3ad967 | ||
|
|
aaa161424e | ||
|
|
3bbec6a68d | ||
|
|
2a8a929fd7 | ||
|
|
3bcdfccb5c | ||
|
|
9696084f7b | ||
|
|
417bd649e2 | ||
|
|
d38fed297d | ||
|
|
3c110efdfa | ||
|
|
1cbabd2d7a | ||
|
|
133020ece1 | ||
|
|
549d419b69 | ||
|
|
8bbaf1c70c | ||
|
|
d0b7c95be2 | ||
|
|
b0dba2325d | ||
|
|
a9c606ec21 | ||
|
|
81bec4b153 | ||
|
|
0c2feb96ac | ||
|
|
1855b1970d | ||
|
|
0a46258588 | ||
|
|
ca2e529bdf | ||
|
|
82a2d70ce4 | ||
|
|
fa39b6d071 | ||
|
|
0f3f456909 | ||
|
|
727e0469ad | ||
|
|
7e3d6b4e61 | ||
|
|
453403cfde | ||
|
|
9001850c1f | ||
|
|
b97ad4f24b | ||
|
|
452de44f34 | ||
|
|
db7da0699e | ||
|
|
fbd5414e47 | ||
|
|
5310619211 | ||
|
|
edbdba6868 | ||
|
|
2d5fce8554 | ||
|
|
f5b7da5bd2 | ||
|
|
d4c1cdbc6e | ||
|
|
576d439a79 | ||
|
|
00fc978c4f | ||
|
|
44e596327e | ||
|
|
3d95bddb23 | ||
|
|
2210aeb1c2 | ||
|
|
a2b6847898 | ||
|
|
3f252639d5 | ||
|
|
3f7df0f748 | ||
|
|
703090eabd | ||
|
|
33694357bd | ||
|
|
91668e53fa | ||
|
|
39e4efff2b | ||
|
|
1a4d0a38da | ||
|
|
6c4641d2b7 | ||
|
|
815523b4ca | ||
|
|
57b5f30a66 | ||
|
|
94919efd83 | ||
|
|
cd0d740dc2 | ||
|
|
dc3970ceea | ||
|
|
5bba1dff8f | ||
|
|
7ff6e9495e | ||
|
|
04403179d7 | ||
|
|
a39706bff3 | ||
|
|
0ac34740bb | ||
|
|
24c2c1c77d | ||
|
|
a364a4f0e0 | ||
|
|
dcc70745da | ||
|
|
effce6f41c | ||
|
|
a5feaba5e3 | ||
|
|
d8bb42b8c6 | ||
|
|
f74494f34e | ||
|
|
abce5f43e2 | ||
|
|
ce4a6b36b6 | ||
|
|
298ea042f2 | ||
|
|
573d6a740e | ||
|
|
8eb5e09490 | ||
|
|
aa8869ceb1 | ||
|
|
e5f42c9de2 | ||
|
|
532c7e5e86 | ||
|
|
30ccd93967 | ||
|
|
b85538f98a | ||
|
|
d9dede4341 | ||
|
|
4a3c934fe0 | ||
|
|
944fb8a186 | ||
|
|
73fd487a13 | ||
|
|
592027f648 | ||
|
|
84243ac4e6 | ||
|
|
04b9422d5d | ||
|
|
584cb63eaf | ||
|
|
b9871bba54 | ||
|
|
6769e3864e | ||
|
|
cebb644da9 | ||
|
|
734a7b8739 | ||
|
|
e89d1999a6 | ||
|
|
b7cbd50e83 | ||
|
|
76aa04bc4c | ||
|
|
b951cf7024 | ||
|
|
f896d91ebb | ||
|
|
a884adc3a9 | ||
|
|
ce9bc9511a | ||
|
|
2653322232 | ||
|
|
86eb0bb494 | ||
|
|
73be50e7d2 | ||
|
|
da5151df78 | ||
|
|
df47b932b6 | ||
|
|
c096609a27 | ||
|
|
6b07b322f4 | ||
|
|
1b821db248 | ||
|
|
ecf446671c | ||
|
|
a2f204d0d6 | ||
|
|
c8678b7e91 | ||
|
|
ec41738def | ||
|
|
53a7f01507 | ||
|
|
7366f038e5 | ||
|
|
1c9cd2a0b0 | ||
|
|
591824196b | ||
|
|
09aa3f09cb | ||
|
|
eff67b9a06 | ||
|
|
c9b2762bbc | ||
|
|
c49b0625c1 | ||
|
|
42451e2144 | ||
|
|
f52fb00df7 | ||
|
|
b485bb768c | ||
|
|
3f77646f8a | ||
|
|
eb6149a6e3 | ||
|
|
5aa98bd90b | ||
|
|
d71404f400 | ||
|
|
f68eb33852 | ||
|
|
39d790c121 | ||
|
|
10349409fb | ||
|
|
0dc02abc8a | ||
|
|
388346e21b | ||
|
|
1847c6944e | ||
|
|
fd11cf19e4 | ||
|
|
8e7b067310 | ||
|
|
c6a174d93f | ||
|
|
9efbfab253 | ||
|
|
d474f555e3 | ||
|
|
c59a09c252 | ||
|
|
f743ce59fa | ||
|
|
99feb499a2 | ||
|
|
6d28662431 | ||
|
|
27174e4ed3 | ||
|
|
9b1b2c4682 | ||
|
|
674e2b7e1b | ||
|
|
035abde3c3 | ||
|
|
ca998c0685 | ||
|
|
bb5b6e2e59 | ||
|
|
f57988f83e | ||
|
|
17a68b9dbb | ||
|
|
b6aab4f743 | ||
|
|
a0c8035dbb | ||
|
|
34e96f0751 | ||
|
|
9ba05253e9 | ||
|
|
98a9346c1a | ||
|
|
fa66d2389a | ||
|
|
6743c8e630 | ||
|
|
f62e198aed | ||
|
|
387e6b08ed | ||
|
|
721fd06c76 | ||
|
|
0fcdb308b5 | ||
|
|
5492329a21 | ||
|
|
f97253e82a | ||
|
|
b926efb635 | ||
|
|
1becbec412 | ||
|
|
cdc2553d73 | ||
|
|
8781c50e34 | ||
|
|
05eb3cc756 | ||
|
|
6e1c434edf | ||
|
|
ed8e937924 | ||
|
|
1bd17fd887 | ||
|
|
c35c82eaab | ||
|
|
258faec021 | ||
|
|
4bcc523480 | ||
|
|
8900a77d7a | ||
|
|
895e2bd2ec | ||
|
|
4b10dd96d9 | ||
|
|
1126e4f0c1 | ||
|
|
e9f24a88d6 | ||
|
|
f30de35d51 | ||
|
|
0c6f8abbad | ||
|
|
54b37436eb | ||
|
|
02bae79e4a | ||
|
|
cb6779fc83 | ||
|
|
f2c95b6a16 | ||
|
|
d48680c59e | ||
|
|
775390b5df | ||
|
|
1788f566e3 | ||
|
|
d4e1088190 | ||
|
|
a8ecd1f07b | ||
|
|
2c239ac597 | ||
|
|
200eb7f217 | ||
|
|
694fc6d084 | ||
|
|
8ae990bcde | ||
|
|
1d472ce3df | ||
|
|
1d19779dac | ||
|
|
90e671d285 | ||
|
|
33fb44f20a | ||
|
|
67cf380948 | ||
|
|
e0ae79bc2a | ||
|
|
8ccc29c85a |
86
.github/commit-instructions.md
vendored
Normal file
86
.github/commit-instructions.md
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
# Commit Message Instructions (Conventional Commits)
|
||||
|
||||
Commit messages should follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/). This provides a standardized format for commit messages, making it easier to understand changes, automate changelog generation, and trigger build/publish processes.
|
||||
|
||||
## Format
|
||||
|
||||
The commit message structure is as follows:
|
||||
|
||||
```
|
||||
<type>[optional scope]: <description>
|
||||
|
||||
[optional body]
|
||||
|
||||
[optional footer(s)]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Components
|
||||
|
||||
1. **Type**: Indicates the kind of change introduced by the commit. Must be one of the allowed types (see below).
|
||||
2. **Scope (Optional)**: A noun describing the section of the codebase affected by the change (e.g., `auth`, `ui`, `build`). Enclosed in parentheses.
|
||||
3. **Description**: A concise summary of the change in the imperative, present tense (e.g., "add login feature", not "added login feature" or "adds login feature"). Starts with a lowercase letter and should not end with a period. Max 72 characters recommended for the entire header line (`<type>[optional scope]: <description>`).
|
||||
4. **Body (Optional)**: A more detailed explanation of the changes. Use the imperative, present tense. Explain the _what_ and _why_ vs. _how_. Separate from the description by a blank line. Wrap lines at 72 characters.
|
||||
5. **Footer(s) (Optional)**: Contains additional metadata. Common footers include:
|
||||
- `BREAKING CHANGE:` followed by a description of the breaking change. A `!` can also be appended to the type/scope (`feat!:`) to indicate a breaking change.
|
||||
- Issue references (e.g., `Refs: #123`, `Closes: #456`). Separate from the body by a blank line.
|
||||
|
||||
---
|
||||
|
||||
### Allowed Types
|
||||
|
||||
- **feat**: A new feature for the user.
|
||||
- **fix**: A bug fix for the user.
|
||||
- **build**: Changes that affect the build system or external dependencies (e.g., gulp, broccoli, npm).
|
||||
- **chore**: Other changes that don't modify src or test files (e.g., updating dependencies, build tasks).
|
||||
- **ci**: Changes to CI configuration files and scripts (e.g., Travis, Circle, BrowserStack, SauceLabs).
|
||||
- **docs**: Documentation only changes.
|
||||
- **perf**: A code change that improves performance.
|
||||
- **refactor**: A code change that neither fixes a bug nor adds a feature.
|
||||
- **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc).
|
||||
- **test**: Adding missing tests or correcting existing tests.
|
||||
|
||||
---
|
||||
|
||||
### Examples
|
||||
|
||||
**Commit with description only:**
|
||||
|
||||
```
|
||||
fix: correct minor typos in code
|
||||
```
|
||||
|
||||
**Commit with scope:**
|
||||
|
||||
```
|
||||
feat(lang): add polish language
|
||||
```
|
||||
|
||||
**Commit with body and breaking change footer:**
|
||||
|
||||
```
|
||||
refactor: drop support for Node 6
|
||||
|
||||
The new implementation relies on async/await and other features
|
||||
introduced in Node 8+.
|
||||
|
||||
BREAKING CHANGE: refactor to use JavaScript features not available in Node 6.
|
||||
```
|
||||
|
||||
**Commit with scope, body, and issue footer:**
|
||||
|
||||
```
|
||||
docs(readme): improve installation instructions
|
||||
|
||||
Provide clearer steps for setting up the development environment.
|
||||
Add links to prerequisite tools.
|
||||
|
||||
Closes: #12
|
||||
```
|
||||
|
||||
**Commit with `!` for breaking change:**
|
||||
|
||||
```
|
||||
feat(api)!: send an email to the customer when a product is shipped
|
||||
```
|
||||
21
.github/copilot-instructions.md
vendored
Normal file
21
.github/copilot-instructions.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Mentor Instructions
|
||||
|
||||
## Introduction
|
||||
|
||||
You are Mentor, an AI assistant focused on ensuring code quality, strict adherence to best practices, and development efficiency. **Your core function is to enforce the coding standards and guidelines established in this workspace.** Your goal is to help me produce professional, maintainable, and high-performing code.
|
||||
|
||||
## Tone and Personality
|
||||
|
||||
Maintain a professional, objective, and direct tone consistently:
|
||||
|
||||
- **Guideline Enforcement & Error Correction:** When code deviates from guidelines or contains errors, provide precise, technical feedback. Clearly state the issue, cite the relevant guideline or principle, and explain the required correction for optimal, maintainable results.
|
||||
- **Technical Consultation:** In discussions about architecture, best practices, or complex coding inquiries, remain formal and analytical. Provide clear, well-reasoned explanations and recommendations grounded in industry standards and the project's specific guidelines.
|
||||
|
||||
## Behavioral Guidelines
|
||||
|
||||
- **Actionable Feedback:** Prioritize constructive, actionable feedback aimed at improving code quality, maintainability, and adherence to standards. Avoid rewriting code; focus on explaining the necessary changes and their rationale based on guidelines.
|
||||
- **Strict Guideline Adherence:** Base _all_ feedback, suggestions, and explanations rigorously on the guidelines documented within this workspace. Cite specific rules and principles consistently.
|
||||
- **Demand Clarity:** If a query or code snippet lacks sufficient detail for a thorough, professional analysis, request clarification.
|
||||
- **Professional Framing:** Frame all feedback objectively, focusing on the technical aspects and the importance of meeting project standards for long-term success.
|
||||
- **Context-Specific Expertise:** Provide specific, context-aware advice tailored to the code or problem, always within the framework of our established guidelines.
|
||||
- **Enforce Standards:** Actively enforce project preferences for Type safety, Clean Code principles, and thorough documentation, as mandated by the workspace guidelines.
|
||||
32
.github/instructions/nx.instructions.md
vendored
Normal file
32
.github/instructions/nx.instructions.md
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
applyTo: '**'
|
||||
---
|
||||
|
||||
// This file is automatically generated by Nx Console
|
||||
|
||||
You are in an nx workspace using Nx 20.4.6 and npm as the package manager.
|
||||
|
||||
You have access to the Nx MCP server and the tools it provides. Use them. Follow these guidelines in order to best help the user:
|
||||
|
||||
# General Guidelines
|
||||
- When answering questions, use the nx_workspace tool first to gain an understanding of the workspace architecture
|
||||
- For questions around nx configuration, best practices or if you're unsure, use the nx_docs tool to get relevant, up-to-date docs!! Always use this instead of assuming things about nx configuration
|
||||
- If the user needs help with an Nx configuration or project graph error, use the 'nx_workspace' tool to get any errors
|
||||
- To help answer questions about the workspace structure or simply help with demonstrating how tasks depend on each other, use the 'nx_visualize_graph' tool
|
||||
|
||||
# Generation Guidelines
|
||||
If the user wants to generate something, use the following flow:
|
||||
|
||||
- learn about the nx workspace and any specifics the user needs by using the 'nx_workspace' tool and the 'nx_project_details' tool if applicable
|
||||
- get the available generators using the 'nx_generators' tool
|
||||
- decide which generator to use. If no generators seem relevant, check the 'nx_available_plugins' tool to see if the user could install a plugin to help them
|
||||
- get generator details using the 'nx_generator_schema' tool
|
||||
- you may use the 'nx_docs' tool to learn more about a specific generator or technology if you're unsure
|
||||
- decide which options to provide in order to best complete the user's request. Don't make any assumptions and keep the options minimalistic
|
||||
- open the generator UI using the 'nx_open_generate_ui' tool
|
||||
- wait for the user to finish the generator
|
||||
- read the generator log file using the 'nx_read_generator_log' tool
|
||||
- use the information provided in the log file to answer the user's question or continue with what they were doing
|
||||
undefined
|
||||
|
||||
|
||||
182
.github/review-instructions.md
vendored
Normal file
182
.github/review-instructions.md
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
# Code Review Instructions
|
||||
|
||||
## Summary
|
||||
|
||||
When conducting a code review, follow these steps to ensure a thorough and constructive process.
|
||||
**Ensure that all review guidelines are followed. If any guideline is not adhered to, make it explicitly clear which guideline needs to be followed.**
|
||||
|
||||
## Review Process
|
||||
|
||||
1. 🎯 **Key Issues**
|
||||
Identify critical issues in the code such as bugs, security vulnerabilities, or violations of the project's coding standards.
|
||||
_Include specific links to files and line numbers (e.g., file.js#L10) where applicable._
|
||||
|
||||
2. 💡 **Suggestions for Improvement**
|
||||
Highlight areas where the code can be enhanced in terms of readability, performance, maintainability, or adherence to best practices.
|
||||
_Clarify what constitutes a "Critical" versus a "Minor" issue to avoid ambiguity._
|
||||
|
||||
3. ✨ **Code Examples**
|
||||
Provide specific, concise code snippets that illustrate your suggestions.
|
||||
_Include both a "Before" (problematic code) and an "After" (improved version) example where beneficial._
|
||||
|
||||
4. 📚 **Relevant Documentation Links**
|
||||
Attach links to useful resources or official documentation to support the suggested changes.
|
||||
_For example, link to ESLint, Jest, or Angular Style Guide pages when relevant._
|
||||
|
||||
## Tone and Feedback
|
||||
|
||||
- Be constructive and supportive.
|
||||
Frame suggestions as opportunities for growth rather than criticism.
|
||||
- Use the following emojis to categorize your feedback:
|
||||
- 🚨 **Critical issues**
|
||||
- ❗ **Minor Issues**
|
||||
- ⚠️ **Warnings**
|
||||
- 💡 **Suggestions**
|
||||
- ✅ **Good practices**
|
||||
|
||||
## Additional Informations
|
||||
|
||||
- Missing tests and JSDocs are minor issues
|
||||
- Missing unit test are minor issues
|
||||
- Missing End-to-End (E2E) Testing Attributes (`data-what`, `data-which`) are warnings
|
||||
|
||||
### Review Template
|
||||
|
||||
````markdown
|
||||
# Code Review
|
||||
|
||||
## Summary
|
||||
|
||||
A brief overview of the code’s overall quality, highlighting key strengths and areas needing attention. This sets the stage for the detailed feedback below.
|
||||
|
||||
---
|
||||
|
||||
## 🚨 Critical Issues
|
||||
|
||||
High-priority issues that must be addressed immediately due to their potential to severely impact functionality, performance, or security.
|
||||
|
||||
### 1. High Priority: [Issue Title]
|
||||
|
||||
#### 🚨 Issue
|
||||
|
||||
Describe the issue clearly, including links to specific files and lines (e.g., file.js#L10). Explain why it’s critical—highlight crashes, security risks, or significant performance issues.
|
||||
|
||||
#### 💡 Suggestions for Improvement
|
||||
|
||||
Provide specific steps or alternative approaches to resolve the issue.
|
||||
|
||||
#### ✨ Code Example
|
||||
|
||||
**Current**: [file](file.js#L10) Problematic code with path to the file and line of the code
|
||||
|
||||
```typescript
|
||||
// Code...
|
||||
```
|
||||
|
||||
**Improvement**: Improved version
|
||||
|
||||
```typescript
|
||||
// Code...
|
||||
```
|
||||
|
||||
#### 📚 Relevant Documentation
|
||||
|
||||
Include URLs for further research (e.g., [Jest Documentation](https://jestjs.io/docs/getting-started)).
|
||||
|
||||
---
|
||||
|
||||
## ❗ Minor Issues
|
||||
|
||||
Issues that can improve code quality, maintainability, or adherence to best practices when resolved.
|
||||
|
||||
### 1. Medium Priority: [Issue Title]
|
||||
|
||||
#### ❗ Issue
|
||||
|
||||
Describe the issue clearly, including file and line references (e.g., file.js#L10). Explain the impact on the project.
|
||||
|
||||
#### 💡 Suggestions for Improvement
|
||||
|
||||
Offer concrete steps or alternative approaches to mitigate the issue.
|
||||
|
||||
#### ✨ Code Example
|
||||
|
||||
**Current**: [file](file.js#L10) Problematic code with path to the file and line of the code
|
||||
|
||||
```typescript
|
||||
// Code...
|
||||
```
|
||||
|
||||
**Improvement**: Improved version
|
||||
|
||||
```typescript
|
||||
// Code...
|
||||
```
|
||||
|
||||
#### 📚 Relevant Documentation
|
||||
|
||||
Provide links to further resources.
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Warnings
|
||||
|
||||
Low-priority issues or suggestions that could help prevent future problems or improve the code quality over time.
|
||||
|
||||
### 1. Low Priority: [Issue Title]
|
||||
|
||||
#### ⚠️ Issue
|
||||
|
||||
Describe the issue clearly with references (e.g., file.js#L10). Explain the potential impact if left unaddressed.
|
||||
|
||||
#### 💡 Suggestions for Improvement
|
||||
|
||||
Provide suggestions or alternative implementations to mitigate the issue.
|
||||
|
||||
#### ✨ Code Example
|
||||
|
||||
**Current**: [file](file.js#L10) Problematic code with path to the file and line of the code
|
||||
|
||||
```typescript
|
||||
// Code...
|
||||
```
|
||||
|
||||
**Improvement**: Improved version
|
||||
|
||||
```typescript
|
||||
// Code...
|
||||
```
|
||||
|
||||
#### 📚 Relevant Documentation
|
||||
|
||||
Include relevant resources for more information.
|
||||
|
||||
---
|
||||
|
||||
## 🛑 Bad Practices
|
||||
|
||||
Highlight up to five bad aspects of the code to reinforce improvements and encourage good practices. Use different funny emoji at the beginning of each bad practice.
|
||||
|
||||
- Emoji **Bad Practice 1**:
|
||||
Describe a specific weakness (e.g., clear code structure) with an example reference (e.g., file.js#L20). Explain why it’s bad.
|
||||
- Emoji **Bad Practice 2**:
|
||||
Outline another negative feature (e.g., effective error handling) with a snippet reference.
|
||||
|
||||
---
|
||||
|
||||
## ✅ Good Practices
|
||||
|
||||
Highlight up to five positive aspects of the code to reinforce well-implemented patterns and encourage good practices. Use different funny emoji at the beginning of each good practice.
|
||||
|
||||
- Emoji **Good Practice 1**:
|
||||
Describe a specific strength (e.g., clear code structure) with an example reference (e.g., file.js#L20). Explain why it’s commendable.
|
||||
- Emoji **Good Practice 2**:
|
||||
Outline another positive feature (e.g., effective error handling) with a snippet reference.
|
||||
|
||||
---
|
||||
|
||||
## 📓 Additional Notes
|
||||
|
||||
- **General Feedback**: Optional thoughts regarding the overall quality or potential areas for future improvement.
|
||||
- **Next Steps**: Outline follow-up actions or further examination areas as needed.
|
||||
````
|
||||
66
.github/testing-instructions.md
vendored
Normal file
66
.github/testing-instructions.md
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
# Testing Instructions
|
||||
|
||||
## Framework and Tools
|
||||
|
||||
- Use **Jest** as the testing framework.
|
||||
- For unit tests, utilize **Spectator** to simplify Angular component testing.
|
||||
|
||||
## Guidelines
|
||||
|
||||
1. **Error Case Testing**: Ensure all edge cases and error scenarios are thoroughly tested.
|
||||
2. **Arrange-Act-Assert Pattern**: Follow the Arrange-Act-Assert pattern for structuring your tests:
|
||||
- **Arrange**: Set up the testing environment and initialize required variables.
|
||||
- **Act**: Execute the functionality being tested.
|
||||
- **Assert**: Verify the expected outcomes.
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Write clear and descriptive test names.
|
||||
- Ensure tests are isolated and do not depend on each other.
|
||||
- Mock external dependencies to avoid side effects.
|
||||
- Aim for high code coverage without compromising test quality.
|
||||
|
||||
## Example Test Structure
|
||||
|
||||
```typescript
|
||||
// Example using Jest and Spectator
|
||||
import { createComponentFactory, Spectator } from '@ngneat/spectator';
|
||||
import { MyComponent } from './my-component.component';
|
||||
|
||||
describe('MyComponent', () => {
|
||||
let spectator: Spectator<MyComponent>;
|
||||
const createComponent = createComponentFactory(MyComponent);
|
||||
|
||||
beforeEach(() => {
|
||||
spectator = createComponent();
|
||||
});
|
||||
|
||||
it('should display the correct title', () => {
|
||||
// Arrange
|
||||
const expectedTitle = 'Hello World';
|
||||
|
||||
// Act
|
||||
spectator.component.title = expectedTitle;
|
||||
spectator.detectChanges();
|
||||
|
||||
// Assert
|
||||
expect(spectator.query('h1')).toHaveText(expectedTitle);
|
||||
});
|
||||
|
||||
it('should handle error cases gracefully', () => {
|
||||
// Arrange
|
||||
const invalidInput = null;
|
||||
|
||||
// Act
|
||||
spectator.component.input = invalidInput;
|
||||
|
||||
// Assert
|
||||
expect(() => spectator.component.processInput()).toThrowError('Invalid input');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [Jest Documentation](https://jestjs.io/docs/getting-started)
|
||||
- [Spectator Documentation](https://ngneat.github.io/spectator/)
|
||||
19
.gitignore
vendored
19
.gitignore
vendored
@@ -1,10 +1,15 @@
|
||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
.matomo
|
||||
junit.xml
|
||||
|
||||
# compiled output
|
||||
/dist
|
||||
/tmp
|
||||
/out-tsc
|
||||
|
||||
/
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
@@ -47,4 +52,16 @@ testem.log
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
libs/swagger/src/lib/*
|
||||
libs/swagger/src/lib/*
|
||||
*storybook.log
|
||||
|
||||
|
||||
.nx/cache
|
||||
.nx/workspace-data
|
||||
.angular
|
||||
|
||||
|
||||
storybook-static
|
||||
|
||||
.cursor\rules\nx-rules.mdc
|
||||
.github\instructions\nx.instructions.md
|
||||
|
||||
@@ -1 +1 @@
|
||||
npm run pretty-quick
|
||||
npx lint-staged
|
||||
|
||||
7
.lintstagedrc.json
Normal file
7
.lintstagedrc.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"*.ts": "npx eslint --fix --config eslint.config.mjs",
|
||||
"*.tsx": "npx eslint --fix --config eslint.config.mjs",
|
||||
"*.js": "npx eslint --fix --config eslint.config.mjs",
|
||||
"*.jsx": "npx eslint --fix --config eslint.config.mjs",
|
||||
"*.html": "npx eslint --fix --config eslint.config.mjs"
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
# Add files here to ignore them from prettier formatting
|
||||
|
||||
/dist
|
||||
/coverage
|
||||
/helmvalues
|
||||
/apps/swagger
|
||||
/ng-swagger-gen
|
||||
|
||||
*.json
|
||||
*.yml
|
||||
/.nx/cache
|
||||
/.nx/workspace-data
|
||||
/node_modules
|
||||
.angular
|
||||
.vscode
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"printWidth": 140
|
||||
}
|
||||
|
||||
15
.vscode/extensions.json
vendored
15
.vscode/extensions.json
vendored
@@ -1,7 +1,10 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"johnpapa.angular2",
|
||||
"esbenp.prettier-vscode",
|
||||
"angular.ng-template",
|
||||
]
|
||||
}
|
||||
"recommendations": [
|
||||
"johnpapa.angular2",
|
||||
"esbenp.prettier-vscode",
|
||||
"angular.ng-template",
|
||||
"nrwl.angular-console",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"firsttris.vscode-jest-runner"
|
||||
]
|
||||
}
|
||||
|
||||
88
.vscode/settings.json
vendored
88
.vscode/settings.json
vendored
@@ -1,15 +1,93 @@
|
||||
{
|
||||
"editor.accessibilitySupport": "off",
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"exportall.config.exclude": [".test.", ".spec.", ".stories."],
|
||||
"editor.formatOnSave": true,
|
||||
"typescriptHero.imports.insertSemicolons": false,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"[javascript]": {
|
||||
"eslint.validate": [
|
||||
"json"
|
||||
],
|
||||
"[html]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"css.validate": false,
|
||||
"less.validate": false,
|
||||
"scss.validate": false
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"exportall.config.folderListener": [
|
||||
"/libs/oms/data-access/src/lib/models",
|
||||
"/libs/oms/data-access/src/lib/schemas",
|
||||
"/libs/catalogue/data-access/src/lib/models",
|
||||
"/libs/common/data-access/src/lib/models",
|
||||
"/libs/common/data-access/src/lib/error",
|
||||
"/libs/oms/data-access/src/lib/errors/return-process"
|
||||
],
|
||||
"github.copilot.chat.commitMessageGeneration.instructions": [
|
||||
{
|
||||
"file": ".github/commit-instructions.md"
|
||||
}
|
||||
],
|
||||
"github.copilot.chat.codeGeneration.instructions": [
|
||||
{
|
||||
"file": ".github/copilot-instructions.md"
|
||||
},
|
||||
{
|
||||
"file": "docs/tech-stack.md"
|
||||
},
|
||||
{
|
||||
"file": "docs/guidelines/code-style.md"
|
||||
},
|
||||
{
|
||||
"file": "docs/guidelines/project-structure.md"
|
||||
},
|
||||
{
|
||||
"file": "docs/guidelines/state-management.md"
|
||||
},
|
||||
{
|
||||
"file": "docs/guidelines/testing.md"
|
||||
}
|
||||
],
|
||||
"github.copilot.chat.testGeneration.instructions": [
|
||||
{
|
||||
"file": ".github/copilot-instructions.md"
|
||||
},
|
||||
{
|
||||
"file": ".github/testing-instructions.md"
|
||||
},
|
||||
{
|
||||
"file": "docs/tech-stack.md"
|
||||
},
|
||||
{
|
||||
"file": "docs/guidelines/code-style.md"
|
||||
},
|
||||
{
|
||||
"file": "docs/guidelines/testing.md"
|
||||
}
|
||||
],
|
||||
"github.copilot.chat.reviewSelection.instructions": [
|
||||
{
|
||||
"file": ".github/copilot-instructions.md"
|
||||
},
|
||||
{
|
||||
"file": ".github/review-instructions.md"
|
||||
},
|
||||
{
|
||||
"file": "docs/tech-stack.md"
|
||||
},
|
||||
{
|
||||
"file": "docs/guidelines/code-style.md"
|
||||
},
|
||||
{
|
||||
"file": "docs/guidelines/project-structure.md"
|
||||
},
|
||||
{
|
||||
"file": "docs/guidelines/state-management.md"
|
||||
},
|
||||
{
|
||||
"file": "docs/guidelines/testing.md"
|
||||
}
|
||||
],
|
||||
"nxConsole.generateAiAgentRules": true,
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#stage 1
|
||||
FROM node:18 as base
|
||||
FROM node:22 as base
|
||||
ARG IS_PRODUCTION=false
|
||||
ARG SEMVERSION=1.0.0
|
||||
ARG BuildUniqueID
|
||||
@@ -8,7 +8,7 @@ WORKDIR /app
|
||||
COPY . .
|
||||
RUN umask 0022
|
||||
RUN npm version ${SEMVERSION}
|
||||
RUN npm install --always-auth=false
|
||||
RUN npm install --foreground-scripts
|
||||
RUN if [ "${IS_PRODUCTION}" = "true" ] ; then npm run-script build-prod ; else npm run-script build ; fi
|
||||
|
||||
# stage final
|
||||
@@ -24,6 +24,6 @@ ARG BuildUniqueID
|
||||
LABEL build.uniqueid="${BuildUniqueID:-1}"
|
||||
RUN wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb -q -O /tmp/chrome.deb && apt update && apt install -y /tmp/chrome.deb
|
||||
# ignore exitcode, sonst gibts keinen container
|
||||
RUN npm test || true
|
||||
RUN npm run ci || true
|
||||
ENTRYPOINT [ "/bin/sleep", "60000" ]
|
||||
|
||||
|
||||
135
angular.json
135
angular.json
@@ -1,135 +0,0 @@
|
||||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "apps",
|
||||
"projects": {
|
||||
"isa-app": {
|
||||
"projectType": "application",
|
||||
"schematics": {
|
||||
"@schematics/angular:component": {
|
||||
"style": "scss"
|
||||
},
|
||||
"@schematics/angular:application": {
|
||||
"strict": true
|
||||
}
|
||||
},
|
||||
"root": "apps/isa-app",
|
||||
"sourceRoot": "apps/isa-app/src",
|
||||
"prefix": "app",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"allowedCommonJsDependencies": [
|
||||
"lodash",
|
||||
"moment",
|
||||
"jsrsasign",
|
||||
"pdfjs-dist/build/pdf",
|
||||
"pdfjs-dist/web/pdf_viewer",
|
||||
"pdfjs-dist/es5/build/pdf",
|
||||
"pdfjs-dist/es5/web/pdf_viewer",
|
||||
"scandit-sdk"
|
||||
],
|
||||
"outputPath": "dist/isa-app",
|
||||
"index": "apps/isa-app/src/index.html",
|
||||
"main": "apps/isa-app/src/main.ts",
|
||||
"polyfills": "apps/isa-app/src/polyfills.ts",
|
||||
"tsConfig": "apps/isa-app/tsconfig.app.json",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": [
|
||||
"apps/isa-app/src/favicon.ico",
|
||||
"apps/isa-app/src/assets",
|
||||
"apps/isa-app/src/config",
|
||||
"apps/isa-app/src/silent-refresh.html",
|
||||
"apps/isa-app/src/manifest.webmanifest",
|
||||
{
|
||||
"glob": "**/*",
|
||||
"input": "node_modules/scandit-sdk/build",
|
||||
"output": "scandit"
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"apps/isa-app/src/styles.scss"
|
||||
],
|
||||
"scripts": [],
|
||||
"serviceWorker": true,
|
||||
"ngswConfigPath": "apps/isa-app/ngsw-config.json"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "2mb",
|
||||
"maximumError": "5mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "25kb"
|
||||
}
|
||||
],
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "apps/isa-app/src/environments/environment.ts",
|
||||
"with": "apps/isa-app/src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"outputHashing": "all"
|
||||
},
|
||||
"development": {
|
||||
"buildOptimizer": false,
|
||||
"optimization": false,
|
||||
"vendorChunk": true,
|
||||
"extractLicenses": false,
|
||||
"sourceMap": true,
|
||||
"namedChunks": true
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "production"
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"configurations": {
|
||||
"production": {
|
||||
"buildTarget": "isa-app:build:production"
|
||||
},
|
||||
"development": {
|
||||
"buildTarget": "isa-app:build:development"
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "development"
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"buildTarget": "isa-app:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"tsConfig": "apps/isa-app/tsconfig.spec.json",
|
||||
"karmaConfig": "karma.conf.js",
|
||||
"polyfills": [
|
||||
"zone.js",
|
||||
"zone.js/testing"
|
||||
],
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": [
|
||||
"apps/isa-app/src/favicon.ico",
|
||||
"apps/isa-app/src/assets",
|
||||
"apps/isa-app/src/manifest.webmanifest"
|
||||
],
|
||||
"styles": [
|
||||
"apps/isa-app/src/styles.scss"
|
||||
],
|
||||
"scripts": []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cli": {
|
||||
"analytics": false
|
||||
}
|
||||
}
|
||||
21
apps/isa-app/.storybook/main.ts
Normal file
21
apps/isa-app/.storybook/main.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import type { StorybookConfig } from '@storybook/angular';
|
||||
|
||||
const config: StorybookConfig = {
|
||||
stories: ['../stories/**/*.@(mdx|stories.@(js|jsx|ts|tsx))'],
|
||||
addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'],
|
||||
staticDirs: ['../src/assets'],
|
||||
previewHead: (head) => `
|
||||
${head}
|
||||
<link href="/assets/fonts/fonts.css" rel="stylesheet" />
|
||||
`,
|
||||
framework: {
|
||||
name: '@storybook/angular',
|
||||
options: {},
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
||||
// To customize your webpack configuration you can use the webpackFinal field.
|
||||
// Check https://storybook.js.org/docs/react/builders/webpack#extending-storybooks-webpack-config
|
||||
// and https://nx.dev/recipes/storybook/custom-builder-configs
|
||||
7
apps/isa-app/.storybook/preview.ts
Normal file
7
apps/isa-app/.storybook/preview.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import type { Preview } from '@storybook/angular';
|
||||
|
||||
const preview: Preview = {
|
||||
tags: ['autodocs'],
|
||||
};
|
||||
|
||||
export default preview;
|
||||
21
apps/isa-app/.storybook/tsconfig.json
Normal file
21
apps/isa-app/.storybook/tsconfig.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"emitDecoratorMetadata": true
|
||||
},
|
||||
"exclude": ["../**/*.spec.ts"],
|
||||
"include": [
|
||||
// "../src/**/*.stories.ts",
|
||||
// "../src/**/*.stories.js",
|
||||
// "../src/**/*.stories.jsx",
|
||||
// "../src/**/*.stories.tsx",
|
||||
// "../src/**/*.stories.mdx",
|
||||
"../stories/**/*.stories.ts",
|
||||
"../stories/**/*.stories.js",
|
||||
"../stories/**/*.stories.jsx",
|
||||
"../stories/**/*.stories.tsx",
|
||||
"../stories/**/*.stories.mdx",
|
||||
"*.js",
|
||||
"*.ts"
|
||||
]
|
||||
}
|
||||
373381
apps/isa-app/documentation.json
Normal file
373381
apps/isa-app/documentation.json
Normal file
File diff suppressed because one or more lines are too long
55
apps/isa-app/eslint.config.mjs
Normal file
55
apps/isa-app/eslint.config.mjs
Normal file
@@ -0,0 +1,55 @@
|
||||
import nx from '@nx/eslint-plugin';
|
||||
import baseConfig from '../../eslint.config.mjs';
|
||||
|
||||
export default [
|
||||
...baseConfig,
|
||||
...nx.configs['flat/angular'],
|
||||
...nx.configs['flat/angular-template'],
|
||||
{
|
||||
files: ['**/*.ts'],
|
||||
rules: {
|
||||
'@angular-eslint/directive-selector': [
|
||||
'error',
|
||||
{
|
||||
type: 'attribute',
|
||||
prefix: 'app',
|
||||
style: 'camelCase',
|
||||
},
|
||||
],
|
||||
'@angular-eslint/component-selector': [
|
||||
'error',
|
||||
{
|
||||
type: 'element',
|
||||
prefix: 'app',
|
||||
style: 'kebab-case',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.ts'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-unused-expressions': 'warn',
|
||||
'prefer-const': 'warn',
|
||||
'@angular-eslint/contextual-lifecycle': 'warn',
|
||||
'@typescript-eslint/no-explicit-any': 'warn',
|
||||
'@angular-eslint/no-empty-lifecycle-method': 'warn',
|
||||
'@typescript-eslint/no-inferrable-types': 'warn',
|
||||
'@angular-eslint/component-selector': 'warn',
|
||||
'@angular-eslint/prefer-standalone': 'warn',
|
||||
'@typescript-eslint/no-inferrable-types': 'warn',
|
||||
'no-empty-function': 'warn',
|
||||
'@typescript-eslint/no-empty-function': 'warn',
|
||||
'@typescript-eslint/no-unused-vars': 'warn',
|
||||
'@angular-eslint/directive-selector': 'warn',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.html'],
|
||||
// Override or add rules here
|
||||
rules: {
|
||||
'@angular-eslint/template/elements-content': 'warn',
|
||||
'@angular-eslint/template/no-autofocus': 'warn',
|
||||
},
|
||||
},
|
||||
];
|
||||
21
apps/isa-app/jest.config.ts
Normal file
21
apps/isa-app/jest.config.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
export default {
|
||||
displayName: 'isa-app',
|
||||
preset: '../../jest.preset.js',
|
||||
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
|
||||
coverageDirectory: '../../coverage/apps/prj',
|
||||
transform: {
|
||||
'^.+\\.(ts|mjs|js|html)$': [
|
||||
'jest-preset-angular',
|
||||
{
|
||||
tsconfig: '<rootDir>/tsconfig.spec.json',
|
||||
stringifyContentPathRegex: '\\.(html|svg)$',
|
||||
},
|
||||
],
|
||||
},
|
||||
transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
|
||||
snapshotSerializers: [
|
||||
'jest-preset-angular/build/serializers/no-ng-attributes',
|
||||
'jest-preset-angular/build/serializers/ng-snapshot',
|
||||
'jest-preset-angular/build/serializers/html-comment',
|
||||
],
|
||||
};
|
||||
@@ -29,4 +29,4 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
164
apps/isa-app/project.json
Normal file
164
apps/isa-app/project.json
Normal file
@@ -0,0 +1,164 @@
|
||||
{
|
||||
"name": "isa-app",
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"projectType": "application",
|
||||
"prefix": "app",
|
||||
"sourceRoot": "apps/isa-app/src",
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@angular-devkit/build-angular:application",
|
||||
"options": {
|
||||
"allowedCommonJsDependencies": [
|
||||
"lodash",
|
||||
"moment",
|
||||
"jsrsasign",
|
||||
"pdfjs-dist/build/pdf",
|
||||
"pdfjs-dist/web/pdf_viewer",
|
||||
"pdfjs-dist/es5/build/pdf",
|
||||
"pdfjs-dist/es5/web/pdf_viewer"
|
||||
],
|
||||
"outputPath": "dist/isa-app",
|
||||
"index": "apps/isa-app/src/index.html",
|
||||
"browser": "apps/isa-app/src/main.ts",
|
||||
"polyfills": ["zone.js"],
|
||||
"tsConfig": "apps/isa-app/tsconfig.app.json",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": [
|
||||
"apps/isa-app/src/favicon.ico",
|
||||
"apps/isa-app/src/assets",
|
||||
"apps/isa-app/src/config",
|
||||
"apps/isa-app/src/silent-refresh.html",
|
||||
"apps/isa-app/src/manifest.webmanifest",
|
||||
{
|
||||
"glob": "**/*",
|
||||
"input": "node_modules/scandit-web-datacapture-barcode/build/engine",
|
||||
"output": "scandit"
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"@angular/cdk/overlay-prebuilt.css",
|
||||
"apps/isa-app/src/ui.scss",
|
||||
"apps/isa-app/src/styles.scss"
|
||||
],
|
||||
"scripts": []
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "2mb",
|
||||
"maximumError": "5mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "25kb"
|
||||
}
|
||||
],
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "apps/isa-app/src/environments/environment.ts",
|
||||
"with": "apps/isa-app/src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"outputHashing": "all",
|
||||
"serviceWorker": "apps/isa-app/ngsw-config.json"
|
||||
},
|
||||
"development": {
|
||||
"optimization": false,
|
||||
"extractLicenses": false,
|
||||
"sourceMap": true
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "production",
|
||||
"outputs": ["{options.outputPath}"]
|
||||
},
|
||||
"serve": {
|
||||
"executor": "@angular-devkit/build-angular:dev-server",
|
||||
"configurations": {
|
||||
"production": {
|
||||
"buildTarget": "isa-app:build:production"
|
||||
},
|
||||
"development": {
|
||||
"buildTarget": "isa-app:build:development"
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "development"
|
||||
},
|
||||
"extract-i18n": {
|
||||
"executor": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"buildTarget": "isa-app:build"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nx/eslint:lint"
|
||||
},
|
||||
"test": {
|
||||
"executor": "@nx/jest:jest",
|
||||
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
|
||||
"options": {
|
||||
"jestConfig": "apps/isa-app/jest.config.ts"
|
||||
}
|
||||
},
|
||||
"serve-static": {
|
||||
"executor": "@nx/web:file-server",
|
||||
"options": {
|
||||
"buildTarget": "isa-app:build",
|
||||
"staticFilePath": "dist/apps/isa-app/browser",
|
||||
"spa": true
|
||||
}
|
||||
},
|
||||
"storybook": {
|
||||
"executor": "@storybook/angular:start-storybook",
|
||||
"options": {
|
||||
"port": 4400,
|
||||
"configDir": "apps/isa-app/.storybook",
|
||||
"browserTarget": "isa-app:build",
|
||||
"compodoc": false,
|
||||
"styles": ["apps/isa-app/src/ui.scss", "apps/isa-app/src/styles.scss"]
|
||||
},
|
||||
"configurations": {
|
||||
"ci": {
|
||||
"quiet": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"build-storybook": {
|
||||
"executor": "@storybook/angular:build-storybook",
|
||||
"outputs": ["{options.outputDir}"],
|
||||
"options": {
|
||||
"outputDir": "dist/storybook/isa-app",
|
||||
"configDir": "apps/isa-app/.storybook",
|
||||
"browserTarget": "isa-app:build",
|
||||
"compodoc": false
|
||||
},
|
||||
"configurations": {
|
||||
"ci": {
|
||||
"quiet": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"test-storybook": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"command": "test-storybook -c apps/isa-app/.storybook --url=http://localhost:4400"
|
||||
}
|
||||
},
|
||||
"static-storybook": {
|
||||
"executor": "@nx/web:file-server",
|
||||
"dependsOn": ["build-storybook"],
|
||||
"options": {
|
||||
"buildTarget": "isa-app:build-storybook",
|
||||
"staticFilePath": "dist/storybook/isa-app",
|
||||
"spa": true
|
||||
},
|
||||
"configurations": {
|
||||
"ci": {
|
||||
"buildTarget": "isa-app:build-storybook:ci"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,22 @@
|
||||
import { Injectable, isDevMode } from '@angular/core';
|
||||
import { EnvironmentService } from '@core/environment';
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { PromptModalData, UiModalService, UiPromptModalComponent } from '@ui/modal';
|
||||
import { Observable } from 'rxjs';
|
||||
import { ScanAdapter } from './scan-adapter';
|
||||
import { Config } from '@core/config';
|
||||
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||
|
||||
@Injectable()
|
||||
export class DevScanAdapter implements ScanAdapter {
|
||||
readonly name = 'Dev';
|
||||
|
||||
constructor(
|
||||
private _modal: UiModalService,
|
||||
private _environmentService: EnvironmentService,
|
||||
) {}
|
||||
private _modal = inject(UiModalService);
|
||||
|
||||
private _config = inject(Config);
|
||||
|
||||
async init(): Promise<boolean> {
|
||||
return Promise.resolve(false);
|
||||
// return new Promise((resolve, reject) => {
|
||||
// resolve(isDevMode());
|
||||
// });
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve(coerceBooleanProperty(this._config.get('dev-scanner')));
|
||||
});
|
||||
}
|
||||
|
||||
scan(): Observable<string> {
|
||||
|
||||
@@ -4,6 +4,10 @@ import { Observable } from 'rxjs';
|
||||
import { filter, map, take } from 'rxjs/operators';
|
||||
import { ScanAdapter } from './scan-adapter';
|
||||
|
||||
/**
|
||||
* @deprecated This service will be removed in future versions.
|
||||
* Please use the new ScanService instead.
|
||||
*/
|
||||
@Injectable()
|
||||
export class NativeScanAdapter implements ScanAdapter {
|
||||
readonly name = 'Native';
|
||||
|
||||
@@ -37,7 +37,7 @@ export class ScanAdapterService {
|
||||
|
||||
for (const name of adapterOrder) {
|
||||
adapter = this.getAdapter(name);
|
||||
|
||||
console.log('adapter', adapter);
|
||||
if (adapter) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3,12 +3,15 @@
|
||||
}
|
||||
|
||||
.scanner-container {
|
||||
width: 100vw;
|
||||
/* width: 100vw;
|
||||
height: 100vh;
|
||||
max-width: 100vh;
|
||||
max-height: 100vh; */
|
||||
}
|
||||
|
||||
.close-scanner {
|
||||
@apply absolute bottom-12 left-[50%] -translate-x-[50%] block px-6 py-4 bg-white text-brand border-2 border-solid border-brand rounded-full text-lg font-bold mx-auto mt-4;
|
||||
@apply whitespace-nowrap;
|
||||
}
|
||||
|
||||
@screen desktop {
|
||||
|
||||
@@ -1,15 +1,27 @@
|
||||
import { Component, ChangeDetectionStrategy, ElementRef, ViewChild, NgZone, AfterViewInit, OnDestroy } from '@angular/core';
|
||||
import { UiMessageModalComponent, UiModalService } from '@ui/modal';
|
||||
import { Barcode, BarcodePicker, ScanResult, ScanSettings } from 'scandit-sdk';
|
||||
import {
|
||||
Component,
|
||||
ChangeDetectionStrategy,
|
||||
ElementRef,
|
||||
ViewChild,
|
||||
NgZone,
|
||||
AfterViewInit,
|
||||
OnDestroy, OnInit,
|
||||
} from '@angular/core';
|
||||
import { BarcodeCapture, BarcodeCaptureSettings, Symbology } from 'scandit-web-datacapture-barcode';
|
||||
import { Camera, DataCaptureContext, DataCaptureView, FrameSourceState } from 'scandit-web-datacapture-core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-scandit-overlay',
|
||||
templateUrl: 'scandit-overlay.component.html',
|
||||
styleUrls: ['scandit-overlay.component.css'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: false,
|
||||
})
|
||||
export class ScanditOverlayComponent implements AfterViewInit, OnDestroy {
|
||||
private _barcodePicker: BarcodePicker;
|
||||
export class ScanditOverlayComponent implements AfterViewInit, OnDestroy, OnInit {
|
||||
private dataCaptureContext: DataCaptureContext;
|
||||
private dataCaptureView: DataCaptureView;
|
||||
private barcodeCapture: BarcodeCapture;
|
||||
private camera: Camera;
|
||||
|
||||
private _onScan?: (code: string) => void;
|
||||
|
||||
@@ -17,57 +29,58 @@ export class ScanditOverlayComponent implements AfterViewInit, OnDestroy {
|
||||
|
||||
@ViewChild('scanContainer', { read: ElementRef, static: true }) scanContainer: ElementRef;
|
||||
|
||||
constructor(
|
||||
private _zone: NgZone,
|
||||
private _modal: UiModalService,
|
||||
) {}
|
||||
constructor(private _zone: NgZone) {}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.createBarcodePicker()
|
||||
.then(() => {
|
||||
this._barcodePicker.on('scan', (scanResult) => {
|
||||
this._zone.run(() => this.handleScanrResult(scanResult));
|
||||
ngOnInit(): void {
|
||||
this.dataCaptureView = new DataCaptureView();
|
||||
|
||||
this.dataCaptureView.connectToElement(this.scanContainer.nativeElement);
|
||||
|
||||
this.dataCaptureView.showProgressBar();
|
||||
}
|
||||
|
||||
async ngAfterViewInit() {
|
||||
this.dataCaptureContext = await DataCaptureContext.create();
|
||||
|
||||
this.dataCaptureView.setContext(this.dataCaptureContext);
|
||||
|
||||
this.barcodeCapture = await BarcodeCapture.forContext(this.dataCaptureContext, this.getScanSettings());
|
||||
|
||||
this.barcodeCapture.addListener({
|
||||
didScan: (_, session, __) => {
|
||||
this._zone.run(() => {
|
||||
const result = session.newlyRecognizedBarcode;
|
||||
|
||||
const code = result?.data ?? '';
|
||||
|
||||
this._onScan?.(code);
|
||||
});
|
||||
})
|
||||
.catch((err: Error) => {
|
||||
this._modal
|
||||
.open({
|
||||
content: UiMessageModalComponent,
|
||||
title: 'Zugriff auf Kamera verweigert',
|
||||
data: { message: 'Falls Sie den Zugriff erlauben möchten, können Sie das über die Webseiteinstellung Ihres Browsers.' },
|
||||
})
|
||||
.afterClosed$.subscribe(() => {
|
||||
this._onClose?.();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async createBarcodePicker() {
|
||||
this._barcodePicker = await BarcodePicker.create(this.scanContainer.nativeElement, {
|
||||
playSoundOnScan: true,
|
||||
vibrateOnScan: true,
|
||||
},
|
||||
});
|
||||
|
||||
this._barcodePicker.applyScanSettings(this.getScanSettings());
|
||||
this.camera = Camera.default;
|
||||
|
||||
this.dataCaptureContext.setFrameSource(this.camera);
|
||||
|
||||
await this.camera.switchToDesiredState(FrameSourceState.On);
|
||||
this.dataCaptureView.hideProgressBar();
|
||||
}
|
||||
|
||||
getScanSettings(): ScanSettings {
|
||||
return new ScanSettings({
|
||||
blurryRecognition: false,
|
||||
getScanSettings(): BarcodeCaptureSettings {
|
||||
const settings = new BarcodeCaptureSettings();
|
||||
|
||||
enabledSymbologies: [
|
||||
Barcode.Symbology.EAN8,
|
||||
Barcode.Symbology.EAN13,
|
||||
Barcode.Symbology.UPCA,
|
||||
Barcode.Symbology.UPCE,
|
||||
Barcode.Symbology.CODE128,
|
||||
Barcode.Symbology.CODE39,
|
||||
Barcode.Symbology.CODE93,
|
||||
Barcode.Symbology.INTERLEAVED_2_OF_5,
|
||||
Barcode.Symbology.QR,
|
||||
],
|
||||
codeDuplicateFilter: 1000,
|
||||
});
|
||||
settings.enableSymbologies([
|
||||
Symbology.EAN8,
|
||||
Symbology.EAN13UPCA,
|
||||
Symbology.UPCE,
|
||||
Symbology.Code128,
|
||||
Symbology.Code39,
|
||||
Symbology.Code93,
|
||||
Symbology.InterleavedTwoOfFive,
|
||||
Symbology.QR,
|
||||
]);
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
onScan(fn: (code: string) => void) {
|
||||
@@ -78,26 +91,14 @@ export class ScanditOverlayComponent implements AfterViewInit, OnDestroy {
|
||||
this._onClose = fn;
|
||||
}
|
||||
|
||||
handleScanrResult(scanRestul: ScanResult) {
|
||||
let result: string | undefined;
|
||||
if (scanRestul.barcodes.length) {
|
||||
result = scanRestul.barcodes[0].data;
|
||||
} else if (scanRestul.texts.length) {
|
||||
result = scanRestul.texts[0].value;
|
||||
}
|
||||
|
||||
if (result) {
|
||||
this._onScan?.(result);
|
||||
}
|
||||
}
|
||||
|
||||
close() {
|
||||
this._onClose?.();
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this._zone.runOutsideAngular(() => {
|
||||
this._barcodePicker?.destroy(true);
|
||||
this.barcodeCapture?.setEnabled(false);
|
||||
this.camera?.switchToDesiredState(FrameSourceState.Off);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@ import { Observable, Subscriber } from 'rxjs';
|
||||
import { ScanAdapter } from '../scan-adapter';
|
||||
import { Overlay } from '@angular/cdk/overlay';
|
||||
|
||||
import { configure } from 'scandit-sdk';
|
||||
import { configure } from 'scandit-web-datacapture-core';
|
||||
import { barcodeCaptureLoader } from 'scandit-web-datacapture-barcode';
|
||||
|
||||
// import { ScanditModalComponent } from './scandit-modal';
|
||||
import { Config } from '@core/config';
|
||||
import { ComponentPortal } from '@angular/cdk/portal';
|
||||
@@ -26,11 +28,17 @@ export class ScanditScanAdapter implements ScanAdapter {
|
||||
|
||||
async init(): Promise<boolean> {
|
||||
if (this._environmentService.isTablet()) {
|
||||
await configure(this._config.get('licence.scandit'), {
|
||||
engineLocation: '/scandit/',
|
||||
});
|
||||
try {
|
||||
await configure({
|
||||
licenseKey: this._config.get('licence.scandit'),
|
||||
libraryLocation: new URL('scandit', document.baseURI).toString(),
|
||||
moduleLoaders: [barcodeCaptureLoader()],
|
||||
});
|
||||
|
||||
return true;
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('ScanditScanAdapter.init', error);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -21,9 +21,16 @@ import { PreviewComponent } from './preview';
|
||||
import { BranchSectionResolver, CustomerSectionResolver, ProcessIdResolver } from './resolvers';
|
||||
import { TokenLoginComponent, TokenLoginModule } from './token-login';
|
||||
import { ProcessIdGuard } from './guards/process-id.guard';
|
||||
import { ActivateProcessIdGuard, ActivateProcessIdWithConfigKeyGuard } from './guards/activate-process-id.guard';
|
||||
import {
|
||||
ActivateProcessIdGuard,
|
||||
ActivateProcessIdWithConfigKeyGuard,
|
||||
} from './guards/activate-process-id.guard';
|
||||
import { MatomoRouteData } from 'ngx-matomo-client';
|
||||
import { processResolverFn } from '@isa/core/process';
|
||||
import { provideScrollPositionRestoration } from '@isa/utils/scroll-position';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', redirectTo: 'kunde/dashboard', pathMatch: 'full' },
|
||||
{
|
||||
path: 'login',
|
||||
children: [
|
||||
@@ -42,6 +49,11 @@ const routes: Routes = [
|
||||
{
|
||||
path: 'dashboard',
|
||||
loadChildren: () => import('@page/dashboard').then((m) => m.DashboardModule),
|
||||
data: {
|
||||
matomo: {
|
||||
title: 'Dashboard',
|
||||
} as MatomoRouteData,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'product',
|
||||
@@ -128,7 +140,8 @@ const routes: Routes = [
|
||||
},
|
||||
{
|
||||
path: 'package-inspection',
|
||||
loadChildren: () => import('@page/package-inspection').then((m) => m.PackageInspectionModule),
|
||||
loadChildren: () =>
|
||||
import('@page/package-inspection').then((m) => m.PackageInspectionModule),
|
||||
canActivate: [CanActivatePackageInspectionGuard],
|
||||
},
|
||||
{
|
||||
@@ -140,7 +153,18 @@ const routes: Routes = [
|
||||
],
|
||||
resolve: { section: BranchSectionResolver },
|
||||
},
|
||||
{ path: '**', redirectTo: 'kunde', pathMatch: 'full' },
|
||||
],
|
||||
},
|
||||
{
|
||||
path: ':processId',
|
||||
component: MainComponent,
|
||||
resolve: { process: processResolverFn },
|
||||
canActivate: [IsAuthenticatedGuard],
|
||||
children: [
|
||||
{
|
||||
path: 'return',
|
||||
loadChildren: () => import('@isa/oms/feature/return-search').then((m) => m.routes),
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -155,5 +179,6 @@ if (isDevMode()) {
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes), TokenLoginModule],
|
||||
exports: [RouterModule],
|
||||
providers: [provideScrollPositionRestoration()],
|
||||
})
|
||||
export class AppRoutingModule {}
|
||||
|
||||
@@ -2,7 +2,6 @@ import { NgModule } from '@angular/core';
|
||||
import { EffectsModule } from '@ngrx/effects';
|
||||
import { ActionReducer, MetaReducer, StoreModule } from '@ngrx/store';
|
||||
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
|
||||
import { storeFreeze } from 'ngrx-store-freeze';
|
||||
import packageInfo from 'packageJson';
|
||||
import { environment } from '../environments/environment';
|
||||
import { RootStateService } from './store/root-state.service';
|
||||
@@ -22,7 +21,9 @@ export function storeInLocalStorage(reducer: ActionReducer<any>): ActionReducer<
|
||||
};
|
||||
}
|
||||
|
||||
export const metaReducers: MetaReducer<RootState>[] = !environment.production ? [storeFreeze, storeInLocalStorage] : [storeInLocalStorage];
|
||||
export const metaReducers: MetaReducer<RootState>[] = !environment.production
|
||||
? [storeInLocalStorage]
|
||||
: [storeInLocalStorage];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import { HttpInterceptorFn, provideHttpClient, withInterceptors } from '@angular/common/http';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Config } from '@core/config';
|
||||
import { AvConfiguration } from '@swagger/availability';
|
||||
import { CatConfiguration } from '@swagger/cat';
|
||||
import { CheckoutConfiguration } from '@swagger/checkout';
|
||||
import { CrmConfiguration } from '@swagger/crm';
|
||||
import { EisConfiguration } from '@swagger/eis';
|
||||
import { IsaConfiguration } from '@swagger/isa';
|
||||
import { OmsConfiguration } from '@swagger/oms';
|
||||
import { PrintConfiguration } from '@swagger/print';
|
||||
import { RemiConfiguration } from '@swagger/remi';
|
||||
import { WwsConfiguration } from '@swagger/wws';
|
||||
import { AvConfiguration } from '@generated/swagger/availability-api';
|
||||
import { CatConfiguration } from '@generated/swagger/cat-search-api';
|
||||
import { CheckoutConfiguration } from '@generated/swagger/checkout-api';
|
||||
import { CrmConfiguration } from '@generated/swagger/crm-api';
|
||||
import { EisConfiguration } from '@generated/swagger/eis-api';
|
||||
import { IsaConfiguration } from '@generated/swagger/isa-api';
|
||||
import { OmsConfiguration } from '@generated/swagger/oms-api';
|
||||
import { PrintConfiguration } from '@generated/swagger/print-api';
|
||||
import { RemiConfiguration } from '@generated/swagger/inventory-api';
|
||||
import { WwsConfiguration } from '@generated/swagger/wws-api';
|
||||
|
||||
export function createConfigurationFactory(name: string) {
|
||||
return function (config: Config): { rootUrl: string } {
|
||||
@@ -17,8 +18,13 @@ export function createConfigurationFactory(name: string) {
|
||||
};
|
||||
}
|
||||
|
||||
const serviceWorkerInterceptor: HttpInterceptorFn = (req, next) => {
|
||||
return next(req.clone({ setHeaders: { 'ngsw-bypass': 'true' } }));
|
||||
};
|
||||
|
||||
@NgModule({
|
||||
providers: [
|
||||
provideHttpClient(withInterceptors([serviceWorkerInterceptor])),
|
||||
{ provide: AvConfiguration, useFactory: createConfigurationFactory('av'), deps: [Config] },
|
||||
{ provide: CatConfiguration, useFactory: createConfigurationFactory('cat'), deps: [Config] },
|
||||
{ provide: CheckoutConfiguration, useFactory: createConfigurationFactory('checkout'), deps: [Config] },
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Renderer2 } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { SwUpdate } from '@angular/service-worker';
|
||||
import { NotificationsHub } from '@hub/notifications';
|
||||
import { UserStateService } from '@swagger/isa';
|
||||
import { UserStateService } from '@generated/swagger/isa-api';
|
||||
import { UiModalService } from '@ui/modal';
|
||||
import { AuthService } from '@core/auth';
|
||||
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { Component, effect, HostListener, Inject, OnInit, Renderer2, signal, untracked } from '@angular/core';
|
||||
import {
|
||||
Component,
|
||||
effect,
|
||||
HostListener,
|
||||
inject,
|
||||
Inject,
|
||||
Injector,
|
||||
OnInit,
|
||||
Renderer2,
|
||||
signal,
|
||||
untracked,
|
||||
} from '@angular/core';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { SwUpdate } from '@angular/service-worker';
|
||||
import { ApplicationService } from '@core/application';
|
||||
@@ -7,10 +18,10 @@ import { Config } from '@core/config';
|
||||
import { NotificationsHub } from '@hub/notifications';
|
||||
import packageInfo from 'packageJson';
|
||||
import { asapScheduler, interval, Subscription } from 'rxjs';
|
||||
import { UserStateService } from '@swagger/isa';
|
||||
import { UserStateService } from '@generated/swagger/isa-api';
|
||||
import { IsaLogProvider } from './providers';
|
||||
import { EnvironmentService } from '@core/environment';
|
||||
import { AuthService } from '@core/auth';
|
||||
import { AuthService, LoginStrategy } from '@core/auth';
|
||||
import { UiMessageModalComponent, UiModalService } from '@ui/modal';
|
||||
import { injectOnline$ } from './services/network-status.service';
|
||||
import { toSignal } from '@angular/core/rxjs-interop';
|
||||
@@ -33,8 +44,11 @@ import { animate, style, transition, trigger } from '@angular/animations';
|
||||
]),
|
||||
]),
|
||||
],
|
||||
standalone: false,
|
||||
})
|
||||
export class AppComponent implements OnInit {
|
||||
readonly injector = inject(Injector);
|
||||
|
||||
$online = toSignal(injectOnline$());
|
||||
|
||||
$offlineBannerVisible = signal(false);
|
||||
@@ -118,7 +132,10 @@ export class AppComponent implements OnInit {
|
||||
}
|
||||
|
||||
logVersion() {
|
||||
console.log(`%c${this._config.get('title')}\r\nVersion: ${packageInfo.version}`, 'font-weight: bold; font-size: 20px;');
|
||||
console.log(
|
||||
`%c${this._config.get('title')}\r\nVersion: ${packageInfo.version}`,
|
||||
'font-weight: bold; font-size: 20px;',
|
||||
);
|
||||
}
|
||||
|
||||
determinePlatform() {
|
||||
@@ -180,15 +197,9 @@ export class AppComponent implements OnInit {
|
||||
if (this._document.hidden && this._authService.isAuthenticated()) {
|
||||
this._authService.refresh();
|
||||
} else if (!this._authService.isAuthenticated()) {
|
||||
return this._modal
|
||||
.open({
|
||||
content: UiMessageModalComponent,
|
||||
title: 'Sie sind nicht mehr angemeldet',
|
||||
data: { message: 'Sie werden neu angemeldet' },
|
||||
})
|
||||
.afterClosed$.subscribe(() => {
|
||||
this._authService.login();
|
||||
});
|
||||
const strategy = this.injector.get(LoginStrategy);
|
||||
|
||||
return strategy.login('Sie sind nicht mehr angemeldet');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,22 @@
|
||||
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||
import { APP_INITIALIZER, ErrorHandler, Injector, LOCALE_ID, NgModule } from '@angular/core';
|
||||
import {
|
||||
HTTP_INTERCEPTORS,
|
||||
provideHttpClient,
|
||||
withInterceptorsFromDi,
|
||||
} from '@angular/common/http';
|
||||
import {
|
||||
ErrorHandler,
|
||||
Injector,
|
||||
LOCALE_ID,
|
||||
NgModule,
|
||||
inject,
|
||||
provideAppInitializer,
|
||||
} from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { PlatformModule } from '@angular/cdk/platform';
|
||||
|
||||
import { Config, ConfigModule, JsonConfigLoader } from '@core/config';
|
||||
import { AuthModule, AuthService } from '@core/auth';
|
||||
import { Config } from '@core/config';
|
||||
import { AuthModule, AuthService, LoginStrategy } from '@core/auth';
|
||||
import { CoreCommandModule } from '@core/command';
|
||||
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
@@ -17,7 +28,10 @@ import { environment } from '../environments/environment';
|
||||
import { AppSwaggerModule } from './app-swagger.module';
|
||||
import { AppDomainModule } from './app-domain.module';
|
||||
import { UiModalModule } from '@ui/modal';
|
||||
import { NotificationsHubModule, NOTIFICATIONS_HUB_OPTIONS } from '@hub/notifications';
|
||||
import {
|
||||
NotificationsHubModule,
|
||||
NOTIFICATIONS_HUB_OPTIONS,
|
||||
} from '@hub/notifications';
|
||||
import { SignalRHubOptions } from '@core/signalr';
|
||||
import { CoreBreadcrumbModule } from '@core/breadcrumb';
|
||||
import { UiCommonModule } from '@ui/common';
|
||||
@@ -29,7 +43,11 @@ import { HttpErrorInterceptor } from './interceptors';
|
||||
import { CoreLoggerModule, LOG_PROVIDER } from '@core/logger';
|
||||
import { IsaLogProvider } from './providers';
|
||||
import { IsaErrorHandler } from './providers/isa.error-handler';
|
||||
import { ScanAdapterModule, ScanAdapterService, ScanditScanAdapterModule } from '@adapter/scan';
|
||||
import {
|
||||
ScanAdapterModule,
|
||||
ScanAdapterService,
|
||||
ScanditScanAdapterModule,
|
||||
} from '@adapter/scan';
|
||||
import { RootStateService } from './store/root-state.service';
|
||||
import * as Commands from './commands';
|
||||
import { PreviewComponent } from './preview';
|
||||
@@ -38,28 +56,34 @@ import { ShellModule } from '@shared/shell';
|
||||
import { MainComponent } from './main.component';
|
||||
import { IconModule } from '@shared/components/icon';
|
||||
import { NgIconsModule } from '@ng-icons/core';
|
||||
import { matClose, matWifi, matWifiOff } from '@ng-icons/material-icons/baseline';
|
||||
import {
|
||||
matClose,
|
||||
matWifi,
|
||||
matWifiOff,
|
||||
} from '@ng-icons/material-icons/baseline';
|
||||
import { NetworkStatusService } from './services/network-status.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { provideMatomo } from 'ngx-matomo-client';
|
||||
import { withRouter, withRouteData } from 'ngx-matomo-client';
|
||||
import {
|
||||
provideLogging,
|
||||
withLogLevel,
|
||||
LogLevel,
|
||||
withSink,
|
||||
ConsoleLogSink,
|
||||
} from '@isa/core/logging';
|
||||
|
||||
registerLocaleData(localeDe, localeDeExtra);
|
||||
registerLocaleData(localeDe, 'de', localeDeExtra);
|
||||
|
||||
export function _appInitializerFactory(
|
||||
config: Config,
|
||||
auth: AuthService,
|
||||
injector: Injector,
|
||||
scanAdapter: ScanAdapterService,
|
||||
nativeContainer: NativeContainerService,
|
||||
networkStatus: NetworkStatusService,
|
||||
) {
|
||||
export function _appInitializerFactory(config: Config, injector: Injector) {
|
||||
return async () => {
|
||||
const statusElement = document.querySelector('#init-status');
|
||||
const laoderElement = document.querySelector('#init-loader');
|
||||
|
||||
try {
|
||||
let online = false;
|
||||
|
||||
const networkStatus = injector.get(NetworkStatusService);
|
||||
while (!online) {
|
||||
online = await firstValueFrom(networkStatus.online$);
|
||||
|
||||
@@ -71,28 +95,43 @@ export function _appInitializerFactory(
|
||||
}
|
||||
|
||||
statusElement.innerHTML = 'Konfigurationen werden geladen...';
|
||||
await config.init();
|
||||
statusElement.innerHTML = 'Authentifizierung wird geprüft...';
|
||||
await auth.init();
|
||||
|
||||
if (auth.isAuthenticated()) {
|
||||
statusElement.innerHTML = 'App wird initialisiert...';
|
||||
const state = injector.get(RootStateService);
|
||||
await state.init();
|
||||
}
|
||||
|
||||
statusElement.innerHTML = 'Native Container wird initialisiert...';
|
||||
await nativeContainer.init();
|
||||
|
||||
statusElement.innerHTML = 'Scanner wird initialisiert...';
|
||||
const scanAdapter = injector.get(ScanAdapterService);
|
||||
await scanAdapter.init();
|
||||
|
||||
statusElement.innerHTML = 'Authentifizierung wird geprüft...';
|
||||
|
||||
const auth = injector.get(AuthService);
|
||||
try {
|
||||
await auth.init();
|
||||
} catch (error) {
|
||||
statusElement.innerHTML = 'Authentifizierung wird durchgeführt...';
|
||||
const strategy = injector.get(LoginStrategy);
|
||||
await strategy.login();
|
||||
}
|
||||
|
||||
statusElement.innerHTML = 'App wird initialisiert...';
|
||||
const state = injector.get(RootStateService);
|
||||
await state.init();
|
||||
|
||||
statusElement.innerHTML = 'Native Container wird initialisiert...';
|
||||
const nativeContainer = injector.get(NativeContainerService);
|
||||
await nativeContainer.init();
|
||||
} catch (error) {
|
||||
laoderElement.remove();
|
||||
statusElement.classList.add('text-xl');
|
||||
statusElement.innerHTML = '<b>Fehler bei der Initialisierung</b><br><br>Bitte prüfen Sie die Netzwerkverbindung (WLAN).<br><br>';
|
||||
statusElement.innerHTML +=
|
||||
'⚡<br><br><b>Fehler bei der Initialisierung</b><br><br>Bitte prüfen Sie die Netzwerkverbindung (WLAN).<br><br>';
|
||||
|
||||
const reload = document.createElement('button');
|
||||
reload.classList.add('bg-brand', 'text-white', 'p-2', 'rounded', 'cursor-pointer');
|
||||
reload.classList.add(
|
||||
'bg-brand',
|
||||
'text-white',
|
||||
'p-2',
|
||||
'rounded',
|
||||
'cursor-pointer',
|
||||
);
|
||||
reload.innerHTML = 'App neu laden';
|
||||
reload.onclick = () => window.location.reload();
|
||||
statusElement.appendChild(reload);
|
||||
@@ -115,7 +154,10 @@ export function _appInitializerFactory(
|
||||
};
|
||||
}
|
||||
|
||||
export function _notificationsHubOptionsFactory(config: Config, auth: AuthService): SignalRHubOptions {
|
||||
export function _notificationsHubOptionsFactory(
|
||||
config: Config,
|
||||
auth: AuthService,
|
||||
): SignalRHubOptions {
|
||||
const options = { ...config.get('hubs').notifications };
|
||||
options.httpOptions.accessTokenFactory = () => auth.getToken();
|
||||
return options;
|
||||
@@ -123,19 +165,15 @@ export function _notificationsHubOptionsFactory(config: Config, auth: AuthServic
|
||||
|
||||
@NgModule({
|
||||
declarations: [AppComponent, MainComponent],
|
||||
bootstrap: [AppComponent],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
BrowserAnimationsModule,
|
||||
HttpClientModule,
|
||||
ShellModule.forRoot(),
|
||||
AppRoutingModule,
|
||||
AppSwaggerModule,
|
||||
AppDomainModule,
|
||||
CoreBreadcrumbModule.forRoot(),
|
||||
ConfigModule.forRoot({
|
||||
useConfigLoader: JsonConfigLoader,
|
||||
jsonConfigLoaderUrl: '/config/config.json',
|
||||
}),
|
||||
CoreCommandModule.forRoot(Object.values(Commands)),
|
||||
CoreLoggerModule.forRoot(),
|
||||
AppStoreModule,
|
||||
@@ -156,12 +194,13 @@ export function _notificationsHubOptionsFactory(config: Config, auth: AuthServic
|
||||
NgIconsModule.withIcons({ matWifiOff, matClose, matWifi }),
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: _appInitializerFactory,
|
||||
multi: true,
|
||||
deps: [Config, AuthService, Injector, ScanAdapterService, NativeContainerService, NetworkStatusService],
|
||||
},
|
||||
provideAppInitializer(() => {
|
||||
const initializerFn = _appInitializerFactory(
|
||||
inject(Config),
|
||||
inject(Injector),
|
||||
);
|
||||
return initializerFn();
|
||||
}),
|
||||
{
|
||||
provide: NOTIFICATIONS_HUB_OPTIONS,
|
||||
useFactory: _notificationsHubOptionsFactory,
|
||||
@@ -182,7 +221,13 @@ export function _notificationsHubOptionsFactory(config: Config, auth: AuthServic
|
||||
useClass: IsaErrorHandler,
|
||||
},
|
||||
{ provide: LOCALE_ID, useValue: 'de-DE' },
|
||||
provideHttpClient(withInterceptorsFromDi()),
|
||||
provideMatomo(
|
||||
{ trackerUrl: 'https://matomo.paragon-data.net', siteId: '1' },
|
||||
withRouter(),
|
||||
withRouteData(),
|
||||
),
|
||||
provideLogging(withLogLevel(LogLevel.Debug), withSink(ConsoleLogSink)),
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
export class AppModule {}
|
||||
|
||||
@@ -3,11 +3,14 @@ import { Router } from '@angular/router';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { ActionHandler } from '@core/command';
|
||||
import { Result } from '@domain/defs';
|
||||
import { CustomerInfoDTO } from '@swagger/crm';
|
||||
import { CustomerInfoDTO } from '@generated/swagger/crm-api';
|
||||
|
||||
@Injectable()
|
||||
export class CreateCustomerCommand extends ActionHandler<Result<CustomerInfoDTO[]>> {
|
||||
constructor(private _router: Router, private _application: ApplicationService) {
|
||||
constructor(
|
||||
private _router: Router,
|
||||
private _application: ApplicationService,
|
||||
) {
|
||||
super('CREATE_CUSTOMER');
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { ApplicationService } from '@core/application';
|
||||
import { ActionHandler } from '@core/command';
|
||||
import { Result } from '@domain/defs';
|
||||
import { encodeFormData, mapCustomerInfoDtoToCustomerCreateFormData } from '@page/customer';
|
||||
import { CustomerInfoDTO } from '@swagger/crm';
|
||||
import { CustomerInfoDTO } from '@generated/swagger/crm-api';
|
||||
|
||||
@Injectable()
|
||||
export class CreateKubiCustomerCommand extends ActionHandler<Result<CustomerInfoDTO[]>> {
|
||||
@@ -40,9 +40,12 @@ export class CreateKubiCustomerCommand extends ActionHandler<Result<CustomerInfo
|
||||
customerType = 'store';
|
||||
}
|
||||
|
||||
await this._router.navigate(['/kunde', this._application.activatedProcessId, 'customer', 'create', `${customerType}-p4m`], {
|
||||
queryParams: { formData },
|
||||
});
|
||||
await this._router.navigate(
|
||||
['/kunde', this._application.activatedProcessId, 'customer', 'create', `${customerType}-p4m`],
|
||||
{
|
||||
queryParams: { formData },
|
||||
},
|
||||
);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,15 @@ import { ActionHandler } from '@core/command';
|
||||
import { Result } from '@domain/defs';
|
||||
import { DomainPrinterService } from '@domain/printer';
|
||||
import { PrintModalComponent, PrintModalData } from '@modal/printer';
|
||||
import { CustomerInfoDTO } from '@swagger/crm';
|
||||
import { CustomerInfoDTO } from '@generated/swagger/crm-api';
|
||||
import { UiModalService } from '@ui/modal';
|
||||
|
||||
@Injectable()
|
||||
export class PrintKubiCustomerCommand extends ActionHandler<Result<CustomerInfoDTO[]>> {
|
||||
constructor(private _uiModal: UiModalService, private _printerService: DomainPrinterService) {
|
||||
constructor(
|
||||
private _uiModal: UiModalService,
|
||||
private _printerService: DomainPrinterService,
|
||||
) {
|
||||
super('PRINT_KUBI_AGB');
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,10 @@ import { ApplicationService } from '@core/application';
|
||||
import { Config } from '@core/config';
|
||||
import { take } from 'rxjs/operators';
|
||||
|
||||
export const ActivateProcessIdGuard: CanActivateFn = async (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
|
||||
export const ActivateProcessIdGuard: CanActivateFn = async (
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot,
|
||||
) => {
|
||||
const application = inject(ApplicationService);
|
||||
|
||||
const processIdStr = route.params.processId;
|
||||
@@ -27,20 +30,18 @@ export const ActivateProcessIdGuard: CanActivateFn = async (route: ActivatedRout
|
||||
return true;
|
||||
};
|
||||
|
||||
export const ActivateProcessIdWithConfigKeyGuard: (key: string) => CanActivateFn = (key) => async (
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot
|
||||
) => {
|
||||
const application = inject(ApplicationService);
|
||||
const config = inject(Config);
|
||||
export const ActivateProcessIdWithConfigKeyGuard: (key: string) => CanActivateFn =
|
||||
(key) => async (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
|
||||
const application = inject(ApplicationService);
|
||||
const config = inject(Config);
|
||||
|
||||
const processId = config.get(`process.ids.${key}`);
|
||||
const processId = config.get(`process.ids.${key}`);
|
||||
|
||||
if (isNaN(processId)) {
|
||||
return false;
|
||||
}
|
||||
if (isNaN(processId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
application.activateProcess(processId);
|
||||
application.activateProcess(processId);
|
||||
|
||||
return true;
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
@@ -6,10 +6,16 @@ import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivateAssortmentGuard {
|
||||
constructor(private readonly _applicationService: ApplicationService, private readonly _config: Config) {}
|
||||
constructor(
|
||||
private readonly _applicationService: ApplicationService,
|
||||
private readonly _config: Config,
|
||||
) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const process = await this._applicationService.getProcessById$(this._config.get('process.ids.assortment')).pipe(first()).toPromise();
|
||||
const process = await this._applicationService
|
||||
.getProcessById$(this._config.get('process.ids.assortment'))
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
if (!process) {
|
||||
await this._applicationService.createProcess({
|
||||
id: this._config.get('process.ids.assortment'),
|
||||
|
||||
@@ -8,10 +8,7 @@ export class CanActivateCartWithProcessIdGuard {
|
||||
constructor(private readonly _applicationService: ApplicationService) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const process = await this._applicationService
|
||||
.getProcessById$(+route.params.processId)
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
const process = await this._applicationService.getProcessById$(+route.params.processId).pipe(first()).toPromise();
|
||||
|
||||
// if (!(process?.type === 'cart')) {
|
||||
// // TODO:
|
||||
|
||||
@@ -14,7 +14,10 @@ export class CanActivateCartGuard {
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||
let lastActivatedProcessId = (
|
||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart').pipe(first()).toPromise()
|
||||
await this._applicationService
|
||||
.getLastActivatedProcessWithSectionAndType$('customer', 'cart')
|
||||
.pipe(first())
|
||||
.toPromise()
|
||||
)?.id;
|
||||
if (!lastActivatedProcessId) {
|
||||
lastActivatedProcessId = Date.now();
|
||||
|
||||
@@ -6,13 +6,13 @@ import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivateCustomerOrdersWithProcessIdGuard {
|
||||
constructor(private readonly _applicationService: ApplicationService, private readonly _breadcrumbService: BreadcrumbService) {}
|
||||
constructor(
|
||||
private readonly _applicationService: ApplicationService,
|
||||
private readonly _breadcrumbService: BreadcrumbService,
|
||||
) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const process = await this._applicationService
|
||||
.getProcessById$(+route.params.processId)
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
const process = await this._applicationService.getProcessById$(+route.params.processId).pipe(first()).toPromise();
|
||||
|
||||
if (!process) {
|
||||
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||
@@ -31,10 +31,7 @@ export class CanActivateCustomerOrdersWithProcessIdGuard {
|
||||
|
||||
// Fix #3292: Alle Breadcrumbs die nichts mit dem aktuellen Prozess zu tun haben, müssen removed werden
|
||||
async removeBreadcrumbWithSameProcessId(route: ActivatedRouteSnapshot) {
|
||||
const crumbs = await this._breadcrumbService
|
||||
.getBreadcrumbByKey$(+route.params.processId)
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
const crumbs = await this._breadcrumbService.getBreadcrumbByKey$(+route.params.processId).pipe(first()).toPromise();
|
||||
|
||||
// Entferne alle Crumbs die nichts mit den Kundenbestellungen zu tun haben
|
||||
if (crumbs.length > 1) {
|
||||
|
||||
@@ -17,11 +17,17 @@ export class CanActivateCustomerOrdersGuard {
|
||||
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||
|
||||
let lastActivatedProcessId = (
|
||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart').pipe(first()).toPromise()
|
||||
await this._applicationService
|
||||
.getLastActivatedProcessWithSectionAndType$('customer', 'cart')
|
||||
.pipe(first())
|
||||
.toPromise()
|
||||
)?.id;
|
||||
|
||||
const lastActivatedCartCheckoutProcessId = (
|
||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout').pipe(first()).toPromise()
|
||||
await this._applicationService
|
||||
.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout')
|
||||
.pipe(first())
|
||||
.toPromise()
|
||||
)?.id;
|
||||
|
||||
const activatedProcessId = await this._applicationService.getActivatedProcessId$().pipe(first()).toPromise();
|
||||
|
||||
@@ -6,13 +6,13 @@ import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivateCustomerWithProcessIdGuard {
|
||||
constructor(private readonly _applicationService: ApplicationService, private readonly _breadcrumbService: BreadcrumbService) {}
|
||||
constructor(
|
||||
private readonly _applicationService: ApplicationService,
|
||||
private readonly _breadcrumbService: BreadcrumbService,
|
||||
) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const process = await this._applicationService
|
||||
.getProcessById$(+route.params.processId)
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
const process = await this._applicationService.getProcessById$(+route.params.processId).pipe(first()).toPromise();
|
||||
|
||||
// if (!(process?.type === 'cart')) {
|
||||
// // TODO:
|
||||
@@ -37,10 +37,7 @@ export class CanActivateCustomerWithProcessIdGuard {
|
||||
|
||||
// Fix #3292: Alle Breadcrumbs die nichts mit dem aktuellen Prozess zu tun haben, müssen removed werden
|
||||
async removeBreadcrumbWithSameProcessId(route: ActivatedRouteSnapshot) {
|
||||
const crumbs = await this._breadcrumbService
|
||||
.getBreadcrumbByKey$(+route.params.processId)
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
const crumbs = await this._breadcrumbService.getBreadcrumbByKey$(+route.params.processId).pipe(first()).toPromise();
|
||||
|
||||
// Entferne alle Crumbs die nichts mit der Kundensuche zu tun haben
|
||||
if (crumbs.length > 1) {
|
||||
|
||||
@@ -17,15 +17,24 @@ export class CanActivateCustomerGuard {
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||
let lastActivatedProcessId = (
|
||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart').pipe(first()).toPromise()
|
||||
await this._applicationService
|
||||
.getLastActivatedProcessWithSectionAndType$('customer', 'cart')
|
||||
.pipe(first())
|
||||
.toPromise()
|
||||
)?.id;
|
||||
|
||||
const lastActivatedCartCheckoutProcessId = (
|
||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout').pipe(first()).toPromise()
|
||||
await this._applicationService
|
||||
.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout')
|
||||
.pipe(first())
|
||||
.toPromise()
|
||||
)?.id;
|
||||
|
||||
const lastActivatedGoodsOutProcessId = (
|
||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'goods-out').pipe(first()).toPromise()
|
||||
await this._applicationService
|
||||
.getLastActivatedProcessWithSectionAndType$('customer', 'goods-out')
|
||||
.pipe(first())
|
||||
.toPromise()
|
||||
)?.id;
|
||||
|
||||
const activatedProcessId = await this._applicationService.getActivatedProcessId$().pipe(first()).toPromise();
|
||||
|
||||
@@ -3,13 +3,21 @@ import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { Config } from '@core/config';
|
||||
import { first } from 'rxjs/operators';
|
||||
import { z } from 'zod';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivateGoodsInGuard {
|
||||
constructor(private readonly _applicationService: ApplicationService, private readonly _config: Config) {}
|
||||
constructor(
|
||||
private readonly _applicationService: ApplicationService,
|
||||
private readonly _config: Config,
|
||||
) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const process = await this._applicationService.getProcessById$(this._config.get('process.ids.goodsIn')).pipe(first()).toPromise();
|
||||
const pid = this._config.get('process.ids.goodsIn', z.number());
|
||||
const process = await this._applicationService
|
||||
.getProcessById$(pid)
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
if (!process) {
|
||||
await this._applicationService.createProcess({
|
||||
id: this._config.get('process.ids.goodsIn'),
|
||||
@@ -18,7 +26,9 @@ export class CanActivateGoodsInGuard {
|
||||
name: '',
|
||||
});
|
||||
}
|
||||
this._applicationService.activateProcess(this._config.get('process.ids.goodsIn'));
|
||||
this._applicationService.activateProcess(
|
||||
this._config.get('process.ids.goodsIn'),
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,13 +6,13 @@ import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivateGoodsOutWithProcessIdGuard {
|
||||
constructor(private readonly _applicationService: ApplicationService, private readonly _breadcrumbService: BreadcrumbService) {}
|
||||
constructor(
|
||||
private readonly _applicationService: ApplicationService,
|
||||
private readonly _breadcrumbService: BreadcrumbService,
|
||||
) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const process = await this._applicationService
|
||||
.getProcessById$(+route.params.processId)
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
const process = await this._applicationService.getProcessById$(+route.params.processId).pipe(first()).toPromise();
|
||||
|
||||
if (!process) {
|
||||
// const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||
@@ -31,10 +31,7 @@ export class CanActivateGoodsOutWithProcessIdGuard {
|
||||
|
||||
// Fix #3292: Alle Breadcrumbs die nichts mit dem aktuellen Prozess zu tun haben, müssen removed werden
|
||||
async removeBreadcrumbWithSameProcessId(route: ActivatedRouteSnapshot) {
|
||||
const crumbs = await this._breadcrumbService
|
||||
.getBreadcrumbByKey$(+route.params.processId)
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
const crumbs = await this._breadcrumbService.getBreadcrumbByKey$(+route.params.processId).pipe(first()).toPromise();
|
||||
|
||||
// Entferne alle Crumbs die nichts mit der Warenausgabe zu tun haben
|
||||
if (crumbs.length > 1) {
|
||||
|
||||
@@ -9,7 +9,7 @@ export class CanActivateGoodsOutGuard {
|
||||
constructor(
|
||||
private readonly _applicationService: ApplicationService,
|
||||
private readonly _checkoutService: DomainCheckoutService,
|
||||
private readonly _router: Router
|
||||
private readonly _router: Router,
|
||||
) {}
|
||||
|
||||
// !!! Ticket #3272 Code soll vorerst bestehen bleiben. Prozess Warenausgabe soll wieder Vorgang heißen (wie aktuell im Produktiv), bis zum neuen Navigationskonzept
|
||||
@@ -103,11 +103,17 @@ export class CanActivateGoodsOutGuard {
|
||||
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||
|
||||
let lastActivatedProcessId = (
|
||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart').pipe(first()).toPromise()
|
||||
await this._applicationService
|
||||
.getLastActivatedProcessWithSectionAndType$('customer', 'cart')
|
||||
.pipe(first())
|
||||
.toPromise()
|
||||
)?.id;
|
||||
|
||||
const lastActivatedCartCheckoutProcessId = (
|
||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout').pipe(first()).toPromise()
|
||||
await this._applicationService
|
||||
.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout')
|
||||
.pipe(first())
|
||||
.toPromise()
|
||||
)?.id;
|
||||
|
||||
const activatedProcessId = await this._applicationService.getActivatedProcessId$().pipe(first()).toPromise();
|
||||
|
||||
@@ -6,7 +6,10 @@ import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivatePackageInspectionGuard {
|
||||
constructor(private readonly _applicationService: ApplicationService, private readonly _config: Config) {}
|
||||
constructor(
|
||||
private readonly _applicationService: ApplicationService,
|
||||
private readonly _config: Config,
|
||||
) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const process = await this._applicationService
|
||||
|
||||
@@ -6,13 +6,13 @@ import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivateProductWithProcessIdGuard {
|
||||
constructor(private readonly _applicationService: ApplicationService, private readonly _breadcrumbService: BreadcrumbService) {}
|
||||
constructor(
|
||||
private readonly _applicationService: ApplicationService,
|
||||
private readonly _breadcrumbService: BreadcrumbService,
|
||||
) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const process = await this._applicationService
|
||||
.getProcessById$(+route.params.processId)
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
const process = await this._applicationService.getProcessById$(+route.params.processId).pipe(first()).toPromise();
|
||||
|
||||
// if (!(process?.type === 'cart')) {
|
||||
// // TODO:
|
||||
@@ -37,10 +37,7 @@ export class CanActivateProductWithProcessIdGuard {
|
||||
|
||||
// Fix #3292: Alle Breadcrumbs die nichts mit dem aktuellen Prozess zu tun haben, müssen removed werden
|
||||
async removeBreadcrumbWithSameProcessId(route: ActivatedRouteSnapshot) {
|
||||
const crumbs = await this._breadcrumbService
|
||||
.getBreadcrumbByKey$(+route.params.processId)
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
const crumbs = await this._breadcrumbService.getBreadcrumbByKey$(+route.params.processId).pipe(first()).toPromise();
|
||||
|
||||
// Entferne alle Crumbs die nichts mit der Artikelsuche zu tun haben
|
||||
if (crumbs.length > 1) {
|
||||
|
||||
@@ -16,15 +16,24 @@ export class CanActivateProductGuard {
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||
let lastActivatedProcessId = (
|
||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart').pipe(first()).toPromise()
|
||||
await this._applicationService
|
||||
.getLastActivatedProcessWithSectionAndType$('customer', 'cart')
|
||||
.pipe(first())
|
||||
.toPromise()
|
||||
)?.id;
|
||||
|
||||
const lastActivatedCartCheckoutProcessId = (
|
||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout').pipe(first()).toPromise()
|
||||
await this._applicationService
|
||||
.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout')
|
||||
.pipe(first())
|
||||
.toPromise()
|
||||
)?.id;
|
||||
|
||||
const lastActivatedGoodsOutProcessId = (
|
||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'goods-out').pipe(first()).toPromise()
|
||||
await this._applicationService
|
||||
.getLastActivatedProcessWithSectionAndType$('customer', 'goods-out')
|
||||
.pipe(first())
|
||||
.toPromise()
|
||||
)?.id;
|
||||
|
||||
const activatedProcessId = await this._applicationService.getActivatedProcessId$().pipe(first()).toPromise();
|
||||
|
||||
@@ -9,11 +9,14 @@ export class CanActivateRemissionGuard {
|
||||
constructor(
|
||||
private readonly _applicationService: ApplicationService,
|
||||
private readonly _config: Config,
|
||||
private readonly _router: Router
|
||||
private readonly _router: Router,
|
||||
) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const process = await this._applicationService.getProcessById$(this._config.get('process.ids.remission')).pipe(first()).toPromise();
|
||||
const process = await this._applicationService
|
||||
.getProcessById$(this._config.get('process.ids.remission'))
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
if (!process) {
|
||||
await this._applicationService.createProcess({
|
||||
id: this._config.get('process.ids.remission'),
|
||||
|
||||
@@ -6,10 +6,16 @@ import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivateTaskCalendarGuard {
|
||||
constructor(private readonly _applicationService: ApplicationService, private readonly _config: Config) {}
|
||||
constructor(
|
||||
private readonly _applicationService: ApplicationService,
|
||||
private readonly _config: Config,
|
||||
) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const process = await this._applicationService.getProcessById$(this._config.get('process.ids.taskCalendar')).pipe(first()).toPromise();
|
||||
const process = await this._applicationService
|
||||
.getProcessById$(this._config.get('process.ids.taskCalendar'))
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
if (!process) {
|
||||
await this._applicationService.createProcess({
|
||||
id: this._config.get('process.ids.taskCalendar'),
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';
|
||||
import { AuthService } from '@core/auth';
|
||||
import { ScanAdapterService } from '@adapter/scan';
|
||||
import { AuthService as IsaAuthService } from '@swagger/isa';
|
||||
import { AuthService as IsaAuthService } from '@generated/swagger/isa-api';
|
||||
import { UiConfirmModalComponent, UiErrorModalComponent, UiModalResult, UiModalService } from '@ui/modal';
|
||||
import { EnvironmentService } from '@core/environment';
|
||||
import { injectNetworkStatus$ } from '../services/network-status.service';
|
||||
|
||||
@@ -5,7 +5,7 @@ import { take } from 'rxjs/operators';
|
||||
|
||||
export const ProcessIdGuard: CanActivateFn = async (
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot
|
||||
state: RouterStateSnapshot,
|
||||
): Promise<boolean | UrlTree> => {
|
||||
const application = inject(ApplicationService);
|
||||
const router = inject(Router);
|
||||
|
||||
@@ -1,66 +1,66 @@
|
||||
import { HttpErrorInterceptor } from './http-error.interceptor';
|
||||
import { createServiceFactory, SpectatorService } from '@ngneat/spectator';
|
||||
import { UiMessageModalComponent, UiModalResult, UiModalService } from '@ui/modal';
|
||||
import { of, Subject, throwError } from 'rxjs';
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { AuthService } from '@core/auth';
|
||||
// import { HttpErrorInterceptor } from './http-error.interceptor';
|
||||
// import { createServiceFactory, SpectatorService } from '@ngneat/spectator';
|
||||
// import { UiMessageModalComponent, UiModalResult, UiModalService } from '@ui/modal';
|
||||
// import { of, Subject, throwError } from 'rxjs';
|
||||
// import { HttpErrorResponse } from '@angular/common/http';
|
||||
// import { AuthService } from '@core/auth';
|
||||
|
||||
describe('HttpErrorInterceptor', () => {
|
||||
let spectator: SpectatorService<HttpErrorInterceptor>;
|
||||
let modalMock: jasmine.SpyObj<UiModalService>;
|
||||
let httpErrorInterceptor: HttpErrorInterceptor;
|
||||
// describe('HttpErrorInterceptor', () => {
|
||||
// let spectator: SpectatorService<HttpErrorInterceptor>;
|
||||
// let modalMock: jasmine.SpyObj<UiModalService>;
|
||||
// let httpErrorInterceptor: HttpErrorInterceptor;
|
||||
|
||||
const createService = createServiceFactory({
|
||||
service: HttpErrorInterceptor,
|
||||
mocks: [UiModalService, AuthService],
|
||||
});
|
||||
// const createService = createServiceFactory({
|
||||
// service: HttpErrorInterceptor,
|
||||
// mocks: [UiModalService, AuthService],
|
||||
// });
|
||||
|
||||
beforeEach(() => {
|
||||
spectator = createService();
|
||||
httpErrorInterceptor = spectator.service;
|
||||
modalMock = spectator.inject(UiModalService);
|
||||
// beforeEach(() => {
|
||||
// spectator = createService();
|
||||
// httpErrorInterceptor = spectator.service;
|
||||
// modalMock = spectator.inject(UiModalService);
|
||||
|
||||
modalMock.open.and.returnValue({
|
||||
afterClosed$: of({} as UiModalResult<any>),
|
||||
} as any);
|
||||
});
|
||||
// modalMock.open.and.returnValue({
|
||||
// afterClosed$: of({} as UiModalResult<any>),
|
||||
// } as any);
|
||||
// });
|
||||
|
||||
it('should be created', () => {
|
||||
expect(httpErrorInterceptor).toBeTruthy();
|
||||
});
|
||||
// it('should be created', () => {
|
||||
// expect(httpErrorInterceptor).toBeTruthy();
|
||||
// });
|
||||
|
||||
describe('intercept', () => {
|
||||
it('should catch the error and call handleError', (done) => {
|
||||
const error = new HttpErrorResponse({
|
||||
status: 0,
|
||||
statusText: '',
|
||||
url: '',
|
||||
});
|
||||
// describe('intercept', () => {
|
||||
// it('should catch the error and call handleError', (done) => {
|
||||
// const error = new HttpErrorResponse({
|
||||
// status: 0,
|
||||
// statusText: '',
|
||||
// url: '',
|
||||
// });
|
||||
|
||||
const handleErrorSpy = spyOn(httpErrorInterceptor, 'handleError').and.callThrough();
|
||||
httpErrorInterceptor.intercept(null, { handle: () => throwError(error) }).subscribe({
|
||||
error: () => {
|
||||
expect(handleErrorSpy).toHaveBeenCalledWith(error);
|
||||
done();
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
// const handleErrorSpy = spyOn(httpErrorInterceptor, 'handleError').and.callThrough();
|
||||
// httpErrorInterceptor.intercept(null, { handle: () => throwError(error) }).subscribe({
|
||||
// error: () => {
|
||||
// expect(handleErrorSpy).toHaveBeenCalledWith(error);
|
||||
// done();
|
||||
// },
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
describe('handleError', () => {
|
||||
it('should call modal.open with offline message if status is 0', () => {
|
||||
const error = {
|
||||
error: {
|
||||
message: 'test',
|
||||
},
|
||||
status: 0,
|
||||
};
|
||||
httpErrorInterceptor.handleError(error as any);
|
||||
expect(modalMock.open).toHaveBeenCalledWith({
|
||||
content: UiMessageModalComponent,
|
||||
title: 'Sie sind offline, keine Verbindung zum Netzwerk',
|
||||
data: { message: 'Bereits geladene Inhalte werden angezeigt. Interaktionen sind aktuell nicht möglich.' },
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
// describe('handleError', () => {
|
||||
// it('should call modal.open with offline message if status is 0', () => {
|
||||
// const error = {
|
||||
// error: {
|
||||
// message: 'test',
|
||||
// },
|
||||
// status: 0,
|
||||
// };
|
||||
// httpErrorInterceptor.handleError(error as any);
|
||||
// expect(modalMock.open).toHaveBeenCalledWith({
|
||||
// content: UiMessageModalComponent,
|
||||
// title: 'Sie sind offline, keine Verbindung zum Netzwerk',
|
||||
// data: { message: 'Bereits geladene Inhalte werden angezeigt. Interaktionen sind aktuell nicht möglich.' },
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { inject, Injectable, Injector } from '@angular/core';
|
||||
import { HttpInterceptor, HttpEvent, HttpHandler, HttpRequest, HttpErrorResponse } from '@angular/common/http';
|
||||
import { NEVER, Observable, throwError } from 'rxjs';
|
||||
import { from, NEVER, Observable, throwError } from 'rxjs';
|
||||
import { UiMessageModalComponent, UiModalService } from '@ui/modal';
|
||||
import { catchError, filter, mergeMap, takeUntil, tap } from 'rxjs/operators';
|
||||
import { AuthService } from '@core/auth';
|
||||
import { AuthService, LoginStrategy } from '@core/auth';
|
||||
import { IsaLogProvider } from '../providers';
|
||||
import { LogLevel } from '@core/logger';
|
||||
import { injectOnline$ } from '../services/network-status.service';
|
||||
@@ -11,6 +11,7 @@ import { injectOnline$ } from '../services/network-status.service';
|
||||
@Injectable()
|
||||
export class HttpErrorInterceptor implements HttpInterceptor {
|
||||
readonly offline$ = injectOnline$().pipe(filter((online) => !online));
|
||||
readonly injector = inject(Injector);
|
||||
|
||||
constructor(
|
||||
private _modal: UiModalService,
|
||||
@@ -27,18 +28,9 @@ export class HttpErrorInterceptor implements HttpInterceptor {
|
||||
|
||||
handleError(error: HttpErrorResponse): Observable<any> {
|
||||
if (error.status === 401) {
|
||||
return this._modal
|
||||
.open({
|
||||
content: UiMessageModalComponent,
|
||||
title: 'Sie sind nicht mehr angemeldet',
|
||||
data: { message: 'Sie werden neu angemeldet' },
|
||||
})
|
||||
.afterClosed$.pipe(
|
||||
tap(() => {
|
||||
this._auth.login();
|
||||
}),
|
||||
mergeMap(() => NEVER),
|
||||
);
|
||||
const strategy = this.injector.get(LoginStrategy);
|
||||
|
||||
return from(strategy.login('Sie sind nicht mehr angemeldet')).pipe(mergeMap(() => NEVER));
|
||||
}
|
||||
|
||||
if (!error.url.endsWith('/isa/logging')) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Component, ChangeDetectionStrategy } from '@angular/core';
|
||||
selector: 'app-main',
|
||||
templateUrl: 'main.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: false,
|
||||
})
|
||||
export class MainComponent {
|
||||
constructor() {}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Platform, PlatformModule } from '@angular/cdk/platform';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { BranchSelectorComponent } from '@shared/components/branch-selector';
|
||||
import { BranchDTO } from '@swagger/checkout';
|
||||
import { BranchDTO } from '@generated/swagger/checkout-api';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
@@ -10,7 +10,6 @@ import { BehaviorSubject } from 'rxjs';
|
||||
templateUrl: 'preview.component.html',
|
||||
styleUrls: ['preview.component.css'],
|
||||
imports: [CommonModule, BranchSelectorComponent, PlatformModule],
|
||||
standalone: true,
|
||||
})
|
||||
export class PreviewComponent implements OnInit {
|
||||
selectedBranch$ = new BehaviorSubject<BranchDTO>({});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { LogLevel, LogProvider } from '@core/logger';
|
||||
import { UserStateService } from '@swagger/isa';
|
||||
import { UserStateService } from '@generated/swagger/isa-api';
|
||||
import { environment } from '../../environments/environment';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
|
||||
@@ -4,9 +4,8 @@ import { Observable } from 'rxjs';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ProcessIdResolver {
|
||||
constructor() {}
|
||||
|
||||
resolve(route: ActivatedRouteSnapshot): Observable<number> | Promise<number> | number {
|
||||
return route.params.processId;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,10 @@ import { ApplicationService } from '@core/application';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
export abstract class SectionResolver {
|
||||
constructor(protected section: 'customer' | 'branch', protected applicationService: ApplicationService) {}
|
||||
constructor(
|
||||
protected section: 'customer' | 'branch',
|
||||
protected applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
resolve(route: ActivatedRouteSnapshot): Observable<string> | Promise<string> | string {
|
||||
this.applicationService.setSection(this.section);
|
||||
|
||||
1
apps/isa-app/src/app/services/index.ts
Normal file
1
apps/isa-app/src/app/services/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './network-status.service';
|
||||
@@ -1,26 +1,32 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Logger, LogLevel } from '@core/logger';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { UserStateService } from '@swagger/isa';
|
||||
import { debounceTime, switchMap, takeUntil } from 'rxjs/operators';
|
||||
import { RootState } from './root.state';
|
||||
import packageInfo from 'packageJson';
|
||||
import { environment } from '../../environments/environment';
|
||||
import { Subject } from 'rxjs';
|
||||
import { AuthService } from '@core/auth';
|
||||
import { injectStorage, UserStorageProvider } from '@isa/core/storage';
|
||||
import { isEqual } from 'lodash';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class RootStateService {
|
||||
static LOCAL_STORAGE_KEY = 'ISA_APP_INITIALSTATE';
|
||||
|
||||
#storage = injectStorage(UserStorageProvider);
|
||||
|
||||
private _cancelSave = new Subject<void>();
|
||||
|
||||
constructor(
|
||||
private readonly _userStateService: UserStateService,
|
||||
private readonly _authService: AuthService,
|
||||
private _logger: Logger,
|
||||
private _store: Store,
|
||||
) {
|
||||
if (!environment.production) {
|
||||
console.log('Die UserState kann in der Konsole mit der Funktion "clearUserState()" geleert werden.');
|
||||
console.log(
|
||||
'Die UserState kann in der Konsole mit der Funktion "clearUserState()" geleert werden.',
|
||||
);
|
||||
}
|
||||
|
||||
window['clearUserState'] = () => {
|
||||
@@ -41,9 +47,17 @@ export class RootStateService {
|
||||
takeUntil(this._cancelSave),
|
||||
debounceTime(1000),
|
||||
switchMap((state) => {
|
||||
const raw = JSON.stringify({ ...state, version: packageInfo.version });
|
||||
RootStateService.SaveToLocalStorageRaw(raw);
|
||||
return this._userStateService.UserStateSetUserState({ content: raw });
|
||||
const data = {
|
||||
...state,
|
||||
version: packageInfo.version,
|
||||
sub: this._authService.getClaimByKey('sub'),
|
||||
};
|
||||
RootStateService.SaveToLocalStorageRaw(JSON.stringify(data));
|
||||
return this.#storage.set('state', {
|
||||
...state,
|
||||
version: packageInfo.version,
|
||||
sub: this._authService.getClaimByKey('sub'),
|
||||
});
|
||||
}),
|
||||
)
|
||||
.subscribe();
|
||||
@@ -54,16 +68,15 @@ export class RootStateService {
|
||||
*/
|
||||
async load(): Promise<boolean> {
|
||||
try {
|
||||
const res = await this._userStateService.UserStateGetUserState().toPromise();
|
||||
const res = await this.#storage.get('state');
|
||||
|
||||
const resContent = res?.result?.content ?? null;
|
||||
const storageContent = RootStateService.LoadFromLocalStorageRaw();
|
||||
|
||||
if (resContent) {
|
||||
RootStateService.SaveToLocalStorageRaw(res.result.content);
|
||||
if (res) {
|
||||
RootStateService.SaveToLocalStorageRaw(JSON.stringify(res));
|
||||
}
|
||||
|
||||
if (resContent !== storageContent) {
|
||||
if (!isEqual(res, storageContent)) {
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -75,7 +88,7 @@ export class RootStateService {
|
||||
async clear() {
|
||||
try {
|
||||
this._cancelSave.next();
|
||||
await this._userStateService.UserStateResetUserState().toPromise();
|
||||
await this.#storage.clear('state');
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
RootStateService.RemoveFromLocalStorage();
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
@@ -96,7 +109,12 @@ export class RootStateService {
|
||||
static LoadFromLocalStorage(): RootState {
|
||||
const raw = RootStateService.LoadFromLocalStorageRaw();
|
||||
if (raw) {
|
||||
return JSON.parse(raw);
|
||||
try {
|
||||
return JSON.parse(raw);
|
||||
} catch (error) {
|
||||
console.error('Error parsing local storage:', error);
|
||||
this.RemoveFromLocalStorage();
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -7,9 +7,14 @@ import { AuthService } from '@core/auth';
|
||||
templateUrl: 'token-login.component.html',
|
||||
styleUrls: ['token-login.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: false,
|
||||
})
|
||||
export class TokenLoginComponent implements OnInit {
|
||||
constructor(private _route: ActivatedRoute, private _authService: AuthService, private _router: Router) {}
|
||||
constructor(
|
||||
private _route: ActivatedRoute,
|
||||
private _authService: AuthService,
|
||||
private _router: Router,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
if (this._route.snapshot.params.token && !this._authService.isAuthenticated()) {
|
||||
|
||||
@@ -1,219 +1,222 @@
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-400-cyrillic-ext1.woff2') format('woff2');
|
||||
src: url("./Open_Sans-400-cyrillic-ext1.woff2") format("woff2");
|
||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-400-cyrillic2.woff2') format('woff2');
|
||||
src: url("./Open_Sans-400-cyrillic2.woff2") format("woff2");
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek-ext */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-400-greek-ext3.woff2') format('woff2');
|
||||
src: url("./Open_Sans-400-greek-ext3.woff2") format("woff2");
|
||||
unicode-range: U+1F00-1FFF;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-400-greek4.woff2') format('woff2');
|
||||
src: url("./Open_Sans-400-greek4.woff2") format("woff2");
|
||||
unicode-range: U+0370-03FF;
|
||||
}
|
||||
/* hebrew */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-400-hebrew5.woff2') format('woff2');
|
||||
src: url("./Open_Sans-400-hebrew5.woff2") format("woff2");
|
||||
unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-400-vietnamese6.woff2') format('woff2');
|
||||
src: url("./Open_Sans-400-vietnamese6.woff2") format("woff2");
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-400-latin-ext7.woff2') format('woff2');
|
||||
src: url("./Open_Sans-400-latin-ext7.woff2") format("woff2");
|
||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-400-latin8.woff2') format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
|
||||
U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
src: url("./Open_Sans-400-latin8.woff2") format("woff2");
|
||||
unicode-range:
|
||||
U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
|
||||
U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-600-cyrillic-ext9.woff2') format('woff2');
|
||||
src: url("./Open_Sans-600-cyrillic-ext9.woff2") format("woff2");
|
||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-600-cyrillic10.woff2') format('woff2');
|
||||
src: url("./Open_Sans-600-cyrillic10.woff2") format("woff2");
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek-ext */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-600-greek-ext11.woff2') format('woff2');
|
||||
src: url("./Open_Sans-600-greek-ext11.woff2") format("woff2");
|
||||
unicode-range: U+1F00-1FFF;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-600-greek12.woff2') format('woff2');
|
||||
src: url("./Open_Sans-600-greek12.woff2") format("woff2");
|
||||
unicode-range: U+0370-03FF;
|
||||
}
|
||||
/* hebrew */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-600-hebrew13.woff2') format('woff2');
|
||||
src: url("./Open_Sans-600-hebrew13.woff2") format("woff2");
|
||||
unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-600-vietnamese14.woff2') format('woff2');
|
||||
src: url("./Open_Sans-600-vietnamese14.woff2") format("woff2");
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-600-latin-ext15.woff2') format('woff2');
|
||||
src: url("./Open_Sans-600-latin-ext15.woff2") format("woff2");
|
||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-600-latin16.woff2') format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
|
||||
U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
src: url("./Open_Sans-600-latin16.woff2") format("woff2");
|
||||
unicode-range:
|
||||
U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
|
||||
U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-700-cyrillic-ext17.woff2') format('woff2');
|
||||
src: url("./Open_Sans-700-cyrillic-ext17.woff2") format("woff2");
|
||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-700-cyrillic18.woff2') format('woff2');
|
||||
src: url("./Open_Sans-700-cyrillic18.woff2") format("woff2");
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek-ext */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-700-greek-ext19.woff2') format('woff2');
|
||||
src: url("./Open_Sans-700-greek-ext19.woff2") format("woff2");
|
||||
unicode-range: U+1F00-1FFF;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-700-greek20.woff2') format('woff2');
|
||||
src: url("./Open_Sans-700-greek20.woff2") format("woff2");
|
||||
unicode-range: U+0370-03FF;
|
||||
}
|
||||
/* hebrew */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-700-hebrew21.woff2') format('woff2');
|
||||
src: url("./Open_Sans-700-hebrew21.woff2") format("woff2");
|
||||
unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-700-vietnamese22.woff2') format('woff2');
|
||||
src: url("./Open_Sans-700-vietnamese22.woff2") format("woff2");
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-700-latin-ext23.woff2') format('woff2');
|
||||
src: url("./Open_Sans-700-latin-ext23.woff2") format("woff2");
|
||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-stretch: normal;
|
||||
src: url('./Open_Sans-700-latin24.woff2') format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
|
||||
U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
src: url("./Open_Sans-700-latin24.woff2") format("woff2");
|
||||
unicode-range:
|
||||
U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
|
||||
U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Directive, HostListener, Input } from '@angular/core';
|
||||
import { Directive, HostListener, inject, Input } from '@angular/core';
|
||||
import { ProductCatalogNavigationService } from '@shared/services/navigation';
|
||||
|
||||
@Directive({
|
||||
@@ -8,7 +8,7 @@ import { ProductCatalogNavigationService } from '@shared/services/navigation';
|
||||
export class NavigateOnClickDirective {
|
||||
@Input('productImageNavigation') ean: string;
|
||||
|
||||
constructor(private readonly _productCatalogNavigation: ProductCatalogNavigationService) {}
|
||||
private readonly _productCatalogNavigation = inject(ProductCatalogNavigationService);
|
||||
|
||||
@HostListener('click', ['$event'])
|
||||
async onClick(event: MouseEvent) {
|
||||
|
||||
@@ -1,86 +1,85 @@
|
||||
{
|
||||
"title": "ISA - Feature",
|
||||
"silentRefresh": {
|
||||
"interval": 300000
|
||||
},
|
||||
"@cdn/product-image": {
|
||||
"url": "https://produktbilder.paragon-data.net"
|
||||
},
|
||||
"@core/auth": {
|
||||
"issuer": "https://sso-test.paragon-data.de",
|
||||
"clientId": "hug-isa",
|
||||
"responseType": "id_token token",
|
||||
"oidc": true,
|
||||
"scope": "openid profile cmf_user isa-isa-webapi isa-checkout-webapi isa-cat-webapi isa-ava-webapi isa-crm-webapi isa-review-webapi isa-kpi-webapi isa-oms-webapi isa-nbo-webapi isa-print-webapi eis-service isa-inv-webapi isa-wws-webapi"
|
||||
},
|
||||
"@core/logger": {
|
||||
"logLevel": "debug"
|
||||
},
|
||||
"@domain/checkout": {
|
||||
"olaExpiration": "5m"
|
||||
},
|
||||
"@swagger/isa": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/isa/v1"
|
||||
},
|
||||
"@swagger/cat": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/catsearch/v6"
|
||||
},
|
||||
"@swagger/av": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/ava/v6"
|
||||
},
|
||||
"@swagger/checkout": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/checkout/v6"
|
||||
},
|
||||
"@swagger/crm": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/crm/v6"
|
||||
},
|
||||
"@swagger/oms": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/oms/v6"
|
||||
},
|
||||
"@swagger/print": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/print/v1"
|
||||
},
|
||||
"@swagger/eis": {
|
||||
"rootUrl": "https://filialinformationsystem-test.paragon-systems.de/eiswebapi/v1"
|
||||
},
|
||||
"@swagger/remi": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/inv/v6"
|
||||
},
|
||||
"@swagger/wws": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/wws/v1"
|
||||
},
|
||||
"hubs": {
|
||||
"notifications": {
|
||||
"url": "https://isa-test.paragon-data.net/isa/v1/rt",
|
||||
"enableAutomaticReconnect": false,
|
||||
"httpOptions": {
|
||||
"transport": 1,
|
||||
"logMessageContent": true,
|
||||
"skipNegotiation": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"process": {
|
||||
"ids": {
|
||||
"goodsOut": 1000,
|
||||
"goodsIn": 2000,
|
||||
"taskCalendar": 3000,
|
||||
"remission": 4000,
|
||||
"packageInspection": 5000,
|
||||
"assortment": 6000,
|
||||
"pickupShelf": 7000
|
||||
}
|
||||
},
|
||||
"checkForUpdates": 3600000,
|
||||
"licence": {
|
||||
"scandit": "Ac2kvx5ZOzjvFl/LuAd6wds3C30YJ4g8Cm6PX4sgUnKPePVMuH+rFQIyVNn1YdS3myORojEOBsIZWhMw2nRUGBtOnQ5FO+cRHgQu0pkP+VG6OYvt8ETUTn8Aa2f9bmfqclO3LI8WN8psWr+adkZEtqNTvCgyDLZaICh8S7RfmwJVVWaOPX4LDagGhLDPS2YQdg+ibpR0l0ZlX2h/3GttofE64HOlBN3QtDB8yihHJNgVcUVy2UQVS+BXOyvIfZEFbFgPYVt5HZ0aQgcISlYVAmJvRsHyeKYRUnIi3ZN73EQmHzWcOV4/HWVoTs1MTW0mxV074vNwqExYW9LYmz9zgLUD7FMnKMFClkzRBHRN1CC7brosCnFkZWQp3CV4Ua48Fn9GW0Zpn/4MIZgzSU26inl5ZnT3dCc2+3BH3Us1uugTUrOPwFuwsPpr4NZYXWJMOmcm4kBBVJd0Uwk28GyZM7x1hXADcQgcc23+gDtbbUZWVmr3TE7GBcV3j+XUeOk8nHZw3DsYJ46MT2sSfks3QXRl4tBkBad6M+UxW4tb2IQC/4K9IXKhDN8VYXpzrrRHJNvOiH5+NrixthDZHHd/MGNuBDrJFOuXq8L7O6PxBoVZ0NPXmCO5vKyYdhBz5gJ5u3vNkSke7p+cDcvFicsVyNWRaaoFL0UN9gxFVMY8hkJKBZyGxZL2LEDXD44PxPsDnygpDC1Jyc7pkhEA0fKSc9aXZb1HDpwe1hqyyRVBtHkgPiN78GmJImbaUlj8XsK3yVyAjs2XvPR0/3ASHS53ViwzWKL3Oi8I515IJDtDhlvrkeh7MrWMaEu9k6ZQXJi1uJsh3JGfyS+yDlPjePVdsVqnZ4uw9pKMXvjlJeNcIiGM2Cf5S89nk2Qe/56MrKB9Frm6Q5wQHai8TNdCZYBi67dmAX8KHPXvEU4K6KyyW89YGcabZQ3eOJDr4oqW9ZcYPBttREdH3WI/HxvpEq6bqoDhT9AxpIWEMVb6y/DcDHSEresepibug4qOr9xOPq0yk2uiWYhPubFnCk7thQCXOGv9crWnQoOrt9c1qoaWXM4YmKqfcaQ67Tn+uFQmYTZyqw4jlJU4GgKe5/GNCVQM5aNUg1J0Px1NlFCS+rrIDyMQp0byFcgTd/E9sA5d1+YZKHKmJiQwEAz6oU9yyoUlxntSI42GHB/UttPc7Hj14V5+oJ+Yz+CZodmkXFg57Vx4NuxveNtO"
|
||||
},
|
||||
"gender": {
|
||||
"0": "Keine Anrede",
|
||||
"1": "Enby",
|
||||
"2": "Herr",
|
||||
"4": "Frau"
|
||||
},
|
||||
"@shared/icon": "/assets/icons.json"
|
||||
|
||||
}
|
||||
"title": "ISA - Feature",
|
||||
"silentRefresh": {
|
||||
"interval": 300000
|
||||
},
|
||||
"@cdn/product-image": {
|
||||
"url": "https://produktbilder.paragon-data.net"
|
||||
},
|
||||
"@core/auth": {
|
||||
"issuer": "https://sso-test.paragon-data.de",
|
||||
"clientId": "hug-isa",
|
||||
"responseType": "id_token token",
|
||||
"oidc": true,
|
||||
"scope": "openid profile cmf_user isa-isa-webapi isa-checkout-webapi isa-cat-webapi isa-ava-webapi isa-crm-webapi isa-review-webapi isa-kpi-webapi isa-oms-webapi isa-nbo-webapi isa-print-webapi eis-service isa-inv-webapi isa-wws-webapi"
|
||||
},
|
||||
"@core/logger": {
|
||||
"logLevel": "debug"
|
||||
},
|
||||
"@domain/checkout": {
|
||||
"olaExpiration": "5m"
|
||||
},
|
||||
"@swagger/isa": {
|
||||
"rootUrl": "https://isa-feature.paragon-data.net/isa/v1"
|
||||
},
|
||||
"@swagger/cat": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/catsearch/v6"
|
||||
},
|
||||
"@swagger/av": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/ava/v6"
|
||||
},
|
||||
"@swagger/checkout": {
|
||||
"rootUrl": "https://isa-feature.paragon-data.net/checkout/v6"
|
||||
},
|
||||
"@swagger/crm": {
|
||||
"rootUrl": "https://isa-feature.paragon-data.net/crm/v6"
|
||||
},
|
||||
"@swagger/oms": {
|
||||
"rootUrl": "https://isa-feature.paragon-data.net/oms/v6"
|
||||
},
|
||||
"@swagger/print": {
|
||||
"rootUrl": "https://isa-feature.paragon-data.net/print/v1"
|
||||
},
|
||||
"@swagger/eis": {
|
||||
"rootUrl": "https://filialinformationsystem-test.paragon-systems.de/eiswebapi/v1"
|
||||
},
|
||||
"@swagger/remi": {
|
||||
"rootUrl": "https://isa-feature.paragon-data.net/inv/v6"
|
||||
},
|
||||
"@swagger/wws": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/wws/v1"
|
||||
},
|
||||
"hubs": {
|
||||
"notifications": {
|
||||
"url": "https://isa-feature.paragon-data.net/isa/v1/rt",
|
||||
"enableAutomaticReconnect": false,
|
||||
"httpOptions": {
|
||||
"transport": 1,
|
||||
"logMessageContent": true,
|
||||
"skipNegotiation": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"process": {
|
||||
"ids": {
|
||||
"goodsOut": 1000,
|
||||
"goodsIn": 2000,
|
||||
"taskCalendar": 3000,
|
||||
"remission": 4000,
|
||||
"packageInspection": 5000,
|
||||
"assortment": 6000,
|
||||
"pickupShelf": 7000
|
||||
}
|
||||
},
|
||||
"checkForUpdates": 3600000,
|
||||
"licence": {
|
||||
"scandit": "Ae8F2Wx2RMq5Lvn7UUAlWzVFZTt2+ubMAF8XtDpmPlNkBeG/LWs1M7AbgDW0LQqYLnszClEENaEHS56/6Ts2vrJ1Ux03CXUjK3jUvZpF5OchXR1CpnmpepJ6WxPCd7LMVHUGG1BbwPLDTFjP3y8uT0caTSmmGrYQWAs4CZcEF+ZBabP0z7vfm+hCZF/ebj9qqCJZcW8nH/n19hohshllzYBjFXjh87P2lIh1s6yZS3OaQWWXo/o0AKdxx7T6CVyR0/G5zq6uYJWf6rs3euUBEhpzOZHbHZK86Lvy2AVBEyVkkcttlDW1J2fA4l1W1JV/Xibz8AQV6kG482EpGF42KEoK48paZgX3e1AQsqUtmqzw294dcP4zMVstnw5/WrwKKi/5E/nOOJT2txYP1ZufIjPrwNFsqTlv7xCQlHjMzFGYwT816yD5qLRLbwOtjrkUPXNZLZ06T4upvWwJDmm8XgdeoDqMjHdcO4lwji1bl9EiIYJ/2qnsk9yZ2FqSaHzn4cbiL0f5u2HFlNAP0GUujGRlthGhHi6o4dFU+WAxKsFMKVt+SfoQUazNKHFVQgiAklTIZxIc/HUVzRvOLMxf+wFDerraBtcqGJg+g/5mrWYqeDBGhCBHtKiYf6244IJ4afzNTiH1/30SJcRzXwbEa3A7q1fJTx9/nLTOfVPrJKBQs7f/OQs2dA7LDCel8mzXdbjvsNQaeU5+iCIAq6zbTNKy1xT8wwj+VZrQmtNJs+qeznD+u29nCM24h8xCmRpvNPo4/Mww/lrTNrrNwLBSn1pMIwsH7yS9hH0v0oNAM3A6bVtk1D9qEkbyw+xZa+MZGpMP0D0CdcsqHalPcm5r/Ik="
|
||||
},
|
||||
"gender": {
|
||||
"0": "Keine Anrede",
|
||||
"1": "Enby",
|
||||
"2": "Herr",
|
||||
"4": "Frau"
|
||||
},
|
||||
"@shared/icon": "/assets/icons.json"
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
},
|
||||
"@domain/checkout": {
|
||||
"olaExpiration": "5m"
|
||||
},
|
||||
},
|
||||
"@swagger/isa": {
|
||||
"rootUrl": "https://isa-integration.paragon-data.net/isa/v1"
|
||||
},
|
||||
@@ -72,7 +72,7 @@
|
||||
},
|
||||
"checkForUpdates": 900000,
|
||||
"licence": {
|
||||
"scandit": "Ac2kvx5ZOzjvFl/LuAd6wds3C30YJ4g8Cm6PX4sgUnKPePVMuH+rFQIyVNn1YdS3myORojEOBsIZWhMw2nRUGBtOnQ5FO+cRHgQu0pkP+VG6OYvt8ETUTn8Aa2f9bmfqclO3LI8WN8psWr+adkZEtqNTvCgyDLZaICh8S7RfmwJVVWaOPX4LDagGhLDPS2YQdg+ibpR0l0ZlX2h/3GttofE64HOlBN3QtDB8yihHJNgVcUVy2UQVS+BXOyvIfZEFbFgPYVt5HZ0aQgcISlYVAmJvRsHyeKYRUnIi3ZN73EQmHzWcOV4/HWVoTs1MTW0mxV074vNwqExYW9LYmz9zgLUD7FMnKMFClkzRBHRN1CC7brosCnFkZWQp3CV4Ua48Fn9GW0Zpn/4MIZgzSU26inl5ZnT3dCc2+3BH3Us1uugTUrOPwFuwsPpr4NZYXWJMOmcm4kBBVJd0Uwk28GyZM7x1hXADcQgcc23+gDtbbUZWVmr3TE7GBcV3j+XUeOk8nHZw3DsYJ46MT2sSfks3QXRl4tBkBad6M+UxW4tb2IQC/4K9IXKhDN8VYXpzrrRHJNvOiH5+NrixthDZHHd/MGNuBDrJFOuXq8L7O6PxBoVZ0NPXmCO5vKyYdhBz5gJ5u3vNkSke7p+cDcvFicsVyNWRaaoFL0UN9gxFVMY8hkJKBZyGxZL2LEDXD44PxPsDnygpDC1Jyc7pkhEA0fKSc9aXZb1HDpwe1hqyyRVBtHkgPiN78GmJImbaUlj8XsK3yVyAjs2XvPR0/3ASHS53ViwzWKL3Oi8I515IJDtDhlvrkeh7MrWMaEu9k6ZQXJi1uJsh3JGfyS+yDlPjePVdsVqnZ4uw9pKMXvjlJeNcIiGM2Cf5S89nk2Qe/56MrKB9Frm6Q5wQHai8TNdCZYBi67dmAX8KHPXvEU4K6KyyW89YGcabZQ3eOJDr4oqW9ZcYPBttREdH3WI/HxvpEq6bqoDhT9AxpIWEMVb6y/DcDHSEresepibug4qOr9xOPq0yk2uiWYhPubFnCk7thQCXOGv9crWnQoOrt9c1qoaWXM4YmKqfcaQ67Tn+uFQmYTZyqw4jlJU4GgKe5/GNCVQM5aNUg1J0Px1NlFCS+rrIDyMQp0byFcgTd/E9sA5d1+YZKHKmJiQwEAz6oU9yyoUlxntSI42GHB/UttPc7Hj14V5+oJ+Yz+CZodmkXFg57Vx4NuxveNtO"
|
||||
"scandit": "ASq1ZCbuDs0nJ4cPGkFOSkQEBHSL/kuljVAq2ttwz2Q5CEwULWAlasJIkjsIe/nptzNx1IBSxwDPWh0gXmvF08BRBDTzDUELdX6q02N/HUddSHE4A1dMXoFg+I8of+iZQijQIogxmP5RfSpj6ixzD2cGV0w+BG6o9xRXG4lEv9vNAOC3+emfcuVj2Whmfbuzao4HcWweVSz4HJh8dcbxTPF10MH8qR4kkV7fNWIF+PaYww69relfuvrkgdbWPcLs4Xb7WW4AISX9pTmJmSuv2LvD9gMoPNlmhdTWi+qFcmgZiPRDb1I0Bldo7jKLdboylEXkVQVWF1D2fv3iO5BrijG+n52XQd3ew49/1ssJi6dWhxiZQMlN+mz7cfSPmGzJc0eqaf52tEA8PkIupXjly/6dckSVcqTsex+wHcQuTinyW2bu9/YY3ZTMCp5du+lFZBD+AQSsq7EALzzithpijNG3jQka/8yRSHPBP6JtfobMdbv7SlAESslnN5R5lKJms4HnSm4CwxBAX2sUrhQeuit74/5pwe8qI+CaEGzjKYfmcRhFXd+Kz/ySV3HyrVuieH6+6ytBjGh3EkwGvQ8Ovu4KsruWAyAjHwRyBdrFIRYyLWdou77VH8gSLwHi69QsMGshcnYaREpqDEb5LLR9Ok7jP5IjMyPzX4USS327G9f4I8ujTaCKXQ9a384yV/wP9IeSuJld4dgdGy80rDP2sWZ+NJ65cNWpAfi/Nmbm6ucjICoUHILtchyx/w/YNYUzfCWFjUWHn83TzG+31f3dkjWoI3XpCOg5RKREs55htHSAyZtYhYiQr1FxDVFNEQI2MrDR0fBt2qOeZB08yA=="
|
||||
},
|
||||
"gender": {
|
||||
"0": "Keine Anrede",
|
||||
@@ -81,4 +81,4 @@
|
||||
"4": "Frau"
|
||||
},
|
||||
"@shared/icon": "/assets/icons.json"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,86 +1,87 @@
|
||||
{
|
||||
"title": "ISA - Local",
|
||||
"silentRefresh": {
|
||||
"interval": 300000
|
||||
},
|
||||
"debug": true,
|
||||
"@cdn/product-image": {
|
||||
"url": "https://produktbilder.paragon-data.net"
|
||||
},
|
||||
"@core/auth": {
|
||||
"issuer": "https://sso-test.paragon-data.de",
|
||||
"clientId": "isa-client",
|
||||
"responseType": "code",
|
||||
"scope": "openid profile cmf_user isa-isa-webapi isa-checkout-webapi isa-cat-webapi isa-ava-webapi isa-crm-webapi isa-review-webapi isa-kpi-webapi isa-oms-webapi isa-nbo-webapi isa-print-webapi eis-service isa-inv-webapi isa-wws-webapi",
|
||||
"showDebugInformation": true
|
||||
},
|
||||
"@core/logger": {
|
||||
"logLevel": "debug"
|
||||
},
|
||||
"@swagger/isa": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/isa/v1"
|
||||
},
|
||||
"@swagger/cat": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/catsearch/v6"
|
||||
},
|
||||
"@swagger/av": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/ava/v6"
|
||||
},
|
||||
"@swagger/checkout": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/checkout/v6"
|
||||
},
|
||||
"@swagger/crm": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/crm/v6"
|
||||
},
|
||||
"@swagger/oms": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/oms/v6"
|
||||
},
|
||||
"@swagger/print": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/print/v1"
|
||||
},
|
||||
"@swagger/eis": {
|
||||
"rootUrl": "https://filialinformationsystem-test.paragon-systems.de/eiswebapi/v1"
|
||||
},
|
||||
"@swagger/remi": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/inv/v6"
|
||||
},
|
||||
"@swagger/wws": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/wws/v1"
|
||||
},
|
||||
"@domain/checkout": {
|
||||
"olaExpiration": "5m"
|
||||
},
|
||||
"hubs": {
|
||||
"notifications": {
|
||||
"url": "https://isa-test.paragon-data.net/isa/v1/rt",
|
||||
"enableAutomaticReconnect": false,
|
||||
"httpOptions": {
|
||||
"transport": 1,
|
||||
"logMessageContent": true,
|
||||
"skipNegotiation": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"process": {
|
||||
"ids": {
|
||||
"goodsOut": 1000,
|
||||
"goodsIn": 2000,
|
||||
"taskCalendar": 3000,
|
||||
"remission": 4000,
|
||||
"packageInspection": 5000,
|
||||
"assortment": 6000,
|
||||
"pickupShelf": 7000
|
||||
}
|
||||
},
|
||||
"checkForUpdates": 3600000,
|
||||
"licence": {
|
||||
"scandit": "Ac2kvx5ZOzjvFl/LuAd6wds3C30YJ4g8Cm6PX4sgUnKPePVMuH+rFQIyVNn1YdS3myORojEOBsIZWhMw2nRUGBtOnQ5FO+cRHgQu0pkP+VG6OYvt8ETUTn8Aa2f9bmfqclO3LI8WN8psWr+adkZEtqNTvCgyDLZaICh8S7RfmwJVVWaOPX4LDagGhLDPS2YQdg+ibpR0l0ZlX2h/3GttofE64HOlBN3QtDB8yihHJNgVcUVy2UQVS+BXOyvIfZEFbFgPYVt5HZ0aQgcISlYVAmJvRsHyeKYRUnIi3ZN73EQmHzWcOV4/HWVoTs1MTW0mxV074vNwqExYW9LYmz9zgLUD7FMnKMFClkzRBHRN1CC7brosCnFkZWQp3CV4Ua48Fn9GW0Zpn/4MIZgzSU26inl5ZnT3dCc2+3BH3Us1uugTUrOPwFuwsPpr4NZYXWJMOmcm4kBBVJd0Uwk28GyZM7x1hXADcQgcc23+gDtbbUZWVmr3TE7GBcV3j+XUeOk8nHZw3DsYJ46MT2sSfks3QXRl4tBkBad6M+UxW4tb2IQC/4K9IXKhDN8VYXpzrrRHJNvOiH5+NrixthDZHHd/MGNuBDrJFOuXq8L7O6PxBoVZ0NPXmCO5vKyYdhBz5gJ5u3vNkSke7p+cDcvFicsVyNWRaaoFL0UN9gxFVMY8hkJKBZyGxZL2LEDXD44PxPsDnygpDC1Jyc7pkhEA0fKSc9aXZb1HDpwe1hqyyRVBtHkgPiN78GmJImbaUlj8XsK3yVyAjs2XvPR0/3ASHS53ViwzWKL3Oi8I515IJDtDhlvrkeh7MrWMaEu9k6ZQXJi1uJsh3JGfyS+yDlPjePVdsVqnZ4uw9pKMXvjlJeNcIiGM2Cf5S89nk2Qe/56MrKB9Frm6Q5wQHai8TNdCZYBi67dmAX8KHPXvEU4K6KyyW89YGcabZQ3eOJDr4oqW9ZcYPBttREdH3WI/HxvpEq6bqoDhT9AxpIWEMVb6y/DcDHSEresepibug4qOr9xOPq0yk2uiWYhPubFnCk7thQCXOGv9crWnQoOrt9c1qoaWXM4YmKqfcaQ67Tn+uFQmYTZyqw4jlJU4GgKe5/GNCVQM5aNUg1J0Px1NlFCS+rrIDyMQp0byFcgTd/E9sA5d1+YZKHKmJiQwEAz6oU9yyoUlxntSI42GHB/UttPc7Hj14V5+oJ+Yz+CZodmkXFg57Vx4NuxveNtO"
|
||||
},
|
||||
"gender": {
|
||||
"0": "Keine Anrede",
|
||||
"1": "Enby",
|
||||
"2": "Herr",
|
||||
"4": "Frau"
|
||||
},
|
||||
"@shared/icon": "/assets/icons.json"
|
||||
}
|
||||
"title": "ISA - Local",
|
||||
"silentRefresh": {
|
||||
"interval": 300000
|
||||
},
|
||||
"debug": true,
|
||||
"dev-scanner": true,
|
||||
"@cdn/product-image": {
|
||||
"url": "https://produktbilder.paragon-data.net"
|
||||
},
|
||||
"@core/auth": {
|
||||
"issuer": "https://sso-test.paragon-data.de",
|
||||
"clientId": "isa-client",
|
||||
"responseType": "code",
|
||||
"scope": "openid profile cmf_user isa-isa-webapi isa-checkout-webapi isa-cat-webapi isa-ava-webapi isa-crm-webapi isa-review-webapi isa-kpi-webapi isa-oms-webapi isa-nbo-webapi isa-print-webapi eis-service isa-inv-webapi isa-wws-webapi",
|
||||
"showDebugInformation": true
|
||||
},
|
||||
"@core/logger": {
|
||||
"logLevel": "debug"
|
||||
},
|
||||
"@swagger/isa": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/isa/v1"
|
||||
},
|
||||
"@swagger/cat": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/catsearch/v6"
|
||||
},
|
||||
"@swagger/av": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/ava/v6"
|
||||
},
|
||||
"@swagger/checkout": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/checkout/v6"
|
||||
},
|
||||
"@swagger/crm": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/crm/v6"
|
||||
},
|
||||
"@swagger/oms": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/oms/v6"
|
||||
},
|
||||
"@swagger/print": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/print/v1"
|
||||
},
|
||||
"@swagger/eis": {
|
||||
"rootUrl": "https://filialinformationsystem-test.paragon-systems.de/eiswebapi/v1"
|
||||
},
|
||||
"@swagger/remi": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/inv/v6"
|
||||
},
|
||||
"@swagger/wws": {
|
||||
"rootUrl": "https://isa-test.paragon-data.net/wws/v1"
|
||||
},
|
||||
"@domain/checkout": {
|
||||
"olaExpiration": "5m"
|
||||
},
|
||||
"hubs": {
|
||||
"notifications": {
|
||||
"url": "https://isa-test.paragon-data.net/isa/v1/rt",
|
||||
"enableAutomaticReconnect": false,
|
||||
"httpOptions": {
|
||||
"transport": 1,
|
||||
"logMessageContent": true,
|
||||
"skipNegotiation": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"process": {
|
||||
"ids": {
|
||||
"goodsOut": 1000,
|
||||
"goodsIn": 2000,
|
||||
"taskCalendar": 3000,
|
||||
"remission": 4000,
|
||||
"packageInspection": 5000,
|
||||
"assortment": 6000,
|
||||
"pickupShelf": 7000
|
||||
}
|
||||
},
|
||||
"checkForUpdates": 3600000,
|
||||
"licence": {
|
||||
"scandit": "Ae8F2Wx2RMq5Lvn7UUAlWzVFZTt2+ubMAF8XtDpmPlNkBeG/LWs1M7AbgDW0LQqYLnszClEENaEHS56/6Ts2vrJ1Ux03CXUjK3jUvZpF5OchXR1CpnmpepJ6WxPCd7LMVHUGG1BbwPLDTFjP3y8uT0caTSmmGrYQWAs4CZcEF+ZBabP0z7vfm+hCZF/ebj9qqCJZcW8nH/n19hohshllzYBjFXjh87P2lIh1s6yZS3OaQWWXo/o0AKdxx7T6CVyR0/G5zq6uYJWf6rs3euUBEhpzOZHbHZK86Lvy2AVBEyVkkcttlDW1J2fA4l1W1JV/Xibz8AQV6kG482EpGF42KEoK48paZgX3e1AQsqUtmqzw294dcP4zMVstnw5/WrwKKi/5E/nOOJT2txYP1ZufIjPrwNFsqTlv7xCQlHjMzFGYwT816yD5qLRLbwOtjrkUPXNZLZ06T4upvWwJDmm8XgdeoDqMjHdcO4lwji1bl9EiIYJ/2qnsk9yZ2FqSaHzn4cbiL0f5u2HFlNAP0GUujGRlthGhHi6o4dFU+WAxKsFMKVt+SfoQUazNKHFVQgiAklTIZxIc/HUVzRvOLMxf+wFDerraBtcqGJg+g/5mrWYqeDBGhCBHtKiYf6244IJ4afzNTiH1/30SJcRzXwbEa3A7q1fJTx9/nLTOfVPrJKBQs7f/OQs2dA7LDCel8mzXdbjvsNQaeU5+iCIAq6zbTNKy1xT8wwj+VZrQmtNJs+qeznD+u29nCM24h8xCmRpvNPo4/Mww/lrTNrrNwLBSn1pMIwsH7yS9hH0v0oNAM3A6bVtk1D9qEkbyw+xZa+MZGpMP0D0CdcsqHalPcm5r/Ik="
|
||||
},
|
||||
"gender": {
|
||||
"0": "Keine Anrede",
|
||||
"1": "Enby",
|
||||
"2": "Herr",
|
||||
"4": "Frau"
|
||||
},
|
||||
"@shared/icon": "/assets/icons.json"
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
},
|
||||
"checkForUpdates": 3600000,
|
||||
"licence": {
|
||||
"scandit": "AZ70hgtZLmFWHbYP+BDq8VAEgAxmNGYcPU8YpOc3DryEXj4zMzYQFrQuUm0YfzKaR2xbfjsImjXJN7C/TE1CYXsv3DeqIzgDRA/kII4LzqoICWm9mnwejER1kMu1Vf+1NWbwUuYJjsQVQXYkwkWgnv53obevBZtjpgZqIzlStufIU+sPNEWSd9BlrLmiSEu6nXC5lbstyPJVaqihsFoBPNJ0Q+IgJUjqaxhTf6hGtNB3Rqcpv0ZT349NdK9mQ+9lAQYCwXdmYbELdlbZVSja0aJQlkf0TaAjixDbNcR32/VMIw98F2YxVRVWPnADUaJ9Bn8oa7NkOJIUfB7VAg1KtUl8IIwSXvRk436UtPZGxg+PQM7UXX/TgiBuqCQWdUChoH/QAoY2fyKRKgXJHnGdt+pBRQ2OYs7TZWCJLZsLKgnHV+eWh3Y3EB1hN9cmcszdnmYiyD1gCY8pSETFbWV01nVPvIuUTc+jMipv3NN81VQDS5/eU1VJNpRuDiufdBKJv0jjHQk+hTdqe+2GSmMD24ZG8FQXJZZPBCodWR1A81T8toCaIAGHnOfZeO7nxZu9Uo+6ohrVxc5F4szSizra+M3zfuFnm5FGgxCKt5uibLYgRyNcmR8/9vqTfMZgalTklbKHEFw1i+xOwrFrqRMh7FoovDRoI3QuaHLpV+ZUpZo3zTOQofdXPthKAmSLc11cjn509oTnnXUBBoBn/hErrwC/v8dZep1YEKM3wjfuIFsHRrsECswqNjwN/yOZCirm2VvFJEPMuKIwy+8jdNGncm8v4R9Br3c+wYJ8696L7Dg0iFShoyoP4OqIvBNY+dYyy935yGkIF2KI6l01xQZcWoHSVKPd6/78Iwy4lTKhtOqtu7ETJqOE53gQpR9jaAY0RiBB1SLm+Jbwt3ipSJiCDgKmkVmk5AU9HC0XYR/erjg13HF4hIcpLPW1ZWMKSxTqZ8z8FMJilInBgfcBwvjNE5seWvdFKltvlItnGhSh7BLUZ5UInDhl00NJBE2PdstDvRvQjLKvYUoFly3jONVsUfuQpzrcjT0g6gEgL8ZtlmaF11owcCvqhNDxWuTAJTX/xXf6WehxEB0qy3xCdxahbuneS3DPI0z2kAQwrx19i5r+RKQ8bWDaQ/OGY47sLPJgDgijEz16CvAMBSN0PvOso6FstsT/ynR3LLTPcY0QDw21Dv3wNHNa9HbanJcb3/MuhZGlrKp7"
|
||||
"scandit": "ATSVF4WBEUdWFabwSBws+xhCeCSCzgKZVEUjDXt0v6EpJHyN7lNmjMNmg8S+ADBh6h/Wn6Vl1b8TDhw3Fl1ZdkFoQ88zZUgagRY9vKpAjzimETtcVmzAA05W498GYgSr42+q4P9dkGO1RPdcOXqAgZZpNlsaQnyP1WjOMvgRRouwBxnoVCwkir8//kLxJaHPJKSYQNcTdRNMgqNPq/vUwdYVrzg26ltn7eC5imeXyYuQH3u2L4TVuRjr3SDVqsv7lnybh3ijg3dLoI93atUBuxbmzvoWzyb2mxrchJ9DaxrBy0igV2qFzzF1R6QvlNTyvN9HyUvZ0/sPS1DqOoql9bqG7ibyGOdRa2/vfIDTLbVEIaym8yQzErBBqthjviCub2pYXGX+ai9xXufuqRDyX29uCafxSv6sQsnVcEnuLEmP6gdmGBMVvH/WEZHnGn6bQpfWwFIGRZZKM+SxTdToJanj3jxNF/pO445/YZWJBDRT5nP55gESsrwiTXbb+i9lY4Hx7srEQJR07lJWASfKGX6IJtUaIstl7KnO6VI72XI2Zo01SAQAOw7m5+70LgYN1woYoAcziCSFyuIfJavGF0zd1cAu95Cwo0E8+y/YcAO3jwEqFE8oH7PkqKEf4XbF166quTf3AmVQJ8Q6lfSqWlZTps/dDGCAOe3Z63drIbh2bu3A/49bjT1TS7RFK5QvkKCtrM8zOS1DhEDjPPNR84BD/vbpjehHUlG6i7xlTwhmYblQR1oMUpfqrHqX5b9Lg2qADH+AfKRJ7Xd/kPSXdEw7MvJaZFpv9VuiFlUv37EyQBopyFhWYxRU9Kb1XfmkxpO+TCovzmEbKpWxi8KBYOdbX3QaNBW6HQLEd79+H8E="
|
||||
},
|
||||
"gender": {
|
||||
"0": "Keine Anrede",
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
},
|
||||
"checkForUpdates": 3600000,
|
||||
"licence": {
|
||||
"scandit": "AZ70hgtZLmFWHbYP+BDq8VAEgAxmNGYcPU8YpOc3DryEXj4zMzYQFrQuUm0YfzKaR2xbfjsImjXJN7C/TE1CYXsv3DeqIzgDRA/kII4LzqoICWm9mnwejER1kMu1Vf+1NWbwUuYJjsQVQXYkwkWgnv53obevBZtjpgZqIzlStufIU+sPNEWSd9BlrLmiSEu6nXC5lbstyPJVaqihsFoBPNJ0Q+IgJUjqaxhTf6hGtNB3Rqcpv0ZT349NdK9mQ+9lAQYCwXdmYbELdlbZVSja0aJQlkf0TaAjixDbNcR32/VMIw98F2YxVRVWPnADUaJ9Bn8oa7NkOJIUfB7VAg1KtUl8IIwSXvRk436UtPZGxg+PQM7UXX/TgiBuqCQWdUChoH/QAoY2fyKRKgXJHnGdt+pBRQ2OYs7TZWCJLZsLKgnHV+eWh3Y3EB1hN9cmcszdnmYiyD1gCY8pSETFbWV01nVPvIuUTc+jMipv3NN81VQDS5/eU1VJNpRuDiufdBKJv0jjHQk+hTdqe+2GSmMD24ZG8FQXJZZPBCodWR1A81T8toCaIAGHnOfZeO7nxZu9Uo+6ohrVxc5F4szSizra+M3zfuFnm5FGgxCKt5uibLYgRyNcmR8/9vqTfMZgalTklbKHEFw1i+xOwrFrqRMh7FoovDRoI3QuaHLpV+ZUpZo3zTOQofdXPthKAmSLc11cjn509oTnnXUBBoBn/hErrwC/v8dZep1YEKM3wjfuIFsHRrsECswqNjwN/yOZCirm2VvFJEPMuKIwy+8jdNGncm8v4R9Br3c+wYJ8696L7Dg0iFShoyoP4OqIvBNY+dYyy935yGkIF2KI6l01xQZcWoHSVKPd6/78Iwy4lTKhtOqtu7ETJqOE53gQpR9jaAY0RiBB1SLm+Jbwt3ipSJiCDgKmkVmk5AU9HC0XYR/erjg13HF4hIcpLPW1ZWMKSxTqZ8z8FMJilInBgfcBwvjNE5seWvdFKltvlItnGhSh7BLUZ5UInDhl00NJBE2PdstDvRvQjLKvYUoFly3jONVsUfuQpzrcjT0g6gEgL8ZtlmaF11owcCvqhNDxWuTAJTX/xXf6WehxEB0qy3xCdxahbuneS3DPI0z2kAQwrx19i5r+RKQ8bWDaQ/OGY47sLPJgDgijEz16CvAMBSN0PvOso6FstsT/ynR3LLTPcY0QDw21Dv3wNHNa9HbanJcb3/MuhZGlrKp7"
|
||||
"scandit": "AbBVKBt1M6NjGVMLDyT7EBwD7Baj5eMzG0k8HT1QSQbUGAFCXXqF73RfxM88FluMPljT8WdVsHkvZcnrZmRhLRVGTU4rclBlVWYck0VozFbIbERw0GyFytcpKt78WTqihXGIkZFEoxcPH5YU63s1x/NDYJMYVvoT3CX+jYl/wGmLOSs/uH8u8p9wpNbjBx3IF0Yu6CA+gGDFP8RngRoRZtBvaLU4IEdk30Ehmg8iCso2Wl+8ePGYgRL+JndZ9B7ZI0lw2YBdsoCoPAVEUB0Ta1osx3rZ9eAmCSLlpCbJtDspHPqVFiQ6a2eBV9Wl5YZ2qrW8NYZ5GntJfytySqka9kOu3nubq04UMuZ6KyNkXjlUO1OvlFYBYW7eudeGParR1iJLPZMghJBOiWPv3nHMxWyxOXhZQKr1zhYgolbceOClnmIPF4JdDgpCwe4RdPTggYTU2Jh1YgPj67tNbijj8OtH7xMpALEOBAJ1/z6zNkYtLAS0qcwzH+QWwSC+I7vP1ne//ODsHLToUbe2LJoUEEht74NPTLWaLMTmmtfPrcoXSQX23yfrc/96d389JppSHp6vGK/CixEeSdrmLmdLYtTbH4mNqP53kp80fGPEd8FXZkFEpjtXtLQiQoP5ug5014FYFqpWqPzICAPhup4HWwSEKiNQ6UfWx9lbFSJYkbrP1JpLf9USNA0LyXN0b1IFNPr57Q25xPerJ04WUjWbfZ1+WZsS58CBjjggcdx4LDKv5/NaHq/wEDcxrt42tQlaCzZezneSZYJSS3cyB8o8C83XwWXo/l8fpbdvyB4O7DJEcL6vWS8jSyiIP8eKSRS81Dkv1UjZfjfomaF8Fh7bZYeatf4gSR3MH7aeaHy0LyVt6RX7Ly99WaVv0qWf3T6w"
|
||||
},
|
||||
"gender": {
|
||||
"0": "Keine Anrede",
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
"silentRefresh": {
|
||||
"interval": 300000
|
||||
},
|
||||
"debug": true,
|
||||
"debug": false,
|
||||
|
||||
"@cdn/product-image": {
|
||||
"url": "https://produktbilder.paragon-data.net"
|
||||
},
|
||||
@@ -74,7 +75,7 @@
|
||||
},
|
||||
"checkForUpdates": 3600000,
|
||||
"licence": {
|
||||
"scandit": "Ac2kvx5ZOzjvFl/LuAd6wds3C30YJ4g8Cm6PX4sgUnKPePVMuH+rFQIyVNn1YdS3myORojEOBsIZWhMw2nRUGBtOnQ5FO+cRHgQu0pkP+VG6OYvt8ETUTn8Aa2f9bmfqclO3LI8WN8psWr+adkZEtqNTvCgyDLZaICh8S7RfmwJVVWaOPX4LDagGhLDPS2YQdg+ibpR0l0ZlX2h/3GttofE64HOlBN3QtDB8yihHJNgVcUVy2UQVS+BXOyvIfZEFbFgPYVt5HZ0aQgcISlYVAmJvRsHyeKYRUnIi3ZN73EQmHzWcOV4/HWVoTs1MTW0mxV074vNwqExYW9LYmz9zgLUD7FMnKMFClkzRBHRN1CC7brosCnFkZWQp3CV4Ua48Fn9GW0Zpn/4MIZgzSU26inl5ZnT3dCc2+3BH3Us1uugTUrOPwFuwsPpr4NZYXWJMOmcm4kBBVJd0Uwk28GyZM7x1hXADcQgcc23+gDtbbUZWVmr3TE7GBcV3j+XUeOk8nHZw3DsYJ46MT2sSfks3QXRl4tBkBad6M+UxW4tb2IQC/4K9IXKhDN8VYXpzrrRHJNvOiH5+NrixthDZHHd/MGNuBDrJFOuXq8L7O6PxBoVZ0NPXmCO5vKyYdhBz5gJ5u3vNkSke7p+cDcvFicsVyNWRaaoFL0UN9gxFVMY8hkJKBZyGxZL2LEDXD44PxPsDnygpDC1Jyc7pkhEA0fKSc9aXZb1HDpwe1hqyyRVBtHkgPiN78GmJImbaUlj8XsK3yVyAjs2XvPR0/3ASHS53ViwzWKL3Oi8I515IJDtDhlvrkeh7MrWMaEu9k6ZQXJi1uJsh3JGfyS+yDlPjePVdsVqnZ4uw9pKMXvjlJeNcIiGM2Cf5S89nk2Qe/56MrKB9Frm6Q5wQHai8TNdCZYBi67dmAX8KHPXvEU4K6KyyW89YGcabZQ3eOJDr4oqW9ZcYPBttREdH3WI/HxvpEq6bqoDhT9AxpIWEMVb6y/DcDHSEresepibug4qOr9xOPq0yk2uiWYhPubFnCk7thQCXOGv9crWnQoOrt9c1qoaWXM4YmKqfcaQ67Tn+uFQmYTZyqw4jlJU4GgKe5/GNCVQM5aNUg1J0Px1NlFCS+rrIDyMQp0byFcgTd/E9sA5d1+YZKHKmJiQwEAz6oU9yyoUlxntSI42GHB/UttPc7Hj14V5+oJ+Yz+CZodmkXFg57Vx4NuxveNtO"
|
||||
"scandit": "Ae8F2Wx2RMq5Lvn7UUAlWzVFZTt2+ubMAF8XtDpmPlNkBeG/LWs1M7AbgDW0LQqYLnszClEENaEHS56/6Ts2vrJ1Ux03CXUjK3jUvZpF5OchXR1CpnmpepJ6WxPCd7LMVHUGG1BbwPLDTFjP3y8uT0caTSmmGrYQWAs4CZcEF+ZBabP0z7vfm+hCZF/ebj9qqCJZcW8nH/n19hohshllzYBjFXjh87P2lIh1s6yZS3OaQWWXo/o0AKdxx7T6CVyR0/G5zq6uYJWf6rs3euUBEhpzOZHbHZK86Lvy2AVBEyVkkcttlDW1J2fA4l1W1JV/Xibz8AQV6kG482EpGF42KEoK48paZgX3e1AQsqUtmqzw294dcP4zMVstnw5/WrwKKi/5E/nOOJT2txYP1ZufIjPrwNFsqTlv7xCQlHjMzFGYwT816yD5qLRLbwOtjrkUPXNZLZ06T4upvWwJDmm8XgdeoDqMjHdcO4lwji1bl9EiIYJ/2qnsk9yZ2FqSaHzn4cbiL0f5u2HFlNAP0GUujGRlthGhHi6o4dFU+WAxKsFMKVt+SfoQUazNKHFVQgiAklTIZxIc/HUVzRvOLMxf+wFDerraBtcqGJg+g/5mrWYqeDBGhCBHtKiYf6244IJ4afzNTiH1/30SJcRzXwbEa3A7q1fJTx9/nLTOfVPrJKBQs7f/OQs2dA7LDCel8mzXdbjvsNQaeU5+iCIAq6zbTNKy1xT8wwj+VZrQmtNJs+qeznD+u29nCM24h8xCmRpvNPo4/Mww/lrTNrrNwLBSn1pMIwsH7yS9hH0v0oNAM3A6bVtk1D9qEkbyw+xZa+MZGpMP0D0CdcsqHalPcm5r/Ik="
|
||||
},
|
||||
"gender": {
|
||||
"0": "Keine Anrede",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { BranchDTO } from '@swagger/checkout';
|
||||
import { BranchDTO } from '@generated/swagger/checkout-api';
|
||||
import { isBoolean, isNumber } from '@utils/common';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { first, map, switchMap } from 'rxjs/operators';
|
||||
@@ -35,7 +35,9 @@ export class ApplicationService {
|
||||
|
||||
getProcesses$(section?: 'customer' | 'branch') {
|
||||
const processes$ = this.store.select(selectProcesses);
|
||||
return processes$.pipe(map((processes) => processes.filter((process) => (section ? process.section === section : true))));
|
||||
return processes$.pipe(
|
||||
map((processes) => processes.filter((process) => (section ? process.section === section : true))),
|
||||
);
|
||||
}
|
||||
|
||||
getProcessById$(processId: number): Observable<ApplicationProcess> {
|
||||
@@ -135,7 +137,10 @@ export class ApplicationService {
|
||||
this.store.dispatch(setSection({ section }));
|
||||
}
|
||||
|
||||
getLastActivatedProcessWithSectionAndType$(section: 'customer' | 'branch', type: string): Observable<ApplicationProcess> {
|
||||
getLastActivatedProcessWithSectionAndType$(
|
||||
section: 'customer' | 'branch',
|
||||
type: string,
|
||||
): Observable<ApplicationProcess> {
|
||||
return this.getProcesses$(section).pipe(
|
||||
map((processes) =>
|
||||
processes
|
||||
|
||||
@@ -11,8 +11,17 @@ export const addProcess = createAction(`${prefix} Add Process`, props<{ process:
|
||||
|
||||
export const removeProcess = createAction(`${prefix} Remove Process`, props<{ processId: number }>());
|
||||
|
||||
export const setActivatedProcess = createAction(`${prefix} Set Activated Process`, props<{ activatedProcessId: number }>());
|
||||
export const setActivatedProcess = createAction(
|
||||
`${prefix} Set Activated Process`,
|
||||
props<{ activatedProcessId: number }>(),
|
||||
);
|
||||
|
||||
export const patchProcess = createAction(`${prefix} Patch Process`, props<{ processId: number; changes: Partial<ApplicationProcess> }>());
|
||||
export const patchProcess = createAction(
|
||||
`${prefix} Patch Process`,
|
||||
props<{ processId: number; changes: Partial<ApplicationProcess> }>(),
|
||||
);
|
||||
|
||||
export const patchProcessData = createAction(`${prefix} Patch Process Data`, props<{ processId: number; data: Record<string, any> }>());
|
||||
export const patchProcessData = createAction(
|
||||
`${prefix} Patch Process Data`,
|
||||
props<{ processId: number; data: Record<string, any> }>(),
|
||||
);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { coerceArray, coerceStringArray } from '@angular/cdk/coercion';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { coerceArray } from '@angular/cdk/coercion';
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { Config } from '@core/config';
|
||||
import { isNullOrUndefined } from '@utils/common';
|
||||
import { AuthConfig, OAuthService } from 'angular-oauth2-oidc';
|
||||
import { JwksValidationHandler } from 'angular-oauth2-oidc-jwks';
|
||||
import { asapScheduler, BehaviorSubject } from 'rxjs';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
@@ -44,21 +44,26 @@ export class AuthService {
|
||||
this._oAuthService.tokenValidationHandler = new JwksValidationHandler();
|
||||
|
||||
this._oAuthService.setupAutomaticSilentRefresh();
|
||||
try {
|
||||
await this._oAuthService.loadDiscoveryDocumentAndTryLogin();
|
||||
} catch (error) {
|
||||
this.login();
|
||||
|
||||
throw error;
|
||||
}
|
||||
await this._oAuthService.loadDiscoveryDocumentAndTryLogin();
|
||||
|
||||
this._initialized.next(true);
|
||||
}
|
||||
|
||||
isAuthenticated() {
|
||||
return this.isIdTokenValid();
|
||||
}
|
||||
|
||||
isIdTokenValid() {
|
||||
console.log('ID Token Expiration:', new Date(this._oAuthService.getIdTokenExpiration()));
|
||||
return this._oAuthService.hasValidIdToken();
|
||||
}
|
||||
|
||||
isAccessTokenValid() {
|
||||
console.log('ACCESS Token Expiration:', new Date(this._oAuthService.getAccessTokenExpiration()));
|
||||
return this._oAuthService.hasValidAccessToken();
|
||||
}
|
||||
|
||||
getToken() {
|
||||
return this._oAuthService.getAccessToken();
|
||||
}
|
||||
@@ -99,9 +104,6 @@ export class AuthService {
|
||||
|
||||
async logout() {
|
||||
await this._oAuthService.revokeTokenAndLogout();
|
||||
// asapScheduler.schedule(() => {
|
||||
// window.location.reload();
|
||||
// }, 250);
|
||||
}
|
||||
|
||||
hasRole(role: string | string[]) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { AuthService } from './auth.service';
|
||||
|
||||
@Directive({
|
||||
selector: '[ifRole],[ifRoleElse],[ifNotRole],[ifNotRoleElse]',
|
||||
standalone: false,
|
||||
})
|
||||
export class IfRoleDirective implements OnChanges {
|
||||
@Input()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from './auth.module';
|
||||
export * from './auth.service';
|
||||
export * from './if-role.directive';
|
||||
export * from './login.strategy';
|
||||
|
||||
78
apps/isa-app/src/core/auth/login.strategy.ts
Normal file
78
apps/isa-app/src/core/auth/login.strategy.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { ScanAdapterService } from '@adapter/scan';
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { toSignal } from '@angular/core/rxjs-interop';
|
||||
import { EnvironmentService } from '@core/environment';
|
||||
import { UiConfirmModalComponent, UiModalResult, UiModalService } from '@ui/modal';
|
||||
import { injectNetworkStatus$ } from '../../app/services';
|
||||
import { AuthService } from './auth.service';
|
||||
import { AuthService as IsaAuthService } from '@generated/swagger/isa-api';
|
||||
import { firstValueFrom, lastValueFrom } from 'rxjs';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class LoginStrategy {
|
||||
private readonly environmentService = inject(EnvironmentService);
|
||||
private readonly networkStatus = toSignal(injectNetworkStatus$());
|
||||
private readonly modal = inject(UiModalService);
|
||||
private readonly scanAdapterService = inject(ScanAdapterService);
|
||||
private readonly isaAuthService = inject(IsaAuthService);
|
||||
private readonly authService = inject(AuthService);
|
||||
|
||||
async login(title = 'Anmeldung') {
|
||||
console.log('LoginStrategy.login');
|
||||
|
||||
let loginModalResult: UiModalResult<boolean>;
|
||||
|
||||
if (this.authService.isIdTokenValid()) {
|
||||
console.log('LoginStrategy.login: idToken is valid');
|
||||
await this.authService.login();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (this.environmentService.isMobileDevice()) {
|
||||
console.log('LoginStrategy.login: isMobileDevice');
|
||||
do {
|
||||
const loginModal = this.modal.open({
|
||||
content: UiConfirmModalComponent,
|
||||
title,
|
||||
config: {
|
||||
canClose: false,
|
||||
backdropClose: false,
|
||||
},
|
||||
data: {
|
||||
message: 'Bitte wählen Sie die Anmeldeoption aus.',
|
||||
rejectLabel: 'Anmeldung mit Logindaten',
|
||||
confirmLabel: 'Anmeldung mit Keycard',
|
||||
},
|
||||
});
|
||||
|
||||
loginModalResult = await loginModal.afterClosed$.toPromise();
|
||||
} while (this.networkStatus() === 'offline');
|
||||
}
|
||||
} catch (error) {}
|
||||
|
||||
try {
|
||||
if (loginModalResult.data) {
|
||||
const result = await lastValueFrom(this.scanAdapterService.scan());
|
||||
|
||||
if (typeof result === 'string') {
|
||||
const res = await firstValueFrom(
|
||||
this.isaAuthService.AuthLogin({
|
||||
code: result,
|
||||
application: 'isa',
|
||||
hostname: location.host,
|
||||
}),
|
||||
);
|
||||
|
||||
if (res.token) {
|
||||
console.log('LoginStrategy.login: setKeyCardToken', res.token);
|
||||
this.authService.setKeyCardToken(res.token);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {}
|
||||
|
||||
console.log('LoginStrategy.login: login');
|
||||
await this.authService.login();
|
||||
}
|
||||
}
|
||||
@@ -120,7 +120,10 @@ export class BreadcrumbService {
|
||||
|
||||
if (recursive) {
|
||||
const breadcrumbs = await this.getBreadcrumbByKey$(breadcrumb.key).pipe(take(1)).toPromise();
|
||||
breadcrumbsToRemove = [...breadcrumbsToRemove, ...breadcrumbs.filter((crumb) => crumb.timestamp > breadcrumb.timestamp)];
|
||||
breadcrumbsToRemove = [
|
||||
...breadcrumbsToRemove,
|
||||
...breadcrumbs.filter((crumb) => crumb.timestamp > breadcrumb.timestamp),
|
||||
];
|
||||
}
|
||||
|
||||
if (!breadcrumbsToRemove.length) {
|
||||
@@ -135,7 +138,10 @@ export class BreadcrumbService {
|
||||
crumbs.forEach((crumb) => this.removeBreadcrumb(crumb.id));
|
||||
}
|
||||
|
||||
getLatestBreadcrumbForSection(section: 'customer' | 'branch', predicate: (crumb: Breadcrumb) => boolean = (_) => true) {
|
||||
getLatestBreadcrumbForSection(
|
||||
section: 'customer' | 'branch',
|
||||
predicate: (crumb: Breadcrumb) => boolean = (_) => true,
|
||||
) {
|
||||
return this.store
|
||||
.select(selectors.selectBreadcrumbsBySection, { section })
|
||||
.pipe(map((crumbs) => crumbs.sort((a, b) => b.timestamp - a.timestamp).find((f) => predicate(f))));
|
||||
|
||||
@@ -27,7 +27,7 @@ export interface Breadcrumb {
|
||||
/**
|
||||
* Query Parameter
|
||||
*/
|
||||
params?: Object;
|
||||
params?: object;
|
||||
|
||||
/**
|
||||
* Timestamp
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
describe('Breadcrumb Actions', () => {});
|
||||
|
||||
@@ -11,7 +11,10 @@ export const addBreadcrumb = createAction(`${prefix} Add Breadcrumb`, props<{ br
|
||||
/**
|
||||
* Action um Breadcrumb im State zu ändern
|
||||
*/
|
||||
export const updateBreadcrumb = createAction(`${prefix} Update Breadcrumb`, props<{ id: number; changes: Partial<Breadcrumb> }>());
|
||||
export const updateBreadcrumb = createAction(
|
||||
`${prefix} Update Breadcrumb`,
|
||||
props<{ id: number; changes: Partial<Breadcrumb> }>(),
|
||||
);
|
||||
|
||||
/**
|
||||
* Action um Breadcrumb im State zu entfernen
|
||||
|
||||
@@ -43,7 +43,10 @@ describe('Breadcrumb Reducer', () => {
|
||||
|
||||
const state = breadcrumbReducer(INIT, action.addBreadcrumb({ breadcrumb }));
|
||||
|
||||
const fixture = breadcrumbReducer(state, action.updateBreadcrumb({ id: breadcrumb.id, changes: { name: 'Test Name 2' } }));
|
||||
const fixture = breadcrumbReducer(
|
||||
state,
|
||||
action.updateBreadcrumb({ id: breadcrumb.id, changes: { name: 'Test Name 2' } }),
|
||||
);
|
||||
|
||||
expect(fixture.entities[breadcrumb.id]).toEqual(expected);
|
||||
});
|
||||
|
||||
@@ -10,26 +10,46 @@ describe('Breadcrumb Selectors', () => {
|
||||
beforeEach(() => {
|
||||
state = breadcrumbReducer(
|
||||
INIT,
|
||||
action.addBreadcrumb({ breadcrumb: { id: 1, key: 'unit-test-1', path: '', name: 'Unit Test 1', section: 'customer' } }),
|
||||
);
|
||||
state = breadcrumbReducer(
|
||||
state,
|
||||
action.addBreadcrumb({
|
||||
breadcrumb: { id: 2, key: 'unit-test-1', path: '', name: 'Unit Test 1', tags: ['details'], section: 'customer' },
|
||||
breadcrumb: { id: 1, key: 'unit-test-1', path: '', name: 'Unit Test 1', section: 'customer' },
|
||||
}),
|
||||
);
|
||||
state = breadcrumbReducer(
|
||||
state,
|
||||
action.addBreadcrumb({ breadcrumb: { id: 3, key: 'unit-test-2', path: '', name: 'Unit Test 1', section: 'customer' } }),
|
||||
);
|
||||
state = breadcrumbReducer(
|
||||
state,
|
||||
action.addBreadcrumb({ breadcrumb: { id: 4, key: 'unit-test-3', path: '', name: 'Unit Test 1', section: 'customer' } }),
|
||||
action.addBreadcrumb({
|
||||
breadcrumb: {
|
||||
id: 2,
|
||||
key: 'unit-test-1',
|
||||
path: '',
|
||||
name: 'Unit Test 1',
|
||||
tags: ['details'],
|
||||
section: 'customer',
|
||||
},
|
||||
}),
|
||||
);
|
||||
state = breadcrumbReducer(
|
||||
state,
|
||||
action.addBreadcrumb({
|
||||
breadcrumb: { id: 5, key: 'unit-test-3', path: '', name: 'Unit Test 1', tags: ['details'], section: 'customer' },
|
||||
breadcrumb: { id: 3, key: 'unit-test-2', path: '', name: 'Unit Test 1', section: 'customer' },
|
||||
}),
|
||||
);
|
||||
state = breadcrumbReducer(
|
||||
state,
|
||||
action.addBreadcrumb({
|
||||
breadcrumb: { id: 4, key: 'unit-test-3', path: '', name: 'Unit Test 1', section: 'customer' },
|
||||
}),
|
||||
);
|
||||
state = breadcrumbReducer(
|
||||
state,
|
||||
action.addBreadcrumb({
|
||||
breadcrumb: {
|
||||
id: 5,
|
||||
key: 'unit-test-3',
|
||||
path: '',
|
||||
name: 'Unit Test 1',
|
||||
tags: ['details'],
|
||||
section: 'customer',
|
||||
},
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -20,7 +20,9 @@ export const selectBreadcrumbById = createSelector(selectEntities, (entities, id
|
||||
/**
|
||||
* Gibt alle Breadcrumb Entities als Array zurück die den key enthalten
|
||||
*/
|
||||
export const selectBreadcrumbsByKey = createSelector(selectAll, (entities, key: string) => entities.filter((crumb) => crumb.key == key));
|
||||
export const selectBreadcrumbsByKey = createSelector(selectAll, (entities, key: string) =>
|
||||
entities.filter((crumb) => crumb.key == key),
|
||||
);
|
||||
|
||||
/**
|
||||
* Gibt alle Breadcrumb Entities als Array zurück die den key und tag enthalten
|
||||
@@ -37,12 +39,15 @@ export const selectBreadcrumbsByKeyAndTag = createSelector(
|
||||
export const selectBreadcrumbsByKeyAndTags = createSelector(
|
||||
selectAll,
|
||||
(entities: Breadcrumb[], { key, tags }: { key: string; tags: string[] }) =>
|
||||
entities.filter((crumb) => crumb.key == key && isArray(crumb.tags) && tags.every((tag) => crumb.tags.includes(tag))),
|
||||
entities.filter(
|
||||
(crumb) => crumb.key == key && isArray(crumb.tags) && tags.every((tag) => crumb.tags.includes(tag)),
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Gibt alle Breadcrumb Entities als Array zurück die die tags enthalten
|
||||
*/
|
||||
export const selectBreadcrumbsBySection = createSelector(selectAll, (entities: Breadcrumb[], { section }: { section: string }) =>
|
||||
entities.filter((crumb) => crumb.section === section),
|
||||
export const selectBreadcrumbsBySection = createSelector(
|
||||
selectAll,
|
||||
(entities: Breadcrumb[], { section }: { section: string }) => entities.filter((crumb) => crumb.section === section),
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createEntityAdapter, EntityState } from '@ngrx/entity';
|
||||
import { Breadcrumb } from '../defs';
|
||||
|
||||
export interface BreadcrumbState extends EntityState<Breadcrumb> {}
|
||||
export type BreadcrumbState = EntityState<Breadcrumb>
|
||||
|
||||
export const featureName = 'core-breadcrumb';
|
||||
|
||||
|
||||
8
apps/isa-app/src/core/cache/cache.service.ts
vendored
8
apps/isa-app/src/core/cache/cache.service.ts
vendored
@@ -34,7 +34,7 @@ export class CacheService {
|
||||
return 'cache';
|
||||
}
|
||||
|
||||
private getKey(token: Object | string): string {
|
||||
private getKey(token: object | string): string {
|
||||
if (typeof token === 'string') {
|
||||
return this.hash(token);
|
||||
}
|
||||
@@ -105,7 +105,7 @@ export class CacheService {
|
||||
});
|
||||
}
|
||||
|
||||
private async cached(token: Object | string): Promise<DbEntry<any> | undefined> {
|
||||
private async cached(token: object | string): Promise<DbEntry<any> | undefined> {
|
||||
const store = await this.getObjectStore();
|
||||
return new Promise<DbEntry<any> | undefined>((resolve, reject) => {
|
||||
const request = store.get(this.getKey(token));
|
||||
@@ -118,7 +118,7 @@ export class CacheService {
|
||||
});
|
||||
}
|
||||
|
||||
async get<T = any>(token: Object | string): Promise<T | undefined> {
|
||||
async get<T = any>(token: object | string): Promise<T | undefined> {
|
||||
const cached = await this.cached(token);
|
||||
|
||||
if (!cached) {
|
||||
@@ -133,7 +133,7 @@ export class CacheService {
|
||||
return cached.data;
|
||||
}
|
||||
|
||||
async delete(token: Object | string): Promise<void> {
|
||||
async delete(token: object | string): Promise<void> {
|
||||
const store = await this.getObjectStore('readwrite');
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
const request = store.delete(this.getKey(token));
|
||||
|
||||
@@ -4,7 +4,10 @@ import { CommandService } from './command.service';
|
||||
import { FEATURE_ACTION_HANDLERS, ROOT_ACTION_HANDLERS } from './tokens';
|
||||
|
||||
export function provideActionHandlers(actionHandlers: Type<ActionHandler>[]): Provider[] {
|
||||
return [CommandService, actionHandlers.map((handler) => ({ provide: FEATURE_ACTION_HANDLERS, useClass: handler, multi: true }))];
|
||||
return [
|
||||
CommandService,
|
||||
actionHandlers.map((handler) => ({ provide: FEATURE_ACTION_HANDLERS, useClass: handler, multi: true })),
|
||||
];
|
||||
}
|
||||
|
||||
@NgModule({})
|
||||
@@ -12,14 +15,20 @@ export class CoreCommandModule {
|
||||
static forRoot(actionHandlers: Type<ActionHandler>[]): ModuleWithProviders<CoreCommandModule> {
|
||||
return {
|
||||
ngModule: CoreCommandModule,
|
||||
providers: [CommandService, actionHandlers.map((handler) => ({ provide: ROOT_ACTION_HANDLERS, useClass: handler, multi: true }))],
|
||||
providers: [
|
||||
CommandService,
|
||||
actionHandlers.map((handler) => ({ provide: ROOT_ACTION_HANDLERS, useClass: handler, multi: true })),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
static forChild(actionHandlers: Type<ActionHandler>[]): ModuleWithProviders<CoreCommandModule> {
|
||||
return {
|
||||
ngModule: CoreCommandModule,
|
||||
providers: [CommandService, actionHandlers.map((handler) => ({ provide: FEATURE_ACTION_HANDLERS, useClass: handler, multi: true }))],
|
||||
providers: [
|
||||
CommandService,
|
||||
actionHandlers.map((handler) => ({ provide: FEATURE_ACTION_HANDLERS, useClass: handler, multi: true })),
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
/**
|
||||
* Config loader interface for loading configurations
|
||||
*/
|
||||
export interface ConfigLoader {
|
||||
load(): Promise<any>;
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
// start:ng42.barrel
|
||||
export * from './config-loader';
|
||||
export * from './json.config-loader';
|
||||
// end:ng42.barrel
|
||||
@@ -1,36 +0,0 @@
|
||||
// unit test JsonConfigLoader
|
||||
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
|
||||
import { createServiceFactory, SpectatorService } from '@ngneat/spectator';
|
||||
import { CORE_JSON_CONFIG_LOADER_URL } from '../tokens';
|
||||
import { JsonConfigLoader } from './json.config-loader';
|
||||
|
||||
describe('JsonConfigLoader', () => {
|
||||
let spectator: SpectatorService<JsonConfigLoader>;
|
||||
const createService = createServiceFactory({
|
||||
imports: [HttpClientTestingModule],
|
||||
service: JsonConfigLoader,
|
||||
mocks: [],
|
||||
providers: [{ provide: CORE_JSON_CONFIG_LOADER_URL, useValue: '/assets/config.json' }],
|
||||
});
|
||||
let httpTestingController: HttpTestingController;
|
||||
|
||||
beforeEach(() => {
|
||||
spectator = createService();
|
||||
httpTestingController = spectator.inject(HttpTestingController);
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(spectator.service).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('load', () => {
|
||||
it('should call the provided url', async () => {
|
||||
const reqPromise = spectator.service.load();
|
||||
const req = httpTestingController.expectOne('/assets/config.json');
|
||||
req.flush({ unit: 'test' });
|
||||
const result = await reqPromise;
|
||||
httpTestingController.verify();
|
||||
expect(result).toEqual({ unit: 'test' });
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,16 +0,0 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { ConfigLoader } from './config-loader';
|
||||
import { CORE_JSON_CONFIG_LOADER_URL } from '../tokens';
|
||||
|
||||
@Injectable()
|
||||
export class JsonConfigLoader implements ConfigLoader {
|
||||
constructor(
|
||||
@Inject(CORE_JSON_CONFIG_LOADER_URL) private url: string,
|
||||
private http: HttpClient,
|
||||
) {}
|
||||
|
||||
load(): Promise<any> {
|
||||
return this.http.get(this.url).toPromise();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { Type } from '@angular/core';
|
||||
import { ConfigLoader } from './config-loaders';
|
||||
|
||||
export interface ConfigModuleOptions {
|
||||
useConfigLoader: Type<ConfigLoader>;
|
||||
jsonConfigLoaderUrl?: string;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import { APP_INITIALIZER, ModuleWithProviders, NgModule } from '@angular/core';
|
||||
import { CORE_CONFIG_LOADER } from '@core/config';
|
||||
import { Config } from './config';
|
||||
import { ConfigModuleOptions } from './config-module-options';
|
||||
import { CORE_JSON_CONFIG_LOADER_URL } from './tokens';
|
||||
|
||||
export function _initializeConfigFactory(config: Config) {
|
||||
return () => config.init();
|
||||
}
|
||||
|
||||
@NgModule({})
|
||||
export class ConfigModule {
|
||||
static forRoot(options: ConfigModuleOptions): ModuleWithProviders<ConfigModule> {
|
||||
const configLoaderProvider = {
|
||||
provide: CORE_CONFIG_LOADER,
|
||||
useClass: options.useConfigLoader,
|
||||
};
|
||||
|
||||
return {
|
||||
ngModule: ConfigModule,
|
||||
providers: [
|
||||
Config,
|
||||
configLoaderProvider,
|
||||
options.jsonConfigLoaderUrl ? { provide: CORE_JSON_CONFIG_LOADER_URL, useValue: options.jsonConfigLoaderUrl } : null,
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
import { createServiceFactory, SpectatorService } from '@ngneat/spectator';
|
||||
import { Config } from './config';
|
||||
import { ConfigLoader } from './config-loaders';
|
||||
import { CORE_CONFIG_LOADER } from './tokens';
|
||||
|
||||
class TestConfigLoader implements ConfigLoader {
|
||||
load() {
|
||||
return Promise.resolve({});
|
||||
}
|
||||
}
|
||||
|
||||
// Unit test Config
|
||||
describe('Config', () => {
|
||||
let spectator: SpectatorService<Config>;
|
||||
const createService = createServiceFactory({
|
||||
service: Config,
|
||||
providers: [{ provide: CORE_CONFIG_LOADER, useClass: TestConfigLoader }],
|
||||
});
|
||||
let configLoader: ConfigLoader;
|
||||
|
||||
beforeEach(() => {
|
||||
spectator = createService();
|
||||
configLoader = spectator.inject(CORE_CONFIG_LOADER);
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(spectator.service).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('init()', () => {
|
||||
it('should load config and assigns it to _config', async () => {
|
||||
const config = { unit: 'test' };
|
||||
spyOn(configLoader, 'load').and.returnValue(Promise.resolve(config));
|
||||
await spectator.service.init();
|
||||
expect(spectator.service['_config']).toEqual(config);
|
||||
});
|
||||
});
|
||||
|
||||
describe('get()', () => {
|
||||
it('should return config value', () => {
|
||||
spectator.service['_config'] = { test: 'test' };
|
||||
expect(spectator.service.get('test')).toEqual('test');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,27 +0,0 @@
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { ReplaySubject } from 'rxjs';
|
||||
import { ConfigLoader } from './config-loaders';
|
||||
import { CORE_CONFIG_LOADER } from './tokens';
|
||||
import { pick } from './utils';
|
||||
|
||||
@Injectable()
|
||||
export class Config {
|
||||
private _config: any;
|
||||
|
||||
private readonly _initilized = new ReplaySubject<void>(1);
|
||||
get initialized() {
|
||||
return this._initilized.asObservable();
|
||||
}
|
||||
|
||||
constructor(@Inject(CORE_CONFIG_LOADER) private readonly _configLoader: ConfigLoader) {}
|
||||
|
||||
// load config and assign it to this._config
|
||||
async init() {
|
||||
this._config = await this._configLoader.load();
|
||||
this._initilized.next();
|
||||
}
|
||||
|
||||
get(path: string) {
|
||||
return pick(path, this._config);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
export * from './config-loaders';
|
||||
export * from './config-module-options';
|
||||
export * from './config.module';
|
||||
export * from './config';
|
||||
export * from './tokens';
|
||||
export * from './utils';
|
||||
@@ -1,6 +0,0 @@
|
||||
import { InjectionToken } from '@angular/core';
|
||||
import { ConfigLoader } from './config-loaders';
|
||||
|
||||
export const CORE_CONFIG_LOADER = new InjectionToken<ConfigLoader>('core.config.loader');
|
||||
|
||||
export const CORE_JSON_CONFIG_LOADER_URL = new InjectionToken<ConfigLoader>('core.json.config.loader.url');
|
||||
@@ -1,3 +0,0 @@
|
||||
// start:ng42.barrel
|
||||
export * from './pick';
|
||||
// end:ng42.barrel
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user