mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Merge branch 'develop' into release/4.0
This commit is contained in:
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/)
|
||||||
13
.gitignore
vendored
13
.gitignore
vendored
@@ -1,5 +1,8 @@
|
|||||||
# 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
|
||||||
@@ -50,4 +53,12 @@ testem.log
|
|||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|
||||||
libs/swagger/src/lib/*
|
libs/swagger/src/lib/*
|
||||||
*storybook.log
|
*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
|
||||||
|
|||||||
164
angular.json
164
angular.json
@@ -1,164 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
|
||||||
"version": 1,
|
|
||||||
"newProjectRoot": "apps",
|
|
||||||
"projects": {
|
|
||||||
"isa-app": {
|
|
||||||
"projectType": "application",
|
|
||||||
"schematics": {
|
|
||||||
"@schematics/angular:component": {
|
|
||||||
"style": "scss"
|
|
||||||
},
|
|
||||||
"@schematics/angular:application": {
|
|
||||||
"strict": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": "apps/isa-app",
|
|
||||||
"sourceRoot": "apps/isa-app/src",
|
|
||||||
"prefix": "app",
|
|
||||||
"architect": {
|
|
||||||
"build": {
|
|
||||||
"builder": "@angular-devkit/build-angular:browser",
|
|
||||||
"options": {
|
|
||||||
"allowedCommonJsDependencies": [
|
|
||||||
"lodash",
|
|
||||||
"moment",
|
|
||||||
"jsrsasign",
|
|
||||||
"pdfjs-dist/build/pdf",
|
|
||||||
"pdfjs-dist/web/pdf_viewer",
|
|
||||||
"pdfjs-dist/es5/build/pdf",
|
|
||||||
"pdfjs-dist/es5/web/pdf_viewer"
|
|
||||||
],
|
|
||||||
"outputPath": "dist/isa-app",
|
|
||||||
"index": "apps/isa-app/src/index.html",
|
|
||||||
"main": "apps/isa-app/src/main.ts",
|
|
||||||
"polyfills": "apps/isa-app/src/polyfills.ts",
|
|
||||||
"tsConfig": "apps/isa-app/tsconfig.app.json",
|
|
||||||
"inlineStyleLanguage": "scss",
|
|
||||||
"assets": [
|
|
||||||
"apps/isa-app/src/favicon.ico",
|
|
||||||
"apps/isa-app/src/assets",
|
|
||||||
"apps/isa-app/src/config",
|
|
||||||
"apps/isa-app/src/silent-refresh.html",
|
|
||||||
"apps/isa-app/src/manifest.webmanifest",
|
|
||||||
{
|
|
||||||
"glob": "**/*",
|
|
||||||
"input": "node_modules/scandit-web-datacapture-barcode/build/engine",
|
|
||||||
"output": "scandit"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"styles": [
|
|
||||||
"apps/isa-app/src/styles.scss"
|
|
||||||
],
|
|
||||||
"scripts": [],
|
|
||||||
"serviceWorker": true,
|
|
||||||
"ngswConfigPath": "apps/isa-app/ngsw-config.json"
|
|
||||||
},
|
|
||||||
"configurations": {
|
|
||||||
"production": {
|
|
||||||
"budgets": [
|
|
||||||
{
|
|
||||||
"type": "initial",
|
|
||||||
"maximumWarning": "2mb",
|
|
||||||
"maximumError": "5mb"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "anyComponentStyle",
|
|
||||||
"maximumWarning": "25kb"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"fileReplacements": [
|
|
||||||
{
|
|
||||||
"replace": "apps/isa-app/src/environments/environment.ts",
|
|
||||||
"with": "apps/isa-app/src/environments/environment.prod.ts"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputHashing": "all"
|
|
||||||
},
|
|
||||||
"development": {
|
|
||||||
"buildOptimizer": false,
|
|
||||||
"optimization": false,
|
|
||||||
"vendorChunk": true,
|
|
||||||
"extractLicenses": false,
|
|
||||||
"sourceMap": true,
|
|
||||||
"namedChunks": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"defaultConfiguration": "production"
|
|
||||||
},
|
|
||||||
"serve": {
|
|
||||||
"builder": "@angular-devkit/build-angular:dev-server",
|
|
||||||
"configurations": {
|
|
||||||
"production": {
|
|
||||||
"buildTarget": "isa-app:build:production"
|
|
||||||
},
|
|
||||||
"development": {
|
|
||||||
"buildTarget": "isa-app:build:development"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"defaultConfiguration": "development"
|
|
||||||
},
|
|
||||||
"extract-i18n": {
|
|
||||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
|
||||||
"options": {
|
|
||||||
"buildTarget": "isa-app:build"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"test": {
|
|
||||||
"builder": "@angular-devkit/build-angular:karma",
|
|
||||||
"options": {
|
|
||||||
"tsConfig": "apps/isa-app/tsconfig.spec.json",
|
|
||||||
"karmaConfig": "karma.conf.js",
|
|
||||||
"polyfills": [
|
|
||||||
"zone.js",
|
|
||||||
"zone.js/testing"
|
|
||||||
],
|
|
||||||
"inlineStyleLanguage": "scss",
|
|
||||||
"assets": [
|
|
||||||
"apps/isa-app/src/favicon.ico",
|
|
||||||
"apps/isa-app/src/assets",
|
|
||||||
"apps/isa-app/src/manifest.webmanifest"
|
|
||||||
],
|
|
||||||
"styles": [
|
|
||||||
"apps/isa-app/src/styles.scss"
|
|
||||||
],
|
|
||||||
"scripts": []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"storybook": {
|
|
||||||
"builder": "@storybook/angular:start-storybook",
|
|
||||||
"options": {
|
|
||||||
"configDir": "apps/isa-app/.storybook",
|
|
||||||
"browserTarget": "isa-app:build",
|
|
||||||
"compodoc": true,
|
|
||||||
"compodocArgs": [
|
|
||||||
"-e",
|
|
||||||
"json",
|
|
||||||
"-d",
|
|
||||||
"apps/isa-app"
|
|
||||||
],
|
|
||||||
"port": 6006
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"build-storybook": {
|
|
||||||
"builder": "@storybook/angular:build-storybook",
|
|
||||||
"options": {
|
|
||||||
"configDir": "apps/isa-app/.storybook",
|
|
||||||
"browserTarget": "isa-app:build",
|
|
||||||
"compodoc": true,
|
|
||||||
"compodocArgs": [
|
|
||||||
"-e",
|
|
||||||
"json",
|
|
||||||
"-d",
|
|
||||||
"apps/isa-app"
|
|
||||||
],
|
|
||||||
"outputDir": "storybook-static"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"cli": {
|
|
||||||
"analytics": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +1,21 @@
|
|||||||
import type { StorybookConfig } from '@storybook/angular';
|
import type { StorybookConfig } from '@storybook/angular';
|
||||||
|
|
||||||
const config: StorybookConfig = {
|
const config: StorybookConfig = {
|
||||||
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
|
stories: ['../stories/**/*.@(mdx|stories.@(js|jsx|ts|tsx))'],
|
||||||
addons: [
|
addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'],
|
||||||
'@storybook/addon-onboarding',
|
staticDirs: ['../src/assets'],
|
||||||
'@storybook/addon-links',
|
previewHead: (head) => `
|
||||||
'@storybook/addon-essentials',
|
${head}
|
||||||
'@chromatic-com/storybook',
|
<link href="/assets/fonts/fonts.css" rel="stylesheet" />
|
||||||
'@storybook/addon-interactions',
|
`,
|
||||||
],
|
|
||||||
framework: {
|
framework: {
|
||||||
name: '@storybook/angular',
|
name: '@storybook/angular',
|
||||||
options: {},
|
options: {},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config;
|
export default config;
|
||||||
|
|
||||||
|
// To customize your webpack configuration you can use the webpackFinal field.
|
||||||
|
// Check https://storybook.js.org/docs/react/builders/webpack#extending-storybooks-webpack-config
|
||||||
|
// and https://nx.dev/recipes/storybook/custom-builder-configs
|
||||||
|
|||||||
@@ -1,17 +1,7 @@
|
|||||||
import type { Preview } from '@storybook/angular';
|
import type { Preview } from '@storybook/angular';
|
||||||
import { setCompodocJson } from '@storybook/addon-docs/angular';
|
|
||||||
import docJson from '../documentation.json';
|
|
||||||
setCompodocJson(docJson);
|
|
||||||
|
|
||||||
const preview: Preview = {
|
const preview: Preview = {
|
||||||
parameters: {
|
tags: ['autodocs'],
|
||||||
controls: {
|
|
||||||
matchers: {
|
|
||||||
color: /(background|color)$/i,
|
|
||||||
date: /Date$/i,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default preview;
|
export default preview;
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
// This tsconfig is used by Compodoc to generate the documentation for the project.
|
|
||||||
// If Compodoc is not used, this file can be deleted.
|
|
||||||
{
|
|
||||||
"extends": "./tsconfig.json",
|
|
||||||
// Exclude all files that are not needed for documentation generation.
|
|
||||||
"exclude": ["../src/test.ts", "../src/**/*.spec.ts", "../src/**/*.stories.ts"],
|
|
||||||
// Please make sure to include all files from which Compodoc should generate documentation.
|
|
||||||
"include": ["../src/**/*"],
|
|
||||||
"files": ["./typings.d.ts"]
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,21 @@
|
|||||||
{
|
{
|
||||||
"extends": "../tsconfig.app.json",
|
"extends": "../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"types": ["node"],
|
"emitDecoratorMetadata": true
|
||||||
"allowSyntheticDefaultImports": true,
|
|
||||||
"resolveJsonModule": true
|
|
||||||
},
|
},
|
||||||
"exclude": ["../src/test.ts", "../src/**/*.spec.ts"],
|
"exclude": ["../**/*.spec.ts"],
|
||||||
"include": ["../src/**/*.stories.*", "./preview.ts", "../src/polyfills.ts"],
|
"include": [
|
||||||
"files": ["./typings.d.ts"]
|
// "../src/**/*.stories.ts",
|
||||||
|
// "../src/**/*.stories.js",
|
||||||
|
// "../src/**/*.stories.jsx",
|
||||||
|
// "../src/**/*.stories.tsx",
|
||||||
|
// "../src/**/*.stories.mdx",
|
||||||
|
"../stories/**/*.stories.ts",
|
||||||
|
"../stories/**/*.stories.js",
|
||||||
|
"../stories/**/*.stories.jsx",
|
||||||
|
"../stories/**/*.stories.tsx",
|
||||||
|
"../stories/**/*.stories.mdx",
|
||||||
|
"*.js",
|
||||||
|
"*.ts"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
4
apps/isa-app/.storybook/typings.d.ts
vendored
4
apps/isa-app/.storybook/typings.d.ts
vendored
@@ -1,4 +0,0 @@
|
|||||||
declare module '*.md' {
|
|
||||||
const content: string;
|
|
||||||
export default content;
|
|
||||||
}
|
|
||||||
55
apps/isa-app/eslint.config.mjs
Normal file
55
apps/isa-app/eslint.config.mjs
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import nx from '@nx/eslint-plugin';
|
||||||
|
import baseConfig from '../../eslint.config.mjs';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
...baseConfig,
|
||||||
|
...nx.configs['flat/angular'],
|
||||||
|
...nx.configs['flat/angular-template'],
|
||||||
|
{
|
||||||
|
files: ['**/*.ts'],
|
||||||
|
rules: {
|
||||||
|
'@angular-eslint/directive-selector': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
type: 'attribute',
|
||||||
|
prefix: 'app',
|
||||||
|
style: 'camelCase',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'@angular-eslint/component-selector': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
type: 'element',
|
||||||
|
prefix: 'app',
|
||||||
|
style: 'kebab-case',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['**/*.ts'],
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/no-unused-expressions': 'warn',
|
||||||
|
'prefer-const': 'warn',
|
||||||
|
'@angular-eslint/contextual-lifecycle': 'warn',
|
||||||
|
'@typescript-eslint/no-explicit-any': 'warn',
|
||||||
|
'@angular-eslint/no-empty-lifecycle-method': 'warn',
|
||||||
|
'@typescript-eslint/no-inferrable-types': 'warn',
|
||||||
|
'@angular-eslint/component-selector': 'warn',
|
||||||
|
'@angular-eslint/prefer-standalone': 'warn',
|
||||||
|
'@typescript-eslint/no-inferrable-types': 'warn',
|
||||||
|
'no-empty-function': 'warn',
|
||||||
|
'@typescript-eslint/no-empty-function': 'warn',
|
||||||
|
'@typescript-eslint/no-unused-vars': 'warn',
|
||||||
|
'@angular-eslint/directive-selector': 'warn',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['**/*.html'],
|
||||||
|
// Override or add rules here
|
||||||
|
rules: {
|
||||||
|
'@angular-eslint/template/elements-content': 'warn',
|
||||||
|
'@angular-eslint/template/no-autofocus': 'warn',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
21
apps/isa-app/jest.config.ts
Normal file
21
apps/isa-app/jest.config.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
export default {
|
||||||
|
displayName: 'isa-app',
|
||||||
|
preset: '../../jest.preset.js',
|
||||||
|
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
|
||||||
|
coverageDirectory: '../../coverage/apps/prj',
|
||||||
|
transform: {
|
||||||
|
'^.+\\.(ts|mjs|js|html)$': [
|
||||||
|
'jest-preset-angular',
|
||||||
|
{
|
||||||
|
tsconfig: '<rootDir>/tsconfig.spec.json',
|
||||||
|
stringifyContentPathRegex: '\\.(html|svg)$',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
|
||||||
|
snapshotSerializers: [
|
||||||
|
'jest-preset-angular/build/serializers/no-ng-attributes',
|
||||||
|
'jest-preset-angular/build/serializers/ng-snapshot',
|
||||||
|
'jest-preset-angular/build/serializers/html-comment',
|
||||||
|
],
|
||||||
|
};
|
||||||
@@ -29,4 +29,4 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
164
apps/isa-app/project.json
Normal file
164
apps/isa-app/project.json
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
{
|
||||||
|
"name": "isa-app",
|
||||||
|
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"projectType": "application",
|
||||||
|
"prefix": "app",
|
||||||
|
"sourceRoot": "apps/isa-app/src",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {
|
||||||
|
"build": {
|
||||||
|
"executor": "@angular-devkit/build-angular:application",
|
||||||
|
"options": {
|
||||||
|
"allowedCommonJsDependencies": [
|
||||||
|
"lodash",
|
||||||
|
"moment",
|
||||||
|
"jsrsasign",
|
||||||
|
"pdfjs-dist/build/pdf",
|
||||||
|
"pdfjs-dist/web/pdf_viewer",
|
||||||
|
"pdfjs-dist/es5/build/pdf",
|
||||||
|
"pdfjs-dist/es5/web/pdf_viewer"
|
||||||
|
],
|
||||||
|
"outputPath": "dist/isa-app",
|
||||||
|
"index": "apps/isa-app/src/index.html",
|
||||||
|
"browser": "apps/isa-app/src/main.ts",
|
||||||
|
"polyfills": ["zone.js"],
|
||||||
|
"tsConfig": "apps/isa-app/tsconfig.app.json",
|
||||||
|
"inlineStyleLanguage": "scss",
|
||||||
|
"assets": [
|
||||||
|
"apps/isa-app/src/favicon.ico",
|
||||||
|
"apps/isa-app/src/assets",
|
||||||
|
"apps/isa-app/src/config",
|
||||||
|
"apps/isa-app/src/silent-refresh.html",
|
||||||
|
"apps/isa-app/src/manifest.webmanifest",
|
||||||
|
{
|
||||||
|
"glob": "**/*",
|
||||||
|
"input": "node_modules/scandit-web-datacapture-barcode/build/engine",
|
||||||
|
"output": "scandit"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"styles": [
|
||||||
|
"@angular/cdk/overlay-prebuilt.css",
|
||||||
|
"apps/isa-app/src/ui.scss",
|
||||||
|
"apps/isa-app/src/styles.scss"
|
||||||
|
],
|
||||||
|
"scripts": []
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"budgets": [
|
||||||
|
{
|
||||||
|
"type": "initial",
|
||||||
|
"maximumWarning": "2mb",
|
||||||
|
"maximumError": "5mb"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "anyComponentStyle",
|
||||||
|
"maximumWarning": "25kb"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fileReplacements": [
|
||||||
|
{
|
||||||
|
"replace": "apps/isa-app/src/environments/environment.ts",
|
||||||
|
"with": "apps/isa-app/src/environments/environment.prod.ts"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputHashing": "all",
|
||||||
|
"serviceWorker": "apps/isa-app/ngsw-config.json"
|
||||||
|
},
|
||||||
|
"development": {
|
||||||
|
"optimization": false,
|
||||||
|
"extractLicenses": false,
|
||||||
|
"sourceMap": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultConfiguration": "production",
|
||||||
|
"outputs": ["{options.outputPath}"]
|
||||||
|
},
|
||||||
|
"serve": {
|
||||||
|
"executor": "@angular-devkit/build-angular:dev-server",
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"buildTarget": "isa-app:build:production"
|
||||||
|
},
|
||||||
|
"development": {
|
||||||
|
"buildTarget": "isa-app:build:development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultConfiguration": "development"
|
||||||
|
},
|
||||||
|
"extract-i18n": {
|
||||||
|
"executor": "@angular-devkit/build-angular:extract-i18n",
|
||||||
|
"options": {
|
||||||
|
"buildTarget": "isa-app:build"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"executor": "@nx/eslint:lint"
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"executor": "@nx/jest:jest",
|
||||||
|
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
|
||||||
|
"options": {
|
||||||
|
"jestConfig": "apps/isa-app/jest.config.ts"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"serve-static": {
|
||||||
|
"executor": "@nx/web:file-server",
|
||||||
|
"options": {
|
||||||
|
"buildTarget": "isa-app:build",
|
||||||
|
"staticFilePath": "dist/apps/isa-app/browser",
|
||||||
|
"spa": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"storybook": {
|
||||||
|
"executor": "@storybook/angular:start-storybook",
|
||||||
|
"options": {
|
||||||
|
"port": 4400,
|
||||||
|
"configDir": "apps/isa-app/.storybook",
|
||||||
|
"browserTarget": "isa-app:build",
|
||||||
|
"compodoc": false,
|
||||||
|
"styles": ["apps/isa-app/src/ui.scss", "apps/isa-app/src/styles.scss"]
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"ci": {
|
||||||
|
"quiet": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"build-storybook": {
|
||||||
|
"executor": "@storybook/angular:build-storybook",
|
||||||
|
"outputs": ["{options.outputDir}"],
|
||||||
|
"options": {
|
||||||
|
"outputDir": "dist/storybook/isa-app",
|
||||||
|
"configDir": "apps/isa-app/.storybook",
|
||||||
|
"browserTarget": "isa-app:build",
|
||||||
|
"compodoc": false
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"ci": {
|
||||||
|
"quiet": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"test-storybook": {
|
||||||
|
"executor": "nx:run-commands",
|
||||||
|
"options": {
|
||||||
|
"command": "test-storybook -c apps/isa-app/.storybook --url=http://localhost:4400"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"static-storybook": {
|
||||||
|
"executor": "@nx/web:file-server",
|
||||||
|
"dependsOn": ["build-storybook"],
|
||||||
|
"options": {
|
||||||
|
"buildTarget": "isa-app:build-storybook",
|
||||||
|
"staticFilePath": "dist/storybook/isa-app",
|
||||||
|
"spa": true
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"ci": {
|
||||||
|
"buildTarget": "isa-app:build-storybook:ci"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,12 @@
|
|||||||
import { Component, ChangeDetectionStrategy, ElementRef, ViewChild, NgZone, AfterViewInit, OnDestroy } from '@angular/core';
|
import {
|
||||||
|
Component,
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
ElementRef,
|
||||||
|
ViewChild,
|
||||||
|
NgZone,
|
||||||
|
AfterViewInit,
|
||||||
|
OnDestroy, OnInit,
|
||||||
|
} from '@angular/core';
|
||||||
import { BarcodeCapture, BarcodeCaptureSettings, Symbology } from 'scandit-web-datacapture-barcode';
|
import { BarcodeCapture, BarcodeCaptureSettings, Symbology } from 'scandit-web-datacapture-barcode';
|
||||||
import { Camera, DataCaptureContext, DataCaptureView, FrameSourceState } from 'scandit-web-datacapture-core';
|
import { Camera, DataCaptureContext, DataCaptureView, FrameSourceState } from 'scandit-web-datacapture-core';
|
||||||
|
|
||||||
@@ -7,8 +15,9 @@ import { Camera, DataCaptureContext, DataCaptureView, FrameSourceState } from 's
|
|||||||
templateUrl: 'scandit-overlay.component.html',
|
templateUrl: 'scandit-overlay.component.html',
|
||||||
styleUrls: ['scandit-overlay.component.css'],
|
styleUrls: ['scandit-overlay.component.css'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class ScanditOverlayComponent implements AfterViewInit, OnDestroy {
|
export class ScanditOverlayComponent implements AfterViewInit, OnDestroy, OnInit {
|
||||||
private dataCaptureContext: DataCaptureContext;
|
private dataCaptureContext: DataCaptureContext;
|
||||||
private dataCaptureView: DataCaptureView;
|
private dataCaptureView: DataCaptureView;
|
||||||
private barcodeCapture: BarcodeCapture;
|
private barcodeCapture: BarcodeCapture;
|
||||||
|
|||||||
@@ -21,9 +21,16 @@ import { PreviewComponent } from './preview';
|
|||||||
import { BranchSectionResolver, CustomerSectionResolver, ProcessIdResolver } from './resolvers';
|
import { BranchSectionResolver, CustomerSectionResolver, ProcessIdResolver } from './resolvers';
|
||||||
import { TokenLoginComponent, TokenLoginModule } from './token-login';
|
import { TokenLoginComponent, TokenLoginModule } from './token-login';
|
||||||
import { ProcessIdGuard } from './guards/process-id.guard';
|
import { ProcessIdGuard } from './guards/process-id.guard';
|
||||||
import { ActivateProcessIdGuard, ActivateProcessIdWithConfigKeyGuard } from './guards/activate-process-id.guard';
|
import {
|
||||||
|
ActivateProcessIdGuard,
|
||||||
|
ActivateProcessIdWithConfigKeyGuard,
|
||||||
|
} from './guards/activate-process-id.guard';
|
||||||
|
import { MatomoRouteData } from 'ngx-matomo-client';
|
||||||
|
import { processResolverFn } from '@isa/core/process';
|
||||||
|
import { provideScrollPositionRestoration } from '@isa/utils/scroll-position';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
|
{ path: '', redirectTo: 'kunde/dashboard', pathMatch: 'full' },
|
||||||
{
|
{
|
||||||
path: 'login',
|
path: 'login',
|
||||||
children: [
|
children: [
|
||||||
@@ -42,6 +49,11 @@ const routes: Routes = [
|
|||||||
{
|
{
|
||||||
path: 'dashboard',
|
path: 'dashboard',
|
||||||
loadChildren: () => import('@page/dashboard').then((m) => m.DashboardModule),
|
loadChildren: () => import('@page/dashboard').then((m) => m.DashboardModule),
|
||||||
|
data: {
|
||||||
|
matomo: {
|
||||||
|
title: 'Dashboard',
|
||||||
|
} as MatomoRouteData,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'product',
|
path: 'product',
|
||||||
@@ -128,7 +140,8 @@ const routes: Routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'package-inspection',
|
path: 'package-inspection',
|
||||||
loadChildren: () => import('@page/package-inspection').then((m) => m.PackageInspectionModule),
|
loadChildren: () =>
|
||||||
|
import('@page/package-inspection').then((m) => m.PackageInspectionModule),
|
||||||
canActivate: [CanActivatePackageInspectionGuard],
|
canActivate: [CanActivatePackageInspectionGuard],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -140,7 +153,18 @@ const routes: Routes = [
|
|||||||
],
|
],
|
||||||
resolve: { section: BranchSectionResolver },
|
resolve: { section: BranchSectionResolver },
|
||||||
},
|
},
|
||||||
{ path: '**', redirectTo: 'kunde', pathMatch: 'full' },
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: ':processId',
|
||||||
|
component: MainComponent,
|
||||||
|
resolve: { process: processResolverFn },
|
||||||
|
canActivate: [IsAuthenticatedGuard],
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'return',
|
||||||
|
loadChildren: () => import('@isa/oms/feature/return-search').then((m) => m.routes),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -155,5 +179,6 @@ if (isDevMode()) {
|
|||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [RouterModule.forRoot(routes), TokenLoginModule],
|
imports: [RouterModule.forRoot(routes), TokenLoginModule],
|
||||||
exports: [RouterModule],
|
exports: [RouterModule],
|
||||||
|
providers: [provideScrollPositionRestoration()],
|
||||||
})
|
})
|
||||||
export class AppRoutingModule {}
|
export class AppRoutingModule {}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { NgModule } from '@angular/core';
|
|||||||
import { EffectsModule } from '@ngrx/effects';
|
import { EffectsModule } from '@ngrx/effects';
|
||||||
import { ActionReducer, MetaReducer, StoreModule } from '@ngrx/store';
|
import { ActionReducer, MetaReducer, StoreModule } from '@ngrx/store';
|
||||||
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
|
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
|
||||||
import { storeFreeze } from 'ngrx-store-freeze';
|
|
||||||
import packageInfo from 'packageJson';
|
import packageInfo from 'packageJson';
|
||||||
import { environment } from '../environments/environment';
|
import { environment } from '../environments/environment';
|
||||||
import { RootStateService } from './store/root-state.service';
|
import { RootStateService } from './store/root-state.service';
|
||||||
@@ -22,7 +21,9 @@ export function storeInLocalStorage(reducer: ActionReducer<any>): ActionReducer<
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const metaReducers: MetaReducer<RootState>[] = !environment.production ? [storeFreeze, storeInLocalStorage] : [storeInLocalStorage];
|
export const metaReducers: MetaReducer<RootState>[] = !environment.production
|
||||||
|
? [storeInLocalStorage]
|
||||||
|
: [storeInLocalStorage];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
import { HttpInterceptorFn, provideHttpClient, withInterceptors } from '@angular/common/http';
|
import { HttpInterceptorFn, provideHttpClient, withInterceptors } from '@angular/common/http';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { Config } from '@core/config';
|
import { Config } from '@core/config';
|
||||||
import { AvConfiguration } from '@swagger/availability';
|
import { AvConfiguration } from '@generated/swagger/availability-api';
|
||||||
import { CatConfiguration } from '@swagger/cat';
|
import { CatConfiguration } from '@generated/swagger/cat-search-api';
|
||||||
import { CheckoutConfiguration } from '@swagger/checkout';
|
import { CheckoutConfiguration } from '@generated/swagger/checkout-api';
|
||||||
import { CrmConfiguration } from '@swagger/crm';
|
import { CrmConfiguration } from '@generated/swagger/crm-api';
|
||||||
import { EisConfiguration } from '@swagger/eis';
|
import { EisConfiguration } from '@generated/swagger/eis-api';
|
||||||
import { IsaConfiguration } from '@swagger/isa';
|
import { IsaConfiguration } from '@generated/swagger/isa-api';
|
||||||
import { OmsConfiguration } from '@swagger/oms';
|
import { OmsConfiguration } from '@generated/swagger/oms-api';
|
||||||
import { PrintConfiguration } from '@swagger/print';
|
import { PrintConfiguration } from '@generated/swagger/print-api';
|
||||||
import { RemiConfiguration } from '@swagger/remi';
|
import { RemiConfiguration } from '@generated/swagger/inventory-api';
|
||||||
import { WwsConfiguration } from '@swagger/wws';
|
import { WwsConfiguration } from '@generated/swagger/wws-api';
|
||||||
|
|
||||||
export function createConfigurationFactory(name: string) {
|
export function createConfigurationFactory(name: string) {
|
||||||
return function (config: Config): { rootUrl: string } {
|
return function (config: Config): { rootUrl: string } {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { Renderer2 } from '@angular/core';
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { SwUpdate } from '@angular/service-worker';
|
import { SwUpdate } from '@angular/service-worker';
|
||||||
import { NotificationsHub } from '@hub/notifications';
|
import { NotificationsHub } from '@hub/notifications';
|
||||||
import { UserStateService } from '@swagger/isa';
|
import { UserStateService } from '@generated/swagger/isa-api';
|
||||||
import { UiModalService } from '@ui/modal';
|
import { UiModalService } from '@ui/modal';
|
||||||
import { AuthService } from '@core/auth';
|
import { AuthService } from '@core/auth';
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,16 @@
|
|||||||
import { DOCUMENT } from '@angular/common';
|
import { DOCUMENT } from '@angular/common';
|
||||||
import { Component, effect, HostListener, inject, Inject, Injector, OnInit, Renderer2, signal, untracked } from '@angular/core';
|
import {
|
||||||
|
Component,
|
||||||
|
effect,
|
||||||
|
HostListener,
|
||||||
|
inject,
|
||||||
|
Inject,
|
||||||
|
Injector,
|
||||||
|
OnInit,
|
||||||
|
Renderer2,
|
||||||
|
signal,
|
||||||
|
untracked,
|
||||||
|
} from '@angular/core';
|
||||||
import { Title } from '@angular/platform-browser';
|
import { Title } from '@angular/platform-browser';
|
||||||
import { SwUpdate } from '@angular/service-worker';
|
import { SwUpdate } from '@angular/service-worker';
|
||||||
import { ApplicationService } from '@core/application';
|
import { ApplicationService } from '@core/application';
|
||||||
@@ -7,7 +18,7 @@ import { Config } from '@core/config';
|
|||||||
import { NotificationsHub } from '@hub/notifications';
|
import { NotificationsHub } from '@hub/notifications';
|
||||||
import packageInfo from 'packageJson';
|
import packageInfo from 'packageJson';
|
||||||
import { asapScheduler, interval, Subscription } from 'rxjs';
|
import { asapScheduler, interval, Subscription } from 'rxjs';
|
||||||
import { UserStateService } from '@swagger/isa';
|
import { UserStateService } from '@generated/swagger/isa-api';
|
||||||
import { IsaLogProvider } from './providers';
|
import { IsaLogProvider } from './providers';
|
||||||
import { EnvironmentService } from '@core/environment';
|
import { EnvironmentService } from '@core/environment';
|
||||||
import { AuthService, LoginStrategy } from '@core/auth';
|
import { AuthService, LoginStrategy } from '@core/auth';
|
||||||
@@ -33,6 +44,7 @@ import { animate, style, transition, trigger } from '@angular/animations';
|
|||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
],
|
],
|
||||||
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class AppComponent implements OnInit {
|
export class AppComponent implements OnInit {
|
||||||
readonly injector = inject(Injector);
|
readonly injector = inject(Injector);
|
||||||
@@ -120,7 +132,10 @@ export class AppComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logVersion() {
|
logVersion() {
|
||||||
console.log(`%c${this._config.get('title')}\r\nVersion: ${packageInfo.version}`, 'font-weight: bold; font-size: 20px;');
|
console.log(
|
||||||
|
`%c${this._config.get('title')}\r\nVersion: ${packageInfo.version}`,
|
||||||
|
'font-weight: bold; font-size: 20px;',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
determinePlatform() {
|
determinePlatform() {
|
||||||
|
|||||||
@@ -1,10 +1,21 @@
|
|||||||
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
|
import {
|
||||||
import { APP_INITIALIZER, ErrorHandler, Injector, LOCALE_ID, NgModule } from '@angular/core';
|
HTTP_INTERCEPTORS,
|
||||||
|
provideHttpClient,
|
||||||
|
withInterceptorsFromDi,
|
||||||
|
} from '@angular/common/http';
|
||||||
|
import {
|
||||||
|
ErrorHandler,
|
||||||
|
Injector,
|
||||||
|
LOCALE_ID,
|
||||||
|
NgModule,
|
||||||
|
inject,
|
||||||
|
provideAppInitializer,
|
||||||
|
} from '@angular/core';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { PlatformModule } from '@angular/cdk/platform';
|
import { PlatformModule } from '@angular/cdk/platform';
|
||||||
|
|
||||||
import { Config, ConfigModule, JsonConfigLoader } from '@core/config';
|
import { Config } from '@core/config';
|
||||||
import { AuthModule, AuthService, LoginStrategy } from '@core/auth';
|
import { AuthModule, AuthService, LoginStrategy } from '@core/auth';
|
||||||
import { CoreCommandModule } from '@core/command';
|
import { CoreCommandModule } from '@core/command';
|
||||||
|
|
||||||
@@ -17,7 +28,10 @@ import { environment } from '../environments/environment';
|
|||||||
import { AppSwaggerModule } from './app-swagger.module';
|
import { AppSwaggerModule } from './app-swagger.module';
|
||||||
import { AppDomainModule } from './app-domain.module';
|
import { AppDomainModule } from './app-domain.module';
|
||||||
import { UiModalModule } from '@ui/modal';
|
import { UiModalModule } from '@ui/modal';
|
||||||
import { NotificationsHubModule, NOTIFICATIONS_HUB_OPTIONS } from '@hub/notifications';
|
import {
|
||||||
|
NotificationsHubModule,
|
||||||
|
NOTIFICATIONS_HUB_OPTIONS,
|
||||||
|
} from '@hub/notifications';
|
||||||
import { SignalRHubOptions } from '@core/signalr';
|
import { SignalRHubOptions } from '@core/signalr';
|
||||||
import { CoreBreadcrumbModule } from '@core/breadcrumb';
|
import { CoreBreadcrumbModule } from '@core/breadcrumb';
|
||||||
import { UiCommonModule } from '@ui/common';
|
import { UiCommonModule } from '@ui/common';
|
||||||
@@ -29,7 +43,11 @@ import { HttpErrorInterceptor } from './interceptors';
|
|||||||
import { CoreLoggerModule, LOG_PROVIDER } from '@core/logger';
|
import { CoreLoggerModule, LOG_PROVIDER } from '@core/logger';
|
||||||
import { IsaLogProvider } from './providers';
|
import { IsaLogProvider } from './providers';
|
||||||
import { IsaErrorHandler } from './providers/isa.error-handler';
|
import { IsaErrorHandler } from './providers/isa.error-handler';
|
||||||
import { ScanAdapterModule, ScanAdapterService, ScanditScanAdapterModule } from '@adapter/scan';
|
import {
|
||||||
|
ScanAdapterModule,
|
||||||
|
ScanAdapterService,
|
||||||
|
ScanditScanAdapterModule,
|
||||||
|
} from '@adapter/scan';
|
||||||
import { RootStateService } from './store/root-state.service';
|
import { RootStateService } from './store/root-state.service';
|
||||||
import * as Commands from './commands';
|
import * as Commands from './commands';
|
||||||
import { PreviewComponent } from './preview';
|
import { PreviewComponent } from './preview';
|
||||||
@@ -38,9 +56,22 @@ import { ShellModule } from '@shared/shell';
|
|||||||
import { MainComponent } from './main.component';
|
import { MainComponent } from './main.component';
|
||||||
import { IconModule } from '@shared/components/icon';
|
import { IconModule } from '@shared/components/icon';
|
||||||
import { NgIconsModule } from '@ng-icons/core';
|
import { NgIconsModule } from '@ng-icons/core';
|
||||||
import { matClose, matWifi, matWifiOff } from '@ng-icons/material-icons/baseline';
|
import {
|
||||||
|
matClose,
|
||||||
|
matWifi,
|
||||||
|
matWifiOff,
|
||||||
|
} from '@ng-icons/material-icons/baseline';
|
||||||
import { NetworkStatusService } from './services/network-status.service';
|
import { NetworkStatusService } from './services/network-status.service';
|
||||||
import { firstValueFrom } from 'rxjs';
|
import { firstValueFrom } from 'rxjs';
|
||||||
|
import { provideMatomo } from 'ngx-matomo-client';
|
||||||
|
import { withRouter, withRouteData } from 'ngx-matomo-client';
|
||||||
|
import {
|
||||||
|
provideLogging,
|
||||||
|
withLogLevel,
|
||||||
|
LogLevel,
|
||||||
|
withSink,
|
||||||
|
ConsoleLogSink,
|
||||||
|
} from '@isa/core/logging';
|
||||||
|
|
||||||
registerLocaleData(localeDe, localeDeExtra);
|
registerLocaleData(localeDe, localeDeExtra);
|
||||||
registerLocaleData(localeDe, 'de', localeDeExtra);
|
registerLocaleData(localeDe, 'de', localeDeExtra);
|
||||||
@@ -64,7 +95,6 @@ export function _appInitializerFactory(config: Config, injector: Injector) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
statusElement.innerHTML = 'Konfigurationen werden geladen...';
|
statusElement.innerHTML = 'Konfigurationen werden geladen...';
|
||||||
await config.init();
|
|
||||||
|
|
||||||
statusElement.innerHTML = 'Scanner wird initialisiert...';
|
statusElement.innerHTML = 'Scanner wird initialisiert...';
|
||||||
const scanAdapter = injector.get(ScanAdapterService);
|
const scanAdapter = injector.get(ScanAdapterService);
|
||||||
@@ -95,7 +125,13 @@ export function _appInitializerFactory(config: Config, injector: Injector) {
|
|||||||
'⚡<br><br><b>Fehler bei der Initialisierung</b><br><br>Bitte prüfen Sie die Netzwerkverbindung (WLAN).<br><br>';
|
'⚡<br><br><b>Fehler bei der Initialisierung</b><br><br>Bitte prüfen Sie die Netzwerkverbindung (WLAN).<br><br>';
|
||||||
|
|
||||||
const reload = document.createElement('button');
|
const reload = document.createElement('button');
|
||||||
reload.classList.add('bg-brand', 'text-white', 'p-2', 'rounded', 'cursor-pointer');
|
reload.classList.add(
|
||||||
|
'bg-brand',
|
||||||
|
'text-white',
|
||||||
|
'p-2',
|
||||||
|
'rounded',
|
||||||
|
'cursor-pointer',
|
||||||
|
);
|
||||||
reload.innerHTML = 'App neu laden';
|
reload.innerHTML = 'App neu laden';
|
||||||
reload.onclick = () => window.location.reload();
|
reload.onclick = () => window.location.reload();
|
||||||
statusElement.appendChild(reload);
|
statusElement.appendChild(reload);
|
||||||
@@ -118,7 +154,10 @@ export function _appInitializerFactory(config: Config, injector: Injector) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function _notificationsHubOptionsFactory(config: Config, auth: AuthService): SignalRHubOptions {
|
export function _notificationsHubOptionsFactory(
|
||||||
|
config: Config,
|
||||||
|
auth: AuthService,
|
||||||
|
): SignalRHubOptions {
|
||||||
const options = { ...config.get('hubs').notifications };
|
const options = { ...config.get('hubs').notifications };
|
||||||
options.httpOptions.accessTokenFactory = () => auth.getToken();
|
options.httpOptions.accessTokenFactory = () => auth.getToken();
|
||||||
return options;
|
return options;
|
||||||
@@ -135,10 +174,6 @@ export function _notificationsHubOptionsFactory(config: Config, auth: AuthServic
|
|||||||
AppSwaggerModule,
|
AppSwaggerModule,
|
||||||
AppDomainModule,
|
AppDomainModule,
|
||||||
CoreBreadcrumbModule.forRoot(),
|
CoreBreadcrumbModule.forRoot(),
|
||||||
ConfigModule.forRoot({
|
|
||||||
useConfigLoader: JsonConfigLoader,
|
|
||||||
jsonConfigLoaderUrl: '/config/config.json',
|
|
||||||
}),
|
|
||||||
CoreCommandModule.forRoot(Object.values(Commands)),
|
CoreCommandModule.forRoot(Object.values(Commands)),
|
||||||
CoreLoggerModule.forRoot(),
|
CoreLoggerModule.forRoot(),
|
||||||
AppStoreModule,
|
AppStoreModule,
|
||||||
@@ -159,12 +194,13 @@ export function _notificationsHubOptionsFactory(config: Config, auth: AuthServic
|
|||||||
NgIconsModule.withIcons({ matWifiOff, matClose, matWifi }),
|
NgIconsModule.withIcons({ matWifiOff, matClose, matWifi }),
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{
|
provideAppInitializer(() => {
|
||||||
provide: APP_INITIALIZER,
|
const initializerFn = _appInitializerFactory(
|
||||||
useFactory: _appInitializerFactory,
|
inject(Config),
|
||||||
multi: true,
|
inject(Injector),
|
||||||
deps: [Config, Injector],
|
);
|
||||||
},
|
return initializerFn();
|
||||||
|
}),
|
||||||
{
|
{
|
||||||
provide: NOTIFICATIONS_HUB_OPTIONS,
|
provide: NOTIFICATIONS_HUB_OPTIONS,
|
||||||
useFactory: _notificationsHubOptionsFactory,
|
useFactory: _notificationsHubOptionsFactory,
|
||||||
@@ -186,6 +222,12 @@ export function _notificationsHubOptionsFactory(config: Config, auth: AuthServic
|
|||||||
},
|
},
|
||||||
{ provide: LOCALE_ID, useValue: 'de-DE' },
|
{ provide: LOCALE_ID, useValue: 'de-DE' },
|
||||||
provideHttpClient(withInterceptorsFromDi()),
|
provideHttpClient(withInterceptorsFromDi()),
|
||||||
|
provideMatomo(
|
||||||
|
{ trackerUrl: 'https://matomo.paragon-data.net', siteId: '1' },
|
||||||
|
withRouter(),
|
||||||
|
withRouteData(),
|
||||||
|
),
|
||||||
|
provideLogging(withLogLevel(LogLevel.Debug), withSink(ConsoleLogSink)),
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule {}
|
||||||
|
|||||||
@@ -3,11 +3,14 @@ import { Router } from '@angular/router';
|
|||||||
import { ApplicationService } from '@core/application';
|
import { ApplicationService } from '@core/application';
|
||||||
import { ActionHandler } from '@core/command';
|
import { ActionHandler } from '@core/command';
|
||||||
import { Result } from '@domain/defs';
|
import { Result } from '@domain/defs';
|
||||||
import { CustomerInfoDTO } from '@swagger/crm';
|
import { CustomerInfoDTO } from '@generated/swagger/crm-api';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CreateCustomerCommand extends ActionHandler<Result<CustomerInfoDTO[]>> {
|
export class CreateCustomerCommand extends ActionHandler<Result<CustomerInfoDTO[]>> {
|
||||||
constructor(private _router: Router, private _application: ApplicationService) {
|
constructor(
|
||||||
|
private _router: Router,
|
||||||
|
private _application: ApplicationService,
|
||||||
|
) {
|
||||||
super('CREATE_CUSTOMER');
|
super('CREATE_CUSTOMER');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { ApplicationService } from '@core/application';
|
|||||||
import { ActionHandler } from '@core/command';
|
import { ActionHandler } from '@core/command';
|
||||||
import { Result } from '@domain/defs';
|
import { Result } from '@domain/defs';
|
||||||
import { encodeFormData, mapCustomerInfoDtoToCustomerCreateFormData } from '@page/customer';
|
import { encodeFormData, mapCustomerInfoDtoToCustomerCreateFormData } from '@page/customer';
|
||||||
import { CustomerInfoDTO } from '@swagger/crm';
|
import { CustomerInfoDTO } from '@generated/swagger/crm-api';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CreateKubiCustomerCommand extends ActionHandler<Result<CustomerInfoDTO[]>> {
|
export class CreateKubiCustomerCommand extends ActionHandler<Result<CustomerInfoDTO[]>> {
|
||||||
@@ -40,9 +40,12 @@ export class CreateKubiCustomerCommand extends ActionHandler<Result<CustomerInfo
|
|||||||
customerType = 'store';
|
customerType = 'store';
|
||||||
}
|
}
|
||||||
|
|
||||||
await this._router.navigate(['/kunde', this._application.activatedProcessId, 'customer', 'create', `${customerType}-p4m`], {
|
await this._router.navigate(
|
||||||
queryParams: { formData },
|
['/kunde', this._application.activatedProcessId, 'customer', 'create', `${customerType}-p4m`],
|
||||||
});
|
{
|
||||||
|
queryParams: { formData },
|
||||||
|
},
|
||||||
|
);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,15 @@ import { ActionHandler } from '@core/command';
|
|||||||
import { Result } from '@domain/defs';
|
import { Result } from '@domain/defs';
|
||||||
import { DomainPrinterService } from '@domain/printer';
|
import { DomainPrinterService } from '@domain/printer';
|
||||||
import { PrintModalComponent, PrintModalData } from '@modal/printer';
|
import { PrintModalComponent, PrintModalData } from '@modal/printer';
|
||||||
import { CustomerInfoDTO } from '@swagger/crm';
|
import { CustomerInfoDTO } from '@generated/swagger/crm-api';
|
||||||
import { UiModalService } from '@ui/modal';
|
import { UiModalService } from '@ui/modal';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PrintKubiCustomerCommand extends ActionHandler<Result<CustomerInfoDTO[]>> {
|
export class PrintKubiCustomerCommand extends ActionHandler<Result<CustomerInfoDTO[]>> {
|
||||||
constructor(private _uiModal: UiModalService, private _printerService: DomainPrinterService) {
|
constructor(
|
||||||
|
private _uiModal: UiModalService,
|
||||||
|
private _printerService: DomainPrinterService,
|
||||||
|
) {
|
||||||
super('PRINT_KUBI_AGB');
|
super('PRINT_KUBI_AGB');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ import { ApplicationService } from '@core/application';
|
|||||||
import { Config } from '@core/config';
|
import { Config } from '@core/config';
|
||||||
import { take } from 'rxjs/operators';
|
import { take } from 'rxjs/operators';
|
||||||
|
|
||||||
export const ActivateProcessIdGuard: CanActivateFn = async (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
|
export const ActivateProcessIdGuard: CanActivateFn = async (
|
||||||
|
route: ActivatedRouteSnapshot,
|
||||||
|
state: RouterStateSnapshot,
|
||||||
|
) => {
|
||||||
const application = inject(ApplicationService);
|
const application = inject(ApplicationService);
|
||||||
|
|
||||||
const processIdStr = route.params.processId;
|
const processIdStr = route.params.processId;
|
||||||
@@ -27,20 +30,18 @@ export const ActivateProcessIdGuard: CanActivateFn = async (route: ActivatedRout
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ActivateProcessIdWithConfigKeyGuard: (key: string) => CanActivateFn = (key) => async (
|
export const ActivateProcessIdWithConfigKeyGuard: (key: string) => CanActivateFn =
|
||||||
route: ActivatedRouteSnapshot,
|
(key) => async (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
|
||||||
state: RouterStateSnapshot
|
const application = inject(ApplicationService);
|
||||||
) => {
|
const config = inject(Config);
|
||||||
const application = inject(ApplicationService);
|
|
||||||
const config = inject(Config);
|
|
||||||
|
|
||||||
const processId = config.get(`process.ids.${key}`);
|
const processId = config.get(`process.ids.${key}`);
|
||||||
|
|
||||||
if (isNaN(processId)) {
|
if (isNaN(processId)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
application.activateProcess(processId);
|
application.activateProcess(processId);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,10 +6,16 @@ import { first } from 'rxjs/operators';
|
|||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class CanActivateAssortmentGuard {
|
export class CanActivateAssortmentGuard {
|
||||||
constructor(private readonly _applicationService: ApplicationService, private readonly _config: Config) {}
|
constructor(
|
||||||
|
private readonly _applicationService: ApplicationService,
|
||||||
|
private readonly _config: Config,
|
||||||
|
) {}
|
||||||
|
|
||||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||||
const process = await this._applicationService.getProcessById$(this._config.get('process.ids.assortment')).pipe(first()).toPromise();
|
const process = await this._applicationService
|
||||||
|
.getProcessById$(this._config.get('process.ids.assortment'))
|
||||||
|
.pipe(first())
|
||||||
|
.toPromise();
|
||||||
if (!process) {
|
if (!process) {
|
||||||
await this._applicationService.createProcess({
|
await this._applicationService.createProcess({
|
||||||
id: this._config.get('process.ids.assortment'),
|
id: this._config.get('process.ids.assortment'),
|
||||||
|
|||||||
@@ -8,10 +8,7 @@ export class CanActivateCartWithProcessIdGuard {
|
|||||||
constructor(private readonly _applicationService: ApplicationService) {}
|
constructor(private readonly _applicationService: ApplicationService) {}
|
||||||
|
|
||||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||||
const process = await this._applicationService
|
const process = await this._applicationService.getProcessById$(+route.params.processId).pipe(first()).toPromise();
|
||||||
.getProcessById$(+route.params.processId)
|
|
||||||
.pipe(first())
|
|
||||||
.toPromise();
|
|
||||||
|
|
||||||
// if (!(process?.type === 'cart')) {
|
// if (!(process?.type === 'cart')) {
|
||||||
// // TODO:
|
// // TODO:
|
||||||
|
|||||||
@@ -14,7 +14,10 @@ export class CanActivateCartGuard {
|
|||||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||||
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||||
let lastActivatedProcessId = (
|
let lastActivatedProcessId = (
|
||||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart').pipe(first()).toPromise()
|
await this._applicationService
|
||||||
|
.getLastActivatedProcessWithSectionAndType$('customer', 'cart')
|
||||||
|
.pipe(first())
|
||||||
|
.toPromise()
|
||||||
)?.id;
|
)?.id;
|
||||||
if (!lastActivatedProcessId) {
|
if (!lastActivatedProcessId) {
|
||||||
lastActivatedProcessId = Date.now();
|
lastActivatedProcessId = Date.now();
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ import { first } from 'rxjs/operators';
|
|||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class CanActivateCustomerOrdersWithProcessIdGuard {
|
export class CanActivateCustomerOrdersWithProcessIdGuard {
|
||||||
constructor(private readonly _applicationService: ApplicationService, private readonly _breadcrumbService: BreadcrumbService) {}
|
constructor(
|
||||||
|
private readonly _applicationService: ApplicationService,
|
||||||
|
private readonly _breadcrumbService: BreadcrumbService,
|
||||||
|
) {}
|
||||||
|
|
||||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||||
const process = await this._applicationService
|
const process = await this._applicationService.getProcessById$(+route.params.processId).pipe(first()).toPromise();
|
||||||
.getProcessById$(+route.params.processId)
|
|
||||||
.pipe(first())
|
|
||||||
.toPromise();
|
|
||||||
|
|
||||||
if (!process) {
|
if (!process) {
|
||||||
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||||
@@ -31,10 +31,7 @@ export class CanActivateCustomerOrdersWithProcessIdGuard {
|
|||||||
|
|
||||||
// Fix #3292: Alle Breadcrumbs die nichts mit dem aktuellen Prozess zu tun haben, müssen removed werden
|
// Fix #3292: Alle Breadcrumbs die nichts mit dem aktuellen Prozess zu tun haben, müssen removed werden
|
||||||
async removeBreadcrumbWithSameProcessId(route: ActivatedRouteSnapshot) {
|
async removeBreadcrumbWithSameProcessId(route: ActivatedRouteSnapshot) {
|
||||||
const crumbs = await this._breadcrumbService
|
const crumbs = await this._breadcrumbService.getBreadcrumbByKey$(+route.params.processId).pipe(first()).toPromise();
|
||||||
.getBreadcrumbByKey$(+route.params.processId)
|
|
||||||
.pipe(first())
|
|
||||||
.toPromise();
|
|
||||||
|
|
||||||
// Entferne alle Crumbs die nichts mit den Kundenbestellungen zu tun haben
|
// Entferne alle Crumbs die nichts mit den Kundenbestellungen zu tun haben
|
||||||
if (crumbs.length > 1) {
|
if (crumbs.length > 1) {
|
||||||
|
|||||||
@@ -17,11 +17,17 @@ export class CanActivateCustomerOrdersGuard {
|
|||||||
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||||
|
|
||||||
let lastActivatedProcessId = (
|
let lastActivatedProcessId = (
|
||||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart').pipe(first()).toPromise()
|
await this._applicationService
|
||||||
|
.getLastActivatedProcessWithSectionAndType$('customer', 'cart')
|
||||||
|
.pipe(first())
|
||||||
|
.toPromise()
|
||||||
)?.id;
|
)?.id;
|
||||||
|
|
||||||
const lastActivatedCartCheckoutProcessId = (
|
const lastActivatedCartCheckoutProcessId = (
|
||||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout').pipe(first()).toPromise()
|
await this._applicationService
|
||||||
|
.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout')
|
||||||
|
.pipe(first())
|
||||||
|
.toPromise()
|
||||||
)?.id;
|
)?.id;
|
||||||
|
|
||||||
const activatedProcessId = await this._applicationService.getActivatedProcessId$().pipe(first()).toPromise();
|
const activatedProcessId = await this._applicationService.getActivatedProcessId$().pipe(first()).toPromise();
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ import { first } from 'rxjs/operators';
|
|||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class CanActivateCustomerWithProcessIdGuard {
|
export class CanActivateCustomerWithProcessIdGuard {
|
||||||
constructor(private readonly _applicationService: ApplicationService, private readonly _breadcrumbService: BreadcrumbService) {}
|
constructor(
|
||||||
|
private readonly _applicationService: ApplicationService,
|
||||||
|
private readonly _breadcrumbService: BreadcrumbService,
|
||||||
|
) {}
|
||||||
|
|
||||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||||
const process = await this._applicationService
|
const process = await this._applicationService.getProcessById$(+route.params.processId).pipe(first()).toPromise();
|
||||||
.getProcessById$(+route.params.processId)
|
|
||||||
.pipe(first())
|
|
||||||
.toPromise();
|
|
||||||
|
|
||||||
// if (!(process?.type === 'cart')) {
|
// if (!(process?.type === 'cart')) {
|
||||||
// // TODO:
|
// // TODO:
|
||||||
@@ -37,10 +37,7 @@ export class CanActivateCustomerWithProcessIdGuard {
|
|||||||
|
|
||||||
// Fix #3292: Alle Breadcrumbs die nichts mit dem aktuellen Prozess zu tun haben, müssen removed werden
|
// Fix #3292: Alle Breadcrumbs die nichts mit dem aktuellen Prozess zu tun haben, müssen removed werden
|
||||||
async removeBreadcrumbWithSameProcessId(route: ActivatedRouteSnapshot) {
|
async removeBreadcrumbWithSameProcessId(route: ActivatedRouteSnapshot) {
|
||||||
const crumbs = await this._breadcrumbService
|
const crumbs = await this._breadcrumbService.getBreadcrumbByKey$(+route.params.processId).pipe(first()).toPromise();
|
||||||
.getBreadcrumbByKey$(+route.params.processId)
|
|
||||||
.pipe(first())
|
|
||||||
.toPromise();
|
|
||||||
|
|
||||||
// Entferne alle Crumbs die nichts mit der Kundensuche zu tun haben
|
// Entferne alle Crumbs die nichts mit der Kundensuche zu tun haben
|
||||||
if (crumbs.length > 1) {
|
if (crumbs.length > 1) {
|
||||||
|
|||||||
@@ -17,15 +17,24 @@ export class CanActivateCustomerGuard {
|
|||||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||||
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||||
let lastActivatedProcessId = (
|
let lastActivatedProcessId = (
|
||||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart').pipe(first()).toPromise()
|
await this._applicationService
|
||||||
|
.getLastActivatedProcessWithSectionAndType$('customer', 'cart')
|
||||||
|
.pipe(first())
|
||||||
|
.toPromise()
|
||||||
)?.id;
|
)?.id;
|
||||||
|
|
||||||
const lastActivatedCartCheckoutProcessId = (
|
const lastActivatedCartCheckoutProcessId = (
|
||||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout').pipe(first()).toPromise()
|
await this._applicationService
|
||||||
|
.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout')
|
||||||
|
.pipe(first())
|
||||||
|
.toPromise()
|
||||||
)?.id;
|
)?.id;
|
||||||
|
|
||||||
const lastActivatedGoodsOutProcessId = (
|
const lastActivatedGoodsOutProcessId = (
|
||||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'goods-out').pipe(first()).toPromise()
|
await this._applicationService
|
||||||
|
.getLastActivatedProcessWithSectionAndType$('customer', 'goods-out')
|
||||||
|
.pipe(first())
|
||||||
|
.toPromise()
|
||||||
)?.id;
|
)?.id;
|
||||||
|
|
||||||
const activatedProcessId = await this._applicationService.getActivatedProcessId$().pipe(first()).toPromise();
|
const activatedProcessId = await this._applicationService.getActivatedProcessId$().pipe(first()).toPromise();
|
||||||
|
|||||||
@@ -3,13 +3,21 @@ import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
|||||||
import { ApplicationService } from '@core/application';
|
import { ApplicationService } from '@core/application';
|
||||||
import { Config } from '@core/config';
|
import { Config } from '@core/config';
|
||||||
import { first } from 'rxjs/operators';
|
import { first } from 'rxjs/operators';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class CanActivateGoodsInGuard {
|
export class CanActivateGoodsInGuard {
|
||||||
constructor(private readonly _applicationService: ApplicationService, private readonly _config: Config) {}
|
constructor(
|
||||||
|
private readonly _applicationService: ApplicationService,
|
||||||
|
private readonly _config: Config,
|
||||||
|
) {}
|
||||||
|
|
||||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||||
const process = await this._applicationService.getProcessById$(this._config.get('process.ids.goodsIn')).pipe(first()).toPromise();
|
const pid = this._config.get('process.ids.goodsIn', z.number());
|
||||||
|
const process = await this._applicationService
|
||||||
|
.getProcessById$(pid)
|
||||||
|
.pipe(first())
|
||||||
|
.toPromise();
|
||||||
if (!process) {
|
if (!process) {
|
||||||
await this._applicationService.createProcess({
|
await this._applicationService.createProcess({
|
||||||
id: this._config.get('process.ids.goodsIn'),
|
id: this._config.get('process.ids.goodsIn'),
|
||||||
@@ -18,7 +26,9 @@ export class CanActivateGoodsInGuard {
|
|||||||
name: '',
|
name: '',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this._applicationService.activateProcess(this._config.get('process.ids.goodsIn'));
|
this._applicationService.activateProcess(
|
||||||
|
this._config.get('process.ids.goodsIn'),
|
||||||
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ import { first } from 'rxjs/operators';
|
|||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class CanActivateGoodsOutWithProcessIdGuard {
|
export class CanActivateGoodsOutWithProcessIdGuard {
|
||||||
constructor(private readonly _applicationService: ApplicationService, private readonly _breadcrumbService: BreadcrumbService) {}
|
constructor(
|
||||||
|
private readonly _applicationService: ApplicationService,
|
||||||
|
private readonly _breadcrumbService: BreadcrumbService,
|
||||||
|
) {}
|
||||||
|
|
||||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||||
const process = await this._applicationService
|
const process = await this._applicationService.getProcessById$(+route.params.processId).pipe(first()).toPromise();
|
||||||
.getProcessById$(+route.params.processId)
|
|
||||||
.pipe(first())
|
|
||||||
.toPromise();
|
|
||||||
|
|
||||||
if (!process) {
|
if (!process) {
|
||||||
// const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
// const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||||
@@ -31,10 +31,7 @@ export class CanActivateGoodsOutWithProcessIdGuard {
|
|||||||
|
|
||||||
// Fix #3292: Alle Breadcrumbs die nichts mit dem aktuellen Prozess zu tun haben, müssen removed werden
|
// Fix #3292: Alle Breadcrumbs die nichts mit dem aktuellen Prozess zu tun haben, müssen removed werden
|
||||||
async removeBreadcrumbWithSameProcessId(route: ActivatedRouteSnapshot) {
|
async removeBreadcrumbWithSameProcessId(route: ActivatedRouteSnapshot) {
|
||||||
const crumbs = await this._breadcrumbService
|
const crumbs = await this._breadcrumbService.getBreadcrumbByKey$(+route.params.processId).pipe(first()).toPromise();
|
||||||
.getBreadcrumbByKey$(+route.params.processId)
|
|
||||||
.pipe(first())
|
|
||||||
.toPromise();
|
|
||||||
|
|
||||||
// Entferne alle Crumbs die nichts mit der Warenausgabe zu tun haben
|
// Entferne alle Crumbs die nichts mit der Warenausgabe zu tun haben
|
||||||
if (crumbs.length > 1) {
|
if (crumbs.length > 1) {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export class CanActivateGoodsOutGuard {
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly _applicationService: ApplicationService,
|
private readonly _applicationService: ApplicationService,
|
||||||
private readonly _checkoutService: DomainCheckoutService,
|
private readonly _checkoutService: DomainCheckoutService,
|
||||||
private readonly _router: Router
|
private readonly _router: Router,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
// !!! Ticket #3272 Code soll vorerst bestehen bleiben. Prozess Warenausgabe soll wieder Vorgang heißen (wie aktuell im Produktiv), bis zum neuen Navigationskonzept
|
// !!! Ticket #3272 Code soll vorerst bestehen bleiben. Prozess Warenausgabe soll wieder Vorgang heißen (wie aktuell im Produktiv), bis zum neuen Navigationskonzept
|
||||||
@@ -103,11 +103,17 @@ export class CanActivateGoodsOutGuard {
|
|||||||
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||||
|
|
||||||
let lastActivatedProcessId = (
|
let lastActivatedProcessId = (
|
||||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart').pipe(first()).toPromise()
|
await this._applicationService
|
||||||
|
.getLastActivatedProcessWithSectionAndType$('customer', 'cart')
|
||||||
|
.pipe(first())
|
||||||
|
.toPromise()
|
||||||
)?.id;
|
)?.id;
|
||||||
|
|
||||||
const lastActivatedCartCheckoutProcessId = (
|
const lastActivatedCartCheckoutProcessId = (
|
||||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout').pipe(first()).toPromise()
|
await this._applicationService
|
||||||
|
.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout')
|
||||||
|
.pipe(first())
|
||||||
|
.toPromise()
|
||||||
)?.id;
|
)?.id;
|
||||||
|
|
||||||
const activatedProcessId = await this._applicationService.getActivatedProcessId$().pipe(first()).toPromise();
|
const activatedProcessId = await this._applicationService.getActivatedProcessId$().pipe(first()).toPromise();
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ import { first } from 'rxjs/operators';
|
|||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class CanActivatePackageInspectionGuard {
|
export class CanActivatePackageInspectionGuard {
|
||||||
constructor(private readonly _applicationService: ApplicationService, private readonly _config: Config) {}
|
constructor(
|
||||||
|
private readonly _applicationService: ApplicationService,
|
||||||
|
private readonly _config: Config,
|
||||||
|
) {}
|
||||||
|
|
||||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||||
const process = await this._applicationService
|
const process = await this._applicationService
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ import { first } from 'rxjs/operators';
|
|||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class CanActivateProductWithProcessIdGuard {
|
export class CanActivateProductWithProcessIdGuard {
|
||||||
constructor(private readonly _applicationService: ApplicationService, private readonly _breadcrumbService: BreadcrumbService) {}
|
constructor(
|
||||||
|
private readonly _applicationService: ApplicationService,
|
||||||
|
private readonly _breadcrumbService: BreadcrumbService,
|
||||||
|
) {}
|
||||||
|
|
||||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||||
const process = await this._applicationService
|
const process = await this._applicationService.getProcessById$(+route.params.processId).pipe(first()).toPromise();
|
||||||
.getProcessById$(+route.params.processId)
|
|
||||||
.pipe(first())
|
|
||||||
.toPromise();
|
|
||||||
|
|
||||||
// if (!(process?.type === 'cart')) {
|
// if (!(process?.type === 'cart')) {
|
||||||
// // TODO:
|
// // TODO:
|
||||||
@@ -37,10 +37,7 @@ export class CanActivateProductWithProcessIdGuard {
|
|||||||
|
|
||||||
// Fix #3292: Alle Breadcrumbs die nichts mit dem aktuellen Prozess zu tun haben, müssen removed werden
|
// Fix #3292: Alle Breadcrumbs die nichts mit dem aktuellen Prozess zu tun haben, müssen removed werden
|
||||||
async removeBreadcrumbWithSameProcessId(route: ActivatedRouteSnapshot) {
|
async removeBreadcrumbWithSameProcessId(route: ActivatedRouteSnapshot) {
|
||||||
const crumbs = await this._breadcrumbService
|
const crumbs = await this._breadcrumbService.getBreadcrumbByKey$(+route.params.processId).pipe(first()).toPromise();
|
||||||
.getBreadcrumbByKey$(+route.params.processId)
|
|
||||||
.pipe(first())
|
|
||||||
.toPromise();
|
|
||||||
|
|
||||||
// Entferne alle Crumbs die nichts mit der Artikelsuche zu tun haben
|
// Entferne alle Crumbs die nichts mit der Artikelsuche zu tun haben
|
||||||
if (crumbs.length > 1) {
|
if (crumbs.length > 1) {
|
||||||
|
|||||||
@@ -16,15 +16,24 @@ export class CanActivateProductGuard {
|
|||||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||||
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||||
let lastActivatedProcessId = (
|
let lastActivatedProcessId = (
|
||||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart').pipe(first()).toPromise()
|
await this._applicationService
|
||||||
|
.getLastActivatedProcessWithSectionAndType$('customer', 'cart')
|
||||||
|
.pipe(first())
|
||||||
|
.toPromise()
|
||||||
)?.id;
|
)?.id;
|
||||||
|
|
||||||
const lastActivatedCartCheckoutProcessId = (
|
const lastActivatedCartCheckoutProcessId = (
|
||||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout').pipe(first()).toPromise()
|
await this._applicationService
|
||||||
|
.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout')
|
||||||
|
.pipe(first())
|
||||||
|
.toPromise()
|
||||||
)?.id;
|
)?.id;
|
||||||
|
|
||||||
const lastActivatedGoodsOutProcessId = (
|
const lastActivatedGoodsOutProcessId = (
|
||||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'goods-out').pipe(first()).toPromise()
|
await this._applicationService
|
||||||
|
.getLastActivatedProcessWithSectionAndType$('customer', 'goods-out')
|
||||||
|
.pipe(first())
|
||||||
|
.toPromise()
|
||||||
)?.id;
|
)?.id;
|
||||||
|
|
||||||
const activatedProcessId = await this._applicationService.getActivatedProcessId$().pipe(first()).toPromise();
|
const activatedProcessId = await this._applicationService.getActivatedProcessId$().pipe(first()).toPromise();
|
||||||
|
|||||||
@@ -9,11 +9,14 @@ export class CanActivateRemissionGuard {
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly _applicationService: ApplicationService,
|
private readonly _applicationService: ApplicationService,
|
||||||
private readonly _config: Config,
|
private readonly _config: Config,
|
||||||
private readonly _router: Router
|
private readonly _router: Router,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||||
const process = await this._applicationService.getProcessById$(this._config.get('process.ids.remission')).pipe(first()).toPromise();
|
const process = await this._applicationService
|
||||||
|
.getProcessById$(this._config.get('process.ids.remission'))
|
||||||
|
.pipe(first())
|
||||||
|
.toPromise();
|
||||||
if (!process) {
|
if (!process) {
|
||||||
await this._applicationService.createProcess({
|
await this._applicationService.createProcess({
|
||||||
id: this._config.get('process.ids.remission'),
|
id: this._config.get('process.ids.remission'),
|
||||||
|
|||||||
@@ -6,10 +6,16 @@ import { first } from 'rxjs/operators';
|
|||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class CanActivateTaskCalendarGuard {
|
export class CanActivateTaskCalendarGuard {
|
||||||
constructor(private readonly _applicationService: ApplicationService, private readonly _config: Config) {}
|
constructor(
|
||||||
|
private readonly _applicationService: ApplicationService,
|
||||||
|
private readonly _config: Config,
|
||||||
|
) {}
|
||||||
|
|
||||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||||
const process = await this._applicationService.getProcessById$(this._config.get('process.ids.taskCalendar')).pipe(first()).toPromise();
|
const process = await this._applicationService
|
||||||
|
.getProcessById$(this._config.get('process.ids.taskCalendar'))
|
||||||
|
.pipe(first())
|
||||||
|
.toPromise();
|
||||||
if (!process) {
|
if (!process) {
|
||||||
await this._applicationService.createProcess({
|
await this._applicationService.createProcess({
|
||||||
id: this._config.get('process.ids.taskCalendar'),
|
id: this._config.get('process.ids.taskCalendar'),
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
|
|||||||
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';
|
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';
|
||||||
import { AuthService } from '@core/auth';
|
import { AuthService } from '@core/auth';
|
||||||
import { ScanAdapterService } from '@adapter/scan';
|
import { ScanAdapterService } from '@adapter/scan';
|
||||||
import { AuthService as IsaAuthService } from '@swagger/isa';
|
import { AuthService as IsaAuthService } from '@generated/swagger/isa-api';
|
||||||
import { UiConfirmModalComponent, UiErrorModalComponent, UiModalResult, UiModalService } from '@ui/modal';
|
import { UiConfirmModalComponent, UiErrorModalComponent, UiModalResult, UiModalService } from '@ui/modal';
|
||||||
import { EnvironmentService } from '@core/environment';
|
import { EnvironmentService } from '@core/environment';
|
||||||
import { injectNetworkStatus$ } from '../services/network-status.service';
|
import { injectNetworkStatus$ } from '../services/network-status.service';
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { take } from 'rxjs/operators';
|
|||||||
|
|
||||||
export const ProcessIdGuard: CanActivateFn = async (
|
export const ProcessIdGuard: CanActivateFn = async (
|
||||||
route: ActivatedRouteSnapshot,
|
route: ActivatedRouteSnapshot,
|
||||||
state: RouterStateSnapshot
|
state: RouterStateSnapshot,
|
||||||
): Promise<boolean | UrlTree> => {
|
): Promise<boolean | UrlTree> => {
|
||||||
const application = inject(ApplicationService);
|
const application = inject(ApplicationService);
|
||||||
const router = inject(Router);
|
const router = inject(Router);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Component, ChangeDetectionStrategy } from '@angular/core';
|
|||||||
selector: 'app-main',
|
selector: 'app-main',
|
||||||
templateUrl: 'main.component.html',
|
templateUrl: 'main.component.html',
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class MainComponent {
|
export class MainComponent {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Platform, PlatformModule } from '@angular/cdk/platform';
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { BranchSelectorComponent } from '@shared/components/branch-selector';
|
import { BranchSelectorComponent } from '@shared/components/branch-selector';
|
||||||
import { BranchDTO } from '@swagger/checkout';
|
import { BranchDTO } from '@generated/swagger/checkout-api';
|
||||||
import { BehaviorSubject } from 'rxjs';
|
import { BehaviorSubject } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -10,7 +10,6 @@ import { BehaviorSubject } from 'rxjs';
|
|||||||
templateUrl: 'preview.component.html',
|
templateUrl: 'preview.component.html',
|
||||||
styleUrls: ['preview.component.css'],
|
styleUrls: ['preview.component.css'],
|
||||||
imports: [CommonModule, BranchSelectorComponent, PlatformModule],
|
imports: [CommonModule, BranchSelectorComponent, PlatformModule],
|
||||||
standalone: true,
|
|
||||||
})
|
})
|
||||||
export class PreviewComponent implements OnInit {
|
export class PreviewComponent implements OnInit {
|
||||||
selectedBranch$ = new BehaviorSubject<BranchDTO>({});
|
selectedBranch$ = new BehaviorSubject<BranchDTO>({});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Injectable, Injector } from '@angular/core';
|
import { Injectable, Injector } from '@angular/core';
|
||||||
import { LogLevel, LogProvider } from '@core/logger';
|
import { LogLevel, LogProvider } from '@core/logger';
|
||||||
import { UserStateService } from '@swagger/isa';
|
import { UserStateService } from '@generated/swagger/isa-api';
|
||||||
import { environment } from '../../environments/environment';
|
import { environment } from '../../environments/environment';
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ import { Observable } from 'rxjs';
|
|||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class ProcessIdResolver {
|
export class ProcessIdResolver {
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
resolve(route: ActivatedRouteSnapshot): Observable<number> | Promise<number> | number {
|
resolve(route: ActivatedRouteSnapshot): Observable<number> | Promise<number> | number {
|
||||||
return route.params.processId;
|
return route.params.processId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ import { ApplicationService } from '@core/application';
|
|||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
export abstract class SectionResolver {
|
export abstract class SectionResolver {
|
||||||
constructor(protected section: 'customer' | 'branch', protected applicationService: ApplicationService) {}
|
constructor(
|
||||||
|
protected section: 'customer' | 'branch',
|
||||||
|
protected applicationService: ApplicationService,
|
||||||
|
) {}
|
||||||
|
|
||||||
resolve(route: ActivatedRouteSnapshot): Observable<string> | Promise<string> | string {
|
resolve(route: ActivatedRouteSnapshot): Observable<string> | Promise<string> | string {
|
||||||
this.applicationService.setSection(this.section);
|
this.applicationService.setSection(this.section);
|
||||||
|
|||||||
@@ -1,28 +1,32 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Logger, LogLevel } from '@core/logger';
|
import { Logger, LogLevel } from '@core/logger';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { UserStateService } from '@swagger/isa';
|
|
||||||
import { debounceTime, switchMap, takeUntil } from 'rxjs/operators';
|
import { debounceTime, switchMap, takeUntil } from 'rxjs/operators';
|
||||||
import { RootState } from './root.state';
|
import { RootState } from './root.state';
|
||||||
import packageInfo from 'packageJson';
|
import packageInfo from 'packageJson';
|
||||||
import { environment } from '../../environments/environment';
|
import { environment } from '../../environments/environment';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { AuthService } from '@core/auth';
|
import { AuthService } from '@core/auth';
|
||||||
|
import { injectStorage, UserStorageProvider } from '@isa/core/storage';
|
||||||
|
import { isEqual } from 'lodash';
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class RootStateService {
|
export class RootStateService {
|
||||||
static LOCAL_STORAGE_KEY = 'ISA_APP_INITIALSTATE';
|
static LOCAL_STORAGE_KEY = 'ISA_APP_INITIALSTATE';
|
||||||
|
|
||||||
|
#storage = injectStorage(UserStorageProvider);
|
||||||
|
|
||||||
private _cancelSave = new Subject<void>();
|
private _cancelSave = new Subject<void>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly _authService: AuthService,
|
private readonly _authService: AuthService,
|
||||||
private readonly _userStateService: UserStateService,
|
|
||||||
private _logger: Logger,
|
private _logger: Logger,
|
||||||
private _store: Store,
|
private _store: Store,
|
||||||
) {
|
) {
|
||||||
if (!environment.production) {
|
if (!environment.production) {
|
||||||
console.log('Die UserState kann in der Konsole mit der Funktion "clearUserState()" geleert werden.');
|
console.log(
|
||||||
|
'Die UserState kann in der Konsole mit der Funktion "clearUserState()" geleert werden.',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
window['clearUserState'] = () => {
|
window['clearUserState'] = () => {
|
||||||
@@ -43,9 +47,17 @@ export class RootStateService {
|
|||||||
takeUntil(this._cancelSave),
|
takeUntil(this._cancelSave),
|
||||||
debounceTime(1000),
|
debounceTime(1000),
|
||||||
switchMap((state) => {
|
switchMap((state) => {
|
||||||
const raw = JSON.stringify({ ...state, version: packageInfo.version, sub: this._authService.getClaimByKey('sub') });
|
const data = {
|
||||||
RootStateService.SaveToLocalStorageRaw(raw);
|
...state,
|
||||||
return this._userStateService.UserStateSetUserState({ content: raw });
|
version: packageInfo.version,
|
||||||
|
sub: this._authService.getClaimByKey('sub'),
|
||||||
|
};
|
||||||
|
RootStateService.SaveToLocalStorageRaw(JSON.stringify(data));
|
||||||
|
return this.#storage.set('state', {
|
||||||
|
...state,
|
||||||
|
version: packageInfo.version,
|
||||||
|
sub: this._authService.getClaimByKey('sub'),
|
||||||
|
});
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.subscribe();
|
.subscribe();
|
||||||
@@ -56,16 +68,15 @@ export class RootStateService {
|
|||||||
*/
|
*/
|
||||||
async load(): Promise<boolean> {
|
async load(): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
const res = await this._userStateService.UserStateGetUserState().toPromise();
|
const res = await this.#storage.get('state');
|
||||||
|
|
||||||
const resContent = res?.result?.content ?? null;
|
|
||||||
const storageContent = RootStateService.LoadFromLocalStorageRaw();
|
const storageContent = RootStateService.LoadFromLocalStorageRaw();
|
||||||
|
|
||||||
if (resContent) {
|
if (res) {
|
||||||
RootStateService.SaveToLocalStorageRaw(res.result.content);
|
RootStateService.SaveToLocalStorageRaw(JSON.stringify(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resContent !== storageContent) {
|
if (!isEqual(res, storageContent)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -77,7 +88,7 @@ export class RootStateService {
|
|||||||
async clear() {
|
async clear() {
|
||||||
try {
|
try {
|
||||||
this._cancelSave.next();
|
this._cancelSave.next();
|
||||||
await this._userStateService.UserStateResetUserState().toPromise();
|
await this.#storage.clear('state');
|
||||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||||
RootStateService.RemoveFromLocalStorage();
|
RootStateService.RemoveFromLocalStorage();
|
||||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||||
|
|||||||
@@ -7,9 +7,14 @@ import { AuthService } from '@core/auth';
|
|||||||
templateUrl: 'token-login.component.html',
|
templateUrl: 'token-login.component.html',
|
||||||
styleUrls: ['token-login.component.scss'],
|
styleUrls: ['token-login.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class TokenLoginComponent implements OnInit {
|
export class TokenLoginComponent implements OnInit {
|
||||||
constructor(private _route: ActivatedRoute, private _authService: AuthService, private _router: Router) {}
|
constructor(
|
||||||
|
private _route: ActivatedRoute,
|
||||||
|
private _authService: AuthService,
|
||||||
|
private _router: Router,
|
||||||
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
if (this._route.snapshot.params.token && !this._authService.isAuthenticated()) {
|
if (this._route.snapshot.params.token && !this._authService.isAuthenticated()) {
|
||||||
|
|||||||
@@ -1,219 +1,222 @@
|
|||||||
/* cyrillic-ext */
|
/* cyrillic-ext */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-400-cyrillic-ext1.woff2') format('woff2');
|
src: url("./Open_Sans-400-cyrillic-ext1.woff2") format("woff2");
|
||||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||||
}
|
}
|
||||||
/* cyrillic */
|
/* cyrillic */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-400-cyrillic2.woff2') format('woff2');
|
src: url("./Open_Sans-400-cyrillic2.woff2") format("woff2");
|
||||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||||
}
|
}
|
||||||
/* greek-ext */
|
/* greek-ext */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-400-greek-ext3.woff2') format('woff2');
|
src: url("./Open_Sans-400-greek-ext3.woff2") format("woff2");
|
||||||
unicode-range: U+1F00-1FFF;
|
unicode-range: U+1F00-1FFF;
|
||||||
}
|
}
|
||||||
/* greek */
|
/* greek */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-400-greek4.woff2') format('woff2');
|
src: url("./Open_Sans-400-greek4.woff2") format("woff2");
|
||||||
unicode-range: U+0370-03FF;
|
unicode-range: U+0370-03FF;
|
||||||
}
|
}
|
||||||
/* hebrew */
|
/* hebrew */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-400-hebrew5.woff2') format('woff2');
|
src: url("./Open_Sans-400-hebrew5.woff2") format("woff2");
|
||||||
unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
|
unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
|
||||||
}
|
}
|
||||||
/* vietnamese */
|
/* vietnamese */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-400-vietnamese6.woff2') format('woff2');
|
src: url("./Open_Sans-400-vietnamese6.woff2") format("woff2");
|
||||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
|
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
|
||||||
}
|
}
|
||||||
/* latin-ext */
|
/* latin-ext */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-400-latin-ext7.woff2') format('woff2');
|
src: url("./Open_Sans-400-latin-ext7.woff2") format("woff2");
|
||||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||||
}
|
}
|
||||||
/* latin */
|
/* latin */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-400-latin8.woff2') format('woff2');
|
src: url("./Open_Sans-400-latin8.woff2") format("woff2");
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
|
unicode-range:
|
||||||
U+2212, U+2215, U+FEFF, U+FFFD;
|
U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
|
||||||
|
U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
}
|
}
|
||||||
/* cyrillic-ext */
|
/* cyrillic-ext */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-600-cyrillic-ext9.woff2') format('woff2');
|
src: url("./Open_Sans-600-cyrillic-ext9.woff2") format("woff2");
|
||||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||||
}
|
}
|
||||||
/* cyrillic */
|
/* cyrillic */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-600-cyrillic10.woff2') format('woff2');
|
src: url("./Open_Sans-600-cyrillic10.woff2") format("woff2");
|
||||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||||
}
|
}
|
||||||
/* greek-ext */
|
/* greek-ext */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-600-greek-ext11.woff2') format('woff2');
|
src: url("./Open_Sans-600-greek-ext11.woff2") format("woff2");
|
||||||
unicode-range: U+1F00-1FFF;
|
unicode-range: U+1F00-1FFF;
|
||||||
}
|
}
|
||||||
/* greek */
|
/* greek */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-600-greek12.woff2') format('woff2');
|
src: url("./Open_Sans-600-greek12.woff2") format("woff2");
|
||||||
unicode-range: U+0370-03FF;
|
unicode-range: U+0370-03FF;
|
||||||
}
|
}
|
||||||
/* hebrew */
|
/* hebrew */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-600-hebrew13.woff2') format('woff2');
|
src: url("./Open_Sans-600-hebrew13.woff2") format("woff2");
|
||||||
unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
|
unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
|
||||||
}
|
}
|
||||||
/* vietnamese */
|
/* vietnamese */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-600-vietnamese14.woff2') format('woff2');
|
src: url("./Open_Sans-600-vietnamese14.woff2") format("woff2");
|
||||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
|
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
|
||||||
}
|
}
|
||||||
/* latin-ext */
|
/* latin-ext */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-600-latin-ext15.woff2') format('woff2');
|
src: url("./Open_Sans-600-latin-ext15.woff2") format("woff2");
|
||||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||||
}
|
}
|
||||||
/* latin */
|
/* latin */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-600-latin16.woff2') format('woff2');
|
src: url("./Open_Sans-600-latin16.woff2") format("woff2");
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
|
unicode-range:
|
||||||
U+2212, U+2215, U+FEFF, U+FFFD;
|
U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
|
||||||
|
U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
}
|
}
|
||||||
/* cyrillic-ext */
|
/* cyrillic-ext */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-700-cyrillic-ext17.woff2') format('woff2');
|
src: url("./Open_Sans-700-cyrillic-ext17.woff2") format("woff2");
|
||||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||||
}
|
}
|
||||||
/* cyrillic */
|
/* cyrillic */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-700-cyrillic18.woff2') format('woff2');
|
src: url("./Open_Sans-700-cyrillic18.woff2") format("woff2");
|
||||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||||
}
|
}
|
||||||
/* greek-ext */
|
/* greek-ext */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-700-greek-ext19.woff2') format('woff2');
|
src: url("./Open_Sans-700-greek-ext19.woff2") format("woff2");
|
||||||
unicode-range: U+1F00-1FFF;
|
unicode-range: U+1F00-1FFF;
|
||||||
}
|
}
|
||||||
/* greek */
|
/* greek */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-700-greek20.woff2') format('woff2');
|
src: url("./Open_Sans-700-greek20.woff2") format("woff2");
|
||||||
unicode-range: U+0370-03FF;
|
unicode-range: U+0370-03FF;
|
||||||
}
|
}
|
||||||
/* hebrew */
|
/* hebrew */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-700-hebrew21.woff2') format('woff2');
|
src: url("./Open_Sans-700-hebrew21.woff2") format("woff2");
|
||||||
unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
|
unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
|
||||||
}
|
}
|
||||||
/* vietnamese */
|
/* vietnamese */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-700-vietnamese22.woff2') format('woff2');
|
src: url("./Open_Sans-700-vietnamese22.woff2") format("woff2");
|
||||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
|
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
|
||||||
}
|
}
|
||||||
/* latin-ext */
|
/* latin-ext */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-700-latin-ext23.woff2') format('woff2');
|
src: url("./Open_Sans-700-latin-ext23.woff2") format("woff2");
|
||||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||||
}
|
}
|
||||||
/* latin */
|
/* latin */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: "Open Sans";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-stretch: normal;
|
font-stretch: normal;
|
||||||
src: url('./Open_Sans-700-latin24.woff2') format('woff2');
|
src: url("./Open_Sans-700-latin24.woff2") format("woff2");
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
|
unicode-range:
|
||||||
U+2212, U+2215, U+FEFF, U+FFFD;
|
U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
|
||||||
|
U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
},
|
},
|
||||||
"@domain/checkout": {
|
"@domain/checkout": {
|
||||||
"olaExpiration": "5m"
|
"olaExpiration": "5m"
|
||||||
},
|
},
|
||||||
"@swagger/isa": {
|
"@swagger/isa": {
|
||||||
"rootUrl": "https://isa-integration.paragon-data.net/isa/v1"
|
"rootUrl": "https://isa-integration.paragon-data.net/isa/v1"
|
||||||
},
|
},
|
||||||
@@ -72,8 +72,8 @@
|
|||||||
},
|
},
|
||||||
"checkForUpdates": 900000,
|
"checkForUpdates": 900000,
|
||||||
"licence": {
|
"licence": {
|
||||||
"scandit": "Ae8F2Wx2RMq5Lvn7UUAlWzVFZTt2+ubMAF8XtDpmPlNkBeG/LWs1M7AbgDW0LQqYLnszClEENaEHS56/6Ts2vrJ1Ux03CXUjK3jUvZpF5OchXR1CpnmpepJ6WxPCd7LMVHUGG1BbwPLDTFjP3y8uT0caTSmmGrYQWAs4CZcEF+ZBabP0z7vfm+hCZF/ebj9qqCJZcW8nH/n19hohshllzYBjFXjh87P2lIh1s6yZS3OaQWWXo/o0AKdxx7T6CVyR0/G5zq6uYJWf6rs3euUBEhpzOZHbHZK86Lvy2AVBEyVkkcttlDW1J2fA4l1W1JV/Xibz8AQV6kG482EpGF42KEoK48paZgX3e1AQsqUtmqzw294dcP4zMVstnw5/WrwKKi/5E/nOOJT2txYP1ZufIjPrwNFsqTlv7xCQlHjMzFGYwT816yD5qLRLbwOtjrkUPXNZLZ06T4upvWwJDmm8XgdeoDqMjHdcO4lwji1bl9EiIYJ/2qnsk9yZ2FqSaHzn4cbiL0f5u2HFlNAP0GUujGRlthGhHi6o4dFU+WAxKsFMKVt+SfoQUazNKHFVQgiAklTIZxIc/HUVzRvOLMxf+wFDerraBtcqGJg+g/5mrWYqeDBGhCBHtKiYf6244IJ4afzNTiH1/30SJcRzXwbEa3A7q1fJTx9/nLTOfVPrJKBQs7f/OQs2dA7LDCel8mzXdbjvsNQaeU5+iCIAq6zbTNKy1xT8wwj+VZrQmtNJs+qeznD+u29nCM24h8xCmRpvNPo4/Mww/lrTNrrNwLBSn1pMIwsH7yS9hH0v0oNAM3A6bVtk1D9qEkbyw+xZa+MZGpMP0D0CdcsqHalPcm5r/Ik="
|
"scandit": "ASq1ZCbuDs0nJ4cPGkFOSkQEBHSL/kuljVAq2ttwz2Q5CEwULWAlasJIkjsIe/nptzNx1IBSxwDPWh0gXmvF08BRBDTzDUELdX6q02N/HUddSHE4A1dMXoFg+I8of+iZQijQIogxmP5RfSpj6ixzD2cGV0w+BG6o9xRXG4lEv9vNAOC3+emfcuVj2Whmfbuzao4HcWweVSz4HJh8dcbxTPF10MH8qR4kkV7fNWIF+PaYww69relfuvrkgdbWPcLs4Xb7WW4AISX9pTmJmSuv2LvD9gMoPNlmhdTWi+qFcmgZiPRDb1I0Bldo7jKLdboylEXkVQVWF1D2fv3iO5BrijG+n52XQd3ew49/1ssJi6dWhxiZQMlN+mz7cfSPmGzJc0eqaf52tEA8PkIupXjly/6dckSVcqTsex+wHcQuTinyW2bu9/YY3ZTMCp5du+lFZBD+AQSsq7EALzzithpijNG3jQka/8yRSHPBP6JtfobMdbv7SlAESslnN5R5lKJms4HnSm4CwxBAX2sUrhQeuit74/5pwe8qI+CaEGzjKYfmcRhFXd+Kz/ySV3HyrVuieH6+6ytBjGh3EkwGvQ8Ovu4KsruWAyAjHwRyBdrFIRYyLWdou77VH8gSLwHi69QsMGshcnYaREpqDEb5LLR9Ok7jP5IjMyPzX4USS327G9f4I8ujTaCKXQ9a384yV/wP9IeSuJld4dgdGy80rDP2sWZ+NJ65cNWpAfi/Nmbm6ucjICoUHILtchyx/w/YNYUzfCWFjUWHn83TzG+31f3dkjWoI3XpCOg5RKREs55htHSAyZtYhYiQr1FxDVFNEQI2MrDR0fBt2qOeZB08yA=="
|
||||||
},
|
},
|
||||||
"gender": {
|
"gender": {
|
||||||
"0": "Keine Anrede",
|
"0": "Keine Anrede",
|
||||||
"1": "Enby",
|
"1": "Enby",
|
||||||
@@ -81,4 +81,4 @@
|
|||||||
"4": "Frau"
|
"4": "Frau"
|
||||||
},
|
},
|
||||||
"@shared/icon": "/assets/icons.json"
|
"@shared/icon": "/assets/icons.json"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,87 +1,87 @@
|
|||||||
{
|
{
|
||||||
"title": "ISA - Local",
|
"title": "ISA - Local",
|
||||||
"silentRefresh": {
|
"silentRefresh": {
|
||||||
"interval": 300000
|
"interval": 300000
|
||||||
},
|
},
|
||||||
"debug": true,
|
"debug": true,
|
||||||
"dev-scanner": true,
|
"dev-scanner": true,
|
||||||
"@cdn/product-image": {
|
"@cdn/product-image": {
|
||||||
"url": "https://produktbilder.paragon-data.net"
|
"url": "https://produktbilder.paragon-data.net"
|
||||||
},
|
},
|
||||||
"@core/auth": {
|
"@core/auth": {
|
||||||
"issuer": "https://sso-test.paragon-data.de",
|
"issuer": "https://sso-test.paragon-data.de",
|
||||||
"clientId": "isa-client",
|
"clientId": "isa-client",
|
||||||
"responseType": "code",
|
"responseType": "code",
|
||||||
"scope": "openid profile cmf_user isa-isa-webapi isa-checkout-webapi isa-cat-webapi isa-ava-webapi isa-crm-webapi isa-review-webapi isa-kpi-webapi isa-oms-webapi isa-nbo-webapi isa-print-webapi eis-service isa-inv-webapi isa-wws-webapi",
|
"scope": "openid profile cmf_user isa-isa-webapi isa-checkout-webapi isa-cat-webapi isa-ava-webapi isa-crm-webapi isa-review-webapi isa-kpi-webapi isa-oms-webapi isa-nbo-webapi isa-print-webapi eis-service isa-inv-webapi isa-wws-webapi",
|
||||||
"showDebugInformation": true
|
"showDebugInformation": true
|
||||||
},
|
},
|
||||||
"@core/logger": {
|
"@core/logger": {
|
||||||
"logLevel": "debug"
|
"logLevel": "debug"
|
||||||
},
|
},
|
||||||
"@swagger/isa": {
|
"@swagger/isa": {
|
||||||
"rootUrl": "https://isa-test.paragon-data.net/isa/v1"
|
"rootUrl": "https://isa-test.paragon-data.net/isa/v1"
|
||||||
},
|
},
|
||||||
"@swagger/cat": {
|
"@swagger/cat": {
|
||||||
"rootUrl": "https://isa-test.paragon-data.net/catsearch/v6"
|
"rootUrl": "https://isa-test.paragon-data.net/catsearch/v6"
|
||||||
},
|
},
|
||||||
"@swagger/av": {
|
"@swagger/av": {
|
||||||
"rootUrl": "https://isa-test.paragon-data.net/ava/v6"
|
"rootUrl": "https://isa-test.paragon-data.net/ava/v6"
|
||||||
},
|
},
|
||||||
"@swagger/checkout": {
|
"@swagger/checkout": {
|
||||||
"rootUrl": "https://isa-test.paragon-data.net/checkout/v6"
|
"rootUrl": "https://isa-test.paragon-data.net/checkout/v6"
|
||||||
},
|
},
|
||||||
"@swagger/crm": {
|
"@swagger/crm": {
|
||||||
"rootUrl": "https://isa-test.paragon-data.net/crm/v6"
|
"rootUrl": "https://isa-test.paragon-data.net/crm/v6"
|
||||||
},
|
},
|
||||||
"@swagger/oms": {
|
"@swagger/oms": {
|
||||||
"rootUrl": "https://isa-test.paragon-data.net/oms/v6"
|
"rootUrl": "https://isa-test.paragon-data.net/oms/v6"
|
||||||
},
|
},
|
||||||
"@swagger/print": {
|
"@swagger/print": {
|
||||||
"rootUrl": "https://isa-test.paragon-data.net/print/v1"
|
"rootUrl": "https://isa-test.paragon-data.net/print/v1"
|
||||||
},
|
},
|
||||||
"@swagger/eis": {
|
"@swagger/eis": {
|
||||||
"rootUrl": "https://filialinformationsystem-test.paragon-systems.de/eiswebapi/v1"
|
"rootUrl": "https://filialinformationsystem-test.paragon-systems.de/eiswebapi/v1"
|
||||||
},
|
},
|
||||||
"@swagger/remi": {
|
"@swagger/remi": {
|
||||||
"rootUrl": "https://isa-test.paragon-data.net/inv/v6"
|
"rootUrl": "https://isa-test.paragon-data.net/inv/v6"
|
||||||
},
|
},
|
||||||
"@swagger/wws": {
|
"@swagger/wws": {
|
||||||
"rootUrl": "https://isa-test.paragon-data.net/wws/v1"
|
"rootUrl": "https://isa-test.paragon-data.net/wws/v1"
|
||||||
},
|
},
|
||||||
"@domain/checkout": {
|
"@domain/checkout": {
|
||||||
"olaExpiration": "5m"
|
"olaExpiration": "5m"
|
||||||
},
|
},
|
||||||
"hubs": {
|
"hubs": {
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"url": "https://isa-test.paragon-data.net/isa/v1/rt",
|
"url": "https://isa-test.paragon-data.net/isa/v1/rt",
|
||||||
"enableAutomaticReconnect": false,
|
"enableAutomaticReconnect": false,
|
||||||
"httpOptions": {
|
"httpOptions": {
|
||||||
"transport": 1,
|
"transport": 1,
|
||||||
"logMessageContent": true,
|
"logMessageContent": true,
|
||||||
"skipNegotiation": true
|
"skipNegotiation": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"process": {
|
"process": {
|
||||||
"ids": {
|
"ids": {
|
||||||
"goodsOut": 1000,
|
"goodsOut": 1000,
|
||||||
"goodsIn": 2000,
|
"goodsIn": 2000,
|
||||||
"taskCalendar": 3000,
|
"taskCalendar": 3000,
|
||||||
"remission": 4000,
|
"remission": 4000,
|
||||||
"packageInspection": 5000,
|
"packageInspection": 5000,
|
||||||
"assortment": 6000,
|
"assortment": 6000,
|
||||||
"pickupShelf": 7000
|
"pickupShelf": 7000
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"checkForUpdates": 3600000,
|
"checkForUpdates": 3600000,
|
||||||
"licence": {
|
"licence": {
|
||||||
"scandit": "Ae8F2Wx2RMq5Lvn7UUAlWzVFZTt2+ubMAF8XtDpmPlNkBeG/LWs1M7AbgDW0LQqYLnszClEENaEHS56/6Ts2vrJ1Ux03CXUjK3jUvZpF5OchXR1CpnmpepJ6WxPCd7LMVHUGG1BbwPLDTFjP3y8uT0caTSmmGrYQWAs4CZcEF+ZBabP0z7vfm+hCZF/ebj9qqCJZcW8nH/n19hohshllzYBjFXjh87P2lIh1s6yZS3OaQWWXo/o0AKdxx7T6CVyR0/G5zq6uYJWf6rs3euUBEhpzOZHbHZK86Lvy2AVBEyVkkcttlDW1J2fA4l1W1JV/Xibz8AQV6kG482EpGF42KEoK48paZgX3e1AQsqUtmqzw294dcP4zMVstnw5/WrwKKi/5E/nOOJT2txYP1ZufIjPrwNFsqTlv7xCQlHjMzFGYwT816yD5qLRLbwOtjrkUPXNZLZ06T4upvWwJDmm8XgdeoDqMjHdcO4lwji1bl9EiIYJ/2qnsk9yZ2FqSaHzn4cbiL0f5u2HFlNAP0GUujGRlthGhHi6o4dFU+WAxKsFMKVt+SfoQUazNKHFVQgiAklTIZxIc/HUVzRvOLMxf+wFDerraBtcqGJg+g/5mrWYqeDBGhCBHtKiYf6244IJ4afzNTiH1/30SJcRzXwbEa3A7q1fJTx9/nLTOfVPrJKBQs7f/OQs2dA7LDCel8mzXdbjvsNQaeU5+iCIAq6zbTNKy1xT8wwj+VZrQmtNJs+qeznD+u29nCM24h8xCmRpvNPo4/Mww/lrTNrrNwLBSn1pMIwsH7yS9hH0v0oNAM3A6bVtk1D9qEkbyw+xZa+MZGpMP0D0CdcsqHalPcm5r/Ik="
|
"scandit": "Ae8F2Wx2RMq5Lvn7UUAlWzVFZTt2+ubMAF8XtDpmPlNkBeG/LWs1M7AbgDW0LQqYLnszClEENaEHS56/6Ts2vrJ1Ux03CXUjK3jUvZpF5OchXR1CpnmpepJ6WxPCd7LMVHUGG1BbwPLDTFjP3y8uT0caTSmmGrYQWAs4CZcEF+ZBabP0z7vfm+hCZF/ebj9qqCJZcW8nH/n19hohshllzYBjFXjh87P2lIh1s6yZS3OaQWWXo/o0AKdxx7T6CVyR0/G5zq6uYJWf6rs3euUBEhpzOZHbHZK86Lvy2AVBEyVkkcttlDW1J2fA4l1W1JV/Xibz8AQV6kG482EpGF42KEoK48paZgX3e1AQsqUtmqzw294dcP4zMVstnw5/WrwKKi/5E/nOOJT2txYP1ZufIjPrwNFsqTlv7xCQlHjMzFGYwT816yD5qLRLbwOtjrkUPXNZLZ06T4upvWwJDmm8XgdeoDqMjHdcO4lwji1bl9EiIYJ/2qnsk9yZ2FqSaHzn4cbiL0f5u2HFlNAP0GUujGRlthGhHi6o4dFU+WAxKsFMKVt+SfoQUazNKHFVQgiAklTIZxIc/HUVzRvOLMxf+wFDerraBtcqGJg+g/5mrWYqeDBGhCBHtKiYf6244IJ4afzNTiH1/30SJcRzXwbEa3A7q1fJTx9/nLTOfVPrJKBQs7f/OQs2dA7LDCel8mzXdbjvsNQaeU5+iCIAq6zbTNKy1xT8wwj+VZrQmtNJs+qeznD+u29nCM24h8xCmRpvNPo4/Mww/lrTNrrNwLBSn1pMIwsH7yS9hH0v0oNAM3A6bVtk1D9qEkbyw+xZa+MZGpMP0D0CdcsqHalPcm5r/Ik="
|
||||||
},
|
},
|
||||||
"gender": {
|
"gender": {
|
||||||
"0": "Keine Anrede",
|
"0": "Keine Anrede",
|
||||||
"1": "Enby",
|
"1": "Enby",
|
||||||
"2": "Herr",
|
"2": "Herr",
|
||||||
"4": "Frau"
|
"4": "Frau"
|
||||||
},
|
},
|
||||||
"@shared/icon": "/assets/icons.json"
|
"@shared/icon": "/assets/icons.json"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { BranchDTO } from '@swagger/checkout';
|
import { BranchDTO } from '@generated/swagger/checkout-api';
|
||||||
import { isBoolean, isNumber } from '@utils/common';
|
import { isBoolean, isNumber } from '@utils/common';
|
||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
import { first, map, switchMap } from 'rxjs/operators';
|
import { first, map, switchMap } from 'rxjs/operators';
|
||||||
@@ -35,7 +35,9 @@ export class ApplicationService {
|
|||||||
|
|
||||||
getProcesses$(section?: 'customer' | 'branch') {
|
getProcesses$(section?: 'customer' | 'branch') {
|
||||||
const processes$ = this.store.select(selectProcesses);
|
const processes$ = this.store.select(selectProcesses);
|
||||||
return processes$.pipe(map((processes) => processes.filter((process) => (section ? process.section === section : true))));
|
return processes$.pipe(
|
||||||
|
map((processes) => processes.filter((process) => (section ? process.section === section : true))),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getProcessById$(processId: number): Observable<ApplicationProcess> {
|
getProcessById$(processId: number): Observable<ApplicationProcess> {
|
||||||
@@ -135,7 +137,10 @@ export class ApplicationService {
|
|||||||
this.store.dispatch(setSection({ section }));
|
this.store.dispatch(setSection({ section }));
|
||||||
}
|
}
|
||||||
|
|
||||||
getLastActivatedProcessWithSectionAndType$(section: 'customer' | 'branch', type: string): Observable<ApplicationProcess> {
|
getLastActivatedProcessWithSectionAndType$(
|
||||||
|
section: 'customer' | 'branch',
|
||||||
|
type: string,
|
||||||
|
): Observable<ApplicationProcess> {
|
||||||
return this.getProcesses$(section).pipe(
|
return this.getProcesses$(section).pipe(
|
||||||
map((processes) =>
|
map((processes) =>
|
||||||
processes
|
processes
|
||||||
|
|||||||
@@ -11,8 +11,17 @@ export const addProcess = createAction(`${prefix} Add Process`, props<{ process:
|
|||||||
|
|
||||||
export const removeProcess = createAction(`${prefix} Remove Process`, props<{ processId: number }>());
|
export const removeProcess = createAction(`${prefix} Remove Process`, props<{ processId: number }>());
|
||||||
|
|
||||||
export const setActivatedProcess = createAction(`${prefix} Set Activated Process`, props<{ activatedProcessId: number }>());
|
export const setActivatedProcess = createAction(
|
||||||
|
`${prefix} Set Activated Process`,
|
||||||
|
props<{ activatedProcessId: number }>(),
|
||||||
|
);
|
||||||
|
|
||||||
export const patchProcess = createAction(`${prefix} Patch Process`, props<{ processId: number; changes: Partial<ApplicationProcess> }>());
|
export const patchProcess = createAction(
|
||||||
|
`${prefix} Patch Process`,
|
||||||
|
props<{ processId: number; changes: Partial<ApplicationProcess> }>(),
|
||||||
|
);
|
||||||
|
|
||||||
export const patchProcessData = createAction(`${prefix} Patch Process Data`, props<{ processId: number; data: Record<string, any> }>());
|
export const patchProcessData = createAction(
|
||||||
|
`${prefix} Patch Process Data`,
|
||||||
|
props<{ processId: number; data: Record<string, any> }>(),
|
||||||
|
);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { AuthService } from './auth.service';
|
|||||||
|
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: '[ifRole],[ifRoleElse],[ifNotRole],[ifNotRoleElse]',
|
selector: '[ifRole],[ifRoleElse],[ifNotRole],[ifNotRoleElse]',
|
||||||
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class IfRoleDirective implements OnChanges {
|
export class IfRoleDirective implements OnChanges {
|
||||||
@Input()
|
@Input()
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { EnvironmentService } from '@core/environment';
|
|||||||
import { UiConfirmModalComponent, UiModalResult, UiModalService } from '@ui/modal';
|
import { UiConfirmModalComponent, UiModalResult, UiModalService } from '@ui/modal';
|
||||||
import { injectNetworkStatus$ } from '../../app/services';
|
import { injectNetworkStatus$ } from '../../app/services';
|
||||||
import { AuthService } from './auth.service';
|
import { AuthService } from './auth.service';
|
||||||
import { AuthService as IsaAuthService } from '@swagger/isa';
|
import { AuthService as IsaAuthService } from '@generated/swagger/isa-api';
|
||||||
import { firstValueFrom, lastValueFrom } from 'rxjs';
|
import { firstValueFrom, lastValueFrom } from 'rxjs';
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
|
|||||||
@@ -120,7 +120,10 @@ export class BreadcrumbService {
|
|||||||
|
|
||||||
if (recursive) {
|
if (recursive) {
|
||||||
const breadcrumbs = await this.getBreadcrumbByKey$(breadcrumb.key).pipe(take(1)).toPromise();
|
const breadcrumbs = await this.getBreadcrumbByKey$(breadcrumb.key).pipe(take(1)).toPromise();
|
||||||
breadcrumbsToRemove = [...breadcrumbsToRemove, ...breadcrumbs.filter((crumb) => crumb.timestamp > breadcrumb.timestamp)];
|
breadcrumbsToRemove = [
|
||||||
|
...breadcrumbsToRemove,
|
||||||
|
...breadcrumbs.filter((crumb) => crumb.timestamp > breadcrumb.timestamp),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!breadcrumbsToRemove.length) {
|
if (!breadcrumbsToRemove.length) {
|
||||||
@@ -135,7 +138,10 @@ export class BreadcrumbService {
|
|||||||
crumbs.forEach((crumb) => this.removeBreadcrumb(crumb.id));
|
crumbs.forEach((crumb) => this.removeBreadcrumb(crumb.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
getLatestBreadcrumbForSection(section: 'customer' | 'branch', predicate: (crumb: Breadcrumb) => boolean = (_) => true) {
|
getLatestBreadcrumbForSection(
|
||||||
|
section: 'customer' | 'branch',
|
||||||
|
predicate: (crumb: Breadcrumb) => boolean = (_) => true,
|
||||||
|
) {
|
||||||
return this.store
|
return this.store
|
||||||
.select(selectors.selectBreadcrumbsBySection, { section })
|
.select(selectors.selectBreadcrumbsBySection, { section })
|
||||||
.pipe(map((crumbs) => crumbs.sort((a, b) => b.timestamp - a.timestamp).find((f) => predicate(f))));
|
.pipe(map((crumbs) => crumbs.sort((a, b) => b.timestamp - a.timestamp).find((f) => predicate(f))));
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export interface Breadcrumb {
|
|||||||
/**
|
/**
|
||||||
* Query Parameter
|
* Query Parameter
|
||||||
*/
|
*/
|
||||||
params?: Object;
|
params?: object;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timestamp
|
* Timestamp
|
||||||
|
|||||||
@@ -11,7 +11,10 @@ export const addBreadcrumb = createAction(`${prefix} Add Breadcrumb`, props<{ br
|
|||||||
/**
|
/**
|
||||||
* Action um Breadcrumb im State zu ändern
|
* Action um Breadcrumb im State zu ändern
|
||||||
*/
|
*/
|
||||||
export const updateBreadcrumb = createAction(`${prefix} Update Breadcrumb`, props<{ id: number; changes: Partial<Breadcrumb> }>());
|
export const updateBreadcrumb = createAction(
|
||||||
|
`${prefix} Update Breadcrumb`,
|
||||||
|
props<{ id: number; changes: Partial<Breadcrumb> }>(),
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action um Breadcrumb im State zu entfernen
|
* Action um Breadcrumb im State zu entfernen
|
||||||
|
|||||||
@@ -43,7 +43,10 @@ describe('Breadcrumb Reducer', () => {
|
|||||||
|
|
||||||
const state = breadcrumbReducer(INIT, action.addBreadcrumb({ breadcrumb }));
|
const state = breadcrumbReducer(INIT, action.addBreadcrumb({ breadcrumb }));
|
||||||
|
|
||||||
const fixture = breadcrumbReducer(state, action.updateBreadcrumb({ id: breadcrumb.id, changes: { name: 'Test Name 2' } }));
|
const fixture = breadcrumbReducer(
|
||||||
|
state,
|
||||||
|
action.updateBreadcrumb({ id: breadcrumb.id, changes: { name: 'Test Name 2' } }),
|
||||||
|
);
|
||||||
|
|
||||||
expect(fixture.entities[breadcrumb.id]).toEqual(expected);
|
expect(fixture.entities[breadcrumb.id]).toEqual(expected);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,26 +10,46 @@ describe('Breadcrumb Selectors', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
state = breadcrumbReducer(
|
state = breadcrumbReducer(
|
||||||
INIT,
|
INIT,
|
||||||
action.addBreadcrumb({ breadcrumb: { id: 1, key: 'unit-test-1', path: '', name: 'Unit Test 1', section: 'customer' } }),
|
|
||||||
);
|
|
||||||
state = breadcrumbReducer(
|
|
||||||
state,
|
|
||||||
action.addBreadcrumb({
|
action.addBreadcrumb({
|
||||||
breadcrumb: { id: 2, key: 'unit-test-1', path: '', name: 'Unit Test 1', tags: ['details'], section: 'customer' },
|
breadcrumb: { id: 1, key: 'unit-test-1', path: '', name: 'Unit Test 1', section: 'customer' },
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
state = breadcrumbReducer(
|
state = breadcrumbReducer(
|
||||||
state,
|
state,
|
||||||
action.addBreadcrumb({ breadcrumb: { id: 3, key: 'unit-test-2', path: '', name: 'Unit Test 1', section: 'customer' } }),
|
action.addBreadcrumb({
|
||||||
);
|
breadcrumb: {
|
||||||
state = breadcrumbReducer(
|
id: 2,
|
||||||
state,
|
key: 'unit-test-1',
|
||||||
action.addBreadcrumb({ breadcrumb: { id: 4, key: 'unit-test-3', path: '', name: 'Unit Test 1', section: 'customer' } }),
|
path: '',
|
||||||
|
name: 'Unit Test 1',
|
||||||
|
tags: ['details'],
|
||||||
|
section: 'customer',
|
||||||
|
},
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
state = breadcrumbReducer(
|
state = breadcrumbReducer(
|
||||||
state,
|
state,
|
||||||
action.addBreadcrumb({
|
action.addBreadcrumb({
|
||||||
breadcrumb: { id: 5, key: 'unit-test-3', path: '', name: 'Unit Test 1', tags: ['details'], section: 'customer' },
|
breadcrumb: { id: 3, key: 'unit-test-2', path: '', name: 'Unit Test 1', section: 'customer' },
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
state = breadcrumbReducer(
|
||||||
|
state,
|
||||||
|
action.addBreadcrumb({
|
||||||
|
breadcrumb: { id: 4, key: 'unit-test-3', path: '', name: 'Unit Test 1', section: 'customer' },
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
state = breadcrumbReducer(
|
||||||
|
state,
|
||||||
|
action.addBreadcrumb({
|
||||||
|
breadcrumb: {
|
||||||
|
id: 5,
|
||||||
|
key: 'unit-test-3',
|
||||||
|
path: '',
|
||||||
|
name: 'Unit Test 1',
|
||||||
|
tags: ['details'],
|
||||||
|
section: 'customer',
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ export const selectBreadcrumbById = createSelector(selectEntities, (entities, id
|
|||||||
/**
|
/**
|
||||||
* Gibt alle Breadcrumb Entities als Array zurück die den key enthalten
|
* Gibt alle Breadcrumb Entities als Array zurück die den key enthalten
|
||||||
*/
|
*/
|
||||||
export const selectBreadcrumbsByKey = createSelector(selectAll, (entities, key: string) => entities.filter((crumb) => crumb.key == key));
|
export const selectBreadcrumbsByKey = createSelector(selectAll, (entities, key: string) =>
|
||||||
|
entities.filter((crumb) => crumb.key == key),
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gibt alle Breadcrumb Entities als Array zurück die den key und tag enthalten
|
* Gibt alle Breadcrumb Entities als Array zurück die den key und tag enthalten
|
||||||
@@ -37,12 +39,15 @@ export const selectBreadcrumbsByKeyAndTag = createSelector(
|
|||||||
export const selectBreadcrumbsByKeyAndTags = createSelector(
|
export const selectBreadcrumbsByKeyAndTags = createSelector(
|
||||||
selectAll,
|
selectAll,
|
||||||
(entities: Breadcrumb[], { key, tags }: { key: string; tags: string[] }) =>
|
(entities: Breadcrumb[], { key, tags }: { key: string; tags: string[] }) =>
|
||||||
entities.filter((crumb) => crumb.key == key && isArray(crumb.tags) && tags.every((tag) => crumb.tags.includes(tag))),
|
entities.filter(
|
||||||
|
(crumb) => crumb.key == key && isArray(crumb.tags) && tags.every((tag) => crumb.tags.includes(tag)),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gibt alle Breadcrumb Entities als Array zurück die die tags enthalten
|
* Gibt alle Breadcrumb Entities als Array zurück die die tags enthalten
|
||||||
*/
|
*/
|
||||||
export const selectBreadcrumbsBySection = createSelector(selectAll, (entities: Breadcrumb[], { section }: { section: string }) =>
|
export const selectBreadcrumbsBySection = createSelector(
|
||||||
entities.filter((crumb) => crumb.section === section),
|
selectAll,
|
||||||
|
(entities: Breadcrumb[], { section }: { section: string }) => entities.filter((crumb) => crumb.section === section),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createEntityAdapter, EntityState } from '@ngrx/entity';
|
import { createEntityAdapter, EntityState } from '@ngrx/entity';
|
||||||
import { Breadcrumb } from '../defs';
|
import { Breadcrumb } from '../defs';
|
||||||
|
|
||||||
export interface BreadcrumbState extends EntityState<Breadcrumb> {}
|
export type BreadcrumbState = EntityState<Breadcrumb>
|
||||||
|
|
||||||
export const featureName = 'core-breadcrumb';
|
export const featureName = 'core-breadcrumb';
|
||||||
|
|
||||||
|
|||||||
8
apps/isa-app/src/core/cache/cache.service.ts
vendored
8
apps/isa-app/src/core/cache/cache.service.ts
vendored
@@ -34,7 +34,7 @@ export class CacheService {
|
|||||||
return 'cache';
|
return 'cache';
|
||||||
}
|
}
|
||||||
|
|
||||||
private getKey(token: Object | string): string {
|
private getKey(token: object | string): string {
|
||||||
if (typeof token === 'string') {
|
if (typeof token === 'string') {
|
||||||
return this.hash(token);
|
return this.hash(token);
|
||||||
}
|
}
|
||||||
@@ -105,7 +105,7 @@ export class CacheService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async cached(token: Object | string): Promise<DbEntry<any> | undefined> {
|
private async cached(token: object | string): Promise<DbEntry<any> | undefined> {
|
||||||
const store = await this.getObjectStore();
|
const store = await this.getObjectStore();
|
||||||
return new Promise<DbEntry<any> | undefined>((resolve, reject) => {
|
return new Promise<DbEntry<any> | undefined>((resolve, reject) => {
|
||||||
const request = store.get(this.getKey(token));
|
const request = store.get(this.getKey(token));
|
||||||
@@ -118,7 +118,7 @@ export class CacheService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async get<T = any>(token: Object | string): Promise<T | undefined> {
|
async get<T = any>(token: object | string): Promise<T | undefined> {
|
||||||
const cached = await this.cached(token);
|
const cached = await this.cached(token);
|
||||||
|
|
||||||
if (!cached) {
|
if (!cached) {
|
||||||
@@ -133,7 +133,7 @@ export class CacheService {
|
|||||||
return cached.data;
|
return cached.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(token: Object | string): Promise<void> {
|
async delete(token: object | string): Promise<void> {
|
||||||
const store = await this.getObjectStore('readwrite');
|
const store = await this.getObjectStore('readwrite');
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
const request = store.delete(this.getKey(token));
|
const request = store.delete(this.getKey(token));
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ import { CommandService } from './command.service';
|
|||||||
import { FEATURE_ACTION_HANDLERS, ROOT_ACTION_HANDLERS } from './tokens';
|
import { FEATURE_ACTION_HANDLERS, ROOT_ACTION_HANDLERS } from './tokens';
|
||||||
|
|
||||||
export function provideActionHandlers(actionHandlers: Type<ActionHandler>[]): Provider[] {
|
export function provideActionHandlers(actionHandlers: Type<ActionHandler>[]): Provider[] {
|
||||||
return [CommandService, actionHandlers.map((handler) => ({ provide: FEATURE_ACTION_HANDLERS, useClass: handler, multi: true }))];
|
return [
|
||||||
|
CommandService,
|
||||||
|
actionHandlers.map((handler) => ({ provide: FEATURE_ACTION_HANDLERS, useClass: handler, multi: true })),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@NgModule({})
|
@NgModule({})
|
||||||
@@ -12,14 +15,20 @@ export class CoreCommandModule {
|
|||||||
static forRoot(actionHandlers: Type<ActionHandler>[]): ModuleWithProviders<CoreCommandModule> {
|
static forRoot(actionHandlers: Type<ActionHandler>[]): ModuleWithProviders<CoreCommandModule> {
|
||||||
return {
|
return {
|
||||||
ngModule: CoreCommandModule,
|
ngModule: CoreCommandModule,
|
||||||
providers: [CommandService, actionHandlers.map((handler) => ({ provide: ROOT_ACTION_HANDLERS, useClass: handler, multi: true }))],
|
providers: [
|
||||||
|
CommandService,
|
||||||
|
actionHandlers.map((handler) => ({ provide: ROOT_ACTION_HANDLERS, useClass: handler, multi: true })),
|
||||||
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static forChild(actionHandlers: Type<ActionHandler>[]): ModuleWithProviders<CoreCommandModule> {
|
static forChild(actionHandlers: Type<ActionHandler>[]): ModuleWithProviders<CoreCommandModule> {
|
||||||
return {
|
return {
|
||||||
ngModule: CoreCommandModule,
|
ngModule: CoreCommandModule,
|
||||||
providers: [CommandService, actionHandlers.map((handler) => ({ provide: FEATURE_ACTION_HANDLERS, useClass: handler, multi: true }))],
|
providers: [
|
||||||
|
CommandService,
|
||||||
|
actionHandlers.map((handler) => ({ provide: FEATURE_ACTION_HANDLERS, useClass: handler, multi: true })),
|
||||||
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
import { Observable } from 'rxjs';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Config loader interface for loading configurations
|
|
||||||
*/
|
|
||||||
export interface ConfigLoader {
|
|
||||||
load(): Promise<any>;
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
// start:ng42.barrel
|
|
||||||
export * from './config-loader';
|
|
||||||
export * from './json.config-loader';
|
|
||||||
// end:ng42.barrel
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
// // unit test JsonConfigLoader
|
|
||||||
// import { HttpTestingController } from '@angular/common/http/testing';
|
|
||||||
// import { createServiceFactory, SpectatorService } from '@ngneat/spectator';
|
|
||||||
// import { CORE_JSON_CONFIG_LOADER_URL } from '../tokens';
|
|
||||||
// import { JsonConfigLoader } from './json.config-loader';
|
|
||||||
|
|
||||||
// describe('JsonConfigLoader', () => {
|
|
||||||
// let spectator: SpectatorService<JsonConfigLoader>;
|
|
||||||
// const createService = createServiceFactory({
|
|
||||||
// imports: [HttpClientTestingModule],
|
|
||||||
// service: JsonConfigLoader,
|
|
||||||
// mocks: [],
|
|
||||||
// providers: [{ provide: CORE_JSON_CONFIG_LOADER_URL, useValue: '/assets/config.json' }],
|
|
||||||
// });
|
|
||||||
// let httpTestingController: HttpTestingController;
|
|
||||||
|
|
||||||
// beforeEach(() => {
|
|
||||||
// spectator = createService();
|
|
||||||
// httpTestingController = spectator.inject(HttpTestingController);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// it('should create', () => {
|
|
||||||
// expect(spectator.service).toBeTruthy();
|
|
||||||
// });
|
|
||||||
|
|
||||||
// describe('load', () => {
|
|
||||||
// it('should call the provided url', async () => {
|
|
||||||
// const reqPromise = spectator.service.load();
|
|
||||||
// const req = httpTestingController.expectOne('/assets/config.json');
|
|
||||||
// req.flush({ unit: 'test' });
|
|
||||||
// const result = await reqPromise;
|
|
||||||
// httpTestingController.verify();
|
|
||||||
// expect(result).toEqual({ unit: 'test' });
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import { HttpClient } from '@angular/common/http';
|
|
||||||
import { Inject, Injectable } from '@angular/core';
|
|
||||||
import { ConfigLoader } from './config-loader';
|
|
||||||
import { CORE_JSON_CONFIG_LOADER_URL } from '../tokens';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class JsonConfigLoader implements ConfigLoader {
|
|
||||||
constructor(
|
|
||||||
@Inject(CORE_JSON_CONFIG_LOADER_URL) private url: string,
|
|
||||||
private http: HttpClient,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
load(): Promise<any> {
|
|
||||||
return this.http.get(this.url).toPromise();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { Type } from '@angular/core';
|
|
||||||
import { ConfigLoader } from './config-loaders';
|
|
||||||
|
|
||||||
export interface ConfigModuleOptions {
|
|
||||||
useConfigLoader: Type<ConfigLoader>;
|
|
||||||
jsonConfigLoaderUrl?: string;
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
import { APP_INITIALIZER, ModuleWithProviders, NgModule } from '@angular/core';
|
|
||||||
import { CORE_CONFIG_LOADER } from '@core/config';
|
|
||||||
import { Config } from './config';
|
|
||||||
import { ConfigModuleOptions } from './config-module-options';
|
|
||||||
import { CORE_JSON_CONFIG_LOADER_URL } from './tokens';
|
|
||||||
|
|
||||||
export function _initializeConfigFactory(config: Config) {
|
|
||||||
return () => config.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NgModule({})
|
|
||||||
export class ConfigModule {
|
|
||||||
static forRoot(options: ConfigModuleOptions): ModuleWithProviders<ConfigModule> {
|
|
||||||
const configLoaderProvider = {
|
|
||||||
provide: CORE_CONFIG_LOADER,
|
|
||||||
useClass: options.useConfigLoader,
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
ngModule: ConfigModule,
|
|
||||||
providers: [
|
|
||||||
Config,
|
|
||||||
configLoaderProvider,
|
|
||||||
options.jsonConfigLoaderUrl ? { provide: CORE_JSON_CONFIG_LOADER_URL, useValue: options.jsonConfigLoaderUrl } : null,
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
import { createServiceFactory, SpectatorService } from '@ngneat/spectator';
|
|
||||||
import { Config } from './config';
|
|
||||||
import { ConfigLoader } from './config-loaders';
|
|
||||||
import { CORE_CONFIG_LOADER } from './tokens';
|
|
||||||
|
|
||||||
class TestConfigLoader implements ConfigLoader {
|
|
||||||
load() {
|
|
||||||
return Promise.resolve({});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unit test Config
|
|
||||||
describe('Config', () => {
|
|
||||||
let spectator: SpectatorService<Config>;
|
|
||||||
const createService = createServiceFactory({
|
|
||||||
service: Config,
|
|
||||||
providers: [{ provide: CORE_CONFIG_LOADER, useClass: TestConfigLoader }],
|
|
||||||
});
|
|
||||||
let configLoader: ConfigLoader;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
spectator = createService();
|
|
||||||
configLoader = spectator.inject(CORE_CONFIG_LOADER);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(spectator.service).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('init()', () => {
|
|
||||||
it('should load config and assigns it to _config', async () => {
|
|
||||||
const config = { unit: 'test' };
|
|
||||||
spyOn(configLoader, 'load').and.returnValue(Promise.resolve(config));
|
|
||||||
await spectator.service.init();
|
|
||||||
expect(spectator.service['_config']).toEqual(config);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('get()', () => {
|
|
||||||
it('should return config value', () => {
|
|
||||||
spectator.service['_config'] = { test: 'test' };
|
|
||||||
expect(spectator.service.get('test')).toEqual('test');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
import { Inject, Injectable } from '@angular/core';
|
|
||||||
import { ReplaySubject } from 'rxjs';
|
|
||||||
import { ConfigLoader } from './config-loaders';
|
|
||||||
import { CORE_CONFIG_LOADER } from './tokens';
|
|
||||||
import { pick } from './utils';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class Config {
|
|
||||||
private _config: any;
|
|
||||||
|
|
||||||
private readonly _initilized = new ReplaySubject<void>(1);
|
|
||||||
get initialized() {
|
|
||||||
return this._initilized.asObservable();
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(@Inject(CORE_CONFIG_LOADER) private readonly _configLoader: ConfigLoader) {}
|
|
||||||
|
|
||||||
// load config and assign it to this._config
|
|
||||||
async init() {
|
|
||||||
this._config = await this._configLoader.load();
|
|
||||||
this._initilized.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
get(path: string) {
|
|
||||||
return pick(path, this._config);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
export * from './config-loaders';
|
|
||||||
export * from './config-module-options';
|
|
||||||
export * from './config.module';
|
|
||||||
export * from './config';
|
|
||||||
export * from './tokens';
|
|
||||||
export * from './utils';
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import { InjectionToken } from '@angular/core';
|
|
||||||
import { ConfigLoader } from './config-loaders';
|
|
||||||
|
|
||||||
export const CORE_CONFIG_LOADER = new InjectionToken<ConfigLoader>('core.config.loader');
|
|
||||||
|
|
||||||
export const CORE_JSON_CONFIG_LOADER_URL = new InjectionToken<ConfigLoader>('core.json.config.loader.url');
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
// start:ng42.barrel
|
|
||||||
export * from './pick';
|
|
||||||
// end:ng42.barrel
|
|
||||||
@@ -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 +1,5 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { ItemDTO } from '@swagger/cat';
|
import { ItemDTO } from '@generated/swagger/cat-search-api';
|
||||||
import {
|
import {
|
||||||
AvailabilityDTO,
|
AvailabilityDTO,
|
||||||
BranchDTO,
|
BranchDTO,
|
||||||
@@ -7,20 +7,25 @@ import {
|
|||||||
StoreCheckoutBranchService,
|
StoreCheckoutBranchService,
|
||||||
StoreCheckoutSupplierService,
|
StoreCheckoutSupplierService,
|
||||||
SupplierDTO,
|
SupplierDTO,
|
||||||
} from '@swagger/checkout';
|
} from '@generated/swagger/checkout-api';
|
||||||
import { BehaviorSubject, combineLatest, Observable, of } from 'rxjs';
|
import { BehaviorSubject, combineLatest, Observable, of } from 'rxjs';
|
||||||
import {
|
import {
|
||||||
AvailabilityRequestDTO,
|
AvailabilityRequestDTO,
|
||||||
AvailabilityService,
|
AvailabilityService,
|
||||||
AvailabilityDTO as SwaggerAvailabilityDTO,
|
AvailabilityDTO as SwaggerAvailabilityDTO,
|
||||||
AvailabilityType,
|
AvailabilityType,
|
||||||
} from '@swagger/availability';
|
} from '@generated/swagger/availability-api';
|
||||||
import { AvailabilityDTO as CatAvailabilityDTO } from '@swagger/cat';
|
import { AvailabilityDTO as CatAvailabilityDTO } from '@generated/swagger/cat-search-api';
|
||||||
import { map, shareReplay, switchMap, withLatestFrom, mergeMap, timeout, first } from 'rxjs/operators';
|
import { map, shareReplay, switchMap, withLatestFrom, mergeMap, timeout, first } from 'rxjs/operators';
|
||||||
import { isArray, memorize } from '@utils/common';
|
import { isArray, memorize } from '@utils/common';
|
||||||
import { LogisticianDTO, LogisticianService } from '@swagger/oms';
|
import { LogisticianDTO, LogisticianService } from '@generated/swagger/oms-api';
|
||||||
import { ResponseArgsOfIEnumerableOfStockInfoDTO, StockDTO, StockInfoDTO, StockService } from '@swagger/remi';
|
import {
|
||||||
import { PriceDTO } from '@swagger/availability';
|
ResponseArgsOfIEnumerableOfStockInfoDTO,
|
||||||
|
StockDTO,
|
||||||
|
StockInfoDTO,
|
||||||
|
StockService,
|
||||||
|
} from '@generated/swagger/inventory-api';
|
||||||
|
import { PriceDTO } from '@generated/swagger/availability-api';
|
||||||
import { AvailabilityByBranchDTO, ItemData, Ssc } from './defs';
|
import { AvailabilityByBranchDTO, ItemData, Ssc } from './defs';
|
||||||
import { Availability } from './defs/availability';
|
import { Availability } from './defs/availability';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
@@ -160,7 +165,7 @@ export class DomainAvailabilityService {
|
|||||||
quantity: number;
|
quantity: number;
|
||||||
branch?: BranchDTO;
|
branch?: BranchDTO;
|
||||||
}): Observable<AvailabilityDTO> {
|
}): Observable<AvailabilityDTO> {
|
||||||
const request = !!branch ? this.getStockByBranch(branch.id) : this.getDefaultStock();
|
const request = branch ? this.getStockByBranch(branch.id) : this.getDefaultStock();
|
||||||
return request.pipe(
|
return request.pipe(
|
||||||
switchMap((s) =>
|
switchMap((s) =>
|
||||||
combineLatest([
|
combineLatest([
|
||||||
@@ -171,7 +176,13 @@ export class DomainAvailabilityService {
|
|||||||
),
|
),
|
||||||
map(([response, supplier, defaultBranch]) => {
|
map(([response, supplier, defaultBranch]) => {
|
||||||
const price = item?.price;
|
const price = item?.price;
|
||||||
return this._mapToTakeAwayAvailability({ response, supplier, branchId: branch?.id ?? defaultBranch?.id, quantity, price });
|
return this._mapToTakeAwayAvailability({
|
||||||
|
response,
|
||||||
|
supplier,
|
||||||
|
branchId: branch?.id ?? defaultBranch?.id,
|
||||||
|
quantity,
|
||||||
|
price,
|
||||||
|
});
|
||||||
}),
|
}),
|
||||||
shareReplay(1),
|
shareReplay(1),
|
||||||
);
|
);
|
||||||
@@ -211,12 +222,18 @@ export class DomainAvailabilityService {
|
|||||||
quantity: number;
|
quantity: number;
|
||||||
branchId?: number;
|
branchId?: number;
|
||||||
}): Observable<AvailabilityDTO> {
|
}): Observable<AvailabilityDTO> {
|
||||||
const request = !!branchId ? this.getStockByBranch(branchId) : this.getDefaultStock();
|
const request = branchId ? this.getStockByBranch(branchId) : this.getDefaultStock();
|
||||||
return request.pipe(
|
return request.pipe(
|
||||||
switchMap((s) => this._stockService.StockInStockByEAN({ eans, stockId: s.id })),
|
switchMap((s) => this._stockService.StockInStockByEAN({ eans, stockId: s.id })),
|
||||||
withLatestFrom(this.getTakeAwaySupplier(), this.getDefaultBranch()),
|
withLatestFrom(this.getTakeAwaySupplier(), this.getDefaultBranch()),
|
||||||
map(([response, supplier, defaultBranch]) => {
|
map(([response, supplier, defaultBranch]) => {
|
||||||
return this._mapToTakeAwayAvailability({ response, supplier, branchId: branchId ?? defaultBranch.id, quantity, price });
|
return this._mapToTakeAwayAvailability({
|
||||||
|
response,
|
||||||
|
supplier,
|
||||||
|
branchId: branchId ?? defaultBranch.id,
|
||||||
|
quantity,
|
||||||
|
price,
|
||||||
|
});
|
||||||
}),
|
}),
|
||||||
shareReplay(1),
|
shareReplay(1),
|
||||||
);
|
);
|
||||||
@@ -329,7 +346,10 @@ export class DomainAvailabilityService {
|
|||||||
this.getPickUpAvailability({ item, quantity, branch: branch ?? defaultBranch }).pipe(
|
this.getPickUpAvailability({ item, quantity, branch: branch ?? defaultBranch }).pipe(
|
||||||
mergeMap((availability) =>
|
mergeMap((availability) =>
|
||||||
logistician$.pipe(
|
logistician$.pipe(
|
||||||
map((logistician) => ({ ...(availability?.length > 0 ? availability[0] : []), logistician: { id: logistician.id } })),
|
map((logistician) => ({
|
||||||
|
...(availability?.length > 0 ? availability[0] : []),
|
||||||
|
logistician: { id: logistician.id },
|
||||||
|
})),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
shareReplay(1),
|
shareReplay(1),
|
||||||
@@ -427,7 +447,9 @@ export class DomainAvailabilityService {
|
|||||||
return this.getPickUpAvailabilities(payload, true).pipe(
|
return this.getPickUpAvailabilities(payload, true).pipe(
|
||||||
timeout(20000),
|
timeout(20000),
|
||||||
switchMap((availability) =>
|
switchMap((availability) =>
|
||||||
logistician$.pipe(map((logistician) => ({ availability: [...availability], logistician: { id: logistician.id } }))),
|
logistician$.pipe(
|
||||||
|
map((logistician) => ({ availability: [...availability], logistician: { id: logistician.id } })),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
shareReplay(1),
|
shareReplay(1),
|
||||||
);
|
);
|
||||||
@@ -512,7 +534,9 @@ export class DomainAvailabilityService {
|
|||||||
return availability;
|
return availability;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _mapToPickUpAvailability(availabilities: SwaggerAvailabilityDTO[]): Availability<AvailabilityDTO, SwaggerAvailabilityDTO>[] {
|
private _mapToPickUpAvailability(
|
||||||
|
availabilities: SwaggerAvailabilityDTO[],
|
||||||
|
): Availability<AvailabilityDTO, SwaggerAvailabilityDTO>[] {
|
||||||
if (isArray(availabilities)) {
|
if (isArray(availabilities)) {
|
||||||
const preferred = availabilities.filter((f) => f.preferred === 1);
|
const preferred = availabilities.filter((f) => f.preferred === 1);
|
||||||
const totalAvailable = availabilities.reduce((sum, av) => sum + (av?.qty || 0), 0);
|
const totalAvailable = availabilities.reduce((sum, av) => sum + (av?.qty || 0), 0);
|
||||||
@@ -572,7 +596,9 @@ export class DomainAvailabilityService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const stock$ = branchId$.pipe(
|
const stock$ = branchId$.pipe(
|
||||||
mergeMap((branchId) => this._stockService.StockGetStocksByBranch({ branchId }).pipe(map((response) => response.result?.[0]))),
|
mergeMap((branchId) =>
|
||||||
|
this._stockService.StockGetStocksByBranch({ branchId }).pipe(map((response) => response.result?.[0])),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
return stock$.pipe(
|
return stock$.pipe(
|
||||||
@@ -598,7 +624,9 @@ export class DomainAvailabilityService {
|
|||||||
getInStock({ itemIds, branchId }: { itemIds: number[]; branchId: number }): Observable<StockInfoDTO[]> {
|
getInStock({ itemIds, branchId }: { itemIds: number[]; branchId: number }): Observable<StockInfoDTO[]> {
|
||||||
return this.getStockByBranch(branchId).pipe(
|
return this.getStockByBranch(branchId).pipe(
|
||||||
mergeMap((stock) =>
|
mergeMap((stock) =>
|
||||||
this._stockService.StockInStock({ articleIds: itemIds, stockId: stock.id }).pipe(map((response) => response.result)),
|
this._stockService
|
||||||
|
.StockInStock({ articleIds: itemIds, stockId: stock.id })
|
||||||
|
.pipe(map((response) => response.result)),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { AvailabilityDTO } from '@swagger/checkout';
|
import { AvailabilityDTO } from '@generated/swagger/checkout-api';
|
||||||
|
|
||||||
export interface AvailabilityByBranchDTO extends AvailabilityDTO {
|
export interface AvailabilityByBranchDTO extends AvailabilityDTO {
|
||||||
availableQuantity?: number;
|
availableQuantity?: number;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { PriceDTO } from '@swagger/availability';
|
import { PriceDTO } from '@generated/swagger/availability-api';
|
||||||
|
|
||||||
export interface ItemData {
|
export interface ItemData {
|
||||||
ean: string;
|
ean: string;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { StockInfoDTO } from '@swagger/remi';
|
import { StockInfoDTO } from '@generated/swagger/inventory-api';
|
||||||
import { groupBy, isEqual, uniqWith } from 'lodash';
|
import { groupBy, isEqual, uniqWith } from 'lodash';
|
||||||
import { BehaviorSubject, combineLatest, Observable, Subject } from 'rxjs';
|
import { BehaviorSubject, combineLatest, Observable, Subject } from 'rxjs';
|
||||||
import { buffer, debounceTime, distinctUntilChanged } from 'rxjs/operators';
|
import { buffer, debounceTime, distinctUntilChanged } from 'rxjs/operators';
|
||||||
@@ -90,10 +90,15 @@ export class DomainInStockService {
|
|||||||
const grouped = groupBy(itemBranchData, 'branchId');
|
const grouped = groupBy(itemBranchData, 'branchId');
|
||||||
Object.keys(grouped).forEach((key) => {
|
Object.keys(grouped).forEach((key) => {
|
||||||
const branchId = Number(key);
|
const branchId = Number(key);
|
||||||
const itemIds = itemBranchData.filter((itemBranch) => itemBranch.branchId === branchId).map((item) => item.itemId);
|
const itemIds = itemBranchData
|
||||||
|
.filter((itemBranch) => itemBranch.branchId === branchId)
|
||||||
|
.map((item) => item.itemId);
|
||||||
this._availability
|
this._availability
|
||||||
.getInStock({ itemIds, branchId })
|
.getInStock({ itemIds, branchId })
|
||||||
.subscribe(this._fetchStockDataResponse({ itemIds, branchId }), this._fetchStockDataError({ itemIds, branchId }));
|
.subscribe(
|
||||||
|
this._fetchStockDataResponse({ itemIds, branchId }),
|
||||||
|
this._fetchStockDataError({ itemIds, branchId }),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +106,9 @@ export class DomainInStockService {
|
|||||||
({ itemIds, branchId }: { itemIds: number[]; branchId: number }) =>
|
({ itemIds, branchId }: { itemIds: number[]; branchId: number }) =>
|
||||||
(stockInfos: StockInfoDTO[]) => {
|
(stockInfos: StockInfoDTO[]) => {
|
||||||
itemIds.forEach((itemId) => {
|
itemIds.forEach((itemId) => {
|
||||||
const stockInfo = stockInfos.find((stockInfo) => stockInfo.itemId === itemId && stockInfo.branchId === branchId);
|
const stockInfo = stockInfos.find(
|
||||||
|
(stockInfo) => stockInfo.itemId === itemId && stockInfo.branchId === branchId,
|
||||||
|
);
|
||||||
let inStock = 0;
|
let inStock = 0;
|
||||||
|
|
||||||
if (stockInfo?.inStock) {
|
if (stockInfo?.inStock) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { OLAAvailabilityDTO } from '@swagger/checkout';
|
import { OLAAvailabilityDTO } from '@generated/swagger/checkout-api';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { CartItem } from './defs/cart-item.model';
|
import { CartItem } from './defs/cart-item.model';
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { AvailabilityDTO, BranchDTO, ItemDTO, Price, ProductDTO } from '@swagger/checkout';
|
import { AvailabilityDTO, BranchDTO, ItemDTO, Price, ProductDTO } from '@generated/swagger/checkout-api';
|
||||||
import { BranchInfoDTO } from '@swagger/isa';
|
import { BranchInfoDTO } from '@generated/swagger/isa-api';
|
||||||
|
|
||||||
export interface CartItem {
|
export interface CartItem {
|
||||||
// cartId: number;
|
// cartId: number;
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { ApplicationService } from '@core/application';
|
import { ApplicationService } from '@core/application';
|
||||||
import { AutocompleteTokenDTO, PromotionService, QueryTokenDTO, SearchService } from '@swagger/cat';
|
import {
|
||||||
|
AutocompleteTokenDTO,
|
||||||
|
PromotionService,
|
||||||
|
QueryTokenDTO,
|
||||||
|
SearchService,
|
||||||
|
} from '@generated/swagger/cat-search-api';
|
||||||
import { memorize } from '@utils/common';
|
import { memorize } from '@utils/common';
|
||||||
import { map, share, shareReplay } from 'rxjs/operators';
|
import { map, share, shareReplay } from 'rxjs/operators';
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { DomainCatalogThumbnailService } from './thumbnail.service';
|
|||||||
@Pipe({
|
@Pipe({
|
||||||
name: 'thumbnailUrl',
|
name: 'thumbnailUrl',
|
||||||
pure: false,
|
pure: false,
|
||||||
|
standalone: false,
|
||||||
})
|
})
|
||||||
export class ThumbnailUrlPipe implements PipeTransform, OnDestroy {
|
export class ThumbnailUrlPipe implements PipeTransform, OnDestroy {
|
||||||
private input$ = new BehaviorSubject<{ width?: number; height?: number; ean?: string }>(undefined);
|
private input$ = new BehaviorSubject<{ width?: number; height?: number; ean?: string }>(undefined);
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ export class DomainCheckoutModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [StoreModule.forFeature(storeFeatureName, domainCheckoutReducer), EffectsModule.forFeature([DomainCheckoutEffects])],
|
imports: [
|
||||||
|
StoreModule.forFeature(storeFeatureName, domainCheckoutReducer),
|
||||||
|
EffectsModule.forFeature([DomainCheckoutEffects]),
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class RootDomainCheckoutModule {}
|
export class RootDomainCheckoutModule {}
|
||||||
|
|||||||
@@ -30,14 +30,14 @@ import {
|
|||||||
KulturPassService,
|
KulturPassService,
|
||||||
ProductDTO,
|
ProductDTO,
|
||||||
KulturPassResult,
|
KulturPassResult,
|
||||||
} from '@swagger/checkout';
|
} from '@generated/swagger/checkout-api';
|
||||||
import {
|
import {
|
||||||
DisplayOrderDTO,
|
DisplayOrderDTO,
|
||||||
DisplayOrderItemDTO,
|
DisplayOrderItemDTO,
|
||||||
OrderCheckoutService,
|
OrderCheckoutService,
|
||||||
ReorderValues,
|
ReorderValues,
|
||||||
ResponseArgsOfValueTupleOfIEnumerableOfDisplayOrderDTOAndIEnumerableOfKeyValueDTOOfStringAndString,
|
ResponseArgsOfValueTupleOfIEnumerableOfDisplayOrderDTOAndIEnumerableOfKeyValueDTOOfStringAndString,
|
||||||
} from '@swagger/oms';
|
} from '@generated/swagger/oms-api';
|
||||||
import { isNullOrUndefined, memorize } from '@utils/common';
|
import { isNullOrUndefined, memorize } from '@utils/common';
|
||||||
import { combineLatest, Observable, of, concat, isObservable, throwError, interval as rxjsInterval } from 'rxjs';
|
import { combineLatest, Observable, of, concat, isObservable, throwError, interval as rxjsInterval } from 'rxjs';
|
||||||
import {
|
import {
|
||||||
@@ -60,7 +60,7 @@ import * as DomainCheckoutActions from './store/domain-checkout.actions';
|
|||||||
import { DomainAvailabilityService, ItemData } from '@domain/availability';
|
import { DomainAvailabilityService, ItemData } from '@domain/availability';
|
||||||
import { HttpErrorResponse } from '@angular/common/http';
|
import { HttpErrorResponse } from '@angular/common/http';
|
||||||
import { ApplicationService } from '@core/application';
|
import { ApplicationService } from '@core/application';
|
||||||
import { CustomerDTO } from '@swagger/crm';
|
import { CustomerDTO } from '@generated/swagger/crm-api';
|
||||||
import { Config } from '@core/config';
|
import { Config } from '@core/config';
|
||||||
import parseDuration from 'parse-duration';
|
import parseDuration from 'parse-duration';
|
||||||
|
|
||||||
@@ -135,7 +135,13 @@ export class DomainCheckoutService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
addItemToShoppingCart({ processId, items }: { processId: number; items: AddToShoppingCartDTO[] }): Observable<ShoppingCartDTO> {
|
addItemToShoppingCart({
|
||||||
|
processId,
|
||||||
|
items,
|
||||||
|
}: {
|
||||||
|
processId: number;
|
||||||
|
items: AddToShoppingCartDTO[];
|
||||||
|
}): Observable<ShoppingCartDTO> {
|
||||||
return this.getShoppingCart({ processId }).pipe(
|
return this.getShoppingCart({ processId }).pipe(
|
||||||
first(),
|
first(),
|
||||||
mergeMap((cart) =>
|
mergeMap((cart) =>
|
||||||
@@ -488,7 +494,11 @@ export class DomainCheckoutService {
|
|||||||
checkAvailabilities({ processId }: { processId: number }): Observable<any> {
|
checkAvailabilities({ processId }: { processId: number }): Observable<any> {
|
||||||
const shoppingCart$ = this.getShoppingCart({ processId }).pipe(first());
|
const shoppingCart$ = this.getShoppingCart({ processId }).pipe(first());
|
||||||
const itemsToCheck$ = shoppingCart$.pipe(
|
const itemsToCheck$ = shoppingCart$.pipe(
|
||||||
map((cart) => cart?.items?.filter((item) => item?.data?.features?.orderType === 'Download' && !item.data.availability.lastRequest)),
|
map((cart) =>
|
||||||
|
cart?.items?.filter(
|
||||||
|
(item) => item?.data?.features?.orderType === 'Download' && !item.data.availability.lastRequest,
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
return itemsToCheck$.pipe(
|
return itemsToCheck$.pipe(
|
||||||
@@ -537,7 +547,8 @@ export class DomainCheckoutService {
|
|||||||
const itemsToUpdate$ = shoppingCart$.pipe(
|
const itemsToUpdate$ = shoppingCart$.pipe(
|
||||||
map((cart) =>
|
map((cart) =>
|
||||||
cart?.items?.filter(
|
cart?.items?.filter(
|
||||||
(item) => item?.data?.features?.orderType === 'DIG-Versand' || item?.data?.features?.orderType === 'B2B-Versand',
|
(item) =>
|
||||||
|
item?.data?.features?.orderType === 'DIG-Versand' || item?.data?.features?.orderType === 'B2B-Versand',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -770,7 +781,9 @@ export class DomainCheckoutService {
|
|||||||
|
|
||||||
const availabilities$ = this.validateAvailabilities({ processId });
|
const availabilities$ = this.validateAvailabilities({ processId });
|
||||||
|
|
||||||
return combineLatest([olaStatus$, availabilities$]).pipe(map(([olaStatus, availabilities]) => olaStatus && availabilities));
|
return combineLatest([olaStatus$, availabilities$]).pipe(
|
||||||
|
map(([olaStatus, availabilities]) => olaStatus && availabilities),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
completeCheckout({ processId }: { processId: number }): Observable<DisplayOrderDTO[]> {
|
completeCheckout({ processId }: { processId: number }): Observable<DisplayOrderDTO[]> {
|
||||||
@@ -817,7 +830,7 @@ export class DomainCheckoutService {
|
|||||||
const setSpecialComment$ = this.getSpecialComment({ processId }).pipe(
|
const setSpecialComment$ = this.getSpecialComment({ processId }).pipe(
|
||||||
first(),
|
first(),
|
||||||
mergeMap((specialComment) => {
|
mergeMap((specialComment) => {
|
||||||
if (!!specialComment) {
|
if (specialComment) {
|
||||||
return this.setSpecialCommentOnItem({ processId, specialComment });
|
return this.setSpecialCommentOnItem({ processId, specialComment });
|
||||||
}
|
}
|
||||||
return of(specialComment);
|
return of(specialComment);
|
||||||
@@ -871,7 +884,8 @@ export class DomainCheckoutService {
|
|||||||
|
|
||||||
const setPaymentType$ = itemOrderOptions$.pipe(
|
const setPaymentType$ = itemOrderOptions$.pipe(
|
||||||
mergeMap(({ hasDownload, hasDelivery, hasDigDelivery, hasB2BDelivery }) => {
|
mergeMap(({ hasDownload, hasDelivery, hasDigDelivery, hasB2BDelivery }) => {
|
||||||
const paymentType = hasDownload || hasDelivery || hasDigDelivery || hasB2BDelivery ? 128 /* Rechnung */ : 4; /* Bar */
|
const paymentType =
|
||||||
|
hasDownload || hasDelivery || hasDigDelivery || hasB2BDelivery ? 128 /* Rechnung */ : 4; /* Bar */
|
||||||
return this.setPayment({ processId, paymentType });
|
return this.setPayment({ processId, paymentType });
|
||||||
}),
|
}),
|
||||||
shareReplay(),
|
shareReplay(),
|
||||||
@@ -1057,7 +1071,13 @@ export class DomainCheckoutService {
|
|||||||
.pipe(shareReplay(1));
|
.pipe(shareReplay(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
setNotificationChannels({ processId, notificationChannels }: { processId: number; notificationChannels: NotificationChannel }): void {
|
setNotificationChannels({
|
||||||
|
processId,
|
||||||
|
notificationChannels,
|
||||||
|
}: {
|
||||||
|
processId: number;
|
||||||
|
notificationChannels: NotificationChannel;
|
||||||
|
}): void {
|
||||||
this.store.dispatch(DomainCheckoutActions.setNotificationChannels({ processId, notificationChannels }));
|
this.store.dispatch(DomainCheckoutActions.setNotificationChannels({ processId, notificationChannels }));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1065,7 +1085,15 @@ export class DomainCheckoutService {
|
|||||||
return this.store.select(DomainCheckoutSelectors.selectNotificationChannels, { processId });
|
return this.store.select(DomainCheckoutSelectors.selectNotificationChannels, { processId });
|
||||||
}
|
}
|
||||||
|
|
||||||
setBuyerCommunicationDetails({ processId, mobile, email }: { processId: number; mobile?: string; email?: string }): void {
|
setBuyerCommunicationDetails({
|
||||||
|
processId,
|
||||||
|
mobile,
|
||||||
|
email,
|
||||||
|
}: {
|
||||||
|
processId: number;
|
||||||
|
mobile?: string;
|
||||||
|
email?: string;
|
||||||
|
}): void {
|
||||||
this.store.dispatch(DomainCheckoutActions.setBuyerCommunicationDetails({ processId, mobile, email }));
|
this.store.dispatch(DomainCheckoutActions.setBuyerCommunicationDetails({ processId, mobile, email }));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1125,7 +1153,11 @@ export class DomainCheckoutService {
|
|||||||
.pipe(
|
.pipe(
|
||||||
map((r) => {
|
map((r) => {
|
||||||
return r.result.filter(
|
return r.result.filter(
|
||||||
(branch) => branch.status === 1 && branch.branchType === 1 && branch.isOnline === true && branch.isShippingEnabled === true,
|
(branch) =>
|
||||||
|
branch.status === 1 &&
|
||||||
|
branch.branchType === 1 &&
|
||||||
|
branch.isOnline === true &&
|
||||||
|
branch.isShippingEnabled === true,
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
shareReplay(),
|
shareReplay(),
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ import {
|
|||||||
PayerDTO,
|
PayerDTO,
|
||||||
ShippingAddressDTO,
|
ShippingAddressDTO,
|
||||||
ShoppingCartDTO,
|
ShoppingCartDTO,
|
||||||
} from '@swagger/checkout';
|
} from '@generated/swagger/checkout-api';
|
||||||
import { CustomerDTO } from '@swagger/crm';
|
import { CustomerDTO } from '@generated/swagger/crm-api';
|
||||||
import { DisplayOrderDTO } from '@swagger/oms';
|
import { DisplayOrderDTO } from '@generated/swagger/oms-api';
|
||||||
|
|
||||||
export interface CheckoutEntity {
|
export interface CheckoutEntity {
|
||||||
processId: number;
|
processId: number;
|
||||||
|
|||||||
@@ -8,15 +8,21 @@ import {
|
|||||||
BuyerDTO,
|
BuyerDTO,
|
||||||
PayerDTO,
|
PayerDTO,
|
||||||
AvailabilityDTO,
|
AvailabilityDTO,
|
||||||
} from '@swagger/checkout';
|
} from '@generated/swagger/checkout-api';
|
||||||
import { CustomerDTO } from '@swagger/crm';
|
import { CustomerDTO } from '@generated/swagger/crm-api';
|
||||||
import { DisplayOrderDTO, DisplayOrderItemDTO } from '@swagger/oms';
|
import { DisplayOrderDTO, DisplayOrderItemDTO } from '@generated/swagger/oms-api';
|
||||||
|
|
||||||
const prefix = '[DOMAIN-CHECKOUT]';
|
const prefix = '[DOMAIN-CHECKOUT]';
|
||||||
|
|
||||||
export const setShoppingCart = createAction(`${prefix} Set Shopping Cart`, props<{ processId: number; shoppingCart: ShoppingCartDTO }>());
|
export const setShoppingCart = createAction(
|
||||||
|
`${prefix} Set Shopping Cart`,
|
||||||
|
props<{ processId: number; shoppingCart: ShoppingCartDTO }>(),
|
||||||
|
);
|
||||||
|
|
||||||
export const setCheckout = createAction(`${prefix} Set Checkout`, props<{ processId: number; checkout: CheckoutDTO }>());
|
export const setCheckout = createAction(
|
||||||
|
`${prefix} Set Checkout`,
|
||||||
|
props<{ processId: number; checkout: CheckoutDTO }>(),
|
||||||
|
);
|
||||||
|
|
||||||
export const setNotificationChannels = createAction(
|
export const setNotificationChannels = createAction(
|
||||||
`${prefix} Set Notification Channel`,
|
`${prefix} Set Notification Channel`,
|
||||||
@@ -45,7 +51,10 @@ export const setShippingAddress = createAction(
|
|||||||
props<{ processId: number; shippingAddress: ShippingAddressDTO }>(),
|
props<{ processId: number; shippingAddress: ShippingAddressDTO }>(),
|
||||||
);
|
);
|
||||||
|
|
||||||
export const removeCheckoutWithProcessId = createAction(`${prefix} Remove Checkout With Process Id`, props<{ processId: number }>());
|
export const removeCheckoutWithProcessId = createAction(
|
||||||
|
`${prefix} Remove Checkout With Process Id`,
|
||||||
|
props<{ processId: number }>(),
|
||||||
|
);
|
||||||
|
|
||||||
export const setOrders = createAction(`${prefix} Add Orders`, props<{ orders: DisplayOrderDTO[] }>());
|
export const setOrders = createAction(`${prefix} Add Orders`, props<{ orders: DisplayOrderDTO[] }>());
|
||||||
|
|
||||||
@@ -57,11 +66,20 @@ export const setBuyer = createAction(`${prefix} Set Buyer`, props<{ processId: n
|
|||||||
|
|
||||||
export const setPayer = createAction(`${prefix} Set Payer`, props<{ processId: number; payer: PayerDTO }>());
|
export const setPayer = createAction(`${prefix} Set Payer`, props<{ processId: number; payer: PayerDTO }>());
|
||||||
|
|
||||||
export const setSpecialComment = createAction(`${prefix} Set Agent Comment`, props<{ processId: number; agentComment: string }>());
|
export const setSpecialComment = createAction(
|
||||||
|
`${prefix} Set Agent Comment`,
|
||||||
|
props<{ processId: number; agentComment: string }>(),
|
||||||
|
);
|
||||||
|
|
||||||
export const setOlaError = createAction(`${prefix} Set Ola Error`, props<{ processId: number; olaErrorIds: number[] }>());
|
export const setOlaError = createAction(
|
||||||
|
`${prefix} Set Ola Error`,
|
||||||
|
props<{ processId: number; olaErrorIds: number[] }>(),
|
||||||
|
);
|
||||||
|
|
||||||
export const setCustomer = createAction(`${prefix} Set Customer`, props<{ processId: number; customer: CustomerDTO }>());
|
export const setCustomer = createAction(
|
||||||
|
`${prefix} Set Customer`,
|
||||||
|
props<{ processId: number; customer: CustomerDTO }>(),
|
||||||
|
);
|
||||||
|
|
||||||
export const addShoppingCartItemAvailabilityToHistory = createAction(
|
export const addShoppingCartItemAvailabilityToHistory = createAction(
|
||||||
`${prefix} Add Shopping Cart Item Availability To History`,
|
`${prefix} Add Shopping Cart Item Availability To History`,
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ const _domainCheckoutReducer = createReducer(
|
|||||||
const entity = getOrCreateCheckoutEntity({ processId, entities: s.entities });
|
const entity = getOrCreateCheckoutEntity({ processId, entities: s.entities });
|
||||||
|
|
||||||
const addedShoppingCartItems =
|
const addedShoppingCartItems =
|
||||||
shoppingCart?.items?.filter((item) => !entity.shoppingCart?.items?.find((i) => i.id === item.id))?.map((item) => item.data) ?? [];
|
shoppingCart?.items
|
||||||
|
?.filter((item) => !entity.shoppingCart?.items?.find((i) => i.id === item.id))
|
||||||
|
?.map((item) => item.data) ?? [];
|
||||||
|
|
||||||
entity.shoppingCart = shoppingCart;
|
entity.shoppingCart = shoppingCart;
|
||||||
|
|
||||||
@@ -118,27 +120,34 @@ const _domainCheckoutReducer = createReducer(
|
|||||||
entity.customer = customer;
|
entity.customer = customer;
|
||||||
return storeCheckoutAdapter.setOne(entity, s);
|
return storeCheckoutAdapter.setOne(entity, s);
|
||||||
}),
|
}),
|
||||||
on(DomainCheckoutActions.addShoppingCartItemAvailabilityToHistory, (s, { processId, shoppingCartItemId, availability }) => {
|
on(
|
||||||
const entity = getOrCreateCheckoutEntity({ processId, entities: s.entities });
|
DomainCheckoutActions.addShoppingCartItemAvailabilityToHistory,
|
||||||
|
(s, { processId, shoppingCartItemId, availability }) => {
|
||||||
|
const entity = getOrCreateCheckoutEntity({ processId, entities: s.entities });
|
||||||
|
|
||||||
const itemAvailabilityTimestamp = entity?.itemAvailabilityTimestamp ? { ...entity?.itemAvailabilityTimestamp } : {};
|
const itemAvailabilityTimestamp = entity?.itemAvailabilityTimestamp
|
||||||
|
? { ...entity?.itemAvailabilityTimestamp }
|
||||||
|
: {};
|
||||||
|
|
||||||
const item = entity?.shoppingCart?.items?.find((i) => i.id === shoppingCartItemId)?.data;
|
const item = entity?.shoppingCart?.items?.find((i) => i.id === shoppingCartItemId)?.data;
|
||||||
|
|
||||||
if (!item?.features?.orderType) return s;
|
if (!item?.features?.orderType) return s;
|
||||||
|
|
||||||
itemAvailabilityTimestamp[`${item.id}_${item?.features?.orderType}`] = Date.now();
|
itemAvailabilityTimestamp[`${item.id}_${item?.features?.orderType}`] = Date.now();
|
||||||
|
|
||||||
entity.itemAvailabilityTimestamp = itemAvailabilityTimestamp;
|
entity.itemAvailabilityTimestamp = itemAvailabilityTimestamp;
|
||||||
|
|
||||||
return storeCheckoutAdapter.setOne(entity, s);
|
return storeCheckoutAdapter.setOne(entity, s);
|
||||||
}),
|
},
|
||||||
|
),
|
||||||
on(
|
on(
|
||||||
DomainCheckoutActions.addShoppingCartItemAvailabilityToHistoryByShoppingCartId,
|
DomainCheckoutActions.addShoppingCartItemAvailabilityToHistoryByShoppingCartId,
|
||||||
(s, { shoppingCartId, shoppingCartItemId, availability }) => {
|
(s, { shoppingCartId, shoppingCartItemId, availability }) => {
|
||||||
const entity = getCheckoutEntityByShoppingCartId({ shoppingCartId, entities: s.entities });
|
const entity = getCheckoutEntityByShoppingCartId({ shoppingCartId, entities: s.entities });
|
||||||
|
|
||||||
const itemAvailabilityTimestamp = entity?.itemAvailabilityTimestamp ? { ...entity?.itemAvailabilityTimestamp } : {};
|
const itemAvailabilityTimestamp = entity?.itemAvailabilityTimestamp
|
||||||
|
? { ...entity?.itemAvailabilityTimestamp }
|
||||||
|
: {};
|
||||||
|
|
||||||
const item = entity?.shoppingCart?.items?.find((i) => i.id === shoppingCartItemId)?.data;
|
const item = entity?.shoppingCart?.items?.find((i) => i.id === shoppingCartItemId)?.data;
|
||||||
|
|
||||||
@@ -157,7 +166,13 @@ export function domainCheckoutReducer(state, action) {
|
|||||||
return _domainCheckoutReducer(state, action);
|
return _domainCheckoutReducer(state, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getOrCreateCheckoutEntity({ entities, processId }: { entities: Dictionary<CheckoutEntity>; processId: number }): CheckoutEntity {
|
function getOrCreateCheckoutEntity({
|
||||||
|
entities,
|
||||||
|
processId,
|
||||||
|
}: {
|
||||||
|
entities: Dictionary<CheckoutEntity>;
|
||||||
|
processId: number;
|
||||||
|
}): CheckoutEntity {
|
||||||
let entity = entities[processId];
|
let entity = entities[processId];
|
||||||
|
|
||||||
if (isNullOrUndefined(entity)) {
|
if (isNullOrUndefined(entity)) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Dictionary } from '@ngrx/entity';
|
import { Dictionary } from '@ngrx/entity';
|
||||||
import { createSelector } from '@ngrx/store';
|
import { createSelector } from '@ngrx/store';
|
||||||
import { CustomerDTO } from '@swagger/crm';
|
import { CustomerDTO } from '@generated/swagger/crm-api';
|
||||||
import { CheckoutEntity } from './defs/checkout.entity';
|
import { CheckoutEntity } from './defs/checkout.entity';
|
||||||
import { storeCheckoutAdapter, storeFeatureSelector } from './domain-checkout.state';
|
import { storeCheckoutAdapter, storeFeatureSelector } from './domain-checkout.state';
|
||||||
|
|
||||||
@@ -23,7 +23,8 @@ export const selectCheckoutByProcessId = createSelector(
|
|||||||
|
|
||||||
export const selectCustomerFeaturesByProcessId = createSelector(
|
export const selectCustomerFeaturesByProcessId = createSelector(
|
||||||
selectEntities,
|
selectEntities,
|
||||||
(entities: Dictionary<CheckoutEntity>, { processId }: { processId: number }) => getCusomterFeatures(entities[processId]?.customer),
|
(entities: Dictionary<CheckoutEntity>, { processId }: { processId: number }) =>
|
||||||
|
getCusomterFeatures(entities[processId]?.customer),
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectShippingAddressByProcessId = createSelector(
|
export const selectShippingAddressByProcessId = createSelector(
|
||||||
@@ -48,12 +49,14 @@ export const selectSpecialComment = createSelector(
|
|||||||
|
|
||||||
export const selectNotificationChannels = createSelector(
|
export const selectNotificationChannels = createSelector(
|
||||||
selectEntities,
|
selectEntities,
|
||||||
(entities: Dictionary<CheckoutEntity>, { processId }: { processId: number }) => entities[processId]?.notificationChannels,
|
(entities: Dictionary<CheckoutEntity>, { processId }: { processId: number }) =>
|
||||||
|
entities[processId]?.notificationChannels,
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectBuyerCommunicationDetails = createSelector(
|
export const selectBuyerCommunicationDetails = createSelector(
|
||||||
selectEntities,
|
selectEntities,
|
||||||
(entities: Dictionary<CheckoutEntity>, { processId }: { processId: number }) => entities[processId]?.buyer?.communicationDetails,
|
(entities: Dictionary<CheckoutEntity>, { processId }: { processId: number }) =>
|
||||||
|
entities[processId]?.buyer?.communicationDetails,
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectOrders = createSelector(storeFeatureSelector, (s) => s.orders);
|
export const selectOrders = createSelector(storeFeatureSelector, (s) => s.orders);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user