Merge branch 'master' of ssh://dev.hostsharing.net:29418/hsadmin/hsadmin-ng

This commit is contained in:
Michael Hierweck 2019-05-04 10:24:45 +02:00
commit 24e76e03d1
42 changed files with 1053 additions and 216 deletions

248
README.md
View File

@ -1,16 +1,38 @@
# hsadminNg Development
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** _generated with [DocToc](https://github.com/thlorenz/doctoc)_
- [Setting up the Development Environment](#setting-up-the-development-environment)
- [Frequent Tasks](#frequent-tasks)
- [Building the Application with Test Execution](#building-the-application-with-test-execution)
- [Starting the Application](#starting-the-application)
- [Running JUnit tests with branch coverage](#running-junit-tests-with-branch-coverage)
- [HOWTO Commits](#howto-commits)
- [Creating HOWTO Commits](#creating-howto-commits)
- [Special Build Tasks](#special-build-tasks)
- [Spotless Formatting](#spotless-formatting)
- [Mutation Testing PiTest](#mutation-testing-pitest)
- [Git Workflow for JHipster Generator](#git-workflow-for-jhipster-generator)
- [Generating the Table of Contents for Markdown](#generating-the-table-of-contents-for-markdown)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Setting up the Development Environment
You'll often need to execute `./gradlew`, therefore we suggest to define this alias:
alias gw='./gradlew'
TODO: Instructions for setting up the dev environment from scratch.
## Frequent Tasks
### Building the Application with Test Execution
gw build
gw build
### Starting the Application
@ -31,45 +53,82 @@ see: https://confluence.jetbrains.com/display/IDEADEV/IDEA+Coverage+Runner
Either apply it to specific test configurations or,
better, delete the previous test configurations and amend the JUnit template.
## Git Workflow for JHipster Generator
## HOWTO Commits
The jhipster-generated git branch tracks the history of the JDL model file
and the generated source code. The project has to be resetted to a clean state
(without any generated entities) before changes to the JDL file can be imported.
There are git tags on some commits which show how to add certain features.
| WARNING: This is just a guideline. You should understand what you are doing! |
| ---------------------------------------------------------------------------- |
Find all of such tags with:
git tag | grep HOWTO
git checkout jhipster-generated
git pull
git tag REAL-HEAD
git reset --hard jdl-base
git clean -f -d
git cherry-pick -n spotless
git reset --soft REAL-HEAD
git checkout REAL-HEAD src/main/jdl/customer.jdl # AND OTHERS!
git tag -d REAL-HEAD
### Creating HOWTO Commits
# MANUAL STEP: Apply changes to the jdl file!
If you want to add such a commit, make sure that it contains no clutter
(no changes which are not necessary for whatever the commit is about to explain),
and is complete with all unit tests, code coverage, pitest and other checks.
Otherwise the next developer would run into the same problems again.
# (Re-) Importing
jhipster import-jdl src/main/jdl/customer.jdl
jhipster import-jdl src/main/jdl/accessrights.jdl
# AND OTHERS, if applicable!
One way to keep the commit clean, is to develop it on a local branch.
If any other changes (e.g. bugfixes, API extensions etc.) are necessary,
apply these only to the master or cherry-pick just these to the master,
then rebase your local branch. Do not forget to run all checks locally:
gw clean check pitest # might need over an hour
(Check the PiTest section for speeding up mutation testing.)
To create and push a new tag use:
git tag HOWTO-... master
git push origin HOWTO-...
After you've moved an existing the tag to another commit, you can use:
git push --force origin HOWTO-...
## Special Build Tasks
Besides common build tasks like `build`, `test` or `bootRun` this projects has some not so common tasks which are explained in this section.
### Spotless Formatting
To make sure that no IDE auto-formatter destroys the git history of any file and
especially to avoid merge conflicts from JHipster generated files after these had been changed,
we are using a standard formatter enforced by _spotless_, which is based on the standard Eclipse formatter.
The rules can be checked and applied with these commands:
gw spotlessCheck
gw spotlessApply
git add .
git commit -m"..."
# MANUAL STEP:
# - if you've renamed any identifiers, use refactoring to rename in master as well BEFORE MERGING!
The spotlessCheck task is included as an early step in our Jenkins build pipeline.
Therefore wrong formatting is automatically detected.
# Merge changeset into master branch
git checkout master
git merge jhipster-generated
Our configuration can be found under the directory `cfg/spotless`.
Currently we only have specific rules for _\*.java_-files and their import-order.
### Amending the spotless commit
#### Our Changes to the Standard Eclipse Formatter
We amended the Standard Eclipse Formatter in these respects:
- Lines of code are never joined, thus the developer has control about linebreaks,
which is important for readability in some implementations like toString().
- Lines in comments are never joined either, because that often destroys readable stucture.
- Parts of files can be excluded from getting formatted, by using `@formatter:off` and `@formatter:on` in a comment.
See for example in class `SecurityConfiguration`.
#### Pre-Commit Hook
If you like, you could add this code to the _pre-commit or \_pre_push_ hook\_ in your `.git/hooks` directory:
if ! ./gradlew spotlessCheck; then
exit 1
fi
#### The Tagged Spotless Commit
The commit which introduces the spotless configuration is tagged.
Through this tag it can easily be cherry-picked in the JHipster workflow.
If you need to amend the commit tagged 'spotless', e.g. to change the spotless configuration,
it can be done with these steps:
@ -87,43 +146,6 @@ it can be done with these steps:
git reset --hard REAL-HEAD
git tag -d REAL-HEAD
## HOWTO do This and That
There are git tags on some commits which show how to add certian features.
Find all of such tags with:
git tag | grep HOWTO
### creating HOWTO commits
If you want to add such a commit, make sure that it contains no clutter
(no changes which are not necessary for whatever the commit is about to explain),
and is complete with all unit tests, code coverage, pitest and other checks.
Otherwise the next developer would run into the same problems again.
One way to keep the commit clean, is to develop it on a local branch.
If any other changes (e.g. bugfixes, API extensions etc.) are necessary,
apply these only to the master or cherry-pick just these to the master,
then rebase your local branch. Do not forget to run all checks locally:
gw clean check pitest # might need over an hour
(Check the pitest section for speeding up pitest.)
To create and push a new tag use:
git tag HOWTO-... master
git push origin HOWTO-...
After you've moved an existing the tag to another commit, you can use:
git push origin HOWTO-... --force
## Special Build Tasks
Besides common build tasks like `build`, `test` or `bootRun` this projects has some not so common tasks which are explained in this section.
### Mutation Testing PiTest
./gradlew pitest
@ -168,3 +190,97 @@ If you want to spend more CPU threads on your local system, you can change that
gw pitest -Doverride.pitest.threads=7
I suggest to leave one CPU thread for other tasks or your might lag extremely.
### Git Workflow for JHipster Generator
The following workflow steps make sure that
- JHipster re-imports work properly,
- the git history of changes to the JDL-files, the generated code and the master is comprehensible,
- and merging newly generated code to the master branch is smooth.
It uses a git branch `jhipster-generated` to track the history of the JDL model file and the generated source code.
Applying commits which contain non-generated changes to that branch breaks the normal git history for generated files.
Therefore, this documentation is also not available in that branch.
Thus:
**MANUAL STEP before starting:** Copy this workflow documentation, because this file will be gone once you switched the branch.
| WARNING: The following steps are just a guideline. You should understand what you are doing! |
| -------------------------------------------------------------------------------------------- |
#### 1. Preparing the `jhipster-generated` git Branch
This step assumes that the latest `*.jdl` files are on the `HEAD` of the `jhipster-generated` git branch.
On a re-import of a JDL-file, JHipster does not remove any generated classes which belong to entities deleted from the JDL-file.
Therefore, the project has to be reset to a clean state before changes to the JDL file can be re-imported.
We have not yet finally tested a simplified workflow for just adding new entities or properties.
A git tag `jdl-base` is assumed to sit on the base commit after the application was generated, but before any entities were imported.
git checkout jhipster-generated
git pull
git tag REAL-HEAD
git reset --hard jdl-base
git clean -f -d
git cherry-pick -n spotless
git reset --soft REAL-HEAD
git checkout REAL-HEAD src/main/jdl/customer.jdl # AND OTHERS!
git tag -d REAL-HEAD
#### 2. Amending and Re-Importing the JDL
**MANUAL STEP:** First apply all necessary changes to the JDL files.
Then re-import like this:
# (Re-) Importing
jhipster import-jdl src/main/jdl/customer.jdl
jhipster import-jdl src/main/jdl/accessrights.jdl
jhipster import-jdl src/main/jdl/... # once there are more
For smoothly being able to merge, we need the same formatting in the generated code as on the master:
gw spotlessApply
#### 3. Committing our Changes
git add .
git commit -m"..."
#### 4. Merging our Changes to the `master` Branch
git checkout master
git pull
**MANUAL STEP:** If you've renamed any identifiers, use the refactoring feature of your IDE to rename in master as well.
To avoid oodles of merge-conflicts, you need to do that **BEFORE MERGING!**
Commit any of such changes, if any.
Now we can finally merge our changes to master.
git merge jhipster-generated
It's a good idea doing this step in an IDE because it makes conflict resolving much easier.
Typical merge conflicts stem from:
- Random numbers in test data of `*IntTest.java` files.
- Timestamps in Liquibase-xml-Files.
Now, I suggest to run all tests locally:
gw clean test
Once everything works again, we can push our new version:
git push
### Generating the Table of Contents for Markdown
This README file contains a table of contents generated by _doctoc_.
It's quite simple to use:
npm install -g doctoc
doctoc --maxlevel 3 README.md
Further information can be found [https://github.com/thlorenz/doctoc/blob/master/README.md](on the _doctoc_ github page).

View File

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">
<changeSet id="sample-data-Customer-01" author="mhoennig" context="sample-data">
<loadData encoding="UTF-8"
file="config/liquibase/sample-data/customers.csv"
separator=";"
quotchar="'"
tableName="customer">
<column name="id" type="numeric"/>
<column name="jhi_number" type="numeric"/>
<column name="prefix" type="string"/>
<column name="name" type="string"/>
<column name="contractual_address" type="string"/>
</loadData>
<!-- Liquibase CSV files can contain linebreaks just as real linebreaks, but which
make the CSV files hard to read. Therefore I've encoded linebreaks as '|' and
replace these after import with '\n'. -->
<sql>
UPDATE customer SET contractual_address = REPLACE(contractual_address, '|', STRINGDECODE('\n'));
</sql>
<rollback>
DELETE FROM customer;
</rollback>
</changeSet>
</databaseChangeLog>

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">
<changeSet id="sample-data-Membership-01" author="mhoennig" context="sample-data">
<loadData encoding="UTF-8"
file="config/liquibase/sample-data/memberships.csv"
separator=";"
tableName="membership">
<column name="id" type="numeric"/>
<column name="customer" type="numeric"/>
<column name="jhi_from" type="date"/>
<column name="jhi_to" type="date"/>
</loadData>
</changeSet>
</databaseChangeLog>

View File

@ -21,5 +21,9 @@
<!-- sample data -->
<include file="config/liquibase/sample-data/customers.xml" relativeToChangelogFile="false"/>
<include file="config/liquibase/sample-data/memberships.xml" relativeToChangelogFile="false"/>
<include file="config/liquibase/sample-data/shares.xml" relativeToChangelogFile="false"/>
<include file="config/liquibase/sample-data/assets.xml" relativeToChangelogFile="false"/>
<include file="config/liquibase/sample-data/sepamandates.xml" relativeToChangelogFile="false"/>
</databaseChangeLog>

View File

@ -0,0 +1,58 @@
id;membership_id;document_date;value_date;action;amount;remark
210001;1;2001-05-10;2001-05-11;PAYMENT;64;some|multiline|1. instalment|just to produce some more rows for tests :-)
210002;1;2001-05-10;2001-05-12;PAYMENT;64;some|multiline|2. instalment
210003;1;2001-05-10;2001-05-13;PAYMENT;64;some|multiline|3. instalment
210004;1;2001-05-10;2001-05-14;PAYMENT;64;some|multiline|4. instalment
210005;1;2001-05-10;2001-05-15;PAYMENT;64;some|multiline|5. instalment
210006;1;2001-05-10;2001-05-16;PAYMENT;64;some|multiline|6. instalment
210007;1;2001-05-10;2001-05-17;PAYMENT;64;some|multiline|7. instalment
210008;1;2001-05-10;2001-05-18;PAYMENT;64;some|multiline|8. instalment
210009;1;2001-05-10;2001-05-19;PAYMENT;64;some|multiline|9. instalment
210010;1;2001-05-10;2001-05-20;PAYMENT;64;some|multiline|10. instalment
210011;1;2001-05-10;2001-05-21;PAYMENT;64;some|multiline|11. instalment
210012;1;2001-05-10;2001-05-22;PAYMENT;64;some|multiline|12. instalment
210013;1;2001-05-10;2001-05-23;PAYMENT;64;some|multiline|13. instalment
210014;1;2001-05-10;2001-05-24;PAYMENT;64;some|multiline|14. instalment
210015;1;2001-05-10;2001-05-25;PAYMENT;64;some|multiline|15. instalment
210016;1;2001-05-10;2001-05-26;PAYMENT;64;some|multiline|16. instalment
210017;1;2007-09-09;2008-07-10;PAYBACK;512;1. instalment
210018;1;2007-09-09;2009-07-10;PAYBACK;512;2. instalment
210019;2;2017-02-15;2017-02-15;PAYMENT;512;became a member again
210020;2;2017-02-15;2017-02-15;PAYMENT;64;just writing something
210021;3;2003-06-11;2003-06-11;PAYMENT;256;some comment
210022;3;2003-06-15;2004-07-03;PAYBACK;256;cancelled membership
210023;4;2017-06-15;2017-05-17;PAYMENT;1024;
210024;5;2011-09-18;2011-09-01;PAYMENT;640;
210101;5;2013-01-15;2013-01-01;PAYMENT;64;signed more shares|1. installment
210102;5;2013-01-15;2013-01-02;PAYMENT;64;signed more shares|2. installment
210103;5;2013-01-15;2013-01-03;PAYMENT;64;signed more shares|3. installment
210104;5;2013-01-15;2013-01-04;PAYMENT;64;signed more shares|4. installment
210105;5;2013-01-15;2013-01-05;PAYMENT;64;signed more shares|5. installment
210106;5;2013-01-15;2013-01-06;PAYMENT;64;signed more shares|6. installment
210107;5;2013-01-15;2013-01-07;PAYMENT;64;signed more shares|7. installment
210108;5;2013-01-15;2013-01-08;PAYMENT;64;signed more shares|8. installment
210109;5;2013-01-15;2013-01-09;PAYMENT;64;signed more shares|9. installment
210110;5;2013-01-15;2013-01-10;PAYMENT;64;signed more shares|10. installment
210111;5;2013-01-15;2013-01-11;PAYMENT;64;signed more shares|11. installment
210112;5;2013-01-15;2013-01-12;PAYMENT;64;signed more shares|12. installment
210123;5;2013-01-15;2013-01-13;PAYMENT;64;signed more shares|13. installment
210124;5;2013-01-15;2013-01-14;PAYMENT;64;signed more shares|14. installment
210125;5;2013-01-15;2013-01-15;PAYMENT;64;signed more shares|15. installment
210126;5;2013-01-15;2013-01-16;PAYMENT;64;signed more shares|16. installment
210127;5;2013-01-15;2013-01-17;PAYMENT;64;signed more shares|17. installment
210128;5;2013-01-15;2013-01-18;PAYMENT;64;signed more shares|18. installment
210129;5;2013-01-15;2013-01-19;PAYMENT;64;signed more shares|19. installment
210130;5;2013-01-15;2013-01-20;PAYMENT;64;signed more shares|20. installment
210230;5;2017-12-22;2018-07-01;PAYBACK;160;cancelled most of their shares|1. installment|just to produce more rows for tests :-)
210231;5;2017-12-22;2018-07-02;PAYBACK;160;cancelled most of their shares|2. installment|just to produce more rows for tests :-)
210232;5;2017-12-22;2018-08-03;PAYBACK;160;cancelled most of their shares|3. installment|just to produce more rows for tests :-)
210233;5;2017-12-22;2018-09-04;PAYBACK;160;cancelled most of their shares|4. installment|just to produce more rows for tests :-)
210234;5;2017-12-22;2018-10-05;PAYBACK;160;cancelled most of their shares|5. installment|just to produce more rows for tests :-)
210235;5;2017-12-22;2018-11-06;PAYBACK;160;cancelled most of their shares|6. installment|just to produce more rows for tests :-)
210236;5;2017-12-22;2018-12-07;PAYBACK;160;cancelled most of their shares|7. installment|just to produce more rows for tests :-)
210237;5;2017-12-22;2019-01-08;PAYBACK;160;cancelled most of their shares|8. installment|just to produce more rows for tests :-)
210238;5;2017-12-22;2019-02-09;PAYBACK;160;cancelled most of their shares|9. installment|just to produce more rows for tests :-)
210239;5;2017-12-22;2019-03-10;PAYBACK;160;cancelled most of their shares|10. installment|just to produce more rows for tests :-)
1 id membership_id document_date value_date action amount remark
2 210001 1 2001-05-10 2001-05-11 PAYMENT 64 some|multiline|1. instalment|just to produce some more rows for tests :-)
3 210002 1 2001-05-10 2001-05-12 PAYMENT 64 some|multiline|2. instalment
4 210003 1 2001-05-10 2001-05-13 PAYMENT 64 some|multiline|3. instalment
5 210004 1 2001-05-10 2001-05-14 PAYMENT 64 some|multiline|4. instalment
6 210005 1 2001-05-10 2001-05-15 PAYMENT 64 some|multiline|5. instalment
7 210006 1 2001-05-10 2001-05-16 PAYMENT 64 some|multiline|6. instalment
8 210007 1 2001-05-10 2001-05-17 PAYMENT 64 some|multiline|7. instalment
9 210008 1 2001-05-10 2001-05-18 PAYMENT 64 some|multiline|8. instalment
10 210009 1 2001-05-10 2001-05-19 PAYMENT 64 some|multiline|9. instalment
11 210010 1 2001-05-10 2001-05-20 PAYMENT 64 some|multiline|10. instalment
12 210011 1 2001-05-10 2001-05-21 PAYMENT 64 some|multiline|11. instalment
13 210012 1 2001-05-10 2001-05-22 PAYMENT 64 some|multiline|12. instalment
14 210013 1 2001-05-10 2001-05-23 PAYMENT 64 some|multiline|13. instalment
15 210014 1 2001-05-10 2001-05-24 PAYMENT 64 some|multiline|14. instalment
16 210015 1 2001-05-10 2001-05-25 PAYMENT 64 some|multiline|15. instalment
17 210016 1 2001-05-10 2001-05-26 PAYMENT 64 some|multiline|16. instalment
18 210017 1 2007-09-09 2008-07-10 PAYBACK 512 1. instalment
19 210018 1 2007-09-09 2009-07-10 PAYBACK 512 2. instalment
20 210019 2 2017-02-15 2017-02-15 PAYMENT 512 became a member again
21 210020 2 2017-02-15 2017-02-15 PAYMENT 64 just writing something
22 210021 3 2003-06-11 2003-06-11 PAYMENT 256 some comment
23 210022 3 2003-06-15 2004-07-03 PAYBACK 256 cancelled membership
24 210023 4 2017-06-15 2017-05-17 PAYMENT 1024
25 210024 5 2011-09-18 2011-09-01 PAYMENT 640
26 210101 5 2013-01-15 2013-01-01 PAYMENT 64 signed more shares|1. installment
27 210102 5 2013-01-15 2013-01-02 PAYMENT 64 signed more shares|2. installment
28 210103 5 2013-01-15 2013-01-03 PAYMENT 64 signed more shares|3. installment
29 210104 5 2013-01-15 2013-01-04 PAYMENT 64 signed more shares|4. installment
30 210105 5 2013-01-15 2013-01-05 PAYMENT 64 signed more shares|5. installment
31 210106 5 2013-01-15 2013-01-06 PAYMENT 64 signed more shares|6. installment
32 210107 5 2013-01-15 2013-01-07 PAYMENT 64 signed more shares|7. installment
33 210108 5 2013-01-15 2013-01-08 PAYMENT 64 signed more shares|8. installment
34 210109 5 2013-01-15 2013-01-09 PAYMENT 64 signed more shares|9. installment
35 210110 5 2013-01-15 2013-01-10 PAYMENT 64 signed more shares|10. installment
36 210111 5 2013-01-15 2013-01-11 PAYMENT 64 signed more shares|11. installment
37 210112 5 2013-01-15 2013-01-12 PAYMENT 64 signed more shares|12. installment
38 210123 5 2013-01-15 2013-01-13 PAYMENT 64 signed more shares|13. installment
39 210124 5 2013-01-15 2013-01-14 PAYMENT 64 signed more shares|14. installment
40 210125 5 2013-01-15 2013-01-15 PAYMENT 64 signed more shares|15. installment
41 210126 5 2013-01-15 2013-01-16 PAYMENT 64 signed more shares|16. installment
42 210127 5 2013-01-15 2013-01-17 PAYMENT 64 signed more shares|17. installment
43 210128 5 2013-01-15 2013-01-18 PAYMENT 64 signed more shares|18. installment
44 210129 5 2013-01-15 2013-01-19 PAYMENT 64 signed more shares|19. installment
45 210130 5 2013-01-15 2013-01-20 PAYMENT 64 signed more shares|20. installment
46 210230 5 2017-12-22 2018-07-01 PAYBACK 160 cancelled most of their shares|1. installment|just to produce more rows for tests :-)
47 210231 5 2017-12-22 2018-07-02 PAYBACK 160 cancelled most of their shares|2. installment|just to produce more rows for tests :-)
48 210232 5 2017-12-22 2018-08-03 PAYBACK 160 cancelled most of their shares|3. installment|just to produce more rows for tests :-)
49 210233 5 2017-12-22 2018-09-04 PAYBACK 160 cancelled most of their shares|4. installment|just to produce more rows for tests :-)
50 210234 5 2017-12-22 2018-10-05 PAYBACK 160 cancelled most of their shares|5. installment|just to produce more rows for tests :-)
51 210235 5 2017-12-22 2018-11-06 PAYBACK 160 cancelled most of their shares|6. installment|just to produce more rows for tests :-)
52 210236 5 2017-12-22 2018-12-07 PAYBACK 160 cancelled most of their shares|7. installment|just to produce more rows for tests :-)
53 210237 5 2017-12-22 2019-01-08 PAYBACK 160 cancelled most of their shares|8. installment|just to produce more rows for tests :-)
54 210238 5 2017-12-22 2019-02-09 PAYBACK 160 cancelled most of their shares|9. installment|just to produce more rows for tests :-)
55 210239 5 2017-12-22 2019-03-10 PAYBACK 160 cancelled most of their shares|10. installment|just to produce more rows for tests :-)

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
<property name="now" value="now()" dbms="h2"/>
<property name="now" value="current_timestamp" dbms="postgresql"/>
<property name="floatType" value="float4" dbms="postgresql, h2"/>
<property name="floatType" value="float" dbms="mysql, oracle, mssql"/>
<changeSet id="20190502111400-1" author="mhoennig" context="sample-data">
<loadData encoding="UTF-8"
file="config/liquibase/sample-data/assets.csv"
separator=";"
tableName="asset">
</loadData>
</changeSet>
<changeSet id="20190502111400-2" author="mhoennig" context="sample-data">
<sql>
UPDATE asset SET remark = replace(remark, '|', STRINGDECODE('\n'))
</sql>
<rollback>
DELETE FROM asset;
</rollback>
</changeSet>
</databaseChangeLog>

