mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-31 09:37:15 +01:00
Compare commits
368 Commits
3.2
...
feature/50
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3cc623920f | ||
|
|
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 | ||
|
|
301f5878c2 | ||
|
|
39c8a512f4 | ||
|
|
f37dfd41f1 | ||
|
|
a518fc50e2 | ||
|
|
c9236f191b | ||
|
|
d1584d1edb | ||
|
|
5f34b514ef | ||
|
|
7a1ef06a4c | ||
|
|
acc2f7f664 | ||
|
|
ad08e999a2 | ||
|
|
1d472ce3df | ||
|
|
92d760b8b4 | ||
|
|
1d19779dac | ||
|
|
294be5dcb4 | ||
|
|
90e671d285 | ||
|
|
9a2c520ab4 | ||
|
|
13d41a7a81 | ||
|
|
79b0a1324c | ||
|
|
0fd94273ce | ||
|
|
44abd4698e | ||
|
|
2b262cc8be | ||
|
|
5775e444b8 | ||
|
|
cdfe88c1cc | ||
|
|
c71d1f8886 | ||
|
|
a09eef038e | ||
|
|
f0a0189523 | ||
|
|
4d42c4ea45 | ||
|
|
cad2926c45 | ||
|
|
161d9c6fea | ||
|
|
1b33258728 | ||
|
|
73b6133306 | ||
|
|
eb6e93149e | ||
|
|
33fb44f20a | ||
|
|
8723f7aa7e | ||
|
|
86a11ff07a | ||
|
|
41be8533dc | ||
|
|
186afbc828 | ||
|
|
c3561339a9 | ||
|
|
5312073184 | ||
|
|
4dfe3bfa11 | ||
|
|
f1bdba5d10 | ||
|
|
d5dc4e053d | ||
|
|
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.
|
||||||
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/)
|
||||||
16
.gitignore
vendored
16
.gitignore
vendored
@@ -1,10 +1,15 @@
|
|||||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
.matomo
|
||||||
|
junit.xml
|
||||||
|
|
||||||
# compiled output
|
# compiled output
|
||||||
/dist
|
/dist
|
||||||
/tmp
|
/tmp
|
||||||
/out-tsc
|
/out-tsc
|
||||||
|
|
||||||
|
/
|
||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
/node_modules
|
/node_modules
|
||||||
|
|
||||||
@@ -47,4 +52,13 @@ testem.log
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|
||||||
libs/swagger/src/lib/*
|
libs/swagger/src/lib/*
|
||||||
|
*storybook.log
|
||||||
|
|
||||||
|
|
||||||
|
.nx/cache
|
||||||
|
.nx/workspace-data
|
||||||
|
.angular
|
||||||
|
|
||||||
|
|
||||||
|
storybook-static
|
||||||
|
|||||||
@@ -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
|
# Add files here to ignore them from prettier formatting
|
||||||
|
|
||||||
/dist
|
/dist
|
||||||
/coverage
|
/coverage
|
||||||
/helmvalues
|
/.nx/cache
|
||||||
/apps/swagger
|
/.nx/workspace-data
|
||||||
/ng-swagger-gen
|
/node_modules
|
||||||
|
.angular
|
||||||
*.json
|
.vscode
|
||||||
*.yml
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"singleQuote": true,
|
|
||||||
"printWidth": 140
|
|
||||||
}
|
|
||||||
|
|
||||||
15
.vscode/extensions.json
vendored
15
.vscode/extensions.json
vendored
@@ -1,7 +1,10 @@
|
|||||||
{
|
{
|
||||||
"recommendations": [
|
"recommendations": [
|
||||||
"johnpapa.angular2",
|
"johnpapa.angular2",
|
||||||
"esbenp.prettier-vscode",
|
"esbenp.prettier-vscode",
|
||||||
"angular.ng-template",
|
"angular.ng-template",
|
||||||
]
|
"nrwl.angular-console",
|
||||||
}
|
"dbaeumer.vscode-eslint",
|
||||||
|
"firsttris.vscode-jest-runner"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
93
.vscode/settings.json
vendored
93
.vscode/settings.json
vendored
@@ -1,15 +1,98 @@
|
|||||||
{
|
{
|
||||||
|
"editor.accessibilitySupport": "off",
|
||||||
"typescript.tsdk": "node_modules/typescript/lib",
|
"typescript.tsdk": "node_modules/typescript/lib",
|
||||||
|
"exportall.config.exclude": [".test.", ".spec.", ".stories."],
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
"typescriptHero.imports.insertSemicolons": false,
|
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
"[javascript]": {
|
"eslint.validate": [
|
||||||
|
"json"
|
||||||
|
],
|
||||||
|
"[html]": {
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
},
|
},
|
||||||
"[typescript]": {
|
"[typescript]": {
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
},
|
},
|
||||||
"css.validate": false,
|
"[typescriptreact]": {
|
||||||
"less.validate": false,
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
"scss.validate": false
|
},
|
||||||
|
"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": ".github/review-instructions.md"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": ".github/testing-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"
|
||||||
|
}
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#stage 1
|
#stage 1
|
||||||
FROM node:18 as base
|
FROM node:22 as base
|
||||||
ARG IS_PRODUCTION=false
|
ARG IS_PRODUCTION=false
|
||||||
ARG SEMVERSION=1.0.0
|
ARG SEMVERSION=1.0.0
|
||||||
ARG BuildUniqueID
|
ARG BuildUniqueID
|
||||||
@@ -8,7 +8,7 @@ WORKDIR /app
|
|||||||
COPY . .
|
COPY . .
|
||||||
RUN umask 0022
|
RUN umask 0022
|
||||||
RUN npm version ${SEMVERSION}
|
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
|
RUN if [ "${IS_PRODUCTION}" = "true" ] ; then npm run-script build-prod ; else npm run-script build ; fi
|
||||||
|
|
||||||
# stage final
|
# stage final
|
||||||
@@ -24,6 +24,6 @@ ARG BuildUniqueID
|
|||||||
LABEL build.uniqueid="${BuildUniqueID:-1}"
|
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
|
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
|
# ignore exitcode, sonst gibts keinen container
|
||||||
RUN npm test || true
|
RUN npm run ci || true
|
||||||
ENTRYPOINT [ "/bin/sleep", "60000" ]
|
ENTRYPOINT [ "/bin/sleep", "60000" ]
|
||||||
|
|
||||||
|
|||||||
1478
angular.json
1478
angular.json
File diff suppressed because it is too large
Load Diff
@@ -1,25 +0,0 @@
|
|||||||
# Scan
|
|
||||||
|
|
||||||
This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 12.2.0.
|
|
||||||
|
|
||||||
## Code scaffolding
|
|
||||||
|
|
||||||
Run `ng generate component component-name --project scan` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project scan`.
|
|
||||||
|
|
||||||
> Note: Don't forget to add `--project scan` or else it will be added to the default project in your `angular.json` file.
|
|
||||||
|
|
||||||
## Build
|
|
||||||
|
|
||||||
Run `ng build scan` to build the project. The build artifacts will be stored in the `dist/` directory.
|
|
||||||
|
|
||||||
## Publishing
|
|
||||||
|
|
||||||
After building your library with `ng build scan`, go to the dist folder `cd dist/scan` and run `npm publish`.
|
|
||||||
|
|
||||||
## Running unit tests
|
|
||||||
|
|
||||||
Run `ng test scan` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
|
||||||
|
|
||||||
## Further help
|
|
||||||
|
|
||||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
|
||||||
"dest": "../../../dist/adapter/scan",
|
|
||||||
"lib": {
|
|
||||||
"entryFile": "src/public-api.ts"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@adapter/scan",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"peerDependencies": {
|
|
||||||
"@angular/common": "^12.2.0",
|
|
||||||
"@angular/core": "^12.2.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"tslib": "^2.3.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
import { Injectable, isDevMode } from '@angular/core';
|
|
||||||
import { EnvironmentService } from '@core/environment';
|
|
||||||
import { PromptModalData, UiModalService, UiPromptModalComponent } from '@ui/modal';
|
|
||||||
import { Observable } from 'rxjs';
|
|
||||||
import { ScanAdapter } from './scan-adapter';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class DevScanAdapter implements ScanAdapter {
|
|
||||||
readonly name = 'Dev';
|
|
||||||
|
|
||||||
constructor(private _modal: UiModalService, private _environmentService: EnvironmentService) {}
|
|
||||||
|
|
||||||
async init(): Promise<boolean> {
|
|
||||||
return Promise.resolve(false);
|
|
||||||
// return new Promise((resolve, reject) => {
|
|
||||||
// resolve(isDevMode());
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
|
|
||||||
scan(): Observable<string> {
|
|
||||||
return new Observable((observer) => {
|
|
||||||
const modalRef = this._modal.open({
|
|
||||||
content: UiPromptModalComponent,
|
|
||||||
title: 'Scannen',
|
|
||||||
data: {
|
|
||||||
message: 'Diese Eingabemaske dient nur zu Entwicklungs und Testzwecken.',
|
|
||||||
placeholder: 'Scan Code',
|
|
||||||
confirmText: 'weiter',
|
|
||||||
cancelText: 'abbrechen',
|
|
||||||
} as PromptModalData,
|
|
||||||
});
|
|
||||||
|
|
||||||
const sub = modalRef.afterClosed$.subscribe((result) => {
|
|
||||||
observer.next(result.data);
|
|
||||||
observer.complete();
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
modalRef.close();
|
|
||||||
sub.unsubscribe();
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
<div class="scanner-container" #scanContainer></div>
|
|
||||||
<button class="close-scanner" type="button" (click)="close()">
|
|
||||||
Scan abbrechen
|
|
||||||
</button>
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
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';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-scandit-overlay',
|
|
||||||
templateUrl: 'scandit-overlay.component.html',
|
|
||||||
styleUrls: ['scandit-overlay.component.css'],
|
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
||||||
})
|
|
||||||
export class ScanditOverlayComponent implements AfterViewInit, OnDestroy {
|
|
||||||
private _barcodePicker: BarcodePicker;
|
|
||||||
|
|
||||||
private _onScan?: (code: string) => void;
|
|
||||||
|
|
||||||
private _onClose?: () => void;
|
|
||||||
|
|
||||||
@ViewChild('scanContainer', { read: ElementRef, static: true }) scanContainer: ElementRef;
|
|
||||||
|
|
||||||
constructor(private _zone: NgZone, private _modal: UiModalService) {}
|
|
||||||
|
|
||||||
ngAfterViewInit(): void {
|
|
||||||
this.createBarcodePicker()
|
|
||||||
.then(() => {
|
|
||||||
this._barcodePicker.on('scan', (scanResult) => {
|
|
||||||
this._zone.run(() => this.handleScanrResult(scanResult));
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.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());
|
|
||||||
}
|
|
||||||
|
|
||||||
getScanSettings(): ScanSettings {
|
|
||||||
return new ScanSettings({
|
|
||||||
blurryRecognition: false,
|
|
||||||
|
|
||||||
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,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onScan(fn: (code: string) => void) {
|
|
||||||
this._onScan = fn;
|
|
||||||
}
|
|
||||||
|
|
||||||
onClose(fn: () => void) {
|
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
/*
|
|
||||||
* Public API Surface of scan
|
|
||||||
*/
|
|
||||||
|
|
||||||
export * from './lib/scandit';
|
|
||||||
export * from './lib/dev.scan-adapter';
|
|
||||||
export * from './lib/native.scan-adapter';
|
|
||||||
export * from './lib/scan-adapter';
|
|
||||||
export * from './lib/scan.module';
|
|
||||||
export * from './lib/scan.service';
|
|
||||||
export * from './lib/tokens';
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
|
||||||
{
|
|
||||||
"extends": "../../../tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "../../../out-tsc/lib",
|
|
||||||
"declaration": true,
|
|
||||||
"declarationMap": true,
|
|
||||||
"inlineSources": true,
|
|
||||||
"types": [],
|
|
||||||
"lib": [
|
|
||||||
"dom",
|
|
||||||
"es2018"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"exclude": [
|
|
||||||
"src/test.ts",
|
|
||||||
"**/*.spec.ts"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
|
||||||
{
|
|
||||||
"extends": "./tsconfig.lib.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"declarationMap": false
|
|
||||||
},
|
|
||||||
"angularCompilerOptions": {
|
|
||||||
"compilationMode": "partial"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
|
||||||
{
|
|
||||||
"extends": "../../../tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "../../../out-tsc/spec",
|
|
||||||
"types": [
|
|
||||||
"jasmine"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"**/*.spec.ts",
|
|
||||||
"**/*.d.ts"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
# ProductImage
|
|
||||||
|
|
||||||
This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 10.1.2.
|
|
||||||
|
|
||||||
## Code scaffolding
|
|
||||||
|
|
||||||
Run `ng generate component component-name --project product-image` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project product-image`.
|
|
||||||
|
|
||||||
> Note: Don't forget to add `--project product-image` or else it will be added to the default project in your `angular.json` file.
|
|
||||||
|
|
||||||
## Build
|
|
||||||
|
|
||||||
Run `ng build product-image` to build the project. The build artifacts will be stored in the `dist/` directory.
|
|
||||||
|
|
||||||
## Publishing
|
|
||||||
|
|
||||||
After building your library with `ng build product-image`, go to the dist folder `cd dist/product-image` and run `npm publish`.
|
|
||||||
|
|
||||||
## Running unit tests
|
|
||||||
|
|
||||||
Run `ng test product-image` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
|
||||||
|
|
||||||
## Further help
|
|
||||||
|
|
||||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
|
||||||
"dest": "../../../dist/cdn/product-image",
|
|
||||||
"lib": {
|
|
||||||
"entryFile": "src/public-api.ts"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@cdn/product-image",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"peerDependencies": {
|
|
||||||
"@angular/common": "^10.1.2",
|
|
||||||
"@angular/core": "^10.1.2"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"tslib": "^2.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
/*
|
|
||||||
* Public API Surface of product-image
|
|
||||||
*/
|
|
||||||
|
|
||||||
export * from './lib/product-image.service';
|
|
||||||
export * from './lib/product-image.module';
|
|
||||||
export * from './lib/product-image.pipe';
|
|
||||||
export * from './lib/product-image-navigation.directive';
|
|
||||||
export * from './lib/tokens';
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
|
||||||
{
|
|
||||||
"extends": "../../../tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "../../../out-tsc/lib",
|
|
||||||
"declaration": true,
|
|
||||||
"declarationMap": true,
|
|
||||||
"inlineSources": true,
|
|
||||||
"types": [],
|
|
||||||
"lib": [
|
|
||||||
"dom",
|
|
||||||
"es2018"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"angularCompilerOptions": {
|
|
||||||
"skipTemplateCodegen": true,
|
|
||||||
"strictMetadataEmit": true,
|
|
||||||
"enableResourceInlining": true
|
|
||||||
},
|
|
||||||
"exclude": [
|
|
||||||
"src/test.ts",
|
|
||||||
"**/*.spec.ts"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
|
||||||
{
|
|
||||||
"extends": "./tsconfig.lib.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"declarationMap": false
|
|
||||||
},
|
|
||||||
"angularCompilerOptions": {
|
|
||||||
"compilationMode": "partial"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
|
||||||
{
|
|
||||||
"extends": "../../../tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "../../../out-tsc/spec",
|
|
||||||
"types": [
|
|
||||||
"jasmine"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"**/*.spec.ts",
|
|
||||||
"**/*.d.ts"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../../../tslint.json",
|
|
||||||
"rules": {
|
|
||||||
"directive-selector": [
|
|
||||||
true,
|
|
||||||
"attribute",
|
|
||||||
"cdn",
|
|
||||||
"camelCase"
|
|
||||||
],
|
|
||||||
"component-selector": [
|
|
||||||
true,
|
|
||||||
"element",
|
|
||||||
"cdn",
|
|
||||||
"kebab-case"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
# Core
|
|
||||||
|
|
||||||
This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 15.0.0.
|
|
||||||
|
|
||||||
## Code scaffolding
|
|
||||||
|
|
||||||
Run `ng generate component component-name --project core` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project core`.
|
|
||||||
|
|
||||||
> Note: Don't forget to add `--project core` or else it will be added to the default project in your `angular.json` file.
|
|
||||||
|
|
||||||
## Build
|
|
||||||
|
|
||||||
Run `ng build core` to build the project. The build artifacts will be stored in the `dist/` directory.
|
|
||||||
|
|
||||||
## Publishing
|
|
||||||
|
|
||||||
After building your library with `ng build core`, go to the dist folder `cd dist/core` and run `npm publish`.
|
|
||||||
|
|
||||||
## Running unit tests
|
|
||||||
|
|
||||||
Run `ng test core` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
|
||||||
|
|
||||||
## Further help
|
|
||||||
|
|
||||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
|
||||||
"dest": "../../../dist/core/application",
|
|
||||||
"lib": {
|
|
||||||
"entryFile": "src/public-api.ts"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
// start:ng42.barrel
|
|
||||||
export * from './application.module';
|
|
||||||
export * from './application.service';
|
|
||||||
export * from './defs';
|
|
||||||
export * from './store';
|
|
||||||
// end:ng42.barrel
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
import { createAction, props } from '@ngrx/store';
|
|
||||||
import { ApplicationProcess } from '..';
|
|
||||||
|
|
||||||
const prefix = '[CORE-APPLICATION]';
|
|
||||||
|
|
||||||
export const setTitle = createAction(`${prefix} Set Title`, props<{ title: string }>());
|
|
||||||
|
|
||||||
export const setSection = createAction(`${prefix} Set Section`, props<{ section: 'customer' | 'branch' }>());
|
|
||||||
|
|
||||||
export const addProcess = createAction(`${prefix} Add Process`, props<{ process: ApplicationProcess }>());
|
|
||||||
|
|
||||||
export const removeProcess = createAction(`${prefix} Remove Process`, props<{ processId: 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 patchProcessData = createAction(`${prefix} Patch Process Data`, props<{ processId: number; data: Record<string, any> }>());
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
import { ApplicationState } from './application.state';
|
|
||||||
import { ApplicationProcess } from '../defs';
|
|
||||||
import * as selectors from './application.selectors';
|
|
||||||
|
|
||||||
describe('applicationSelectors', () => {
|
|
||||||
it('should select the processes', () => {
|
|
||||||
const processes: ApplicationProcess[] = [{ id: 1, name: 'Vorgang 1', section: 'customer' }];
|
|
||||||
const state: ApplicationState = {
|
|
||||||
processes,
|
|
||||||
section: 'customer',
|
|
||||||
};
|
|
||||||
expect(selectors.selectProcesses.projector(state)).toEqual(processes);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should select the section', () => {
|
|
||||||
const state: ApplicationState = {
|
|
||||||
processes: [],
|
|
||||||
section: 'customer',
|
|
||||||
};
|
|
||||||
expect(selectors.selectSection.projector(state)).toEqual('customer');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should select the activatedProcess', () => {
|
|
||||||
const processes: ApplicationProcess[] = [
|
|
||||||
{ id: 1, name: 'Vorgang 1', section: 'customer', activated: 100 },
|
|
||||||
{ id: 2, name: 'Vorgang 2', section: 'customer', activated: 300 },
|
|
||||||
{ id: 3, name: 'Vorgang 3', section: 'customer', activated: 200 },
|
|
||||||
];
|
|
||||||
const state: ApplicationState = {
|
|
||||||
processes,
|
|
||||||
section: 'customer',
|
|
||||||
};
|
|
||||||
expect(selectors.selectActivatedProcess.projector(state)).toEqual(processes[1]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
/*
|
|
||||||
* Public API Surface of application
|
|
||||||
*/
|
|
||||||
|
|
||||||
export * from './lib';
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
|
||||||
"dest": "../../../dist/core/auth",
|
|
||||||
"lib": {
|
|
||||||
"entryFile": "src/public-api.ts"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,130 +0,0 @@
|
|||||||
import { coerceArray, coerceStringArray } from '@angular/cdk/coercion';
|
|
||||||
import { 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';
|
|
||||||
|
|
||||||
@Injectable({
|
|
||||||
providedIn: 'root',
|
|
||||||
})
|
|
||||||
export class AuthService {
|
|
||||||
private readonly _initialized = new BehaviorSubject<boolean>(false);
|
|
||||||
get initialized$() {
|
|
||||||
return this._initialized.asObservable();
|
|
||||||
}
|
|
||||||
|
|
||||||
private _authConfig: AuthConfig;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private _config: Config,
|
|
||||||
private readonly _oAuthService: OAuthService,
|
|
||||||
) {
|
|
||||||
this._oAuthService.events?.subscribe((event) => {
|
|
||||||
if (event.type === 'token_received') {
|
|
||||||
console.log('SSO Token Expiration:', new Date(this._oAuthService.getAccessTokenExpiration()));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async init() {
|
|
||||||
if (this._initialized.getValue()) {
|
|
||||||
throw new Error('AuthService is already initialized');
|
|
||||||
}
|
|
||||||
|
|
||||||
this._authConfig = this._config.get('@core/auth');
|
|
||||||
|
|
||||||
this._authConfig.redirectUri = window.location.origin;
|
|
||||||
|
|
||||||
this._authConfig.silentRefreshRedirectUri = window.location.origin + '/silent-refresh.html';
|
|
||||||
this._authConfig.useSilentRefresh = true;
|
|
||||||
|
|
||||||
this._oAuthService.configure(this._authConfig);
|
|
||||||
this._oAuthService.tokenValidationHandler = new JwksValidationHandler();
|
|
||||||
|
|
||||||
this._oAuthService.setupAutomaticSilentRefresh();
|
|
||||||
try {
|
|
||||||
await this._oAuthService.loadDiscoveryDocumentAndTryLogin();
|
|
||||||
} catch (error) {
|
|
||||||
this.login();
|
|
||||||
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._initialized.next(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
isAuthenticated() {
|
|
||||||
return this._oAuthService.hasValidIdToken();
|
|
||||||
}
|
|
||||||
|
|
||||||
getToken() {
|
|
||||||
return this._oAuthService.getAccessToken();
|
|
||||||
}
|
|
||||||
|
|
||||||
getClaims() {
|
|
||||||
const token = this._oAuthService.getAccessToken();
|
|
||||||
return this.parseJwt(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
getClaimByKey(key: string) {
|
|
||||||
const claims = this.getClaims();
|
|
||||||
if (isNullOrUndefined(claims)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return claims[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
parseJwt(token: string) {
|
|
||||||
if (isNullOrUndefined(token)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const base64Url = token.split('.')[1];
|
|
||||||
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
|
|
||||||
|
|
||||||
const encoded = window.atob(base64);
|
|
||||||
return JSON.parse(encoded);
|
|
||||||
}
|
|
||||||
|
|
||||||
login() {
|
|
||||||
this._oAuthService.initLoginFlow();
|
|
||||||
}
|
|
||||||
|
|
||||||
setKeyCardToken(token: string) {
|
|
||||||
this._oAuthService.customQueryParams = {
|
|
||||||
temp_token: token,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async logout() {
|
|
||||||
await this._oAuthService.revokeTokenAndLogout();
|
|
||||||
// asapScheduler.schedule(() => {
|
|
||||||
// window.location.reload();
|
|
||||||
// }, 250);
|
|
||||||
}
|
|
||||||
|
|
||||||
hasRole(role: string | string[]) {
|
|
||||||
const roles = coerceArray(role);
|
|
||||||
|
|
||||||
const userRoles = this.getClaimByKey('role');
|
|
||||||
|
|
||||||
if (isNullOrUndefined(userRoles)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return roles.every((r) => userRoles.includes(r));
|
|
||||||
}
|
|
||||||
|
|
||||||
async refresh() {
|
|
||||||
try {
|
|
||||||
if (this._authConfig.responseType.includes('code') && this._authConfig.scope.includes('offline_access')) {
|
|
||||||
await this._oAuthService.refreshToken();
|
|
||||||
} else {
|
|
||||||
await this._oAuthService.silentRefresh();
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
// start:ng42.barrel
|
|
||||||
export * from './auth.module';
|
|
||||||
export * from './auth.service';
|
|
||||||
// end:ng42.barrel
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
/*
|
|
||||||
* Public API Surface of auth
|
|
||||||
*/
|
|
||||||
|
|
||||||
export * from './lib';
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
|
||||||
"dest": "../../../dist/core/breadcrumb",
|
|
||||||
"lib": {
|
|
||||||
"entryFile": "src/public-api.ts"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
describe('Breadcrumb Actions', () => {});
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
import * as selector from './breadcrumb.selectors';
|
|
||||||
import * as action from './breadcrumb.actions';
|
|
||||||
import { breadcrumbReducer } from './breadcrumb.reducer';
|
|
||||||
|
|
||||||
import { BreadcrumbState, INIT } from './breadcrumb.state';
|
|
||||||
|
|
||||||
describe('Breadcrumb Selectors', () => {
|
|
||||||
let state: BreadcrumbState;
|
|
||||||
|
|
||||||
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' },
|
|
||||||
})
|
|
||||||
);
|
|
||||||
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' } })
|
|
||||||
);
|
|
||||||
state = breadcrumbReducer(
|
|
||||||
state,
|
|
||||||
action.addBreadcrumb({
|
|
||||||
breadcrumb: { id: 5, key: 'unit-test-3', path: '', name: 'Unit Test 1', tags: ['details'], section: 'customer' },
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('selectBreadcrumbsByKey', () => {
|
|
||||||
it('should return all breadcrumbs with the key unit-test-1', () => {
|
|
||||||
const fixture = selector.selectBreadcrumbsByKey.projector(Object.values(state.entities), 'unit-test-1');
|
|
||||||
expect(fixture.length).toBe(2);
|
|
||||||
expect(fixture[0].key).toBe('unit-test-1');
|
|
||||||
expect(fixture[1].key).toBe('unit-test-1');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('selectBreadcrumbsByKeyAndTag', () => {
|
|
||||||
it('should return all breadcrumbs with the key unit-test-3 and tag details', () => {
|
|
||||||
const fixture = selector.selectBreadcrumbsByKeyAndTag.projector(Object.values(state.entities), {
|
|
||||||
key: 'unit-test-3',
|
|
||||||
tag: 'details',
|
|
||||||
});
|
|
||||||
expect(fixture.length).toBe(1);
|
|
||||||
expect(fixture[0].key).toBe('unit-test-3');
|
|
||||||
expect(fixture[0].tags).toContain('details');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
/*
|
|
||||||
* Public API Surface of breadcrumb
|
|
||||||
*/
|
|
||||||
|
|
||||||
export * from './lib/breadcrumb.service';
|
|
||||||
export * from './lib/core-breadcrumb.module';
|
|
||||||
export * from './lib/defs';
|
|
||||||
7
apps/core/cache/ng-package.json
vendored
7
apps/core/cache/ng-package.json
vendored
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
|
||||||
"dest": "../../../dist/core/cache",
|
|
||||||
"lib": {
|
|
||||||
"entryFile": "src/public-api.ts"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
4
apps/core/cache/src/lib/cache-options.ts
vendored
4
apps/core/cache/src/lib/cache-options.ts
vendored
@@ -1,4 +0,0 @@
|
|||||||
export interface CacheOptions {
|
|
||||||
ttl?: number;
|
|
||||||
persist?: boolean;
|
|
||||||
}
|
|
||||||
116
apps/core/cache/src/lib/cache.service.ts
vendored
116
apps/core/cache/src/lib/cache.service.ts
vendored
@@ -1,116 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { CacheOptions } from './cache-options';
|
|
||||||
import { Cached } from './cached';
|
|
||||||
import { interval } from 'rxjs';
|
|
||||||
|
|
||||||
@Injectable({
|
|
||||||
providedIn: 'root',
|
|
||||||
})
|
|
||||||
export class CacheService {
|
|
||||||
constructor() {
|
|
||||||
this._registerCleanupTask();
|
|
||||||
}
|
|
||||||
|
|
||||||
_registerCleanupTask() {
|
|
||||||
this.cleanup();
|
|
||||||
interval(1000 * 60).subscribe(() => {
|
|
||||||
this.cleanup();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
set<T>(token: Object, data: T, options?: CacheOptions) {
|
|
||||||
const persist = options?.persist;
|
|
||||||
const ttl = options?.ttl;
|
|
||||||
const cached: Cached = {
|
|
||||||
data,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (ttl) {
|
|
||||||
cached.until = Date.now() + ttl;
|
|
||||||
} else {
|
|
||||||
cached.until = Date.now() + 1000 * 60 * 60 * 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (persist) {
|
|
||||||
localStorage.setItem(this.getKey(token), this.serialize(cached));
|
|
||||||
} else {
|
|
||||||
sessionStorage.setItem(this.getKey(token), this.serialize(cached));
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.freeze(cached);
|
|
||||||
return cached;
|
|
||||||
}
|
|
||||||
|
|
||||||
get<T = any>(token: Object, from?: 'session' | 'persist'): T {
|
|
||||||
let cached: Cached;
|
|
||||||
|
|
||||||
if (from === 'session') {
|
|
||||||
cached = this.deserialize(sessionStorage.getItem(this.getKey(token)));
|
|
||||||
} else if (from === 'persist') {
|
|
||||||
cached = this.deserialize(localStorage.getItem(this.getKey(token)));
|
|
||||||
} else {
|
|
||||||
cached = this.deserialize(sessionStorage.getItem(this.getKey(token))) || this.deserialize(localStorage.getItem(this.getKey(token)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cached) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cached.until < Date.now()) {
|
|
||||||
this.delete(token, from);
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
return cached.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete(token: Object, from: 'session' | 'persist' = 'session') {
|
|
||||||
if (from === 'session') {
|
|
||||||
sessionStorage.removeItem(this.getKey(token));
|
|
||||||
} else if (from === 'persist') {
|
|
||||||
localStorage.removeItem(this.getKey(token));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private getKey(token: Object) {
|
|
||||||
const key = `CacheService_` + this.hash(JSON.stringify(token));
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
private hash(data: string): string {
|
|
||||||
let hash = 0;
|
|
||||||
for (let i = 0; i < data.length; i++) {
|
|
||||||
hash = data.charCodeAt(i) + ((hash << 5) - hash);
|
|
||||||
}
|
|
||||||
return hash.toString(16);
|
|
||||||
}
|
|
||||||
|
|
||||||
private serialize(data: Cached): string {
|
|
||||||
return JSON.stringify(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
private deserialize(data: string): Cached {
|
|
||||||
return JSON.parse(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup() {
|
|
||||||
// get all keys created by this service by looking for the service name and remove the entries
|
|
||||||
// that ttl is expired
|
|
||||||
let localStorageKeys = Object.keys(localStorage).filter((key) => key.startsWith('CacheService_'));
|
|
||||||
let seesionStorageKeys = Object.keys(sessionStorage).filter((key) => key.startsWith('CacheService_'));
|
|
||||||
|
|
||||||
localStorageKeys.forEach((key) => {
|
|
||||||
const cached = this.deserialize(localStorage.getItem(key));
|
|
||||||
if (cached.until < Date.now()) {
|
|
||||||
localStorage.removeItem(key);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
seesionStorageKeys.forEach((key) => {
|
|
||||||
const cached = this.deserialize(sessionStorage.getItem(key));
|
|
||||||
if (cached.until < Date.now()) {
|
|
||||||
sessionStorage.removeItem(key);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
4
apps/core/cache/src/lib/cached.ts
vendored
4
apps/core/cache/src/lib/cached.ts
vendored
@@ -1,4 +0,0 @@
|
|||||||
export interface Cached {
|
|
||||||
until?: number;
|
|
||||||
data?: any;
|
|
||||||
}
|
|
||||||
6
apps/core/cache/src/public-api.ts
vendored
6
apps/core/cache/src/public-api.ts
vendored
@@ -1,6 +0,0 @@
|
|||||||
/*
|
|
||||||
* Public API Surface of cache
|
|
||||||
*/
|
|
||||||
|
|
||||||
export * from './lib/cache.service';
|
|
||||||
export * from './lib/cache.module';
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
|
||||||
"dest": "../../../dist/core/command",
|
|
||||||
"lib": {
|
|
||||||
"entryFile": "src/public-api.ts"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import { ModuleWithProviders, NgModule, Provider, Type } from '@angular/core';
|
|
||||||
import { ActionHandler } from './action-handler.interface';
|
|
||||||
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 }))];
|
|
||||||
}
|
|
||||||
|
|
||||||
@NgModule({})
|
|
||||||
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 }))],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static forChild(actionHandlers: Type<ActionHandler>[]): ModuleWithProviders<CoreCommandModule> {
|
|
||||||
return {
|
|
||||||
ngModule: CoreCommandModule,
|
|
||||||
providers: [CommandService, actionHandlers.map((handler) => ({ provide: FEATURE_ACTION_HANDLERS, useClass: handler, multi: true }))],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
// start:ng42.barrel
|
|
||||||
export * from './action-handler.interface';
|
|
||||||
export * from './command.module';
|
|
||||||
export * from './command.service';
|
|
||||||
export * from './tokens';
|
|
||||||
// end:ng42.barrel
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
/*
|
|
||||||
* Public API Surface of command
|
|
||||||
*/
|
|
||||||
|
|
||||||
export * from './lib';
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
|
||||||
"dest": "../../../dist/core/config",
|
|
||||||
"lib": {
|
|
||||||
"entryFile": "src/public-api.ts"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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,13 +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,8 +0,0 @@
|
|||||||
// start:ng42.barrel
|
|
||||||
export * from './config-module-options';
|
|
||||||
export * from './config.module';
|
|
||||||
export * from './config';
|
|
||||||
export * from './tokens';
|
|
||||||
export * from './config-loaders';
|
|
||||||
export * from './utils';
|
|
||||||
// end:ng42.barrel
|
|
||||||
@@ -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
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
import { pick } from './pick';
|
|
||||||
|
|
||||||
describe('pick', () => {
|
|
||||||
it('should pick properties from the 1st level from the object', () => {
|
|
||||||
const obj = {
|
|
||||||
foo: 'bar',
|
|
||||||
};
|
|
||||||
expect(pick('foo', obj)).toEqual('bar');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should pick properties from the 2nd level from the object', () => {
|
|
||||||
const obj = {
|
|
||||||
foo: {
|
|
||||||
bar: 'baz',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
expect(pick('foo.bar', obj)).toEqual('baz');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should pick properties from the 3rd level from the object', () => {
|
|
||||||
const obj = {
|
|
||||||
foo: {
|
|
||||||
bar: {
|
|
||||||
baz: 'qux',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
expect(pick('foo.bar.baz', obj)).toEqual('qux');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an error of obj is not an object', () => {
|
|
||||||
expect(() => pick('foo', 'bar')).toThrowError(`bar is not an object`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return undefined if the property is not found', () => {
|
|
||||||
const obj = {
|
|
||||||
foo: 'bar',
|
|
||||||
};
|
|
||||||
expect(pick('bar', obj)).toEqual(undefined);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/**
|
|
||||||
* Pick a value from an object at a given path.
|
|
||||||
* @param path path of the value to pick
|
|
||||||
* @param obj object to pick from
|
|
||||||
* @returns the value at the path or undefined
|
|
||||||
* @throws if obj is not an object
|
|
||||||
*/
|
|
||||||
export function pick<T = any>(path: string, obj: Object): T {
|
|
||||||
const paths = path.split('.');
|
|
||||||
|
|
||||||
// check if obj is null or undefined
|
|
||||||
if (obj == null) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if obj is of type object and not an array
|
|
||||||
// and throw an error if not
|
|
||||||
if (typeof obj !== 'object' || Array.isArray(obj)) {
|
|
||||||
throw new Error(`${obj} is not an object`);
|
|
||||||
}
|
|
||||||
|
|
||||||
let result = obj;
|
|
||||||
|
|
||||||
// loop through the path and pick the value
|
|
||||||
// early exit if the path is empty
|
|
||||||
for (const path of paths) {
|
|
||||||
result = result[path];
|
|
||||||
if (result == null) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result as T;
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
/*
|
|
||||||
* Public API Surface of config
|
|
||||||
*/
|
|
||||||
|
|
||||||
export * from './lib';
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
|
||||||
"dest": "../../../dist/core/environment",
|
|
||||||
"lib": {
|
|
||||||
"entryFile": "src/public-api.ts"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
/*
|
|
||||||
* Public API Surface of environment
|
|
||||||
*/
|
|
||||||
|
|
||||||
export * from './lib/environment.service';
|
|
||||||
export * from './lib/environment.module';
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
|
||||||
"dest": "../../../dist/core/logger",
|
|
||||||
"lib": {
|
|
||||||
"entryFile": "src/public-api.ts"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
// start:ng42.barrel
|
|
||||||
export * from './console-log.provider';
|
|
||||||
export * from './log-level';
|
|
||||||
export * from './log.provider';
|
|
||||||
export * from './logger.module';
|
|
||||||
export * from './logger.service';
|
|
||||||
export * from './tokens';
|
|
||||||
// end:ng42.barrel
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
/*
|
|
||||||
* Public API Surface of logger
|
|
||||||
*/
|
|
||||||
|
|
||||||
export * from './lib';
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
|
|
||||||
"dest": "../../dist/core",
|
|
||||||
"lib": {
|
|
||||||
"entryFile": "src/public-api.ts"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "core",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"peerDependencies": {
|
|
||||||
"@angular/common": "^15.0.0",
|
|
||||||
"@angular/core": "^15.0.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"tslib": "^2.3.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
|
||||||
"dest": "../../../dist/core/signalr",
|
|
||||||
"lib": {
|
|
||||||
"entryFile": "src/public-api.ts"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
/*
|
|
||||||
* Public API Surface of signalr
|
|
||||||
*/
|
|
||||||
|
|
||||||
export * from './lib/signalr-hub-options';
|
|
||||||
export * from './lib/signalr.hub';
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { CoreComponent } from './core.component';
|
|
||||||
|
|
||||||
describe('CoreComponent', () => {
|
|
||||||
let component: CoreComponent;
|
|
||||||
let fixture: ComponentFixture<CoreComponent>;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await TestBed.configureTestingModule({
|
|
||||||
declarations: [CoreComponent],
|
|
||||||
}).compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(CoreComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
import { Component } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'lib-core',
|
|
||||||
template: `
|
|
||||||
<p>
|
|
||||||
core works!
|
|
||||||
</p>
|
|
||||||
`,
|
|
||||||
styles: [],
|
|
||||||
})
|
|
||||||
export class CoreComponent {}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { CoreComponent } from './core.component';
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
declarations: [CoreComponent],
|
|
||||||
imports: [],
|
|
||||||
exports: [CoreComponent],
|
|
||||||
})
|
|
||||||
export class CoreModule {}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { CoreService } from './core.service';
|
|
||||||
|
|
||||||
describe('CoreService', () => {
|
|
||||||
let service: CoreService;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
TestBed.configureTestingModule({});
|
|
||||||
service = TestBed.inject(CoreService);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be created', () => {
|
|
||||||
expect(service).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
|
|
||||||
@Injectable({
|
|
||||||
providedIn: 'root',
|
|
||||||
})
|
|
||||||
export class CoreService {
|
|
||||||
constructor() {}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
/*
|
|
||||||
* Public API Surface of core
|
|
||||||
*/
|
|
||||||
|
|
||||||
export * from './lib/core.service';
|
|
||||||
export * from './lib/core.component';
|
|
||||||
export * from './lib/core.module';
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
|
||||||
{
|
|
||||||
"extends": "../../tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "../../out-tsc/lib",
|
|
||||||
"declaration": true,
|
|
||||||
"declarationMap": true,
|
|
||||||
"inlineSources": true,
|
|
||||||
"types": []
|
|
||||||
},
|
|
||||||
"exclude": [
|
|
||||||
"**/*.spec.ts"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
|
||||||
{
|
|
||||||
"extends": "./tsconfig.lib.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"declarationMap": false
|
|
||||||
},
|
|
||||||
"angularCompilerOptions": {
|
|
||||||
"compilationMode": "partial"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
|
||||||
{
|
|
||||||
"extends": "../../tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "../../out-tsc/spec",
|
|
||||||
"types": [
|
|
||||||
"jasmine"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"**/*.spec.ts",
|
|
||||||
"**/*.d.ts"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
# Availability
|
|
||||||
|
|
||||||
This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 10.1.2.
|
|
||||||
|
|
||||||
## Code scaffolding
|
|
||||||
|
|
||||||
Run `ng generate component component-name --project availability` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project availability`.
|
|
||||||
|
|
||||||
> Note: Don't forget to add `--project availability` or else it will be added to the default project in your `angular.json` file.
|
|
||||||
|
|
||||||
## Build
|
|
||||||
|
|
||||||
Run `ng build availability` to build the project. The build artifacts will be stored in the `dist/` directory.
|
|
||||||
|
|
||||||
## Publishing
|
|
||||||
|
|
||||||
After building your library with `ng build availability`, go to the dist folder `cd dist/availability` and run `npm publish`.
|
|
||||||
|
|
||||||
## Running unit tests
|
|
||||||
|
|
||||||
Run `ng test availability` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
|
||||||
|
|
||||||
## Further help
|
|
||||||
|
|
||||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
|
||||||
"dest": "../../../dist/domain/availability",
|
|
||||||
"lib": {
|
|
||||||
"entryFile": "src/public-api.ts"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@domain/availability",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"peerDependencies": {
|
|
||||||
"@angular/common": "^10.1.2",
|
|
||||||
"@angular/core": "^10.1.2"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"tslib": "^2.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { DomainAvailabilityService } from './availability.service';
|
|
||||||
|
|
||||||
describe('AvailabilityService', () => {
|
|
||||||
let service: DomainAvailabilityService;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
TestBed.configureTestingModule({});
|
|
||||||
service = TestBed.inject(DomainAvailabilityService);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be created', () => {
|
|
||||||
expect(service).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,605 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { ItemDTO } from '@swagger/cat';
|
|
||||||
import {
|
|
||||||
AvailabilityDTO,
|
|
||||||
BranchDTO,
|
|
||||||
OLAAvailabilityDTO,
|
|
||||||
StoreCheckoutBranchService,
|
|
||||||
StoreCheckoutSupplierService,
|
|
||||||
SupplierDTO,
|
|
||||||
} from '@swagger/checkout';
|
|
||||||
import { BehaviorSubject, combineLatest, Observable, of } from 'rxjs';
|
|
||||||
import {
|
|
||||||
AvailabilityRequestDTO,
|
|
||||||
AvailabilityService,
|
|
||||||
AvailabilityDTO as SwaggerAvailabilityDTO,
|
|
||||||
AvailabilityType,
|
|
||||||
} from '@swagger/availability';
|
|
||||||
import { AvailabilityDTO as CatAvailabilityDTO } from '@swagger/cat';
|
|
||||||
import { map, shareReplay, switchMap, withLatestFrom, mergeMap, timeout, first } from 'rxjs/operators';
|
|
||||||
import { isArray, memorize } from '@utils/common';
|
|
||||||
import { LogisticianDTO, LogisticianService } from '@swagger/oms';
|
|
||||||
import { ResponseArgsOfIEnumerableOfStockInfoDTO, StockDTO, StockInfoDTO, StockService } from '@swagger/remi';
|
|
||||||
import { PriceDTO } from '@swagger/availability';
|
|
||||||
import { AvailabilityByBranchDTO, ItemData, Ssc } from './defs';
|
|
||||||
import { Availability } from './defs/availability';
|
|
||||||
import { isEmpty } from 'lodash';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class DomainAvailabilityService {
|
|
||||||
// Ticket #3378 Keep Result List Items and Details Page SSC in sync
|
|
||||||
sscs$ = new BehaviorSubject<Array<Ssc>>([]);
|
|
||||||
sscsObs$ = this.sscs$.asObservable();
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private _availabilityService: AvailabilityService,
|
|
||||||
private _logisticanService: LogisticianService,
|
|
||||||
private _stockService: StockService,
|
|
||||||
private _supplierService: StoreCheckoutSupplierService,
|
|
||||||
private _branchService: StoreCheckoutBranchService,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
@memorize({ ttl: 10000 })
|
|
||||||
memorizedAvailabilityShippingAvailability(request: Array<AvailabilityRequestDTO>) {
|
|
||||||
return this._availabilityService.AvailabilityShippingAvailability(request).pipe(shareReplay(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
@memorize()
|
|
||||||
getSuppliers(): Observable<SupplierDTO[]> {
|
|
||||||
return this._supplierService.StoreCheckoutSupplierGetSuppliers({}).pipe(
|
|
||||||
map((response) => response.result),
|
|
||||||
shareReplay(1),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@memorize()
|
|
||||||
getTakeAwaySupplier(): Observable<SupplierDTO> {
|
|
||||||
return this._supplierService.StoreCheckoutSupplierGetSuppliers({}).pipe(
|
|
||||||
map(({ result }) => result?.find((supplier) => supplier?.supplierNumber === 'F')),
|
|
||||||
shareReplay(1),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@memorize()
|
|
||||||
getBranches(): Observable<BranchDTO[]> {
|
|
||||||
return this._branchService.StoreCheckoutBranchGetBranches({}).pipe(
|
|
||||||
map((response) => response.result),
|
|
||||||
shareReplay(1),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@memorize()
|
|
||||||
getStockByBranch(branchId: number): Observable<StockDTO> {
|
|
||||||
return this._stockService.StockGetStocksByBranch({ branchId }).pipe(
|
|
||||||
map((response) => response.result),
|
|
||||||
map((result) => result?.find((_) => true)),
|
|
||||||
shareReplay(1),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@memorize()
|
|
||||||
getDefaultStock(): Observable<StockDTO> {
|
|
||||||
return this._stockService.StockCurrentStock().pipe(
|
|
||||||
map((response) => response.result),
|
|
||||||
shareReplay(1),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@memorize()
|
|
||||||
getDefaultBranch(): Observable<BranchDTO> {
|
|
||||||
return this._stockService.StockCurrentBranch().pipe(
|
|
||||||
map((response) => ({
|
|
||||||
id: response.result.id,
|
|
||||||
name: response.result.name,
|
|
||||||
address: response.result.address,
|
|
||||||
branchType: response.result.branchType,
|
|
||||||
branchNumber: response.result.branchNumber,
|
|
||||||
changed: response.result.changed,
|
|
||||||
created: response.result.created,
|
|
||||||
isDefault: response.result.isDefault,
|
|
||||||
isOnline: response.result.isOnline,
|
|
||||||
key: response.result.key,
|
|
||||||
label: response.result.label,
|
|
||||||
pId: response.result.pId,
|
|
||||||
shortName: response.result.shortName,
|
|
||||||
status: response.result.status,
|
|
||||||
version: response.result.version,
|
|
||||||
})),
|
|
||||||
shareReplay(1),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@memorize({})
|
|
||||||
getLogisticians(): Observable<LogisticianDTO> {
|
|
||||||
return this._logisticanService.LogisticianGetLogisticians({}).pipe(
|
|
||||||
map((response) => response.result?.find((l) => l.logisticianNumber === '2470')),
|
|
||||||
shareReplay(1),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTakeAwayAvailabilityByBranches({
|
|
||||||
branchIds,
|
|
||||||
itemId,
|
|
||||||
price,
|
|
||||||
quantity,
|
|
||||||
}: {
|
|
||||||
branchIds: number[];
|
|
||||||
itemId: number;
|
|
||||||
price: PriceDTO;
|
|
||||||
quantity: number;
|
|
||||||
}): Observable<AvailabilityByBranchDTO[]> {
|
|
||||||
return this._stockService.StockStockRequest({ stockRequest: { branchIds, itemId } }).pipe(
|
|
||||||
map((response) => response.result),
|
|
||||||
withLatestFrom(this.getTakeAwaySupplier()),
|
|
||||||
map(([result, supplier]) => {
|
|
||||||
const availabilities: AvailabilityByBranchDTO[] = result.map((stockInfo) => {
|
|
||||||
return {
|
|
||||||
availableQuantity: stockInfo.availableQuantity,
|
|
||||||
availabilityType: quantity <= stockInfo.inStock ? 1024 : 1, // 1024 (=Available)
|
|
||||||
inStock: stockInfo.inStock,
|
|
||||||
supplierSSC: quantity <= stockInfo.inStock ? '999' : '',
|
|
||||||
supplierSSCText: quantity <= stockInfo.inStock ? 'Filialentnahme' : '',
|
|
||||||
price,
|
|
||||||
supplier: { id: supplier?.id },
|
|
||||||
branchId: stockInfo.branchId,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return availabilities;
|
|
||||||
}),
|
|
||||||
shareReplay(1),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@memorize({ ttl: 10000 })
|
|
||||||
getTakeAwayAvailability({
|
|
||||||
item,
|
|
||||||
quantity,
|
|
||||||
branch,
|
|
||||||
}: {
|
|
||||||
item: ItemData;
|
|
||||||
quantity: number;
|
|
||||||
branch?: BranchDTO;
|
|
||||||
}): Observable<AvailabilityDTO> {
|
|
||||||
const request = !!branch ? this.getStockByBranch(branch.id) : this.getDefaultStock();
|
|
||||||
return request.pipe(
|
|
||||||
switchMap((s) =>
|
|
||||||
combineLatest([
|
|
||||||
this._stockService.StockInStock({ articleIds: [item.itemId], stockId: s.id }),
|
|
||||||
this.getTakeAwaySupplier(),
|
|
||||||
this.getDefaultBranch(),
|
|
||||||
]),
|
|
||||||
),
|
|
||||||
map(([response, supplier, defaultBranch]) => {
|
|
||||||
const price = item?.price;
|
|
||||||
return this._mapToTakeAwayAvailability({ response, supplier, branchId: branch?.id ?? defaultBranch?.id, quantity, price });
|
|
||||||
}),
|
|
||||||
shareReplay(1),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@memorize({ ttl: 10000 })
|
|
||||||
getTakeAwayAvailabilityByBranch({
|
|
||||||
branch,
|
|
||||||
itemId,
|
|
||||||
price,
|
|
||||||
quantity,
|
|
||||||
}: {
|
|
||||||
branch: BranchDTO;
|
|
||||||
itemId: number;
|
|
||||||
price: PriceDTO;
|
|
||||||
quantity: number;
|
|
||||||
}): Observable<AvailabilityDTO> {
|
|
||||||
return combineLatest([
|
|
||||||
this._stockService.StockStockRequest({ stockRequest: { branchIds: [branch.id], itemId } }),
|
|
||||||
this.getTakeAwaySupplier(),
|
|
||||||
]).pipe(
|
|
||||||
map(([response, supplier]) => {
|
|
||||||
return this._mapToTakeAwayAvailability({ response, supplier, branchId: branch.id, quantity, price });
|
|
||||||
}),
|
|
||||||
shareReplay(1),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTakeAwayAvailabilityByEan({
|
|
||||||
eans,
|
|
||||||
price,
|
|
||||||
quantity,
|
|
||||||
branchId,
|
|
||||||
}: {
|
|
||||||
eans: string[];
|
|
||||||
price: PriceDTO;
|
|
||||||
quantity: number;
|
|
||||||
branchId?: number;
|
|
||||||
}): Observable<AvailabilityDTO> {
|
|
||||||
const request = !!branchId ? this.getStockByBranch(branchId) : this.getDefaultStock();
|
|
||||||
return request.pipe(
|
|
||||||
switchMap((s) => this._stockService.StockInStockByEAN({ eans, stockId: s.id })),
|
|
||||||
withLatestFrom(this.getTakeAwaySupplier(), this.getDefaultBranch()),
|
|
||||||
map(([response, supplier, defaultBranch]) => {
|
|
||||||
return this._mapToTakeAwayAvailability({ response, supplier, branchId: branchId ?? defaultBranch.id, quantity, price });
|
|
||||||
}),
|
|
||||||
shareReplay(1),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTakeAwayAvailabilitiesByEans({ eans }: { eans: string[] }): Observable<StockInfoDTO[]> {
|
|
||||||
const eansFiltered = Array.from(new Set(eans));
|
|
||||||
return this.getDefaultStock().pipe(
|
|
||||||
switchMap((s) => this._stockService.StockInStockByEAN({ eans: eansFiltered, stockId: s.id })),
|
|
||||||
withLatestFrom(this.getTakeAwaySupplier(), this.getDefaultBranch()),
|
|
||||||
map((response) => response[0].result),
|
|
||||||
shareReplay(1),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@memorize({ ttl: 10000 })
|
|
||||||
getPickUpAvailability({
|
|
||||||
item,
|
|
||||||
branch,
|
|
||||||
quantity,
|
|
||||||
}: {
|
|
||||||
item: ItemData;
|
|
||||||
quantity: number;
|
|
||||||
branch: BranchDTO;
|
|
||||||
}): Observable<Availability<AvailabilityDTO, SwaggerAvailabilityDTO>> {
|
|
||||||
return this._availabilityService
|
|
||||||
.AvailabilityStoreAvailability([
|
|
||||||
{
|
|
||||||
qty: quantity,
|
|
||||||
ean: item?.ean,
|
|
||||||
itemId: item?.itemId ? String(item?.itemId) : null,
|
|
||||||
shopId: branch?.id,
|
|
||||||
price: item?.price,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
.pipe(
|
|
||||||
map((r) => this._mapToPickUpAvailability(r.result)?.find((_) => true)),
|
|
||||||
shareReplay(1),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@memorize({ ttl: 10000 })
|
|
||||||
getDeliveryAvailability({ item, quantity }: { item: ItemData; quantity: number }): Observable<AvailabilityDTO> {
|
|
||||||
return this.memorizedAvailabilityShippingAvailability([
|
|
||||||
{
|
|
||||||
ean: item?.ean,
|
|
||||||
itemId: item?.itemId ? String(item?.itemId) : null,
|
|
||||||
price: item?.price,
|
|
||||||
qty: quantity,
|
|
||||||
},
|
|
||||||
]).pipe(
|
|
||||||
timeout(5000),
|
|
||||||
map((r) => this._mapToShippingAvailability(r.result)?.find((_) => true)),
|
|
||||||
shareReplay(1),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@memorize({ ttl: 10000 })
|
|
||||||
getDigDeliveryAvailability({ item, quantity }: { item: ItemData; quantity: number }): Observable<AvailabilityDTO> {
|
|
||||||
return this.memorizedAvailabilityShippingAvailability([
|
|
||||||
{
|
|
||||||
qty: quantity,
|
|
||||||
ean: item?.ean,
|
|
||||||
itemId: item?.itemId ? String(item?.itemId) : null,
|
|
||||||
price: item?.price,
|
|
||||||
},
|
|
||||||
]).pipe(
|
|
||||||
timeout(5000),
|
|
||||||
map((r) => {
|
|
||||||
const availabilities = r.result;
|
|
||||||
const preferred = availabilities?.find((f) => f.preferred === 1);
|
|
||||||
|
|
||||||
return {
|
|
||||||
availabilityType: preferred?.status,
|
|
||||||
ssc: preferred?.ssc,
|
|
||||||
sscText: preferred?.sscText,
|
|
||||||
supplier: { id: preferred?.supplierId },
|
|
||||||
isPrebooked: preferred?.isPrebooked,
|
|
||||||
estimatedShippingDate: preferred?.requestStatusCode === '32' ? preferred?.altAt : preferred?.at,
|
|
||||||
estimatedDelivery: preferred?.estimatedDelivery,
|
|
||||||
price: preferred?.price,
|
|
||||||
logistician: { id: preferred?.logisticianId },
|
|
||||||
supplierProductNumber: preferred?.supplierProductNumber,
|
|
||||||
supplierInfo: preferred?.requestStatusCode,
|
|
||||||
lastRequest: preferred?.requested,
|
|
||||||
priceMaintained: preferred?.priceMaintained,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
shareReplay(1),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@memorize({ ttl: 10000 })
|
|
||||||
getB2bDeliveryAvailability({
|
|
||||||
item,
|
|
||||||
quantity,
|
|
||||||
branch,
|
|
||||||
}: {
|
|
||||||
item: ItemData;
|
|
||||||
quantity: number;
|
|
||||||
branch?: BranchDTO;
|
|
||||||
}): Observable<AvailabilityDTO> {
|
|
||||||
const logistician$ = this.getLogisticians();
|
|
||||||
|
|
||||||
const currentBranch$ = this.getDefaultBranch();
|
|
||||||
|
|
||||||
return currentBranch$.pipe(
|
|
||||||
timeout(5000),
|
|
||||||
mergeMap((defaultBranch) =>
|
|
||||||
this.getPickUpAvailability({ item, quantity, branch: branch ?? defaultBranch }).pipe(
|
|
||||||
mergeMap((availability) =>
|
|
||||||
logistician$.pipe(
|
|
||||||
map((logistician) => ({ ...(availability?.length > 0 ? availability[0] : []), logistician: { id: logistician.id } })),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
shareReplay(1),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@memorize({ ttl: 10000 })
|
|
||||||
getDownloadAvailability({ item }: { item: ItemData }): Observable<AvailabilityDTO> {
|
|
||||||
return this.memorizedAvailabilityShippingAvailability([
|
|
||||||
{
|
|
||||||
ean: item?.ean,
|
|
||||||
itemId: item?.itemId ? String(item?.itemId) : null,
|
|
||||||
price: item?.price,
|
|
||||||
qty: 1,
|
|
||||||
},
|
|
||||||
]).pipe(
|
|
||||||
map((r) => {
|
|
||||||
const availabilities = r.result;
|
|
||||||
const preferred = availabilities?.find((f) => f.preferred === 1);
|
|
||||||
|
|
||||||
return {
|
|
||||||
availabilityType: preferred?.status,
|
|
||||||
ssc: preferred?.ssc,
|
|
||||||
sscText: preferred?.sscText,
|
|
||||||
supplier: { id: preferred?.supplierId },
|
|
||||||
isPrebooked: preferred?.isPrebooked,
|
|
||||||
estimatedShippingDate: preferred?.requestStatusCode === '32' ? preferred?.altAt : preferred?.at,
|
|
||||||
price: preferred?.price,
|
|
||||||
supplierProductNumber: preferred?.supplierProductNumber,
|
|
||||||
logistician: { id: preferred?.logisticianId },
|
|
||||||
supplierInfo: preferred?.requestStatusCode,
|
|
||||||
lastRequest: preferred?.requested,
|
|
||||||
priceMaintained: preferred?.priceMaintained,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
shareReplay(1),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@memorize({ ttl: 10000 })
|
|
||||||
getTakeAwayAvailabilities(items: { id: number; price: PriceDTO }[], branchId: number) {
|
|
||||||
return this._stockService.StockGetStocksByBranch({ branchId }).pipe(
|
|
||||||
map((req) => req.result?.find((_) => true)?.id),
|
|
||||||
switchMap((stockId) =>
|
|
||||||
stockId
|
|
||||||
? this._stockService.StockInStock({ articleIds: items.map((i) => i.id), stockId })
|
|
||||||
: of({ result: [] } as ResponseArgsOfIEnumerableOfStockInfoDTO),
|
|
||||||
),
|
|
||||||
timeout(20000),
|
|
||||||
withLatestFrom(this.getTakeAwaySupplier()),
|
|
||||||
map(([response, supplier]) => {
|
|
||||||
return response.result?.map((stockInfo) =>
|
|
||||||
this._mapToTakeAwayAvailabilities({
|
|
||||||
stockInfo,
|
|
||||||
supplier,
|
|
||||||
quantity: 1,
|
|
||||||
price: items?.find((i) => i.id === stockInfo.itemId)?.price,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
shareReplay(1),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@memorize({ ttl: 10000 })
|
|
||||||
getPickUpAvailabilities(payload: AvailabilityRequestDTO[], preferred?: boolean) {
|
|
||||||
return this._availabilityService.AvailabilityStoreAvailability(payload).pipe(
|
|
||||||
timeout(20000),
|
|
||||||
map((response) => (preferred ? this._mapToPickUpAvailability(response.result) : response.result)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@memorize({ ttl: 10000 })
|
|
||||||
getDeliveryAvailabilities(payload: AvailabilityRequestDTO[]) {
|
|
||||||
return this.memorizedAvailabilityShippingAvailability(payload).pipe(
|
|
||||||
timeout(20000),
|
|
||||||
map((response) => this._mapToShippingAvailability(response.result)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@memorize({ ttl: 10000 })
|
|
||||||
getDigDeliveryAvailabilities(payload: AvailabilityRequestDTO[]) {
|
|
||||||
return this.memorizedAvailabilityShippingAvailability(payload).pipe(
|
|
||||||
timeout(20000),
|
|
||||||
map((response) => this._mapToShippingAvailability(response.result)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@memorize({ ttl: 10000 })
|
|
||||||
getB2bDeliveryAvailabilities(payload: AvailabilityRequestDTO[]) {
|
|
||||||
const logistician$ = this.getLogisticians();
|
|
||||||
|
|
||||||
return this.getPickUpAvailabilities(payload, true).pipe(
|
|
||||||
timeout(20000),
|
|
||||||
switchMap((availability) =>
|
|
||||||
logistician$.pipe(map((logistician) => ({ availability: [...availability], logistician: { id: logistician.id } }))),
|
|
||||||
),
|
|
||||||
shareReplay(1),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getPriceForAvailability(
|
|
||||||
purchasingOption: string,
|
|
||||||
catalogAvailability: CatAvailabilityDTO | AvailabilityDTO,
|
|
||||||
availability: AvailabilityDTO,
|
|
||||||
): PriceDTO {
|
|
||||||
switch (purchasingOption) {
|
|
||||||
case 'take-away':
|
|
||||||
return availability?.price || catalogAvailability?.price;
|
|
||||||
case 'delivery':
|
|
||||||
case 'dig-delivery':
|
|
||||||
if (catalogAvailability?.price?.value?.value < availability?.price?.value?.value) {
|
|
||||||
return catalogAvailability?.price;
|
|
||||||
}
|
|
||||||
return availability?.price || catalogAvailability?.price;
|
|
||||||
}
|
|
||||||
return availability?.price;
|
|
||||||
}
|
|
||||||
|
|
||||||
isAvailable({ availability }: { availability: AvailabilityDTO }) {
|
|
||||||
if (availability?.supplier?.id === 16 && availability?.inStock == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return [2, 32, 256, 1024, 2048, 4096].some((code) => availability?.availabilityType === code);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _mapToTakeAwayAvailability({
|
|
||||||
response,
|
|
||||||
supplier,
|
|
||||||
branchId,
|
|
||||||
quantity,
|
|
||||||
price,
|
|
||||||
}: {
|
|
||||||
response: ResponseArgsOfIEnumerableOfStockInfoDTO;
|
|
||||||
supplier: SupplierDTO;
|
|
||||||
branchId: number;
|
|
||||||
quantity: number;
|
|
||||||
price: PriceDTO;
|
|
||||||
}): AvailabilityDTO {
|
|
||||||
const stockInfo = response.result?.find((si) => si.branchId === branchId);
|
|
||||||
const inStock = stockInfo?.inStock ?? 0;
|
|
||||||
const availability: AvailabilityDTO = {
|
|
||||||
availabilityType: quantity <= inStock ? 1024 : 1, // 1024 (=Available)
|
|
||||||
inStock: inStock,
|
|
||||||
supplierSSC: quantity <= inStock ? '999' : '',
|
|
||||||
supplierSSCText: quantity <= inStock ? 'Filialentnahme' : '',
|
|
||||||
price: stockInfo?.retailPrice ?? price, // #4553 Es soll nun immer der retailPrice aus der InStock Abfrage verwendet werden, egal ob "price" empty ist oder nicht
|
|
||||||
supplier: { id: supplier?.id },
|
|
||||||
// TODO: Change after API Update
|
|
||||||
// LH: 2021-03-09 preis Property hat nun ein Fallback auf retailPrice
|
|
||||||
// retailPrice: (stockInfo as any)?.retailPrice,
|
|
||||||
};
|
|
||||||
return availability;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _mapToTakeAwayAvailabilities({
|
|
||||||
stockInfo,
|
|
||||||
quantity,
|
|
||||||
price,
|
|
||||||
supplier,
|
|
||||||
}: {
|
|
||||||
stockInfo: StockInfoDTO;
|
|
||||||
quantity: number;
|
|
||||||
price: PriceDTO;
|
|
||||||
supplier: SupplierDTO;
|
|
||||||
}) {
|
|
||||||
const inStock = stockInfo?.inStock ?? 0;
|
|
||||||
|
|
||||||
const availability = {
|
|
||||||
itemId: stockInfo.itemId,
|
|
||||||
availabilityType: quantity <= inStock ? (1024 as AvailabilityType) : (1 as AvailabilityType), // 1024 (=Available)
|
|
||||||
inStock: inStock,
|
|
||||||
supplierSSC: quantity <= inStock ? '999' : '',
|
|
||||||
supplierSSCText: quantity <= inStock ? 'Filialentnahme' : '',
|
|
||||||
price,
|
|
||||||
supplier: { id: supplier?.id },
|
|
||||||
};
|
|
||||||
return availability;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _mapToPickUpAvailability(availabilities: SwaggerAvailabilityDTO[]): Availability<AvailabilityDTO, SwaggerAvailabilityDTO>[] {
|
|
||||||
if (isArray(availabilities)) {
|
|
||||||
const preferred = availabilities.filter((f) => f.preferred === 1);
|
|
||||||
const totalAvailable = availabilities.reduce((sum, av) => sum + (av?.qty || 0), 0);
|
|
||||||
|
|
||||||
return preferred.map((p) => {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
orderDeadline: p?.orderDeadline,
|
|
||||||
availabilityType: p?.status,
|
|
||||||
ssc: p?.ssc,
|
|
||||||
sscText: p?.sscText,
|
|
||||||
supplier: { id: p?.supplierId },
|
|
||||||
isPrebooked: p?.isPrebooked,
|
|
||||||
estimatedShippingDate: p?.requestStatusCode === '32' ? p?.altAt : p?.at,
|
|
||||||
price: p?.price,
|
|
||||||
inStock: totalAvailable,
|
|
||||||
supplierProductNumber: p?.supplierProductNumber,
|
|
||||||
supplierInfo: p?.requestStatusCode,
|
|
||||||
lastRequest: p?.requested,
|
|
||||||
itemId: p.itemId,
|
|
||||||
priceMaintained: p.priceMaintained,
|
|
||||||
},
|
|
||||||
p,
|
|
||||||
];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _mapToShippingAvailability(availabilities: SwaggerAvailabilityDTO[]): AvailabilityDTO[] {
|
|
||||||
const preferred = availabilities.filter((f) => f.preferred === 1);
|
|
||||||
return preferred.map((p) => {
|
|
||||||
return {
|
|
||||||
availabilityType: p?.status,
|
|
||||||
ssc: p?.ssc,
|
|
||||||
sscText: p?.sscText,
|
|
||||||
isPrebooked: p?.isPrebooked,
|
|
||||||
estimatedShippingDate: p?.requestStatusCode === '32' ? p?.altAt : p?.at,
|
|
||||||
estimatedDelivery: p?.estimatedDelivery,
|
|
||||||
price: p?.price,
|
|
||||||
supplierProductNumber: p?.supplierProductNumber,
|
|
||||||
supplierInfo: p?.requestStatusCode,
|
|
||||||
lastRequest: p?.requested,
|
|
||||||
itemId: p.itemId,
|
|
||||||
priceMaintained: p.priceMaintained,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getInStockByEan(params: { eans: string[]; branchId?: number }): Observable<Record<string, StockInfoDTO>> {
|
|
||||||
let branchId$ = of(params.branchId);
|
|
||||||
|
|
||||||
if (!params.branchId) {
|
|
||||||
branchId$ = this.getDefaultBranch().pipe(
|
|
||||||
first(),
|
|
||||||
map((b) => b.id),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const stock$ = branchId$.pipe(
|
|
||||||
mergeMap((branchId) => this._stockService.StockGetStocksByBranch({ branchId }).pipe(map((response) => response.result?.[0]))),
|
|
||||||
);
|
|
||||||
|
|
||||||
return stock$.pipe(
|
|
||||||
mergeMap((stock) =>
|
|
||||||
this._stockService.StockInStockByEAN({ eans: params.eans, stockId: stock.id }).pipe(
|
|
||||||
map((response) => {
|
|
||||||
const result = response.result ?? [];
|
|
||||||
|
|
||||||
for (const stockInfo of result) {
|
|
||||||
stockInfo.ean = stockInfo.ean;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.reduce<Record<string, StockInfoDTO>>((acc, stockInfo) => {
|
|
||||||
acc[stockInfo.ean] = stockInfo;
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getInStock({ itemIds, branchId }: { itemIds: number[]; branchId: number }): Observable<StockInfoDTO[]> {
|
|
||||||
return this.getStockByBranch(branchId).pipe(
|
|
||||||
mergeMap((stock) =>
|
|
||||||
this._stockService.StockInStock({ articleIds: itemIds, stockId: stock.id }).pipe(map((response) => response.result)),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { AvailabilityDTO } from '@swagger/checkout';
|
|
||||||
|
|
||||||
export interface AvailabilityByBranchDTO extends AvailabilityDTO {
|
|
||||||
availableQuantity?: number;
|
|
||||||
stockId?: number;
|
|
||||||
branchId: number;
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { PriceDTO } from '@swagger/availability';
|
|
||||||
|
|
||||||
export interface ItemData {
|
|
||||||
ean: string;
|
|
||||||
itemId: number;
|
|
||||||
price: PriceDTO;
|
|
||||||
}
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { StockInfoDTO } from '@swagger/remi';
|
|
||||||
import { groupBy, isEqual, uniqWith } from 'lodash';
|
|
||||||
import { BehaviorSubject, combineLatest, Observable, Subject } from 'rxjs';
|
|
||||||
import { buffer, debounceTime, distinctUntilChanged } from 'rxjs/operators';
|
|
||||||
import { DomainAvailabilityService } from './availability.service';
|
|
||||||
|
|
||||||
export type ItemBranch = { itemId: number; branchId: number };
|
|
||||||
export type InStock = ItemBranch & { inStock: number; fetching: boolean };
|
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
|
||||||
export class DomainInStockService {
|
|
||||||
private _inStockQueue = new Subject<ItemBranch>();
|
|
||||||
private _inStockMap = new BehaviorSubject<Record<string, number>>({});
|
|
||||||
private _inStockFetchingMap = new BehaviorSubject<Record<string, boolean>>({});
|
|
||||||
|
|
||||||
constructor(private _availability: DomainAvailabilityService) {
|
|
||||||
const queueBufferTrigger = this._createQueueBufferTrigger();
|
|
||||||
|
|
||||||
this._inStockQueue.pipe(buffer(queueBufferTrigger)).subscribe(this._handleStockDataToFetch);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _createQueueBufferTrigger() {
|
|
||||||
return this._inStockQueue.pipe(debounceTime(1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
private _handleStockDataToFetch = (itemBranchData: ItemBranch[]) => {
|
|
||||||
const unique = uniqWith(itemBranchData, isEqual);
|
|
||||||
if (unique?.length > 0) {
|
|
||||||
this._fetchStockData(unique);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
getKey({ itemId, branchId }: ItemBranch) {
|
|
||||||
return `${itemId}_${branchId}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
getInStock$({ itemId, branchId }: ItemBranch): Observable<InStock> {
|
|
||||||
return new Observable<InStock>((obs) => {
|
|
||||||
if (!(itemId && branchId)) {
|
|
||||||
obs.error(new Error(`ItemId: ${itemId} or BranchId: ${branchId} missing`));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const key = this.getKey({ itemId, branchId });
|
|
||||||
this._addToInStockQueue({ itemId, branchId });
|
|
||||||
|
|
||||||
let _previousValue: InStock;
|
|
||||||
|
|
||||||
const sub = combineLatest([this._inStockMap, this._inStockFetchingMap])
|
|
||||||
.pipe(distinctUntilChanged(isEqual))
|
|
||||||
.subscribe(([inStockMap, inStockFetchingMap]) => {
|
|
||||||
const inStock: InStock = {
|
|
||||||
itemId,
|
|
||||||
branchId,
|
|
||||||
inStock: inStockMap[key],
|
|
||||||
fetching: inStockFetchingMap[key] ?? false,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!isEqual(inStock, _previousValue)) {
|
|
||||||
obs.next(inStock);
|
|
||||||
}
|
|
||||||
|
|
||||||
_previousValue = inStock;
|
|
||||||
});
|
|
||||||
return () => {
|
|
||||||
sub.unsubscribe();
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private _addToInStockQueue({ itemId, branchId }: ItemBranch): void {
|
|
||||||
this._inStockQueue.next({ itemId, branchId });
|
|
||||||
this._setInStockFetching({ itemId, branchId }, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _setInStockFetching({ itemId, branchId }: ItemBranch, value: boolean) {
|
|
||||||
const key = this.getKey({ itemId, branchId });
|
|
||||||
const current = this._inStockFetchingMap.getValue();
|
|
||||||
this._inStockFetchingMap.next({ ...current, [key]: value });
|
|
||||||
}
|
|
||||||
|
|
||||||
private _setInStock({ itemId, branchId }: ItemBranch, inStock: number) {
|
|
||||||
const key = this.getKey({ itemId, branchId });
|
|
||||||
const current = this._inStockMap.getValue();
|
|
||||||
this._inStockMap.next({ ...current, [key]: inStock });
|
|
||||||
}
|
|
||||||
|
|
||||||
private _fetchStockData(itemBranchData: ItemBranch[]) {
|
|
||||||
const grouped = groupBy(itemBranchData, 'branchId');
|
|
||||||
Object.keys(grouped).forEach((key) => {
|
|
||||||
const branchId = Number(key);
|
|
||||||
const itemIds = itemBranchData.filter((itemBranch) => itemBranch.branchId === branchId).map((item) => item.itemId);
|
|
||||||
this._availability
|
|
||||||
.getInStock({ itemIds, branchId })
|
|
||||||
.subscribe(this._fetchStockDataResponse({ itemIds, branchId }), this._fetchStockDataError({ itemIds, branchId }));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private _fetchStockDataResponse = ({ itemIds, branchId }: { itemIds: number[]; branchId: number }) => (stockInfos: StockInfoDTO[]) => {
|
|
||||||
itemIds.forEach((itemId) => {
|
|
||||||
const stockInfo = stockInfos.find((stockInfo) => stockInfo.itemId === itemId && stockInfo.branchId === branchId);
|
|
||||||
let inStock = 0;
|
|
||||||
|
|
||||||
if (stockInfo?.inStock) {
|
|
||||||
inStock = stockInfo.inStock;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._setInStockFetching({ itemId, branchId }, false);
|
|
||||||
this._setInStock({ itemId, branchId }, inStock);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
private _fetchStockDataError = ({ itemIds, branchId }: { itemIds: number[]; branchId: number }) => (error: Error) => {
|
|
||||||
itemIds.forEach((itemId) => {
|
|
||||||
this._setInStockFetching({ itemId, branchId }, false);
|
|
||||||
this._setInStock({ itemId, branchId }, 0);
|
|
||||||
});
|
|
||||||
console.error('DomainInStockService._fetchStockData()', error);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
/*
|
|
||||||
* Public API Surface of availability
|
|
||||||
*/
|
|
||||||
|
|
||||||
export * from './lib/availability.service';
|
|
||||||
export * from './lib/in-stock.service';
|
|
||||||
export * from './lib/availability.module';
|
|
||||||
export * from './lib/defs';
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
|
||||||
{
|
|
||||||
"extends": "../../../tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "../../../out-tsc/lib",
|
|
||||||
"declaration": true,
|
|
||||||
"declarationMap": true,
|
|
||||||
"inlineSources": true,
|
|
||||||
"types": [],
|
|
||||||
"lib": [
|
|
||||||
"dom",
|
|
||||||
"es2018"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"angularCompilerOptions": {
|
|
||||||
"skipTemplateCodegen": true,
|
|
||||||
"strictMetadataEmit": true,
|
|
||||||
"enableResourceInlining": true
|
|
||||||
},
|
|
||||||
"exclude": [
|
|
||||||
"src/test.ts",
|
|
||||||
"**/*.spec.ts"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
|
||||||
{
|
|
||||||
"extends": "./tsconfig.lib.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"declarationMap": false
|
|
||||||
},
|
|
||||||
"angularCompilerOptions": {
|
|
||||||
"compilationMode": "partial"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
|
||||||
{
|
|
||||||
"extends": "../../../tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "../../../out-tsc/spec",
|
|
||||||
"types": [
|
|
||||||
"jasmine"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"**/*.spec.ts",
|
|
||||||
"**/*.d.ts"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../../../tslint.json",
|
|
||||||
"rules": {
|
|
||||||
"directive-selector": [
|
|
||||||
true,
|
|
||||||
"attribute",
|
|
||||||
"lib",
|
|
||||||
"camelCase"
|
|
||||||
],
|
|
||||||
"component-selector": [
|
|
||||||
true,
|
|
||||||
"element",
|
|
||||||
"lib",
|
|
||||||
"kebab-case"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user