View File

@ -19,7 +19,13 @@
</changeSet>
<changeSet id="20190403083736-3" author="mhoennig" context="sample-data">
<sql>UPDATE customer SET contractual_address = replace(contractual_address, '|', '\n')</sql>
<sql>
UPDATE customer SET contractual_address = replace(contractual_address, '|', STRINGDECODE('\n'))
</sql>
<rollback>
DELETE FROM customer;
</rollback>
</changeSet>
</databaseChangeLog>

View File

@ -1,6 +1,7 @@
id;customer_id;jhi_from;jhi_to
1;1;2001-04-10;2007-12-31
2;1;2017-01-15;null
3;3;2003-05-15;2019-12-31
4;4;2017-05-15;null
5;5;2011-08-18;null
id;customer_id;admission_document_date;cancellation_document_date;member_from_date;member_until_date;remark
1;1;2001-04-10;2007-08-09;2001-04-11;2007-12-31;is now client of another member|see XYZ
2;1;2017-01-15;null;2017-01-15;null;nothing to say here
3;3;2003-05-11;2018-11-30;2003-05-15;2018-12-31;business discontinued
4;4;2017-05-15;null;2017-05-15;null;whatever|is|to|say
5;5;2011-08-18;null;2011-08-18;null;foo bar etc.

1 id customer_id jhi_from admission_document_date jhi_to cancellation_document_date member_from_date member_until_date remark
2 1 1 2001-04-10 2001-04-10 2007-12-31 2007-08-09 2001-04-11 2007-12-31 is now client of another member|see XYZ
3 2 1 2017-01-15 2017-01-15 null null 2017-01-15 null nothing to say here
4 3 3 2003-05-15 2003-05-11 2019-12-31 2018-11-30 2003-05-15 2018-12-31 business discontinued
5 4 4 2017-05-15 2017-05-15 null null 2017-05-15 null whatever|is|to|say
6 5 5 2011-08-18 2011-08-18 null null 2011-08-18 null foo bar etc.
7

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
<property name="now" value="now()" dbms="h2"/>
<property name="now" value="current_timestamp" dbms="postgresql"/>
<property name="floatType" value="float4" dbms="postgresql, h2"/>
<property name="floatType" value="float" dbms="mysql, oracle, mssql"/>
<changeSet id="20190502100700-1" author="mhoennig" context="sample-data">
<loadData encoding="UTF-8"
file="config/liquibase/sample-data/memberships.csv"
separator=";"
tableName="membership">
</loadData>
</changeSet>
<changeSet id="20190502100700-2" author="mhoennig" context="sample-data">
<sql>
UPDATE membership SET remark = replace(remark, '|', STRINGDECODE('\n'))
</sql>
<rollback>
DELETE FROM membership;
</rollback>
</changeSet>
</databaseChangeLog>

View File

@ -0,0 +1,6 @@
id;customer_id;reference;iban;bic;granting_document_date;revokation_document_date;valid_from_date;valid_until_date;last_used_date;remark
1;1;DKXIDEHAC01;DE94500105172859877827;REF02039402;2018-01-15;null;2018-01-16;null;2019-04-09;a remark|over two lines
2;2;JKUIDEBIS00;DE56500105172321139153;REF2834823W;2017-06-03;2019-01-15;2017-06-04;2019-01-31;2019-01-10;for the old bank account
3;2;JUZTDEVER03;DE56500105172321139153;REF2834823W;2019-01-15;null;2019-02-01;null;2019-04-09;for the new bank account
4;3;CKIZDESiX98;DE24500105175933769123;REF23984928;2016-09-13;2018-11-20;2016-09-13;2018-12-31;2018-12-09;membership cancelled
5;5;ZUIJDEVOR12;DE92500105174781793571;REF23882384;2016-12-03;null;2016-12-03;null;2019-04-09;null
1 id customer_id reference iban bic granting_document_date revokation_document_date valid_from_date valid_until_date last_used_date remark
2 1 1 DKXIDEHAC01 DE94500105172859877827 REF02039402 2018-01-15 null 2018-01-16 null 2019-04-09 a remark|over two lines
3 2 2 JKUIDEBIS00 DE56500105172321139153 REF2834823W 2017-06-03 2019-01-15 2017-06-04 2019-01-31 2019-01-10 for the old bank account
4 3 2 JUZTDEVER03 DE56500105172321139153 REF2834823W 2019-01-15 null 2019-02-01 null 2019-04-09 for the new bank account
5 4 3 CKIZDESiX98 DE24500105175933769123 REF23984928 2016-09-13 2018-11-20 2016-09-13 2018-12-31 2018-12-09 membership cancelled
6 5 5 ZUIJDEVOR12 DE92500105174781793571 REF23882384 2016-12-03 null 2016-12-03 null 2019-04-09 null

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
<property name="now" value="now()" dbms="h2"/>
<property name="now" value="current_timestamp" dbms="postgresql"/>
<property name="floatType" value="float4" dbms="postgresql, h2"/>
<property name="floatType" value="float" dbms="mysql, oracle, mssql"/>
<changeSet id="20190503152800-1" author="mhoennig" context="sample-data">
<loadData encoding="UTF-8"
file="config/liquibase/sample-data/sepamandates.csv"
separator=";"
tableName="sepa_mandate">
</loadData>
</changeSet>
<changeSet id="20190503152800-2" author="mhoennig" context="sample-data">
<sql>
UPDATE sepa_mandate SET remark = replace(remark, '|', STRINGDECODE('\n'))
</sql>
<rollback>
DELETE FROM sepa_mandate;
</rollback>
</changeSet>
</databaseChangeLog>

View File

@ -0,0 +1,13 @@
id;membership_id;document_date;value_date;action;quantity;remark
1;1;2001-04-10;2001-04-11;SUBSCRIPTION;16;some|multiline|remark
2;1;2007-08-09;2007-12-31;CANCELLATION;16;another remark
3;2;2017-01-15;2017-01-17;SUBSCRIPTION;8;became a member again
4;2;2017-01-15;2017-01-17;SUBSCRIPTION;1;just writing something
5;3;2003-05-11;2003-05-18;SUBSCRIPTION;4;some comment
6;3;2003-05-15;2003-05-30;CANCELLATION;4;cancelled membership
7;4;2017-05-15;2017-05-17;SUBSCRIPTION;16;
8;5;2011-08-18;2011-09-01;SUBSCRIPTION;10;
9;5;2012-12-15;2013-01-01;SUBSCRIPTION;20;signed more shares
10;5;2017-11-22;2018-01-01;CANCELLATION;25;cancelled most of their shares
1 id membership_id document_date value_date action quantity remark
2 1 1 2001-04-10 2001-04-11 SUBSCRIPTION 16 some|multiline|remark
3 2 1 2007-08-09 2007-12-31 CANCELLATION 16 another remark
4 3 2 2017-01-15 2017-01-17 SUBSCRIPTION 8 became a member again
5 4 2 2017-01-15 2017-01-17 SUBSCRIPTION 1 just writing something
6 5 3 2003-05-11 2003-05-18 SUBSCRIPTION 4 some comment
7 6 3 2003-05-15 2003-05-30 CANCELLATION 4 cancelled membership
8 7 4 2017-05-15 2017-05-17 SUBSCRIPTION 16
9 8 5 2011-08-18 2011-09-01 SUBSCRIPTION 10
10 9 5 2012-12-15 2013-01-01 SUBSCRIPTION 20 signed more shares
11 10 5 2017-11-22 2018-01-01 CANCELLATION 25 cancelled most of their shares

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
<property name="now" value="now()" dbms="h2"/>
<property name="now" value="current_timestamp" dbms="postgresql"/>
<property name="floatType" value="float4" dbms="postgresql, h2"/>
<property name="floatType" value="float" dbms="mysql, oracle, mssql"/>
<changeSet id="20190502111400-1" author="mhoennig" context="sample-data">
<loadData encoding="UTF-8"
file="config/liquibase/sample-data/shares.csv"
separator=";"
tableName="share">
</loadData>
</changeSet>
<changeSet id="20190502111400-2" author="mhoennig" context="sample-data">
<sql>
UPDATE share SET remark = replace(remark, '|', STRINGDECODE('\n'))
</sql>
<rollback>
DELETE FROM share;
</rollback>
</changeSet>
</databaseChangeLog>

View File

@ -45,6 +45,10 @@
<logger name="org.bson" level="WARN"/>
<logger name="org.hibernate.validator" level="WARN"/>
<logger name="org.hibernate" level="WARN"/>
<!-- HOWTO log Hibernate SQL queries with bind parameters
<logger name="org.hibernate.SQL" additivity="false" level="DEBUG" />
<logger name="org.hibernate.type" additivity="false" level="TRACE" />
-->
<logger name="org.hibernate.ejb.HibernatePersistence" level="OFF"/>
<logger name="org.postgresql.jdbc" level="WARN"/>
<logger name="org.springframework" level="WARN"/>

View File

@ -7,11 +7,11 @@
<dl class="row-md jh-entity-details">
<dt><span jhiTranslate="hsadminNgApp.asset.documentDate">Document Date</span></dt>
<dd>
<span>{{asset.documentDate}}</span>
<span>{{asset.documentDate | date:'mediumDate'}}</span>
</dd>
<dt><span jhiTranslate="hsadminNgApp.asset.valueDate">Value Date</span></dt>
<dd>
<span>{{asset.valueDate}}</span>
<span>{{asset.valueDate | date:'mediumDate'}}</span>
</dd>
<dt><span jhiTranslate="hsadminNgApp.asset.action">Action</span></dt>
<dd>
@ -23,7 +23,7 @@
</dd>
<dt><span jhiTranslate="hsadminNgApp.asset.remark">Remark</span></dt>
<dd>
<span>{{asset.remark}}</span>
<span [innerHTML]="asset.remark | linebreaks"></span>
</dd>
<dt><span jhiTranslate="hsadminNgApp.asset.membership">Membership</span></dt>
<dd>

View File

@ -75,8 +75,8 @@
</div>
<div class="form-group">
<label class="form-control-label" jhiTranslate="hsadminNgApp.asset.remark" for="field_remark">Remark</label>
<input type="text" class="form-control" name="remark" id="field_remark"
[(ngModel)]="asset.remark" maxlength="160"/>
<textarea class="form-control" name="remark" id="field_remark" rows="3"
[(ngModel)]="asset.remark" maxlength="160"></textarea>
<div [hidden]="!(editForm.controls.remark?.dirty && editForm.controls.remark?.invalid)">
<small class="form-text text-danger"
[hidden]="!editForm.controls.remark?.errors?.maxlength" jhiTranslate="entity.validation.maxlength" [translateValues]="{ max: 160 }">

View File

@ -19,9 +19,37 @@
<th jhiSortBy="valueDate"><span jhiTranslate="hsadminNgApp.asset.valueDate">Value Date</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="action"><span jhiTranslate="hsadminNgApp.asset.action">Action</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="amount"><span jhiTranslate="hsadminNgApp.asset.amount">Amount</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="membershipDisplayLabel"><span jhiTranslate="hsadminNgApp.asset.membership">Membership</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th><span jhiTranslate="hsadminNgApp.asset.membership">Membership</span></th>
<th></th>
</tr>
<!-- filter start: -->
<tr>
<th style="width: 10%"></th>
<th style="width: 10%"><input type="text" class="form-control" style="max-width: 20em" minlength="4" maxlength="4" placeholder="YYYY|--|++" [(ngModel)]="filter.criteria.documentDate" (keyup)="filter.trigger($event)"></th>
<th style="width: 10%"><input type="text" class="form-control" style="max-width: 20em" minlength="4" maxlength="4" placeholder="YYYY|--|++" [(ngModel)]="filter.criteria.valueDate" (keyup)="filter.trigger($event)"></th>
<th style="width: 10%">
<select class="form-control" [(ngModel)]="filter.criteria.action" (change)="filter.trigger($event)">
<option value=""></option>
<option value="PAYMENT" jhiTranslate="{{'hsadminNgApp.AssetAction.PAYMENT'}}">PAYMENT</option>
<option value="HANDOVER" jhiTranslate="{{'hsadminNgApp.AssetAction.HANDOVER'}}">HANDOVER</option>
<option value="ADOPTION" jhiTranslate="{{'hsadminNgApp.AssetAction.ADOPTION'}}">ADOPTION</option>
<option value="LOSS" jhiTranslate="{{'hsadminNgApp.AssetAction.LOSS'}}">LOSS</option>
<option value="CLEARING" jhiTranslate="{{'hsadminNgApp.AssetAction.CLEARING'}}">CLEARING</option>
<option value="PAYBACK" jhiTranslate="{{'hsadminNgApp.AssetAction.PAYBACK'}}">PAYBACK</option>
</select>
</th>
<th style="width: 10%"><input type="text" class="form-control" [(ngModel)]="filter.criteria.amount" (keyup)="filter.trigger($event)"></th>
<th style="width: 30%">
<select id="field_membership" class="form-control" name="membership" [(ngModel)]="filter.criteria.membershipId" (change)="filter.trigger($event)">
<option [ngValue]="null" selected></option>
<option [ngValue]="membershipOption.id" *ngFor="let membershipOption of memberships; trackBy: trackId">{{membershipOption.displayLabel}}</option>
</select>
</th>
<th style="width: 20%"><button class="btn btn-primary float-left" (click)="filter.reset()">Reset Filter</button></th>
</tr>
<!-- filter end. -->
</thead>
<tbody infinite-scroll (scrolled)="loadPage(page + 1)" [infiniteScrollDisabled]="page >= links['last']" [infiniteScrollDistance]="0">
<tr *ngFor="let asset of assets ;trackBy: trackId">

View File

@ -9,6 +9,9 @@ import { AccountService } from 'app/core';
import { ITEMS_PER_PAGE } from 'app/shared';
import { AssetService } from './asset.service';
import { IMembership } from 'app/shared/model/membership.model';
import { MembershipService } from 'app/entities/membership';
import { queryEquals, queryYearAsDateRange, TableFilter } from 'app/shared/util/tablefilter';
@Component({
selector: 'jhi-asset',
@ -24,9 +27,18 @@ export class AssetComponent implements OnInit, OnDestroy {
predicate: any;
reverse: any;
totalItems: number;
memberships: IMembership[];
filter: TableFilter<{
documentDate?: string;
valueDate?: string;
action?: string;
amount?: string;
membershipId?: string;
}>;
constructor(
protected assetService: AssetService,
protected membershipService: MembershipService,
protected jhiAlertService: JhiAlertService,
protected eventManager: JhiEventManager,
protected parseLinks: JhiParseLinks,
@ -40,11 +52,25 @@ export class AssetComponent implements OnInit, OnDestroy {
};
this.predicate = 'id';
this.reverse = true;
this.filter = new TableFilter(
{
documentDate: queryYearAsDateRange,
valueDate: queryYearAsDateRange,
action: queryEquals,
amount: queryEquals,
membershipId: queryEquals
},
500,
() => {
this.reset();
}
);
}
loadAll() {
this.assetService
.query({
...this.filter.buildQueryCriteria(),
page: this.page,
size: this.itemsPerPage,
sort: this.sort()
@ -71,6 +97,13 @@ export class AssetComponent implements OnInit, OnDestroy {
this.accountService.identity().then(account => {
this.currentAccount = account;
});
this.membershipService
.query()
.pipe(
filter((mayBeOk: HttpResponse<IMembership[]>) => mayBeOk.ok),
map((response: HttpResponse<IMembership[]>) => response.body)
)
.subscribe((res: IMembership[]) => (this.memberships = res), (res: HttpErrorResponse) => this.onError(res.message));
this.registerChangeInAssets();
}
@ -78,7 +111,7 @@ export class AssetComponent implements OnInit, OnDestroy {
this.eventManager.destroy(this.eventSubscriber);
}
trackId(index: number, item: IAsset) {
trackId(index: number, item: { id: number }) {
return item.id;
}

View File

@ -51,7 +51,7 @@
</dd>
<dt><span jhiTranslate="hsadminNgApp.customer.contractualAddress">Contractual Address</span></dt>
<dd>
<span>{{customer.contractualAddress}}</span>
<span [innerHTML]="customer.contractualAddress | linebreaks"></span>
</dd>
<dt><span jhiTranslate="hsadminNgApp.customer.billingSalutation">Billing Salutation</span></dt>
<dd>
@ -59,11 +59,11 @@
</dd>
<dt><span jhiTranslate="hsadminNgApp.customer.billingAddress">Billing Address</span></dt>
<dd>
<span>{{customer.billingAddress}}</span>
<span [innerHTML]="customer.billingAddress | linebreaks"></span>
</dd>
<dt><span jhiTranslate="hsadminNgApp.customer.remark">Remark</span></dt>
<dd>
<span>{{customer.remark}}</span>
<span [innerHTML]="customer.remark | linebreaks"></span>
</dd>
</dl>

View File

@ -159,9 +159,10 @@
</div>
</div>
<div class="form-group">
<label class="form-control-label" jhiTranslate="hsadminNgApp.customer.contractualAddress" for="field_contractualAddress">Contractual Address</label>
<input type="text" class="form-control" name="contractualAddress" id="field_contractualAddress"
[(ngModel)]="customer.contractualAddress" required maxlength="400"/>
<label class="form-control-label" jhiTranslate="hsadminNgApp.customer.contractualAddress"
for="field_contractualAddress">Contractual Address X</label>
<textarea class="form-control" name="contractualAddress" id="field_contractualAddress" rows="3"
[(ngModel)]="customer.contractualAddress" required maxlength="400"></textarea>
<div [hidden]="!(editForm.controls.contractualAddress?.dirty && editForm.controls.contractualAddress?.invalid)">
<small class="form-text text-danger"
[hidden]="!editForm.controls.contractualAddress?.errors?.required" jhiTranslate="entity.validation.required">
@ -186,8 +187,8 @@
</div>
<div class="form-group">
<label class="form-control-label" jhiTranslate="hsadminNgApp.customer.billingAddress" for="field_billingAddress">Billing Address</label>
<input type="text" class="form-control" name="billingAddress" id="field_billingAddress"
[(ngModel)]="customer.billingAddress" maxlength="400"/>
<textarea class="form-control" name="billingAddress" id="field_billingAddress" rows="3"
[(ngModel)]="customer.billingAddress" maxlength="400"></textarea>
<div [hidden]="!(editForm.controls.billingAddress?.dirty && editForm.controls.billingAddress?.invalid)">
<small class="form-text text-danger"
[hidden]="!editForm.controls.billingAddress?.errors?.maxlength" jhiTranslate="entity.validation.maxlength" [translateValues]="{ max: 400 }">
@ -197,8 +198,8 @@
</div>
<div class="form-group">
<label class="form-control-label" jhiTranslate="hsadminNgApp.customer.remark" for="field_remark">Remark</label>
<input type="text" class="form-control" name="remark" id="field_remark"
[(ngModel)]="customer.remark" maxlength="160"/>
<textarea class="form-control" name="remark" id="field_remark" rows="3"
[(ngModel)]="customer.remark" maxlength="160"></textarea>
<div [hidden]="!(editForm.controls.remark?.dirty && editForm.controls.remark?.invalid)">
<small class="form-text text-danger"
[hidden]="!editForm.controls.remark?.errors?.maxlength" jhiTranslate="entity.validation.maxlength" [translateValues]="{ max: 160 }">

View File

@ -18,9 +18,23 @@
<th jhiSortBy="reference"><span jhiTranslate="hsadminNgApp.customer.reference">Reference</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="prefix"><span jhiTranslate="hsadminNgApp.customer.prefix">Prefix</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="name"><span jhiTranslate="hsadminNgApp.customer.name">Name</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="kind"><span jhiTranslate="hsadminNgApp.customer.kind">Kind</span> <fa-icon [icon]="'sort'"></fa-icon></thn></th>
<th jhiSortBy="kind"><span jhiTranslate="hsadminNgApp.customer.kind">Kind</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th></th>
</tr>
<tr>
<th></th>
<th><input type="text" class="form-control" [(ngModel)]="filter.criteria.reference" (keyup)="filter.trigger($event)"></th>
<th><input type="text" class="form-control" [(ngModel)]="filter.criteria.prefix" (keyup)="filter.trigger($event)"></th>
<th><input type="text" class="form-control" [(ngModel)]="filter.criteria.name" (keyup)="filter.trigger($event)"></th>
<th>
<select class="form-control" [(ngModel)]="filter.criteria.kind" (change)="filter.trigger($event)">
<option value=""></option>
<option value="NATURAL" jhiTranslate="{{'hsadminNgApp.CustomerKind.NATURAL'}}">NATURAL</option>
<option value="LEGAL" jhiTranslate="{{'hsadminNgApp.CustomerKind.LEGAL'}}">LEGAL</option>
</select>
</th>
<th><button class="btn btn-primary float-left" (click)="filter.reset()">Reset Filter</button></th>
</tr>
</thead>
<tbody infinite-scroll (scrolled)="loadPage(page + 1)" [infiniteScrollDisabled]="page >= links['last']" [infiniteScrollDistance]="0">
<tr *ngFor="let customer of customers ;trackBy: trackId">

View File

@ -8,6 +8,7 @@ import { AccountService } from 'app/core';
import { ITEMS_PER_PAGE } from 'app/shared';
import { CustomerService } from './customer.service';
import { TableFilter } from 'app/shared/util/tablefilter';
@Component({
selector: 'jhi-customer',
@ -23,6 +24,7 @@ export class CustomerComponent implements OnInit, OnDestroy {
predicate: any;
reverse: any;
totalItems: number;
filter: TableFilter<{ reference?: string; prefix?: string; name?: string; kind?: string }>;
constructor(
protected customerService: CustomerService,
@ -39,11 +41,24 @@ export class CustomerComponent implements OnInit, OnDestroy {
};
this.predicate = 'id';
this.reverse = true;
this.filter = new TableFilter(
{
reference: 'reference.equals',
prefix: 'prefix.contains',
name: 'name.contains',
kind: 'kind.equals'
},
500,
() => {
this.reset();
}
);
}
loadAll() {
this.customerService
.query({
...this.filter.buildQueryCriteria(),
page: this.page,
size: this.itemsPerPage,
sort: this.sort()

View File

@ -7,23 +7,23 @@
<dl class="row-md jh-entity-details">
<dt><span jhiTranslate="hsadminNgApp.membership.admissionDocumentDate">Admission Document Date</span></dt>
<dd>
<span>{{membership.admissionDocumentDate}}</span>
<span>{{membership.admissionDocumentDate | date:'mediumDate'}}</span>
</dd>
<dt><span jhiTranslate="hsadminNgApp.membership.cancellationDocumentDate">Cancellation Document Date</span></dt>
<dd>
<span>{{membership.cancellationDocumentDate}}</span>
<span>{{membership.cancellationDocumentDate | date:'mediumDate'}}</span>
</dd>
<dt><span jhiTranslate="hsadminNgApp.membership.memberFromDate">Member From Date</span></dt>
<dd>
<span>{{membership.memberFromDate}}</span>
<span>{{membership.memberFromDate | date:'mediumDate'}}</span>
</dd>
<dt><span jhiTranslate="hsadminNgApp.membership.memberUntilDate">Member Until Date</span></dt>
<dd>
<span>{{membership.memberUntilDate}}</span>
<span>{{membership.memberUntilDate | date:'mediumDate'}}</span>
</dd>
<dt><span jhiTranslate="hsadminNgApp.membership.remark">Remark</span></dt>
<dd>
<span>{{membership.remark}}</span>
<span [innerHTML]="membership.remark | linebreaks"></span>
</dd>
<dt><span jhiTranslate="hsadminNgApp.membership.customer">Customer</span></dt>
<dd>

View File

@ -63,8 +63,8 @@
</div>
<div class="form-group">
<label class="form-control-label" jhiTranslate="hsadminNgApp.membership.remark" for="field_remark">Remark</label>
<input type="text" class="form-control" name="remark" id="field_remark"
[(ngModel)]="membership.remark" maxlength="160"/>
<textarea class="form-control" name="remark" id="field_remark" rows="3"
[(ngModel)]="membership.remark" maxlength="160"></textarea>
<div [hidden]="!(editForm.controls.remark?.dirty && editForm.controls.remark?.invalid)">
<small class="form-text text-danger"
[hidden]="!editForm.controls.remark?.errors?.maxlength" jhiTranslate="entity.validation.maxlength" [translateValues]="{ max: 160 }">

View File

@ -16,18 +16,36 @@
<tr jhiSort [(predicate)]="predicate" [(ascending)]="reverse" [callback]="reset.bind(this)">
<th jhiSortBy="id"><span jhiTranslate="global.field.id">ID</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="admissionDocumentDate"><span jhiTranslate="hsadminNgApp.membership.admissionDocumentDate">Admission Document Date</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="cancellationDocumentDate"><span jhiTranslate="hsadminNgApp.membership.cancellationDocumentDate">Cancellation Document Date</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="admissionDocumentDate"><span jhiTranslate="hsadminNgApp.membership.cancellationDocumentDate">Cancellation Document Date</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="memberFromDate"><span jhiTranslate="hsadminNgApp.membership.memberFromDate">Member From Date</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="memberUntilDate"><span jhiTranslate="hsadminNgApp.membership.memberUntilDate">Member Until Date</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="customerPrefix"><span jhiTranslate="hsadminNgApp.membership.customer">Customer</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th><span jhiTranslate="hsadminNgApp.membership.customer">Customer</span></th>
<th></th>
</tr>
<!-- filter start: -->
<tr>
<th style="width: 10%"></th>
<th style="width: 10%"><input type="text" class="form-control" style="max-width: 20em" minlength="4" maxlength="4" placeholder="YYYY|--|++" [(ngModel)]="filter.criteria.admissionDocumentDate" (keyup)="filter.trigger($event)"></th>
<th style="width: 10%"><input type="text" class="form-control" style="max-width: 20em" minlength="4" maxlength="4" placeholder="YYYY|--|++" [(ngModel)]="filter.criteria.cancellationDocumentDate" (keyup)="filter.trigger($event)"></th>
<th style="width: 10%"><input type="text" class="form-control" style="max-width: 20em" minlength="4" maxlength="4" placeholder="YYYY|--|++" [(ngModel)]="filter.criteria.memberFromDate" (keyup)="filter.trigger($event)"></th>
<th style="width: 10%"><input type="text" class="form-control" style="max-width: 20em" minlength="4" maxlength="4" placeholder="YYYY|--|++" [(ngModel)]="filter.criteria.memberUntilDate" (keyup)="filter.trigger($event)"></th>
<th style="width: 30%">
<select id="field_customer" class="form-control" name="customer" [(ngModel)]="filter.criteria.customerId" (change)="filter.trigger($event)">
<option [ngValue]="null" selected></option>
<option [ngValue]="customerOption.id" *ngFor="let customerOption of customers; trackBy: trackId">{{customerOption.displayLabel}}</option>
</select>
</th>
<th style="width: 20%"><button class="btn btn-primary float-left" (click)="filter.reset()">Reset Filter</button></th>
</tr>
<!-- filter end. -->
</thead>
<tbody infinite-scroll (scrolled)="loadPage(page + 1)" [infiniteScrollDisabled]="page >= links['last']" [infiniteScrollDistance]="0">
<tr *ngFor="let membership of memberships ;trackBy: trackId">
<td><a [routerLink]="['/membership', membership.id, 'view' ]">{{membership.id}}</a></td>
<td>{{membership.admissionDocumentDate | date:'mediumDate'}}</td>
<td>{{membership.cancellationDocumentDate | date:'mediumDsate'}}</td>
<td>{{membership.cancellationDocumentDate | date:'mediumDate'}}</td>
<td>{{membership.memberFromDate | date:'mediumDate'}}</td>
<td>{{membership.memberUntilDate | date:'mediumDate'}}</td>
<td>

View File

@ -9,6 +9,9 @@ import { AccountService } from 'app/core';
import { ITEMS_PER_PAGE } from 'app/shared';
import { MembershipService } from './membership.service';
import { ICustomer } from 'app/shared/model/customer.model';
import { CustomerService } from 'app/entities/customer';
import { TableFilter, queryYearAsDateRange, queryEquals } from 'app/shared/util/tablefilter';
@Component({
selector: 'jhi-membership',
@ -24,9 +27,18 @@ export class MembershipComponent implements OnInit, OnDestroy {
predicate: any;
reverse: any;
totalItems: number;
customers: ICustomer[];
filter: TableFilter<{
admissionDocumentDate?: string;
cancellationDocumentDate?: string;
memberFromDate?: string;
memberUntilDate?: string;
customerId?: string;
}>;
constructor(
protected membershipService: MembershipService,
protected customerService: CustomerService,
protected jhiAlertService: JhiAlertService,
protected eventManager: JhiEventManager,
protected parseLinks: JhiParseLinks,
@ -40,11 +52,25 @@ export class MembershipComponent implements OnInit, OnDestroy {
};
this.predicate = 'id';
this.reverse = true;
this.filter = new TableFilter(
{
admissionDocumentDate: queryYearAsDateRange,
cancellationDocumentDate: queryYearAsDateRange,
memberFromDate: queryYearAsDateRange,
memberUntilDate: queryYearAsDateRange,
customerId: queryEquals
},
500,
() => {
this.reset();
}
);
}
loadAll() {
this.membershipService
.query({
...this.filter.buildQueryCriteria(),
page: this.page,
size: this.itemsPerPage,
sort: this.sort()
@ -72,13 +98,20 @@ export class MembershipComponent implements OnInit, OnDestroy {
this.currentAccount = account;
});
this.registerChangeInMemberships();
this.customerService
.query()
.pipe(
filter((mayBeOk: HttpResponse<IMembership[]>) => mayBeOk.ok),
map((response: HttpResponse<IMembership[]>) => response.body)
)
.subscribe((res: IMembership[]) => (this.customers = res), (res: HttpErrorResponse) => this.onError(res.message));
}
ngOnDestroy() {
this.eventManager.destroy(this.eventSubscriber);
}
trackId(index: number, item: IMembership) {
trackId(index: number, item: { id: number }) {
return item.id;
}
@ -97,6 +130,7 @@ export class MembershipComponent implements OnInit, OnDestroy {
protected paginateMemberships(data: IMembership[], headers: HttpHeaders) {
this.links = this.parseLinks.parse(headers.get('link'));
this.totalItems = parseInt(headers.get('X-Total-Count'), 10);
this.memberships = [];
for (let i = 0; i < data.length; i++) {
this.memberships.push(data[i]);
}

View File

@ -19,28 +19,27 @@
</dd>
<dt><span jhiTranslate="hsadminNgApp.sepaMandate.grantingDocumentDate">Granting Document Date</span></dt>
<dd>
<span>{{sepaMandate.grantingDocumentDate}}</span>
<span>{{sepaMandate.grantingDocumentDate | date:'mediumDate'}}</span>
</dd>
<dt><span jhiTranslate="hsadminNgApp.sepaMandate.revokationDocumentDate">Revokation Document Date</span></dt>
<dd>
<span>{{sepaMandate.revokationDocumentDate}}</span>
<span>{{sepaMandate.revokationDocumentDate | date:'mediumDate'}}</span>
</dd>
<dt><span jhiTranslate="hsadminNgApp.sepaMandate.validFromDate">Valid From Date</span></dt>
<dd>
<span>{{sepaMandate.validFromDate}}</span>
<span>{{sepaMandate.validFromDate | date:'mediumDate'}}</span>
</dd>
<dt><span jhiTranslate="hsadminNgApp.sepaMandate.validUntilDate">Valid Until Date</span></dt>
<dd>
<span>{{sepaMandate.validUntilDate}}</span>
<span>{{sepaMandate.validUntilDate | date:'mediumDate'}}</span>
</dd>
<dt><span jhiTranslate="hsadminNgApp.sepaMandate.lastUsedDate">Last Used Date</span></dt>
<dd>
<span>{{sepaMandate.lastUsedDate}}</span>
</dd>
<span>{{sepaMandate.lastUsedDate | date:'mediumDate'}}</span>
</dd>
<dt><span jhiTranslate="hsadminNgApp.sepaMandate.remark">Remark</span></dt>
<dd>
<span>{{sepaMandate.remark}}</span>
<span [innerHTML]="sepaMandate.remark | linebreaks"></span>
</dd>
<dt><span jhiTranslate="hsadminNgApp.sepaMandate.customer">Customer</span></dt>
<dd>

View File

@ -110,8 +110,8 @@
</div>
<div class="form-group">
<label class="form-control-label" jhiTranslate="hsadminNgApp.sepaMandate.remark" for="field_remark">Remark</label>
<input type="text" class="form-control" name="remark" id="field_remark"
[(ngModel)]="sepaMandate.remark" maxlength="160"/>
<textarea class="form-control" name="remark" id="field_remark" rows="3"
[(ngModel)]="sepaMandate.remark" maxlength="160"></textarea>
<div [hidden]="!(editForm.controls.remark?.dirty && editForm.controls.remark?.invalid)">
<small class="form-text text-danger"
[hidden]="!editForm.controls.remark?.errors?.maxlength" jhiTranslate="entity.validation.maxlength" [translateValues]="{ max: 160 }">

View File

@ -23,10 +23,31 @@
<th jhiSortBy="validFromDate"><span jhiTranslate="hsadminNgApp.sepaMandate.validFromDate">Valid From Date</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="validUntilDate"><span jhiTranslate="hsadminNgApp.sepaMandate.validUntilDate">Valid Until Date</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="lastUsedDate"><span jhiTranslate="hsadminNgApp.sepaMandate.lastUsedDate">Last Used Date</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="remark"><span jhiTranslate="hsadminNgApp.sepaMandate.remark">Remark</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="customerDisplayLabel"><span jhiTranslate="hsadminNgApp.sepaMandate.customer">Customer</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th><span jhiTranslate="hsadminNgApp.sepaMandate.customer">Customer</span></th>
<th></th>
</tr>
<!-- filter start: -->
<tr>
<th style="width: 7%"></th>
<th style="width: 7%"><input type="text" class="form-control" style="max-width: 20em" [(ngModel)]="filter.criteria.reference" (keyup)="filter.trigger($event)"></th>
<th style="width: 7%"><input type="text" class="form-control" style="max-width: 20em" [(ngModel)]="filter.criteria.iban" (keyup)="filter.trigger($event)"></th>
<th style="width: 7%"><input type="text" class="form-control" style="max-width: 20em" [(ngModel)]="filter.criteria.bic" (keyup)="filter.trigger($event)"></th>
<th style="width: 7%"><input type="text" class="form-control" style="max-width: 20em" minlength="4" maxlength="4" placeholder="YYYY|--|++" [(ngModel)]="filter.criteria.grantingDocumentDate" (keyup)="filter.trigger($event)"></th>
<th style="width: 7%"><input type="text" class="form-control" style="max-width: 20em" minlength="4" maxlength="4" placeholder="YYYY|--|++" [(ngModel)]="filter.criteria.revokationDocumentDate" (keyup)="filter.trigger($event)"></th>
<th style="width: 7%"><input type="text" class="form-control" style="max-width: 20em" minlength="4" maxlength="4" placeholder="YYYY|--|++" [(ngModel)]="filter.criteria.validFromDate" (keyup)="filter.trigger($event)"></th>
<th style="width: 7%"><input type="text" class="form-control" style="max-width: 20em" minlength="4" maxlength="4" placeholder="YYYY|--|++" [(ngModel)]="filter.criteria.validUntilDate" (keyup)="filter.trigger($event)"></th>
<th style="width: 7%"><input type="text" class="form-control" style="max-width: 20em" minlength="4" maxlength="4" placeholder="YYYY|--|++" [(ngModel)]="filter.criteria.lastUsedDate" (keyup)="filter.trigger($event)"></th>
<th style="width: 17%">
<select id="field_customer" class="form-control" name="customer" [(ngModel)]="filter.criteria.customerId" (change)="filter.trigger($event)">
<option [ngValue]="null" selected></option>
<option [ngValue]="customerOption.id" *ngFor="let customerOption of customers; trackBy: trackId">{{customerOption.displayLabel}}</option>
</select>
</th>
<th style="width: 20%"><button class="btn btn-primary float-left" (click)="filter.reset()">Reset Filter</button></th>
</tr>
<!-- filter end. -->
</thead>
<tbody infinite-scroll (scrolled)="loadPage(page + 1)" [infiniteScrollDisabled]="page >= links['last']" [infiniteScrollDistance]="0">
<tr *ngFor="let sepaMandate of sepaMandates ;trackBy: trackId">
@ -39,7 +60,6 @@
<td>{{sepaMandate.validFromDate | date:'mediumDate'}}</td>
<td>{{sepaMandate.validUntilDate | date:'mediumDate'}}</td>
<td>{{sepaMandate.lastUsedDate | date:'mediumDate'}}</td>
<td>{{sepaMandate.remark}}</td>
<td>
<div *ngIf="sepaMandate.customerId">
<a [routerLink]="['../customer', sepaMandate.customerId , 'view' ]" >{{sepaMandate.customerDisplayLabel}}</a>

View File

@ -9,6 +9,10 @@ import { AccountService } from 'app/core';
import { ITEMS_PER_PAGE } from 'app/shared';
import { SepaMandateService } from './sepa-mandate.service';
import { ICustomer } from 'app/shared/model/customer.model';
import { CustomerService } from 'app/entities/customer';
import { TableFilter, queryYearAsDateRange, queryEquals, queryContains } from 'app/shared/util/tablefilter';
import { IMembership } from 'app/shared/model/membership.model';
@Component({
selector: 'jhi-sepa-mandate',
@ -24,9 +28,22 @@ export class SepaMandateComponent implements OnInit, OnDestroy {
predicate: any;
reverse: any;
totalItems: number;
customers: ICustomer[];
filter: TableFilter<{
reference?: string;
iban?: string;
bic?: string;
grantingDocumentDate?: string;
revokationDocumentDate?: string;
validFromDate?: string;
validUntilDate?: string;
lastUsedDate?: string;
customerId?: string;
}>;
constructor(
protected sepaMandateService: SepaMandateService,
protected customerService: CustomerService,
protected jhiAlertService: JhiAlertService,
protected eventManager: JhiEventManager,
protected parseLinks: JhiParseLinks,
@ -40,11 +57,29 @@ export class SepaMandateComponent implements OnInit, OnDestroy {
};
this.predicate = 'id';
this.reverse = true;
this.filter = new TableFilter(
{
reference: queryContains,
iban: queryContains,
bic: queryContains,
grantingDocumentDate: queryYearAsDateRange,
revokationDocumentDate: queryYearAsDateRange,
validFromDate: queryYearAsDateRange,
validUntilDate: queryYearAsDateRange,
lastUsedDate: queryYearAsDateRange,
customerId: queryEquals
},
500,
() => {
this.reset();
}
);
}
loadAll() {
this.sepaMandateService
.query({
...this.filter.buildQueryCriteria(),
page: this.page,
size: this.itemsPerPage,
sort: this.sort()
@ -72,13 +107,20 @@ export class SepaMandateComponent implements OnInit, OnDestroy {
this.currentAccount = account;
});
this.registerChangeInSepaMandates();
this.customerService
.query()
.pipe(
filter((mayBeOk: HttpResponse<IMembership[]>) => mayBeOk.ok),
map((response: HttpResponse<IMembership[]>) => response.body)
)
.subscribe((res: IMembership[]) => (this.customers = res), (res: HttpErrorResponse) => this.onError(res.message));
}
ngOnDestroy() {
this.eventManager.destroy(this.eventSubscriber);
}
trackId(index: number, item: ISepaMandate) {
trackId(index: number, item: { id: number }) {
return item.id;
}

View File

@ -7,11 +7,11 @@
<dl class="row-md jh-entity-details">
<dt><span jhiTranslate="hsadminNgApp.share.documentDate">Document Date</span></dt>
<dd>
<span>{{share.documentDate}}</span>
<span>{{share.documentDate | date:'mediumDate'}}</span>
</dd>
<dt><span jhiTranslate="hsadminNgApp.share.valueDate">Value Date</span></dt>
<dd>
<span>{{share.valueDate}}</span>
<span>{{share.valueDate | date:'mediumDate'}}</span>
</dd>
<dt><span jhiTranslate="hsadminNgApp.share.action">Action</span></dt>
<dd>
@ -23,7 +23,7 @@
</dd>
<dt><span jhiTranslate="hsadminNgApp.share.remark">Remark</span></dt>
<dd>
<span>{{share.remark}}</span>
<span [innerHTML]="share.remark | linebreaks"></span>
</dd>
<dt><span jhiTranslate="hsadminNgApp.share.membership">Membership</span></dt>
<dd>

View File

@ -71,8 +71,8 @@
</div>
<div class="form-group">
<label class="form-control-label" jhiTranslate="hsadminNgApp.share.remark" for="field_remark">Remark</label>
<input type="text" class="form-control" name="remark" id="field_remark"
[(ngModel)]="share.remark" maxlength="160"/>
<textarea class="form-control" name="remark" id="field_remark" rows="3"
[(ngModel)]="share.remark" maxlength="160"></textarea>
<div [hidden]="!(editForm.controls.remark?.dirty && editForm.controls.remark?.invalid)">
<small class="form-text text-danger"
[hidden]="!editForm.controls.remark?.errors?.maxlength" jhiTranslate="entity.validation.maxlength" [translateValues]="{ max: 160 }">

View File

@ -3,7 +3,6 @@ import { ActivatedRoute } from '@angular/router';
import { HttpResponse, HttpErrorResponse } from '@angular/common/http';
import { Observable } from 'rxjs';
import { filter, map } from 'rxjs/operators';
import * as moment from 'moment';
import { JhiAlertService } from 'ng-jhipster';
import { IShare } from 'app/shared/model/share.model';
import { ShareService } from './share.service';

View File

@ -19,17 +19,41 @@
<th jhiSortBy="valueDate"><span jhiTranslate="hsadminNgApp.share.valueDate">Value Date</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="action"><span jhiTranslate="hsadminNgApp.share.action">Action</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="quantity"><span jhiTranslate="hsadminNgApp.share.quantity">Quantity</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th jhiSortBy="membershipDisplayLabel"><span jhiTranslate="hsadminNgApp.share.membership">Membership</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th><span jhiTranslate="hsadminNgApp.share.membership">Membership</span></th>
<th></th>
</tr>
<!-- filter start: -->
<tr>
<th style="width: 10%"></th>
<th style="width: 10%"><input type="text" class="form-control" style="max-width: 20em" minlength="4" maxlength="4" placeholder="YYYY|--|++" [(ngModel)]="filter.criteria.documentDate" (keyup)="filter.trigger($event)"></th>
<th style="width: 10%"><input type="text" class="form-control" style="max-width: 20em" minlength="4" maxlength="4" placeholder="YYYY|--|++" [(ngModel)]="filter.criteria.valueDate" (keyup)="filter.trigger($event)"></th>
<th style="width: 10%">
<select class="form-control" [(ngModel)]="filter.criteria.action" (change)="filter.trigger($event)">
<option value=""></option>
<option value="SUBSCRIPTION" jhiTranslate="{{'hsadminNgApp.ShareAction.SUBSCRIPTION'}}">SUBSCRIPTION</option>
<option value="CANCELLATION" jhiTranslate="{{'hsadminNgApp.ShareAction.CANCELLATION'}}">CANCELLATION</option>
</select>
</th>
<th style="width: 10%"><input type="text" class="form-control" [(ngModel)]="filter.criteria.quantity" (keyup)="filter.trigger($event)"></th>
<th style="width: 30%">
<select id="field_membership" class="form-control" name="membership" [(ngModel)]="filter.criteria.membershipId" (change)="filter.trigger($event)">
<option [ngValue]="null" selected></option>
<option [ngValue]="membershipOption.id" *ngFor="let membershipOption of memberships; trackBy: trackId">{{membershipOption.displayLabel}}</option>
</select>
</th>
<th style="width: 20%"><button class="btn btn-primary float-left" (click)="filter.reset()">Reset Filter</button></th>
</tr>
<!-- filter end. -->
</thead>
<tbody infinite-scroll (scrolled)="loadPage(page + 1)" [infiniteScrollDisabled]="page >= links['last']" [infiniteScrollDistance]="0">
<tr *ngFor="let share of shares ;trackBy: trackId">
<td><a [routerLink]="['/share', share.id, 'view' ]">{{share.id}}</a></td>
<td class="text-right"><a [routerLink]="['/share', share.id, 'view' ]">{{share.id}}</a></td>
<td>{{share.documentDate | date:'mediumDate'}}</td>
<td>{{share.valueDate | date:'mediumDate'}}</td>
<td jhiTranslate="{{'hsadminNgApp.ShareAction.' + share.action}}">{{share.action}}</td>
<td>{{share.quantity}}</td>
<td class="text-right">{{share.quantity}}</td>
<td>
<div *ngIf="share.membershipId">
<a [routerLink]="['../membership', share.membershipId , 'view' ]" >{{share.membershipDisplayLabel}}</a>

View File

@ -9,6 +9,9 @@ import { AccountService } from 'app/core';
import { ITEMS_PER_PAGE } from 'app/shared';
import { ShareService } from './share.service';
import { IMembership } from 'app/shared/model/membership.model';
import { MembershipService } from 'app/entities/membership';
import { TableFilter, queryYearAsDateRange, queryEquals } from 'app/shared/util/tablefilter';
@Component({
selector: 'jhi-share',
@ -24,9 +27,18 @@ export class ShareComponent implements OnInit, OnDestroy {
predicate: any;
reverse: any;
totalItems: number;
memberships: IMembership[];
filter: TableFilter<{
documentDate?: string;
valueDate?: string;
action?: string;
quantity?: string;
membershipId?: string;
}>;
constructor(
protected shareService: ShareService,
protected membershipService: MembershipService,
protected jhiAlertService: JhiAlertService,
protected eventManager: JhiEventManager,
protected parseLinks: JhiParseLinks,
@ -40,11 +52,25 @@ export class ShareComponent implements OnInit, OnDestroy {
};
this.predicate = 'id';
this.reverse = true;
this.filter = new TableFilter(
{
documentDate: queryYearAsDateRange,
valueDate: queryYearAsDateRange,
action: queryEquals,
quantity: queryEquals,
membershipId: queryEquals
},
500,
() => {
this.reset();
}
);
}
loadAll() {
this.shareService
.query({
...this.filter.buildQueryCriteria(),
page: this.page,
size: this.itemsPerPage,
sort: this.sort()
@ -71,6 +97,13 @@ export class ShareComponent implements OnInit, OnDestroy {
this.accountService.identity().then(account => {
this.currentAccount = account;
});
this.membershipService
.query()
.pipe(
filter((mayBeOk: HttpResponse<IMembership[]>) => mayBeOk.ok),
map((response: HttpResponse<IMembership[]>) => response.body)
)
.subscribe((res: IMembership[]) => (this.memberships = res), (res: HttpErrorResponse) => this.onError(res.message));
this.registerChangeInShares();
}
@ -78,7 +111,7 @@ export class ShareComponent implements OnInit, OnDestroy {
this.eventManager.destroy(this.eventSubscriber);
}
trackId(index: number, item: IShare) {
trackId(index: number, item: { id: number }) {
return item.id;
}

View File

@ -21,6 +21,34 @@
<th jhiSortBy="user.login"><span jhiTranslate="hsadminNgApp.userRoleAssignment.user">User</span> <fa-icon [icon]="'sort'"></fa-icon></th>
<th></th>
</tr>
<!-- filter start: -->
<tr>
<th style="width: 10%"></th>
<th style="width: 10%"><input type="text" class="form-control" style="max-width: 20em" [(ngModel)]="filter.criteria.entityTypeId" (keyup)="filter.trigger($event)"></th>
<th style="width: 10%"><input type="text" class="form-control" style="max-width: 20em" [(ngModel)]="filter.criteria.entityObjectId" (keyup)="filter.trigger($event)"></th>
<th style="width: 10%">
<select class="form-control" [(ngModel)]="filter.criteria.assignedRole" (change)="filter.trigger($event)">
<option value=""></option>
<option value="HOSTMASTER" jhiTranslate="{{'hsadminNgApp.UserRole.HOSTMASTER'}}">HOSTMASTER</option>
<option value="ADMIN" jhiTranslate="{{'hsadminNgApp.UserRole.ADMIN'}}">ADMIN</option>
<option value="SUPPORTER" jhiTranslate="{{'hsadminNgApp.UserRole.SUPPORTER'}}">SUPPORTER</option>
<option value="CONTRACTUAL_CONTACT" jhiTranslate="{{'hsadminNgApp.UserRole.CONTRACTUAL_CONTACT'}}">CONTRACTUAL_CONTACT</option>
<option value="FINANCIAL_CONTACT" jhiTranslate="{{'hsadminNgApp.UserRole.FINANCIAL_CONTACT'}}">FINANCIAL_CONTACT</option>
<option value="TECHNICAL_CONTACT" jhiTranslate="{{'hsadminNgApp.UserRole.TECHNICAL_CONTACT'}}">TECHNICAL_CONTACT</option>
<option value="CUSTOMER_USER" jhiTranslate="{{'hsadminNgApp.UserRole.CUSTOMER_USER'}}">CUSTOMER_USER</option>
</select>
</th>
<th style="width: 30%">
<select id="field_user" class="form-control" name="user" [(ngModel)]="filter.criteria.userId" (change)="filter.trigger($event)">
<option [ngValue]="null" selected></option>
<option [ngValue]="userOption.id" *ngFor="let userOption of users; trackBy: trackId">{{userOption.login}}</option>
</select>
</th>
<th style="width: 20%"><button class="btn btn-primary float-left" (click)="filter.reset()">Reset Filter</button></th>
</tr>
<!-- filter end. -->
</thead>
<tbody infinite-scroll (scrolled)="loadPage(page + 1)" [infiniteScrollDisabled]="page >= links['last']" [infiniteScrollDistance]="0">
<tr *ngFor="let userRoleAssignment of userRoleAssignments ;trackBy: trackId">

View File

@ -9,6 +9,9 @@ import { AccountService } from 'app/core';
import { ITEMS_PER_PAGE } from 'app/shared';
import { UserRoleAssignmentService } from './user-role-assignment.service';
import { IUser } from 'app/core/user/user.model';
import { UserService } from 'app/core/user/user.service';
import { TableFilter, queryEquals, queryContains } from 'app/shared/util/tablefilter';
@Component({
selector: 'jhi-user-role-assignment',
@ -24,9 +27,17 @@ export class UserRoleAssignmentComponent implements OnInit, OnDestroy {
predicate: any;
reverse: any;
totalItems: number;
users: IUser[];
filter: TableFilter<{
entityTypeId?: string;
entityObjectId?: string;
assignedRole?: string;
userId?: string;
}>;
constructor(
protected userRoleAssignmentService: UserRoleAssignmentService,
protected userService: UserService,
protected jhiAlertService: JhiAlertService,
protected eventManager: JhiEventManager,
protected parseLinks: JhiParseLinks,
@ -40,11 +51,24 @@ export class UserRoleAssignmentComponent implements OnInit, OnDestroy {
};
this.predicate = 'id';
this.reverse = true;
this.filter = new TableFilter(
{
entityTypeId: queryContains,
entityObjectId: queryEquals,
assignedRole: queryEquals,
userId: queryEquals
},
500,
() => {
this.reset();
}
);
}
loadAll() {
this.userRoleAssignmentService
.query({
...this.filter.buildQueryCriteria(),
page: this.page,
size: this.itemsPerPage,
sort: this.sort()
@ -71,6 +95,13 @@ export class UserRoleAssignmentComponent implements OnInit, OnDestroy {
this.accountService.identity().then(account => {
this.currentAccount = account;
});
this.userService
.query()
.pipe(
filter((mayBeOk: HttpResponse<IUser[]>) => mayBeOk.ok),
map((response: HttpResponse<IUser[]>) => response.body)
)
.subscribe((res: IUser[]) => (this.users = res), (res: HttpErrorResponse) => this.onError(res.message));
this.registerChangeInUserRoleAssignments();
}
@ -78,7 +109,7 @@ export class UserRoleAssignmentComponent implements OnInit, OnDestroy {
this.eventManager.destroy(this.eventSubscriber);
}
trackId(index: number, item: IUserRoleAssignment) {
trackId(index: number, item: { id: number }) {
return item.id;
}

View File

@ -1 +1,3 @@
export const ITEMS_PER_PAGE = 20;
// For infinite scroll, it should be more than fits into a window height.
// Otherwise, the scrollbar might not be there at all, and further pages can't be reached.
export const ITEMS_PER_PAGE = 100;

View File

@ -0,0 +1,79 @@
import { Subject, Subscription } from 'rxjs';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
export interface QueryDeclarations {
[key: string]: string;
}
export type DynamicQueryDefinition = (name: string, value: string) => QueryDefinitions;
export interface QueryDefinitions {
[key: string]: string | DynamicQueryDefinition;
}
/**
* Handles filtering in data tables by converting the user input to query criteria of the JHipster REST API.
*
* It also does not reload during a given debounce period.
*/
export class TableFilter<T extends {}> {
criteria: T;
private criteriaChangedSubject = new Subject<void>();
private criteriaChangedDebouncer: Subscription;
constructor(private query: QueryDefinitions, private debounceMillis: number, private reload: () => void) {
this.criteria = {} as any;
this.criteriaChangedDebouncer = this.criteriaChangedSubject.pipe(debounceTime(debounceMillis)).subscribe(() => this.reload());
}
trigger($event) {
this.debounce();
}
reset() {
this.criteria = {} as any;
this.debounce();
}
buildQueryCriteria(): QueryDeclarations {
let queryCriteria: any = {} as any;
Object.keys(this.criteria).forEach(name => {
const value = this.criteria[name];
if (value === '--') {
queryCriteria[name + '.specified'] = false;
} else if (value === '++') {
queryCriteria[name + '.specified'] = true;
} else {
const queryDef = this.query[name];
if (typeof queryDef !== 'function') {
queryCriteria[queryDef] = value;
} else {
const additionalQueryCriteria = queryDef(name, value);
queryCriteria = { ...queryCriteria, ...additionalQueryCriteria };
}
}
});
return queryCriteria;
}
private debounce() {
this.criteriaChangedSubject.next();
}
}
export function queryYearAsDateRange(name: string, value: string) {
if (value.length === 'YYYY'.length) {
const queryCriteria: any = {} as any;
queryCriteria[name + '.greaterOrEqualThan'] = value + '-01-01';
queryCriteria[name + '.lessOrEqualThan'] = value + '-12-31';
return queryCriteria;
}
return null;
}
export function queryEquals(name: string, value: string) {
return { [name + '.equals']: value };
}
export function queryContains(name: string, value: string) {
return { [name + '.contains']: value };
}

View File

@ -225,3 +225,14 @@ ui bootstrap tweaks
}
/* jhipster-needle-css-add-main JHipster will add new css style */
/* ==========================================================================
ui tweaks by Hostsharing
========================================================================== */
.jh-entity-details > dt {
color: lightslategray;
}
.jh-entity-details > dd {
font-size: 140%;
}

View File

@ -2,8 +2,8 @@
"hsadminNgApp": {
"CustomerKind": {
"null": "",
"NATURAL": "NATURAL",
"LEGAL": "LEGAL"
"NATURAL": "natürliche Person",
"LEGAL": "juristische Person"
}
}
}

View File

@ -0,0 +1,145 @@
import { queryContains, queryEquals, queryYearAsDateRange, TableFilter } from 'app/shared/util/tablefilter';
/* To run these tests in IntelliJ IDEA, you need a run configuration with
Configuration File:
~/Projekte/Hostsharing/hsadmin-ng/src/test/javascript/jest.conf.js
and a Node Interpreter, e.g. if installed with nvm, this could be:
~/.nvm/versions/node/v10.15.3/bin/node
*/
describe('TableFilter Tests', () => {
describe('TableFilter', () => {
const TEST_DEBOUNCE_MILLIS = 100;
let filter: TableFilter<{ name?: string; number?: string; date?: string }>;
let asynchronously: () => void;
beforeEach(() => {
filter = new TableFilter(
{
name: queryContains,
number: queryEquals,
date: queryYearAsDateRange
},
TEST_DEBOUNCE_MILLIS,
() => {
asynchronously();
}
);
});
it('trigger() asynchronously calls the reload-handler', done => {
// given
filter.criteria.name = 'Test Filter Value';
// when
filter.trigger({ target: { valid: true } });
const triggerStartedAtMillis = Date.now();
// then
asynchronously = () => {
expect(Date.now()).toBeGreaterThan(triggerStartedAtMillis);
done();
};
});
it('if trigger() is called multiple times during debounce, debounce period ands after last trigger()', done => {
// given
filter.criteria.name = 'Test Filter Value';
// when
filter.trigger({ target: { valid: true } });
let triggerStartedAtMillis = null;
setTimeout(() => {
filter.trigger({ target: { valid: true } });
triggerStartedAtMillis = Date.now();
}, 50);
// then
asynchronously = () => {
expect(triggerStartedAtMillis).not.toBeNull();
expect(Date.now()).toBeGreaterThan(triggerStartedAtMillis);
done();
};
});
it('when filter "name" is set, buildQueryCriteria() returns a name.contains query', () => {
// given
filter.criteria.name = 'test value';
// when
const actual = filter.buildQueryCriteria();
// then
expect(filter.buildQueryCriteria()).toEqual({ 'name.contains': 'test value' });
});
it('when filter "name" is set to "--", buildQueryCriteria() returns a name.specified=false query', () => {
// given
filter.criteria.name = '--';
// when
const actual = filter.buildQueryCriteria();
// then
expect(filter.buildQueryCriteria()).toEqual({ 'name.specified': false });
});
it('when filter "name" is set to "++", buildQueryCriteria() returns a name.specified=true query', () => {
// given
filter.criteria.name = '++';
// when
const actual = filter.buildQueryCriteria();
// then
expect(filter.buildQueryCriteria()).toEqual({ 'name.specified': true });
});
it('when filter "number" is set, buildQueryCriteria() returns a number.equals query', () => {
// given
filter.criteria.number = '-42';
// when
const actual = filter.buildQueryCriteria();
// then
expect(filter.buildQueryCriteria()).toEqual({ 'number.equals': '-42' });
});
it('when filter "date" is set to "2019", buildQueryCriteria() returns a date range query', () => {
// given
filter.criteria.date = '2019';
// when
const actual = filter.buildQueryCriteria();
// then
expect(filter.buildQueryCriteria()).toEqual({ 'date.greaterOrEqualThan': '2019-01-01', 'date.lessOrEqualThan': '2019-12-31' });
});
it('queryYearAsDateRange() returns null if year is not 4-digit', () => {
expect(queryYearAsDateRange('date', '201')).toBeNull();
expect(queryYearAsDateRange('date', '20191')).toBeNull();
});
it('reset() clears criteria and calls reload-handler, considering debounce period', done => {
// given
filter.criteria.name = 'Test Filter Value';
// when
filter.trigger({ target: { valid: true } });
let triggerStartedAtMillis = null;
setTimeout(() => {
filter.reset();
triggerStartedAtMillis = Date.now();
}, TEST_DEBOUNCE_MILLIS / 2);
// then
asynchronously = () => {
expect(triggerStartedAtMillis).not.toBeNull();
expect(Date.now()).toBeGreaterThan(triggerStartedAtMillis);
done();
};
});
});
});